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 | 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 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 1x | import {type IMeta, handler} from '@feasibleone/blong';
import {newUuid, uuidBuf} from './gatewayUuid.ts';
type KnexQb = any;
/**
* Register an OAuth application for a developer.
*
* Wire: `gateway.application.register` — creates the application resource
* (clientId = resourceName) plus its `clientSecret` credential (via
* `access.credential.add`). The client secret is returned ONCE; it cannot be
* retrieved later (only re-issued by rotating the credential).
*
* Uses the shared `core.resource.ensure` helper (find-or-create by name) so
* re-registering the same clientId is idempotent — the existing resource is
* reused and `access.credential.add` rotates the active secret.
*/
export default handler(
({
errors,
lib: {crockfordDecode, crockfordEncode},
handler: {'db/coreResourceEnsure': coreResourceEnsure, accessCredentialAdd},
}) =>
async function gatewayApplicationRegister(
params: {
/** ClientId / application display name. */
clientId: string;
/** Owner (developer) resource id (hex UUID); defaults to the authenticated user. */
ownerUserId?: string;
applicationType?: string;
description?: string;
isActive?: boolean;
},
$meta: IMeta,
): Promise<{
applicationId: string;
clientId: string;
clientSecret: string;
}> {
const qb: KnexQb = this.config?.context?.queryBuilder;
if (!qb) throw new Error('Database not available');
// Resolve the owner from the authenticated developer when not supplied.
const ownerUserId =
params.ownerUserId ??
(() => {
const actorId = ($meta?.auth as {actorId?: string} | undefined)?.actorId;
if (!actorId) throw errors.applicationNotFound();
return Buffer.from(crockfordDecode(actorId) as Uint8Array).toString('hex');
})();
const {resourceId: applicationId} = await coreResourceEnsure<{resourceId: string}>(
{
name: params.clientId,
typeAlias: 'gateway.application',
table: 'gateway_application',
extraColumns: {
ownerUserId: uuidBuf(ownerUserId),
applicationType: params.applicationType ?? 'oauth2_client',
description: params.description ?? 'Registered application',
isActive: params.isActive ?? 1,
},
keyName: 'applicationId',
},
$meta,
);
const clientSecret = newUuid();
await accessCredentialAdd<{success: boolean}>(
{
subjectResourceId: applicationId,
credentialType: 'clientSecret',
secret: clientSecret,
isActive: params.isActive ?? 1,
},
$meta,
);
return {
applicationId: crockfordEncode(uuidBuf(applicationId)),
clientId: params.clientId,
clientSecret,
};
},
);
|