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 81 82 83 84 85 86 87 88 89 90 91 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 7x 7x 7x 7x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 1x | import {type IMeta, handler} from '@feasibleone/blong';
import * as model from './accessModel.ts';
import * as account from './account.ts';
type KnexQb = any;
/**
* `access.user.add` — create a user (resource + `access_user` row), plus
* optional credentials and granted roles.
*
* Reuses `core.resource.ensure` to create the resource-backed row (the generic
* knex `add` cannot — the PK is `uidNotNull`, not `uuid()`), and
* `core.triple.merge` for the `hasRole` edges. Credentials are hashed via the
* shared password library. A submitted `matrix` seeds 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 accessUserAdd(
params: {
user?: {emailAddress?: string; isActive?: boolean; userName?: string};
credential?: Array<Record<string, unknown>>;
role?: Array<{roleId?: string; roleName?: string; granted?: boolean}>;
matrix?: model.AclMatrixRow[];
},
$meta: IMeta,
): Promise<Record<string, unknown>> {
const qb: KnexQb = this.config?.context?.queryBuilder;
if (!qb) throw new Error('Database not available');
const user = params.user ?? {};
const name = user.emailAddress || user.userName || `user-${Date.now()}`;
const {resourceId} = await coreResourceEnsure<{resourceId: string}>(
{
name,
typeAlias: 'access.user',
table: 'access_user',
extraColumns: {
emailAddress: user.emailAddress ?? null,
isActive: user.isActive ?? 1,
},
keyName: 'userId',
},
$meta,
);
const userIdHex = model.binHex(resourceId);
if (!userIdHex) throw new Error('Could not resolve user resource id');
if (Array.isArray(params.credential) && params.credential.length) {
await model.syncCredentials(
qb,
{hashPassword, credentialPolicyParams},
userIdHex,
params.credential,
);
}
const roleIds = (params.role ?? [])
.filter(r => r.granted !== false)
.map(r => model.binHex(r.roleId))
.filter((x): x is string => !!x);
if (roleIds.length) {
await model.syncEdges(qb, coreTripleMerge, userIdHex, 'hasRole', roleIds, $meta);
}
if (Array.isArray(params.matrix) && params.matrix.length) {
await model.syncAclMatrix(
qb,
{
coreResourceEnsure,
newAclId: () => Buffer.from(crockfordDecode(ulid())),
},
userIdHex,
params.matrix,
$meta,
);
}
return {
user: {
userId: model.bufToBase64(account.uuidBuf(resourceId)),
emailAddress: user.emailAddress ?? null,
isActive: user.isActive ?? 1,
},
};
},
}),
);
|