All files / src/security doPermApplyToCtx.ts

87.65% Statements 71/81
59.09% Branches 13/22
100% Functions 2/2
87.65% Lines 71/81

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 72 73 74 75 76 77 78 79 80 811x 1x 1x 1x 1x 1x 1x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x 36x         36x 4x 2x 2x   4x 32x 36x 9x 9x 9x 32x 36x 32x 32x 32x 32x 35x 35x 32x 32x 1x 1x 1x 1x 1x 35x 35x 35x 35x 35x 35x 35x 35x 35x 15x           15x 35x 35x 35x
 
 
import { ForClauseParsed } from '../types/core.types'
 
import { asArray } from 'topkat-utils'
 
export async function doPermApplyToCtx(
    ctx: Ctx,
    expectedPermissions: MaybeArray<ForClauseParsed>,
    /** Define which value should be returned when ctx.isSystem.
     * * => 'matchStrict' will search for an exact matching perm in forPerms
     * * => 'matchAll' will search for a matching perm in forPerms, including 'ALL' perm
     */
    returnValueIfSystem: 'alwaysReturnTrue' | 'alwaysReturnFalse' | 'matchStrict' | 'matchAll',
    /** Define which value should be returned when ctx.isPublic.
     * * => 'matchStrict' will search for an exact matching perm in forPerms
     * * => 'matchAll' will search for a matching perm in forPerms, including 'ALL' perm
     */
    returnValueIfPublic: 'alwaysReturnTrue' | 'alwaysReturnFalse' | 'matchStrict' | 'matchAll',
    /** If forPerm includes public, what shall be returned for a user with a perm 'user' for example? */
    returnValueIfForPermContainsPublic: 'alwaysReturnTrue' | 'alwaysReturnFalse' | 'match'
): Promise<boolean> {
 
    const expectedPermArr = asArray(expectedPermissions)
 
 
    const permsThatApplyToUser = []
 
    const publicTargeted = expectedPermArr.some(p => p.role === 'public')
    const systemTargeted = expectedPermArr.some(p => p.role === 'system')
 
    if (ctx.isSystem) {
        if (systemTargeted) return true
        else if (returnValueIfSystem === 'alwaysReturnFalse') return false
        else if (returnValueIfSystem === 'alwaysReturnTrue') return true
        else if (returnValueIfSystem === 'matchAll') permsThatApplyToUser.push('ALL')
    } else if (ctx.isPublic) {
        if (publicTargeted) return true
        else if (returnValueIfPublic === 'alwaysReturnFalse') return false
        else if (returnValueIfPublic === 'alwaysReturnTrue') return true
        else if (returnValueIfPublic === 'matchAll') permsThatApplyToUser.push('ALL')
    }
 
    if (publicTargeted) {
        if (returnValueIfForPermContainsPublic === 'alwaysReturnFalse') return false
        else if (returnValueIfForPermContainsPublic === 'alwaysReturnTrue') return true
    }
 
    if (ctx.isSystem) permsThatApplyToUser.push('system')
    else if (ctx.isPublic) permsThatApplyToUser.push('public')
    else permsThatApplyToUser.push('ALL', ctx.role)
 
    return expectedPermArr.some(p => {
        const { role, ...permissions } = p
        return doPermAndRoleMatch(permsThatApplyToUser, role, ctx.permissions, permissions)
    })
}
 
 
 
 
 
function doPermAndRoleMatch(
    inputRole: string | string[],
    expectedRole: string,
    inputPermissions = {},
    expectedPermissions = {}
) {
    const roleMatch = expectedRole ? asArray(inputRole).includes(expectedRole) : true
    let permissionMatch = true
    if (roleMatch) {
        for (const [permName, expectedPermValue] of Object.entries(expectedPermissions)) {
            const userPerm = typeof inputPermissions[permName] !== 'undefined' ? inputPermissions[permName] : false
            if (userPerm !== expectedPermValue) {
                permissionMatch = false
            }
        }
    }
 
    return roleMatch && permissionMatch
}