From a140780ec30e6c27b4d066b0f153fb537ec872be Mon Sep 17 00:00:00 2001 From: Kodemon Date: Fri, 19 Sep 2025 08:45:30 +0200 Subject: [PATCH] feat: add documentation to access response --- api/libraries/auth/access.ts | 69 ++++++++++++++ api/libraries/auth/resources.ts | 2 +- api/package.json | 3 +- deno.lock | 164 +------------------------------- 4 files changed, 76 insertions(+), 162 deletions(-) diff --git a/api/libraries/auth/access.ts b/api/libraries/auth/access.ts index 830897c..fb75ba0 100644 --- a/api/libraries/auth/access.ts +++ b/api/libraries/auth/access.ts @@ -4,12 +4,81 @@ import { Resource } from "./resources.ts"; export function access(principal: Principal) { return { + /** + * Check if a principal is allowed to perform an action on a resource. + * + * @param resource - Resource which we are validating. + * @param action - Action which we are validating. + * + * @example + * + * await access.isAllowed( + * { + * kind: "document", + * id: "1", + * attr: { owner: "user@example.com" }, + * }, + * "view" + * ); // => true + */ isAllowed(resource: Resource, action: string) { return cerbos.isAllowed({ principal, resource, action }); }, + + /** + * Check a principal's permissions on a resource. + * + * @param resource - Resource which we are validating. + * @param actions - Actions which we are validating. + * + * @example + * + * const decision = await access.checkResource( + * { + * kind: "document", + * id: "1", + * attr: { owner: "user@example.com" }, + * }, + * ["view", "edit"], + * ); + * + * decision.isAllowed("view"); // => true + */ checkResource(resource: Resource, actions: string[]) { return cerbos.checkResource({ principal, resource, actions }); }, + + /** + * Check a principal's permissions on a set of resources. + * + * @param resources - Resources which we are validating. + * + * @example + * + * const decision = await access.checkResources([ + * { + * resource: { + * kind: "document", + * id: "1", + * attr: { owner: "user@example.com" }, + * }, + * actions: ["view", "edit"], + * }, + * { + * resource: { + * kind: "image", + * id: "1", + * attr: { owner: "user@example.com" }, + * }, + * actions: ["delete"], + * }, + * ]); + * + * decision.isAllowed({ + * resource: { kind: "document", id: "1" }, + * action: "view", + * }); // => true + */ checkResources(resources: { resource: Resource; actions: string[] }[]) { return cerbos.checkResources({ principal, resources }); }, diff --git a/api/libraries/auth/resources.ts b/api/libraries/auth/resources.ts index 6bc1b9f..6c2e36c 100644 --- a/api/libraries/auth/resources.ts +++ b/api/libraries/auth/resources.ts @@ -3,7 +3,7 @@ import { ResourceRegistry } from "@valkyr/auth"; export const resources = new ResourceRegistry([ { kind: "account", - attributes: {}, + attr: {}, }, ] as const); diff --git a/api/package.json b/api/package.json index 8d57f43..ac65ba0 100644 --- a/api/package.json +++ b/api/package.json @@ -5,7 +5,6 @@ "migrate": "deno run --allow-all .tasks/migrate.ts" }, "dependencies": { - "@cerbos/grpc": "0.23.1", "@cerbos/http": "0.23.1", "@felix/bcrypt": "npm:@jsr/felix__bcrypt@1.0.5", "@spec/modules": "workspace:*", @@ -15,7 +14,7 @@ "@std/dotenv": "npm:@jsr/std__dotenv@0.225.5", "@std/fs": "npm:@jsr/std__fs@1.0.19", "@std/path": "npm:@jsr/std__path@1.1.2", - "@valkyr/auth": "npm:@jsr/valkyr__auth@2.1.3", + "@valkyr/auth": "npm:@jsr/valkyr__auth@2.1.4", "@valkyr/event-store": "npm:@jsr/valkyr__event-store@2", "@valkyr/inverse": "npm:@jsr/valkyr__inverse@1.0.1", "@valkyr/json-rpc": "npm:@jsr/valkyr__json-rpc@1.1.0", diff --git a/deno.lock b/deno.lock index 3dc9eb8..40146c0 100644 --- a/deno.lock +++ b/deno.lock @@ -1,7 +1,6 @@ { "version": "5", "specifiers": { - "npm:@cerbos/grpc@0.23.1": "0.23.1", "npm:@cerbos/http@0.23.1": "0.23.1", "npm:@eslint/js@9.35.0": "9.35.0", "npm:@jsr/felix__bcrypt@1.0.5": "1.0.5", @@ -11,7 +10,7 @@ "npm:@jsr/std__fs@1.0.19": "1.0.19", "npm:@jsr/std__path@1.1.2": "1.1.2", "npm:@jsr/std__testing@1.0.15": "1.0.15", - "npm:@jsr/valkyr__auth@2.1.3": "2.1.3", + "npm:@jsr/valkyr__auth@2.1.4": "2.1.4", "npm:@jsr/valkyr__db@2.0.0": "2.0.0", "npm:@jsr/valkyr__event-emitter@1.0.1": "1.0.1", "npm:@jsr/valkyr__event-store@2": "2.0.0", @@ -182,23 +181,12 @@ "@babel/helper-validator-identifier" ] }, - "@bufbuild/protobuf@2.9.0": { - "integrity": "sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==" - }, "@cerbos/core@0.24.1": { "integrity": "sha512-Gt9ETQR3WDVcPlxN+HiGUDtNgWFulwS5ZjBgzJFsdb7e2GCw0tOPE9Ex1qHNZvG/0JHpFWJWIiYaSKyXcp35YQ==", "dependencies": [ "uuid" ] }, - "@cerbos/grpc@0.23.1": { - "integrity": "sha512-6ve6d9m+hBZ4xZAI6Oc2/TR2RAoy+QE8zmTVNt38MMyif+BJ3T2dD/Lwd5t75+9+pBJCLch5kLz5ZtnbnGoyuw==", - "dependencies": [ - "@bufbuild/protobuf", - "@cerbos/core", - "@grpc/grpc-js" - ] - }, "@cerbos/http@0.23.1": { "integrity": "sha512-XzWFS6L7M+oUnjGEFIoQygtlmZy3zOpUobN6spGp1MAaT6GQJMRFK8P8xhY2BQjTIhqYgnoiEFOAULTkbgNIjg==", "dependencies": [ @@ -390,23 +378,6 @@ "levn" ] }, - "@grpc/grpc-js@1.14.0": { - "integrity": "sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg==", - "dependencies": [ - "@grpc/proto-loader", - "@js-sdsl/ordered-map" - ] - }, - "@grpc/proto-loader@0.8.0": { - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "dependencies": [ - "lodash.camelcase", - "long", - "protobufjs", - "yargs" - ], - "bin": true - }, "@humanfs/core@0.19.1": { "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==" }, @@ -456,9 +427,6 @@ "@jridgewell/sourcemap-codec" ] }, - "@js-sdsl/ordered-map@4.4.2": { - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==" - }, "@jsr/denosaurs__plug@1.1.0": { "integrity": "sha512-GNRMr8XcYWbv8C1B5OjDa5u8q3p2lz7YVWQLhH5HAy0pkpb0+Y3npSxzjM49v5ajTFIzUCwIKv1gQukPm9q7qw==", "dependencies": [ @@ -545,13 +513,13 @@ ], "tarball": "https://npm.jsr.io/~/11/@jsr/std__testing/1.0.15.tgz" }, - "@jsr/valkyr__auth@2.1.3": { - "integrity": "sha512-J2r6bfd2IMoVtln/valsagVh9LDBLG2tBzfxBHoi+6NZzA0g3DAHevC2Rf8TTsMDFSiqz3ewUgntBnmMpR9SVA==", + "@jsr/valkyr__auth@2.1.4": { + "integrity": "sha512-z4/OfPJ+7KZKdILrCWMO9nDQgOsLFw0A6HHgV3h7N1DpH1Ok0uRHUNAUA2IbI5KZif8yUPw+wsKztM6pOEMjbg==", "dependencies": [ "jose", "zod" ], - "tarball": "https://npm.jsr.io/~/11/@jsr/valkyr__auth/2.1.3.tgz" + "tarball": "https://npm.jsr.io/~/11/@jsr/valkyr__auth/2.1.4.tgz" }, "@jsr/valkyr__db@2.0.0": { "integrity": "sha512-0gIauba+vQW6ssqMACLO1Z/METlhzoX+y4t9Sawh/IafQ986Rgvp6gCI+WArp7vbsO5hpItixrqjkxnnNC+h5g==", @@ -626,40 +594,6 @@ "fastq" ] }, - "@protobufjs/aspromise@1.1.2": { - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "@protobufjs/base64@1.1.2": { - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen@2.0.4": { - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter@1.1.0": { - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "@protobufjs/fetch@1.1.0": { - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": [ - "@protobufjs/aspromise", - "@protobufjs/inquire" - ] - }, - "@protobufjs/float@1.0.2": { - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "@protobufjs/inquire@1.1.0": { - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "@protobufjs/path@1.1.2": { - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "@protobufjs/pool@1.1.0": { - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "@protobufjs/utf8@1.1.0": { - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, "@rolldown/pluginutils@1.0.0-beta.27": { "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==" }, @@ -1153,9 +1087,6 @@ "uri-js" ] }, - "ansi-regex@5.0.1": { - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, "ansi-styles@4.3.0": { "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": [ @@ -1235,14 +1166,6 @@ "chownr@3.0.0": { "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" }, - "cliui@8.0.1": { - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": [ - "string-width", - "strip-ansi", - "wrap-ansi" - ] - }, "clsx@2.1.1": { "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" }, @@ -1301,9 +1224,6 @@ "electron-to-chromium@1.5.222": { "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==" }, - "emoji-regex@8.0.0": { - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, "enhanced-resolve@5.18.3": { "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dependencies": [ @@ -1540,9 +1460,6 @@ "gensync@1.0.0-beta.2": { "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, - "get-caller-file@2.0.5": { - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, "get-intrinsic@1.3.0": { "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dependencies": [ @@ -1632,9 +1549,6 @@ "is-extglob@2.1.1": { "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, - "is-fullwidth-code-point@3.0.0": { - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, "is-glob@4.0.3": { "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dependencies": [ @@ -1771,15 +1685,9 @@ "p-locate" ] }, - "lodash.camelcase@4.3.0": { - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, "lodash.merge@4.6.2": { "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, - "long@5.3.2": { - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==" - }, "lru-cache@5.1.1": { "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dependencies": [ @@ -1932,24 +1840,6 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "bin": true }, - "protobufjs@7.5.4": { - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "dependencies": [ - "@protobufjs/aspromise", - "@protobufjs/base64", - "@protobufjs/codegen", - "@protobufjs/eventemitter", - "@protobufjs/fetch", - "@protobufjs/float", - "@protobufjs/inquire", - "@protobufjs/path", - "@protobufjs/pool", - "@protobufjs/utf8", - "@types/node", - "long" - ], - "scripts": true - }, "punycode@2.3.1": { "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, @@ -1975,9 +1865,6 @@ "react@19.1.1": { "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==" }, - "require-directory@2.1.1": { - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, "resolve-from@4.0.0": { "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, @@ -2109,20 +1996,6 @@ "memory-pager" ] }, - "string-width@4.2.3": { - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": [ - "emoji-regex", - "is-fullwidth-code-point", - "strip-ansi" - ] - }, - "strip-ansi@6.0.1": { - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": [ - "ansi-regex" - ] - }, "strip-json-comments@3.1.1": { "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, @@ -2286,38 +2159,12 @@ "word-wrap@1.2.5": { "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==" }, - "wrap-ansi@7.0.0": { - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": [ - "ansi-styles", - "string-width", - "strip-ansi" - ] - }, - "y18n@5.0.8": { - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, "yallist@3.1.1": { "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yallist@5.0.0": { "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" }, - "yargs-parser@21.1.1": { - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - }, - "yargs@17.7.2": { - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": [ - "cliui", - "escalade", - "get-caller-file", - "require-directory", - "string-width", - "y18n", - "yargs-parser" - ] - }, "yocto-queue@0.1.0": { "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" }, @@ -2340,14 +2187,13 @@ "api": { "packageJson": { "dependencies": [ - "npm:@cerbos/grpc@0.23.1", "npm:@cerbos/http@0.23.1", "npm:@jsr/felix__bcrypt@1.0.5", "npm:@jsr/std__cli@1.0.22", "npm:@jsr/std__dotenv@0.225.5", "npm:@jsr/std__fs@1.0.19", "npm:@jsr/std__path@1.1.2", - "npm:@jsr/valkyr__auth@2.1.3", + "npm:@jsr/valkyr__auth@2.1.4", "npm:@jsr/valkyr__event-store@2", "npm:@jsr/valkyr__inverse@1.0.1", "npm:@jsr/valkyr__json-rpc@1.1.0",