@openhi/constructs 0.0.118 → 0.0.120
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/lib/{chunk-QWWLM452.mjs → chunk-7WDX6GPO.mjs} +57 -1
- package/lib/chunk-7WDX6GPO.mjs.map +1 -0
- package/lib/{chunk-AJQUWHFK.mjs → chunk-WXS3PUHR.mjs} +2 -2
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +14 -3
- package/lib/index.mjs.map +1 -1
- package/lib/provision-default-workspace.handler.js +53 -0
- package/lib/provision-default-workspace.handler.js.map +1 -1
- package/lib/provision-default-workspace.handler.mjs +1 -1
- package/lib/rest-api-lambda.handler.js +85 -0
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +34 -1
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/lib/seed-demo-data.handler.js +53 -0
- package/lib/seed-demo-data.handler.js.map +1 -1
- package/lib/seed-demo-data.handler.mjs +2 -2
- package/package.json +3 -3
- package/lib/chunk-QWWLM452.mjs.map +0 -1
- /package/lib/{chunk-AJQUWHFK.mjs.map → chunk-WXS3PUHR.mjs.map} +0 -0
|
@@ -4946,6 +4946,19 @@ function extractDenormalizedReferenceDisplay(resource, fieldName) {
|
|
|
4946
4946
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
4947
4947
|
}
|
|
4948
4948
|
|
|
4949
|
+
// src/data/operations/control/membership-constraints/assert-workspace-in-tenant-operation.ts
|
|
4950
|
+
async function assertWorkspaceInTenantOperation(params) {
|
|
4951
|
+
const { tenantId, workspaceId, tableName } = params;
|
|
4952
|
+
const service = getDynamoControlService(tableName);
|
|
4953
|
+
const { data: item } = await service.entities.workspace.get({ tenantId, id: workspaceId, sk: "CURRENT" }).go();
|
|
4954
|
+
if (!item) {
|
|
4955
|
+
throw new ConflictError(
|
|
4956
|
+
`Workspace ${workspaceId} does not belong to tenant ${tenantId}; the workspace must be created in the referenced tenant before this resource can reference it.`,
|
|
4957
|
+
{ details: { tenantId, workspaceId } }
|
|
4958
|
+
);
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4961
|
+
|
|
4949
4962
|
// src/data/operations/control/membership/membership-create-operation.ts
|
|
4950
4963
|
async function createMembershipOperation(params) {
|
|
4951
4964
|
const { context, body, tableName } = params;
|
|
@@ -4986,6 +4999,15 @@ async function createMembershipOperation(params) {
|
|
|
4986
4999
|
resourceRecord,
|
|
4987
5000
|
"workspace"
|
|
4988
5001
|
);
|
|
5002
|
+
if (workspaceIdFromResource !== void 0) {
|
|
5003
|
+
const tenantIdFromResource = extractReferenceSlug(resourceRecord, "tenant");
|
|
5004
|
+
const referencedTenantId = tenantIdFromResource ?? context.tenantId;
|
|
5005
|
+
await assertWorkspaceInTenantOperation({
|
|
5006
|
+
tenantId: referencedTenantId,
|
|
5007
|
+
workspaceId: workspaceIdFromResource,
|
|
5008
|
+
tableName
|
|
5009
|
+
});
|
|
5010
|
+
}
|
|
4989
5011
|
const userProjectionItem = userIdFromResource !== void 0 ? buildMembershipUserProjectionItem({
|
|
4990
5012
|
tenantId: context.tenantId,
|
|
4991
5013
|
userId: userIdFromResource,
|
|
@@ -5061,6 +5083,22 @@ async function createMembershipRoute(req, res) {
|
|
|
5061
5083
|
});
|
|
5062
5084
|
return res.status(201).location(`${BASE_PATH.MEMBERSHIP}/${result.id}`).json({ ...result.resource, meta: result.meta });
|
|
5063
5085
|
} catch (err) {
|
|
5086
|
+
if (err instanceof ConflictError) {
|
|
5087
|
+
return res.status(409).json({
|
|
5088
|
+
resourceType: "OperationOutcome",
|
|
5089
|
+
issue: [
|
|
5090
|
+
{ severity: "error", code: "conflict", diagnostics: err.message }
|
|
5091
|
+
]
|
|
5092
|
+
});
|
|
5093
|
+
}
|
|
5094
|
+
if (err instanceof ValidationError) {
|
|
5095
|
+
return res.status(400).json({
|
|
5096
|
+
resourceType: "OperationOutcome",
|
|
5097
|
+
issue: [
|
|
5098
|
+
{ severity: "error", code: "invalid", diagnostics: err.message }
|
|
5099
|
+
]
|
|
5100
|
+
});
|
|
5101
|
+
}
|
|
5064
5102
|
console.error("POST Membership error:", err);
|
|
5065
5103
|
return res.status(500).json({
|
|
5066
5104
|
resourceType: "OperationOutcome",
|
|
@@ -5743,6 +5781,21 @@ function buildRoleAssignmentWorkspaceProjectionItem(input) {
|
|
|
5743
5781
|
};
|
|
5744
5782
|
}
|
|
5745
5783
|
|
|
5784
|
+
// src/data/operations/control/membership-constraints/assert-user-has-tenant-membership-operation.ts
|
|
5785
|
+
var TENANT_LANE_SK_PREFIX = "MEMBERSHIP#TENANT#";
|
|
5786
|
+
async function assertUserHasTenantMembershipOperation(params) {
|
|
5787
|
+
const { userId, tenantId, tableName } = params;
|
|
5788
|
+
const service = getDynamoControlService(tableName);
|
|
5789
|
+
const result = await service.entities.membershipUserProjection.query.record({ userId }).begins({ sk: TENANT_LANE_SK_PREFIX }).go();
|
|
5790
|
+
const matched = (result.data ?? []).some((row) => row.tenantId === tenantId);
|
|
5791
|
+
if (!matched) {
|
|
5792
|
+
throw new ConflictError(
|
|
5793
|
+
`User ${userId} has no tenant-level Membership in tenant ${tenantId}; a Membership must exist before a RoleAssignment can be created.`,
|
|
5794
|
+
{ details: { userId, tenantId } }
|
|
5795
|
+
);
|
|
5796
|
+
}
|
|
5797
|
+
}
|
|
5798
|
+
|
|
5746
5799
|
// src/data/operations/control/roleassignment/roleassignment-create-operation.ts
|
|
5747
5800
|
async function createRoleAssignmentOperation(params) {
|
|
5748
5801
|
const { context, body, tableName } = params;
|
|
@@ -5772,6 +5825,22 @@ async function createRoleAssignmentOperation(params) {
|
|
|
5772
5825
|
resourceRecord,
|
|
5773
5826
|
"workspace"
|
|
5774
5827
|
);
|
|
5828
|
+
if (userIdFromResource !== void 0) {
|
|
5829
|
+
const tenantIdFromResource = extractReferenceSlug2(resourceRecord, "tenant");
|
|
5830
|
+
const referencedTenantId = tenantIdFromResource ?? context.tenantId;
|
|
5831
|
+
await assertUserHasTenantMembershipOperation({
|
|
5832
|
+
userId: userIdFromResource,
|
|
5833
|
+
tenantId: referencedTenantId,
|
|
5834
|
+
tableName
|
|
5835
|
+
});
|
|
5836
|
+
if (workspaceIdFromResource !== void 0) {
|
|
5837
|
+
await assertWorkspaceInTenantOperation({
|
|
5838
|
+
tenantId: referencedTenantId,
|
|
5839
|
+
workspaceId: workspaceIdFromResource,
|
|
5840
|
+
tableName
|
|
5841
|
+
});
|
|
5842
|
+
}
|
|
5843
|
+
}
|
|
5775
5844
|
const userProjectionItem = userIdFromResource !== void 0 && roleIdFromResource !== void 0 ? buildRoleAssignmentUserProjectionItem({
|
|
5776
5845
|
tenantId: context.tenantId,
|
|
5777
5846
|
userId: userIdFromResource,
|
|
@@ -5850,6 +5919,22 @@ async function createRoleAssignmentRoute(req, res) {
|
|
|
5850
5919
|
});
|
|
5851
5920
|
return res.status(201).location(`${BASE_PATH.ROLEASSIGNMENT}/${result.id}`).json({ ...result.resource, meta: result.meta });
|
|
5852
5921
|
} catch (err) {
|
|
5922
|
+
if (err instanceof ConflictError) {
|
|
5923
|
+
return res.status(409).json({
|
|
5924
|
+
resourceType: "OperationOutcome",
|
|
5925
|
+
issue: [
|
|
5926
|
+
{ severity: "error", code: "conflict", diagnostics: err.message }
|
|
5927
|
+
]
|
|
5928
|
+
});
|
|
5929
|
+
}
|
|
5930
|
+
if (err instanceof ValidationError) {
|
|
5931
|
+
return res.status(400).json({
|
|
5932
|
+
resourceType: "OperationOutcome",
|
|
5933
|
+
issue: [
|
|
5934
|
+
{ severity: "error", code: "invalid", diagnostics: err.message }
|
|
5935
|
+
]
|
|
5936
|
+
});
|
|
5937
|
+
}
|
|
5853
5938
|
console.error("POST RoleAssignment error:", err);
|
|
5854
5939
|
return res.status(500).json({
|
|
5855
5940
|
resourceType: "OperationOutcome",
|