const { Middleware } = require('libflitter') class PermissionMiddleware extends Middleware { static get services() { return [...super.services, 'models', 'activity'] } async test(req, res, next, { check }) { const Policy = this.models.get('iam:Policy') req.additional_api_log_data.permission_check = check // If the request was authorized using an OAuth2 bearer token, // make sure the associated client has permission to access this endpoint. if ( req?.oauth?.client ) { if ( !req.oauth.client.can(check) ) { const reason = 'oauth-permission-fail' const fail_activity = await this.activity.api_access_denial({ req, reason, check, oauth_client_id: req.oauth.client.uuid, }) req.additional_api_log_data.permission_check_succeeded = false req.additional_api_log_data.permission_check_activity_id = fail_activity.id return res.status(401) .message('Insufficient permissions (OAuth2 Client).') .api() } req.additional_api_log_data.permission_check_succeeded = true // If the oauth2 client has this permission, then allow the request to continue, // even if the user does not. // OAuth2Clients need to be able to query users via the API. return next() } const policy_denied = await Policy.check_user_denied(req.user, check) const policy_access = await Policy.check_user_access(req.user, check) // Make sure the user has permission if ( policy_denied || (!req.user.can(check) && !policy_access) ) { // Record the failed API access const reason = policy_denied ? 'iam-denial' : (!req.user.can(check) ? 'user-permission-fail' : 'iam-not-granted') const fail_activity = await this.activity.api_access_denial({ req, reason, check }) req.additional_api_log_data.permission_check_succeeded = false req.additional_api_log_data.permission_check_reason = reason req.additional_api_log_data.permission_check_activity_id = fail_activity.id return res.status(401) .message('Insufficient permissions.') .api() } req.additional_api_log_data.permission_check_succeeded = true return next() } } module.exports = exports = PermissionMiddleware