public async authorizationCheck()

in source/packages/services/assetlibrary/src/authz/authz.full.service.ts [28:107]


    public async authorizationCheck(
        deviceIds: string[],
        groupPaths: string[],
        accessLevelRequired: ClaimAccess
    ): Promise<void> {
        logger.debug(
            `authz.full.service authorizationCheck: in: deviceIds:${deviceIds}, groupPaths:${groupPaths}, accessLevelRequired:${accessLevelRequired}`
        );

        if (!this.isAuthzEnabled) {
            logger.debug(`authz.full.service authorizationCheck: authz not enabled`);
            return;
        }

        if (deviceIds === undefined || deviceIds === null) {
            deviceIds = [];
        }
        if (groupPaths === undefined || groupPaths === null) {
            groupPaths = [];
        }

        const combinedIds: string[] = [...new Set([...deviceIds, ...groupPaths])];

        logger.debug(
            `authz.full.service authorizationCheck: combinedIds:${JSON.stringify(combinedIds)}`
        );
        if (combinedIds.length === 0) {
            return;
        }

        // retrieve the claims from the thread local
        const claims = Claims.getInstance();
        logger.debug(`authz.full.service authorizationCheck: claims: ${JSON.stringify(claims)}`);

        // determine if the user has any access to provided ids via their allowed hierarchies
        const authorizations = await this.dao.listAuthorizedHierarchies(
            deviceIds,
            groupPaths,
            claims.listPaths()
        );

        const existsSet =
            authorizations?.exists !== undefined ? new Set(authorizations.exists) : undefined;
        // if one of the requested items is missing, we refuse the whole request
        if ((existsSet?.size ?? 0) !== combinedIds.length) {
            const notFound = combinedIds.filter((id) => !authorizations.exists.includes(id));
            throw new NotFoundError(`Device(s)/group(s) ${JSON.stringify(notFound)} not found.`);
        }

        // if the user does not have access to all, then not authorized to any
        const notAuthorized = Object.keys(authorizations.authorized).filter(
            (k) => !combinedIds.includes(k)
        );
        if (notAuthorized.length > 0) {
            throw new NotAuthorizedError(
                `Access to ${JSON.stringify(notAuthorized)} not authorized.`
            );
        }

        // even though the user has access to a hierarchy, need to ensure its the right level of access
        const entitiesWithSufficientAccess: string[] = [];
        for (const entityId of Object.keys(authorizations.authorized)) {
            const paths = authorizations.authorized[entityId];
            for (const path of paths) {
                if (claims.hasAccessForPath(path, accessLevelRequired)) {
                    entitiesWithSufficientAccess.push(entityId);
                    break;
                }
            }
        }

        if (entitiesWithSufficientAccess.length !== combinedIds.length) {
            logger.debug(`authz.full.service authorizationCheck: not authorized`);
            throw new NotAuthorizedError(
                `Insufficient access to ${JSON.stringify(entitiesWithSufficientAccess)}.`
            );
        }

        logger.debug(`authz.full.service authorizationCheck: exit`);
    }