@cedarjs/tenancy 8.0.0-canary.3567 → 8.0.0-canary.3568

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/README.md CHANGED
@@ -73,33 +73,22 @@ import {
73
73
  - `getCurrentOrg()` / `requireCurrentOrg()` — read the organization set on the
74
74
  current request; the latter throws `TenantScopeError` when none is set.
75
75
 
76
- ## Auth helpers
76
+ ## User checks
77
77
 
78
- ```ts
79
- // api/src/lib/auth.ts, in place of the single-tenant hasRole/requireAuth
80
- import { createTenancyAuth } from '@cedarjs/tenancy'
81
-
82
- export const { hasUserRole, requireUserAuth } = createTenancyAuth()
83
-
84
- // In a service:
85
- requireUserAuth() // signed in, no organization needed
86
-
87
- // Anywhere:
88
- if (hasUserRole('superuser')) { ... } // currentUser.roles
89
- ```
90
-
91
- `requireUserAuth` (and the `@requireUserAuth` directive `setup tenancy` adds)
92
- is for fields about the user rather than an organization: their account,
93
- their memberships, accepting an invitation. It needs a signed-in user, and
94
- checks `roles` against `currentUser.roles`. There's no `requireAuth` or
95
- `hasRole`, and no role check on the current organization: fields about an
96
- organization ask for a permission (below).
78
+ `hasRole` and `requireAuth` in `api/src/lib/auth.ts`, and the `@requireAuth`
79
+ directive, are for fields about the user rather than an organization: their
80
+ account, their memberships, accepting an invitation. `requireAuth` needs a
81
+ signed-in user, and both check `roles` against `currentUser.roles`: the user's own roles, in
82
+ any organization or none. There's no role check on the current
83
+ organization: fields about an organization ask for a permission (below).
97
84
 
98
85
  ## Permissions
99
86
 
100
- Roles are named bundles of permissions, defined in one place. Fields,
101
- services and components check permissions, never roles, so a role can do
102
- exactly what its list says.
87
+ Roles in an organization are named bundles of permissions, defined in one
88
+ place. Fields, services and components check a permission in an
89
+ organization, never the membership's role, so a role can do exactly what its
90
+ list says. `hasRole` and `<PrivateSet roles>` check the user's own roles, in
91
+ `currentUser.roles`.
103
92
 
104
93
  ```ts
105
94
  // packages/permissions/src/index.ts, shared by the api and web sides
@@ -184,12 +173,13 @@ export const tenancy = createTenancy({
184
173
  })
185
174
  ```
186
175
 
187
- The router checks the permission in the organization of the route's
188
- `orgSlug` param. A `PrivateSet` with `orgPermission` throws when
176
+ The router checks the permission in the organization that `tenancy.useOrg`
177
+ returns. The default `useOrg` finds it by the route's `orgSlug` param, and a
178
+ custom one can find it another way, such as from the host. A `PrivateSet` with `orgPermission` throws when
189
179
  the router has no `tenancy` or its `useOrg` finds no organization for the
190
180
  route; with the default lookup, that's a route without `{orgSlug}`. A route
191
181
  with `{orgSlug}` outside a `PrivateSet` is a public page with no organization
192
- context. `useAuth().hasUserRole` and `<PrivateSet userRoles>` check
193
- `currentUser.roles`; there's no `useAuth().hasRole` or `<PrivateSet roles>` in
194
- an app with tenancy. See the
182
+ context. `useAuth().hasRole` and `<PrivateSet roles>` check
183
+ `currentUser.roles`, the user's own roles, as in an app without tenancy;
184
+ checks in an organization use a permission. See the
195
185
  how-to for the full setup `yarn cedar setup tenancy` generates.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from './errors.js';
2
2
  export * from './context.js';
3
- export * from './auth.js';
4
3
  export * from './permissions.js';
5
4
  export { createTenancyExtension } from './prismaExtension.js';
6
5
  export type { ModelNamesFor, TenancyConfig, UnscopedClient, } from './prismaExtension.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,YAAY,EACV,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,YAAY,EACV,aAAa,EACb,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from "./errors.js";
2
2
  export * from "./context.js";
3
- export * from "./auth.js";
4
3
  export * from "./permissions.js";
5
4
  import { createTenancyExtension } from "./prismaExtension.js";
6
5
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/tenancy",
3
- "version": "8.0.0-canary.3567",
3
+ "version": "8.0.0-canary.3568",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/cedarjs/cedar.git",
@@ -44,17 +44,17 @@
44
44
  "test:watch": "vitest watch"
45
45
  },
46
46
  "dependencies": {
47
- "@cedarjs/api": "8.0.0-canary.3567",
48
- "@cedarjs/context": "8.0.0-canary.3567",
49
- "@cedarjs/graphql-server": "8.0.0-canary.3567"
47
+ "@cedarjs/api": "8.0.0-canary.3568",
48
+ "@cedarjs/context": "8.0.0-canary.3568",
49
+ "@cedarjs/graphql-server": "8.0.0-canary.3568"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@apollo/client": "4.3.5",
53
53
  "@arethetypeswrong/cli": "0.18.5",
54
- "@cedarjs/auth": "8.0.0-canary.3567",
55
- "@cedarjs/framework-tools": "8.0.0-canary.3567",
56
- "@cedarjs/router": "8.0.0-canary.3567",
57
- "@cedarjs/web": "8.0.0-canary.3567",
54
+ "@cedarjs/auth": "8.0.0-canary.3568",
55
+ "@cedarjs/framework-tools": "8.0.0-canary.3568",
56
+ "@cedarjs/router": "8.0.0-canary.3568",
57
+ "@cedarjs/web": "8.0.0-canary.3568",
58
58
  "@prisma/adapter-better-sqlite3": "7.10.1",
59
59
  "@prisma/client": "7.10.1",
60
60
  "@testing-library/dom": "10.4.2",
@@ -80,9 +80,9 @@
80
80
  },
81
81
  "peerDependencies": {
82
82
  "@apollo/client": "4.3.5",
83
- "@cedarjs/auth": "8.0.0-canary.3567",
84
- "@cedarjs/router": "8.0.0-canary.3567",
85
- "@cedarjs/web": "8.0.0-canary.3567",
83
+ "@cedarjs/auth": "8.0.0-canary.3568",
84
+ "@cedarjs/router": "8.0.0-canary.3568",
85
+ "@cedarjs/web": "8.0.0-canary.3568",
86
86
  "@prisma/client": "7.10.1",
87
87
  "react": "19.3.1"
88
88
  },
package/dist/auth.d.ts DELETED
@@ -1,37 +0,0 @@
1
- type Roles = string | readonly string[];
2
- export interface TenancyAuth {
3
- /**
4
- * Whether the signed-in user holds one of `roles` in `currentUser.roles`,
5
- * in any organization or none. What the single-tenant `hasRole()` checked.
6
- */
7
- hasUserRole(roles: Roles): boolean;
8
- /**
9
- * Guards a service or directive on the signed-in user alone, in any
10
- * organization or none: their account, their memberships, accepting an
11
- * invitation. When `roles` are given, the user needs one of them in
12
- * `currentUser.roles`.
13
- *
14
- * Throws `AuthenticationError` when no one is signed in, and
15
- * `ForbiddenError` otherwise.
16
- */
17
- requireUserAuth(options?: {
18
- roles?: Roles;
19
- }): void;
20
- }
21
- /**
22
- * The auth checks for an app with tenancy, which `api/src/lib/auth.ts`
23
- * exports in place of its single-tenant `hasRole` and `requireAuth`:
24
- *
25
- * ```ts
26
- * export const { hasUserRole, requireUserAuth } =
27
- * createTenancyAuth()
28
- * ```
29
- *
30
- * There's no `hasRole` or `requireAuth`: every check says whether it's
31
- * about the signed-in user alone or the current organization. Checks on
32
- * the current organization are permissions (`createPermissions`), so a
33
- * role can do only what its entry in the permission definitions lists.
34
- */
35
- export declare function createTenancyAuth(): TenancyAuth;
36
- export {};
37
- //# sourceMappingURL=auth.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAGA,KAAK,KAAK,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;AAwBvC,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAA;IAClC;;;;;;;;OAQG;IACH,eAAe,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,IAAI,CAAA;CACnD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAuB/C"}
package/dist/auth.js DELETED
@@ -1,32 +0,0 @@
1
- import { context } from "@cedarjs/context";
2
- import { AuthenticationError, ForbiddenError } from "@cedarjs/graphql-server";
3
- const toList = (roles) => typeof roles === "string" ? [roles] : [...roles];
4
- function userRoles() {
5
- const roles = context.currentUser?.roles;
6
- if (typeof roles === "string") {
7
- return [roles];
8
- }
9
- if (Array.isArray(roles)) {
10
- return roles.filter((role) => typeof role === "string");
11
- }
12
- return [];
13
- }
14
- function createTenancyAuth() {
15
- return {
16
- hasUserRole(roles) {
17
- const roleList = toList(roles);
18
- return !!context.currentUser && userRoles().some((role) => roleList.includes(role));
19
- },
20
- requireUserAuth({ roles } = {}) {
21
- if (!context.currentUser) {
22
- throw new AuthenticationError("You don't have permission to do that.");
23
- }
24
- if (roles && !userRoles().some((role) => toList(roles).includes(role))) {
25
- throw new ForbiddenError("You don't have access to do that.");
26
- }
27
- }
28
- };
29
- }
30
- export {
31
- createTenancyAuth
32
- };