@devxcrew/platform 0.1.2 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -2
- package/dist/modules/identity/audit/audit.controller.d.ts +17 -0
- package/dist/modules/identity/audit/audit.controller.js +12 -0
- package/dist/modules/identity/audit/audit.migration.d.ts +1 -0
- package/dist/modules/identity/audit/audit.migration.js +1 -0
- package/dist/modules/identity/audit/audit.provider.d.ts +24 -0
- package/dist/modules/identity/audit/audit.provider.js +14 -0
- package/dist/modules/identity/audit/audit.repository.d.ts +26 -0
- package/dist/modules/identity/audit/audit.repository.js +46 -0
- package/dist/modules/identity/audit/audit.routes.d.ts +5 -0
- package/dist/modules/identity/audit/audit.routes.js +2 -0
- package/dist/modules/identity/audit/audit.schema.d.ts +1 -0
- package/dist/modules/identity/audit/audit.schema.js +1 -0
- package/dist/modules/identity/audit/audit.seed.d.ts +1 -0
- package/dist/modules/identity/audit/audit.seed.js +1 -0
- package/dist/modules/identity/audit/audit.service.d.ts +23 -0
- package/dist/modules/identity/audit/audit.service.js +46 -0
- package/dist/modules/identity/audit/audit.types.d.ts +12 -0
- package/dist/modules/identity/audit/audit.types.js +1 -0
- package/dist/modules/identity/audit/index.d.ts +4 -0
- package/dist/modules/identity/audit/index.js +3 -0
- package/dist/modules/identity/{identity.administration-service.d.ts → composition/identity.composition.d.ts} +59 -27
- package/dist/modules/identity/composition/identity.composition.js +171 -0
- package/dist/modules/identity/composition/identity.seed.d.ts +3 -0
- package/dist/modules/identity/composition/identity.seed.js +16 -0
- package/dist/modules/identity/identity.controller.d.ts +8 -6
- package/dist/modules/identity/identity.controller.js +90 -70
- package/dist/modules/identity/identity.migration.d.ts +1 -2
- package/dist/modules/identity/identity.migration.js +1 -79
- package/dist/modules/identity/identity.provider.d.ts +39 -13
- package/dist/modules/identity/identity.provider.js +19 -73
- package/dist/modules/identity/identity.public-schemas.d.ts +9 -3
- package/dist/modules/identity/identity.public-schemas.js +9 -3
- package/dist/modules/identity/identity.repository.d.ts +1 -40
- package/dist/modules/identity/identity.repository.js +1 -196
- package/dist/modules/identity/identity.routes.d.ts +2 -5
- package/dist/modules/identity/identity.routes.js +3 -11
- package/dist/modules/identity/identity.schema.d.ts +1 -27
- package/dist/modules/identity/identity.schema.js +1 -34
- package/dist/modules/identity/identity.seed.d.ts +1 -3
- package/dist/modules/identity/identity.seed.js +1 -81
- package/dist/modules/identity/identity.service.d.ts +1 -32
- package/dist/modules/identity/identity.service.js +1 -83
- package/dist/modules/identity/identity.types.d.ts +13 -106
- package/dist/modules/identity/index.d.ts +18 -11
- package/dist/modules/identity/index.js +14 -8
- package/dist/modules/identity/{identity.administration-migration.js → legacy/identity.administration-migration.js} +3 -11
- package/dist/modules/identity/legacy/identity.migration.d.ts +2 -0
- package/dist/modules/identity/legacy/identity.migration.js +72 -0
- package/dist/modules/identity/organization/index.d.ts +6 -0
- package/dist/modules/identity/organization/index.js +5 -0
- package/dist/modules/identity/organization/organization.controller.d.ts +35 -0
- package/dist/modules/identity/organization/organization.controller.js +18 -0
- package/dist/modules/identity/organization/organization.migration.d.ts +1 -0
- package/dist/modules/identity/organization/organization.migration.js +1 -0
- package/dist/modules/identity/organization/organization.provider.d.ts +46 -0
- package/dist/modules/identity/organization/organization.provider.js +33 -0
- package/dist/modules/identity/organization/organization.repository.d.ts +58 -0
- package/dist/modules/identity/organization/organization.repository.js +101 -0
- package/dist/modules/identity/organization/organization.routes.d.ts +5 -0
- package/dist/modules/identity/organization/organization.routes.js +2 -0
- package/dist/modules/identity/organization/organization.schema.d.ts +11 -0
- package/dist/modules/identity/organization/organization.schema.js +18 -0
- package/dist/modules/identity/organization/organization.seed.d.ts +3 -0
- package/dist/modules/identity/organization/organization.seed.js +11 -0
- package/dist/modules/identity/organization/organization.service.d.ts +39 -0
- package/dist/modules/identity/organization/organization.service.js +55 -0
- package/dist/modules/identity/organization/organization.types.d.ts +19 -0
- package/dist/modules/identity/organization/organization.types.js +1 -0
- package/dist/modules/identity/permission/index.d.ts +9 -0
- package/dist/modules/identity/permission/index.js +6 -0
- package/dist/modules/identity/permission/permission.controller.d.ts +21 -0
- package/dist/modules/identity/permission/permission.controller.js +12 -0
- package/dist/modules/identity/{identity.permission-declarations-migration.js → permission/permission.declarations.migration.js} +9 -4
- package/dist/modules/identity/{identity.permission-labels-migration.js → permission/permission.labels.migration.js} +5 -2
- package/dist/modules/identity/permission/permission.migration.d.ts +2 -0
- package/dist/modules/identity/permission/permission.migration.js +2 -0
- package/dist/modules/identity/permission/permission.provider.d.ts +19 -0
- package/dist/modules/identity/permission/permission.provider.js +14 -0
- package/dist/modules/identity/permission/permission.repository.d.ts +51 -0
- package/dist/modules/identity/permission/permission.repository.js +84 -0
- package/dist/modules/identity/permission/permission.routes.d.ts +5 -0
- package/dist/modules/identity/permission/permission.routes.js +2 -0
- package/dist/modules/identity/permission/permission.schema.d.ts +14 -0
- package/dist/modules/identity/permission/permission.schema.js +29 -0
- package/dist/modules/identity/permission/permission.seed.d.ts +4 -0
- package/dist/modules/identity/permission/permission.seed.js +17 -0
- package/dist/modules/identity/permission/permission.service.d.ts +31 -0
- package/dist/modules/identity/permission/permission.service.js +77 -0
- package/dist/modules/identity/permission/permission.types.d.ts +15 -0
- package/dist/modules/identity/permission/permission.types.js +1 -0
- package/dist/modules/identity/role/index.d.ts +10 -0
- package/dist/modules/identity/role/index.js +6 -0
- package/dist/modules/identity/role/role.controller.d.ts +42 -0
- package/dist/modules/identity/role/role.controller.js +25 -0
- package/dist/modules/identity/{identity.roles-migration.js → role/role.migration.js} +5 -18
- package/dist/modules/identity/role/role.provider.d.ts +14 -0
- package/dist/modules/identity/role/role.provider.js +30 -0
- package/dist/modules/identity/role/role.repository.d.ts +38 -0
- package/dist/modules/identity/role/role.repository.js +46 -0
- package/dist/modules/identity/role/role.routes.d.ts +5 -0
- package/dist/modules/identity/role/role.routes.js +2 -0
- package/dist/modules/identity/role/role.schema.d.ts +16 -0
- package/dist/modules/identity/role/role.schema.js +27 -0
- package/dist/modules/identity/role/role.seed.d.ts +3 -0
- package/dist/modules/identity/role/role.seed.js +8 -0
- package/dist/modules/identity/role/role.service.d.ts +69 -0
- package/dist/modules/identity/role/role.service.js +192 -0
- package/dist/modules/identity/role/role.types.d.ts +17 -0
- package/dist/modules/identity/role/role.types.js +1 -0
- package/dist/modules/identity/role-permission/index.d.ts +6 -0
- package/dist/modules/identity/role-permission/index.js +4 -0
- package/dist/modules/identity/role-permission/role-permission.controller.d.ts +1 -0
- package/dist/modules/identity/role-permission/role-permission.controller.js +1 -0
- package/dist/modules/identity/role-permission/role-permission.migration.d.ts +1 -0
- package/dist/modules/identity/role-permission/role-permission.migration.js +1 -0
- package/dist/modules/identity/role-permission/role-permission.provider.d.ts +14 -0
- package/dist/modules/identity/role-permission/role-permission.provider.js +15 -0
- package/dist/modules/identity/role-permission/role-permission.repository.d.ts +12 -0
- package/dist/modules/identity/role-permission/role-permission.repository.js +51 -0
- package/dist/modules/identity/role-permission/role-permission.routes.d.ts +1 -0
- package/dist/modules/identity/role-permission/role-permission.routes.js +2 -0
- package/dist/modules/identity/role-permission/role-permission.schema.d.ts +2 -0
- package/dist/modules/identity/role-permission/role-permission.schema.js +3 -0
- package/dist/modules/identity/role-permission/role-permission.seed.d.ts +3 -0
- package/dist/modules/identity/role-permission/role-permission.seed.js +10 -0
- package/dist/modules/identity/role-permission/role-permission.service.d.ts +13 -0
- package/dist/modules/identity/role-permission/role-permission.service.js +35 -0
- package/dist/modules/identity/role-permission/role-permission.types.d.ts +12 -0
- package/dist/modules/identity/role-permission/role-permission.types.js +1 -0
- package/dist/modules/identity/session/index.d.ts +6 -0
- package/dist/modules/identity/session/index.js +5 -0
- package/dist/modules/identity/session/session.authentication.controller.d.ts +30 -0
- package/dist/modules/identity/session/session.authentication.controller.js +37 -0
- package/dist/modules/identity/session/session.controller.d.ts +18 -0
- package/dist/modules/identity/session/session.controller.js +15 -0
- package/dist/modules/identity/session/session.migration.d.ts +1 -0
- package/dist/modules/identity/session/session.migration.js +1 -0
- package/dist/modules/identity/session/session.provider.d.ts +34 -0
- package/dist/modules/identity/session/session.provider.js +23 -0
- package/dist/modules/identity/session/session.repository.d.ts +36 -0
- package/dist/modules/identity/session/session.repository.js +128 -0
- package/dist/modules/identity/session/session.routes.d.ts +27 -0
- package/dist/modules/identity/session/session.routes.js +13 -0
- package/dist/modules/identity/session/session.schema.d.ts +6 -0
- package/dist/modules/identity/session/session.schema.js +12 -0
- package/dist/modules/identity/session/session.seed.d.ts +1 -0
- package/dist/modules/identity/session/session.seed.js +1 -0
- package/dist/modules/identity/session/session.service.d.ts +20 -0
- package/dist/modules/identity/session/session.service.js +27 -0
- package/dist/modules/identity/session/session.types.d.ts +17 -0
- package/dist/modules/identity/session/session.types.js +1 -0
- package/dist/modules/identity/settings/index.d.ts +5 -0
- package/dist/modules/identity/settings/index.js +4 -0
- package/dist/modules/identity/settings/settings.controller.d.ts +35 -0
- package/dist/modules/identity/settings/settings.controller.js +18 -0
- package/dist/modules/identity/settings/settings.migration.d.ts +1 -0
- package/dist/modules/identity/settings/settings.migration.js +1 -0
- package/dist/modules/identity/settings/settings.provider.d.ts +35 -0
- package/dist/modules/identity/settings/settings.provider.js +14 -0
- package/dist/modules/identity/settings/settings.repository.d.ts +49 -0
- package/dist/modules/identity/settings/settings.repository.js +75 -0
- package/dist/modules/identity/settings/settings.routes.d.ts +1 -0
- package/dist/modules/identity/settings/settings.routes.js +7 -0
- package/dist/modules/identity/settings/settings.schema.d.ts +15 -0
- package/dist/modules/identity/settings/settings.schema.js +27 -0
- package/dist/modules/identity/settings/settings.seed.d.ts +1 -0
- package/dist/modules/identity/settings/settings.seed.js +1 -0
- package/dist/modules/identity/settings/settings.service.d.ts +40 -0
- package/dist/modules/identity/settings/settings.service.js +101 -0
- package/dist/modules/identity/settings/settings.types.d.ts +20 -0
- package/dist/modules/identity/settings/settings.types.js +1 -0
- package/dist/modules/identity/support/identity.schema.d.ts +8 -0
- package/dist/modules/identity/support/identity.schema.js +10 -0
- package/dist/modules/identity/support/pagination.d.ts +13 -0
- package/dist/modules/identity/support/pagination.js +27 -0
- package/dist/modules/identity/support/pagination.schema.d.ts +43 -0
- package/dist/modules/identity/support/pagination.schema.js +15 -0
- package/dist/modules/identity/support/resource-controller.d.ts +14 -0
- package/dist/modules/identity/support/resource-controller.js +1 -0
- package/dist/modules/identity/user/index.d.ts +13 -0
- package/dist/modules/identity/user/index.js +11 -0
- package/dist/modules/identity/user/user.administration.service.d.ts +59 -0
- package/dist/modules/identity/user/user.administration.service.js +159 -0
- package/dist/modules/identity/user/user.controller.d.ts +44 -0
- package/dist/modules/identity/user/user.controller.js +21 -0
- package/dist/modules/identity/user/user.lifecycle.controller.d.ts +58 -0
- package/dist/modules/identity/user/user.lifecycle.controller.js +27 -0
- package/dist/modules/identity/{identity.lifecycle-schema.js → user/user.lifecycle.schema.js} +5 -5
- package/dist/modules/identity/{identity.lifecycle-service.d.ts → user/user.lifecycle.service.d.ts} +8 -4
- package/dist/modules/identity/{identity.lifecycle-service.js → user/user.lifecycle.service.js} +66 -118
- package/dist/modules/identity/user/user.migration.d.ts +1 -0
- package/dist/modules/identity/user/user.migration.js +1 -0
- package/dist/modules/identity/{identity.password.js → user/user.password.js} +1 -1
- package/dist/modules/identity/user/user.provider.d.ts +80 -0
- package/dist/modules/identity/user/user.provider.js +22 -0
- package/dist/modules/identity/user/user.repository.d.ts +64 -0
- package/dist/modules/identity/user/user.repository.js +129 -0
- package/dist/modules/identity/user/user.routes.d.ts +12 -0
- package/dist/modules/identity/user/user.routes.js +9 -0
- package/dist/modules/identity/user/user.schema.d.ts +34 -0
- package/dist/modules/identity/user/user.schema.js +46 -0
- package/dist/modules/identity/user/user.seed.d.ts +14 -0
- package/dist/modules/identity/user/user.seed.js +47 -0
- package/dist/modules/identity/user/user.service.d.ts +33 -0
- package/dist/modules/identity/user/user.service.js +76 -0
- package/dist/modules/identity/user/user.types.d.ts +27 -0
- package/dist/modules/identity/user/user.types.js +1 -0
- package/dist/modules/identity/user-role/index.d.ts +8 -0
- package/dist/modules/identity/user-role/index.js +6 -0
- package/dist/modules/identity/user-role/user-role.controller.d.ts +42 -0
- package/dist/modules/identity/user-role/user-role.controller.js +21 -0
- package/dist/modules/identity/user-role/user-role.migration.d.ts +1 -0
- package/dist/modules/identity/user-role/user-role.migration.js +1 -0
- package/dist/modules/identity/user-role/user-role.policy.d.ts +3 -0
- package/dist/modules/identity/user-role/user-role.policy.js +25 -0
- package/dist/modules/identity/user-role/user-role.provider.d.ts +18 -0
- package/dist/modules/identity/user-role/user-role.provider.js +23 -0
- package/dist/modules/identity/user-role/user-role.repository.d.ts +34 -0
- package/dist/modules/identity/user-role/user-role.repository.js +87 -0
- package/dist/modules/identity/user-role/user-role.routes.d.ts +5 -0
- package/dist/modules/identity/user-role/user-role.routes.js +2 -0
- package/dist/modules/identity/user-role/user-role.schema.d.ts +14 -0
- package/dist/modules/identity/user-role/user-role.schema.js +25 -0
- package/dist/modules/identity/user-role/user-role.seed.d.ts +7 -0
- package/dist/modules/identity/user-role/user-role.seed.js +11 -0
- package/dist/modules/identity/user-role/user-role.service.d.ts +60 -0
- package/dist/modules/identity/user-role/user-role.service.js +216 -0
- package/dist/modules/identity/user-role/user-role.types.d.ts +12 -0
- package/dist/modules/identity/user-role/user-role.types.js +1 -0
- package/dist/modules/tenant/index.d.ts +6 -0
- package/dist/modules/tenant/index.js +5 -0
- package/dist/modules/tenant/tenant.command.d.ts +3 -0
- package/dist/modules/tenant/tenant.command.js +43 -0
- package/dist/modules/tenant/tenant.controller.d.ts +4 -0
- package/dist/modules/tenant/tenant.controller.js +12 -0
- package/dist/modules/tenant/tenant.migration.d.ts +5 -0
- package/dist/modules/tenant/tenant.migration.js +46 -0
- package/dist/modules/tenant/tenant.provider.d.ts +3 -0
- package/dist/modules/tenant/tenant.provider.js +44 -0
- package/dist/modules/tenant/tenant.readiness.d.ts +6 -0
- package/dist/modules/tenant/tenant.readiness.js +45 -0
- package/dist/modules/tenant/tenant.repository.d.ts +15 -0
- package/dist/modules/tenant/tenant.repository.js +23 -0
- package/dist/modules/tenant/tenant.routes.d.ts +4 -0
- package/dist/modules/tenant/tenant.routes.js +7 -0
- package/dist/modules/tenant/tenant.schema.d.ts +20 -0
- package/dist/modules/tenant/tenant.schema.js +31 -0
- package/dist/modules/tenant/tenant.seed.d.ts +8 -0
- package/dist/modules/tenant/tenant.seed.js +40 -0
- package/dist/modules/tenant/tenant.service.d.ts +16 -0
- package/dist/modules/tenant/tenant.service.js +72 -0
- package/dist/modules/tenant/tenant.types.d.ts +39 -0
- package/dist/modules/tenant/tenant.types.js +1 -0
- package/package.json +9 -5
- package/dist/modules/identity/identity.administration-repository.d.ts +0 -19
- package/dist/modules/identity/identity.administration-repository.js +0 -102
- package/dist/modules/identity/identity.administration-schema.d.ts +0 -113
- package/dist/modules/identity/identity.administration-schema.js +0 -121
- package/dist/modules/identity/identity.administration-service.js +0 -517
- package/dist/modules/identity/identity.membership-policy.d.ts +0 -3
- package/dist/modules/identity/identity.membership-policy.js +0 -27
- package/dist/modules/identity/identity.permission-declarations.d.ts +0 -23
- package/dist/modules/identity/identity.permission-declarations.js +0 -57
- package/dist/modules/identity/identity.presentation-service.d.ts +0 -23
- package/dist/modules/identity/identity.presentation-service.js +0 -51
- package/dist/modules/identity/identity.roles-service.d.ts +0 -49
- package/dist/modules/identity/identity.roles-service.js +0 -327
- /package/dist/modules/identity/{identity.administration-migration.d.ts → legacy/identity.administration-migration.d.ts} +0 -0
- /package/dist/modules/identity/{identity.permission-declarations-migration.d.ts → permission/permission.declarations.migration.d.ts} +0 -0
- /package/dist/modules/identity/{identity.permission-labels-migration.d.ts → permission/permission.labels.migration.d.ts} +0 -0
- /package/dist/modules/identity/{identity.roles-migration.d.ts → role/role.migration.d.ts} +0 -0
- /package/dist/modules/identity/{identity.error.d.ts → support/identity.error.d.ts} +0 -0
- /package/dist/modules/identity/{identity.error.js → support/identity.error.js} +0 -0
- /package/dist/modules/identity/{identity.request-context.d.ts → support/identity.request-context.d.ts} +0 -0
- /package/dist/modules/identity/{identity.request-context.js → support/identity.request-context.js} +0 -0
- /package/dist/modules/identity/{identity.lifecycle-schema.d.ts → user/user.lifecycle.schema.d.ts} +0 -0
- /package/dist/modules/identity/{identity.password.d.ts → user/user.password.d.ts} +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export async function seedOrganization(trx, env) {
|
|
2
|
+
await trx
|
|
3
|
+
.insertInto("identity_tenants")
|
|
4
|
+
.values({
|
|
5
|
+
id: env.IDENTITY_TENANT_ID ?? "default",
|
|
6
|
+
name: env.IDENTITY_TENANT_NAME ?? "Default organization",
|
|
7
|
+
active: 1
|
|
8
|
+
})
|
|
9
|
+
.onConflict((c) => c.column("id").doNothing())
|
|
10
|
+
.execute();
|
|
11
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Transaction } from "kysely";
|
|
2
|
+
import type { IdentityMutation, IdentitySchema, Principal } from "../identity.types.js";
|
|
3
|
+
import { IdentityOrganizationRepository } from "./organization.repository.js";
|
|
4
|
+
import type { IdentityListQuery } from "../support/pagination.schema.js";
|
|
5
|
+
export declare class IdentityOrganizationService {
|
|
6
|
+
private readonly repository;
|
|
7
|
+
private readonly mutate;
|
|
8
|
+
private readonly revokeTenantSessions;
|
|
9
|
+
constructor(repository: IdentityOrganizationRepository, mutate: IdentityMutation, revokeTenantSessions: (trx: Transaction<IdentitySchema>, tenantId: string) => Promise<void>);
|
|
10
|
+
list(actor: Principal, query: IdentityListQuery): Promise<{
|
|
11
|
+
data: {
|
|
12
|
+
active: boolean;
|
|
13
|
+
version: number;
|
|
14
|
+
}[];
|
|
15
|
+
meta: {
|
|
16
|
+
page: number;
|
|
17
|
+
perPage: number;
|
|
18
|
+
total: number;
|
|
19
|
+
lastPage: number;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
show(actor: Principal, id: string): Promise<{
|
|
23
|
+
active: boolean;
|
|
24
|
+
version: number;
|
|
25
|
+
} | undefined>;
|
|
26
|
+
create(actor: Principal, raw: unknown): Promise<{
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
active: boolean;
|
|
30
|
+
version: number;
|
|
31
|
+
}>;
|
|
32
|
+
update(actor: Principal, id: string, raw: unknown): Promise<{
|
|
33
|
+
active: boolean;
|
|
34
|
+
version: number;
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
}>;
|
|
38
|
+
private manage;
|
|
39
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { IdentityError } from "../support/identity.error.js";
|
|
2
|
+
import { organizationCreateSchema, organizationUpdateSchema } from "./organization.schema.js";
|
|
3
|
+
export class IdentityOrganizationService {
|
|
4
|
+
repository;
|
|
5
|
+
mutate;
|
|
6
|
+
revokeTenantSessions;
|
|
7
|
+
constructor(repository, mutate, revokeTenantSessions) {
|
|
8
|
+
this.repository = repository;
|
|
9
|
+
this.mutate = mutate;
|
|
10
|
+
this.revokeTenantSessions = revokeTenantSessions;
|
|
11
|
+
}
|
|
12
|
+
list(actor, query) {
|
|
13
|
+
if (actor.portal === "user")
|
|
14
|
+
throw new IdentityError(403, "Access denied.");
|
|
15
|
+
return this.repository.list(actor, query);
|
|
16
|
+
}
|
|
17
|
+
show(actor, id) {
|
|
18
|
+
if (actor.portal === "user")
|
|
19
|
+
throw new IdentityError(403, "Access denied.");
|
|
20
|
+
return this.repository.show(actor, id);
|
|
21
|
+
}
|
|
22
|
+
async create(actor, raw) {
|
|
23
|
+
this.manage(actor);
|
|
24
|
+
const input = organizationCreateSchema.parse(raw);
|
|
25
|
+
return this.mutate(actor, "organizations", input.id, async (trx) => {
|
|
26
|
+
if (await this.repository.exists(trx, input.id))
|
|
27
|
+
throw new IdentityError(409, "Organization already exists.");
|
|
28
|
+
await this.repository.create(trx, input);
|
|
29
|
+
return { ...input, version: 0 };
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async update(actor, id, raw) {
|
|
33
|
+
this.manage(actor);
|
|
34
|
+
if (!(await this.show(actor, id)))
|
|
35
|
+
throw new IdentityError(404, "Resource not found.");
|
|
36
|
+
const input = organizationUpdateSchema.parse(raw);
|
|
37
|
+
return this.mutate(actor, "organizations", id, async (trx) => {
|
|
38
|
+
const current = await this.repository.version(trx, id);
|
|
39
|
+
if (Number(current.version) !== input.expectedVersion)
|
|
40
|
+
throw new IdentityError(409, "This record changed. Reload before saving.");
|
|
41
|
+
if (input.active === false && id === actor.tenant.id)
|
|
42
|
+
throw new IdentityError(409, "Cannot deactivate your current organization.");
|
|
43
|
+
if (!(await this.repository.update(trx, id, input)))
|
|
44
|
+
throw new IdentityError(409, "This record changed. Reload before saving.");
|
|
45
|
+
if (input.active === false)
|
|
46
|
+
await this.revokeTenantSessions(trx, id);
|
|
47
|
+
const row = await this.repository.get(trx, id);
|
|
48
|
+
return { ...row, active: Boolean(row.active), version: Number(row.version) };
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
manage(actor) {
|
|
52
|
+
if (actor.portal !== "super-admin" || !actor.permissions.includes("identity.manage"))
|
|
53
|
+
throw new IdentityError(403, "Only super administrators can change this resource.");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Generated } from "kysely";
|
|
2
|
+
export interface IdentityOrganizationTables {
|
|
3
|
+
identity_tenants: {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
active: number;
|
|
7
|
+
version: Generated<number>;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export type IdentityOrganizationRow = IdentityOrganizationTables["identity_tenants"];
|
|
11
|
+
export interface IdentityTenantDirectory {
|
|
12
|
+
active(id: string): Promise<{
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
} | undefined>;
|
|
16
|
+
listActive(after: string, pageSize: number): Promise<{
|
|
17
|
+
id: string;
|
|
18
|
+
}[]>;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createIdentityPermissionProvider } from "./permission.provider.js";
|
|
2
|
+
export type { IdentityPermissionProvider } from "./permission.provider.js";
|
|
3
|
+
export type { IdentityPermissionDeclaration } from "./permission.schema.js";
|
|
4
|
+
export { defaultPermissions, seedPermissions } from "./permission.seed.js";
|
|
5
|
+
export { permissionResource, permissionResourceRoute } from "./permission.routes.js";
|
|
6
|
+
export { identityPermissionDeclarationsMigration } from "./permission.declarations.migration.js";
|
|
7
|
+
export { identityPermissionLabelsMigration } from "./permission.labels.migration.js";
|
|
8
|
+
export type { IdentityPermissionRow, IdentityPermissionDeclarationRow } from "./permission.types.js";
|
|
9
|
+
export { IdentityPermissionController } from "./permission.controller.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createIdentityPermissionProvider } from "./permission.provider.js";
|
|
2
|
+
export { defaultPermissions, seedPermissions } from "./permission.seed.js";
|
|
3
|
+
export { permissionResource, permissionResourceRoute } from "./permission.routes.js";
|
|
4
|
+
export { identityPermissionDeclarationsMigration } from "./permission.declarations.migration.js";
|
|
5
|
+
export { identityPermissionLabelsMigration } from "./permission.labels.migration.js";
|
|
6
|
+
export { IdentityPermissionController } from "./permission.controller.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Principal } from "../identity.types.js";
|
|
2
|
+
import type { IdentityListQuery } from "../support/pagination.schema.js";
|
|
3
|
+
import type { IdentityPermissionProvider } from "./permission.provider.js";
|
|
4
|
+
export declare class IdentityPermissionController {
|
|
5
|
+
private readonly service;
|
|
6
|
+
constructor(service: IdentityPermissionProvider);
|
|
7
|
+
index(actor: Principal, query: IdentityListQuery): Promise<{
|
|
8
|
+
data: {
|
|
9
|
+
portals: string[];
|
|
10
|
+
}[];
|
|
11
|
+
meta: {
|
|
12
|
+
page: number;
|
|
13
|
+
perPage: number;
|
|
14
|
+
total: number;
|
|
15
|
+
lastPage: number;
|
|
16
|
+
};
|
|
17
|
+
}>;
|
|
18
|
+
show(actor: Principal, id: string): Promise<{
|
|
19
|
+
portals: string[];
|
|
20
|
+
} | undefined>;
|
|
21
|
+
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
export const identityPermissionDeclarationsMigration = {
|
|
2
2
|
async up(db) {
|
|
3
|
-
await db.schema
|
|
3
|
+
await db.schema
|
|
4
|
+
.createTable("identity_permission_declarations")
|
|
4
5
|
.addColumn("permission_id", "text", (column) => column.primaryKey().references("identity_permissions.id"))
|
|
5
6
|
.addColumn("app_id", "text", (column) => column.notNull())
|
|
6
7
|
.addColumn("owner", "text", (column) => column.notNull())
|
|
7
|
-
.addColumn("portals", "text", (column) => column.notNull())
|
|
8
|
+
.addColumn("portals", "text", (column) => column.notNull())
|
|
9
|
+
.execute();
|
|
8
10
|
},
|
|
9
11
|
async down(db) {
|
|
10
|
-
const declared = await db
|
|
12
|
+
const declared = await db
|
|
13
|
+
.selectFrom("identity_permission_declarations")
|
|
14
|
+
.select("permission_id")
|
|
15
|
+
.executeTakeFirst();
|
|
11
16
|
if (declared)
|
|
12
17
|
throw new Error("Restore a compatible snapshot before removing permission ownership restrictions.");
|
|
13
18
|
await db.schema.dropTable("identity_permission_declarations").execute();
|
|
14
|
-
}
|
|
19
|
+
}
|
|
15
20
|
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// Additive migration. Do not rewrite the previously applied declaration schema.
|
|
2
2
|
export const identityPermissionLabelsMigration = {
|
|
3
3
|
async up(db) {
|
|
4
|
-
await db.schema
|
|
4
|
+
await db.schema
|
|
5
|
+
.alterTable("identity_permission_declarations")
|
|
6
|
+
.addColumn("label", "text")
|
|
7
|
+
.execute();
|
|
5
8
|
},
|
|
6
9
|
async down(db) {
|
|
7
10
|
await db.schema.alterTable("identity_permission_declarations").dropColumn("label").execute();
|
|
8
|
-
}
|
|
11
|
+
}
|
|
9
12
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Kysely, Transaction } from "kysely";
|
|
2
|
+
import type { IdentitySchema, Portal } from "../identity.types.js";
|
|
3
|
+
import type { IdentityPermissionDeclaration } from "./permission.schema.js";
|
|
4
|
+
import { IdentityPermissionService } from "./permission.service.js";
|
|
5
|
+
import type { Principal } from "../identity.types.js";
|
|
6
|
+
import type { IdentityListQuery } from "../support/pagination.schema.js";
|
|
7
|
+
export interface IdentityPermissionProvider {
|
|
8
|
+
verify(): Promise<void>;
|
|
9
|
+
list(actor: Principal, query: IdentityListQuery): ReturnType<IdentityPermissionService["list"]>;
|
|
10
|
+
show(actor: Principal, id: string): ReturnType<IdentityPermissionService["show"]>;
|
|
11
|
+
register(appId: string, declaration: IdentityPermissionDeclaration): Promise<{
|
|
12
|
+
owner: string;
|
|
13
|
+
permissionIds: string[];
|
|
14
|
+
}>;
|
|
15
|
+
validateDeclared(database: Kysely<IdentitySchema> | Transaction<IdentitySchema>, appId: string, portal: Portal, ids: string[]): Promise<void>;
|
|
16
|
+
validateKnown(database: Transaction<IdentitySchema>, ids: string[]): Promise<void>;
|
|
17
|
+
filterDeclared(database: Kysely<IdentitySchema>, appId: string, portal: Portal, ids: string[]): Promise<string[]>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createIdentityPermissionProvider(database: Kysely<IdentitySchema>): IdentityPermissionProvider;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IdentityPermissionRepository } from "./permission.repository.js";
|
|
2
|
+
import { IdentityPermissionService } from "./permission.service.js";
|
|
3
|
+
export function createIdentityPermissionProvider(database) {
|
|
4
|
+
const service = new IdentityPermissionService(new IdentityPermissionRepository(database));
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
verify: service.verify.bind(service),
|
|
7
|
+
list: service.list.bind(service),
|
|
8
|
+
show: service.show.bind(service),
|
|
9
|
+
register: service.register.bind(service),
|
|
10
|
+
validateDeclared: service.validateDeclared.bind(service),
|
|
11
|
+
validateKnown: service.validateKnown.bind(service),
|
|
12
|
+
filterDeclared: service.filterDeclared.bind(service)
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Kysely, type Transaction } from "kysely";
|
|
2
|
+
import type { IdentitySchema, Principal } from "../identity.types.js";
|
|
3
|
+
import type { IdentityListQuery } from "../support/pagination.schema.js";
|
|
4
|
+
type Database = Kysely<IdentitySchema> | Transaction<IdentitySchema>;
|
|
5
|
+
export declare class IdentityPermissionRepository {
|
|
6
|
+
private readonly db;
|
|
7
|
+
constructor(db: Kysely<IdentitySchema>);
|
|
8
|
+
verifySchema(): Promise<void>;
|
|
9
|
+
list(actor: Principal, query: IdentityListQuery): Promise<{
|
|
10
|
+
data: {
|
|
11
|
+
portals: string[];
|
|
12
|
+
}[];
|
|
13
|
+
meta: {
|
|
14
|
+
page: number;
|
|
15
|
+
perPage: number;
|
|
16
|
+
total: number;
|
|
17
|
+
lastPage: number;
|
|
18
|
+
};
|
|
19
|
+
}>;
|
|
20
|
+
show(actor: Principal, id: string): Promise<{
|
|
21
|
+
portals: string[];
|
|
22
|
+
} | undefined>;
|
|
23
|
+
transaction<T>(action: (trx: Transaction<IdentitySchema>) => Promise<T>): Promise<T>;
|
|
24
|
+
declaration(db: Database, id: string): Promise<{
|
|
25
|
+
app_id: string;
|
|
26
|
+
label: string | null;
|
|
27
|
+
owner: string;
|
|
28
|
+
permission_id: string;
|
|
29
|
+
portals: string;
|
|
30
|
+
} | undefined>;
|
|
31
|
+
declarations(db: Database): Promise<{
|
|
32
|
+
app_id: string;
|
|
33
|
+
label: string | null;
|
|
34
|
+
owner: string;
|
|
35
|
+
permission_id: string;
|
|
36
|
+
portals: string;
|
|
37
|
+
}[]>;
|
|
38
|
+
permission(db: Database, id: string): Promise<{
|
|
39
|
+
id: string;
|
|
40
|
+
} | undefined>;
|
|
41
|
+
knownIds(db: Database): Promise<Set<string>>;
|
|
42
|
+
updateLabel(trx: Transaction<IdentitySchema>, id: string, label: string): Promise<void>;
|
|
43
|
+
create(trx: Transaction<IdentitySchema>, input: {
|
|
44
|
+
id: string;
|
|
45
|
+
appId: string;
|
|
46
|
+
owner: string;
|
|
47
|
+
portals: string;
|
|
48
|
+
label: string | null;
|
|
49
|
+
}): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { sql } from "kysely";
|
|
2
|
+
import { listRows, showRow } from "../support/pagination.js";
|
|
3
|
+
function permissionListSource(actor) {
|
|
4
|
+
return sql `select p.id,coalesce(d.label,p.id) as label,
|
|
5
|
+
coalesce(d.owner,case when p.id like 'desk.%' then 'desk' else 'identity' end) as owner,
|
|
6
|
+
d.app_id as appId,
|
|
7
|
+
coalesce(d.portals,case when p.id='desk.user' then '["user"]' when p.id='desk.admin' then '["admin"]'
|
|
8
|
+
when p.id='desk.super-admin' then '["super-admin"]' when p.id='identity.manage' then '["admin","super-admin"]'
|
|
9
|
+
else '["user","admin","super-admin"]' end) as portals
|
|
10
|
+
from identity_permissions p left join identity_permission_declarations d on d.permission_id=p.id
|
|
11
|
+
where d.permission_id is null or d.app_id=${actor.appId}`;
|
|
12
|
+
}
|
|
13
|
+
export class IdentityPermissionRepository {
|
|
14
|
+
db;
|
|
15
|
+
constructor(db) {
|
|
16
|
+
this.db = db;
|
|
17
|
+
}
|
|
18
|
+
async verifySchema() {
|
|
19
|
+
await this.db.selectFrom("identity_permissions").select("id").limit(1).execute();
|
|
20
|
+
await this.db
|
|
21
|
+
.selectFrom("identity_permission_declarations")
|
|
22
|
+
.select(["permission_id", "label"])
|
|
23
|
+
.limit(1)
|
|
24
|
+
.execute();
|
|
25
|
+
}
|
|
26
|
+
list(actor, query) {
|
|
27
|
+
const present = (row) => ({
|
|
28
|
+
...row,
|
|
29
|
+
portals: JSON.parse(String(row.portals))
|
|
30
|
+
});
|
|
31
|
+
return listRows(this.db, permissionListSource(actor), ["id"], query, present);
|
|
32
|
+
}
|
|
33
|
+
show(actor, id) {
|
|
34
|
+
const present = (row) => ({
|
|
35
|
+
...row,
|
|
36
|
+
portals: JSON.parse(String(row.portals))
|
|
37
|
+
});
|
|
38
|
+
return showRow(this.db, permissionListSource(actor), id, present);
|
|
39
|
+
}
|
|
40
|
+
transaction(action) {
|
|
41
|
+
return this.db.transaction().execute(action);
|
|
42
|
+
}
|
|
43
|
+
declaration(db, id) {
|
|
44
|
+
return db
|
|
45
|
+
.selectFrom("identity_permission_declarations")
|
|
46
|
+
.selectAll()
|
|
47
|
+
.where("permission_id", "=", id)
|
|
48
|
+
.executeTakeFirst();
|
|
49
|
+
}
|
|
50
|
+
declarations(db) {
|
|
51
|
+
return db.selectFrom("identity_permission_declarations").selectAll().execute();
|
|
52
|
+
}
|
|
53
|
+
permission(db, id) {
|
|
54
|
+
return db
|
|
55
|
+
.selectFrom("identity_permissions")
|
|
56
|
+
.select("id")
|
|
57
|
+
.where("id", "=", id)
|
|
58
|
+
.executeTakeFirst();
|
|
59
|
+
}
|
|
60
|
+
async knownIds(db) {
|
|
61
|
+
const rows = await db.selectFrom("identity_permissions").select("id").execute();
|
|
62
|
+
return new Set(rows.map((row) => row.id));
|
|
63
|
+
}
|
|
64
|
+
async updateLabel(trx, id, label) {
|
|
65
|
+
await trx
|
|
66
|
+
.updateTable("identity_permission_declarations")
|
|
67
|
+
.set({ label })
|
|
68
|
+
.where("permission_id", "=", id)
|
|
69
|
+
.execute();
|
|
70
|
+
}
|
|
71
|
+
async create(trx, input) {
|
|
72
|
+
await trx.insertInto("identity_permissions").values({ id: input.id }).execute();
|
|
73
|
+
await trx
|
|
74
|
+
.insertInto("identity_permission_declarations")
|
|
75
|
+
.values({
|
|
76
|
+
permission_id: input.id,
|
|
77
|
+
app_id: input.appId,
|
|
78
|
+
owner: input.owner,
|
|
79
|
+
portals: input.portals,
|
|
80
|
+
label: input.label
|
|
81
|
+
})
|
|
82
|
+
.execute();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const permissionResource: "permissions";
|
|
2
|
+
export declare const permissionResourceRoute: (controller: import("./permission.controller.js").IdentityPermissionController) => {
|
|
3
|
+
resource: "permissions";
|
|
4
|
+
controller: import("./permission.controller.js").IdentityPermissionController;
|
|
5
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const permissionDeclarationSchema: z.ZodObject<{
|
|
3
|
+
owner: z.ZodString;
|
|
4
|
+
permissions: z.ZodArray<z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
portals: z.ZodArray<z.ZodEnum<{
|
|
7
|
+
admin: "admin";
|
|
8
|
+
"super-admin": "super-admin";
|
|
9
|
+
user: "user";
|
|
10
|
+
}>>;
|
|
11
|
+
label: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strict>>;
|
|
13
|
+
}, z.core.$strict>;
|
|
14
|
+
export type IdentityPermissionDeclaration = z.input<typeof permissionDeclarationSchema>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { portalSchema } from "../support/identity.schema.js";
|
|
3
|
+
export const permissionDeclarationSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
owner: z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^[a-z][a-z0-9-]{0,63}$/)
|
|
8
|
+
.refine((value) => !["identity", "desk"].includes(value)),
|
|
9
|
+
permissions: z
|
|
10
|
+
.array(z
|
|
11
|
+
.object({
|
|
12
|
+
id: z
|
|
13
|
+
.string()
|
|
14
|
+
.regex(/^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*){2,8}$/)
|
|
15
|
+
.max(250),
|
|
16
|
+
portals: z.array(portalSchema).min(1).max(3),
|
|
17
|
+
label: z
|
|
18
|
+
.string()
|
|
19
|
+
.trim()
|
|
20
|
+
.min(1)
|
|
21
|
+
.max(100)
|
|
22
|
+
.regex(/^[^\x00-\x1f\x7f]+$/)
|
|
23
|
+
.optional()
|
|
24
|
+
})
|
|
25
|
+
.strict())
|
|
26
|
+
.min(1)
|
|
27
|
+
.max(100)
|
|
28
|
+
})
|
|
29
|
+
.strict();
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Transaction } from "kysely";
|
|
2
|
+
import type { IdentitySchema, Portal } from "../identity.types.js";
|
|
3
|
+
export declare function defaultPermissions(portal: Portal): string[];
|
|
4
|
+
export declare function seedPermissions(trx: Transaction<IdentitySchema>): Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function defaultPermissions(portal) {
|
|
2
|
+
return [
|
|
3
|
+
`desk.${portal}`,
|
|
4
|
+
"identity.self",
|
|
5
|
+
"identity.password",
|
|
6
|
+
...(portal === "user" ? [] : ["identity.manage"])
|
|
7
|
+
];
|
|
8
|
+
}
|
|
9
|
+
export async function seedPermissions(trx) {
|
|
10
|
+
for (const portal of ["user", "admin", "super-admin"])
|
|
11
|
+
for (const permission of defaultPermissions(portal))
|
|
12
|
+
await trx
|
|
13
|
+
.insertInto("identity_permissions")
|
|
14
|
+
.values({ id: permission })
|
|
15
|
+
.onConflict((c) => c.column("id").doNothing())
|
|
16
|
+
.execute();
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Kysely, Transaction } from "kysely";
|
|
2
|
+
import type { IdentitySchema, Portal } from "../identity.types.js";
|
|
3
|
+
import { IdentityPermissionRepository } from "./permission.repository.js";
|
|
4
|
+
import type { Principal } from "../identity.types.js";
|
|
5
|
+
import type { IdentityListQuery } from "../support/pagination.schema.js";
|
|
6
|
+
export declare class IdentityPermissionService {
|
|
7
|
+
private readonly repository;
|
|
8
|
+
constructor(repository: IdentityPermissionRepository);
|
|
9
|
+
verify(): Promise<void>;
|
|
10
|
+
list(actor: Principal, query: IdentityListQuery): Promise<{
|
|
11
|
+
data: {
|
|
12
|
+
portals: string[];
|
|
13
|
+
}[];
|
|
14
|
+
meta: {
|
|
15
|
+
page: number;
|
|
16
|
+
perPage: number;
|
|
17
|
+
total: number;
|
|
18
|
+
lastPage: number;
|
|
19
|
+
};
|
|
20
|
+
}>;
|
|
21
|
+
show(actor: Principal, id: string): Promise<{
|
|
22
|
+
portals: string[];
|
|
23
|
+
} | undefined>;
|
|
24
|
+
register(appId: string, raw: unknown): Promise<{
|
|
25
|
+
owner: string;
|
|
26
|
+
permissionIds: string[];
|
|
27
|
+
}>;
|
|
28
|
+
validateDeclared(db: Kysely<IdentitySchema> | Transaction<IdentitySchema>, appId: string, portal: Portal, ids: string[]): Promise<void>;
|
|
29
|
+
validateKnown(db: Transaction<IdentitySchema>, ids: string[]): Promise<void>;
|
|
30
|
+
filterDeclared(db: Kysely<IdentitySchema>, appId: string, portal: Portal, ids: string[]): Promise<string[]>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { IdentityError } from "../support/identity.error.js";
|
|
2
|
+
import { permissionDeclarationSchema } from "./permission.schema.js";
|
|
3
|
+
export class IdentityPermissionService {
|
|
4
|
+
repository;
|
|
5
|
+
constructor(repository) {
|
|
6
|
+
this.repository = repository;
|
|
7
|
+
}
|
|
8
|
+
verify() {
|
|
9
|
+
return this.repository.verifySchema();
|
|
10
|
+
}
|
|
11
|
+
list(actor, query) {
|
|
12
|
+
if (actor.portal === "user")
|
|
13
|
+
throw new IdentityError(403, "Access denied.");
|
|
14
|
+
return this.repository.list(actor, query);
|
|
15
|
+
}
|
|
16
|
+
show(actor, id) {
|
|
17
|
+
if (actor.portal === "user")
|
|
18
|
+
throw new IdentityError(403, "Access denied.");
|
|
19
|
+
return this.repository.show(actor, id);
|
|
20
|
+
}
|
|
21
|
+
async register(appId, raw) {
|
|
22
|
+
const declaration = permissionDeclarationSchema.parse(raw);
|
|
23
|
+
const ids = new Set();
|
|
24
|
+
for (const permission of declaration.permissions) {
|
|
25
|
+
if (!permission.id.startsWith(`${appId}.${declaration.owner}.`) || ids.has(permission.id))
|
|
26
|
+
throw new IdentityError(422, "Use unique permission IDs in this app and owner namespace.");
|
|
27
|
+
ids.add(permission.id);
|
|
28
|
+
}
|
|
29
|
+
return this.repository.transaction(async (trx) => {
|
|
30
|
+
for (const permission of declaration.permissions) {
|
|
31
|
+
const portals = JSON.stringify([...new Set(permission.portals)].sort());
|
|
32
|
+
const previous = await this.repository.declaration(trx, permission.id);
|
|
33
|
+
if (previous) {
|
|
34
|
+
if (previous.app_id !== appId ||
|
|
35
|
+
previous.owner !== declaration.owner ||
|
|
36
|
+
previous.portals !== portals)
|
|
37
|
+
throw new IdentityError(409, "Permission declaration conflicts with its registered owner or portal policy.");
|
|
38
|
+
if (permission.label !== undefined && permission.label !== previous.label)
|
|
39
|
+
await this.repository.updateLabel(trx, permission.id, permission.label);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (await this.repository.permission(trx, permission.id))
|
|
43
|
+
throw new IdentityError(409, "Permission already exists without this owner declaration.");
|
|
44
|
+
await this.repository.create(trx, {
|
|
45
|
+
id: permission.id,
|
|
46
|
+
appId,
|
|
47
|
+
owner: declaration.owner,
|
|
48
|
+
portals,
|
|
49
|
+
label: permission.label ?? null
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return { owner: declaration.owner, permissionIds: [...ids] };
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async validateDeclared(db, appId, portal, ids) {
|
|
56
|
+
const declarations = await this.repository.declarations(db);
|
|
57
|
+
for (const id of ids) {
|
|
58
|
+
const declaration = declarations.find((row) => row.permission_id === id);
|
|
59
|
+
if (declaration &&
|
|
60
|
+
(declaration.app_id !== appId || !JSON.parse(declaration.portals).includes(portal)))
|
|
61
|
+
throw new IdentityError(403, "Permission is unavailable in this app or portal.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async validateKnown(db, ids) {
|
|
65
|
+
const known = await this.repository.knownIds(db);
|
|
66
|
+
if (ids.some((id) => !known.has(id)))
|
|
67
|
+
throw new IdentityError(422, "Unknown permission.");
|
|
68
|
+
}
|
|
69
|
+
async filterDeclared(db, appId, portal, ids) {
|
|
70
|
+
const declarations = await this.repository.declarations(db);
|
|
71
|
+
return ids.filter((id) => {
|
|
72
|
+
const declaration = declarations.find((row) => row.permission_id === id);
|
|
73
|
+
return (!declaration ||
|
|
74
|
+
(declaration.app_id === appId && JSON.parse(declaration.portals).includes(portal)));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Generated } from "kysely";
|
|
2
|
+
export interface IdentityPermissionTables {
|
|
3
|
+
identity_permissions: {
|
|
4
|
+
id: string;
|
|
5
|
+
};
|
|
6
|
+
identity_permission_declarations: {
|
|
7
|
+
permission_id: string;
|
|
8
|
+
app_id: string;
|
|
9
|
+
owner: string;
|
|
10
|
+
portals: string;
|
|
11
|
+
label: Generated<string | null>;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export type IdentityPermissionRow = IdentityPermissionTables["identity_permissions"];
|
|
15
|
+
export type IdentityPermissionDeclarationRow = IdentityPermissionTables["identity_permission_declarations"];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IdentityRoleProvider } from "./role.provider.js";
|
|
2
|
+
export { createIdentityRoleProvider } from "./role.provider.js";
|
|
3
|
+
export { identityRolesMigration } from "./role.migration.js";
|
|
4
|
+
export { seedRoles } from "./role.seed.js";
|
|
5
|
+
export { roleResource, roleResourceRoute } from "./role.routes.js";
|
|
6
|
+
export { customRoleCreateSchema, customRoleUpdateSchema, roleUpdateSchema } from "./role.schema.js";
|
|
7
|
+
export type { IdentityRoleProvider };
|
|
8
|
+
export type IdentityRoleResolver = IdentityRoleProvider["resolve"];
|
|
9
|
+
export type { IdentityRoleRow, IdentityCustomRoleRow } from "./role.types.js";
|
|
10
|
+
export { IdentityRoleController } from "./role.controller.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createIdentityRoleProvider } from "./role.provider.js";
|
|
2
|
+
export { identityRolesMigration } from "./role.migration.js";
|
|
3
|
+
export { seedRoles } from "./role.seed.js";
|
|
4
|
+
export { roleResource, roleResourceRoute } from "./role.routes.js";
|
|
5
|
+
export { customRoleCreateSchema, customRoleUpdateSchema, roleUpdateSchema } from "./role.schema.js";
|
|
6
|
+
export { IdentityRoleController } from "./role.controller.js";
|