All files / realm/blong-access/adapter/db accessUserEdit.ts

65.21% Statements 45/69
28.57% Branches 2/7
50% Functions 1/2
65.21% Lines 45/69

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 701x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 7x 7x 7x 7x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x               3x             3x                       3x 3x 7x 1x  
import {type IMeta, handler} from '@feasibleone/blong';
 
import * as model from './accessModel.ts';
 
type KnexQb = any;
 
/**
 * `access.user.edit` — update a user's columns plus its credential rows and
 * granted roles.
 *
 * The standard `access_user` update runs through the automatic knex CRUD
 * (`super.exec`). Credential rows are then synced (only when the form actually
 * submitted a `credential` array — otherwise they are left untouched), the
 * `hasRole` edges are brought in line with the submitted `role` array, and the
 * `matrix` array updates the user's own scope-level `access_acl` rules.
 */
export default handler(
    ({
        handler: {
            'db/coreResourceEnsure': coreResourceEnsure,
            'db/coreTripleMerge': coreTripleMerge,
        },
        lib: {hashPassword, credentialPolicyParams, ulid, crockfordDecode},
    }) => ({
        async accessUserEdit(
            params: {
                user?: {userId?: string; emailAddress?: string; isActive?: boolean};
                credential?: Array<Record<string, unknown>>;
                role?: Array<{roleId?: string; roleName?: string; granted?: boolean}>;
                matrix?: model.AclMatrixRow[];
            },
            $meta: IMeta,
        ): Promise<unknown> {
            const qb: KnexQb = this.config?.context?.queryBuilder;
            if (!qb) throw new Error('Database not available');
            const result = await super.exec(params, $meta);
            const hex = model.binHex(params.user?.userId);
            if (!hex) throw new Error('Invalid user id');
            if (Array.isArray(params.credential)) {
                await model.syncCredentials(
                    qb,
                    {hashPassword, credentialPolicyParams},
                    hex,
                    params.credential,
                );
            }
            if (Array.isArray(params.role)) {
                const roleIds = (params.role ?? [])
                    .filter(r => r.granted !== false)
                    .map(r => model.binHex(r.roleId))
                    .filter((x): x is string => !!x);
                await model.syncEdges(qb, coreTripleMerge, hex, 'hasRole', roleIds, $meta);
            }
            if (Array.isArray(params.matrix)) {
                await model.syncAclMatrix(
                    qb,
                    {
                        coreResourceEnsure,
                        newAclId: () => Buffer.from(crockfordDecode(ulid())),
                    },
                    hex,
                    params.matrix,
                    $meta,
                );
            }
            return result;
        },
    }),
);