nonePublicAuth = async (apiConfig, frame) => {
    debug('check admin permissions');

    let singular;
    if (apiConfig.docName.match(/ies$/)) {
        singular = apiConfig.docName.replace(/ies$/, 'y');
    } else {
        singular = apiConfig.docName.replace(/s$/, '');
    }
    let permissionIdentifier = frame.options.id;

    // CASE: Target ctrl can override the identifier. The identifier is the unique identifier of the target resource
    //       e.g. edit a setting -> the key of the setting
    //       e.g. edit a post -> post id from url param
    //       e.g. change user password -> user id inside of the body structure
    if (apiConfig.identifier) {
        permissionIdentifier = apiConfig.identifier(frame);
    }

    let unsafeAttrObject = apiConfig.unsafeAttrs && _.has(frame, `data.[${apiConfig.docName}][0]`) ? _.pick(frame.data[apiConfig.docName][0], apiConfig.unsafeAttrs) : {};

    if (apiConfig.unsafeAttrsObject) {
        unsafeAttrObject = apiConfig.unsafeAttrsObject(frame);
    }

    try {
        const result = await permissions.canThis(frame.options.context)[apiConfig.method][singular](permissionIdentifier, unsafeAttrObject);

        /*
         * Allow the permissions function to return a list of excluded attributes.
         * If it does, omit those attrs from the data passed through
         *
         * NOTE: excludedAttrs differ from unsafeAttrs in that they're determined by the model's permissible function,
         * and the attributes are simply excluded rather than throwing a NoPermission exception
         *
         * TODO: This is currently only needed because of the posts model and the contributor role. Once we extend the
         * contributor role to be able to edit existing tags, this concept can be removed.
         */
        if (result && result.excludedAttrs && _.has(frame, `data.[${apiConfig.docName}][0]`)) {
            frame.data[apiConfig.docName][0] = _.omit(frame.data[apiConfig.docName][0], result.excludedAttrs);
        }
    } catch (err) {
        if (err instanceof errors.NoPermissionError) {
            err.message = tpl(messages.noPermissionToCall, {
                method: apiConfig.method,
                docName: apiConfig.docName
            });
            throw err;
        }

        if (errors.utils.isGhostError(err)) {
            throw err;
        }

        throw new errors.InternalServerError({
            err
        });
    }
}
@description Handle requests, which need authentication.

@param {Object} apiConfig - Docname & method of API ctrl
@param {import('@tryghost/api-framework').Frame} frame
@return {Promise}