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
package/dist/express.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
import { C as Cauthy } from './cauthy-
|
|
3
|
-
import { S as Session } from './system-
|
|
2
|
+
import { C as Cauthy } from './cauthy-BXgsZ-Um.mjs';
|
|
3
|
+
import { S as Session } from './system-0mHrdAgO.mjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.mjs';
|
|
6
6
|
|
package/dist/express.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
import { C as Cauthy } from './cauthy-
|
|
3
|
-
import { S as Session } from './system-
|
|
2
|
+
import { C as Cauthy } from './cauthy-CHENs452.js';
|
|
3
|
+
import { S as Session } from './system-BIYbS7h2.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.js';
|
|
6
6
|
|
package/dist/fastify.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyReply, FastifyPluginAsync } from 'fastify';
|
|
2
|
-
import { C as Cauthy } from './cauthy-
|
|
3
|
-
import { S as Session } from './system-
|
|
2
|
+
import { C as Cauthy } from './cauthy-BXgsZ-Um.mjs';
|
|
3
|
+
import { S as Session } from './system-0mHrdAgO.mjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.mjs';
|
|
6
6
|
|
package/dist/fastify.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyReply, FastifyPluginAsync } from 'fastify';
|
|
2
|
-
import { C as Cauthy } from './cauthy-
|
|
3
|
-
import { S as Session } from './system-
|
|
2
|
+
import { C as Cauthy } from './cauthy-CHENs452.js';
|
|
3
|
+
import { S as Session } from './system-BIYbS7h2.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.js';
|
|
6
6
|
|
package/dist/hono.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MiddlewareHandler } from 'hono';
|
|
2
|
-
import { C as Cauthy } from './cauthy-
|
|
3
|
-
import { S as Session } from './system-
|
|
2
|
+
import { C as Cauthy } from './cauthy-BXgsZ-Um.mjs';
|
|
3
|
+
import { S as Session } from './system-0mHrdAgO.mjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.mjs';
|
|
6
6
|
|
package/dist/hono.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MiddlewareHandler } from 'hono';
|
|
2
|
-
import { C as Cauthy } from './cauthy-
|
|
3
|
-
import { S as Session } from './system-
|
|
2
|
+
import { C as Cauthy } from './cauthy-CHENs452.js';
|
|
3
|
+
import { S as Session } from './system-BIYbS7h2.js';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.js';
|
|
6
6
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-
|
|
2
|
-
export { C as
|
|
1
|
+
export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-BXgsZ-Um.mjs';
|
|
2
|
+
export { A as AttributeType, C as CatalogResource, a as CauthyApiError, b as CauthyConfigError, c as CauthyOptions, d as CauthySystem, e as CheckOf, f as CheckQuestion, g as CheckResult, h as CheckRule, i as ConditionalPermission, J as JsonValue, N as NewMember, O as Organization, j as OrganizationMember, k as OrganizationRef, P as PermissionOf, l as Permitted, m as Policy, n as PolicyDefinition, o as PolicyPermission, p as PolicyRole, q as PublicSession, r as PushPolicyOptions, R as RoleOf, S as Session, s as SessionOrganization, t as SessionStatus, u as SessionUser, v as SystemKey, w as SystemOptions, x as SystemPolicy, y as can, z as createSystem, B as definePolicy, D as policySource, E as pullCatalog, F as pullPolicy, G as pushCatalog, H as pushPolicy } from './system-0mHrdAgO.mjs';
|
|
3
3
|
export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, StackmythTokens, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth, tokensFromStackmyth } from './theme.mjs';
|
|
4
4
|
export { A as AuthField, D as DEFAULT_PASSWORD_POLICY, F as FieldProblem, M as MIN_PASSWORD, P as PasswordClass, a as PasswordLocale, b as PasswordPolicy, c as PasswordReason, d as checkCode, e as checkEmail, f as checkName, g as checkNewPassword, h as checkPassword, i as describePasswordPolicy, j as explainPasswordProblems, p as passwordPolicyOf, k as passwordProblems } from './validate-sEXG82po.mjs';
|
|
5
5
|
import { JWTVerifyGetKey } from 'jose';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-
|
|
2
|
-
export { C as
|
|
1
|
+
export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-CHENs452.js';
|
|
2
|
+
export { A as AttributeType, C as CatalogResource, a as CauthyApiError, b as CauthyConfigError, c as CauthyOptions, d as CauthySystem, e as CheckOf, f as CheckQuestion, g as CheckResult, h as CheckRule, i as ConditionalPermission, J as JsonValue, N as NewMember, O as Organization, j as OrganizationMember, k as OrganizationRef, P as PermissionOf, l as Permitted, m as Policy, n as PolicyDefinition, o as PolicyPermission, p as PolicyRole, q as PublicSession, r as PushPolicyOptions, R as RoleOf, S as Session, s as SessionOrganization, t as SessionStatus, u as SessionUser, v as SystemKey, w as SystemOptions, x as SystemPolicy, y as can, z as createSystem, B as definePolicy, D as policySource, E as pullCatalog, F as pullPolicy, G as pushCatalog, H as pushPolicy } from './system-BIYbS7h2.js';
|
|
3
3
|
export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, StackmythTokens, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth, tokensFromStackmyth } from './theme.js';
|
|
4
4
|
export { A as AuthField, D as DEFAULT_PASSWORD_POLICY, F as FieldProblem, M as MIN_PASSWORD, P as PasswordClass, a as PasswordLocale, b as PasswordPolicy, c as PasswordReason, d as checkCode, e as checkEmail, f as checkName, g as checkNewPassword, h as checkPassword, i as describePasswordPolicy, j as explainPasswordProblems, p as passwordPolicyOf, k as passwordProblems } from './validate-sEXG82po.js';
|
|
5
5
|
import { JWTVerifyGetKey } from 'jose';
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,9 @@ __export(src_exports, {
|
|
|
41
41
|
passwordPolicyOf: () => passwordPolicyOf,
|
|
42
42
|
passwordProblems: () => passwordProblems,
|
|
43
43
|
policySource: () => policySource,
|
|
44
|
+
pullCatalog: () => pullCatalog,
|
|
44
45
|
pullPolicy: () => pullPolicy,
|
|
46
|
+
pushCatalog: () => pushCatalog,
|
|
45
47
|
pushPolicy: () => pushPolicy,
|
|
46
48
|
pushTheme: () => pushTheme,
|
|
47
49
|
themeFromStackmyth: () => themeFromStackmyth,
|
|
@@ -107,9 +109,6 @@ async function unseal(sealed, key) {
|
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
111
|
|
|
110
|
-
// src/system.ts
|
|
111
|
-
var import_jose2 = require("jose");
|
|
112
|
-
|
|
113
112
|
// src/url.ts
|
|
114
113
|
function withoutTrailingSlashes(s) {
|
|
115
114
|
let end = s.length;
|
|
@@ -117,6 +116,218 @@ function withoutTrailingSlashes(s) {
|
|
|
117
116
|
return s.slice(0, end);
|
|
118
117
|
}
|
|
119
118
|
|
|
119
|
+
// src/permissions.ts
|
|
120
|
+
function matches(entry, resource, action) {
|
|
121
|
+
const i = entry.lastIndexOf(":");
|
|
122
|
+
if (i < 0) return false;
|
|
123
|
+
const r = entry.slice(0, i);
|
|
124
|
+
const a = entry.slice(i + 1);
|
|
125
|
+
return (r === "*" || r === resource) && (a === "*" || a === action);
|
|
126
|
+
}
|
|
127
|
+
function can(organization, resource, action) {
|
|
128
|
+
if (!organization?.permissions) return false;
|
|
129
|
+
if ((organization.denied ?? []).some((d) => matches(d, resource, action))) return false;
|
|
130
|
+
return organization.permissions.some((p) => matches(p, resource, action));
|
|
131
|
+
}
|
|
132
|
+
function definePolicy(given) {
|
|
133
|
+
const roles = Array.isArray(given) ? given : given.roles;
|
|
134
|
+
const resources = Array.isArray(given) ? [] : given.catalog ?? [];
|
|
135
|
+
const entry = (p) => `${p.resource}:${p.action}`;
|
|
136
|
+
const byName = new Map(roles.map((r) => [r.role, r]));
|
|
137
|
+
const split = (permission) => {
|
|
138
|
+
const i = permission.lastIndexOf(":");
|
|
139
|
+
return i < 0 ? [permission, ""] : [permission.slice(0, i), permission.slice(i + 1)];
|
|
140
|
+
};
|
|
141
|
+
return {
|
|
142
|
+
roles: roles.map((r) => ({
|
|
143
|
+
role: r.role,
|
|
144
|
+
...r.name !== void 0 ? { name: r.name } : {},
|
|
145
|
+
...r.description !== void 0 ? { description: r.description } : {},
|
|
146
|
+
...r.inherits ? { inherits: [...r.inherits] } : {},
|
|
147
|
+
...r.permissions ? { permissions: r.permissions.map((p) => ({ ...p })) } : {}
|
|
148
|
+
})),
|
|
149
|
+
catalog: resources.map((c) => ({
|
|
150
|
+
resource: c.resource,
|
|
151
|
+
...c.description !== void 0 ? { description: c.description } : {},
|
|
152
|
+
actions: [...c.actions],
|
|
153
|
+
...c.attributes ? { attributes: { ...c.attributes } } : {}
|
|
154
|
+
})),
|
|
155
|
+
roleNames: roles.map((r) => r.role),
|
|
156
|
+
permissions: [...new Set(roles.flatMap((r) => (r.permissions ?? []).map(entry)))],
|
|
157
|
+
can(organization, permission) {
|
|
158
|
+
const [resource, action] = split(permission);
|
|
159
|
+
return can(organization, resource, action);
|
|
160
|
+
},
|
|
161
|
+
hasRole(organization, ...wanted) {
|
|
162
|
+
return organization != null && wanted.includes(organization.role);
|
|
163
|
+
},
|
|
164
|
+
permissionsOf(role) {
|
|
165
|
+
const seen = /* @__PURE__ */ new Set();
|
|
166
|
+
const out2 = /* @__PURE__ */ new Set();
|
|
167
|
+
const walk = (name) => {
|
|
168
|
+
if (seen.has(name)) return;
|
|
169
|
+
seen.add(name);
|
|
170
|
+
const r = byName.get(name);
|
|
171
|
+
for (const p of r?.permissions ?? []) out2.add(entry(p));
|
|
172
|
+
for (const parent of r?.inherits ?? []) walk(parent);
|
|
173
|
+
};
|
|
174
|
+
walk(role);
|
|
175
|
+
return [...out2];
|
|
176
|
+
},
|
|
177
|
+
// The types did the work; this only hands the question on, as a method of
|
|
178
|
+
// the asker so it keeps its `this`.
|
|
179
|
+
check(asker, ...args) {
|
|
180
|
+
return asker.check(...args);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
var IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
185
|
+
function policySource(system, read) {
|
|
186
|
+
const roles = Array.isArray(read) ? read : read.roles;
|
|
187
|
+
const catalog = Array.isArray(read) ? [] : read.catalog ?? [];
|
|
188
|
+
const text = (v) => JSON.stringify(v);
|
|
189
|
+
const key = (k) => IDENT.test(k) ? k : text(k);
|
|
190
|
+
const one = (r, pad) => {
|
|
191
|
+
const parts = [`role: ${text(r.role)}`];
|
|
192
|
+
if (r.name) parts.push(`name: ${text(r.name)}`);
|
|
193
|
+
if (r.description) parts.push(`description: ${text(r.description)}`);
|
|
194
|
+
if (r.inherits?.length) parts.push(`inherits: [${r.inherits.map(text).join(", ")}]`);
|
|
195
|
+
if (r.permissions?.length) {
|
|
196
|
+
const list = r.permissions.map((p) => `${pad} { ${[
|
|
197
|
+
...p.kind && p.kind !== "*" ? [`${key("kind")}: ${text(p.kind)}`] : [],
|
|
198
|
+
`resource: ${text(p.resource)}`,
|
|
199
|
+
`action: ${text(p.action)}`,
|
|
200
|
+
...p.condition ? [`condition: ${text(p.condition)}`] : []
|
|
201
|
+
].join(", ")} },`);
|
|
202
|
+
parts.push(`permissions: [
|
|
203
|
+
${list.join("\n")}
|
|
204
|
+
${pad} ]`);
|
|
205
|
+
}
|
|
206
|
+
return `${pad} {
|
|
207
|
+
${pad} ${parts.join(`,
|
|
208
|
+
${pad} `)},
|
|
209
|
+
${pad} },`;
|
|
210
|
+
};
|
|
211
|
+
const resource = (c) => {
|
|
212
|
+
const parts = [`resource: ${text(c.resource)}`];
|
|
213
|
+
if (c.description) parts.push(`description: ${text(c.description)}`);
|
|
214
|
+
parts.push(`actions: [${c.actions.map(text).join(", ")}]`);
|
|
215
|
+
const attrs = Object.entries(c.attributes ?? {});
|
|
216
|
+
if (attrs.length) parts.push(`attributes: { ${attrs.map(([k, v]) => `${key(k)}: ${text(v)}`).join(", ")} }`);
|
|
217
|
+
return ` { ${parts.join(", ")} },`;
|
|
218
|
+
};
|
|
219
|
+
const head = `// The catalog of roles of ${text(system)}, as Cauthy has it.
|
|
220
|
+
// Written by \`cauthy-auth policy --pull\`: run it again after the catalog
|
|
221
|
+
// changes, and do not edit this file by hand.
|
|
222
|
+
`;
|
|
223
|
+
if (catalog.length === 0) {
|
|
224
|
+
return `${head}
|
|
225
|
+
import { definePolicy, type PermissionOf, type RoleOf } from 'cauthy-auth'
|
|
226
|
+
|
|
227
|
+
export const policy = definePolicy([
|
|
228
|
+
${roles.map((r) => one(r, "")).join("\n")}
|
|
229
|
+
])
|
|
230
|
+
|
|
231
|
+
export const { can, hasRole } = policy
|
|
232
|
+
export type Role = RoleOf<typeof policy>
|
|
233
|
+
export type Permission = PermissionOf<typeof policy>
|
|
234
|
+
`;
|
|
235
|
+
}
|
|
236
|
+
return `${head}
|
|
237
|
+
import { definePolicy, type CheckOf, type PermissionOf, type RoleOf } from 'cauthy-auth'
|
|
238
|
+
|
|
239
|
+
export const policy = definePolicy({
|
|
240
|
+
catalog: [
|
|
241
|
+
${catalog.map(resource).join("\n")}
|
|
242
|
+
],
|
|
243
|
+
roles: [
|
|
244
|
+
${roles.map((r) => one(r, " ")).join("\n")}
|
|
245
|
+
],
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
export const { can, hasRole } = policy
|
|
249
|
+
export type Role = RoleOf<typeof policy>
|
|
250
|
+
export type Permission = PermissionOf<typeof policy>
|
|
251
|
+
/** What a check may ask: \`policy.check(auth, request, { organization, ...question })\`. */
|
|
252
|
+
export type Check = CheckOf<typeof policy>
|
|
253
|
+
`;
|
|
254
|
+
}
|
|
255
|
+
function reach(o, doing) {
|
|
256
|
+
const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
|
|
257
|
+
const r = {
|
|
258
|
+
issuer: withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? ""),
|
|
259
|
+
system: o.system ?? env4("CAUTHY_SYSTEM") ?? "",
|
|
260
|
+
tenant: o.tenant ?? env4("CAUTHY_TENANT") ?? "",
|
|
261
|
+
token: o.token ?? env4("CAUTHY_TOKEN") ?? ""
|
|
262
|
+
};
|
|
263
|
+
for (const [name, v] of Object.entries({ CAUTHY_ISSUER: r.issuer, CAUTHY_SYSTEM: r.system, CAUTHY_TENANT: r.tenant, CAUTHY_TOKEN: r.token })) {
|
|
264
|
+
if (v === "") throw new Error(`cauthy-auth: ${name} is required to ${doing}`);
|
|
265
|
+
}
|
|
266
|
+
return { ...r, fetch: o.fetch ?? fetch };
|
|
267
|
+
}
|
|
268
|
+
async function systemCall(r, method, what, body) {
|
|
269
|
+
const res = await r.fetch(`${r.issuer}/v1/systems/${encodeURIComponent(r.system)}/${what}`, {
|
|
270
|
+
...method === "PUT" ? { method } : {},
|
|
271
|
+
headers: {
|
|
272
|
+
authorization: `Bearer ${r.token}`,
|
|
273
|
+
"x-tenant-key": r.tenant,
|
|
274
|
+
...body === void 0 ? { accept: "application/json" } : { "content-type": "application/json" }
|
|
275
|
+
},
|
|
276
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
277
|
+
});
|
|
278
|
+
const answer = await res.json().catch(() => null);
|
|
279
|
+
if (!res.ok) {
|
|
280
|
+
const verb = method === "GET" ? `refused to give the ${what}` : `refused the ${what}`;
|
|
281
|
+
throw new Error(`cauthy-auth: Cauthy ${verb} (${res.status}): ${answer?.errors?.[0]?.message ?? res.statusText}`);
|
|
282
|
+
}
|
|
283
|
+
return answer?.data;
|
|
284
|
+
}
|
|
285
|
+
async function pullPolicy(o = {}) {
|
|
286
|
+
const data = await systemCall(reach(o, "read a policy"), "GET", "policy");
|
|
287
|
+
return data?.roles ?? [];
|
|
288
|
+
}
|
|
289
|
+
async function pullCatalog(o = {}) {
|
|
290
|
+
const data = await systemCall(reach(o, "read a catalog"), "GET", "catalog");
|
|
291
|
+
return data?.resources ?? [];
|
|
292
|
+
}
|
|
293
|
+
async function pushPolicy(o) {
|
|
294
|
+
const r = reach(o, "push a policy");
|
|
295
|
+
if (o.catalog !== void 0) await systemCall(r, "PUT", "catalog", { resources: o.catalog });
|
|
296
|
+
await systemCall(r, "PUT", "policy", { roles: o.roles });
|
|
297
|
+
}
|
|
298
|
+
async function pushCatalog(o) {
|
|
299
|
+
const data = await systemCall(reach(o, "push a catalog"), "PUT", "catalog", { resources: o.resources });
|
|
300
|
+
return data?.resources ?? [];
|
|
301
|
+
}
|
|
302
|
+
function checkWire(q) {
|
|
303
|
+
return {
|
|
304
|
+
resource: q.resource,
|
|
305
|
+
action: q.action,
|
|
306
|
+
...q.resourceId !== void 0 ? { resource_id: q.resourceId } : {},
|
|
307
|
+
...q.ownerId !== void 0 ? { owner_id: q.ownerId } : {},
|
|
308
|
+
...q.attributes !== void 0 ? { attributes: q.attributes } : {}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function checkResultOf(d) {
|
|
312
|
+
const r = d?.rule;
|
|
313
|
+
const rule = r && typeof r === "object" ? {
|
|
314
|
+
source: r.source === "exception" ? "exception" : "role",
|
|
315
|
+
...r.role ? { role: String(r.role) } : {},
|
|
316
|
+
kind: String(r.kind ?? "*"),
|
|
317
|
+
resource: String(r.resource ?? ""),
|
|
318
|
+
action: String(r.action ?? ""),
|
|
319
|
+
effect: r.effect === "allow" ? "allow" : "deny",
|
|
320
|
+
...r.condition ? { condition: String(r.condition) } : {}
|
|
321
|
+
} : void 0;
|
|
322
|
+
return { allowed: d?.allowed === true, reason: String(d?.reason ?? ""), ...rule ? { rule } : {} };
|
|
323
|
+
}
|
|
324
|
+
function organizationIdOf(o) {
|
|
325
|
+
return typeof o === "string" ? o : typeof o?.id === "string" ? o.id : "";
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// src/system.ts
|
|
329
|
+
var import_jose2 = require("jose");
|
|
330
|
+
|
|
120
331
|
// src/theme.ts
|
|
121
332
|
var MAX_RADIUS = 40;
|
|
122
333
|
function withoutComments(css) {
|
|
@@ -534,6 +745,7 @@ function createSystem(given = {}) {
|
|
|
534
745
|
const clientSecret = given.clientSecret ?? env("CAUTHY_CLIENT_SECRET") ?? "";
|
|
535
746
|
const envKey = env("CAUTHY_SYSTEM_KEY");
|
|
536
747
|
const key = given.key ?? (envKey ? { privateKey: envKey, keyId: env("CAUTHY_SYSTEM_KEY_ID") ?? "" } : void 0);
|
|
748
|
+
const ownSystem = given.system ?? env("CAUTHY_SYSTEM") ?? "";
|
|
537
749
|
const doFetch = (...args) => (given.fetch ?? fetch)(...args);
|
|
538
750
|
const tokenEndpoint = `${issuer}/v1/oauth/token`;
|
|
539
751
|
function configured() {
|
|
@@ -651,6 +863,19 @@ function createSystem(given = {}) {
|
|
|
651
863
|
return (await data("GET", `/v1/systems/${id(system)}/policy`)).roles ?? [];
|
|
652
864
|
}
|
|
653
865
|
},
|
|
866
|
+
catalog: {
|
|
867
|
+
async get(system) {
|
|
868
|
+
return (await data("GET", `/v1/systems/${id(system)}/catalog`)).resources ?? [];
|
|
869
|
+
},
|
|
870
|
+
async set(system, resources) {
|
|
871
|
+
return (await data("PUT", `/v1/systems/${id(system)}/catalog`, { resources })).resources ?? [];
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
async check(q) {
|
|
875
|
+
const system = q.system ?? ownSystem;
|
|
876
|
+
if (system === "") throw new CauthyConfigError("name the system to check in (system, or CAUTHY_SYSTEM)");
|
|
877
|
+
return checkResultOf(await data("POST", `/v1/systems/${id(system)}/check`, { organization_id: q.organizationId, user_id: q.userId, ...checkWire(q) }));
|
|
878
|
+
},
|
|
654
879
|
async publicJwks() {
|
|
655
880
|
if (!key) return { keys: [] };
|
|
656
881
|
const { kty, n, e } = asJwk(key) ?? await (0, import_jose2.exportJWK)(await signingKey());
|
|
@@ -798,6 +1023,12 @@ function checkOrganization(value, required = false) {
|
|
|
798
1023
|
if (v.length > MAX_ORGANIZATION) return { field: "organization", code: "too_long", message: `Use at most ${MAX_ORGANIZATION} characters.` };
|
|
799
1024
|
return null;
|
|
800
1025
|
}
|
|
1026
|
+
function checkOrganizationName(value) {
|
|
1027
|
+
const v = typeof value === "string" ? value.trim() : "";
|
|
1028
|
+
if (v === "") return { field: "name", code: "required", message: "Enter the organization's name." };
|
|
1029
|
+
if (v.length > MAX_ORGANIZATION) return { field: "name", code: "too_long", message: `Use at most ${MAX_ORGANIZATION} characters.` };
|
|
1030
|
+
return null;
|
|
1031
|
+
}
|
|
801
1032
|
function checkCode(value) {
|
|
802
1033
|
const v = typeof value === "string" ? value.trim() : "";
|
|
803
1034
|
if (v === "") return { field: "code", code: "required", message: "Enter the code." };
|
|
@@ -929,6 +1160,9 @@ function redirect(location, cookies = []) {
|
|
|
929
1160
|
for (const c of cookies) h.append("set-cookie", c);
|
|
930
1161
|
return new Response(null, { status: 302, headers: h });
|
|
931
1162
|
}
|
|
1163
|
+
function conditionalOf(c) {
|
|
1164
|
+
return { resource: String(c?.resource ?? ""), action: String(c?.action ?? ""), effect: c?.effect === "deny" ? "deny" : "allow" };
|
|
1165
|
+
}
|
|
932
1166
|
function createCauthy(given = {}) {
|
|
933
1167
|
const issuer = withoutTrailingSlashes(given.issuer ?? env2("CAUTHY_ISSUER") ?? "");
|
|
934
1168
|
const clientId = given.clientId ?? env2("CAUTHY_CLIENT_ID") ?? "";
|
|
@@ -957,7 +1191,7 @@ function createCauthy(given = {}) {
|
|
|
957
1191
|
resetPassword: given.pages?.resetPassword ? localPath(given.pages.resetPassword, "/") : void 0,
|
|
958
1192
|
verifyEmail: given.pages?.verifyEmail ? localPath(given.pages.verifyEmail, "/") : void 0
|
|
959
1193
|
};
|
|
960
|
-
const ownSystem = createSystem({ issuer, clientId, clientSecret, key: given.systemKey, fetch: given.fetch });
|
|
1194
|
+
const ownSystem = createSystem({ issuer, clientId, clientSecret, key: given.systemKey, system: system || void 0, fetch: given.fetch });
|
|
961
1195
|
const originOf = (request) => {
|
|
962
1196
|
if (baseURL) return withoutTrailingSlashes(baseURL);
|
|
963
1197
|
const url = new URL(request.url);
|
|
@@ -1092,13 +1326,35 @@ function createCauthy(given = {}) {
|
|
|
1092
1326
|
role: String(o.role ?? ""),
|
|
1093
1327
|
metadata: o.metadata ?? {},
|
|
1094
1328
|
...o.external_id ? { externalId: String(o.external_id) } : {},
|
|
1095
|
-
...Array.isArray(o.permissions) ? { permissions: o.permissions.map(String), denied: Array.isArray(o.denied) ? o.denied.map(String) : [] } : {}
|
|
1329
|
+
...Array.isArray(o.permissions) ? { permissions: o.permissions.map(String), denied: Array.isArray(o.denied) ? o.denied.map(String) : [], conditional: Array.isArray(o.conditional) ? o.conditional.map(conditionalOf) : [] } : {}
|
|
1096
1330
|
})
|
|
1097
1331
|
);
|
|
1098
1332
|
if (orgCache.size > 5e3) orgCache.clear();
|
|
1099
1333
|
orgCache.set(session.accessToken, { at: Date.now(), value });
|
|
1100
1334
|
return value;
|
|
1101
1335
|
}
|
|
1336
|
+
async function decide(token2, question) {
|
|
1337
|
+
const org = organizationIdOf(question.organization);
|
|
1338
|
+
if (org === "") return { allowed: false, reason: "no organization named" };
|
|
1339
|
+
const res = await doFetch(`${issuer}/v1/oauth/organizations/${encodeURIComponent(org)}/check`, {
|
|
1340
|
+
method: "POST",
|
|
1341
|
+
headers: { authorization: `Bearer ${token2}`, "content-type": "application/json", accept: "application/json" },
|
|
1342
|
+
body: JSON.stringify(checkWire(question))
|
|
1343
|
+
}).catch(() => null);
|
|
1344
|
+
if (res === null) throw new CauthyApiError(503, "unavailable", "Cauthy could not be reached to check a permission");
|
|
1345
|
+
const body2 = await res.json().catch(() => null);
|
|
1346
|
+
if (res.ok) return checkResultOf(body2?.data);
|
|
1347
|
+
const first = body2?.errors?.[0];
|
|
1348
|
+
if (res.status === 401 || res.status === 403 || res.status === 404) {
|
|
1349
|
+
return { allowed: false, reason: first?.message ?? (res.status === 401 ? "not signed in" : res.status === 404 ? "not a member of the organization" : "refused") };
|
|
1350
|
+
}
|
|
1351
|
+
throw new CauthyApiError(res.status, first?.code ?? "error", `Cauthy refused to check a permission (${res.status}): ${first?.message ?? res.statusText}`);
|
|
1352
|
+
}
|
|
1353
|
+
async function check(who, question) {
|
|
1354
|
+
const session = "accessToken" in who ? who : await getSession(who);
|
|
1355
|
+
if (!session) return { allowed: false, reason: "not signed in" };
|
|
1356
|
+
return decide(session.accessToken, question);
|
|
1357
|
+
}
|
|
1102
1358
|
const forgetting = (fn) => async (...args) => {
|
|
1103
1359
|
const out2 = await fn(...args);
|
|
1104
1360
|
orgCache.clear();
|
|
@@ -1231,7 +1487,15 @@ function createCauthy(given = {}) {
|
|
|
1231
1487
|
name: String(d?.name ?? ""),
|
|
1232
1488
|
kind: String(d?.kind ?? ""),
|
|
1233
1489
|
role: String(d?.role ?? ""),
|
|
1234
|
-
|
|
1490
|
+
// A Cauthy from before a power says nothing of it: then it is not given.
|
|
1491
|
+
can: {
|
|
1492
|
+
readMembers: d?.can?.read_members === true,
|
|
1493
|
+
manageMembers: d?.can?.manage_members === true,
|
|
1494
|
+
removeMembers: d?.can?.remove_members === true,
|
|
1495
|
+
update: d?.can?.update === true,
|
|
1496
|
+
archive: d?.can?.archive === true,
|
|
1497
|
+
delete: d?.can?.delete === true
|
|
1498
|
+
}
|
|
1235
1499
|
});
|
|
1236
1500
|
const orgMemberOf = (d) => ({
|
|
1237
1501
|
userId: String(d?.user_id ?? ""),
|
|
@@ -1424,7 +1688,10 @@ function createCauthy(given = {}) {
|
|
|
1424
1688
|
"/me/organizations/members/add",
|
|
1425
1689
|
"/me/organizations/members/role",
|
|
1426
1690
|
"/me/organizations/members/remove",
|
|
1427
|
-
"/me/organizations/members/invite"
|
|
1691
|
+
"/me/organizations/members/invite",
|
|
1692
|
+
"/me/organizations/rename",
|
|
1693
|
+
"/me/organizations/archive",
|
|
1694
|
+
"/me/organizations/delete"
|
|
1428
1695
|
].includes(route) || route.startsWith("/sign-in/social/") || route.startsWith("/callback/") || route.startsWith("/me/identities/link/") || route.startsWith("/me/upgrade/social/") || route === "/sign-in/sso" || route === "/sign-in/sso/discover" || route === "/sso/callback";
|
|
1429
1696
|
if (!own) return null;
|
|
1430
1697
|
if (tenant === "") {
|
|
@@ -1895,6 +2162,23 @@ function createCauthy(given = {}) {
|
|
|
1895
2162
|
if (res.error) return refused(res, res.error.code === "weak_password" ? "password" : "email");
|
|
1896
2163
|
return signedIn(request, res.data);
|
|
1897
2164
|
}
|
|
2165
|
+
if (route === "/me/organizations/rename" || route === "/me/organizations/archive" || route === "/me/organizations/delete") {
|
|
2166
|
+
const org = typeof b.organizationId === "string" ? b.organizationId : "";
|
|
2167
|
+
if (!UUID.test(org)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
|
|
2168
|
+
const path = `/v1/auth/me/organizations/${org}`;
|
|
2169
|
+
if (route === "/me/organizations/rename") {
|
|
2170
|
+
const bad = checkOrganizationName(b.name);
|
|
2171
|
+
if (bad) return invalid(bad);
|
|
2172
|
+
const res2 = await as(path, { name: String(b.name).trim() }, "PATCH");
|
|
2173
|
+
if (res2.error) return refused(res2, res2.error.code === "validation_error" ? "name" : void 0);
|
|
2174
|
+
orgCache.delete(mine.token);
|
|
2175
|
+
return json({ status: "renamed", organization: seatOf(res2.data) }, 200, mine.headers);
|
|
2176
|
+
}
|
|
2177
|
+
const res = route === "/me/organizations/archive" ? await as(`${path}/archive`) : await as(path, void 0, "DELETE");
|
|
2178
|
+
if (res.error) return refused(res);
|
|
2179
|
+
orgCache.delete(mine.token);
|
|
2180
|
+
return json({ status: route === "/me/organizations/archive" ? "archived" : "deleted", organizationId: org }, 200, mine.headers);
|
|
2181
|
+
}
|
|
1898
2182
|
if (route.startsWith("/me/organizations/members/")) {
|
|
1899
2183
|
const org = typeof b.organizationId === "string" ? b.organizationId : "";
|
|
1900
2184
|
if (!UUID.test(org)) return problem(400, "invalid_organization", "Say which organization.", void 0, mine.headers);
|
|
@@ -2040,6 +2324,7 @@ function createCauthy(given = {}) {
|
|
|
2040
2324
|
const get = request.method === "GET" || request.method === "HEAD";
|
|
2041
2325
|
const mine = await ownRoute(request, url, route);
|
|
2042
2326
|
if (mine !== null) return mine;
|
|
2327
|
+
if (route === "/me/organizations/check") return checkRoute(request);
|
|
2043
2328
|
if (route === "/login" && get) return login(request, url);
|
|
2044
2329
|
if (route === "/callback" && get) return callback(request, url);
|
|
2045
2330
|
if (route === "/logout" && (get || request.method === "POST")) return logout(request);
|
|
@@ -2066,6 +2351,36 @@ function createCauthy(given = {}) {
|
|
|
2066
2351
|
}
|
|
2067
2352
|
return new Response("Not found", { status: 404 });
|
|
2068
2353
|
}
|
|
2354
|
+
async function checkRoute(request) {
|
|
2355
|
+
if (request.method !== "POST") return new Response("Method not allowed", { status: 405, headers: { allow: "POST" } });
|
|
2356
|
+
if (!ownRequest(request)) return problem(403, "cross_site", "This request did not come from this application.");
|
|
2357
|
+
const b = await body(request);
|
|
2358
|
+
if (b === null) return problem(400, "bad_request", "Send the question as JSON.");
|
|
2359
|
+
const asker = await signedInAs(request);
|
|
2360
|
+
if ("response" in asker) return asker.response;
|
|
2361
|
+
const org = typeof b.organizationId === "string" ? b.organizationId : "";
|
|
2362
|
+
if (!UUID.test(org)) return problem(400, "invalid_organization", "Say which organization.", void 0, asker.headers);
|
|
2363
|
+
const named = (v) => typeof v === "string" && v !== "" && v.length <= 200;
|
|
2364
|
+
if (!named(b.resource) || !named(b.action)) return problem(400, "bad_request", "Say which resource and action.", void 0, asker.headers);
|
|
2365
|
+
const attributes2 = b.attributes;
|
|
2366
|
+
if (attributes2 !== void 0 && (typeof attributes2 !== "object" || attributes2 === null || Array.isArray(attributes2))) {
|
|
2367
|
+
return problem(400, "bad_request", "The attributes are an object.", void 0, asker.headers);
|
|
2368
|
+
}
|
|
2369
|
+
try {
|
|
2370
|
+
const r = await decide(asker.token, {
|
|
2371
|
+
organization: org,
|
|
2372
|
+
resource: b.resource,
|
|
2373
|
+
action: b.action,
|
|
2374
|
+
...attributes2 !== void 0 ? { attributes: attributes2 } : {},
|
|
2375
|
+
...typeof b.resourceId === "string" ? { resourceId: b.resourceId } : {},
|
|
2376
|
+
...typeof b.ownerId === "string" ? { ownerId: b.ownerId } : {}
|
|
2377
|
+
});
|
|
2378
|
+
return json({ status: "decided", ...r }, 200, asker.headers);
|
|
2379
|
+
} catch (e) {
|
|
2380
|
+
const err = e instanceof CauthyApiError ? e : new CauthyApiError(503, "unavailable", "Cauthy could not be reached.");
|
|
2381
|
+
return problem(err.status, err.code, err.message.replace(/^cauthy-auth: /, ""), void 0, asker.headers);
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2069
2384
|
async function protect(request) {
|
|
2070
2385
|
const { value } = await read(request);
|
|
2071
2386
|
if (value !== null && fresh(value)) return { session: toSession(value) };
|
|
@@ -2089,6 +2404,7 @@ function createCauthy(given = {}) {
|
|
|
2089
2404
|
resolve: resolve2,
|
|
2090
2405
|
protect,
|
|
2091
2406
|
organizations,
|
|
2407
|
+
check,
|
|
2092
2408
|
toPublic,
|
|
2093
2409
|
urls,
|
|
2094
2410
|
options: { issuer, clientId, basePath, afterSignIn, afterSignOut, cookieName }
|
|
@@ -2103,128 +2419,6 @@ function legalOf(raw) {
|
|
|
2103
2419
|
};
|
|
2104
2420
|
}
|
|
2105
2421
|
|
|
2106
|
-
// src/permissions.ts
|
|
2107
|
-
function matches(entry, resource, action) {
|
|
2108
|
-
const i = entry.lastIndexOf(":");
|
|
2109
|
-
if (i < 0) return false;
|
|
2110
|
-
const r = entry.slice(0, i);
|
|
2111
|
-
const a = entry.slice(i + 1);
|
|
2112
|
-
return (r === "*" || r === resource) && (a === "*" || a === action);
|
|
2113
|
-
}
|
|
2114
|
-
function can(organization, resource, action) {
|
|
2115
|
-
if (!organization?.permissions) return false;
|
|
2116
|
-
if ((organization.denied ?? []).some((d) => matches(d, resource, action))) return false;
|
|
2117
|
-
return organization.permissions.some((p) => matches(p, resource, action));
|
|
2118
|
-
}
|
|
2119
|
-
function definePolicy(roles) {
|
|
2120
|
-
const entry = (p) => `${p.resource}:${p.action}`;
|
|
2121
|
-
const byName = new Map(roles.map((r) => [r.role, r]));
|
|
2122
|
-
const split = (permission) => {
|
|
2123
|
-
const i = permission.lastIndexOf(":");
|
|
2124
|
-
return i < 0 ? [permission, ""] : [permission.slice(0, i), permission.slice(i + 1)];
|
|
2125
|
-
};
|
|
2126
|
-
return {
|
|
2127
|
-
roles: roles.map((r) => ({
|
|
2128
|
-
role: r.role,
|
|
2129
|
-
...r.name !== void 0 ? { name: r.name } : {},
|
|
2130
|
-
...r.description !== void 0 ? { description: r.description } : {},
|
|
2131
|
-
...r.inherits ? { inherits: [...r.inherits] } : {},
|
|
2132
|
-
...r.permissions ? { permissions: r.permissions.map((p) => ({ ...p })) } : {}
|
|
2133
|
-
})),
|
|
2134
|
-
roleNames: roles.map((r) => r.role),
|
|
2135
|
-
permissions: [...new Set(roles.flatMap((r) => (r.permissions ?? []).map(entry)))],
|
|
2136
|
-
can(organization, permission) {
|
|
2137
|
-
const [resource, action] = split(permission);
|
|
2138
|
-
return can(organization, resource, action);
|
|
2139
|
-
},
|
|
2140
|
-
hasRole(organization, ...wanted) {
|
|
2141
|
-
return organization != null && wanted.includes(organization.role);
|
|
2142
|
-
},
|
|
2143
|
-
permissionsOf(role) {
|
|
2144
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2145
|
-
const out2 = /* @__PURE__ */ new Set();
|
|
2146
|
-
const walk = (name) => {
|
|
2147
|
-
if (seen.has(name)) return;
|
|
2148
|
-
seen.add(name);
|
|
2149
|
-
const r = byName.get(name);
|
|
2150
|
-
for (const p of r?.permissions ?? []) out2.add(entry(p));
|
|
2151
|
-
for (const parent of r?.inherits ?? []) walk(parent);
|
|
2152
|
-
};
|
|
2153
|
-
walk(role);
|
|
2154
|
-
return [...out2];
|
|
2155
|
-
}
|
|
2156
|
-
};
|
|
2157
|
-
}
|
|
2158
|
-
var IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
2159
|
-
function policySource(system, roles) {
|
|
2160
|
-
const text = (v) => JSON.stringify(v);
|
|
2161
|
-
const key = (k) => IDENT.test(k) ? k : text(k);
|
|
2162
|
-
const one = (r) => {
|
|
2163
|
-
const parts = [`role: ${text(r.role)}`];
|
|
2164
|
-
if (r.name) parts.push(`name: ${text(r.name)}`);
|
|
2165
|
-
if (r.description) parts.push(`description: ${text(r.description)}`);
|
|
2166
|
-
if (r.inherits?.length) parts.push(`inherits: [${r.inherits.map(text).join(", ")}]`);
|
|
2167
|
-
if (r.permissions?.length) {
|
|
2168
|
-
const list = r.permissions.map((p) => ` { ${[...p.kind && p.kind !== "*" ? [`${key("kind")}: ${text(p.kind)}`] : [], `resource: ${text(p.resource)}`, `action: ${text(p.action)}`].join(", ")} },`);
|
|
2169
|
-
parts.push(`permissions: [
|
|
2170
|
-
${list.join("\n")}
|
|
2171
|
-
]`);
|
|
2172
|
-
}
|
|
2173
|
-
return ` {
|
|
2174
|
-
${parts.join(",\n ")},
|
|
2175
|
-
},`;
|
|
2176
|
-
};
|
|
2177
|
-
return `// The catalog of roles of ${text(system)}, as Cauthy has it.
|
|
2178
|
-
// Written by \`cauthy-auth policy --pull\`: run it again after the catalog
|
|
2179
|
-
// changes, and do not edit this file by hand.
|
|
2180
|
-
|
|
2181
|
-
import { definePolicy, type PermissionOf, type RoleOf } from 'cauthy-auth'
|
|
2182
|
-
|
|
2183
|
-
export const policy = definePolicy([
|
|
2184
|
-
${roles.map(one).join("\n")}
|
|
2185
|
-
])
|
|
2186
|
-
|
|
2187
|
-
export const { can, hasRole } = policy
|
|
2188
|
-
export type Role = RoleOf<typeof policy>
|
|
2189
|
-
export type Permission = PermissionOf<typeof policy>
|
|
2190
|
-
`;
|
|
2191
|
-
}
|
|
2192
|
-
async function pullPolicy(o = {}) {
|
|
2193
|
-
const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
|
|
2194
|
-
const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
|
|
2195
|
-
const system = o.system ?? env4("CAUTHY_SYSTEM") ?? "";
|
|
2196
|
-
const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
|
|
2197
|
-
const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
|
|
2198
|
-
for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_SYSTEM: system, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {
|
|
2199
|
-
if (v === "") throw new Error(`cauthy-auth: ${name} is required to read a policy`);
|
|
2200
|
-
}
|
|
2201
|
-
const res = await (o.fetch ?? fetch)(`${issuer}/v1/systems/${encodeURIComponent(system)}/policy`, {
|
|
2202
|
-
headers: { authorization: `Bearer ${token}`, "x-tenant-key": tenant, accept: "application/json" }
|
|
2203
|
-
});
|
|
2204
|
-
const body = await res.json().catch(() => null);
|
|
2205
|
-
if (!res.ok) throw new Error(`cauthy-auth: Cauthy refused to give the policy (${res.status}): ${body?.errors?.[0]?.message ?? res.statusText}`);
|
|
2206
|
-
return body?.data?.roles ?? [];
|
|
2207
|
-
}
|
|
2208
|
-
async function pushPolicy(o) {
|
|
2209
|
-
const env4 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
|
|
2210
|
-
const issuer = withoutTrailingSlashes(o.issuer ?? env4("CAUTHY_ISSUER") ?? "");
|
|
2211
|
-
const system = o.system ?? env4("CAUTHY_SYSTEM") ?? "";
|
|
2212
|
-
const tenant = o.tenant ?? env4("CAUTHY_TENANT") ?? "";
|
|
2213
|
-
const token = o.token ?? env4("CAUTHY_TOKEN") ?? "";
|
|
2214
|
-
for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_SYSTEM: system, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {
|
|
2215
|
-
if (v === "") throw new Error(`cauthy-auth: ${name} is required to push a policy`);
|
|
2216
|
-
}
|
|
2217
|
-
const res = await (o.fetch ?? fetch)(`${issuer}/v1/systems/${encodeURIComponent(system)}/policy`, {
|
|
2218
|
-
method: "PUT",
|
|
2219
|
-
headers: { authorization: `Bearer ${token}`, "x-tenant-key": tenant, "content-type": "application/json" },
|
|
2220
|
-
body: JSON.stringify({ roles: o.roles })
|
|
2221
|
-
});
|
|
2222
|
-
if (!res.ok) {
|
|
2223
|
-
const body = await res.json().catch(() => null);
|
|
2224
|
-
throw new Error(`cauthy-auth: Cauthy refused the policy (${res.status}): ${body?.errors?.[0]?.message ?? res.statusText}`);
|
|
2225
|
-
}
|
|
2226
|
-
}
|
|
2227
|
-
|
|
2228
2422
|
// src/connect.ts
|
|
2229
2423
|
function sessionSecret() {
|
|
2230
2424
|
const bytes = crypto.getRandomValues(new Uint8Array(32));
|
|
@@ -2350,7 +2544,9 @@ async function verifyToken(from, options = {}) {
|
|
|
2350
2544
|
passwordPolicyOf,
|
|
2351
2545
|
passwordProblems,
|
|
2352
2546
|
policySource,
|
|
2547
|
+
pullCatalog,
|
|
2353
2548
|
pullPolicy,
|
|
2549
|
+
pushCatalog,
|
|
2354
2550
|
pushPolicy,
|
|
2355
2551
|
pushTheme,
|
|
2356
2552
|
themeFromStackmyth,
|