@lobb-js/lobb-ext-auth 0.16.0 → 0.16.1
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/index.js +4 -2
- package/extensions/auth/studio/index.ts +3 -2
- package/extensions/auth/workflows/permissions.ts +37 -0
- package/extensions/auth/workflows/utils.ts +1 -1
- package/package.json +4 -3
- package/dist/shared/permissions.d.ts +0 -2
- package/dist/shared/permissions.js +0 -35
- package/extensions/auth/studio/shared/permissions.ts +0 -42
package/dist/index.js
CHANGED
|
@@ -3,7 +3,6 @@ import { onStartup, onRouteChange } from "./onStartup";
|
|
|
3
3
|
import LoginPage from "./lib/components/pages/loginPage/index.svelte";
|
|
4
4
|
import UserSettings from "./lib/components/pages/userSettings/index.svelte";
|
|
5
5
|
import Settings from "./lib/components/pages/settings/index.svelte";
|
|
6
|
-
import { isActionAllowed } from "./shared/permissions";
|
|
7
6
|
// TODO we should export the extension object directly without a function at all. because we dont set configuration in here
|
|
8
7
|
export default function extension(utils) {
|
|
9
8
|
return {
|
|
@@ -44,7 +43,10 @@ export default function extension(utils) {
|
|
|
44
43
|
? input.collection
|
|
45
44
|
: input.collection ? [input.collection] : [];
|
|
46
45
|
for (const collectionName of requiredCollections) {
|
|
47
|
-
|
|
46
|
+
const collPerm = permissions[collectionName];
|
|
47
|
+
if (collPerm === true)
|
|
48
|
+
continue;
|
|
49
|
+
if (!collPerm || collPerm[action] !== true) {
|
|
48
50
|
return ctx.takeOver(false);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
@@ -4,7 +4,6 @@ import { onStartup, onRouteChange } from "./onStartup";
|
|
|
4
4
|
import LoginPage from "./lib/components/pages/loginPage/index.svelte";
|
|
5
5
|
import UserSettings from "./lib/components/pages/userSettings/index.svelte";
|
|
6
6
|
import Settings from "./lib/components/pages/settings/index.svelte";
|
|
7
|
-
import { isActionAllowed } from "./shared/permissions";
|
|
8
7
|
import type { CollectionPermissionActionsKeys } from "../config/extensionConfigSchema";
|
|
9
8
|
|
|
10
9
|
// TODO we should export the extension object directly without a function at all. because we dont set configuration in here
|
|
@@ -48,7 +47,9 @@ export default function extension(utils: ExtensionUtils): Extension {
|
|
|
48
47
|
: input.collection ? [input.collection] : [];
|
|
49
48
|
|
|
50
49
|
for (const collectionName of requiredCollections) {
|
|
51
|
-
|
|
50
|
+
const collPerm = permissions[collectionName];
|
|
51
|
+
if (collPerm === true) continue;
|
|
52
|
+
if (!collPerm || collPerm[action] !== true) {
|
|
52
53
|
return ctx.takeOver(false);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CollectionPermissionActionsKeys,
|
|
3
|
+
PermissionsConfig,
|
|
4
|
+
} from "../config/extensionConfigSchema.ts";
|
|
5
|
+
|
|
6
|
+
// Pure permission check used by the backend's `handlePolicy` (see utils.ts) to
|
|
7
|
+
// gate collection actions. Walks the permissions tree and returns a yes/no;
|
|
8
|
+
// handlePolicy then layers on the actual guards/filters/error-throwing.
|
|
9
|
+
//
|
|
10
|
+
// It used to live under studio/shared/ because the studio's `auth.canAccess`
|
|
11
|
+
// workflow imported it too — now the studio inlines its own UI-gating check, so
|
|
12
|
+
// this is backend-only.
|
|
13
|
+
//
|
|
14
|
+
// An object value for an action means "conditional access" (filter / fields
|
|
15
|
+
// restrictions), which counts as allowed here; the real restriction is enforced
|
|
16
|
+
// per-request by handlePolicy.
|
|
17
|
+
export function isActionAllowed(
|
|
18
|
+
collection: string,
|
|
19
|
+
action: CollectionPermissionActionsKeys,
|
|
20
|
+
permissions: PermissionsConfig | undefined,
|
|
21
|
+
): boolean {
|
|
22
|
+
if (permissions === true) return true;
|
|
23
|
+
if (!permissions) return false;
|
|
24
|
+
const collPerm = permissions[collection];
|
|
25
|
+
if (collPerm === true) return true;
|
|
26
|
+
if (!collPerm) return false;
|
|
27
|
+
const actionPerm = collPerm[action];
|
|
28
|
+
if (actionPerm === true) return true;
|
|
29
|
+
// A conditional grant must actually list at least one constraint
|
|
30
|
+
// (filter / fields / payloadGuard / mutate). Empty `{}` collapses back
|
|
31
|
+
// to "no grant" — explicit `true` is required for unconditional access.
|
|
32
|
+
return (
|
|
33
|
+
typeof actionPerm === "object" &&
|
|
34
|
+
actionPerm !== null &&
|
|
35
|
+
Object.keys(actionPerm).length > 0
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
PermissionsConfig,
|
|
7
7
|
User,
|
|
8
8
|
} from "../config/extensionConfigSchema.ts";
|
|
9
|
-
import { isActionAllowed } from "
|
|
9
|
+
import { isActionAllowed } from "./permissions.ts";
|
|
10
10
|
|
|
11
11
|
interface HandlePolicyOutput {
|
|
12
12
|
filter?: Filter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobb-js/lobb-ext-auth",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"test": "bun test tests",
|
|
22
22
|
"test:lobb": "bun test tests",
|
|
23
|
+
"test:studio": "playwright test --config studio-e2e/playwright.config.ts",
|
|
23
24
|
"dev": "bun run --watch lobb.ts",
|
|
24
25
|
"dev:studio": "vite dev",
|
|
25
26
|
"build": "vite build",
|
|
@@ -32,13 +33,13 @@
|
|
|
32
33
|
"package": "svelte-package --input extensions/auth/studio"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@lobb-js/core": "^0.50.
|
|
36
|
+
"@lobb-js/core": "^0.50.2",
|
|
36
37
|
"argon2": "^0.40.3",
|
|
37
38
|
"hono": "^4.7.0"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
41
|
-
"@lobb-js/studio": "^0.60.
|
|
42
|
+
"@lobb-js/studio": "^0.60.2",
|
|
42
43
|
"@lucide/svelte": "^0.563.1",
|
|
43
44
|
"@sveltejs/adapter-node": "^5.5.4",
|
|
44
45
|
"@sveltejs/kit": "^2.60.1",
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Lives under studio/ for packaging reasons — `svelte-package` only bundles
|
|
2
|
-
// files inside its `--input` root, so anything the studio entry imports has
|
|
3
|
-
// to be reachable from there. The backend imports this same file via
|
|
4
|
-
// `../studio/shared/permissions` so there's still one source of truth.
|
|
5
|
-
//
|
|
6
|
-
// Anything in this folder must stay environment-neutral (no DOM, no Node-only
|
|
7
|
-
// APIs, no top-level side effects) so it runs the same way on both sides.
|
|
8
|
-
// Pure permission check shared by the server-side handlePolicy and the
|
|
9
|
-
// studio's auth.canAccess workflow. Walks the permissions tree and returns
|
|
10
|
-
// a yes/no — server-side then layers on guards/filters/error-throwing,
|
|
11
|
-
// client-side uses the answer to decide whether to render UI.
|
|
12
|
-
//
|
|
13
|
-
// An object value for action permission means "conditional access" (filter
|
|
14
|
-
// and/or fields restrictions). For UI gating that counts as allowed; the
|
|
15
|
-
// server enforces the actual restrictions on real requests.
|
|
16
|
-
export function isActionAllowed(collection, action, permissions) {
|
|
17
|
-
if (permissions === true)
|
|
18
|
-
return true;
|
|
19
|
-
if (!permissions)
|
|
20
|
-
return false;
|
|
21
|
-
const collPerm = permissions[collection];
|
|
22
|
-
if (collPerm === true)
|
|
23
|
-
return true;
|
|
24
|
-
if (!collPerm)
|
|
25
|
-
return false;
|
|
26
|
-
const actionPerm = collPerm[action];
|
|
27
|
-
if (actionPerm === true)
|
|
28
|
-
return true;
|
|
29
|
-
// A conditional grant must actually list at least one constraint
|
|
30
|
-
// (filter / fields / payloadGuard / mutate). Empty `{}` collapses back
|
|
31
|
-
// to "no grant" — explicit `true` is required for unconditional access.
|
|
32
|
-
return (typeof actionPerm === "object" &&
|
|
33
|
-
actionPerm !== null &&
|
|
34
|
-
Object.keys(actionPerm).length > 0);
|
|
35
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
// Lives under studio/ for packaging reasons — `svelte-package` only bundles
|
|
2
|
-
// files inside its `--input` root, so anything the studio entry imports has
|
|
3
|
-
// to be reachable from there. The backend imports this same file via
|
|
4
|
-
// `../studio/shared/permissions` so there's still one source of truth.
|
|
5
|
-
//
|
|
6
|
-
// Anything in this folder must stay environment-neutral (no DOM, no Node-only
|
|
7
|
-
// APIs, no top-level side effects) so it runs the same way on both sides.
|
|
8
|
-
|
|
9
|
-
import type {
|
|
10
|
-
CollectionPermissionActionsKeys,
|
|
11
|
-
PermissionsConfig,
|
|
12
|
-
} from "../../config/extensionConfigSchema.ts";
|
|
13
|
-
|
|
14
|
-
// Pure permission check shared by the server-side handlePolicy and the
|
|
15
|
-
// studio's auth.canAccess workflow. Walks the permissions tree and returns
|
|
16
|
-
// a yes/no — server-side then layers on guards/filters/error-throwing,
|
|
17
|
-
// client-side uses the answer to decide whether to render UI.
|
|
18
|
-
//
|
|
19
|
-
// An object value for action permission means "conditional access" (filter
|
|
20
|
-
// and/or fields restrictions). For UI gating that counts as allowed; the
|
|
21
|
-
// server enforces the actual restrictions on real requests.
|
|
22
|
-
export function isActionAllowed(
|
|
23
|
-
collection: string,
|
|
24
|
-
action: CollectionPermissionActionsKeys,
|
|
25
|
-
permissions: PermissionsConfig | undefined,
|
|
26
|
-
): boolean {
|
|
27
|
-
if (permissions === true) return true;
|
|
28
|
-
if (!permissions) return false;
|
|
29
|
-
const collPerm = permissions[collection];
|
|
30
|
-
if (collPerm === true) return true;
|
|
31
|
-
if (!collPerm) return false;
|
|
32
|
-
const actionPerm = collPerm[action];
|
|
33
|
-
if (actionPerm === true) return true;
|
|
34
|
-
// A conditional grant must actually list at least one constraint
|
|
35
|
-
// (filter / fields / payloadGuard / mutate). Empty `{}` collapses back
|
|
36
|
-
// to "no grant" — explicit `true` is required for unconditional access.
|
|
37
|
-
return (
|
|
38
|
-
typeof actionPerm === "object" &&
|
|
39
|
-
actionPerm !== null &&
|
|
40
|
-
Object.keys(actionPerm).length > 0
|
|
41
|
-
);
|
|
42
|
-
}
|