@astram/identity 0.16.0 → 0.17.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/branch.object.d.ts +9 -1
- package/dist/branch.object.d.ts.map +1 -1
- package/dist/branch.object.js +14 -1
- package/dist/company-branch.object.d.ts +5 -4
- package/dist/company-branch.object.d.ts.map +1 -1
- package/dist/company-branch.object.js +6 -4
- package/dist/company-department.object.d.ts +6 -6
- package/dist/company-department.object.d.ts.map +1 -1
- package/dist/company-department.object.js +7 -6
- package/dist/department.object.d.ts +9 -1
- package/dist/department.object.d.ts.map +1 -1
- package/dist/department.object.js +14 -1
- package/dist/features/access/access-admin.access.d.ts.map +1 -1
- package/dist/features/access/access-admin.access.js +8 -1
- package/dist/features/access/index.d.ts +1 -0
- package/dist/features/access/index.d.ts.map +1 -1
- package/dist/features/access/index.js +10 -2
- package/dist/features/access/org-structure.access.d.ts +3 -0
- package/dist/features/access/org-structure.access.d.ts.map +1 -0
- package/dist/features/access/org-structure.access.js +41 -0
- package/dist/features/access/user-management.access.d.ts.map +1 -1
- package/dist/features/access/user-management.access.js +5 -0
- package/dist/features/audit/audit-read.service.d.ts +32 -1
- package/dist/features/audit/audit-read.service.d.ts.map +1 -1
- package/dist/features/audit/audit-read.service.js +67 -14
- package/dist/features/audit/auth-audit-sink.d.ts +19 -0
- package/dist/features/audit/auth-audit-sink.d.ts.map +1 -0
- package/dist/features/audit/auth-audit-sink.js +24 -0
- package/dist/features/audit/directory-label-resolver.d.ts +10 -1
- package/dist/features/audit/directory-label-resolver.d.ts.map +1 -1
- package/dist/features/audit/directory-label-resolver.js +28 -1
- package/dist/features/authz/grant-admin.controller.d.ts +4 -4
- package/dist/features/authz/grant-admin.controller.js +4 -4
- package/dist/features/authz/grant-admin.service.d.ts +9 -8
- package/dist/features/authz/grant-admin.service.d.ts.map +1 -1
- package/dist/features/authz/grant-admin.service.js +20 -24
- package/dist/features/authz/grant-ceiling.d.ts +35 -16
- package/dist/features/authz/grant-ceiling.d.ts.map +1 -1
- package/dist/features/authz/grant-ceiling.js +44 -29
- package/dist/features/authz/role-binding.d.ts +25 -24
- package/dist/features/authz/role-binding.d.ts.map +1 -1
- package/dist/features/authz/role-binding.js +31 -44
- package/dist/features/identity-feature.module.d.ts +0 -11
- package/dist/features/identity-feature.module.d.ts.map +1 -1
- package/dist/features/identity-feature.module.js +90 -1
- package/dist/features/membership/membership.controller.d.ts.map +1 -1
- package/dist/features/membership/membership.controller.js +20 -6
- package/dist/features/membership/membership.service.d.ts +16 -10
- package/dist/features/membership/membership.service.d.ts.map +1 -1
- package/dist/features/membership/membership.service.js +61 -21
- package/dist/features/membership/posting.service.d.ts +25 -6
- package/dist/features/membership/posting.service.d.ts.map +1 -1
- package/dist/features/membership/posting.service.js +63 -16
- package/dist/features/org-bootstrap/org-bootstrap-file.d.ts +6 -2
- package/dist/features/org-bootstrap/org-bootstrap-file.d.ts.map +1 -1
- package/dist/features/org-bootstrap/org-bootstrap-file.js +54 -11
- package/dist/features/org-bootstrap/org-bootstrap-plan.d.ts +30 -11
- package/dist/features/org-bootstrap/org-bootstrap-plan.d.ts.map +1 -1
- package/dist/features/org-bootstrap/org-bootstrap-plan.js +172 -68
- package/dist/features/org-bootstrap/org-state.reader.d.ts.map +1 -1
- package/dist/features/org-bootstrap/org-state.reader.js +56 -49
- package/dist/features/org-bootstrap/run-org-bootstrap.d.ts +6 -1
- package/dist/features/org-bootstrap/run-org-bootstrap.d.ts.map +1 -1
- package/dist/features/org-bootstrap/run-org-bootstrap.js +81 -92
- package/dist/features/org-structure/org-catalog.controller.d.ts +29 -6
- package/dist/features/org-structure/org-catalog.controller.d.ts.map +1 -1
- package/dist/features/org-structure/org-catalog.controller.js +105 -17
- package/dist/features/org-structure/org-catalog.service.d.ts +99 -18
- package/dist/features/org-structure/org-catalog.service.d.ts.map +1 -1
- package/dist/features/org-structure/org-catalog.service.js +327 -51
- package/dist/features/org-structure/org-unit-name.d.ts +31 -0
- package/dist/features/org-structure/org-unit-name.d.ts.map +1 -0
- package/dist/features/org-structure/org-unit-name.js +50 -0
- package/dist/features/role/role.controller.d.ts +28 -13
- package/dist/features/role/role.controller.d.ts.map +1 -1
- package/dist/features/role/role.controller.js +54 -14
- package/dist/features/role/role.service.d.ts +76 -21
- package/dist/features/role/role.service.d.ts.map +1 -1
- package/dist/features/role/role.service.js +204 -27
- package/dist/features/security-policy/security-policy-version-bump.d.ts +41 -0
- package/dist/features/security-policy/security-policy-version-bump.d.ts.map +1 -0
- package/dist/features/security-policy/security-policy-version-bump.js +65 -0
- package/dist/features/security-policy/security-policy.controller.d.ts +51 -0
- package/dist/features/security-policy/security-policy.controller.d.ts.map +1 -0
- package/dist/features/security-policy/security-policy.controller.js +121 -0
- package/dist/features/security-policy/security-policy.service.d.ts +94 -0
- package/dist/features/security-policy/security-policy.service.d.ts.map +1 -0
- package/dist/features/security-policy/security-policy.service.js +429 -0
- package/dist/features/service-account/service-account.service.d.ts +13 -3
- package/dist/features/service-account/service-account.service.d.ts.map +1 -1
- package/dist/features/service-account/service-account.service.js +48 -10
- package/dist/features/service-account/service-account.store.d.ts +11 -1
- package/dist/features/service-account/service-account.store.d.ts.map +1 -1
- package/dist/features/service-account/service-account.store.js +20 -1
- package/dist/features/user/signin-admin.tokens.d.ts +11 -0
- package/dist/features/user/signin-admin.tokens.d.ts.map +1 -0
- package/dist/features/user/signin-admin.tokens.js +13 -0
- package/dist/features/user/user-mfa-status.d.ts +38 -0
- package/dist/features/user/user-mfa-status.d.ts.map +1 -0
- package/dist/features/user/user-mfa-status.js +47 -0
- package/dist/features/user/user-signin-admin.service.d.ts +48 -0
- package/dist/features/user/user-signin-admin.service.d.ts.map +1 -0
- package/dist/features/user/user-signin-admin.service.js +232 -0
- package/dist/features/user/user.controller.d.ts +29 -2
- package/dist/features/user/user.controller.d.ts.map +1 -1
- package/dist/features/user/user.controller.js +71 -3
- package/dist/features/user/user.service.d.ts +40 -14
- package/dist/features/user/user.service.d.ts.map +1 -1
- package/dist/features/user/user.service.js +143 -10
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/objects.d.ts.map +1 -1
- package/dist/objects.js +2 -0
- package/dist/role.object.d.ts +1 -1
- package/dist/role.object.d.ts.map +1 -1
- package/dist/role.object.js +6 -15
- package/dist/security-policy.object.d.ts +43 -0
- package/dist/security-policy.object.d.ts.map +1 -0
- package/dist/security-policy.object.js +107 -0
- package/dist/user.object.d.ts +6 -0
- package/dist/user.object.d.ts.map +1 -1
- package/dist/user.object.js +13 -1
- package/migrations/1710000000103-AddUserLoginName.cjs +87 -0
- package/migrations/1710000000104-CreateSecurityPolicy.cjs +90 -0
- package/migrations/1710000000105-OwnDepartmentsAndBranches.cjs +327 -0
- package/migrations/1710000000106-OwnRolesPerCompany.cjs +622 -0
- package/package.json +4 -4
|
@@ -12,7 +12,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.RoleService = void 0;
|
|
15
|
+
exports.RoleService = exports.NO_ROLE_COMPANY = void 0;
|
|
16
|
+
exports.roleNameMessage = roleNameMessage;
|
|
16
17
|
const common_1 = require("@nestjs/common");
|
|
17
18
|
const engine_1 = require("@astram/engine");
|
|
18
19
|
const core_1 = require("@astram/core");
|
|
@@ -20,17 +21,64 @@ const list_query_js_1 = require("../shared/list-query.js");
|
|
|
20
21
|
const grant_ceiling_js_1 = require("../authz/grant-ceiling.js");
|
|
21
22
|
const grant_admin_service_js_1 = require("../authz/grant-admin.service.js");
|
|
22
23
|
const posting_version_bump_js_1 = require("../membership/posting-version-bump.js");
|
|
24
|
+
const identity_errors_js_1 = require("../shared/identity-errors.js");
|
|
25
|
+
const org_unit_name_js_1 = require("../org-structure/org-unit-name.js");
|
|
23
26
|
const ROLE_SEARCH_FIELDS = ['name'];
|
|
24
27
|
const ROLE_SORT_FIELDS = ['name', 'createdAt'];
|
|
28
|
+
/** The 400 of `POST /identity/roles` for a caller with no company to own the role (spec §10). */
|
|
29
|
+
exports.NO_ROLE_COMPANY = 'Choose a company for the role.';
|
|
30
|
+
/** The fixed, user-facing 400 text for a refused role name (the G-012 rule, spec §10). */
|
|
31
|
+
function roleNameMessage(reason) {
|
|
32
|
+
switch (reason) {
|
|
33
|
+
case 'control_character':
|
|
34
|
+
return 'A role name cannot contain control characters.';
|
|
35
|
+
case 'too_long':
|
|
36
|
+
return `A role name can be at most ${org_unit_name_js_1.ORG_UNIT_NAME_MAX} characters.`;
|
|
37
|
+
default:
|
|
38
|
+
return 'Enter a role name.';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** A role or company row has a single uuid key; a composite id here is a wiring defect. */
|
|
42
|
+
function singleId(id) {
|
|
43
|
+
if (typeof id !== 'string')
|
|
44
|
+
throw new TypeError('role/company id is not a single uuid');
|
|
45
|
+
return id;
|
|
46
|
+
}
|
|
47
|
+
/** A driver foreign-key miss (1452: the owner company does not exist), by errno/code only. */
|
|
48
|
+
function isMissingParent(err) {
|
|
49
|
+
const e = err;
|
|
50
|
+
return e.errno === 1452 || e.code === 'ER_NO_REFERENCED_ROW_2';
|
|
51
|
+
}
|
|
52
|
+
/** A driver duplicate-key error, by errno/code only (its message names the value: never echoed). */
|
|
53
|
+
function isDuplicateKey(err) {
|
|
54
|
+
if (typeof err !== 'object' || err === null)
|
|
55
|
+
return false;
|
|
56
|
+
const e = err;
|
|
57
|
+
return e.errno === 1062 || e.code === 'ER_DUP_ENTRY';
|
|
58
|
+
}
|
|
59
|
+
function nameOf(view) {
|
|
60
|
+
const name = view.fields?.name;
|
|
61
|
+
return typeof name === 'string' && name.length > 0 ? name : '(unknown)';
|
|
62
|
+
}
|
|
63
|
+
function ownerOf(view) {
|
|
64
|
+
const owner = view.fields?.ownerCompanyUuid;
|
|
65
|
+
return typeof owner === 'string' && owner.length > 0 ? owner : null;
|
|
66
|
+
}
|
|
67
|
+
function duplicate(storedName) {
|
|
68
|
+
return new identity_errors_js_1.IdentityConflictError(`A role named "${storedName}" already exists in this company.`);
|
|
69
|
+
}
|
|
25
70
|
/**
|
|
26
|
-
* RoleService — role CRUD on the paved road, via the framework's RecordsService
|
|
27
|
-
*
|
|
28
|
-
* no raw SQL, no RECORD_ENGINE.
|
|
71
|
+
* RoleService — role CRUD on the paved road, via the framework's RecordsService facade (the engine
|
|
72
|
+
* pipe: gate, wall, validate, write, audit). No raw SQL, no RECORD_ENGINE.
|
|
29
73
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
74
|
+
* G-013 (spec §5.A, ADR-0047): every role is OWNED by one company (`ownerCompanyUuid`, immutable),
|
|
75
|
+
* stamped here from the reached company (or the caller's active company on the legacy route), never
|
|
76
|
+
* from a request body (R1). The role object's `readScope` walls every read and write by that owner
|
|
77
|
+
* (R3: out of reach ⇒ 404; an ownerless legacy row is root only, R5). Names follow the G-012 rule
|
|
78
|
+
* (`normaliseOrgUnitName`) and are unique within the owner company under the column collation; the
|
|
79
|
+
* check runs under a lock inside one transaction and the per-company unique index is the backstop
|
|
80
|
+
* (a driver 1062 ⇒ the same 409, R6). Rename and delete first pass
|
|
81
|
+
* `GrantCeiling.assertRoleAdministrable` (owner in the actor's subtree, else 404).
|
|
34
82
|
*/
|
|
35
83
|
let RoleService = class RoleService {
|
|
36
84
|
records;
|
|
@@ -44,40 +92,102 @@ let RoleService = class RoleService {
|
|
|
44
92
|
this.grants = grants;
|
|
45
93
|
}
|
|
46
94
|
/**
|
|
47
|
-
* Create a role
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
95
|
+
* Create a role (`POST /identity/roles`, kept for existing clients). Owner = the caller's active
|
|
96
|
+
* company, else its tenant; a caller with neither ⇒ 400 "Choose a company for the role." The
|
|
97
|
+
* company is then reached and locked exactly as {@link createCompanyRole} does.
|
|
98
|
+
*
|
|
99
|
+
* `companyUuid` is for the org bootstrap only (spec §5.E): the bound `roles` step names the
|
|
100
|
+
* DECLARING company explicitly and holds no company key (gate 7), so that company is not read or
|
|
101
|
+
* locked here; the engine's create wall checks the owner against the actor's reach, the duplicate
|
|
102
|
+
* check runs in the transaction and the unique index is the backstop.
|
|
52
103
|
*/
|
|
53
|
-
createRole(
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
56
|
-
|
|
104
|
+
async createRole(rawName, actor, companyUuid) {
|
|
105
|
+
const name = this.validName(rawName);
|
|
106
|
+
if (companyUuid !== undefined) {
|
|
107
|
+
if (companyUuid.length === 0)
|
|
108
|
+
throw new identity_errors_js_1.IdentityBadRequestError(exports.NO_ROLE_COMPANY);
|
|
109
|
+
// Bootstrap-only path (no company read: its gate-7 step holds role keys only). A company that
|
|
110
|
+
// does not exist fails the owner FK (1452): answered as 404, never the driver error.
|
|
111
|
+
try {
|
|
112
|
+
return await this.mappingDuplicates(() => companyUuid, name, () => this.records.transaction((tx) => this.insertRole(tx, companyUuid, name)));
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (isMissingParent(err))
|
|
116
|
+
throw new identity_errors_js_1.IdentityNotFoundError('Company not found.');
|
|
117
|
+
throw err;
|
|
118
|
+
}
|
|
57
119
|
}
|
|
58
|
-
|
|
120
|
+
const company = actor.activeScopeNodeId || actor.tenantId;
|
|
121
|
+
if (typeof company !== 'string' || company.length === 0) {
|
|
122
|
+
throw new identity_errors_js_1.IdentityBadRequestError(exports.NO_ROLE_COMPANY);
|
|
123
|
+
}
|
|
124
|
+
return (await this.createInCompany(company, name)).uuid;
|
|
59
125
|
}
|
|
60
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* Create a role in `companyUuid` (`POST /identity/companies/:companyUuid/roles`): normalise the
|
|
128
|
+
* name; in one transaction lock the company, reach it through the wall (404), refuse a name the
|
|
129
|
+
* company already holds (409 naming the stored role) and create the role owned by the REACHED
|
|
130
|
+
* company. Returns `{ uuid, name }` (the stored name).
|
|
131
|
+
*/
|
|
132
|
+
async createCompanyRole(companyUuid, rawName) {
|
|
133
|
+
return this.createInCompany(companyUuid, this.validName(rawName));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* One company's own roles (`GET /identity/companies/:companyUuid/roles`): the company is reached
|
|
137
|
+
* through the walled read first (404 when out of reach), then its roles are listed with the same
|
|
138
|
+
* paging, search and sort allowlists as {@link listRoles}.
|
|
139
|
+
*/
|
|
140
|
+
async listCompanyRoles(companyUuid, query) {
|
|
141
|
+
const company = await this.records.get('company', companyUuid);
|
|
142
|
+
if (company === null)
|
|
143
|
+
throw new identity_errors_js_1.IdentityNotFoundError('Company not found.');
|
|
144
|
+
const { page, limit, params } = (0, list_query_js_1.parseListQuery)(query);
|
|
145
|
+
const listQuery = {
|
|
146
|
+
...(0, list_query_js_1.buildListQuery)(params, ROLE_SEARCH_FIELDS, ROLE_SORT_FIELDS),
|
|
147
|
+
where: { ownerCompanyUuid: singleId(company.id) },
|
|
148
|
+
};
|
|
149
|
+
const result = await this.records.list('role', listQuery);
|
|
150
|
+
return { total: result.total, rows: result.rows, page, limit };
|
|
151
|
+
}
|
|
152
|
+
/** List roles (walled by owner through the role object's readScope), with paging/search/sort. */
|
|
61
153
|
listRoles(params) {
|
|
62
154
|
return this.records.list('role', (0, list_query_js_1.buildListQuery)(params, ROLE_SEARCH_FIELDS, ROLE_SORT_FIELDS));
|
|
63
155
|
}
|
|
64
|
-
/** Read a single role. */
|
|
156
|
+
/** Read a single role (walled by owner). */
|
|
65
157
|
getRole(uuid) {
|
|
66
158
|
return this.records.get('role', uuid);
|
|
67
159
|
}
|
|
68
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Rename a role — only a role the actor may administer (owner in reach, else 404). The name goes
|
|
162
|
+
* through the name rule (400); in one transaction the role row is locked, re-read through the wall
|
|
163
|
+
* (404; ownerless ⇒ root only), and a name another role of the same company holds is refused (409
|
|
164
|
+
* naming the stored role). The same name ⇒ no write. Only `name` is ever written.
|
|
165
|
+
*/
|
|
69
166
|
async updateRole(actor, uuid, patch) {
|
|
70
167
|
await this.ceiling.assertRoleAdministrable(actor, uuid);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
168
|
+
const name = this.validName(patch?.name);
|
|
169
|
+
let owner = null;
|
|
170
|
+
await this.mappingDuplicates(() => owner, name, () => this.records.transaction(async (tx) => {
|
|
171
|
+
await tx.lockForUpdate('role', uuid);
|
|
172
|
+
const row = await tx.get('role', uuid);
|
|
173
|
+
if (row === null)
|
|
174
|
+
throw new identity_errors_js_1.IdentityNotFoundError('Role not found.');
|
|
175
|
+
owner = ownerOf(row);
|
|
176
|
+
if (owner === null && actor.isRoot !== true) {
|
|
177
|
+
throw new identity_errors_js_1.IdentityNotFoundError('Role not found.');
|
|
178
|
+
}
|
|
179
|
+
if (row.fields?.name === name)
|
|
180
|
+
return; // same name: no write
|
|
181
|
+
if (owner !== null)
|
|
182
|
+
await this.assertNameFree(tx, owner, name, singleId(row.id));
|
|
183
|
+
await tx.update('role', row.id, { fields: { name } });
|
|
184
|
+
}));
|
|
75
185
|
}
|
|
76
186
|
/**
|
|
77
|
-
* Delete a role — only a role the actor may administer (
|
|
187
|
+
* Delete a role — only a role the actor may administer (owner rule) AND whose every holder the
|
|
78
188
|
* actor dominates (Phase 8 #2: the delete cascades the holders' postings, stripping their
|
|
79
189
|
* authority). In ONE transaction: lock the role row (the posting and grant paths lock the same
|
|
80
|
-
* row first), re-check the
|
|
190
|
+
* row first), re-check the owner rule and holder dominance against what is committed now, read
|
|
81
191
|
* the holder tenants (before the cascade removes the postings), then delete. After the commit,
|
|
82
192
|
* every holder tenant's permission version is bumped so cached roles drop at the next request.
|
|
83
193
|
* The bump runs after the commit, never before: an earlier bump would let a session reload the
|
|
@@ -124,6 +234,73 @@ let RoleService = class RoleService {
|
|
|
124
234
|
throw new core_1.AuthorizationUnavailableError('permission version bump failed', cause);
|
|
125
235
|
}
|
|
126
236
|
}
|
|
237
|
+
// ------------------------------------------------------------------------------- internals
|
|
238
|
+
validName(raw) {
|
|
239
|
+
const result = (0, org_unit_name_js_1.normaliseOrgUnitName)(raw);
|
|
240
|
+
if (!result.ok)
|
|
241
|
+
throw new identity_errors_js_1.IdentityBadRequestError(roleNameMessage(result.reason));
|
|
242
|
+
return result.value;
|
|
243
|
+
}
|
|
244
|
+
/** Lock the company FIRST, reach it through the wall (404), then create the role it owns. */
|
|
245
|
+
async createInCompany(companyUuid, name) {
|
|
246
|
+
let owner = companyUuid;
|
|
247
|
+
const uuid = await this.mappingDuplicates(() => owner, name, () => this.records.transaction(async (tx) => {
|
|
248
|
+
await tx.lockForUpdate('company', companyUuid);
|
|
249
|
+
const company = await tx.get('company', companyUuid);
|
|
250
|
+
if (company === null)
|
|
251
|
+
throw new identity_errors_js_1.IdentityNotFoundError('Company not found.');
|
|
252
|
+
owner = singleId(company.id);
|
|
253
|
+
return this.insertRole(tx, owner, name);
|
|
254
|
+
}));
|
|
255
|
+
return { uuid, name };
|
|
256
|
+
}
|
|
257
|
+
/** Duplicate check, then the role owned by `owner`, on the caller's transaction. */
|
|
258
|
+
async insertRole(tx, owner, name) {
|
|
259
|
+
await this.assertNameFree(tx, owner, name, undefined);
|
|
260
|
+
return singleId(await tx.create('role', { fields: { name, ownerCompanyUuid: owner } }));
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Refuse a name another role of the same company already holds. The engine's equality runs under
|
|
264
|
+
* the column collation (`utf8mb4_unicode_ci`: case, accents and width fold), so "manager" finds
|
|
265
|
+
* "Manager"; the 409 names the STORED clashing role.
|
|
266
|
+
*/
|
|
267
|
+
async assertNameFree(tx, owner, name, self) {
|
|
268
|
+
const clash = await this.findByName(tx, owner, name, self);
|
|
269
|
+
if (clash !== undefined)
|
|
270
|
+
throw duplicate(nameOf(clash));
|
|
271
|
+
}
|
|
272
|
+
async findByName(reader, owner, name, self) {
|
|
273
|
+
const rows = (await reader.list('role', { where: { ownerCompanyUuid: owner, name }, limit: 2 }))
|
|
274
|
+
.rows;
|
|
275
|
+
return rows.find((r) => self === undefined || singleId(r.id) !== self);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Run a create/rename; a driver duplicate key (the per-company unique index, the backstop for a
|
|
279
|
+
* concurrent write) becomes the same 409 naming the stored role. Errno only: the driver's message
|
|
280
|
+
* holds the value and is never echoed (KI #87).
|
|
281
|
+
*/
|
|
282
|
+
async mappingDuplicates(owner, name, write) {
|
|
283
|
+
try {
|
|
284
|
+
return await write();
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
if (!isDuplicateKey(err))
|
|
288
|
+
throw err;
|
|
289
|
+
let stored = name;
|
|
290
|
+
const company = owner();
|
|
291
|
+
if (company !== null) {
|
|
292
|
+
try {
|
|
293
|
+
const clash = await this.findByName(this.records, company, name);
|
|
294
|
+
if (clash !== undefined)
|
|
295
|
+
stored = nameOf(clash);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
// The 409 stands; the submitted name names the clash.
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
throw duplicate(stored);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
127
304
|
};
|
|
128
305
|
exports.RoleService = RoleService;
|
|
129
306
|
exports.RoleService = RoleService = __decorate([
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { PermissionVersionBumper } from '../authz/permission-version.bumper.js';
|
|
2
|
+
import type { IdentitySchemaNames } from '../../schema.js';
|
|
3
|
+
/** The query surface used here: the write transaction's own connection (via `transactionQueryOf`). */
|
|
4
|
+
export interface Queryable {
|
|
5
|
+
query(sql: string, params?: readonly unknown[]): Promise<unknown>;
|
|
6
|
+
}
|
|
7
|
+
type Bumper = Pick<PermissionVersionBumper, 'bumpForTenant' | 'publishCommitted' | 'discardPending'>;
|
|
8
|
+
/**
|
|
9
|
+
* Permission-version bump for a security-policy write (auth capabilities R2.5, F17): every tenant
|
|
10
|
+
* whose signed-in users the policy can affect gets its version bumped ON THE WRITE'S TRANSACTION,
|
|
11
|
+
* so the policy and the bump commit or roll back together, and guard's recompute (task 14) sees
|
|
12
|
+
* the change on each user's next request. The new versions reach Redis only after the commit
|
|
13
|
+
* (`publishCommitted`, the ONE `PermissionVersionBumper`, ADR-0035).
|
|
14
|
+
*
|
|
15
|
+
* Which tenants:
|
|
16
|
+
* - a scoped policy: its node and every descendant (`scope_closure`). A policy at a node applies
|
|
17
|
+
* only to sessions ACTIVE at that node or below it (core rule; the version key is the active
|
|
18
|
+
* node's), so ancestors are not bumped (review round 1, item I).
|
|
19
|
+
* - a platform floor policy: every company (no global version exists). One INSERT-or-increment
|
|
20
|
+
* per company inside the transaction; a floor write is a rare root action.
|
|
21
|
+
*
|
|
22
|
+
* Any read or bump failure is an `AuthorizationUnavailableError` with a fixed message (503, the
|
|
23
|
+
* write rolls back): a policy must never commit without its bump.
|
|
24
|
+
*/
|
|
25
|
+
export declare class SecurityPolicyVersionBump {
|
|
26
|
+
private readonly bumper;
|
|
27
|
+
private readonly schemas;
|
|
28
|
+
constructor(bumper: Bumper, schemas: IdentitySchemaNames);
|
|
29
|
+
/** The tenants a policy at `scopeNodeId` (`null` = platform floor) can affect. */
|
|
30
|
+
tenantsInScope(scopeNodeId: string | null, conn: Queryable): Promise<string[]>;
|
|
31
|
+
/** Increment each tenant's permission version on `conn` (published after the commit). */
|
|
32
|
+
bump(tenants: readonly string[], conn: Queryable): Promise<void>;
|
|
33
|
+
/** Publish the versions bumped on `conn` — call after the commit. Never throws. */
|
|
34
|
+
publishCommitted(conn: Queryable): Promise<void>;
|
|
35
|
+
/** Drop the versions bumped on `conn` — call after a rollback. */
|
|
36
|
+
discardPending(conn: Queryable): void;
|
|
37
|
+
}
|
|
38
|
+
/** DI token for the {@link SecurityPolicyVersionBump} built in `IdentityFeatureModule.forRoot`. */
|
|
39
|
+
export declare const SECURITY_POLICY_VERSION_BUMP: unique symbol;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=security-policy-version-bump.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-policy-version-bump.d.ts","sourceRoot":"","sources":["../../../src/features/security-policy/security-policy-version-bump.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,sGAAsG;AACtG,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAED,KAAK,MAAM,GAAG,IAAI,CAChB,uBAAuB,EACvB,eAAe,GAAG,kBAAkB,GAAG,gBAAgB,CACxD,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,yBAAyB;IAElC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB;IAG/C,kFAAkF;IAC5E,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBpF,yFAAyF;IACnF,IAAI,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtE,mFAAmF;IACnF,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,kEAAkE;IAClE,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;CAGtC;AAED,mGAAmG;AACnG,eAAO,MAAM,4BAA4B,eAAyC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SECURITY_POLICY_VERSION_BUMP = exports.SecurityPolicyVersionBump = void 0;
|
|
4
|
+
const core_1 = require("@astram/core");
|
|
5
|
+
/**
|
|
6
|
+
* Permission-version bump for a security-policy write (auth capabilities R2.5, F17): every tenant
|
|
7
|
+
* whose signed-in users the policy can affect gets its version bumped ON THE WRITE'S TRANSACTION,
|
|
8
|
+
* so the policy and the bump commit or roll back together, and guard's recompute (task 14) sees
|
|
9
|
+
* the change on each user's next request. The new versions reach Redis only after the commit
|
|
10
|
+
* (`publishCommitted`, the ONE `PermissionVersionBumper`, ADR-0035).
|
|
11
|
+
*
|
|
12
|
+
* Which tenants:
|
|
13
|
+
* - a scoped policy: its node and every descendant (`scope_closure`). A policy at a node applies
|
|
14
|
+
* only to sessions ACTIVE at that node or below it (core rule; the version key is the active
|
|
15
|
+
* node's), so ancestors are not bumped (review round 1, item I).
|
|
16
|
+
* - a platform floor policy: every company (no global version exists). One INSERT-or-increment
|
|
17
|
+
* per company inside the transaction; a floor write is a rare root action.
|
|
18
|
+
*
|
|
19
|
+
* Any read or bump failure is an `AuthorizationUnavailableError` with a fixed message (503, the
|
|
20
|
+
* write rolls back): a policy must never commit without its bump.
|
|
21
|
+
*/
|
|
22
|
+
class SecurityPolicyVersionBump {
|
|
23
|
+
bumper;
|
|
24
|
+
schemas;
|
|
25
|
+
constructor(bumper, schemas) {
|
|
26
|
+
this.bumper = bumper;
|
|
27
|
+
this.schemas = schemas;
|
|
28
|
+
}
|
|
29
|
+
/** The tenants a policy at `scopeNodeId` (`null` = platform floor) can affect. */
|
|
30
|
+
async tenantsInScope(scopeNodeId, conn) {
|
|
31
|
+
try {
|
|
32
|
+
if (scopeNodeId === null) {
|
|
33
|
+
const rows = (await conn.query(`SELECT c_uuid AS tenant FROM \`${this.schemas.app}\`.\`companies\``));
|
|
34
|
+
return [...new Set(rows.map((r) => r.tenant))];
|
|
35
|
+
}
|
|
36
|
+
const closure = `\`${this.schemas.authz}\`.\`scope_closure\``;
|
|
37
|
+
const down = (await conn.query(`SELECT descendant_uuid AS tenant FROM ${closure} WHERE ancestor_uuid = ?`, [scopeNodeId]));
|
|
38
|
+
return [...new Set([scopeNodeId, ...down.map((r) => r.tenant)])];
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
throw new core_1.AuthorizationUnavailableError('security policy scope unavailable');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Increment each tenant's permission version on `conn` (published after the commit). */
|
|
45
|
+
async bump(tenants, conn) {
|
|
46
|
+
try {
|
|
47
|
+
for (const tenant of tenants)
|
|
48
|
+
await this.bumper.bumpForTenant(tenant, conn);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new core_1.AuthorizationUnavailableError('permission version bump failed');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Publish the versions bumped on `conn` — call after the commit. Never throws. */
|
|
55
|
+
publishCommitted(conn) {
|
|
56
|
+
return this.bumper.publishCommitted(conn);
|
|
57
|
+
}
|
|
58
|
+
/** Drop the versions bumped on `conn` — call after a rollback. */
|
|
59
|
+
discardPending(conn) {
|
|
60
|
+
this.bumper.discardPending(conn);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.SecurityPolicyVersionBump = SecurityPolicyVersionBump;
|
|
64
|
+
/** DI token for the {@link SecurityPolicyVersionBump} built in `IdentityFeatureModule.forRoot`. */
|
|
65
|
+
exports.SECURITY_POLICY_VERSION_BUMP = Symbol('SECURITY_POLICY_VERSION_BUMP');
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { SecurityPolicyService } from './security-policy.service.js';
|
|
2
|
+
import { type ListQueryDto } from '../shared/list-query.js';
|
|
3
|
+
import type { AuthedRequest } from '../shared/http.js';
|
|
4
|
+
interface CreateBody {
|
|
5
|
+
scopeNodeUuid?: unknown;
|
|
6
|
+
platform?: unknown;
|
|
7
|
+
targetKind?: unknown;
|
|
8
|
+
targetValue?: unknown;
|
|
9
|
+
graceDays?: unknown;
|
|
10
|
+
}
|
|
11
|
+
interface UpdateBody {
|
|
12
|
+
targetValue?: unknown;
|
|
13
|
+
graceDays?: unknown;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* `/identity/security-policies` — mandatory-2FA policies (auth capabilities R2.9). Every route is
|
|
17
|
+
* `@Classified` on `security_policy` (registered Gated, `identity:security_policy:<action>`); the
|
|
18
|
+
* R2.6 authority rules, audit and permission-version bump live in {@link SecurityPolicyService}.
|
|
19
|
+
* Bodies are reduced to the documented fields; the scope node is canonicalised here (400 if not a
|
|
20
|
+
* uuid). No static sub-paths, so route order does not matter.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SecurityPolicyController {
|
|
23
|
+
private readonly policies;
|
|
24
|
+
constructor(policies: SecurityPolicyService);
|
|
25
|
+
/** List policies — `identity:security_policy:read`; `{ total, rows, page, limit }`. */
|
|
26
|
+
listPolicies(query: ListQueryDto): Promise<{
|
|
27
|
+
total: number;
|
|
28
|
+
rows: import("packages/engine/dist/types.js").RecordView[];
|
|
29
|
+
page: number;
|
|
30
|
+
limit: number;
|
|
31
|
+
}>;
|
|
32
|
+
/** Read one policy — `identity:security_policy:read`. */
|
|
33
|
+
getPolicy(uuid: string): Promise<import("packages/engine/dist/types.js").RecordView | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Create a policy — `identity:security_policy:create`. Body `{ scopeNodeUuid?, platform?,
|
|
36
|
+
* targetKind, targetValue?, graceDays? }`; no node ⇒ the caller's active organisation.
|
|
37
|
+
*/
|
|
38
|
+
createPolicy(req: AuthedRequest, body: CreateBody): Promise<{
|
|
39
|
+
id: import("packages/engine/dist/types.js").RecordId;
|
|
40
|
+
}>;
|
|
41
|
+
/** Change a policy's target or grace — `identity:security_policy:update`. */
|
|
42
|
+
updatePolicy(req: AuthedRequest, uuid: string, body: UpdateBody): Promise<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
/** Delete a policy — `identity:security_policy:delete`. */
|
|
46
|
+
deletePolicy(req: AuthedRequest, uuid: string): Promise<{
|
|
47
|
+
success: boolean;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=security-policy.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-policy.controller.d.ts","sourceRoot":"","sources":["../../../src/features/security-policy/security-policy.controller.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,UAAU;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,qBAEa,wBAAwB;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,qBAAqB;IAE5D,uFAAuF;IAGjF,YAAY,CAAU,KAAK,EAAE,YAAY;;;;;;IAM/C,yDAAyD;IAGzD,SAAS,CAA0B,IAAI,EAAE,MAAM;IAI/C;;;OAGG;IAGG,YAAY,CAAQ,GAAG,EAAE,aAAa,EAAU,IAAI,EAAE,UAAU;;;IAYtE,6EAA6E;IAGvE,YAAY,CACT,GAAG,EAAE,aAAa,EACA,IAAI,EAAE,MAAM,EAC7B,IAAI,EAAE,UAAU;;;IAS1B,2DAA2D;IAGrD,YAAY,CAAQ,GAAG,EAAE,aAAa,EAA2B,IAAI,EAAE,MAAM;;;CAIpF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
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.SecurityPolicyController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const guard_1 = require("@astram/guard");
|
|
18
|
+
const security_policy_service_js_1 = require("./security-policy.service.js");
|
|
19
|
+
const list_query_js_1 = require("../shared/list-query.js");
|
|
20
|
+
const identity_error_interceptor_js_1 = require("../shared/identity-error.interceptor.js");
|
|
21
|
+
/**
|
|
22
|
+
* `/identity/security-policies` — mandatory-2FA policies (auth capabilities R2.9). Every route is
|
|
23
|
+
* `@Classified` on `security_policy` (registered Gated, `identity:security_policy:<action>`); the
|
|
24
|
+
* R2.6 authority rules, audit and permission-version bump live in {@link SecurityPolicyService}.
|
|
25
|
+
* Bodies are reduced to the documented fields; the scope node is canonicalised here (400 if not a
|
|
26
|
+
* uuid). No static sub-paths, so route order does not matter.
|
|
27
|
+
*/
|
|
28
|
+
let SecurityPolicyController = class SecurityPolicyController {
|
|
29
|
+
policies;
|
|
30
|
+
constructor(policies) {
|
|
31
|
+
this.policies = policies;
|
|
32
|
+
}
|
|
33
|
+
/** List policies — `identity:security_policy:read`; `{ total, rows, page, limit }`. */
|
|
34
|
+
async listPolicies(query) {
|
|
35
|
+
const { page, limit, params } = (0, list_query_js_1.parseListQuery)(query);
|
|
36
|
+
const result = await this.policies.listPolicies(params);
|
|
37
|
+
return { total: result.total, rows: result.rows, page, limit };
|
|
38
|
+
}
|
|
39
|
+
/** Read one policy — `identity:security_policy:read`. */
|
|
40
|
+
getPolicy(uuid) {
|
|
41
|
+
return this.policies.getPolicy(uuid);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a policy — `identity:security_policy:create`. Body `{ scopeNodeUuid?, platform?,
|
|
45
|
+
* targetKind, targetValue?, graceDays? }`; no node ⇒ the caller's active organisation.
|
|
46
|
+
*/
|
|
47
|
+
async createPolicy(req, body) {
|
|
48
|
+
const scopeNodeUuid = (0, guard_1.optionalUuidField)(body?.scopeNodeUuid, 'scopeNodeUuid');
|
|
49
|
+
const id = await this.policies.createPolicy(req.principal, {
|
|
50
|
+
...(scopeNodeUuid !== undefined ? { scopeNodeUuid } : {}),
|
|
51
|
+
targetKind: body?.targetKind,
|
|
52
|
+
targetValue: body?.targetValue,
|
|
53
|
+
graceDays: body?.graceDays,
|
|
54
|
+
platform: body?.platform,
|
|
55
|
+
});
|
|
56
|
+
return { id };
|
|
57
|
+
}
|
|
58
|
+
/** Change a policy's target or grace — `identity:security_policy:update`. */
|
|
59
|
+
async updatePolicy(req, uuid, body) {
|
|
60
|
+
await this.policies.updatePolicy(req.principal, uuid, {
|
|
61
|
+
graceDays: body?.graceDays,
|
|
62
|
+
targetValue: body?.targetValue,
|
|
63
|
+
});
|
|
64
|
+
return { success: true };
|
|
65
|
+
}
|
|
66
|
+
/** Delete a policy — `identity:security_policy:delete`. */
|
|
67
|
+
async deletePolicy(req, uuid) {
|
|
68
|
+
await this.policies.deletePolicy(req.principal, uuid);
|
|
69
|
+
return { success: true };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
exports.SecurityPolicyController = SecurityPolicyController;
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, common_1.Get)('security-policies'),
|
|
75
|
+
(0, guard_1.Classified)({ typeKey: 'security_policy', action: 'read' }),
|
|
76
|
+
__param(0, (0, common_1.Query)()),
|
|
77
|
+
__metadata("design:type", Function),
|
|
78
|
+
__metadata("design:paramtypes", [Object]),
|
|
79
|
+
__metadata("design:returntype", Promise)
|
|
80
|
+
], SecurityPolicyController.prototype, "listPolicies", null);
|
|
81
|
+
__decorate([
|
|
82
|
+
(0, common_1.Get)('security-policies/:uuid'),
|
|
83
|
+
(0, guard_1.Classified)({ typeKey: 'security_policy', action: 'read' }),
|
|
84
|
+
__param(0, (0, common_1.Param)('uuid', guard_1.UuidPipe)),
|
|
85
|
+
__metadata("design:type", Function),
|
|
86
|
+
__metadata("design:paramtypes", [String]),
|
|
87
|
+
__metadata("design:returntype", void 0)
|
|
88
|
+
], SecurityPolicyController.prototype, "getPolicy", null);
|
|
89
|
+
__decorate([
|
|
90
|
+
(0, common_1.Post)('security-policies'),
|
|
91
|
+
(0, guard_1.Classified)({ typeKey: 'security_policy', action: 'create' }),
|
|
92
|
+
__param(0, (0, common_1.Req)()),
|
|
93
|
+
__param(1, (0, common_1.Body)()),
|
|
94
|
+
__metadata("design:type", Function),
|
|
95
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
96
|
+
__metadata("design:returntype", Promise)
|
|
97
|
+
], SecurityPolicyController.prototype, "createPolicy", null);
|
|
98
|
+
__decorate([
|
|
99
|
+
(0, common_1.Put)('security-policies/:uuid'),
|
|
100
|
+
(0, guard_1.Classified)({ typeKey: 'security_policy', action: 'update' }),
|
|
101
|
+
__param(0, (0, common_1.Req)()),
|
|
102
|
+
__param(1, (0, common_1.Param)('uuid', guard_1.UuidPipe)),
|
|
103
|
+
__param(2, (0, common_1.Body)()),
|
|
104
|
+
__metadata("design:type", Function),
|
|
105
|
+
__metadata("design:paramtypes", [Object, String, Object]),
|
|
106
|
+
__metadata("design:returntype", Promise)
|
|
107
|
+
], SecurityPolicyController.prototype, "updatePolicy", null);
|
|
108
|
+
__decorate([
|
|
109
|
+
(0, common_1.Delete)('security-policies/:uuid'),
|
|
110
|
+
(0, guard_1.Classified)({ typeKey: 'security_policy', action: 'delete' }),
|
|
111
|
+
__param(0, (0, common_1.Req)()),
|
|
112
|
+
__param(1, (0, common_1.Param)('uuid', guard_1.UuidPipe)),
|
|
113
|
+
__metadata("design:type", Function),
|
|
114
|
+
__metadata("design:paramtypes", [Object, String]),
|
|
115
|
+
__metadata("design:returntype", Promise)
|
|
116
|
+
], SecurityPolicyController.prototype, "deletePolicy", null);
|
|
117
|
+
exports.SecurityPolicyController = SecurityPolicyController = __decorate([
|
|
118
|
+
(0, common_1.Controller)('identity'),
|
|
119
|
+
(0, common_1.UseInterceptors)(identity_error_interceptor_js_1.IdentityErrorInterceptor),
|
|
120
|
+
__metadata("design:paramtypes", [security_policy_service_js_1.SecurityPolicyService])
|
|
121
|
+
], SecurityPolicyController);
|