Template
1
0

feat: add initial workspace resource

This commit is contained in:
2025-09-22 02:34:29 +02:00
parent ef055ca022
commit 0d70749670
7 changed files with 83 additions and 17 deletions

3
deno.lock generated
View File

@@ -2239,7 +2239,8 @@
"packageJson": { "packageJson": {
"dependencies": [ "dependencies": [
"npm:@cerbos/http@0.23.1", "npm:@cerbos/http@0.23.1",
"npm:@jsr/valkyr__auth@2.1.4" "npm:@jsr/valkyr__auth@2.1.4",
"npm:zod@4.1.11"
] ]
} }
}, },

View File

@@ -1,5 +1,6 @@
import { HttpAdapter, makeClient } from "@platform/relay"; import { HttpAdapter, makeClient } from "@platform/relay";
import { PrincipalProvider } from "@valkyr/auth"; import { PrincipalProvider } from "@valkyr/auth";
import z from "zod";
import { config } from "../config.ts"; import { config } from "../config.ts";
import resolve from "../routes/identities/resolve/spec.ts"; import resolve from "../routes/identities/resolve/spec.ts";
@@ -18,15 +19,21 @@ export const identity = makeClient(
}, },
); );
export const principal = new PrincipalProvider(RoleSchema, {}, async function (id: string) { export const principal = new PrincipalProvider(
const response = await identity.resolve({ params: { id } }); RoleSchema,
if ("data" in response) { {
return { workspaceIds: z.array(z.string()).optional().default([]),
id, },
roles: response.data.roles, async function (id: string) {
attributes: {}, const response = await identity.resolve({ params: { id } });
}; if ("data" in response) {
} return {
}); id,
roles: response.data.roles,
attributes: this.attributes.parse(response.data.attributes),
};
}
},
);
export type Principal = typeof principal.$principal; export type Principal = typeof principal.$principal;

View File

@@ -16,6 +16,7 @@ export const IdentitySchema = z.object({
}), }),
strategies: z.array(StrategySchema).default([]), strategies: z.array(StrategySchema).default([]),
roles: z.array(RoleSchema).default([]), roles: z.array(RoleSchema).default([]),
attributes: z.record(z.string(), z.any()),
}); });
/* /*

View File

@@ -1,8 +1,17 @@
import { HTTP } from "@cerbos/http"; import { HTTP } from "@cerbos/http";
import { getEnvironmentVariable } from "@platform/config/environment.ts";
import z from "zod";
export const cerbos = new HTTP("http://localhost:3592", { export const cerbos = new HTTP(
adminCredentials: { getEnvironmentVariable({
username: "cerbos", key: "CERBOS_URL",
password: "cerbosAdmin", type: z.string(),
fallback: "http://localhost:3592",
}),
{
adminCredentials: {
username: "cerbos",
password: "cerbosAdmin",
},
}, },
}); );

View File

@@ -5,6 +5,8 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@cerbos/http": "0.23.1", "@cerbos/http": "0.23.1",
"@valkyr/auth": "npm:@jsr/valkyr__auth@2.1.4" "@platform/config": "workspace:*",
"@valkyr/auth": "npm:@jsr/valkyr__auth@2.1.4",
"zod": "4.1.11"
} }
} }

View File

@@ -0,0 +1,42 @@
# yaml-language-server: $schema=https://api.cerbos.dev/latest/cerbos/policy/v1/Policy.schema.json
# docs: https://docs.cerbos.dev/cerbos/latest/policies/resource_policies
apiVersion: api.cerbos.dev/v1
resourcePolicy:
resource: workspace
version: default
rules:
### Read
- actions:
- read
effect: EFFECT_ALLOW
roles:
- admin
- user
condition:
match:
expr: request.principal.workspaceIds.includes(request.resource.id)
### Update
- actions:
- update
effect: EFFECT_ALLOW
roles:
- admin
condition:
match:
expr: request.principal.workspaceIds.includes(request.resource.id)
### Delete
- actions:
- delete
effect: EFFECT_ALLOW
roles:
- admin
condition:
match:
expr: request.principal.workspaceIds.includes(request.resource.id)

View File

@@ -5,6 +5,10 @@ export const resources = new ResourceRegistry([
kind: "identity", kind: "identity",
attr: {}, attr: {},
}, },
{
kind: "workspace",
attr: {},
},
] as const); ] as const);
export type Resource = typeof resources.$resource; export type Resource = typeof resources.$resource;