@open-mercato/shared 0.6.8-develop.7048.1.b011912b63 → 0.6.8-develop.7049.1.b41427429a
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/lib/auth/organizationAccess.js +7 -4
- package/dist/lib/auth/organizationAccess.js.map +2 -2
- package/dist/lib/version.js +1 -1
- package/dist/lib/version.js.map +1 -1
- package/package.json +2 -2
- package/src/lib/auth/__tests__/organizationAccess.test.ts +36 -1
- package/src/lib/auth/organizationAccess.ts +11 -3
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
function isUnrestrictedOrganizationScope(input) {
|
|
2
|
+
return input.isSuperAdmin || input.allowedOrganizationIds === null;
|
|
3
|
+
}
|
|
1
4
|
function isOrganizationAccessAllowed(input) {
|
|
2
|
-
if (input
|
|
3
|
-
if (input.allowedOrganizationIds === null) return true;
|
|
5
|
+
if (isUnrestrictedOrganizationScope(input)) return true;
|
|
4
6
|
if (!input.targetOrganizationId) return false;
|
|
5
|
-
return input.allowedOrganizationIds.includes(input.targetOrganizationId);
|
|
7
|
+
return (input.allowedOrganizationIds ?? []).includes(input.targetOrganizationId);
|
|
6
8
|
}
|
|
7
9
|
export {
|
|
8
|
-
isOrganizationAccessAllowed
|
|
10
|
+
isOrganizationAccessAllowed,
|
|
11
|
+
isUnrestrictedOrganizationScope
|
|
9
12
|
};
|
|
10
13
|
//# sourceMappingURL=organizationAccess.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/auth/organizationAccess.ts"],
|
|
4
|
-
"sourcesContent": ["export type OrganizationAccessDecisionInput = {\n isSuperAdmin: boolean\n allowedOrganizationIds: readonly string[] | null\n targetOrganizationId: string | null\n}\n\n/**\n * Fail-closed organization-access predicate. The single source of truth for\n * \"may this principal act on `targetOrganizationId`\".\n *\n * Decision table:\n * - `isSuperAdmin === true` -> allow (global access)\n * - `allowedOrganizationIds === null` -> allow (truly unrestricted)\n * - restricted + no target org -> deny (empty/unknown scope is not a bypass)\n * - restricted + target org -> allow iff the target is a member of the allowed set\n */\nexport function isOrganizationAccessAllowed(input: OrganizationAccessDecisionInput): boolean {\n if (
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["export type OrganizationAccessDecisionInput = {\n isSuperAdmin: boolean\n allowedOrganizationIds: readonly string[] | null\n targetOrganizationId: string | null\n}\n\nexport type UnrestrictedOrganizationScopeInput = {\n isSuperAdmin: boolean\n allowedOrganizationIds: readonly string[] | null | undefined\n}\n\nexport function isUnrestrictedOrganizationScope(input: UnrestrictedOrganizationScopeInput): boolean {\n return input.isSuperAdmin || input.allowedOrganizationIds === null\n}\n\n/**\n * Fail-closed organization-access predicate. The single source of truth for\n * \"may this principal act on `targetOrganizationId`\".\n *\n * Decision table:\n * - `isSuperAdmin === true` -> allow (global access)\n * - `allowedOrganizationIds === null` -> allow (truly unrestricted)\n * - restricted + no target org -> deny (empty/unknown scope is not a bypass)\n * - restricted + target org -> allow iff the target is a member of the allowed set\n */\nexport function isOrganizationAccessAllowed(input: OrganizationAccessDecisionInput): boolean {\n if (isUnrestrictedOrganizationScope(input)) return true\n if (!input.targetOrganizationId) return false\n return (input.allowedOrganizationIds ?? []).includes(input.targetOrganizationId)\n}\n"],
|
|
5
|
+
"mappings": "AAWO,SAAS,gCAAgC,OAAoD;AAClG,SAAO,MAAM,gBAAgB,MAAM,2BAA2B;AAChE;AAYO,SAAS,4BAA4B,OAAiD;AAC3F,MAAI,gCAAgC,KAAK,EAAG,QAAO;AACnD,MAAI,CAAC,MAAM,qBAAsB,QAAO;AACxC,UAAQ,MAAM,0BAA0B,CAAC,GAAG,SAAS,MAAM,oBAAoB;AACjF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/lib/version.js
CHANGED
package/dist/lib/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/version.ts"],
|
|
4
|
-
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.6.8-develop.
|
|
4
|
+
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.6.8-develop.7049.1.b41427429a';\nexport const appVersion = APP_VERSION;\n"],
|
|
5
5
|
"mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/shared",
|
|
3
|
-
"version": "0.6.8-develop.
|
|
3
|
+
"version": "0.6.8-develop.7049.1.b41427429a",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"@mikro-orm/core": "^7.1.8",
|
|
110
110
|
"@mikro-orm/decorators": "^7.1.8",
|
|
111
111
|
"@mikro-orm/postgresql": "^7.1.8",
|
|
112
|
-
"@open-mercato/cache": "0.6.8-develop.
|
|
112
|
+
"@open-mercato/cache": "0.6.8-develop.7049.1.b41427429a",
|
|
113
113
|
"@types/html-to-text": "^9.0.4",
|
|
114
114
|
"@types/sanitize-html": "^2.16.1",
|
|
115
115
|
"dotenv": "^17.4.2",
|
|
@@ -1,4 +1,39 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isOrganizationAccessAllowed,
|
|
3
|
+
isUnrestrictedOrganizationScope,
|
|
4
|
+
} from '@open-mercato/shared/lib/auth/organizationAccess'
|
|
5
|
+
|
|
6
|
+
describe('isUnrestrictedOrganizationScope', () => {
|
|
7
|
+
it('allows super admins regardless of allowed organizations', () => {
|
|
8
|
+
expect(
|
|
9
|
+
isUnrestrictedOrganizationScope({
|
|
10
|
+
isSuperAdmin: true,
|
|
11
|
+
allowedOrganizationIds: [],
|
|
12
|
+
}),
|
|
13
|
+
).toBe(true)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('allows truly unrestricted non-superadmin scopes', () => {
|
|
17
|
+
expect(
|
|
18
|
+
isUnrestrictedOrganizationScope({
|
|
19
|
+
isSuperAdmin: false,
|
|
20
|
+
allowedOrganizationIds: null,
|
|
21
|
+
}),
|
|
22
|
+
).toBe(true)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it.each([undefined, [] as string[], ['org-a']])(
|
|
26
|
+
'denies restricted non-superadmin scopes with allowedOrganizationIds=%p',
|
|
27
|
+
(allowedOrganizationIds) => {
|
|
28
|
+
expect(
|
|
29
|
+
isUnrestrictedOrganizationScope({
|
|
30
|
+
isSuperAdmin: false,
|
|
31
|
+
allowedOrganizationIds,
|
|
32
|
+
}),
|
|
33
|
+
).toBe(false)
|
|
34
|
+
},
|
|
35
|
+
)
|
|
36
|
+
})
|
|
2
37
|
|
|
3
38
|
describe('isOrganizationAccessAllowed', () => {
|
|
4
39
|
it('allows super admins regardless of scope', () => {
|
|
@@ -4,6 +4,15 @@ export type OrganizationAccessDecisionInput = {
|
|
|
4
4
|
targetOrganizationId: string | null
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
export type UnrestrictedOrganizationScopeInput = {
|
|
8
|
+
isSuperAdmin: boolean
|
|
9
|
+
allowedOrganizationIds: readonly string[] | null | undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function isUnrestrictedOrganizationScope(input: UnrestrictedOrganizationScopeInput): boolean {
|
|
13
|
+
return input.isSuperAdmin || input.allowedOrganizationIds === null
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
/**
|
|
8
17
|
* Fail-closed organization-access predicate. The single source of truth for
|
|
9
18
|
* "may this principal act on `targetOrganizationId`".
|
|
@@ -15,8 +24,7 @@ export type OrganizationAccessDecisionInput = {
|
|
|
15
24
|
* - restricted + target org -> allow iff the target is a member of the allowed set
|
|
16
25
|
*/
|
|
17
26
|
export function isOrganizationAccessAllowed(input: OrganizationAccessDecisionInput): boolean {
|
|
18
|
-
if (input
|
|
19
|
-
if (input.allowedOrganizationIds === null) return true
|
|
27
|
+
if (isUnrestrictedOrganizationScope(input)) return true
|
|
20
28
|
if (!input.targetOrganizationId) return false
|
|
21
|
-
return input.allowedOrganizationIds.includes(input.targetOrganizationId)
|
|
29
|
+
return (input.allowedOrganizationIds ?? []).includes(input.targetOrganizationId)
|
|
22
30
|
}
|