All files / src/lib/middleware rbac-middleware.ts

100% Statements 24/24
100% Branches 9/9
100% Functions 3/3
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71  62x                                     62x         163x 163x   163x 753x 492x   492x 1x 1x     491x 475x     16x 1x 1x       15x       15x 4x 4x 11x 3x     15x             753x       62x  
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import {
    CREATE_FEATURE,
    DELETE_FEATURE,
    ADMIN,
    UPDATE_FEATURE,
} from '../types/permissions';
import { IUnleashConfig } from '../types/option';
import { IUnleashStores } from '../types/stores';
import User from '../types/user';
 
interface PermissionChecker {
    hasPermission(
        user: User,
        permission: string,
        projectId?: string,
        environment?: string,
    ): Promise<boolean>;
}
 
const rbacMiddleware = (
    config: Pick<IUnleashConfig, 'getLogger'>,
    { featureToggleStore }: Pick<IUnleashStores, 'featureToggleStore'>,
    accessService: PermissionChecker,
): any => {
    const logger = config.getLogger('/middleware/rbac-middleware.ts');
    logger.debug('Enabling RBAC middleware');
 
    return (req, res, next) => {
        req.checkRbac = async (permission: string) => {
            const { user, params } = req;
 
            if (!user) {
                logger.error('RBAC requires a user to exist on the request.');
                return false;
            }
 
            if (user.isAPI) {
                return user.permissions.includes(ADMIN);
            }
 
            if (!user.id) {
                logger.error('RBAC requires the user to have a unique id.');
                return false;
            }
 
            // For /api/admin/projects/:projectId we will find it as part of params
            let { projectId, environment } = params;
 
            // Temporary workaround to figure out projectId for feature toggle updates.
            // will be removed in Unleash v5.0
            if ([DELETE_FEATURE, UPDATE_FEATURE].includes(permission)) {
                const { featureName } = params;
                projectId = await featureToggleStore.getProjectId(featureName);
            } else if (permission === CREATE_FEATURE) {
                projectId = projectId || req.body.project || 'default';
            }
 
            return accessService.hasPermission(
                user,
                permission,
                projectId,
                environment,
            );
        };
        return next();
    };
};
 
export default rbacMiddleware;