@astram/identity 0.1.1 → 0.2.0
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/dist/auth-facts-keys.d.ts +3 -0
- package/dist/auth-facts-keys.d.ts.map +1 -0
- package/dist/auth-facts-keys.js +24 -0
- package/dist/cross-tenant-grant.object.d.ts +28 -0
- package/dist/cross-tenant-grant.object.d.ts.map +1 -0
- package/dist/cross-tenant-grant.object.js +64 -0
- package/dist/features/access/access-admin.access.d.ts +3 -0
- package/dist/features/access/access-admin.access.d.ts.map +1 -0
- package/dist/features/access/access-admin.access.js +27 -0
- package/dist/features/access/company-admin.access.d.ts +3 -0
- package/dist/features/access/company-admin.access.d.ts.map +1 -0
- package/dist/features/access/company-admin.access.js +31 -0
- package/dist/features/access/index.d.ts +15 -0
- package/dist/features/access/index.d.ts.map +1 -0
- package/dist/features/access/index.js +26 -0
- package/dist/features/access/user-management.access.d.ts +3 -0
- package/dist/features/access/user-management.access.d.ts.map +1 -0
- package/dist/features/access/user-management.access.js +35 -0
- package/dist/features/audit/audit-read.service.d.ts +92 -0
- package/dist/features/audit/audit-read.service.d.ts.map +1 -0
- package/dist/features/audit/audit-read.service.js +97 -0
- package/dist/features/audit/audit.controller.d.ts +35 -0
- package/dist/features/audit/audit.controller.d.ts.map +1 -0
- package/dist/features/audit/audit.controller.js +73 -0
- package/dist/features/audit/directory-label-resolver.d.ts +14 -0
- package/dist/features/audit/directory-label-resolver.d.ts.map +1 -0
- package/dist/features/audit/directory-label-resolver.js +46 -0
- package/dist/features/audit/mariadb-audit-reader.d.ts +46 -0
- package/dist/features/audit/mariadb-audit-reader.d.ts.map +1 -0
- package/dist/features/audit/mariadb-audit-reader.js +116 -0
- package/dist/features/authz/access-bundle-reconcile.job.d.ts +35 -0
- package/dist/features/authz/access-bundle-reconcile.job.d.ts.map +1 -0
- package/dist/features/authz/access-bundle-reconcile.job.js +84 -0
- package/dist/features/authz/access-bundle-store.d.ts +65 -0
- package/dist/features/authz/access-bundle-store.d.ts.map +1 -0
- package/dist/features/authz/access-bundle-store.js +154 -0
- package/dist/features/authz/catalog-bootstrap.provider.d.ts +28 -0
- package/dist/features/authz/catalog-bootstrap.provider.d.ts.map +1 -0
- package/dist/features/authz/catalog-bootstrap.provider.js +85 -0
- package/dist/features/authz/catalog-reconcile.job.d.ts +23 -0
- package/dist/features/authz/catalog-reconcile.job.d.ts.map +1 -0
- package/dist/features/authz/catalog-reconcile.job.js +47 -0
- package/dist/features/authz/db-permission-facts.adapter.d.ts +60 -0
- package/dist/features/authz/db-permission-facts.adapter.d.ts.map +1 -0
- package/dist/features/authz/db-permission-facts.adapter.js +116 -0
- package/dist/features/authz/grant-admin.controller.d.ts +96 -0
- package/dist/features/authz/grant-admin.controller.d.ts.map +1 -0
- package/dist/features/authz/grant-admin.controller.js +209 -0
- package/dist/features/authz/grant-admin.service.d.ts +107 -0
- package/dist/features/authz/grant-admin.service.d.ts.map +1 -0
- package/dist/features/authz/grant-admin.service.js +297 -0
- package/dist/features/authz/mariadb-catalog-store.d.ts +16 -0
- package/dist/features/authz/mariadb-catalog-store.d.ts.map +1 -0
- package/dist/features/authz/mariadb-catalog-store.js +44 -0
- package/dist/features/authz/permission-version.bumper.d.ts +47 -0
- package/dist/features/authz/permission-version.bumper.d.ts.map +1 -0
- package/dist/features/authz/permission-version.bumper.js +68 -0
- package/dist/features/authz/record-authorization.d.ts +31 -0
- package/dist/features/authz/record-authorization.d.ts.map +1 -0
- package/dist/features/authz/record-authorization.js +59 -0
- package/dist/features/authz/session-facts.reader.d.ts +41 -0
- package/dist/features/authz/session-facts.reader.d.ts.map +1 -0
- package/dist/features/authz/session-facts.reader.js +27 -0
- package/dist/features/company/company.controller.d.ts +37 -0
- package/dist/features/company/company.controller.d.ts.map +1 -0
- package/dist/features/company/company.controller.js +100 -0
- package/dist/features/company/company.service.d.ts +25 -0
- package/dist/features/company/company.service.d.ts.map +1 -0
- package/dist/features/company/company.service.js +53 -0
- package/dist/features/cross-tenant/cross-tenant-grant-read.service.d.ts +126 -0
- package/dist/features/cross-tenant/cross-tenant-grant-read.service.d.ts.map +1 -0
- package/dist/features/cross-tenant/cross-tenant-grant-read.service.js +276 -0
- package/dist/features/cross-tenant/cross-tenant-grant.controller.d.ts +65 -0
- package/dist/features/cross-tenant/cross-tenant-grant.controller.d.ts.map +1 -0
- package/dist/features/cross-tenant/cross-tenant-grant.controller.js +250 -0
- package/dist/features/cross-tenant/grant-authorize.d.ts +42 -0
- package/dist/features/cross-tenant/grant-authorize.d.ts.map +1 -0
- package/dist/features/cross-tenant/grant-authorize.js +17 -0
- package/dist/features/identity-feature.module.d.ts +26 -0
- package/dist/features/identity-feature.module.d.ts.map +1 -0
- package/dist/features/identity-feature.module.js +247 -0
- package/dist/features/membership/membership.controller.d.ts +77 -0
- package/dist/features/membership/membership.controller.d.ts.map +1 -0
- package/dist/features/membership/membership.controller.js +174 -0
- package/dist/features/membership/membership.service.d.ts +73 -0
- package/dist/features/membership/membership.service.d.ts.map +1 -0
- package/dist/features/membership/membership.service.js +173 -0
- package/dist/features/membership/posting-version-bump.d.ts +10 -0
- package/dist/features/membership/posting-version-bump.d.ts.map +1 -0
- package/dist/features/membership/posting-version-bump.js +4 -0
- package/dist/features/membership/posting.service.d.ts +59 -0
- package/dist/features/membership/posting.service.d.ts.map +1 -0
- package/dist/features/membership/posting.service.js +181 -0
- package/dist/features/org-structure/org-catalog.controller.d.ts +14 -0
- package/dist/features/org-structure/org-catalog.controller.d.ts.map +1 -0
- package/dist/features/org-structure/org-catalog.controller.js +62 -0
- package/dist/features/org-structure/org-catalog.service.d.ts +19 -0
- package/dist/features/org-structure/org-catalog.service.d.ts.map +1 -0
- package/dist/features/org-structure/org-catalog.service.js +53 -0
- package/dist/features/role/role.controller.d.ts +37 -0
- package/dist/features/role/role.controller.d.ts.map +1 -0
- package/dist/features/role/role.controller.js +104 -0
- package/dist/features/role/role.service.d.ts +24 -0
- package/dist/features/role/role.service.d.ts.map +1 -0
- package/dist/features/role/role.service.js +53 -0
- package/dist/features/shared/http.d.ts +15 -0
- package/dist/features/shared/http.d.ts.map +1 -0
- package/dist/features/shared/http.js +25 -0
- package/dist/features/shared/list-query.d.ts +44 -0
- package/dist/features/shared/list-query.d.ts.map +1 -0
- package/dist/features/shared/list-query.js +53 -0
- package/dist/features/shared/named-option.d.ts +6 -0
- package/dist/features/shared/named-option.d.ts.map +1 -0
- package/dist/features/shared/named-option.js +2 -0
- package/dist/features/shared/record-resolver.d.ts +11 -0
- package/dist/features/shared/record-resolver.d.ts.map +1 -0
- package/dist/features/shared/record-resolver.js +32 -0
- package/dist/features/user/user.controller.d.ts +39 -0
- package/dist/features/user/user.controller.d.ts.map +1 -0
- package/dist/features/user/user.controller.js +104 -0
- package/dist/features/user/user.service.d.ts +26 -0
- package/dist/features/user/user.service.d.ts.map +1 -0
- package/dist/features/user/user.service.js +53 -0
- package/dist/index.d.ts +34 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -33
- package/dist/objects.d.ts +13 -0
- package/dist/objects.d.ts.map +1 -0
- package/dist/objects.js +20 -0
- package/dist/shared-resource.object.d.ts +28 -0
- package/dist/shared-resource.object.d.ts.map +1 -0
- package/dist/shared-resource.object.js +63 -0
- package/migrations/1710000000010-CreateAuditLog.cjs +42 -0
- package/migrations/1710000000011-CreateCrossTenantGrant.cjs +66 -0
- package/migrations/1710000000012-SeedCrossTenantGrantPerms.cjs +86 -0
- package/migrations/1710000000013-CreateSharedResource.cjs +30 -0
- package/migrations/1710000000099-SeedDevIdentity.cjs +130 -0
- package/migrations/1710000000100-SeedDevTenantBAndRoot.cjs +212 -0
- package/package.json +4 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RoleController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const guard_1 = require("@astram/guard");
|
|
18
|
+
const role_service_js_1 = require("./role.service.js");
|
|
19
|
+
const list_query_js_1 = require("../shared/list-query.js");
|
|
20
|
+
// Role management is gated on `identity:role:<action>` grants. `role` is CONTROL-plane
|
|
21
|
+
// for ALL actions — including read: the capped root is the identity administrator (the
|
|
22
|
+
// identity-administrator model), so it may list/read roles AND manage them.
|
|
23
|
+
let RoleController = class RoleController {
|
|
24
|
+
roles;
|
|
25
|
+
constructor(roles) {
|
|
26
|
+
this.roles = roles;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* List roles — gated on `identity:role:read` (see class doc). Server-side DataTable:
|
|
30
|
+
* `?page&limit&search&sortBy&sortOrder`. Returns `{ total, rows, page, limit }` —
|
|
31
|
+
* `total` reflects the FILTERED set so the client can page the true result count.
|
|
32
|
+
*/
|
|
33
|
+
async listRoles(query) {
|
|
34
|
+
const { page, limit, params } = (0, list_query_js_1.parseListQuery)(query);
|
|
35
|
+
const result = await this.roles.listRoles(params);
|
|
36
|
+
return { total: result.total, rows: result.rows, page, limit };
|
|
37
|
+
}
|
|
38
|
+
/** Create a role — gated on `identity:role:create`. */
|
|
39
|
+
async createRole(body) {
|
|
40
|
+
const id = await this.roles.createRole(body?.name ?? 'Untitled');
|
|
41
|
+
return { id };
|
|
42
|
+
}
|
|
43
|
+
/** Read one role — gated on `identity:role:read` (CONTROL-plane; root, the identity
|
|
44
|
+
* administrator, may read roles). */
|
|
45
|
+
getRole(uuid) {
|
|
46
|
+
return this.roles.getRole(uuid);
|
|
47
|
+
}
|
|
48
|
+
/** Update a role — gated on `identity:role:update`. */
|
|
49
|
+
async updateRole(uuid, body) {
|
|
50
|
+
await this.roles.updateRole(uuid, body ?? {});
|
|
51
|
+
return { success: true };
|
|
52
|
+
}
|
|
53
|
+
/** Delete a role — gated on `identity:role:delete`. */
|
|
54
|
+
async deleteRole(uuid) {
|
|
55
|
+
await this.roles.deleteRole(uuid);
|
|
56
|
+
return { success: true };
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
exports.RoleController = RoleController;
|
|
60
|
+
__decorate([
|
|
61
|
+
(0, common_1.Get)('roles'),
|
|
62
|
+
(0, guard_1.Classified)({ typeKey: 'role', action: 'read' }),
|
|
63
|
+
__param(0, (0, common_1.Query)()),
|
|
64
|
+
__metadata("design:type", Function),
|
|
65
|
+
__metadata("design:paramtypes", [Object]),
|
|
66
|
+
__metadata("design:returntype", Promise)
|
|
67
|
+
], RoleController.prototype, "listRoles", null);
|
|
68
|
+
__decorate([
|
|
69
|
+
(0, common_1.Post)('roles'),
|
|
70
|
+
(0, guard_1.Classified)({ typeKey: 'role', action: 'create' }),
|
|
71
|
+
__param(0, (0, common_1.Body)()),
|
|
72
|
+
__metadata("design:type", Function),
|
|
73
|
+
__metadata("design:paramtypes", [Object]),
|
|
74
|
+
__metadata("design:returntype", Promise)
|
|
75
|
+
], RoleController.prototype, "createRole", null);
|
|
76
|
+
__decorate([
|
|
77
|
+
(0, common_1.Get)('roles/:uuid'),
|
|
78
|
+
(0, guard_1.Classified)({ typeKey: 'role', action: 'read' }),
|
|
79
|
+
__param(0, (0, common_1.Param)('uuid')),
|
|
80
|
+
__metadata("design:type", Function),
|
|
81
|
+
__metadata("design:paramtypes", [String]),
|
|
82
|
+
__metadata("design:returntype", void 0)
|
|
83
|
+
], RoleController.prototype, "getRole", null);
|
|
84
|
+
__decorate([
|
|
85
|
+
(0, common_1.Put)('roles/:uuid'),
|
|
86
|
+
(0, guard_1.Classified)({ typeKey: 'role', action: 'update' }),
|
|
87
|
+
__param(0, (0, common_1.Param)('uuid')),
|
|
88
|
+
__param(1, (0, common_1.Body)()),
|
|
89
|
+
__metadata("design:type", Function),
|
|
90
|
+
__metadata("design:paramtypes", [String, Object]),
|
|
91
|
+
__metadata("design:returntype", Promise)
|
|
92
|
+
], RoleController.prototype, "updateRole", null);
|
|
93
|
+
__decorate([
|
|
94
|
+
(0, common_1.Delete)('roles/:uuid'),
|
|
95
|
+
(0, guard_1.Classified)({ typeKey: 'role', action: 'delete' }),
|
|
96
|
+
__param(0, (0, common_1.Param)('uuid')),
|
|
97
|
+
__metadata("design:type", Function),
|
|
98
|
+
__metadata("design:paramtypes", [String]),
|
|
99
|
+
__metadata("design:returntype", Promise)
|
|
100
|
+
], RoleController.prototype, "deleteRole", null);
|
|
101
|
+
exports.RoleController = RoleController = __decorate([
|
|
102
|
+
(0, common_1.Controller)('identity'),
|
|
103
|
+
__metadata("design:paramtypes", [role_service_js_1.RoleService])
|
|
104
|
+
], RoleController);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RecordsService, type RecordId } from '@astram/engine';
|
|
2
|
+
import { type ListParams } from '../shared/list-query.js';
|
|
3
|
+
/**
|
|
4
|
+
* RoleService — role CRUD on the paved road, via the framework's RecordsService
|
|
5
|
+
* facade. The facade supplies the acting identity (the request principal) —
|
|
6
|
+
* this service never threads a Principal. No raw SQL, no RECORD_ENGINE.
|
|
7
|
+
*/
|
|
8
|
+
export declare class RoleService {
|
|
9
|
+
private readonly records;
|
|
10
|
+
constructor(records: RecordsService);
|
|
11
|
+
/** Create a role. */
|
|
12
|
+
createRole(name: string): Promise<RecordId>;
|
|
13
|
+
/** List roles (tenant-scoped by the pipe), with paging/search/sort. */
|
|
14
|
+
listRoles(params?: ListParams): Promise<import("@astram/engine").RecordPage>;
|
|
15
|
+
/** Read a single role. */
|
|
16
|
+
getRole(uuid: string): Promise<import("@astram/engine").RecordView | null>;
|
|
17
|
+
/** Update a role. */
|
|
18
|
+
updateRole(uuid: string, patch: {
|
|
19
|
+
name?: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
/** Delete a role. */
|
|
22
|
+
deleteRole(uuid: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=role.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role.service.d.ts","sourceRoot":"","sources":["../../../src/features/role/role.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1E;;;;GAIG;AACH,qBACa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD,qBAAqB;IACrB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI3C,uEAAuE;IACvE,SAAS,CAAC,MAAM,CAAC,EAAE,UAAU;IAI7B,0BAA0B;IAC1B,OAAO,CAAC,IAAI,EAAE,MAAM;IAIpB,qBAAqB;IACrB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,qBAAqB;IACrB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGxC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RoleService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const engine_1 = require("@astram/engine");
|
|
15
|
+
const list_query_js_1 = require("../shared/list-query.js");
|
|
16
|
+
const ROLE_SEARCH_FIELDS = ['name'];
|
|
17
|
+
const ROLE_SORT_FIELDS = ['name', 'createdAt'];
|
|
18
|
+
/**
|
|
19
|
+
* RoleService — role CRUD on the paved road, via the framework's RecordsService
|
|
20
|
+
* facade. The facade supplies the acting identity (the request principal) —
|
|
21
|
+
* this service never threads a Principal. No raw SQL, no RECORD_ENGINE.
|
|
22
|
+
*/
|
|
23
|
+
let RoleService = class RoleService {
|
|
24
|
+
records;
|
|
25
|
+
constructor(records) {
|
|
26
|
+
this.records = records;
|
|
27
|
+
}
|
|
28
|
+
/** Create a role. */
|
|
29
|
+
createRole(name) {
|
|
30
|
+
return this.records.create('role', { fields: { name } });
|
|
31
|
+
}
|
|
32
|
+
/** List roles (tenant-scoped by the pipe), with paging/search/sort. */
|
|
33
|
+
listRoles(params) {
|
|
34
|
+
return this.records.list('role', (0, list_query_js_1.buildListQuery)(params, ROLE_SEARCH_FIELDS, ROLE_SORT_FIELDS));
|
|
35
|
+
}
|
|
36
|
+
/** Read a single role. */
|
|
37
|
+
getRole(uuid) {
|
|
38
|
+
return this.records.get('role', uuid);
|
|
39
|
+
}
|
|
40
|
+
/** Update a role. */
|
|
41
|
+
updateRole(uuid, patch) {
|
|
42
|
+
return this.records.update('role', uuid, { fields: patch });
|
|
43
|
+
}
|
|
44
|
+
/** Delete a role. */
|
|
45
|
+
deleteRole(uuid) {
|
|
46
|
+
return this.records.delete('role', uuid);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.RoleService = RoleService;
|
|
50
|
+
exports.RoleService = RoleService = __decorate([
|
|
51
|
+
(0, common_1.Injectable)(),
|
|
52
|
+
__metadata("design:paramtypes", [engine_1.RecordsService])
|
|
53
|
+
], RoleService);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Principal } from '@astram/engine';
|
|
2
|
+
/** The authenticated request shape: the framework guard attaches `principal`. */
|
|
3
|
+
export interface AuthedRequest {
|
|
4
|
+
principal: Principal;
|
|
5
|
+
}
|
|
6
|
+
/** Coerce an unknown field value to a string uuid or null. */
|
|
7
|
+
export declare function asUuid(v: unknown): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Coerce a stored effective-window bound to an epoch-ms number, or null. The
|
|
10
|
+
* `membership_posting` object stores these as `number` (BIGINT epoch-ms); the mariadb
|
|
11
|
+
* driver may hand a BIGINT back as a JS `number`, a `bigint`, or a numeric string, so
|
|
12
|
+
* normalize all three.
|
|
13
|
+
*/
|
|
14
|
+
export declare function asEpochMs(v: unknown): number | null;
|
|
15
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/features/shared/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,8DAA8D;AAC9D,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQnD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asUuid = asUuid;
|
|
4
|
+
exports.asEpochMs = asEpochMs;
|
|
5
|
+
/** Coerce an unknown field value to a string uuid or null. */
|
|
6
|
+
function asUuid(v) {
|
|
7
|
+
return typeof v === 'string' && v.length > 0 ? v : null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Coerce a stored effective-window bound to an epoch-ms number, or null. The
|
|
11
|
+
* `membership_posting` object stores these as `number` (BIGINT epoch-ms); the mariadb
|
|
12
|
+
* driver may hand a BIGINT back as a JS `number`, a `bigint`, or a numeric string, so
|
|
13
|
+
* normalize all three.
|
|
14
|
+
*/
|
|
15
|
+
function asEpochMs(v) {
|
|
16
|
+
if (typeof v === 'number')
|
|
17
|
+
return Number.isFinite(v) ? v : null;
|
|
18
|
+
if (typeof v === 'bigint')
|
|
19
|
+
return Number(v);
|
|
20
|
+
if (typeof v === 'string' && v.length > 0) {
|
|
21
|
+
const n = Number(v);
|
|
22
|
+
return Number.isFinite(n) ? n : null;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ListQuery } from '@astram/engine';
|
|
2
|
+
/**
|
|
3
|
+
* A server-side DataTable query for a list method: paging window + optional
|
|
4
|
+
* free-text search term + optional sort. Every field is optional — an empty
|
|
5
|
+
* `{}` reproduces the pre-DataTable behavior (engine defaults).
|
|
6
|
+
*/
|
|
7
|
+
export interface ListParams {
|
|
8
|
+
limit?: number;
|
|
9
|
+
offset?: number;
|
|
10
|
+
search?: string;
|
|
11
|
+
sortBy?: string;
|
|
12
|
+
sortOrder?: 'asc' | 'desc';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build the engine `ListQuery` from a feature `ListParams` + the type's field
|
|
16
|
+
* allowlists. Search maps to `{ fields, term }` only when the term is non-empty;
|
|
17
|
+
* `sortBy` is included ONLY when it is one of `sortFields` (a bad key is dropped
|
|
18
|
+
* so the engine never sees an unknown key → no 500). `limit`/`offset` pass through.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildListQuery(params: ListParams | undefined, searchFields: readonly string[], sortFields: readonly string[]): ListQuery;
|
|
21
|
+
/** The raw `?page=&limit=&search=&sortBy=&sortOrder=` query bag for a list route. */
|
|
22
|
+
export interface ListQueryDto {
|
|
23
|
+
page?: string;
|
|
24
|
+
limit?: string;
|
|
25
|
+
search?: string;
|
|
26
|
+
sortBy?: string;
|
|
27
|
+
sortOrder?: string;
|
|
28
|
+
}
|
|
29
|
+
/** The default + max page size for any DataTable list route. */
|
|
30
|
+
export declare const DEFAULT_LIMIT = 25;
|
|
31
|
+
export declare const MAX_LIMIT = 100;
|
|
32
|
+
/**
|
|
33
|
+
* Parse the DataTable `?page&limit&search&sortBy&sortOrder` query into a normalized
|
|
34
|
+
* `{ page, limit, params }`. `page` ≥ 1 (default 1); `limit` clamped [1, MAX_LIMIT]
|
|
35
|
+
* (default 25); `offset = (page-1)*limit`; `search` trimmed, empty → omitted; `sortBy`
|
|
36
|
+
* passed through as a string (the SERVICE validates it against the type's sortable
|
|
37
|
+
* allowlist and ignores an unknown key). `sortOrder` defaults to 'asc'.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseListQuery(q: ListQueryDto | undefined): {
|
|
40
|
+
page: number;
|
|
41
|
+
limit: number;
|
|
42
|
+
params: ListParams;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=list-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-query.d.ts","sourceRoot":"","sources":["../../../src/features/shared/list-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,GAAG,SAAS,EAC9B,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,SAAS,CAkBX;AAED,qFAAqF;AACrF,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,gEAAgE;AAChE,eAAO,MAAM,aAAa,KAAK,CAAC;AAChC,eAAO,MAAM,SAAS,MAAM,CAAC;AAE7B;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACpB,CAmBA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_LIMIT = exports.DEFAULT_LIMIT = void 0;
|
|
4
|
+
exports.buildListQuery = buildListQuery;
|
|
5
|
+
exports.parseListQuery = parseListQuery;
|
|
6
|
+
/**
|
|
7
|
+
* Build the engine `ListQuery` from a feature `ListParams` + the type's field
|
|
8
|
+
* allowlists. Search maps to `{ fields, term }` only when the term is non-empty;
|
|
9
|
+
* `sortBy` is included ONLY when it is one of `sortFields` (a bad key is dropped
|
|
10
|
+
* so the engine never sees an unknown key → no 500). `limit`/`offset` pass through.
|
|
11
|
+
*/
|
|
12
|
+
function buildListQuery(params, searchFields, sortFields) {
|
|
13
|
+
const p = params ?? {};
|
|
14
|
+
const query = {};
|
|
15
|
+
if (typeof p.limit === 'number')
|
|
16
|
+
query.limit = p.limit;
|
|
17
|
+
if (typeof p.offset === 'number')
|
|
18
|
+
query.offset = p.offset;
|
|
19
|
+
const term = typeof p.search === 'string' ? p.search.trim() : '';
|
|
20
|
+
if (term.length > 0)
|
|
21
|
+
query.search = { fields: [...searchFields], term };
|
|
22
|
+
if (typeof p.sortBy === 'string' && sortFields.includes(p.sortBy)) {
|
|
23
|
+
query.sortBy = p.sortBy;
|
|
24
|
+
query.sortOrder = p.sortOrder === 'desc' ? 'desc' : 'asc';
|
|
25
|
+
}
|
|
26
|
+
return query;
|
|
27
|
+
}
|
|
28
|
+
/** The default + max page size for any DataTable list route. */
|
|
29
|
+
exports.DEFAULT_LIMIT = 25;
|
|
30
|
+
exports.MAX_LIMIT = 100;
|
|
31
|
+
/**
|
|
32
|
+
* Parse the DataTable `?page&limit&search&sortBy&sortOrder` query into a normalized
|
|
33
|
+
* `{ page, limit, params }`. `page` ≥ 1 (default 1); `limit` clamped [1, MAX_LIMIT]
|
|
34
|
+
* (default 25); `offset = (page-1)*limit`; `search` trimmed, empty → omitted; `sortBy`
|
|
35
|
+
* passed through as a string (the SERVICE validates it against the type's sortable
|
|
36
|
+
* allowlist and ignores an unknown key). `sortOrder` defaults to 'asc'.
|
|
37
|
+
*/
|
|
38
|
+
function parseListQuery(q) {
|
|
39
|
+
const rawPage = Number.parseInt(q?.page ?? '', 10);
|
|
40
|
+
const page = Number.isFinite(rawPage) && rawPage >= 1 ? rawPage : 1;
|
|
41
|
+
const rawLimit = Number.parseInt(q?.limit ?? '', 10);
|
|
42
|
+
const limit = Number.isFinite(rawLimit) && rawLimit >= 1 ? Math.min(rawLimit, exports.MAX_LIMIT) : exports.DEFAULT_LIMIT;
|
|
43
|
+
const offset = (page - 1) * limit;
|
|
44
|
+
const search = typeof q?.search === 'string' ? q.search.trim() : '';
|
|
45
|
+
const sortBy = typeof q?.sortBy === 'string' && q.sortBy.length > 0 ? q.sortBy : undefined;
|
|
46
|
+
const sortOrder = q?.sortOrder === 'desc' ? 'desc' : 'asc';
|
|
47
|
+
const params = { limit, offset, sortOrder };
|
|
48
|
+
if (search.length > 0)
|
|
49
|
+
params.search = search;
|
|
50
|
+
if (sortBy)
|
|
51
|
+
params.sortBy = sortBy;
|
|
52
|
+
return { page, limit, params };
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-option.d.ts","sourceRoot":"","sources":["../../../src/features/shared/named-option.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RecordsService } from '@astram/engine';
|
|
2
|
+
/**
|
|
3
|
+
* RecordResolverService — resolve a foreign uuid to its display record (name), via the
|
|
4
|
+
* RecordsService facade (no actor threading). Used to render uuids as names in list DTOs.
|
|
5
|
+
*/
|
|
6
|
+
export declare class RecordResolverService {
|
|
7
|
+
private readonly records;
|
|
8
|
+
constructor(records: RecordsService);
|
|
9
|
+
getRecord(typeKey: string, uuid: string): Promise<import("@astram/engine").RecordView | null>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=record-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-resolver.d.ts","sourceRoot":"","sources":["../../../src/features/shared/record-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;GAGG;AACH,qBACa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAGxC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RecordResolverService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const engine_1 = require("@astram/engine");
|
|
15
|
+
/**
|
|
16
|
+
* RecordResolverService — resolve a foreign uuid to its display record (name), via the
|
|
17
|
+
* RecordsService facade (no actor threading). Used to render uuids as names in list DTOs.
|
|
18
|
+
*/
|
|
19
|
+
let RecordResolverService = class RecordResolverService {
|
|
20
|
+
records;
|
|
21
|
+
constructor(records) {
|
|
22
|
+
this.records = records;
|
|
23
|
+
}
|
|
24
|
+
getRecord(typeKey, uuid) {
|
|
25
|
+
return this.records.get(typeKey, uuid);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
exports.RecordResolverService = RecordResolverService;
|
|
29
|
+
exports.RecordResolverService = RecordResolverService = __decorate([
|
|
30
|
+
(0, common_1.Injectable)(),
|
|
31
|
+
__metadata("design:paramtypes", [engine_1.RecordsService])
|
|
32
|
+
], RecordResolverService);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { UserService } from './user.service.js';
|
|
2
|
+
import { type ListQueryDto } from '../shared/list-query.js';
|
|
3
|
+
export declare class UserController {
|
|
4
|
+
private readonly users;
|
|
5
|
+
constructor(users: UserService);
|
|
6
|
+
/**
|
|
7
|
+
* List users — gated on `identity:user:read` (see class doc). Server-side DataTable:
|
|
8
|
+
* `?page&limit&search&sortBy&sortOrder`. Returns `{ total, rows, page, limit }` —
|
|
9
|
+
* `total` reflects the FILTERED set so the client can page the true result count.
|
|
10
|
+
*/
|
|
11
|
+
listUsers(query: ListQueryDto): Promise<{
|
|
12
|
+
total: number;
|
|
13
|
+
rows: readonly import("packages/engine/dist/types.js").RecordView[];
|
|
14
|
+
page: number;
|
|
15
|
+
limit: number;
|
|
16
|
+
}>;
|
|
17
|
+
/** Create a user — gated on `identity:user:create`. */
|
|
18
|
+
createUser(body: {
|
|
19
|
+
username?: string;
|
|
20
|
+
}): Promise<{
|
|
21
|
+
id: import("packages/engine/dist/types.js").RecordId;
|
|
22
|
+
}>;
|
|
23
|
+
/** Read one user — gated on `identity:user:read` (CONTROL-plane; root, the identity
|
|
24
|
+
* administrator, may read users). */
|
|
25
|
+
getUser(uuid: string): Promise<import("packages/engine/dist/types.js").RecordView | null>;
|
|
26
|
+
/** Update a user — gated on `identity:user:update`. */
|
|
27
|
+
updateUser(uuid: string, body: {
|
|
28
|
+
username?: string;
|
|
29
|
+
email?: string;
|
|
30
|
+
status?: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
success: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
/** Delete a user — gated on `identity:user:delete`. */
|
|
35
|
+
deleteUser(uuid: string): Promise<{
|
|
36
|
+
success: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=user.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.controller.d.ts","sourceRoot":"","sources":["../../../src/features/user/user.controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAK5E,qBACa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,WAAW;IAE/C;;;;OAIG;IAGG,SAAS,CAAU,KAAK,EAAE,YAAY;;;;;;IAM5C,uDAAuD;IAGjD,UAAU,CAAS,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;;;IAKpD;0CACsC;IAGtC,OAAO,CAAgB,IAAI,EAAE,MAAM;IAInC,uDAAuD;IAGjD,UAAU,CACC,IAAI,EAAE,MAAM,EACnB,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;;IAMtE,uDAAuD;IAGjD,UAAU,CAAgB,IAAI,EAAE,MAAM;;;CAI7C"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.UserController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const guard_1 = require("@astram/guard");
|
|
18
|
+
const user_service_js_1 = require("./user.service.js");
|
|
19
|
+
const list_query_js_1 = require("../shared/list-query.js");
|
|
20
|
+
// User management is gated on `identity:user:<action>` grants. `user` is CONTROL-plane
|
|
21
|
+
// for ALL actions — including read: the capped root is the identity administrator (the
|
|
22
|
+
// identity-administrator model), so it may list/read users AND manage them.
|
|
23
|
+
let UserController = class UserController {
|
|
24
|
+
users;
|
|
25
|
+
constructor(users) {
|
|
26
|
+
this.users = users;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* List users — gated on `identity:user:read` (see class doc). Server-side DataTable:
|
|
30
|
+
* `?page&limit&search&sortBy&sortOrder`. Returns `{ total, rows, page, limit }` —
|
|
31
|
+
* `total` reflects the FILTERED set so the client can page the true result count.
|
|
32
|
+
*/
|
|
33
|
+
async listUsers(query) {
|
|
34
|
+
const { page, limit, params } = (0, list_query_js_1.parseListQuery)(query);
|
|
35
|
+
const result = await this.users.listUsers(params);
|
|
36
|
+
return { total: result.total, rows: result.rows, page, limit };
|
|
37
|
+
}
|
|
38
|
+
/** Create a user — gated on `identity:user:create`. */
|
|
39
|
+
async createUser(body) {
|
|
40
|
+
const id = await this.users.createUser(body?.username ?? 'Untitled');
|
|
41
|
+
return { id };
|
|
42
|
+
}
|
|
43
|
+
/** Read one user — gated on `identity:user:read` (CONTROL-plane; root, the identity
|
|
44
|
+
* administrator, may read users). */
|
|
45
|
+
getUser(uuid) {
|
|
46
|
+
return this.users.getUser(uuid);
|
|
47
|
+
}
|
|
48
|
+
/** Update a user — gated on `identity:user:update`. */
|
|
49
|
+
async updateUser(uuid, body) {
|
|
50
|
+
await this.users.updateUser(uuid, body ?? {});
|
|
51
|
+
return { success: true };
|
|
52
|
+
}
|
|
53
|
+
/** Delete a user — gated on `identity:user:delete`. */
|
|
54
|
+
async deleteUser(uuid) {
|
|
55
|
+
await this.users.deleteUser(uuid);
|
|
56
|
+
return { success: true };
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
exports.UserController = UserController;
|
|
60
|
+
__decorate([
|
|
61
|
+
(0, common_1.Get)('users'),
|
|
62
|
+
(0, guard_1.Classified)({ typeKey: 'user', action: 'read' }),
|
|
63
|
+
__param(0, (0, common_1.Query)()),
|
|
64
|
+
__metadata("design:type", Function),
|
|
65
|
+
__metadata("design:paramtypes", [Object]),
|
|
66
|
+
__metadata("design:returntype", Promise)
|
|
67
|
+
], UserController.prototype, "listUsers", null);
|
|
68
|
+
__decorate([
|
|
69
|
+
(0, common_1.Post)('users'),
|
|
70
|
+
(0, guard_1.Classified)({ typeKey: 'user', action: 'create' }),
|
|
71
|
+
__param(0, (0, common_1.Body)()),
|
|
72
|
+
__metadata("design:type", Function),
|
|
73
|
+
__metadata("design:paramtypes", [Object]),
|
|
74
|
+
__metadata("design:returntype", Promise)
|
|
75
|
+
], UserController.prototype, "createUser", null);
|
|
76
|
+
__decorate([
|
|
77
|
+
(0, common_1.Get)('users/:uuid'),
|
|
78
|
+
(0, guard_1.Classified)({ typeKey: 'user', action: 'read' }),
|
|
79
|
+
__param(0, (0, common_1.Param)('uuid')),
|
|
80
|
+
__metadata("design:type", Function),
|
|
81
|
+
__metadata("design:paramtypes", [String]),
|
|
82
|
+
__metadata("design:returntype", void 0)
|
|
83
|
+
], UserController.prototype, "getUser", null);
|
|
84
|
+
__decorate([
|
|
85
|
+
(0, common_1.Put)('users/:uuid'),
|
|
86
|
+
(0, guard_1.Classified)({ typeKey: 'user', action: 'update' }),
|
|
87
|
+
__param(0, (0, common_1.Param)('uuid')),
|
|
88
|
+
__param(1, (0, common_1.Body)()),
|
|
89
|
+
__metadata("design:type", Function),
|
|
90
|
+
__metadata("design:paramtypes", [String, Object]),
|
|
91
|
+
__metadata("design:returntype", Promise)
|
|
92
|
+
], UserController.prototype, "updateUser", null);
|
|
93
|
+
__decorate([
|
|
94
|
+
(0, common_1.Delete)('users/:uuid'),
|
|
95
|
+
(0, guard_1.Classified)({ typeKey: 'user', action: 'delete' }),
|
|
96
|
+
__param(0, (0, common_1.Param)('uuid')),
|
|
97
|
+
__metadata("design:type", Function),
|
|
98
|
+
__metadata("design:paramtypes", [String]),
|
|
99
|
+
__metadata("design:returntype", Promise)
|
|
100
|
+
], UserController.prototype, "deleteUser", null);
|
|
101
|
+
exports.UserController = UserController = __decorate([
|
|
102
|
+
(0, common_1.Controller)('identity'),
|
|
103
|
+
__metadata("design:paramtypes", [user_service_js_1.UserService])
|
|
104
|
+
], UserController);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RecordsService, type RecordId } from '@astram/engine';
|
|
2
|
+
import { type ListParams } from '../shared/list-query.js';
|
|
3
|
+
/**
|
|
4
|
+
* UserService — user (principal) CRUD on the paved road, via the framework's
|
|
5
|
+
* RecordsService facade. The facade supplies the acting identity (the request
|
|
6
|
+
* principal) — this service never threads a Principal. No raw SQL, no RECORD_ENGINE.
|
|
7
|
+
*/
|
|
8
|
+
export declare class UserService {
|
|
9
|
+
private readonly records;
|
|
10
|
+
constructor(records: RecordsService);
|
|
11
|
+
/** Create a user. */
|
|
12
|
+
createUser(username: string): Promise<RecordId>;
|
|
13
|
+
/** List users (tenant-scoped by the pipe), with paging/search/sort. */
|
|
14
|
+
listUsers(params?: ListParams): Promise<import("@astram/engine").RecordPage>;
|
|
15
|
+
/** Read a single user. */
|
|
16
|
+
getUser(uuid: string): Promise<import("@astram/engine").RecordView | null>;
|
|
17
|
+
/** Update a user. */
|
|
18
|
+
updateUser(uuid: string, patch: {
|
|
19
|
+
username?: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
status?: string;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
/** Delete a user. */
|
|
24
|
+
deleteUser(uuid: string): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=user.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../../src/features/user/user.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1E;;;;GAIG;AACH,qBACa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD,qBAAqB;IACrB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI/C,uEAAuE;IACvE,SAAS,CAAC,MAAM,CAAC,EAAE,UAAU;IAI7B,0BAA0B;IAC1B,OAAO,CAAC,IAAI,EAAE,MAAM;IAIpB,qBAAqB;IACrB,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5D,OAAO,CAAC,IAAI,CAAC;IAIhB,qBAAqB;IACrB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGxC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.UserService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const engine_1 = require("@astram/engine");
|
|
15
|
+
const list_query_js_1 = require("../shared/list-query.js");
|
|
16
|
+
const USER_SEARCH_FIELDS = ['username', 'email'];
|
|
17
|
+
const USER_SORT_FIELDS = ['username', 'email', 'status', 'createdAt'];
|
|
18
|
+
/**
|
|
19
|
+
* UserService — user (principal) CRUD on the paved road, via the framework's
|
|
20
|
+
* RecordsService facade. The facade supplies the acting identity (the request
|
|
21
|
+
* principal) — this service never threads a Principal. No raw SQL, no RECORD_ENGINE.
|
|
22
|
+
*/
|
|
23
|
+
let UserService = class UserService {
|
|
24
|
+
records;
|
|
25
|
+
constructor(records) {
|
|
26
|
+
this.records = records;
|
|
27
|
+
}
|
|
28
|
+
/** Create a user. */
|
|
29
|
+
createUser(username) {
|
|
30
|
+
return this.records.create('user', { fields: { username } });
|
|
31
|
+
}
|
|
32
|
+
/** List users (tenant-scoped by the pipe), with paging/search/sort. */
|
|
33
|
+
listUsers(params) {
|
|
34
|
+
return this.records.list('user', (0, list_query_js_1.buildListQuery)(params, USER_SEARCH_FIELDS, USER_SORT_FIELDS));
|
|
35
|
+
}
|
|
36
|
+
/** Read a single user. */
|
|
37
|
+
getUser(uuid) {
|
|
38
|
+
return this.records.get('user', uuid);
|
|
39
|
+
}
|
|
40
|
+
/** Update a user. */
|
|
41
|
+
updateUser(uuid, patch) {
|
|
42
|
+
return this.records.update('user', uuid, { fields: patch });
|
|
43
|
+
}
|
|
44
|
+
/** Delete a user. */
|
|
45
|
+
deleteUser(uuid) {
|
|
46
|
+
return this.records.delete('user', uuid);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.UserService = UserService;
|
|
50
|
+
exports.UserService = UserService = __decorate([
|
|
51
|
+
(0, common_1.Injectable)(),
|
|
52
|
+
__metadata("design:paramtypes", [engine_1.RecordsService])
|
|
53
|
+
], UserService);
|