@carthooks/arcubase-cli 0.1.17 → 0.1.19
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/bundle/arcubase-admin.mjs +20 -25
- package/bundle/arcubase.mjs +20 -25
- package/dist/adapters/user_identity_adapter.d.ts +7 -0
- package/dist/adapters/user_identity_adapter.d.ts.map +1 -0
- package/dist/adapters/user_identity_adapter.js +10 -0
- package/dist/generated/zod_registry.generated.d.ts.map +1 -1
- package/dist/generated/zod_registry.generated.js +1 -1
- package/dist/interface/index.d.ts +3 -0
- package/dist/interface/index.d.ts.map +1 -0
- package/dist/interface/index.js +2 -0
- package/dist/interface/organization.d.ts +14 -0
- package/dist/interface/organization.d.ts.map +1 -0
- package/dist/interface/organization.js +1 -0
- package/dist/interface/user_identity.d.ts +10 -0
- package/dist/interface/user_identity.d.ts.map +1 -0
- package/dist/interface/user_identity.js +1 -0
- package/dist/runtime/execute.d.ts.map +1 -1
- package/dist/runtime/execute.js +18 -16
- package/package.json +1 -1
- package/sdk-dist/docs/runtime-reference/access-rule.md +12 -10
- package/sdk-dist/generated/zod_registry.generated.ts +1 -1
- package/sdk-dist/interface/index.ts +2 -0
- package/sdk-dist/interface/organization.ts +15 -0
- package/sdk-dist/interface/user_identity.ts +11 -0
- package/sdk-dist/types/common.ts +1 -0
- package/sdk-dist/types/entity.ts +1 -1
- package/sdk-dist/types/kiosk-ui.ts +1 -1
- package/sdk-dist/types/tenant.ts +1 -1
- package/src/adapters/user_identity_adapter.ts +17 -0
- package/src/generated/zod_registry.generated.ts +1 -1
- package/src/interface/index.ts +2 -0
- package/src/interface/organization.ts +15 -0
- package/src/interface/user_identity.ts +11 -0
- package/src/runtime/execute.ts +19 -24
- package/src/tests/execute_validation.test.ts +61 -10
- package/src/tests/help.test.ts +13 -1
- package/src/tests/terminology_boundary.test.ts +43 -0
- package/src/tests/zod_registry.test.ts +38 -0
|
@@ -16081,7 +16081,7 @@ var AppCreateEntityReqVOSchema = external_exports.lazy(() => external_exports.ob
|
|
|
16081
16081
|
var I18NTextSchema = external_exports.lazy(() => external_exports.record(external_exports.string(), external_exports.string()));
|
|
16082
16082
|
var PermitColumnSchema = external_exports.lazy(() => external_exports.object({ "field_id": external_exports.number().optional(), "is_field": external_exports.boolean().optional(), "prop": external_exports.string().optional() }).strict());
|
|
16083
16083
|
var PermitSearchColumnSchema = external_exports.lazy(() => external_exports.object({ "default": external_exports.boolean().optional(), "default_value": external_exports.array(external_exports.number()).optional(), "field_id": external_exports.number().optional(), "infilter": external_exports.boolean().optional(), "is_field": external_exports.boolean().optional(), "pinned": external_exports.boolean().optional(), "prop": external_exports.string().optional(), "wildcard": external_exports.boolean().optional() }).strict());
|
|
16084
|
-
var PermitEntityPropSchema = external_exports.lazy(() => external_exports.
|
|
16084
|
+
var PermitEntityPropSchema = external_exports.lazy(() => external_exports.string().min(1));
|
|
16085
16085
|
var PermitValueFromSchema = external_exports.lazy(() => external_exports.union([external_exports.literal(1), external_exports.literal(2), external_exports.literal(3)]));
|
|
16086
16086
|
var PermitRecordConditionSchema = external_exports.lazy(() => external_exports.object({ "column": PermitEntityPropSchema.optional(), "operator": external_exports.string().optional(), "subset": PermitConditionSetSchema.optional(), "value": external_exports.any().optional(), "value_from": PermitValueFromSchema.optional(), "value_relation": PermitEntityPropSchema.optional() }).strict());
|
|
16087
16087
|
var PermitConditionSetSchema = external_exports.lazy(() => external_exports.object({ "conditions": external_exports.array(PermitRecordConditionSchema).optional(), "mode": external_exports.string().optional() }).strict());
|
|
@@ -17509,17 +17509,17 @@ function renderCommandHelp(scope, moduleName, commandName, env = process.env) {
|
|
|
17509
17509
|
` - hide field: ${JSON.stringify(buildHiddenFieldAccessRuleBody())}`,
|
|
17510
17510
|
"success requires:",
|
|
17511
17511
|
" - result.enabled must be true",
|
|
17512
|
-
' - options.user_scope[].type is "user"
|
|
17512
|
+
' - options.user_scope[].type is "user", "department", or "actor"',
|
|
17513
17513
|
' - hidden fields use colon field keys such as ":1002"'
|
|
17514
17514
|
] : [],
|
|
17515
17515
|
...scope === "admin" && command.commandPath[0] === "access-rule" && command.commandPath[1] === "assign-users" ? [
|
|
17516
17516
|
"body-json example:",
|
|
17517
|
-
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
17517
|
+
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
17518
17518
|
"success requires:",
|
|
17519
17519
|
" - result.enabled must be true",
|
|
17520
|
-
" - result.options.user_scope must contain
|
|
17521
|
-
" - PermitUserScope.id must be the numeric arcubaseUserId",
|
|
17522
|
-
" - Do not copy a non-numeric
|
|
17520
|
+
" - result.options.user_scope must contain every assigned user, department, or actor scope",
|
|
17521
|
+
" - PermitUserScope.id must be the numeric arcubaseUserId, department ID, or actor ID",
|
|
17522
|
+
" - Do not copy a non-numeric BotWorks userId into PermitUserScope.id",
|
|
17523
17523
|
" - If result.enabled is false, enable the rule first and retry assign-users"
|
|
17524
17524
|
] : [],
|
|
17525
17525
|
...scope === "admin" && command.commandPath[0] === "app" && command.commandPath[1] === "create-from-bundle-url" ? [
|
|
@@ -17990,14 +17990,18 @@ function buildAssignUsersValidationDetails(scope, command, requestType, path3, m
|
|
|
17990
17990
|
shapeHint: {
|
|
17991
17991
|
update: ["user_scope"],
|
|
17992
17992
|
options: {
|
|
17993
|
-
user_scope: [
|
|
17993
|
+
user_scope: [
|
|
17994
|
+
{ type: "user", id: 2188889901 },
|
|
17995
|
+
{ type: "department", id: 2188881201 },
|
|
17996
|
+
{ type: "actor", id: 2188883301 }
|
|
17997
|
+
]
|
|
17994
17998
|
}
|
|
17995
17999
|
},
|
|
17996
18000
|
commonMistakes: [
|
|
17997
18001
|
"do not use user_scope at top level",
|
|
17998
18002
|
"do not use users or allowedUsers",
|
|
17999
|
-
"do not use non-numeric
|
|
18000
|
-
"id must be the numeric arcubaseUserId"
|
|
18003
|
+
"do not use non-numeric BotWorks userId as id",
|
|
18004
|
+
"id must be the numeric arcubaseUserId, department ID, or actor ID"
|
|
18001
18005
|
]
|
|
18002
18006
|
};
|
|
18003
18007
|
}
|
|
@@ -18278,7 +18282,7 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
|
|
|
18278
18282
|
if (userScope === void 0) return;
|
|
18279
18283
|
if (!Array.isArray(userScope)) {
|
|
18280
18284
|
throwBodyValidationFailure(
|
|
18281
|
-
'access-rule user_scope must be an array of {"type":"user","id":2188889901}',
|
|
18285
|
+
'access-rule user_scope must be an array of {"type":"user","id":2188889901}, {"type":"department","id":2188881201}, or {"type":"actor","id":2188883301}',
|
|
18282
18286
|
requestType,
|
|
18283
18287
|
pathPrefix,
|
|
18284
18288
|
scope,
|
|
@@ -18341,7 +18345,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
|
|
|
18341
18345
|
if (isAssignUsersCommand(scope, command)) {
|
|
18342
18346
|
if ("users" in body || "allowedUsers" in body || "user_scope" in body) {
|
|
18343
18347
|
throwBodyValidationFailure(
|
|
18344
|
-
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
18348
|
+
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
18345
18349
|
command.requestType,
|
|
18346
18350
|
"body.options.user_scope",
|
|
18347
18351
|
scope,
|
|
@@ -18462,7 +18466,7 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
|
|
|
18462
18466
|
const userScope = options && Array.isArray(options.user_scope) ? options.user_scope : void 0;
|
|
18463
18467
|
if ("users" in body || "allowedUsers" in body) {
|
|
18464
18468
|
throwBodyValidationFailure(
|
|
18465
|
-
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
18469
|
+
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
18466
18470
|
command.requestType,
|
|
18467
18471
|
"body.options.user_scope",
|
|
18468
18472
|
scope,
|
|
@@ -18503,19 +18507,9 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
|
|
|
18503
18507
|
env
|
|
18504
18508
|
);
|
|
18505
18509
|
}
|
|
18506
|
-
if (item.type !== "user") {
|
|
18507
|
-
throwBodyValidationFailure(
|
|
18508
|
-
'access-rule assign-users requires body.options.user_scope[].type to be "user"',
|
|
18509
|
-
command.requestType,
|
|
18510
|
-
`body.options.user_scope.${index}.type`,
|
|
18511
|
-
scope,
|
|
18512
|
-
command,
|
|
18513
|
-
env
|
|
18514
|
-
);
|
|
18515
|
-
}
|
|
18516
18510
|
if (typeof item.id !== "number" || !Number.isInteger(item.id) || item.id <= 0) {
|
|
18517
18511
|
throwBodyValidationFailure(
|
|
18518
|
-
"access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId",
|
|
18512
|
+
"access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID",
|
|
18519
18513
|
command.requestType,
|
|
18520
18514
|
`body.options.user_scope.${index}.id`,
|
|
18521
18515
|
scope,
|
|
@@ -19217,16 +19211,17 @@ async function executeCLI(scope, argv, env, fetchImpl = fetch) {
|
|
|
19217
19211
|
const message = parsedBody.error.issues.map((issue2) => `${issue2.path.join(".")}: ${issue2.message}`).join("; ");
|
|
19218
19212
|
if (isAssignUsersCommand(scope, command)) {
|
|
19219
19213
|
const hasUserScopeIDIssue = parsedBody.error.issues.some((issue2) => issue2.path.join(".") === "options.user_scope.0.id" || issue2.path.join(".").startsWith("options.user_scope."));
|
|
19214
|
+
const userScopeIDMessage = "access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID";
|
|
19220
19215
|
throw new CLIError(
|
|
19221
19216
|
"BODY_VALIDATION_FAILED",
|
|
19222
|
-
hasUserScopeIDIssue ?
|
|
19217
|
+
hasUserScopeIDIssue ? userScopeIDMessage : message,
|
|
19223
19218
|
2,
|
|
19224
19219
|
buildAssignUsersValidationDetails(
|
|
19225
19220
|
scope,
|
|
19226
19221
|
command,
|
|
19227
19222
|
command.requestType,
|
|
19228
19223
|
hasUserScopeIDIssue ? "body.options.user_scope" : "body",
|
|
19229
|
-
hasUserScopeIDIssue ?
|
|
19224
|
+
hasUserScopeIDIssue ? userScopeIDMessage : message,
|
|
19230
19225
|
runtimeEnv
|
|
19231
19226
|
)
|
|
19232
19227
|
);
|
package/bundle/arcubase.mjs
CHANGED
|
@@ -16081,7 +16081,7 @@ var AppCreateEntityReqVOSchema = external_exports.lazy(() => external_exports.ob
|
|
|
16081
16081
|
var I18NTextSchema = external_exports.lazy(() => external_exports.record(external_exports.string(), external_exports.string()));
|
|
16082
16082
|
var PermitColumnSchema = external_exports.lazy(() => external_exports.object({ "field_id": external_exports.number().optional(), "is_field": external_exports.boolean().optional(), "prop": external_exports.string().optional() }).strict());
|
|
16083
16083
|
var PermitSearchColumnSchema = external_exports.lazy(() => external_exports.object({ "default": external_exports.boolean().optional(), "default_value": external_exports.array(external_exports.number()).optional(), "field_id": external_exports.number().optional(), "infilter": external_exports.boolean().optional(), "is_field": external_exports.boolean().optional(), "pinned": external_exports.boolean().optional(), "prop": external_exports.string().optional(), "wildcard": external_exports.boolean().optional() }).strict());
|
|
16084
|
-
var PermitEntityPropSchema = external_exports.lazy(() => external_exports.
|
|
16084
|
+
var PermitEntityPropSchema = external_exports.lazy(() => external_exports.string().min(1));
|
|
16085
16085
|
var PermitValueFromSchema = external_exports.lazy(() => external_exports.union([external_exports.literal(1), external_exports.literal(2), external_exports.literal(3)]));
|
|
16086
16086
|
var PermitRecordConditionSchema = external_exports.lazy(() => external_exports.object({ "column": PermitEntityPropSchema.optional(), "operator": external_exports.string().optional(), "subset": PermitConditionSetSchema.optional(), "value": external_exports.any().optional(), "value_from": PermitValueFromSchema.optional(), "value_relation": PermitEntityPropSchema.optional() }).strict());
|
|
16087
16087
|
var PermitConditionSetSchema = external_exports.lazy(() => external_exports.object({ "conditions": external_exports.array(PermitRecordConditionSchema).optional(), "mode": external_exports.string().optional() }).strict());
|
|
@@ -17509,17 +17509,17 @@ function renderCommandHelp(scope, moduleName, commandName, env = process.env) {
|
|
|
17509
17509
|
` - hide field: ${JSON.stringify(buildHiddenFieldAccessRuleBody())}`,
|
|
17510
17510
|
"success requires:",
|
|
17511
17511
|
" - result.enabled must be true",
|
|
17512
|
-
' - options.user_scope[].type is "user"
|
|
17512
|
+
' - options.user_scope[].type is "user", "department", or "actor"',
|
|
17513
17513
|
' - hidden fields use colon field keys such as ":1002"'
|
|
17514
17514
|
] : [],
|
|
17515
17515
|
...scope === "admin" && command.commandPath[0] === "access-rule" && command.commandPath[1] === "assign-users" ? [
|
|
17516
17516
|
"body-json example:",
|
|
17517
|
-
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
17517
|
+
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
17518
17518
|
"success requires:",
|
|
17519
17519
|
" - result.enabled must be true",
|
|
17520
|
-
" - result.options.user_scope must contain
|
|
17521
|
-
" - PermitUserScope.id must be the numeric arcubaseUserId",
|
|
17522
|
-
" - Do not copy a non-numeric
|
|
17520
|
+
" - result.options.user_scope must contain every assigned user, department, or actor scope",
|
|
17521
|
+
" - PermitUserScope.id must be the numeric arcubaseUserId, department ID, or actor ID",
|
|
17522
|
+
" - Do not copy a non-numeric BotWorks userId into PermitUserScope.id",
|
|
17523
17523
|
" - If result.enabled is false, enable the rule first and retry assign-users"
|
|
17524
17524
|
] : [],
|
|
17525
17525
|
...scope === "admin" && command.commandPath[0] === "app" && command.commandPath[1] === "create-from-bundle-url" ? [
|
|
@@ -17990,14 +17990,18 @@ function buildAssignUsersValidationDetails(scope, command, requestType, path3, m
|
|
|
17990
17990
|
shapeHint: {
|
|
17991
17991
|
update: ["user_scope"],
|
|
17992
17992
|
options: {
|
|
17993
|
-
user_scope: [
|
|
17993
|
+
user_scope: [
|
|
17994
|
+
{ type: "user", id: 2188889901 },
|
|
17995
|
+
{ type: "department", id: 2188881201 },
|
|
17996
|
+
{ type: "actor", id: 2188883301 }
|
|
17997
|
+
]
|
|
17994
17998
|
}
|
|
17995
17999
|
},
|
|
17996
18000
|
commonMistakes: [
|
|
17997
18001
|
"do not use user_scope at top level",
|
|
17998
18002
|
"do not use users or allowedUsers",
|
|
17999
|
-
"do not use non-numeric
|
|
18000
|
-
"id must be the numeric arcubaseUserId"
|
|
18003
|
+
"do not use non-numeric BotWorks userId as id",
|
|
18004
|
+
"id must be the numeric arcubaseUserId, department ID, or actor ID"
|
|
18001
18005
|
]
|
|
18002
18006
|
};
|
|
18003
18007
|
}
|
|
@@ -18278,7 +18282,7 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
|
|
|
18278
18282
|
if (userScope === void 0) return;
|
|
18279
18283
|
if (!Array.isArray(userScope)) {
|
|
18280
18284
|
throwBodyValidationFailure(
|
|
18281
|
-
'access-rule user_scope must be an array of {"type":"user","id":2188889901}',
|
|
18285
|
+
'access-rule user_scope must be an array of {"type":"user","id":2188889901}, {"type":"department","id":2188881201}, or {"type":"actor","id":2188883301}',
|
|
18282
18286
|
requestType,
|
|
18283
18287
|
pathPrefix,
|
|
18284
18288
|
scope,
|
|
@@ -18341,7 +18345,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
|
|
|
18341
18345
|
if (isAssignUsersCommand(scope, command)) {
|
|
18342
18346
|
if ("users" in body || "allowedUsers" in body || "user_scope" in body) {
|
|
18343
18347
|
throwBodyValidationFailure(
|
|
18344
|
-
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
18348
|
+
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
18345
18349
|
command.requestType,
|
|
18346
18350
|
"body.options.user_scope",
|
|
18347
18351
|
scope,
|
|
@@ -18462,7 +18466,7 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
|
|
|
18462
18466
|
const userScope = options && Array.isArray(options.user_scope) ? options.user_scope : void 0;
|
|
18463
18467
|
if ("users" in body || "allowedUsers" in body) {
|
|
18464
18468
|
throwBodyValidationFailure(
|
|
18465
|
-
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
18469
|
+
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
18466
18470
|
command.requestType,
|
|
18467
18471
|
"body.options.user_scope",
|
|
18468
18472
|
scope,
|
|
@@ -18503,19 +18507,9 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
|
|
|
18503
18507
|
env
|
|
18504
18508
|
);
|
|
18505
18509
|
}
|
|
18506
|
-
if (item.type !== "user") {
|
|
18507
|
-
throwBodyValidationFailure(
|
|
18508
|
-
'access-rule assign-users requires body.options.user_scope[].type to be "user"',
|
|
18509
|
-
command.requestType,
|
|
18510
|
-
`body.options.user_scope.${index}.type`,
|
|
18511
|
-
scope,
|
|
18512
|
-
command,
|
|
18513
|
-
env
|
|
18514
|
-
);
|
|
18515
|
-
}
|
|
18516
18510
|
if (typeof item.id !== "number" || !Number.isInteger(item.id) || item.id <= 0) {
|
|
18517
18511
|
throwBodyValidationFailure(
|
|
18518
|
-
"access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId",
|
|
18512
|
+
"access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID",
|
|
18519
18513
|
command.requestType,
|
|
18520
18514
|
`body.options.user_scope.${index}.id`,
|
|
18521
18515
|
scope,
|
|
@@ -19217,16 +19211,17 @@ async function executeCLI(scope, argv, env, fetchImpl = fetch) {
|
|
|
19217
19211
|
const message = parsedBody.error.issues.map((issue2) => `${issue2.path.join(".")}: ${issue2.message}`).join("; ");
|
|
19218
19212
|
if (isAssignUsersCommand(scope, command)) {
|
|
19219
19213
|
const hasUserScopeIDIssue = parsedBody.error.issues.some((issue2) => issue2.path.join(".") === "options.user_scope.0.id" || issue2.path.join(".").startsWith("options.user_scope."));
|
|
19214
|
+
const userScopeIDMessage = "access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID";
|
|
19220
19215
|
throw new CLIError(
|
|
19221
19216
|
"BODY_VALIDATION_FAILED",
|
|
19222
|
-
hasUserScopeIDIssue ?
|
|
19217
|
+
hasUserScopeIDIssue ? userScopeIDMessage : message,
|
|
19223
19218
|
2,
|
|
19224
19219
|
buildAssignUsersValidationDetails(
|
|
19225
19220
|
scope,
|
|
19226
19221
|
command,
|
|
19227
19222
|
command.requestType,
|
|
19228
19223
|
hasUserScopeIDIssue ? "body.options.user_scope" : "body",
|
|
19229
|
-
hasUserScopeIDIssue ?
|
|
19224
|
+
hasUserScopeIDIssue ? userScopeIDMessage : message,
|
|
19230
19225
|
runtimeEnv
|
|
19231
19226
|
)
|
|
19232
19227
|
);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ArcubaseCliUserReference } from '../interface/user_identity.js';
|
|
2
|
+
export type ApiTenantUserReference = {
|
|
3
|
+
tenantUserId: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function toCliArcubaseUserId(input: ApiTenantUserReference): ArcubaseCliUserReference;
|
|
6
|
+
export declare function toApiTenantUserId(input: ArcubaseCliUserReference): ApiTenantUserReference;
|
|
7
|
+
//# sourceMappingURL=user_identity_adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user_identity_adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/user_identity_adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AAE7E,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,GAAG,wBAAwB,CAI3F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,wBAAwB,GAAG,sBAAsB,CAIzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod_registry.generated.d.ts","sourceRoot":"","sources":["../../src/generated/zod_registry.generated.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,6BAA6B,EAAE,CAAC,CAAC,UAAwJ,CAAA;AAEtM,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,UAAgH,CAAA;AAE3J,eAAO,MAAM,cAAc,EAAE,CAAC,CAAC,UAA2D,CAAA;AAE1F,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,UAAsJ,CAAA;AAEzL,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,UAAoV,CAAA;AAE7X,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"zod_registry.generated.d.ts","sourceRoot":"","sources":["../../src/generated/zod_registry.generated.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ export const AppCreateEntityReqVOSchema = z.lazy(() => z.object({ "name": z.stri
|
|
|
5
5
|
export const I18NTextSchema = z.lazy(() => z.record(z.string(), z.string()));
|
|
6
6
|
export const PermitColumnSchema = z.lazy(() => z.object({ "field_id": z.number().optional(), "is_field": z.boolean().optional(), "prop": z.string().optional() }).strict());
|
|
7
7
|
export const PermitSearchColumnSchema = z.lazy(() => z.object({ "default": z.boolean().optional(), "default_value": z.array(z.number()).optional(), "field_id": z.number().optional(), "infilter": z.boolean().optional(), "is_field": z.boolean().optional(), "pinned": z.boolean().optional(), "prop": z.string().optional(), "wildcard": z.boolean().optional() }).strict());
|
|
8
|
-
export const PermitEntityPropSchema = z.lazy(() => z.
|
|
8
|
+
export const PermitEntityPropSchema = z.lazy(() => z.string().min(1));
|
|
9
9
|
export const PermitValueFromSchema = z.lazy(() => z.union([z.literal(1), z.literal(2), z.literal(3)]));
|
|
10
10
|
export const PermitRecordConditionSchema = z.lazy(() => z.object({ "column": PermitEntityPropSchema.optional(), "operator": z.string().optional(), "subset": PermitConditionSetSchema.optional(), "value": z.any().optional(), "value_from": PermitValueFromSchema.optional(), "value_relation": PermitEntityPropSchema.optional() }).strict());
|
|
11
11
|
export const PermitConditionSetSchema = z.lazy(() => z.object({ "conditions": z.array(PermitRecordConditionSchema).optional(), "mode": z.string().optional() }).strict());
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interface/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ArcubaseUserId } from './user_identity.js';
|
|
2
|
+
export type ArcubaseCliDepartmentMember = {
|
|
3
|
+
arcubaseUserId: ArcubaseUserId;
|
|
4
|
+
name?: string;
|
|
5
|
+
departments?: string[];
|
|
6
|
+
roles?: string[];
|
|
7
|
+
};
|
|
8
|
+
export type ArcubaseCliRoleMember = {
|
|
9
|
+
arcubaseUserId: ArcubaseUserId;
|
|
10
|
+
name?: string;
|
|
11
|
+
departments?: string[];
|
|
12
|
+
roles?: string[];
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=organization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.d.ts","sourceRoot":"","sources":["../../src/interface/organization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAExD,MAAM,MAAM,2BAA2B,GAAG;IACxC,cAAc,EAAE,cAAc,CAAA;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,cAAc,EAAE,cAAc,CAAA;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type ArcubaseUserId = string;
|
|
2
|
+
export type ArcubaseCliUserIdentity = {
|
|
3
|
+
arcubaseUserId: ArcubaseUserId;
|
|
4
|
+
name?: string;
|
|
5
|
+
email?: string;
|
|
6
|
+
};
|
|
7
|
+
export type ArcubaseCliUserReference = {
|
|
8
|
+
arcubaseUserId: ArcubaseUserId;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=user_identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user_identity.d.ts","sourceRoot":"","sources":["../../src/interface/user_identity.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,CAAA;AAEnC,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,cAAc,CAAA;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,cAAc,EAAE,cAAc,CAAA;CAC/B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAOhJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAc1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AAOD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAMlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA6HpI;
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAyF,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAOhJ,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAc1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CAoB7G;AAOD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAMlD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,QAAsB,GAAG,MAAM,CA6HpI;AA8vDD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CA8MrI"}
|
package/dist/runtime/execute.js
CHANGED
|
@@ -113,19 +113,19 @@ export function renderCommandHelp(scope, moduleName, commandName, env = process.
|
|
|
113
113
|
` - hide field: ${JSON.stringify(buildHiddenFieldAccessRuleBody())}`,
|
|
114
114
|
'success requires:',
|
|
115
115
|
' - result.enabled must be true',
|
|
116
|
-
' - options.user_scope[].type is "user"
|
|
116
|
+
' - options.user_scope[].type is "user", "department", or "actor"',
|
|
117
117
|
' - hidden fields use colon field keys such as ":1002"',
|
|
118
118
|
]
|
|
119
119
|
: []),
|
|
120
120
|
...(scope === 'admin' && command.commandPath[0] === 'access-rule' && command.commandPath[1] === 'assign-users'
|
|
121
121
|
? [
|
|
122
122
|
'body-json example:',
|
|
123
|
-
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
123
|
+
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
124
124
|
'success requires:',
|
|
125
125
|
' - result.enabled must be true',
|
|
126
|
-
' - result.options.user_scope must contain
|
|
127
|
-
' - PermitUserScope.id must be the numeric arcubaseUserId',
|
|
128
|
-
' - Do not copy a non-numeric
|
|
126
|
+
' - result.options.user_scope must contain every assigned user, department, or actor scope',
|
|
127
|
+
' - PermitUserScope.id must be the numeric arcubaseUserId, department ID, or actor ID',
|
|
128
|
+
' - Do not copy a non-numeric BotWorks userId into PermitUserScope.id',
|
|
129
129
|
' - If result.enabled is false, enable the rule first and retry assign-users',
|
|
130
130
|
]
|
|
131
131
|
: []),
|
|
@@ -628,14 +628,18 @@ function buildAssignUsersValidationDetails(scope, command, requestType, path, me
|
|
|
628
628
|
shapeHint: {
|
|
629
629
|
update: ['user_scope'],
|
|
630
630
|
options: {
|
|
631
|
-
user_scope: [
|
|
631
|
+
user_scope: [
|
|
632
|
+
{ type: 'user', id: 2188889901 },
|
|
633
|
+
{ type: 'department', id: 2188881201 },
|
|
634
|
+
{ type: 'actor', id: 2188883301 },
|
|
635
|
+
],
|
|
632
636
|
},
|
|
633
637
|
},
|
|
634
638
|
commonMistakes: [
|
|
635
639
|
'do not use user_scope at top level',
|
|
636
640
|
'do not use users or allowedUsers',
|
|
637
|
-
'do not use non-numeric
|
|
638
|
-
'id must be the numeric arcubaseUserId',
|
|
641
|
+
'do not use non-numeric BotWorks userId as id',
|
|
642
|
+
'id must be the numeric arcubaseUserId, department ID, or actor ID',
|
|
639
643
|
],
|
|
640
644
|
};
|
|
641
645
|
}
|
|
@@ -895,7 +899,7 @@ function validateAccessRuleUserScope(scope, command, requestType, userScope, env
|
|
|
895
899
|
if (userScope === undefined)
|
|
896
900
|
return;
|
|
897
901
|
if (!Array.isArray(userScope)) {
|
|
898
|
-
throwBodyValidationFailure('access-rule user_scope must be an array of {"type":"user","id":2188889901}', requestType, pathPrefix, scope, command, env);
|
|
902
|
+
throwBodyValidationFailure('access-rule user_scope must be an array of {"type":"user","id":2188889901}, {"type":"department","id":2188881201}, or {"type":"actor","id":2188883301}', requestType, pathPrefix, scope, command, env);
|
|
899
903
|
}
|
|
900
904
|
const allowedTypes = new Set(['user', 'department', 'actor']);
|
|
901
905
|
for (const [index, item] of userScope.entries()) {
|
|
@@ -924,7 +928,7 @@ function validateActionSpecificRawBody(scope, command, body, env) {
|
|
|
924
928
|
}
|
|
925
929
|
if (isAssignUsersCommand(scope, command)) {
|
|
926
930
|
if ('users' in body || 'allowedUsers' in body || 'user_scope' in body) {
|
|
927
|
-
throwBodyValidationFailure('access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}', command.requestType, 'body.options.user_scope', scope, command, env);
|
|
931
|
+
throwBodyValidationFailure('access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}', command.requestType, 'body.options.user_scope', scope, command, env);
|
|
928
932
|
}
|
|
929
933
|
}
|
|
930
934
|
if (isTableSchemaCommand(scope, command)) {
|
|
@@ -983,7 +987,7 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
|
|
|
983
987
|
const options = isRecord(body.options) ? body.options : undefined;
|
|
984
988
|
const userScope = options && Array.isArray(options.user_scope) ? options.user_scope : undefined;
|
|
985
989
|
if ('users' in body || 'allowedUsers' in body) {
|
|
986
|
-
throwBodyValidationFailure('access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}', command.requestType, 'body.options.user_scope', scope, command, env);
|
|
990
|
+
throwBodyValidationFailure('access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}', command.requestType, 'body.options.user_scope', scope, command, env);
|
|
987
991
|
}
|
|
988
992
|
if (!update.includes('user_scope')) {
|
|
989
993
|
throwBodyValidationFailure('access-rule assign-users requires body.update to include "user_scope"', command.requestType, 'body.update', scope, command, env);
|
|
@@ -997,11 +1001,8 @@ function validateActionSpecificBody(scope, command, flags, body, env) {
|
|
|
997
1001
|
if (!isRecord(item)) {
|
|
998
1002
|
throwBodyValidationFailure('access-rule assign-users requires each body.options.user_scope item to be an object', command.requestType, `body.options.user_scope.${index}`, scope, command, env);
|
|
999
1003
|
}
|
|
1000
|
-
if (item.type !== 'user') {
|
|
1001
|
-
throwBodyValidationFailure('access-rule assign-users requires body.options.user_scope[].type to be "user"', command.requestType, `body.options.user_scope.${index}.type`, scope, command, env);
|
|
1002
|
-
}
|
|
1003
1004
|
if (typeof item.id !== 'number' || !Number.isInteger(item.id) || item.id <= 0) {
|
|
1004
|
-
throwBodyValidationFailure('access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId', command.requestType, `body.options.user_scope.${index}.id`, scope, command, env);
|
|
1005
|
+
throwBodyValidationFailure('access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID', command.requestType, `body.options.user_scope.${index}.id`, scope, command, env);
|
|
1005
1006
|
}
|
|
1006
1007
|
}
|
|
1007
1008
|
}
|
|
@@ -1714,7 +1715,8 @@ export async function executeCLI(scope, argv, env, fetchImpl = fetch) {
|
|
|
1714
1715
|
const message = parsedBody.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('; ');
|
|
1715
1716
|
if (isAssignUsersCommand(scope, command)) {
|
|
1716
1717
|
const hasUserScopeIDIssue = parsedBody.error.issues.some((issue) => issue.path.join('.') === 'options.user_scope.0.id' || issue.path.join('.').startsWith('options.user_scope.'));
|
|
1717
|
-
|
|
1718
|
+
const userScopeIDMessage = 'access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID';
|
|
1719
|
+
throw new CLIError('BODY_VALIDATION_FAILED', hasUserScopeIDIssue ? userScopeIDMessage : message, 2, buildAssignUsersValidationDetails(scope, command, command.requestType, hasUserScopeIDIssue ? 'body.options.user_scope' : 'body', hasUserScopeIDIssue ? userScopeIDMessage : message, runtimeEnv));
|
|
1718
1720
|
}
|
|
1719
1721
|
throw new CLIError('BODY_VALIDATION_FAILED', message, 2, buildBodyValidationDetails(scope, command, command.requestType, parsedBody.error.issues.map((issue) => ({
|
|
1720
1722
|
path: issue.path.length > 0 ? `body.${issue.path.join('.')}` : 'body',
|
package/package.json
CHANGED
|
@@ -4,9 +4,9 @@ Use `arcubase-admin access-rule` for app/table access.
|
|
|
4
4
|
|
|
5
5
|
## One Path
|
|
6
6
|
|
|
7
|
-
1. Get the numeric `arcubaseUserId
|
|
7
|
+
1. Get the numeric `arcubaseUserId`, department ID, or actor ID.
|
|
8
8
|
2. Create an enabled rule with `options.policy`.
|
|
9
|
-
3. Assign
|
|
9
|
+
3. Assign user scope with `options.user_scope`.
|
|
10
10
|
4. Verify with `access-rule get`.
|
|
11
11
|
|
|
12
12
|
## User Mapping
|
|
@@ -17,8 +17,8 @@ arcubase-admin get-digiemployee-users
|
|
|
17
17
|
|
|
18
18
|
Use the numeric `arcubaseUserId`.
|
|
19
19
|
|
|
20
|
-
Do not use non-numeric
|
|
21
|
-
Use `user_scope[].type:"user"` for a tenant user. Do not use FieldVO field type `member` in access rules.
|
|
20
|
+
Do not use non-numeric BotWorks user ids in `user_scope[].id`.
|
|
21
|
+
Use `user_scope[].type:"user"` for a tenant user, `type:"department"` for a department, and `type:"actor"` for a role/actor. Do not use FieldVO field type `member` in access rules.
|
|
22
22
|
|
|
23
23
|
## Body Input
|
|
24
24
|
|
|
@@ -90,7 +90,7 @@ Rules:
|
|
|
90
90
|
- field key is not the FieldVO `key`; do not use values like `vote_description`
|
|
91
91
|
- preserve `list_options:{}` unless the existing rule has a known replacement
|
|
92
92
|
|
|
93
|
-
## Assign
|
|
93
|
+
## Assign User Scope Only
|
|
94
94
|
|
|
95
95
|
Use this only when the rule already has the correct `policy`.
|
|
96
96
|
|
|
@@ -99,16 +99,18 @@ arcubase-admin access-rule assign-users \
|
|
|
99
99
|
--app-id 2188893436 \
|
|
100
100
|
--table-id 2188893443 \
|
|
101
101
|
--rule-id 2188893557 \
|
|
102
|
-
--body-json '{"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}'
|
|
102
|
+
--body-json '{"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}'
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
Rules:
|
|
106
106
|
|
|
107
|
-
- `assign-users` preserves the existing policy.
|
|
107
|
+
- `assign-users` preserves the existing policy and only replaces `options.user_scope`.
|
|
108
108
|
- body must use `update:["user_scope"]`.
|
|
109
109
|
- body must use `options.user_scope`.
|
|
110
|
-
- `user_scope[].type`
|
|
111
|
-
- `user_scope[].id`
|
|
110
|
+
- `user_scope[].type` must be `user`, `department`, or `actor`.
|
|
111
|
+
- `user_scope[].id` must be the numeric `arcubaseUserId`, department ID, or actor ID.
|
|
112
|
+
- Multiple scope items are OR: any matching user, department membership, or actor membership can use the ingress.
|
|
113
|
+
- Department scope includes child departments because Arcubase matches the user's department path.
|
|
112
114
|
|
|
113
115
|
## Verify
|
|
114
116
|
|
|
@@ -122,7 +124,7 @@ arcubase-admin access-rule get \
|
|
|
122
124
|
Success:
|
|
123
125
|
|
|
124
126
|
- `enabled=true`
|
|
125
|
-
- `options.user_scope` contains
|
|
127
|
+
- `options.user_scope` contains every expected `type/id` scope item
|
|
126
128
|
- `options.policy.actions` contains `view`, `add`, `edit`
|
|
127
129
|
- `options.policy.fields` contains hidden fields as `{"key":":1002","read":false,"write":false,"report":false}`
|
|
128
130
|
- visible fields are explicitly present with `read/write=true` when `all_fields_read/write=false`
|
|
@@ -12,7 +12,7 @@ export const PermitColumnSchema: z.ZodTypeAny = z.lazy(() => z.object({ "field_i
|
|
|
12
12
|
|
|
13
13
|
export const PermitSearchColumnSchema: z.ZodTypeAny = z.lazy(() => z.object({ "default": z.boolean().optional(), "default_value": z.array(z.number()).optional(), "field_id": z.number().optional(), "infilter": z.boolean().optional(), "is_field": z.boolean().optional(), "pinned": z.boolean().optional(), "prop": z.string().optional(), "wildcard": z.boolean().optional() }).strict())
|
|
14
14
|
|
|
15
|
-
export const PermitEntityPropSchema: z.ZodTypeAny = z.lazy(() => z.
|
|
15
|
+
export const PermitEntityPropSchema: z.ZodTypeAny = z.lazy(() => z.string().min(1))
|
|
16
16
|
|
|
17
17
|
export const PermitValueFromSchema: z.ZodTypeAny = z.lazy(() => z.union([z.literal(1), z.literal(2), z.literal(3)]))
|
|
18
18
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ArcubaseUserId } from './user_identity.js'
|
|
2
|
+
|
|
3
|
+
export type ArcubaseCliDepartmentMember = {
|
|
4
|
+
arcubaseUserId: ArcubaseUserId
|
|
5
|
+
name?: string
|
|
6
|
+
departments?: string[]
|
|
7
|
+
roles?: string[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ArcubaseCliRoleMember = {
|
|
11
|
+
arcubaseUserId: ArcubaseUserId
|
|
12
|
+
name?: string
|
|
13
|
+
departments?: string[]
|
|
14
|
+
roles?: string[]
|
|
15
|
+
}
|
package/sdk-dist/types/common.ts
CHANGED
|
@@ -291,6 +291,7 @@ export interface ActionBulkUpdateAction {
|
|
|
291
291
|
|
|
292
292
|
export interface KioskConfig {
|
|
293
293
|
interactiveMode?: string;
|
|
294
|
+
lookupCondition?: PermitConditionSet;
|
|
294
295
|
lookupFields?: number[];
|
|
295
296
|
options?: Record<string, any>;
|
|
296
297
|
printers?: Record<string, any>[];
|
package/sdk-dist/types/entity.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/** @format int32 */
|
|
14
|
-
import type { PermitEntityEvent, NotificationPayloadMode, NotificationNotificationType, MagicStringPartType, ActionBulkUpdate, ActionBulkUpdateAction, GormDeletedAt, KioskConfig, KioskScreen, AiOptions, ApiEndpoint, ApiEndpointParam, ApiOptions, App, AppOptions, Assets, Button, CustomAction, EntityFrontEvent, EntityKioskFlow, EntityOptions, EntityPrintTemplate, Fields, MagicString, MagicStringPart, PermitUserScope, ErrorResponse } from './common'
|
|
14
|
+
import type { PermitValueFrom, PermitEntityProp, PermitEntityEvent, NotificationPayloadMode, NotificationNotificationType, MagicStringPartType, ActionBulkUpdate, ActionBulkUpdateAction, GormDeletedAt, KioskConfig, KioskScreen, AiOptions, ApiEndpoint, ApiEndpointParam, ApiOptions, App, AppOptions, Assets, Button, CustomAction, EntityFrontEvent, EntityKioskFlow, EntityOptions, EntityPrintTemplate, Fields, MagicString, MagicStringPart, PermitConditionSet, PermitRecordCondition, PermitUserScope, ErrorResponse } from './common'
|
|
15
15
|
|
|
16
16
|
export enum FieldInitMode {
|
|
17
17
|
FieldInitModeStatic = 0,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/** @format int32 */
|
|
14
|
-
import type { WorkflowStateType, PermitEntityEvent, NotificationPayloadMode, NotificationNotificationType, PronounsType, MagicStringPartType, KioskConfig, KioskScreen, AiOptions, ApiEndpoint, ApiEndpointParam, ApiOptions, Button, CustomAction, DataRecord, EntityFrontEvent, EntityOptions, EntityVO, Fields, MagicString, MagicStringPart, DataRecordProcess, DataRecordResource, DataRecordTrans, PostqueryAppendData, PostqueryUserData, PostqueryAssetsData, PostqueryDepartmentData, PostqueryLinktoData, StorageUrlSets, ErrorResponse, OpenAPITenantInfo } from './common'
|
|
14
|
+
import type { WorkflowStateType, PermitValueFrom, PermitEntityProp, PermitEntityEvent, NotificationPayloadMode, NotificationNotificationType, PronounsType, MagicStringPartType, KioskConfig, KioskScreen, AiOptions, ApiEndpoint, ApiEndpointParam, ApiOptions, Button, CustomAction, DataRecord, EntityFrontEvent, EntityOptions, EntityVO, Fields, MagicString, MagicStringPart, DataRecordProcess, DataRecordResource, DataRecordTrans, PermitConditionSet, PermitRecordCondition, PostqueryAppendData, PostqueryUserData, PostqueryAssetsData, PostqueryDepartmentData, PostqueryLinktoData, StorageUrlSets, ErrorResponse, OpenAPITenantInfo } from './common'
|
|
15
15
|
|
|
16
16
|
export interface CheckPrintDuplicateReqVO {
|
|
17
17
|
/** kiosk flow id */
|
package/sdk-dist/types/tenant.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/** @format int32 */
|
|
14
|
-
import type { MagicStringPartType, GormDeletedAt, KioskConfig, KioskScreen, ApiEndpoint, ApiEndpointParam, EntityKioskFlow, MagicString, MagicStringPart, PermitUserScope, SqlNullTime, CommonPagination, ErrorResponse } from './common'
|
|
14
|
+
import type { PermitValueFrom, PermitEntityProp, MagicStringPartType, GormDeletedAt, KioskConfig, KioskScreen, ApiEndpoint, ApiEndpointParam, EntityKioskFlow, MagicString, MagicStringPart, PermitConditionSet, PermitRecordCondition, PermitUserScope, SqlNullTime, CommonPagination, ErrorResponse } from './common'
|
|
15
15
|
|
|
16
16
|
export enum TenantUserMetaDataPolicy {
|
|
17
17
|
TenantUserMetaDataPolicyNone = 1,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ArcubaseCliUserReference } from '../interface/user_identity.js'
|
|
2
|
+
|
|
3
|
+
export type ApiTenantUserReference = {
|
|
4
|
+
tenantUserId: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function toCliArcubaseUserId(input: ApiTenantUserReference): ArcubaseCliUserReference {
|
|
8
|
+
return {
|
|
9
|
+
arcubaseUserId: input.tenantUserId,
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function toApiTenantUserId(input: ArcubaseCliUserReference): ApiTenantUserReference {
|
|
14
|
+
return {
|
|
15
|
+
tenantUserId: input.arcubaseUserId,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -12,7 +12,7 @@ export const PermitColumnSchema: z.ZodTypeAny = z.lazy(() => z.object({ "field_i
|
|
|
12
12
|
|
|
13
13
|
export const PermitSearchColumnSchema: z.ZodTypeAny = z.lazy(() => z.object({ "default": z.boolean().optional(), "default_value": z.array(z.number()).optional(), "field_id": z.number().optional(), "infilter": z.boolean().optional(), "is_field": z.boolean().optional(), "pinned": z.boolean().optional(), "prop": z.string().optional(), "wildcard": z.boolean().optional() }).strict())
|
|
14
14
|
|
|
15
|
-
export const PermitEntityPropSchema: z.ZodTypeAny = z.lazy(() => z.
|
|
15
|
+
export const PermitEntityPropSchema: z.ZodTypeAny = z.lazy(() => z.string().min(1))
|
|
16
16
|
|
|
17
17
|
export const PermitValueFromSchema: z.ZodTypeAny = z.lazy(() => z.union([z.literal(1), z.literal(2), z.literal(3)]))
|
|
18
18
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ArcubaseUserId } from './user_identity.js'
|
|
2
|
+
|
|
3
|
+
export type ArcubaseCliDepartmentMember = {
|
|
4
|
+
arcubaseUserId: ArcubaseUserId
|
|
5
|
+
name?: string
|
|
6
|
+
departments?: string[]
|
|
7
|
+
roles?: string[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ArcubaseCliRoleMember = {
|
|
11
|
+
arcubaseUserId: ArcubaseUserId
|
|
12
|
+
name?: string
|
|
13
|
+
departments?: string[]
|
|
14
|
+
roles?: string[]
|
|
15
|
+
}
|
package/src/runtime/execute.ts
CHANGED
|
@@ -130,19 +130,19 @@ export function renderCommandHelp(scope: CommandScope, moduleName: string, comma
|
|
|
130
130
|
` - hide field: ${JSON.stringify(buildHiddenFieldAccessRuleBody())}`,
|
|
131
131
|
'success requires:',
|
|
132
132
|
' - result.enabled must be true',
|
|
133
|
-
' - options.user_scope[].type is "user"
|
|
133
|
+
' - options.user_scope[].type is "user", "department", or "actor"',
|
|
134
134
|
' - hidden fields use colon field keys such as ":1002"',
|
|
135
135
|
]
|
|
136
136
|
: []),
|
|
137
137
|
...(scope === 'admin' && command.commandPath[0] === 'access-rule' && command.commandPath[1] === 'assign-users'
|
|
138
138
|
? [
|
|
139
139
|
'body-json example:',
|
|
140
|
-
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
140
|
+
' - {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
141
141
|
'success requires:',
|
|
142
142
|
' - result.enabled must be true',
|
|
143
|
-
' - result.options.user_scope must contain
|
|
144
|
-
' - PermitUserScope.id must be the numeric arcubaseUserId',
|
|
145
|
-
' - Do not copy a non-numeric
|
|
143
|
+
' - result.options.user_scope must contain every assigned user, department, or actor scope',
|
|
144
|
+
' - PermitUserScope.id must be the numeric arcubaseUserId, department ID, or actor ID',
|
|
145
|
+
' - Do not copy a non-numeric BotWorks userId into PermitUserScope.id',
|
|
146
146
|
' - If result.enabled is false, enable the rule first and retry assign-users',
|
|
147
147
|
]
|
|
148
148
|
: []),
|
|
@@ -697,14 +697,18 @@ function buildAssignUsersValidationDetails(
|
|
|
697
697
|
shapeHint: {
|
|
698
698
|
update: ['user_scope'],
|
|
699
699
|
options: {
|
|
700
|
-
user_scope: [
|
|
700
|
+
user_scope: [
|
|
701
|
+
{ type: 'user', id: 2188889901 },
|
|
702
|
+
{ type: 'department', id: 2188881201 },
|
|
703
|
+
{ type: 'actor', id: 2188883301 },
|
|
704
|
+
],
|
|
701
705
|
},
|
|
702
706
|
},
|
|
703
707
|
commonMistakes: [
|
|
704
708
|
'do not use user_scope at top level',
|
|
705
709
|
'do not use users or allowedUsers',
|
|
706
|
-
'do not use non-numeric
|
|
707
|
-
'id must be the numeric arcubaseUserId',
|
|
710
|
+
'do not use non-numeric BotWorks userId as id',
|
|
711
|
+
'id must be the numeric arcubaseUserId, department ID, or actor ID',
|
|
708
712
|
],
|
|
709
713
|
}
|
|
710
714
|
}
|
|
@@ -1004,7 +1008,7 @@ function validateAccessRuleUserScope(
|
|
|
1004
1008
|
if (userScope === undefined) return
|
|
1005
1009
|
if (!Array.isArray(userScope)) {
|
|
1006
1010
|
throwBodyValidationFailure(
|
|
1007
|
-
|
|
1011
|
+
'access-rule user_scope must be an array of {"type":"user","id":2188889901}, {"type":"department","id":2188881201}, or {"type":"actor","id":2188883301}',
|
|
1008
1012
|
requestType,
|
|
1009
1013
|
pathPrefix,
|
|
1010
1014
|
scope,
|
|
@@ -1081,7 +1085,7 @@ function validateActionSpecificRawBody(
|
|
|
1081
1085
|
if (isAssignUsersCommand(scope, command)) {
|
|
1082
1086
|
if ('users' in body || 'allowedUsers' in body || 'user_scope' in body) {
|
|
1083
1087
|
throwBodyValidationFailure(
|
|
1084
|
-
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
1088
|
+
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
1085
1089
|
command.requestType,
|
|
1086
1090
|
'body.options.user_scope',
|
|
1087
1091
|
scope,
|
|
@@ -1213,7 +1217,7 @@ function validateActionSpecificBody(
|
|
|
1213
1217
|
const userScope = options && Array.isArray(options.user_scope) ? options.user_scope : undefined
|
|
1214
1218
|
if ('users' in body || 'allowedUsers' in body) {
|
|
1215
1219
|
throwBodyValidationFailure(
|
|
1216
|
-
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}',
|
|
1220
|
+
'access-rule assign-users only accepts body.options.user_scope with {"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}',
|
|
1217
1221
|
command.requestType,
|
|
1218
1222
|
'body.options.user_scope',
|
|
1219
1223
|
scope,
|
|
@@ -1254,19 +1258,9 @@ function validateActionSpecificBody(
|
|
|
1254
1258
|
env,
|
|
1255
1259
|
)
|
|
1256
1260
|
}
|
|
1257
|
-
if (item.type !== 'user') {
|
|
1258
|
-
throwBodyValidationFailure(
|
|
1259
|
-
'access-rule assign-users requires body.options.user_scope[].type to be "user"',
|
|
1260
|
-
command.requestType,
|
|
1261
|
-
`body.options.user_scope.${index}.type`,
|
|
1262
|
-
scope,
|
|
1263
|
-
command,
|
|
1264
|
-
env,
|
|
1265
|
-
)
|
|
1266
|
-
}
|
|
1267
1261
|
if (typeof item.id !== 'number' || !Number.isInteger(item.id) || item.id <= 0) {
|
|
1268
1262
|
throwBodyValidationFailure(
|
|
1269
|
-
'access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId',
|
|
1263
|
+
'access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID',
|
|
1270
1264
|
command.requestType,
|
|
1271
1265
|
`body.options.user_scope.${index}.id`,
|
|
1272
1266
|
scope,
|
|
@@ -2108,16 +2102,17 @@ export async function executeCLI(scope: CommandScope, argv: string[], env?: Runt
|
|
|
2108
2102
|
const message = parsedBody.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('; ')
|
|
2109
2103
|
if (isAssignUsersCommand(scope, command)) {
|
|
2110
2104
|
const hasUserScopeIDIssue = parsedBody.error.issues.some((issue) => issue.path.join('.') === 'options.user_scope.0.id' || issue.path.join('.').startsWith('options.user_scope.'))
|
|
2105
|
+
const userScopeIDMessage = 'access-rule assign-users requires body.options.user_scope[].id to be numeric arcubaseUserId, department ID, or actor ID'
|
|
2111
2106
|
throw new CLIError(
|
|
2112
2107
|
'BODY_VALIDATION_FAILED',
|
|
2113
|
-
hasUserScopeIDIssue ?
|
|
2108
|
+
hasUserScopeIDIssue ? userScopeIDMessage : message,
|
|
2114
2109
|
2,
|
|
2115
2110
|
buildAssignUsersValidationDetails(
|
|
2116
2111
|
scope,
|
|
2117
2112
|
command,
|
|
2118
2113
|
command.requestType,
|
|
2119
2114
|
hasUserScopeIDIssue ? 'body.options.user_scope' : 'body',
|
|
2120
|
-
hasUserScopeIDIssue ?
|
|
2115
|
+
hasUserScopeIDIssue ? userScopeIDMessage : message,
|
|
2121
2116
|
runtimeEnv,
|
|
2122
2117
|
)
|
|
2123
2118
|
)
|
|
@@ -55,14 +55,18 @@ function assertAssignUsersGuidance(error: unknown, messagePattern?: RegExp): boo
|
|
|
55
55
|
assert.deepEqual(error.details?.shapeHint, {
|
|
56
56
|
update: ['user_scope'],
|
|
57
57
|
options: {
|
|
58
|
-
user_scope: [
|
|
58
|
+
user_scope: [
|
|
59
|
+
{ type: 'user', id: 2188889901 },
|
|
60
|
+
{ type: 'department', id: 2188881201 },
|
|
61
|
+
{ type: 'actor', id: 2188883301 },
|
|
62
|
+
],
|
|
59
63
|
},
|
|
60
64
|
})
|
|
61
65
|
assert.deepEqual(error.details?.commonMistakes, [
|
|
62
66
|
'do not use user_scope at top level',
|
|
63
67
|
'do not use users or allowedUsers',
|
|
64
|
-
'do not use non-numeric
|
|
65
|
-
'id must be the numeric arcubaseUserId',
|
|
68
|
+
'do not use non-numeric BotWorks userId as id',
|
|
69
|
+
'id must be the numeric arcubaseUserId, department ID, or actor ID',
|
|
66
70
|
])
|
|
67
71
|
assert.ok(error.details?.tsHints?.some((item) => item.symbol === 'AppIngressUpdateReqVO' && item.file === '/runtime/arcubase-sdk/types/ingress.ts'))
|
|
68
72
|
assert.ok(error.details?.tsHints?.some((item) => item.symbol === 'EntityIngressOptions' && item.file === '/runtime/arcubase-sdk/types/ingress.ts'))
|
|
@@ -1318,7 +1322,7 @@ test('access-rule assign-users rejects top-level user_scope', async () => {
|
|
|
1318
1322
|
}, (error: unknown) => assertAssignUsersGuidance(error, /options.user_scope/))
|
|
1319
1323
|
})
|
|
1320
1324
|
|
|
1321
|
-
test('access-rule assign-users rejects
|
|
1325
|
+
test('access-rule assign-users rejects FieldVO member scope type', async () => {
|
|
1322
1326
|
await assert.rejects(async () => {
|
|
1323
1327
|
await executeCLI(
|
|
1324
1328
|
'admin',
|
|
@@ -1326,10 +1330,10 @@ test('access-rule assign-users rejects non-user member scope type', async () =>
|
|
|
1326
1330
|
env as any,
|
|
1327
1331
|
async () => new Response('{}', { status: 200 }),
|
|
1328
1332
|
)
|
|
1329
|
-
}, (error: unknown) => assertAssignUsersGuidance(error, /type
|
|
1333
|
+
}, (error: unknown) => assertAssignUsersGuidance(error, /user.*department.*actor|FieldVO type "member"/))
|
|
1330
1334
|
})
|
|
1331
1335
|
|
|
1332
|
-
test('access-rule assign-users rejects non-numeric
|
|
1336
|
+
test('access-rule assign-users rejects non-numeric user scope id', async () => {
|
|
1333
1337
|
await assert.rejects(async () => {
|
|
1334
1338
|
await executeCLI(
|
|
1335
1339
|
'admin',
|
|
@@ -1337,17 +1341,64 @@ test('access-rule assign-users rejects non-numeric arcubaseUserId', async () =>
|
|
|
1337
1341
|
env as any,
|
|
1338
1342
|
async () => new Response('{}', { status: 200 }),
|
|
1339
1343
|
)
|
|
1340
|
-
}, (error: unknown) => assertAssignUsersGuidance(error, /numeric arcubaseUserId/))
|
|
1344
|
+
}, (error: unknown) => assertAssignUsersGuidance(error, /numeric arcubaseUserId, department ID, or actor ID/))
|
|
1341
1345
|
})
|
|
1342
1346
|
|
|
1343
|
-
test('access-rule assign-users accepts canonical user_scope body', async () => {
|
|
1347
|
+
test('access-rule assign-users accepts canonical mixed user_scope body', async () => {
|
|
1344
1348
|
const out = await executeCLI(
|
|
1345
1349
|
'admin',
|
|
1346
|
-
['access-rule', 'assign-users', '--app-id', 'app_1', '--table-id', 'table_1', '--rule-id', 'rule_1', '--body-json', '{"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901}]}}'],
|
|
1350
|
+
['access-rule', 'assign-users', '--app-id', 'app_1', '--table-id', 'table_1', '--rule-id', 'rule_1', '--body-json', '{"update":["user_scope"],"options":{"user_scope":[{"type":"user","id":2188889901},{"type":"department","id":2188881201},{"type":"actor","id":2188883301}]}}'],
|
|
1347
1351
|
env as any,
|
|
1348
1352
|
async (_url, init) => new Response(String(init?.body ?? '{}'), { status: 200 }),
|
|
1349
1353
|
)
|
|
1350
1354
|
assert.equal(out.kind, 'result')
|
|
1351
1355
|
assert.deepEqual(out.data.update, ['user_scope'])
|
|
1352
|
-
assert.deepEqual(out.data.options.user_scope, [
|
|
1356
|
+
assert.deepEqual(out.data.options.user_scope, [
|
|
1357
|
+
{ type: 'user', id: 2188889901 },
|
|
1358
|
+
{ type: 'department', id: 2188881201 },
|
|
1359
|
+
{ type: 'actor', id: 2188883301 },
|
|
1360
|
+
])
|
|
1361
|
+
})
|
|
1362
|
+
|
|
1363
|
+
test('access-rule create accepts nested custom policy condition with field columns', async () => {
|
|
1364
|
+
const body = JSON.stringify({
|
|
1365
|
+
name: 'Sales own or west region',
|
|
1366
|
+
enabled: true,
|
|
1367
|
+
type: 'form',
|
|
1368
|
+
options: {
|
|
1369
|
+
user_scope: [{ type: 'department', id: 2188881201 }],
|
|
1370
|
+
policy: {
|
|
1371
|
+
key: 'custom',
|
|
1372
|
+
actions: ['view', 'add', 'edit'],
|
|
1373
|
+
all_fields_read: true,
|
|
1374
|
+
all_fields_write: true,
|
|
1375
|
+
condition: {
|
|
1376
|
+
mode: 'and',
|
|
1377
|
+
conditions: [
|
|
1378
|
+
{
|
|
1379
|
+
subset: {
|
|
1380
|
+
mode: 'or',
|
|
1381
|
+
conditions: [
|
|
1382
|
+
{ column: 'creator', operator: '$eq', value: '[[current_user]]' },
|
|
1383
|
+
{ column: ':1002', operator: '$eq', value: '[[current_user]]' },
|
|
1384
|
+
],
|
|
1385
|
+
},
|
|
1386
|
+
},
|
|
1387
|
+
{ column: ':1003', operator: '$eq', value: '华东' },
|
|
1388
|
+
],
|
|
1389
|
+
},
|
|
1390
|
+
},
|
|
1391
|
+
list_options: {},
|
|
1392
|
+
},
|
|
1393
|
+
})
|
|
1394
|
+
const out = await executeCLI(
|
|
1395
|
+
'admin',
|
|
1396
|
+
['access-rule', 'create', '--app-id', 'app_1', '--table-id', 'table_1', '--body-json', body],
|
|
1397
|
+
env as any,
|
|
1398
|
+
async (_url, init) => new Response(String(init?.body ?? '{}'), { status: 200 }),
|
|
1399
|
+
)
|
|
1400
|
+
assert.equal(out.kind, 'result')
|
|
1401
|
+
assert.equal(out.data.options.policy.condition.mode, 'and')
|
|
1402
|
+
assert.equal(out.data.options.policy.condition.conditions[0].subset.mode, 'or')
|
|
1403
|
+
assert.equal(out.data.options.policy.condition.conditions[0].subset.conditions[1].column, ':1002')
|
|
1353
1404
|
})
|
package/src/tests/help.test.ts
CHANGED
|
@@ -120,8 +120,10 @@ test('admin access-rule help gives update whitelist and assign-users body-json e
|
|
|
120
120
|
const assign = await executeCLI('admin', ['access-rule', 'assign-users', '--help'], env as any, async () => new Response('{}'))
|
|
121
121
|
assert.equal(assign.kind, 'help')
|
|
122
122
|
assert.match(assign.text, /"update":\["user_scope"\]/)
|
|
123
|
-
assert.match(assign.text, /\{"update":\["user_scope"\],"options":\{"user_scope":\[\{"type":"user","id":2188889901\}\]\}\}/)
|
|
123
|
+
assert.match(assign.text, /\{"update":\["user_scope"\],"options":\{"user_scope":\[\{"type":"user","id":2188889901\},\{"type":"department","id":2188881201\},\{"type":"actor","id":2188883301\}\]\}\}/)
|
|
124
124
|
assert.match(assign.text, /arcubaseUserId/)
|
|
125
|
+
assert.match(assign.text, /department ID/)
|
|
126
|
+
assert.match(assign.text, /actor ID/)
|
|
125
127
|
assert.doesNotMatch(assign.text, forbiddenArcubaseUserTerms())
|
|
126
128
|
assert.doesNotMatch(assign.text, /"type":"member"/)
|
|
127
129
|
assert.doesNotMatch(assign.text, /"users"/)
|
|
@@ -135,6 +137,16 @@ test('admin assign-users help uses arcubaseUserId terminology', async () => {
|
|
|
135
137
|
assert.match(help.text, /arcubaseUserId/)
|
|
136
138
|
})
|
|
137
139
|
|
|
140
|
+
test('CLI help does not expose tenantUserId', async () => {
|
|
141
|
+
for (const scope of ['admin', 'user'] as const satisfies readonly CommandScope[]) {
|
|
142
|
+
for (const command of listCommands(scope)) {
|
|
143
|
+
const out = await executeCLI(scope, [...command.commandPath, '--help'], env as any, async () => new Response('{}'))
|
|
144
|
+
assert.equal(out.kind, 'help')
|
|
145
|
+
assert.doesNotMatch(out.text, /tenantUserId/)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
138
150
|
function forbiddenArcubaseUserTerms(): RegExp {
|
|
139
151
|
return new RegExp(['tenant' + 'UserId', 'TenantUser' + String.raw`\.ID`, 'tenant user' + ' id'].join('|'), 'i')
|
|
140
152
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import test from 'node:test'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { toApiTenantUserId, toCliArcubaseUserId } from '../adapters/user_identity_adapter.js'
|
|
7
|
+
|
|
8
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..')
|
|
9
|
+
|
|
10
|
+
function walk(dir: string): string[] {
|
|
11
|
+
if (!fs.existsSync(dir)) return []
|
|
12
|
+
const out: string[] = []
|
|
13
|
+
for (const name of fs.readdirSync(dir)) {
|
|
14
|
+
const abs = path.join(dir, name)
|
|
15
|
+
const stat = fs.statSync(abs)
|
|
16
|
+
if (stat.isDirectory()) {
|
|
17
|
+
out.push(...walk(abs))
|
|
18
|
+
} else if (stat.isFile() && /\.(ts|md|js|mjs)$/.test(name)) {
|
|
19
|
+
out.push(abs)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return out
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test('CLI interface types do not expose tenantUserId', () => {
|
|
26
|
+
const files = walk(path.join(packageRoot, 'src/interface'))
|
|
27
|
+
assert.ok(files.length > 0)
|
|
28
|
+
for (const file of files) {
|
|
29
|
+
assert.equal(fs.readFileSync(file, 'utf8').includes('tenantUserId'), false, file)
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('CLI adapter maps tenantUserId to arcubaseUserId', () => {
|
|
34
|
+
assert.deepEqual(toCliArcubaseUserId({ tenantUserId: '2188890296' }), {
|
|
35
|
+
arcubaseUserId: '2188890296',
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('CLI adapter maps arcubaseUserId to tenantUserId', () => {
|
|
40
|
+
assert.deepEqual(toApiTenantUserId({ arcubaseUserId: '2188890296' }), {
|
|
41
|
+
tenantUserId: '2188890296',
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -41,6 +41,44 @@ test('EntityQueryReqVO search only accepts route-query string keys', () => {
|
|
|
41
41
|
}
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
+
test('AppIngressCreateReqVO accepts nested ConditionSet with field EntityProp columns', () => {
|
|
45
|
+
const schema = getBodySchema('AppIngressCreateReqVO')
|
|
46
|
+
assert.ok(schema)
|
|
47
|
+
|
|
48
|
+
const result = schema.safeParse({
|
|
49
|
+
name: 'Sales own or west region',
|
|
50
|
+
enabled: true,
|
|
51
|
+
type: 'form',
|
|
52
|
+
options: {
|
|
53
|
+
user_scope: [{ type: 'department', id: 2188881201 }],
|
|
54
|
+
policy: {
|
|
55
|
+
key: 'custom',
|
|
56
|
+
actions: ['view', 'add', 'edit'],
|
|
57
|
+
all_fields_read: true,
|
|
58
|
+
all_fields_write: true,
|
|
59
|
+
condition: {
|
|
60
|
+
mode: 'and',
|
|
61
|
+
conditions: [
|
|
62
|
+
{
|
|
63
|
+
subset: {
|
|
64
|
+
mode: 'or',
|
|
65
|
+
conditions: [
|
|
66
|
+
{ column: 'creator', operator: '$eq', value: '[[current_user]]' },
|
|
67
|
+
{ column: ':1002', operator: '$eq', value: '[[current_user]]' },
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{ column: ':1003', operator: '$eq', value: '华东' },
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
list_options: {},
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
assert.equal(result.success, true)
|
|
80
|
+
})
|
|
81
|
+
|
|
44
82
|
test('unknown request type has no schema and no unsupported reason', () => {
|
|
45
83
|
assert.equal(getBodySchema('DefinitelyMissingReqVO'), null)
|
|
46
84
|
assert.equal(getUnsupportedBodySchemaReason('DefinitelyMissingReqVO'), null)
|