cauthy-auth 0.28.1 → 0.30.0
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 +51 -0
- package/dist/{cauthy-CTVg4kvo.d.mts → cauthy-BXgsZ-Um.d.mts} +19 -1
- package/dist/{cauthy-BAwAJChs.d.ts → cauthy-CHENs452.d.ts} +19 -1
- package/dist/cli.js +155 -54
- package/dist/client.d.mts +47 -7
- package/dist/client.d.ts +47 -7
- package/dist/client.js +23 -1
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +23 -1
- package/dist/client.mjs.map +1 -1
- package/dist/express.d.mts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/fastify.d.mts +2 -2
- package/dist/fastify.d.ts +2 -2
- package/dist/hono.d.mts +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +325 -129
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +323 -129
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +2 -2
- package/dist/next.d.ts +2 -2
- package/dist/react.d.mts +214 -18
- package/dist/react.d.ts +214 -18
- package/dist/react.js +129 -32
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +129 -32
- package/dist/react.mjs.map +1 -1
- package/dist/svelte.d.mts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +37 -2
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +37 -2
- package/dist/svelte.mjs.map +1 -1
- package/dist/{system-CVBW_AV8.d.mts → system-0mHrdAgO.d.mts} +307 -109
- package/dist/{system-Bn8uckvQ.d.ts → system-BIYbS7h2.d.ts} +307 -109
- package/dist/vue.d.mts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +37 -2
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +37 -2
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,113 +1,6 @@
|
|
|
1
1
|
import { JWK } from 'jose';
|
|
2
2
|
import { CauthyTheme } from './theme.js';
|
|
3
3
|
|
|
4
|
-
/** The part of an organization that says what its member may do. */
|
|
5
|
-
interface Permitted {
|
|
6
|
-
/** "resource:action" entries the person is allowed; "*" is any. Absent when the system keeps no catalog in Cauthy. */
|
|
7
|
-
permissions?: string[];
|
|
8
|
-
/** Entries the person is denied whatever else allows them. */
|
|
9
|
-
denied?: string[];
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Whether the person may do an action on a resource in an organization:
|
|
13
|
-
* allowed by some entry, and denied by none. A denial wins.
|
|
14
|
-
*
|
|
15
|
-
* An organization of a system that keeps no catalog in Cauthy carries no
|
|
16
|
-
* permissions, and the answer is `false`: decide by its `role` instead.
|
|
17
|
-
*
|
|
18
|
-
* if (!can(organization, 'invoicing', 'write')) return forbidden()
|
|
19
|
-
*/
|
|
20
|
-
declare function can(organization: Permitted | null | undefined, resource: string, action: string): boolean;
|
|
21
|
-
/** Something a role may do: an action on a resource, in organizations of a kind ("*", the default, is every kind). */
|
|
22
|
-
interface PolicyPermission {
|
|
23
|
-
kind?: string;
|
|
24
|
-
resource: string;
|
|
25
|
-
action: string;
|
|
26
|
-
}
|
|
27
|
-
interface PolicyRole {
|
|
28
|
-
role: string;
|
|
29
|
-
name?: string;
|
|
30
|
-
description?: string;
|
|
31
|
-
/** Roles whose permissions this one has as well. */
|
|
32
|
-
inherits?: string[];
|
|
33
|
-
permissions?: PolicyPermission[];
|
|
34
|
-
}
|
|
35
|
-
/** A role as `definePolicy` reads it: any `PolicyRole`, kept as written. */
|
|
36
|
-
type RoleShape = {
|
|
37
|
-
readonly role: string;
|
|
38
|
-
readonly name?: string;
|
|
39
|
-
readonly description?: string;
|
|
40
|
-
readonly inherits?: readonly string[];
|
|
41
|
-
readonly permissions?: readonly {
|
|
42
|
-
readonly kind?: string;
|
|
43
|
-
readonly resource: string;
|
|
44
|
-
readonly action: string;
|
|
45
|
-
}[];
|
|
46
|
-
};
|
|
47
|
-
type Named<S extends string> = S extends '*' ? string : S;
|
|
48
|
-
type PermissionsIn<R> = R extends {
|
|
49
|
-
readonly permissions: readonly (infer P)[];
|
|
50
|
-
} ? P extends {
|
|
51
|
-
readonly resource: infer Res extends string;
|
|
52
|
-
readonly action: infer Act extends string;
|
|
53
|
-
} ? `${Named<Res>}:${Named<Act>}` : never : never;
|
|
54
|
-
/** The roles a catalog names: `RoleOf<typeof policy>`. */
|
|
55
|
-
type RoleOf<P> = P extends Policy<infer R, string> ? R : never;
|
|
56
|
-
/** The "resource:action" permissions a catalog names: `PermissionOf<typeof policy>`. */
|
|
57
|
-
type PermissionOf<P> = P extends Policy<string, infer X> ? X : never;
|
|
58
|
-
interface Policy<Role extends string = string, Permission extends string = string> {
|
|
59
|
-
/** The catalog as Cauthy takes it: `pushPolicy({ roles: policy.roles })`. */
|
|
60
|
-
roles: PolicyRole[];
|
|
61
|
-
/** Every role's name. */
|
|
62
|
-
roleNames: Role[];
|
|
63
|
-
/** Every permission some role has, as "resource:action". */
|
|
64
|
-
permissions: Permission[];
|
|
65
|
-
/**
|
|
66
|
-
* Whether the person may do this in the organization: `can(org, 'ledger:write')`.
|
|
67
|
-
* It reads what Cauthy sent with the session, so a catalog edited in Cauthy
|
|
68
|
-
* since this file was written is still what decides.
|
|
69
|
-
*/
|
|
70
|
-
can(organization: Permitted | null | undefined, permission: Permission): boolean;
|
|
71
|
-
/** Whether the person's role in the organization is one of these. */
|
|
72
|
-
hasRole(organization: {
|
|
73
|
-
role: string;
|
|
74
|
-
} | null | undefined, ...roles: Role[]): boolean;
|
|
75
|
-
/**
|
|
76
|
-
* What a role may do by this catalog, with what it inherits: for showing a
|
|
77
|
-
* role, never for deciding about a person (their exceptions are not here).
|
|
78
|
-
*/
|
|
79
|
-
permissionsOf(role: Role): Permission[];
|
|
80
|
-
}
|
|
81
|
-
/** Gives a catalog of roles its types. See the top of this section. */
|
|
82
|
-
declare function definePolicy<const T extends readonly RoleShape[]>(roles: T): Policy<T[number]['role'], PermissionsIn<T[number]>>;
|
|
83
|
-
/**
|
|
84
|
-
* A TypeScript module that defines the catalog given, for `cauthy-auth policy
|
|
85
|
-
* --pull` to write: the application's types then come from the catalog
|
|
86
|
-
* Cauthy has.
|
|
87
|
-
*/
|
|
88
|
-
declare function policySource(system: string, roles: PolicyRole[]): string;
|
|
89
|
-
/** Reads a system's catalog of roles from Cauthy, with a personal access token. */
|
|
90
|
-
declare function pullPolicy(o?: Omit<PushPolicyOptions, 'roles'>): Promise<PolicyRole[]>;
|
|
91
|
-
interface PushPolicyOptions {
|
|
92
|
-
/** The system whose catalog this is. Default: `CAUTHY_SYSTEM`. */
|
|
93
|
-
system?: string;
|
|
94
|
-
roles: PolicyRole[];
|
|
95
|
-
/** Cauthy's address. Default: `CAUTHY_ISSUER`. */
|
|
96
|
-
issuer?: string;
|
|
97
|
-
/** The workspace's slug. Default: `CAUTHY_TENANT`. */
|
|
98
|
-
tenant?: string;
|
|
99
|
-
/** A personal access token with `organizations:manage`. Default: `CAUTHY_TOKEN`. */
|
|
100
|
-
token?: string;
|
|
101
|
-
fetch?: typeof fetch;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Gives Cauthy a system's catalog of roles, replacing the one it has. It is
|
|
105
|
-
* the way to load a first catalog from what a system already had; from then on
|
|
106
|
-
* the catalog is Cauthy's, edited in its dashboard, and pushing again would
|
|
107
|
-
* overwrite what was edited there.
|
|
108
|
-
*/
|
|
109
|
-
declare function pushPolicy(o: PushPolicyOptions): Promise<void>;
|
|
110
|
-
|
|
111
4
|
/** How an application is set up to sign its people in with Cauthy. */
|
|
112
5
|
interface CauthyOptions {
|
|
113
6
|
/** Cauthy's public address, e.g. `https://id.example.com`. Default: `CAUTHY_ISSUER`. */
|
|
@@ -123,7 +16,7 @@ interface CauthyOptions {
|
|
|
123
16
|
secret?: string;
|
|
124
17
|
/**
|
|
125
18
|
* The system this application is, as its organizations are filed under in
|
|
126
|
-
* Cauthy (`"
|
|
19
|
+
* Cauthy (`"acme-crm"`). When set, a session's organizations are that
|
|
127
20
|
* system's. Default: `CAUTHY_SYSTEM`.
|
|
128
21
|
*/
|
|
129
22
|
system?: string;
|
|
@@ -220,6 +113,54 @@ interface SessionOrganization {
|
|
|
220
113
|
permissions?: string[];
|
|
221
114
|
/** What the person is denied here, whatever else allows it. */
|
|
222
115
|
denied?: string[];
|
|
116
|
+
/**
|
|
117
|
+
* Permissions that hold only when their condition does (an amount under a
|
|
118
|
+
* limit, the person's own records…). They are in neither list above: `can`
|
|
119
|
+
* answers no for them, and `auth.check` asks Cauthy. Present, maybe empty,
|
|
120
|
+
* whenever `permissions` is.
|
|
121
|
+
*/
|
|
122
|
+
conditional?: ConditionalPermission[];
|
|
123
|
+
}
|
|
124
|
+
/** A permission with a condition: Cauthy decides it per question (`auth.check`). */
|
|
125
|
+
interface ConditionalPermission {
|
|
126
|
+
resource: string;
|
|
127
|
+
action: string;
|
|
128
|
+
effect: 'allow' | 'deny';
|
|
129
|
+
}
|
|
130
|
+
/** What to ask Cauthy about: an action on a resource, with what the conditions read of it. */
|
|
131
|
+
interface CheckQuestion {
|
|
132
|
+
resource: string;
|
|
133
|
+
action: string;
|
|
134
|
+
/** What a condition reads as `resource.attrs`: `{ amount: 500 }`. */
|
|
135
|
+
attributes?: Record<string, unknown>;
|
|
136
|
+
/** The record's id, as a condition reads it (`resource.id`). */
|
|
137
|
+
resourceId?: string;
|
|
138
|
+
/** Whose the record is (`resource.owner_id`): `resource.owner_id == subject.id`. */
|
|
139
|
+
ownerId?: string;
|
|
140
|
+
}
|
|
141
|
+
/** An organization, by its id or as the session has it. */
|
|
142
|
+
type OrganizationRef = string | {
|
|
143
|
+
id: string;
|
|
144
|
+
};
|
|
145
|
+
/** The rule that decided a check. */
|
|
146
|
+
interface CheckRule {
|
|
147
|
+
/** A permission of the person's role, or an exception given to the person. */
|
|
148
|
+
source: 'role' | 'exception';
|
|
149
|
+
/** The role, when `source` is `role`. */
|
|
150
|
+
role?: string;
|
|
151
|
+
kind: string;
|
|
152
|
+
resource: string;
|
|
153
|
+
action: string;
|
|
154
|
+
effect: 'allow' | 'deny';
|
|
155
|
+
condition?: string;
|
|
156
|
+
}
|
|
157
|
+
/** Cauthy's answer to a check. */
|
|
158
|
+
interface CheckResult {
|
|
159
|
+
allowed: boolean;
|
|
160
|
+
/** Why, in words: "allowed by role accountant: invoices:approve". */
|
|
161
|
+
reason: string;
|
|
162
|
+
/** The rule that decided; absent when none did (nothing allows it). */
|
|
163
|
+
rule?: CheckRule;
|
|
223
164
|
}
|
|
224
165
|
/** A signed-in person, as the server sees them. */
|
|
225
166
|
interface Session {
|
|
@@ -250,6 +191,242 @@ declare class CauthyConfigError extends Error {
|
|
|
250
191
|
constructor(message: string);
|
|
251
192
|
}
|
|
252
193
|
|
|
194
|
+
/** The part of an organization that says what its member may do. */
|
|
195
|
+
interface Permitted {
|
|
196
|
+
/** "resource:action" entries the person is allowed; "*" is any. Absent when the system keeps no catalog in Cauthy. */
|
|
197
|
+
permissions?: string[];
|
|
198
|
+
/** Entries the person is denied whatever else allows them. */
|
|
199
|
+
denied?: string[];
|
|
200
|
+
/** Permissions with a condition: in neither list, so `can` never counts them. Ask with `auth.check`. */
|
|
201
|
+
conditional?: ConditionalPermission[];
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Whether the person may do an action on a resource in an organization:
|
|
205
|
+
* allowed by some entry, and denied by none. A denial wins.
|
|
206
|
+
*
|
|
207
|
+
* An organization of a system that keeps no catalog in Cauthy carries no
|
|
208
|
+
* permissions, and the answer is `false`: decide by its `role` instead.
|
|
209
|
+
*
|
|
210
|
+
* A permission with a condition (`organization.conditional`) is not in the
|
|
211
|
+
* lists, so `can` answers `false` for what only it allows: the condition reads
|
|
212
|
+
* the record at hand, which only Cauthy can weigh. Ask with `auth.check`
|
|
213
|
+
* (`organizations.check` in the browser).
|
|
214
|
+
*
|
|
215
|
+
* if (!can(organization, 'invoicing', 'write')) return forbidden()
|
|
216
|
+
*/
|
|
217
|
+
declare function can(organization: Permitted | null | undefined, resource: string, action: string): boolean;
|
|
218
|
+
/** Something a role may do: an action on a resource, in organizations of a kind ("*", the default, is every kind). */
|
|
219
|
+
interface PolicyPermission {
|
|
220
|
+
kind?: string;
|
|
221
|
+
resource: string;
|
|
222
|
+
action: string;
|
|
223
|
+
/**
|
|
224
|
+
* When it holds, in CEL: `resource.attrs.amount <= 1000000`. A permission
|
|
225
|
+
* with one is decided by Cauthy per question (`auth.check`), never by `can`.
|
|
226
|
+
*/
|
|
227
|
+
condition?: string;
|
|
228
|
+
}
|
|
229
|
+
/** The type of an attribute a condition may read: `list` is any JSON array. */
|
|
230
|
+
type AttributeType = 'string' | 'number' | 'bool' | 'list';
|
|
231
|
+
/** A resource of a system's catalog: the actions done on it and the attributes its conditions read. */
|
|
232
|
+
interface CatalogResource {
|
|
233
|
+
resource: string;
|
|
234
|
+
description?: string;
|
|
235
|
+
actions: string[];
|
|
236
|
+
/** Name → type, as `resource.attrs.<name>` in a condition. */
|
|
237
|
+
attributes?: Record<string, AttributeType>;
|
|
238
|
+
}
|
|
239
|
+
interface PolicyRole {
|
|
240
|
+
role: string;
|
|
241
|
+
name?: string;
|
|
242
|
+
description?: string;
|
|
243
|
+
/** Roles whose permissions this one has as well. */
|
|
244
|
+
inherits?: string[];
|
|
245
|
+
permissions?: PolicyPermission[];
|
|
246
|
+
}
|
|
247
|
+
type PermissionShape = {
|
|
248
|
+
readonly kind?: string;
|
|
249
|
+
readonly resource: string;
|
|
250
|
+
readonly action: string;
|
|
251
|
+
readonly condition?: string;
|
|
252
|
+
};
|
|
253
|
+
/** A role as `definePolicy` reads it: any `PolicyRole`, kept as written. */
|
|
254
|
+
type RoleShape = {
|
|
255
|
+
readonly role: string;
|
|
256
|
+
readonly name?: string;
|
|
257
|
+
readonly description?: string;
|
|
258
|
+
readonly inherits?: readonly string[];
|
|
259
|
+
readonly permissions?: readonly PermissionShape[];
|
|
260
|
+
};
|
|
261
|
+
/** A resource as `definePolicy` reads it: any `CatalogResource`, kept as written. */
|
|
262
|
+
type ResourceShape = {
|
|
263
|
+
readonly resource: string;
|
|
264
|
+
readonly description?: string;
|
|
265
|
+
readonly actions: readonly string[];
|
|
266
|
+
readonly attributes?: {
|
|
267
|
+
readonly [name: string]: AttributeType;
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
type Named<S extends string> = S extends '*' ? string : S;
|
|
271
|
+
type PermissionsIn<R> = R extends {
|
|
272
|
+
readonly permissions: readonly (infer P)[];
|
|
273
|
+
} ? P extends {
|
|
274
|
+
readonly resource: infer Res extends string;
|
|
275
|
+
readonly action: infer Act extends string;
|
|
276
|
+
} ? `${Named<Res>}:${Named<Act>}` : never : never;
|
|
277
|
+
type ValueOf<T> = T extends 'string' ? string : T extends 'number' ? number : T extends 'bool' ? boolean : T extends 'list' ? unknown[] : never;
|
|
278
|
+
/** What a check may say about one declared resource. */
|
|
279
|
+
type QuestionAbout<E> = E extends {
|
|
280
|
+
readonly resource: infer R extends string;
|
|
281
|
+
readonly actions: readonly (infer A extends string)[];
|
|
282
|
+
} ? {
|
|
283
|
+
resource: R;
|
|
284
|
+
action: A;
|
|
285
|
+
attributes?: E extends {
|
|
286
|
+
readonly attributes: infer T;
|
|
287
|
+
} ? {
|
|
288
|
+
[K in keyof T]?: ValueOf<T[K]>;
|
|
289
|
+
} : Record<string, never>;
|
|
290
|
+
resourceId?: string;
|
|
291
|
+
ownerId?: string;
|
|
292
|
+
} : never;
|
|
293
|
+
/**
|
|
294
|
+
* What a role of a catalog that declares its resources may name: a declared
|
|
295
|
+
* resource with one of its actions, or "*", or one of Cauthy's own powers.
|
|
296
|
+
*/
|
|
297
|
+
type PermissionFor<C extends readonly ResourceShape[]> = {
|
|
298
|
+
readonly kind?: string;
|
|
299
|
+
readonly condition?: string;
|
|
300
|
+
} & ((C[number] extends infer E ? E extends {
|
|
301
|
+
readonly resource: infer R extends string;
|
|
302
|
+
readonly actions: readonly (infer A extends string)[];
|
|
303
|
+
} ? {
|
|
304
|
+
readonly resource: R;
|
|
305
|
+
readonly action: A | '*';
|
|
306
|
+
} : never : never) | {
|
|
307
|
+
readonly resource: '*';
|
|
308
|
+
readonly action: string;
|
|
309
|
+
} | {
|
|
310
|
+
readonly resource: `cauthy:${string}`;
|
|
311
|
+
readonly action: string;
|
|
312
|
+
});
|
|
313
|
+
type RoleFor<C extends readonly ResourceShape[]> = Omit<RoleShape, 'permissions'> & {
|
|
314
|
+
readonly permissions?: readonly PermissionFor<C>[];
|
|
315
|
+
};
|
|
316
|
+
/** The roles a catalog names: `RoleOf<typeof policy>`. */
|
|
317
|
+
type RoleOf<P> = P extends Policy<infer R, any, any> ? R : never;
|
|
318
|
+
/** The "resource:action" permissions a catalog names: `PermissionOf<typeof policy>`. */
|
|
319
|
+
type PermissionOf<P> = P extends Policy<any, infer X, any> ? X : never;
|
|
320
|
+
/** What a check about this catalog may ask: `CheckOf<typeof policy>`. Any resource when it declares none. */
|
|
321
|
+
type CheckOf<P> = P extends Policy<any, any, infer Q> ? Q : never;
|
|
322
|
+
/** The fields of a question: whatever else the asker takes (the organization, the person) passes through. */
|
|
323
|
+
type QuestionKeys = keyof CheckQuestion;
|
|
324
|
+
interface Policy<Role extends string = string, Permission extends string = string, Question extends CheckQuestion = CheckQuestion> {
|
|
325
|
+
/** The catalog as Cauthy takes it: `pushPolicy({ roles: policy.roles })`. */
|
|
326
|
+
roles: PolicyRole[];
|
|
327
|
+
/** The resources the system declares, as Cauthy takes them; empty when it declares none. */
|
|
328
|
+
catalog: CatalogResource[];
|
|
329
|
+
/** Every role's name. */
|
|
330
|
+
roleNames: Role[];
|
|
331
|
+
/** Every permission some role has, as "resource:action". */
|
|
332
|
+
permissions: Permission[];
|
|
333
|
+
/**
|
|
334
|
+
* Whether the person may do this in the organization: `can(org, 'ledger:write')`.
|
|
335
|
+
* It reads what Cauthy sent with the session, so a catalog edited in Cauthy
|
|
336
|
+
* since this file was written is still what decides. A permission with a
|
|
337
|
+
* condition is not there: ask with `check`.
|
|
338
|
+
*/
|
|
339
|
+
can(organization: Permitted | null | undefined, permission: Permission): boolean;
|
|
340
|
+
/** Whether the person's role in the organization is one of these. */
|
|
341
|
+
hasRole(organization: {
|
|
342
|
+
role: string;
|
|
343
|
+
} | null | undefined, ...roles: Role[]): boolean;
|
|
344
|
+
/**
|
|
345
|
+
* What a role may do by this catalog, with what it inherits: for showing a
|
|
346
|
+
* role, never for deciding about a person (their exceptions are not here).
|
|
347
|
+
*/
|
|
348
|
+
permissionsOf(role: Role): Permission[];
|
|
349
|
+
/**
|
|
350
|
+
* Asks Cauthy, with the resource, action and attributes typed by the
|
|
351
|
+
* catalog. Give it whoever asks: the server's `auth` with the request,
|
|
352
|
+
* the browser's `organizations`, or the application's `system`.
|
|
353
|
+
*
|
|
354
|
+
* await policy.check(auth, request, { organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })
|
|
355
|
+
* await policy.check(auth.system, { organizationId, userId, resource: 'invoices', action: 'read' })
|
|
356
|
+
*/
|
|
357
|
+
check<I extends CheckQuestion>(asker: {
|
|
358
|
+
check(input: I): Promise<CheckResult>;
|
|
359
|
+
}, input: Omit<I, QuestionKeys> & Question): Promise<CheckResult>;
|
|
360
|
+
check<R, I extends CheckQuestion>(asker: {
|
|
361
|
+
check(request: R, input: I): Promise<CheckResult>;
|
|
362
|
+
}, request: R, input: Omit<I, QuestionKeys> & Question): Promise<CheckResult>;
|
|
363
|
+
}
|
|
364
|
+
/** A catalog with its resources declared, for `definePolicy`. */
|
|
365
|
+
interface PolicyDefinition<C extends readonly ResourceShape[], T extends readonly RoleShape[]> {
|
|
366
|
+
catalog: C;
|
|
367
|
+
roles: T;
|
|
368
|
+
}
|
|
369
|
+
/** Gives a catalog of roles its types. See the top of this section. */
|
|
370
|
+
declare function definePolicy<const T extends readonly RoleShape[]>(roles: T): Policy<T[number]['role'], PermissionsIn<T[number]>>;
|
|
371
|
+
/** Gives a catalog of resources and roles its types: a role names only what the catalog declares. */
|
|
372
|
+
declare function definePolicy<const C extends readonly ResourceShape[], const T extends readonly RoleFor<C>[]>(definition: PolicyDefinition<C, T>): Policy<T[number]['role'], PermissionsIn<T[number]>, QuestionAbout<C[number]>>;
|
|
373
|
+
/** A system's policy as Cauthy has it: the resources it declares (maybe none) and its roles. */
|
|
374
|
+
interface SystemPolicy {
|
|
375
|
+
catalog: CatalogResource[];
|
|
376
|
+
roles: PolicyRole[];
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* A TypeScript module that defines the catalog given, for `cauthy-auth policy
|
|
380
|
+
* --pull` to write: the application's types then come from the catalog
|
|
381
|
+
* Cauthy has. With resources declared it is `definePolicy({ catalog, roles })`;
|
|
382
|
+
* without, the list of roles alone, as it always was.
|
|
383
|
+
*/
|
|
384
|
+
declare function policySource(system: string, read: PolicyRole[] | {
|
|
385
|
+
catalog?: CatalogResource[];
|
|
386
|
+
roles: PolicyRole[];
|
|
387
|
+
}): string;
|
|
388
|
+
/** Reads a system's catalog of roles from Cauthy, with a personal access token. */
|
|
389
|
+
declare function pullPolicy(o?: Omit<PushPolicyOptions, 'roles'>): Promise<PolicyRole[]>;
|
|
390
|
+
/** Reads the resources a system declares (empty when it declares none), with a personal access token. */
|
|
391
|
+
declare function pullCatalog(o?: Omit<PushPolicyOptions, 'roles'>): Promise<CatalogResource[]>;
|
|
392
|
+
interface PushPolicyOptions {
|
|
393
|
+
/** The system whose catalog this is. Default: `CAUTHY_SYSTEM`. */
|
|
394
|
+
system?: string;
|
|
395
|
+
roles: PolicyRole[];
|
|
396
|
+
/**
|
|
397
|
+
* The resources the system declares. Given, they are sent before the roles,
|
|
398
|
+
* which Cauthy then checks against them; left out, the catalog Cauthy has
|
|
399
|
+
* stays as it is.
|
|
400
|
+
*/
|
|
401
|
+
catalog?: CatalogResource[];
|
|
402
|
+
/** Cauthy's address. Default: `CAUTHY_ISSUER`. */
|
|
403
|
+
issuer?: string;
|
|
404
|
+
/** The workspace's slug. Default: `CAUTHY_TENANT`. */
|
|
405
|
+
tenant?: string;
|
|
406
|
+
/**
|
|
407
|
+
* A personal access token: `organizations:manage` reads, and changing a
|
|
408
|
+
* policy or a catalog takes `systems:policy`. Default: `CAUTHY_TOKEN`.
|
|
409
|
+
*/
|
|
410
|
+
token?: string;
|
|
411
|
+
fetch?: typeof fetch;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Gives Cauthy a system's catalog of roles, replacing the one it has. It is
|
|
415
|
+
* the way to load a first catalog from what a system already had; from then on
|
|
416
|
+
* the catalog is Cauthy's, edited in its dashboard, and pushing again would
|
|
417
|
+
* overwrite what was edited there. With `catalog` the declared resources go
|
|
418
|
+
* first: the roles are checked against them.
|
|
419
|
+
*/
|
|
420
|
+
declare function pushPolicy(o: PushPolicyOptions): Promise<void>;
|
|
421
|
+
/**
|
|
422
|
+
* Gives Cauthy the resources a system declares, replacing the ones it has.
|
|
423
|
+
* Cauthy refuses (`catalog_in_use`) to drop a resource or an action the
|
|
424
|
+
* policy still names.
|
|
425
|
+
*/
|
|
426
|
+
declare function pushCatalog(o: Omit<PushPolicyOptions, 'roles' | 'catalog'> & {
|
|
427
|
+
resources: CatalogResource[];
|
|
428
|
+
}): Promise<CatalogResource[]>;
|
|
429
|
+
|
|
253
430
|
/** The key an application signs its assertions with. */
|
|
254
431
|
interface SystemKey {
|
|
255
432
|
/** The private key: PKCS#8 PEM, or a JWK (as an object or its JSON). RSA, for RS256. */
|
|
@@ -269,6 +446,8 @@ interface SystemOptions {
|
|
|
269
446
|
* Default: `CAUTHY_SYSTEM_KEY` (the private key) and `CAUTHY_SYSTEM_KEY_ID`.
|
|
270
447
|
*/
|
|
271
448
|
key?: SystemKey;
|
|
449
|
+
/** The application's system, which `check` asks about. Default: `CAUTHY_SYSTEM`. */
|
|
450
|
+
system?: string;
|
|
272
451
|
fetch?: typeof fetch;
|
|
273
452
|
}
|
|
274
453
|
/** Cauthy refused a request of the application's own. */
|
|
@@ -373,6 +552,25 @@ interface CauthySystem {
|
|
|
373
552
|
policy: {
|
|
374
553
|
get(system: string): Promise<PolicyRole[]>;
|
|
375
554
|
};
|
|
555
|
+
/**
|
|
556
|
+
* The resources one of the application's systems declares, with their
|
|
557
|
+
* actions and the attributes conditions read; empty when it declares none.
|
|
558
|
+
*/
|
|
559
|
+
catalog: {
|
|
560
|
+
get(system: string): Promise<CatalogResource[]>;
|
|
561
|
+
/** Replaces them. Cauthy refuses (`catalog_in_use`) to drop one the policy still names. */
|
|
562
|
+
set(system: string, resources: CatalogResource[]): Promise<CatalogResource[]>;
|
|
563
|
+
};
|
|
564
|
+
/**
|
|
565
|
+
* Asks Cauthy whether a member of one of the system's organizations may do
|
|
566
|
+
* an action on a resource, conditions weighed. A person who is not a member
|
|
567
|
+
* is a no; an organization of another system throws (`organization_not_found`).
|
|
568
|
+
*/
|
|
569
|
+
check(question: CheckQuestion & {
|
|
570
|
+
organizationId: string;
|
|
571
|
+
userId: string;
|
|
572
|
+
system?: string;
|
|
573
|
+
}): Promise<CheckResult>;
|
|
376
574
|
/** The public half of `key`, to serve at the address Cauthy was given (`jwks_uri`). Empty with a secret. */
|
|
377
575
|
publicJwks(): Promise<{
|
|
378
576
|
keys: JWK[];
|
|
@@ -380,4 +578,4 @@ interface CauthySystem {
|
|
|
380
578
|
}
|
|
381
579
|
declare function createSystem(given?: SystemOptions): CauthySystem;
|
|
382
580
|
|
|
383
|
-
export {
|
|
581
|
+
export { type AttributeType as A, definePolicy as B, type CatalogResource as C, policySource as D, pullCatalog as E, pullPolicy as F, pushCatalog as G, pushPolicy as H, type JsonValue as J, type NewMember as N, type Organization as O, type PermissionOf as P, type RoleOf as R, type Session as S, CauthyApiError as a, CauthyConfigError as b, type CauthyOptions as c, type CauthySystem as d, type CheckOf as e, type CheckQuestion as f, type CheckResult as g, type CheckRule as h, type ConditionalPermission as i, type OrganizationMember as j, type OrganizationRef as k, type Permitted as l, type Policy as m, type PolicyDefinition as n, type PolicyPermission as o, type PolicyRole as p, type PublicSession as q, type PushPolicyOptions as r, type SessionOrganization as s, type SessionStatus as t, type SessionUser as u, type SystemKey as v, type SystemOptions as w, type SystemPolicy as x, can as y, createSystem as z };
|
package/dist/vue.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ShallowRef, Plugin } from 'vue';
|
|
2
2
|
import { SessionStore, SessionState, SessionStoreOptions, AuthClient } from './client.mjs';
|
|
3
3
|
export { Account, AccountSession, AuthError, AuthMethods, AuthResult, Passkey, PasskeyKind, SSOConnection } from './client.mjs';
|
|
4
|
-
import {
|
|
5
|
-
export { P as PermissionOf,
|
|
4
|
+
import { q as PublicSession } from './system-0mHrdAgO.mjs';
|
|
5
|
+
export { P as PermissionOf, m as Policy, R as RoleOf, s as SessionOrganization, u as SessionUser, y as can, B as definePolicy } from './system-0mHrdAgO.mjs';
|
|
6
6
|
import './theme.mjs';
|
|
7
7
|
import './validate-sEXG82po.mjs';
|
|
8
8
|
import 'jose';
|
package/dist/vue.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ShallowRef, Plugin } from 'vue';
|
|
2
2
|
import { SessionStore, SessionState, SessionStoreOptions, AuthClient } from './client.js';
|
|
3
3
|
export { Account, AccountSession, AuthError, AuthMethods, AuthResult, Passkey, PasskeyKind, SSOConnection } from './client.js';
|
|
4
|
-
import {
|
|
5
|
-
export { P as PermissionOf,
|
|
4
|
+
import { q as PublicSession } from './system-BIYbS7h2.js';
|
|
5
|
+
export { P as PermissionOf, m as Policy, R as RoleOf, s as SessionOrganization, u as SessionUser, y as can, B as definePolicy } from './system-BIYbS7h2.js';
|
|
6
6
|
import './theme.js';
|
|
7
7
|
import './validate-sEXG82po.js';
|
|
8
8
|
import 'jose';
|
package/dist/vue.js
CHANGED
|
@@ -285,6 +285,12 @@ function checkOrganization(value, required = false) {
|
|
|
285
285
|
if (v.length > MAX_ORGANIZATION) return { field: "organization", code: "too_long", message: `Use at most ${MAX_ORGANIZATION} characters.` };
|
|
286
286
|
return null;
|
|
287
287
|
}
|
|
288
|
+
function checkOrganizationName(value) {
|
|
289
|
+
const v = typeof value === "string" ? value.trim() : "";
|
|
290
|
+
if (v === "") return { field: "name", code: "required", message: "Enter the organization's name." };
|
|
291
|
+
if (v.length > MAX_ORGANIZATION) return { field: "name", code: "too_long", message: `Use at most ${MAX_ORGANIZATION} characters.` };
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
288
294
|
function checkCode(value) {
|
|
289
295
|
const v = typeof value === "string" ? value.trim() : "";
|
|
290
296
|
if (v === "") return { field: "code", code: "required", message: "Enter the code." };
|
|
@@ -537,7 +543,23 @@ function createAuthClient(options = {}) {
|
|
|
537
543
|
add: (id, f) => post("/me/organizations/members/add", { organizationId: id, email: f.email, role: f.role, name: f.name ?? "", locale: f.locale ?? "" }, checkEmail(f.email)),
|
|
538
544
|
setRole: (id, userId, role) => post("/me/organizations/members/role", { organizationId: id, userId, role }, null),
|
|
539
545
|
remove: (id, userId) => post("/me/organizations/members/remove", { organizationId: id, userId }, null),
|
|
540
|
-
inviteAgain: (id, userId, f = {}) => post("/me/organizations/members/invite", { organizationId: id, userId, locale: f.locale ?? "" }, null)
|
|
546
|
+
inviteAgain: (id, userId, f = {}) => post("/me/organizations/members/invite", { organizationId: id, userId, locale: f.locale ?? "" }, null),
|
|
547
|
+
rename: (id, name) => post("/me/organizations/rename", { organizationId: id, name }, checkOrganizationName(name)),
|
|
548
|
+
archive: (id) => post("/me/organizations/archive", { organizationId: id }, null),
|
|
549
|
+
delete: (id) => post("/me/organizations/delete", { organizationId: id }, null),
|
|
550
|
+
async check(q) {
|
|
551
|
+
const organizationId = typeof q.organization === "string" ? q.organization : q.organization?.id ?? "";
|
|
552
|
+
const r = await post("/me/organizations/check", {
|
|
553
|
+
organizationId,
|
|
554
|
+
resource: q.resource,
|
|
555
|
+
action: q.action,
|
|
556
|
+
...q.attributes !== void 0 ? { attributes: q.attributes } : {},
|
|
557
|
+
...q.resourceId !== void 0 ? { resourceId: q.resourceId } : {},
|
|
558
|
+
...q.ownerId !== void 0 ? { ownerId: q.ownerId } : {}
|
|
559
|
+
}, null);
|
|
560
|
+
if (!r.ok) return { allowed: false, reason: r.error.message, error: r.error };
|
|
561
|
+
return { allowed: r.allowed === true, reason: String(r.reason ?? ""), ...r.rule ? { rule: r.rule } : {} };
|
|
562
|
+
}
|
|
541
563
|
},
|
|
542
564
|
account: {
|
|
543
565
|
async get() {
|
|
@@ -741,7 +763,9 @@ function can(organization, resource, action) {
|
|
|
741
763
|
if ((organization.denied ?? []).some((d) => matches(d, resource, action))) return false;
|
|
742
764
|
return organization.permissions.some((p) => matches(p, resource, action));
|
|
743
765
|
}
|
|
744
|
-
function definePolicy(
|
|
766
|
+
function definePolicy(given) {
|
|
767
|
+
const roles = Array.isArray(given) ? given : given.roles;
|
|
768
|
+
const resources = Array.isArray(given) ? [] : given.catalog ?? [];
|
|
745
769
|
const entry = (p) => `${p.resource}:${p.action}`;
|
|
746
770
|
const byName = new Map(roles.map((r) => [r.role, r]));
|
|
747
771
|
const split = (permission) => {
|
|
@@ -756,6 +780,12 @@ function definePolicy(roles) {
|
|
|
756
780
|
...r.inherits ? { inherits: [...r.inherits] } : {},
|
|
757
781
|
...r.permissions ? { permissions: r.permissions.map((p) => ({ ...p })) } : {}
|
|
758
782
|
})),
|
|
783
|
+
catalog: resources.map((c) => ({
|
|
784
|
+
resource: c.resource,
|
|
785
|
+
...c.description !== void 0 ? { description: c.description } : {},
|
|
786
|
+
actions: [...c.actions],
|
|
787
|
+
...c.attributes ? { attributes: { ...c.attributes } } : {}
|
|
788
|
+
})),
|
|
759
789
|
roleNames: roles.map((r) => r.role),
|
|
760
790
|
permissions: [...new Set(roles.flatMap((r) => (r.permissions ?? []).map(entry)))],
|
|
761
791
|
can(organization, permission) {
|
|
@@ -777,6 +807,11 @@ function definePolicy(roles) {
|
|
|
777
807
|
};
|
|
778
808
|
walk(role);
|
|
779
809
|
return [...out];
|
|
810
|
+
},
|
|
811
|
+
// The types did the work; this only hands the question on, as a method of
|
|
812
|
+
// the asker so it keeps its `this`.
|
|
813
|
+
check(asker, ...args) {
|
|
814
|
+
return asker.check(...args);
|
|
780
815
|
}
|
|
781
816
|
};
|
|
782
817
|
}
|