@dyrected/core 2.5.41 → 2.5.43
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/dist/app-config-2vF6W56z.d.cts +1335 -0
- package/dist/app-config-2vF6W56z.d.ts +1335 -0
- package/dist/app-config-BLMX-9MN.d.cts +1045 -0
- package/dist/app-config-BLMX-9MN.d.ts +1045 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/server.cjs +55 -17
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +55 -17
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './
|
|
2
|
-
export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthProvider, i as AdminAuthProvisioningMode, j as AdminAuthResolveAccessArgs, k as AdminAuthResolvedIdentity, l as AdminConfig, m as AdminDashboardComponentSlots, n as AdminIconName, o as ArrayField, p as BaseAdminAuthProvider, q as BlocksField, r as BooleanField, s as CharacterLimitFieldConfig, t as CollectionAfterChangeHook, u as CollectionAfterDeleteHook, v as CollectionAfterReadHook, w as CollectionAfterTransitionHook, x as CollectionBeforeChangeHook, y as CollectionBeforeDeleteHook, z as CollectionBeforeReadHook, E as CollectionBeforeTransitionHook, I as CollectionListComponentSlots, J as CustomAdminAuthProvider, K as DatabaseAdapter, M as DateField, N as DateTimeField, O as DynamicOptionItem, Q as DynamicOptionsConfig, R as DynamicOptionsResolver, S as DynamicOptionsResolverArgs, T as EmailField, U as FieldAdminOnChangeHook, V as FieldAdminOnChangeHookArgs, X as FieldAdminOptionsHook, Y as FieldAdminOptionsHookArgs, Z as FieldAdminOptionsHookResult, _ as FieldAfterReadHook, $ as FieldAfterReadHookArgs, a0 as FieldBeforeChangeHook, a1 as FieldBeforeChangeHookArgs, a2 as FieldHook, a3 as FieldType, a4 as FileData, a5 as GlobalAfterChangeHook, a6 as GlobalAfterReadHook, a7 as GlobalBeforeChangeHook, a8 as GlobalBeforeReadHook, a9 as HookFunction, aa as IconField, ab as ImageField, ac as ImageService, ad as JoinField, ae as JsonField, af as LIFECYCLE_EVENT_NAMES, ag as LifecycleEventHandler, ah as MultiSelectField, ai as NumberField, aj as OIDCAdminAuthProvider, ak as ObjectField, al as PaginatedResult, am as PublicAdminAuthProvider, an as RadioField, ao as ReadonlyDatabaseAdapter, ap as RelationshipField, aq as RichTextField, ar as RowField, as as SelectField, at as StorageAdapter, au as TextField, av as TextareaField, aw as TimeField, ax as UploadConfig, ay as UrlField, az as WordLimitFieldConfig, aA as WorkflowMetadata, aB as WorkflowRole, aC as WorkflowState, aD as WorkflowTransitionContext } from './
|
|
1
|
+
import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './app-config-2vF6W56z.cjs';
|
|
2
|
+
export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthProvider, i as AdminAuthProvisioningMode, j as AdminAuthResolveAccessArgs, k as AdminAuthResolvedIdentity, l as AdminConfig, m as AdminDashboardComponentSlots, n as AdminIconName, o as ArrayField, p as BaseAdminAuthProvider, q as BlocksField, r as BooleanField, s as CharacterLimitFieldConfig, t as CollectionAfterChangeHook, u as CollectionAfterDeleteHook, v as CollectionAfterReadHook, w as CollectionAfterTransitionHook, x as CollectionBeforeChangeHook, y as CollectionBeforeDeleteHook, z as CollectionBeforeReadHook, E as CollectionBeforeTransitionHook, I as CollectionListComponentSlots, J as CustomAdminAuthProvider, K as DatabaseAdapter, M as DateField, N as DateTimeField, O as DynamicOptionItem, Q as DynamicOptionsConfig, R as DynamicOptionsResolver, S as DynamicOptionsResolverArgs, T as EmailField, U as FieldAdminOnChangeHook, V as FieldAdminOnChangeHookArgs, X as FieldAdminOptionsHook, Y as FieldAdminOptionsHookArgs, Z as FieldAdminOptionsHookResult, _ as FieldAfterReadHook, $ as FieldAfterReadHookArgs, a0 as FieldBeforeChangeHook, a1 as FieldBeforeChangeHookArgs, a2 as FieldHook, a3 as FieldType, a4 as FileData, a5 as GlobalAfterChangeHook, a6 as GlobalAfterReadHook, a7 as GlobalBeforeChangeHook, a8 as GlobalBeforeReadHook, a9 as HookFunction, aa as IconField, ab as ImageField, ac as ImageService, ad as JoinField, ae as JsonField, af as LIFECYCLE_EVENT_NAMES, ag as LifecycleEventHandler, ah as MultiSelectField, ai as NumberField, aj as OIDCAdminAuthProvider, ak as ObjectField, al as PaginatedResult, am as PublicAdminAuthProvider, an as RadioField, ao as ReadonlyDatabaseAdapter, ap as RelationshipField, aq as RichTextField, ar as RowField, as as SelectField, at as StorageAdapter, au as TextField, av as TextareaField, aw as TimeField, ax as UploadConfig, ay as UrlField, az as WordLimitFieldConfig, aA as WorkflowMetadata, aB as WorkflowRole, aC as WorkflowState, aD as WorkflowTransitionContext } from './app-config-2vF6W56z.cjs';
|
|
3
3
|
import 'lucide-react';
|
|
4
4
|
|
|
5
5
|
type Prettify<T> = {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './
|
|
2
|
-
export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthProvider, i as AdminAuthProvisioningMode, j as AdminAuthResolveAccessArgs, k as AdminAuthResolvedIdentity, l as AdminConfig, m as AdminDashboardComponentSlots, n as AdminIconName, o as ArrayField, p as BaseAdminAuthProvider, q as BlocksField, r as BooleanField, s as CharacterLimitFieldConfig, t as CollectionAfterChangeHook, u as CollectionAfterDeleteHook, v as CollectionAfterReadHook, w as CollectionAfterTransitionHook, x as CollectionBeforeChangeHook, y as CollectionBeforeDeleteHook, z as CollectionBeforeReadHook, E as CollectionBeforeTransitionHook, I as CollectionListComponentSlots, J as CustomAdminAuthProvider, K as DatabaseAdapter, M as DateField, N as DateTimeField, O as DynamicOptionItem, Q as DynamicOptionsConfig, R as DynamicOptionsResolver, S as DynamicOptionsResolverArgs, T as EmailField, U as FieldAdminOnChangeHook, V as FieldAdminOnChangeHookArgs, X as FieldAdminOptionsHook, Y as FieldAdminOptionsHookArgs, Z as FieldAdminOptionsHookResult, _ as FieldAfterReadHook, $ as FieldAfterReadHookArgs, a0 as FieldBeforeChangeHook, a1 as FieldBeforeChangeHookArgs, a2 as FieldHook, a3 as FieldType, a4 as FileData, a5 as GlobalAfterChangeHook, a6 as GlobalAfterReadHook, a7 as GlobalBeforeChangeHook, a8 as GlobalBeforeReadHook, a9 as HookFunction, aa as IconField, ab as ImageField, ac as ImageService, ad as JoinField, ae as JsonField, af as LIFECYCLE_EVENT_NAMES, ag as LifecycleEventHandler, ah as MultiSelectField, ai as NumberField, aj as OIDCAdminAuthProvider, ak as ObjectField, al as PaginatedResult, am as PublicAdminAuthProvider, an as RadioField, ao as ReadonlyDatabaseAdapter, ap as RelationshipField, aq as RichTextField, ar as RowField, as as SelectField, at as StorageAdapter, au as TextField, av as TextareaField, aw as TimeField, ax as UploadConfig, ay as UrlField, az as WordLimitFieldConfig, aA as WorkflowMetadata, aB as WorkflowRole, aC as WorkflowState, aD as WorkflowTransitionContext } from './
|
|
1
|
+
import { F as Field, B as Block, D as DyrectedConfig, C as CollectionConfig, A as AdminAuthConfig, P as PublicAdminAuthConfig, W as WorkflowConfig, a as AuthenticatedUser, b as WorkflowTransition, L as LifecycleEventName, c as LifecycleEvent, d as BaseDocument, H as HookRequestContext, G as GlobalConfig } from './app-config-2vF6W56z.js';
|
|
2
|
+
export { e as AccessFunction, f as AdminAuthAccessResolution, g as AdminAuthClaimMapping, h as AdminAuthProvider, i as AdminAuthProvisioningMode, j as AdminAuthResolveAccessArgs, k as AdminAuthResolvedIdentity, l as AdminConfig, m as AdminDashboardComponentSlots, n as AdminIconName, o as ArrayField, p as BaseAdminAuthProvider, q as BlocksField, r as BooleanField, s as CharacterLimitFieldConfig, t as CollectionAfterChangeHook, u as CollectionAfterDeleteHook, v as CollectionAfterReadHook, w as CollectionAfterTransitionHook, x as CollectionBeforeChangeHook, y as CollectionBeforeDeleteHook, z as CollectionBeforeReadHook, E as CollectionBeforeTransitionHook, I as CollectionListComponentSlots, J as CustomAdminAuthProvider, K as DatabaseAdapter, M as DateField, N as DateTimeField, O as DynamicOptionItem, Q as DynamicOptionsConfig, R as DynamicOptionsResolver, S as DynamicOptionsResolverArgs, T as EmailField, U as FieldAdminOnChangeHook, V as FieldAdminOnChangeHookArgs, X as FieldAdminOptionsHook, Y as FieldAdminOptionsHookArgs, Z as FieldAdminOptionsHookResult, _ as FieldAfterReadHook, $ as FieldAfterReadHookArgs, a0 as FieldBeforeChangeHook, a1 as FieldBeforeChangeHookArgs, a2 as FieldHook, a3 as FieldType, a4 as FileData, a5 as GlobalAfterChangeHook, a6 as GlobalAfterReadHook, a7 as GlobalBeforeChangeHook, a8 as GlobalBeforeReadHook, a9 as HookFunction, aa as IconField, ab as ImageField, ac as ImageService, ad as JoinField, ae as JsonField, af as LIFECYCLE_EVENT_NAMES, ag as LifecycleEventHandler, ah as MultiSelectField, ai as NumberField, aj as OIDCAdminAuthProvider, ak as ObjectField, al as PaginatedResult, am as PublicAdminAuthProvider, an as RadioField, ao as ReadonlyDatabaseAdapter, ap as RelationshipField, aq as RichTextField, ar as RowField, as as SelectField, at as StorageAdapter, au as TextField, av as TextareaField, aw as TimeField, ax as UploadConfig, ay as UrlField, az as WordLimitFieldConfig, aA as WorkflowMetadata, aB as WorkflowRole, aC as WorkflowState, aD as WorkflowTransitionContext } from './app-config-2vF6W56z.js';
|
|
3
3
|
import 'lucide-react';
|
|
4
4
|
|
|
5
5
|
type Prettify<T> = {
|
package/dist/server.cjs
CHANGED
|
@@ -2137,11 +2137,12 @@ var AdminAuthController = class {
|
|
|
2137
2137
|
return c.json(getPublicAdminAuthConfig(this.config.adminAuth));
|
|
2138
2138
|
}
|
|
2139
2139
|
async start(c) {
|
|
2140
|
-
const
|
|
2140
|
+
const requestConfig = await this.getRequestConfig(c);
|
|
2141
|
+
const provider = this.getProvider(requestConfig, c.req.param("provider"));
|
|
2141
2142
|
if (!provider) {
|
|
2142
2143
|
return c.json({ error: true, message: "Admin auth provider not found." }, 404);
|
|
2143
2144
|
}
|
|
2144
|
-
const siteId =
|
|
2145
|
+
const siteId = this.getSiteId(c);
|
|
2145
2146
|
const returnTo = this.normalizeReturnTo(c.req.query("returnTo"), c);
|
|
2146
2147
|
if (provider.type === "oidc") {
|
|
2147
2148
|
const redirectUrl = await this.buildOidcStartUrl(
|
|
@@ -2155,19 +2156,29 @@ var AdminAuthController = class {
|
|
|
2155
2156
|
if (!provider.startUrl) {
|
|
2156
2157
|
return c.json({ error: true, message: "This provider does not expose a start URL." }, 400);
|
|
2157
2158
|
}
|
|
2158
|
-
const url = new URL(
|
|
2159
|
+
const url = this.buildCustomProviderStartUrl(provider.startUrl, new URL(c.req.url).origin);
|
|
2160
|
+
if (!url) {
|
|
2161
|
+
return c.json(
|
|
2162
|
+
{
|
|
2163
|
+
error: true,
|
|
2164
|
+
message: `Admin auth provider "${provider.id}" has an invalid start URL.`
|
|
2165
|
+
},
|
|
2166
|
+
500
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2159
2169
|
url.searchParams.set("returnTo", returnTo);
|
|
2160
2170
|
if (siteId) url.searchParams.set("siteId", siteId);
|
|
2161
2171
|
url.searchParams.set("provider", provider.id);
|
|
2162
2172
|
return c.redirect(url.toString(), 302);
|
|
2163
2173
|
}
|
|
2164
2174
|
async callback(c) {
|
|
2165
|
-
const
|
|
2175
|
+
const requestConfig = await this.getRequestConfig(c);
|
|
2176
|
+
const provider = this.getProvider(requestConfig, c.req.param("provider"));
|
|
2166
2177
|
if (!provider) {
|
|
2167
2178
|
return c.json({ error: true, message: "Admin auth provider not found." }, 404);
|
|
2168
2179
|
}
|
|
2169
2180
|
try {
|
|
2170
|
-
const exchange = await this.completeProviderAuth(provider, c);
|
|
2181
|
+
const exchange = await this.completeProviderAuth(requestConfig, provider, c);
|
|
2171
2182
|
const redirectUrl = new URL(exchange.returnTo);
|
|
2172
2183
|
redirectUrl.searchParams.set("dyrectedExternalToken", exchange.token);
|
|
2173
2184
|
redirectUrl.searchParams.set("dyrectedAdminCollection", exchange.collectionSlug);
|
|
@@ -2181,12 +2192,13 @@ var AdminAuthController = class {
|
|
|
2181
2192
|
}
|
|
2182
2193
|
}
|
|
2183
2194
|
async exchange(c) {
|
|
2184
|
-
const
|
|
2195
|
+
const requestConfig = await this.getRequestConfig(c);
|
|
2196
|
+
const provider = this.getProvider(requestConfig, c.req.param("provider"));
|
|
2185
2197
|
if (!provider) {
|
|
2186
2198
|
return c.json({ error: true, message: "Admin auth provider not found." }, 404);
|
|
2187
2199
|
}
|
|
2188
2200
|
try {
|
|
2189
|
-
const exchange = await this.completeProviderAuth(provider, c);
|
|
2201
|
+
const exchange = await this.completeProviderAuth(requestConfig, provider, c);
|
|
2190
2202
|
return c.json({
|
|
2191
2203
|
token: exchange.token,
|
|
2192
2204
|
collectionSlug: exchange.collectionSlug,
|
|
@@ -2201,15 +2213,15 @@ var AdminAuthController = class {
|
|
|
2201
2213
|
async logout(c) {
|
|
2202
2214
|
return c.json({ success: true, message: "Logged out. Discard your token." });
|
|
2203
2215
|
}
|
|
2204
|
-
getProvider(id) {
|
|
2205
|
-
if (
|
|
2206
|
-
return
|
|
2216
|
+
getProvider(config, id) {
|
|
2217
|
+
if (config.adminAuth?.mode !== "external") return void 0;
|
|
2218
|
+
return config.adminAuth.providers.find((provider) => provider.id === id);
|
|
2207
2219
|
}
|
|
2208
|
-
async completeProviderAuth(provider, c) {
|
|
2220
|
+
async completeProviderAuth(requestConfig, provider, c) {
|
|
2209
2221
|
const resolved = provider.type === "oidc" ? await this.resolveOidcIdentity(provider, c) : await this.resolveCustomIdentity(provider, c);
|
|
2210
2222
|
const identity = resolved.identity;
|
|
2211
|
-
const siteId =
|
|
2212
|
-
const adminCollection = getAdminAuthCollection(
|
|
2223
|
+
const siteId = this.getSiteId(c);
|
|
2224
|
+
const adminCollection = getAdminAuthCollection(requestConfig);
|
|
2213
2225
|
if (!adminCollection?.auth) {
|
|
2214
2226
|
throw new Error("Admin auth collection is not configured.");
|
|
2215
2227
|
}
|
|
@@ -2220,12 +2232,12 @@ var AdminAuthController = class {
|
|
|
2220
2232
|
where: { email: identity.email },
|
|
2221
2233
|
limit: 1
|
|
2222
2234
|
})).docs[0] : null);
|
|
2223
|
-
const provisioningMode =
|
|
2235
|
+
const provisioningMode = requestConfig.adminAuth?.provisioningMode ?? "jit_plus_membership_management";
|
|
2224
2236
|
const allowJitProvisioning = provisioningMode !== "preprovisioned_only" && provider.allowJitProvisioning !== false;
|
|
2225
2237
|
if (!user && !allowJitProvisioning) {
|
|
2226
2238
|
throw new Error("This account has not been provisioned for admin access.");
|
|
2227
2239
|
}
|
|
2228
|
-
const access = await this.resolveAccess(identity, provider.id, siteId, c, user);
|
|
2240
|
+
const access = await this.resolveAccess(requestConfig, identity, provider.id, siteId, c, user);
|
|
2229
2241
|
if (!access.allowed) {
|
|
2230
2242
|
throw new Error("Access denied for this site.");
|
|
2231
2243
|
}
|
|
@@ -2260,8 +2272,8 @@ var AdminAuthController = class {
|
|
|
2260
2272
|
returnTo: resolved.returnTo
|
|
2261
2273
|
};
|
|
2262
2274
|
}
|
|
2263
|
-
async resolveAccess(identity, providerId, siteId, c, user) {
|
|
2264
|
-
const resolved = await
|
|
2275
|
+
async resolveAccess(requestConfig, identity, providerId, siteId, c, user) {
|
|
2276
|
+
const resolved = await requestConfig.adminAuth?.resolveAccess?.({
|
|
2265
2277
|
identity,
|
|
2266
2278
|
providerId,
|
|
2267
2279
|
siteId,
|
|
@@ -2300,6 +2312,21 @@ var AdminAuthController = class {
|
|
|
2300
2312
|
});
|
|
2301
2313
|
return result.docs[0] ?? null;
|
|
2302
2314
|
}
|
|
2315
|
+
getSiteId(c) {
|
|
2316
|
+
return c.req.header("X-Site-Id") || c.get("siteId");
|
|
2317
|
+
}
|
|
2318
|
+
async getRequestConfig(c) {
|
|
2319
|
+
const siteId = this.getSiteId(c);
|
|
2320
|
+
if (!siteId || !this.config.onSchemaFetch) return this.config;
|
|
2321
|
+
const dynamic = await this.config.onSchemaFetch(siteId);
|
|
2322
|
+
return {
|
|
2323
|
+
...this.config,
|
|
2324
|
+
...dynamic.admin ? { admin: { ...this.config.admin, ...dynamic.admin } } : {},
|
|
2325
|
+
...dynamic.adminAuth ? { adminAuth: { ...this.config.adminAuth, ...dynamic.adminAuth } } : {},
|
|
2326
|
+
collections: dynamic.collections ? [...this.config.collections, ...dynamic.collections] : this.config.collections,
|
|
2327
|
+
globals: dynamic.globals ? [...this.config.globals, ...dynamic.globals] : this.config.globals
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2303
2330
|
async buildOidcStartUrl(provider, returnTo, siteId, origin) {
|
|
2304
2331
|
const discovery = await this.getOidcDiscovery(provider);
|
|
2305
2332
|
const nonce = (0, import_node_crypto2.randomBytes)(16).toString("hex");
|
|
@@ -2452,6 +2479,17 @@ var AdminAuthController = class {
|
|
|
2452
2479
|
defaultCallbackPath(providerId, origin = "") {
|
|
2453
2480
|
return `${origin}/api/admin/auth/${providerId}/callback`;
|
|
2454
2481
|
}
|
|
2482
|
+
buildCustomProviderStartUrl(startUrl, origin) {
|
|
2483
|
+
const value = startUrl.trim();
|
|
2484
|
+
if (!value || /^(undefined|null)(\/|$)/i.test(value)) return null;
|
|
2485
|
+
try {
|
|
2486
|
+
const url = new URL(value, origin);
|
|
2487
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
2488
|
+
return url;
|
|
2489
|
+
} catch {
|
|
2490
|
+
return null;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2455
2493
|
async signState(payload) {
|
|
2456
2494
|
return new import_jose2.SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime("15m").sign(this.getStateSecret());
|
|
2457
2495
|
}
|
package/dist/server.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as hono_types from 'hono/types';
|
|
2
2
|
import * as hono from 'hono';
|
|
3
3
|
import { Hono, Context } from 'hono';
|
|
4
|
-
import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './
|
|
4
|
+
import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-2vF6W56z.cjs';
|
|
5
5
|
import * as hono_utils_http_status from 'hono/utils/http-status';
|
|
6
6
|
import * as hono_utils_types from 'hono/utils/types';
|
|
7
7
|
import 'lucide-react';
|
package/dist/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as hono_types from 'hono/types';
|
|
2
2
|
import * as hono from 'hono';
|
|
3
3
|
import { Hono, Context } from 'hono';
|
|
4
|
-
import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './
|
|
4
|
+
import { D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-config-2vF6W56z.js';
|
|
5
5
|
import * as hono_utils_http_status from 'hono/utils/http-status';
|
|
6
6
|
import * as hono_utils_types from 'hono/utils/types';
|
|
7
7
|
import 'lucide-react';
|
package/dist/server.js
CHANGED
|
@@ -1636,11 +1636,12 @@ var AdminAuthController = class {
|
|
|
1636
1636
|
return c.json(getPublicAdminAuthConfig(this.config.adminAuth));
|
|
1637
1637
|
}
|
|
1638
1638
|
async start(c) {
|
|
1639
|
-
const
|
|
1639
|
+
const requestConfig = await this.getRequestConfig(c);
|
|
1640
|
+
const provider = this.getProvider(requestConfig, c.req.param("provider"));
|
|
1640
1641
|
if (!provider) {
|
|
1641
1642
|
return c.json({ error: true, message: "Admin auth provider not found." }, 404);
|
|
1642
1643
|
}
|
|
1643
|
-
const siteId =
|
|
1644
|
+
const siteId = this.getSiteId(c);
|
|
1644
1645
|
const returnTo = this.normalizeReturnTo(c.req.query("returnTo"), c);
|
|
1645
1646
|
if (provider.type === "oidc") {
|
|
1646
1647
|
const redirectUrl = await this.buildOidcStartUrl(
|
|
@@ -1654,19 +1655,29 @@ var AdminAuthController = class {
|
|
|
1654
1655
|
if (!provider.startUrl) {
|
|
1655
1656
|
return c.json({ error: true, message: "This provider does not expose a start URL." }, 400);
|
|
1656
1657
|
}
|
|
1657
|
-
const url = new URL(
|
|
1658
|
+
const url = this.buildCustomProviderStartUrl(provider.startUrl, new URL(c.req.url).origin);
|
|
1659
|
+
if (!url) {
|
|
1660
|
+
return c.json(
|
|
1661
|
+
{
|
|
1662
|
+
error: true,
|
|
1663
|
+
message: `Admin auth provider "${provider.id}" has an invalid start URL.`
|
|
1664
|
+
},
|
|
1665
|
+
500
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1658
1668
|
url.searchParams.set("returnTo", returnTo);
|
|
1659
1669
|
if (siteId) url.searchParams.set("siteId", siteId);
|
|
1660
1670
|
url.searchParams.set("provider", provider.id);
|
|
1661
1671
|
return c.redirect(url.toString(), 302);
|
|
1662
1672
|
}
|
|
1663
1673
|
async callback(c) {
|
|
1664
|
-
const
|
|
1674
|
+
const requestConfig = await this.getRequestConfig(c);
|
|
1675
|
+
const provider = this.getProvider(requestConfig, c.req.param("provider"));
|
|
1665
1676
|
if (!provider) {
|
|
1666
1677
|
return c.json({ error: true, message: "Admin auth provider not found." }, 404);
|
|
1667
1678
|
}
|
|
1668
1679
|
try {
|
|
1669
|
-
const exchange = await this.completeProviderAuth(provider, c);
|
|
1680
|
+
const exchange = await this.completeProviderAuth(requestConfig, provider, c);
|
|
1670
1681
|
const redirectUrl = new URL(exchange.returnTo);
|
|
1671
1682
|
redirectUrl.searchParams.set("dyrectedExternalToken", exchange.token);
|
|
1672
1683
|
redirectUrl.searchParams.set("dyrectedAdminCollection", exchange.collectionSlug);
|
|
@@ -1680,12 +1691,13 @@ var AdminAuthController = class {
|
|
|
1680
1691
|
}
|
|
1681
1692
|
}
|
|
1682
1693
|
async exchange(c) {
|
|
1683
|
-
const
|
|
1694
|
+
const requestConfig = await this.getRequestConfig(c);
|
|
1695
|
+
const provider = this.getProvider(requestConfig, c.req.param("provider"));
|
|
1684
1696
|
if (!provider) {
|
|
1685
1697
|
return c.json({ error: true, message: "Admin auth provider not found." }, 404);
|
|
1686
1698
|
}
|
|
1687
1699
|
try {
|
|
1688
|
-
const exchange = await this.completeProviderAuth(provider, c);
|
|
1700
|
+
const exchange = await this.completeProviderAuth(requestConfig, provider, c);
|
|
1689
1701
|
return c.json({
|
|
1690
1702
|
token: exchange.token,
|
|
1691
1703
|
collectionSlug: exchange.collectionSlug,
|
|
@@ -1700,15 +1712,15 @@ var AdminAuthController = class {
|
|
|
1700
1712
|
async logout(c) {
|
|
1701
1713
|
return c.json({ success: true, message: "Logged out. Discard your token." });
|
|
1702
1714
|
}
|
|
1703
|
-
getProvider(id) {
|
|
1704
|
-
if (
|
|
1705
|
-
return
|
|
1715
|
+
getProvider(config, id) {
|
|
1716
|
+
if (config.adminAuth?.mode !== "external") return void 0;
|
|
1717
|
+
return config.adminAuth.providers.find((provider) => provider.id === id);
|
|
1706
1718
|
}
|
|
1707
|
-
async completeProviderAuth(provider, c) {
|
|
1719
|
+
async completeProviderAuth(requestConfig, provider, c) {
|
|
1708
1720
|
const resolved = provider.type === "oidc" ? await this.resolveOidcIdentity(provider, c) : await this.resolveCustomIdentity(provider, c);
|
|
1709
1721
|
const identity = resolved.identity;
|
|
1710
|
-
const siteId =
|
|
1711
|
-
const adminCollection = getAdminAuthCollection(
|
|
1722
|
+
const siteId = this.getSiteId(c);
|
|
1723
|
+
const adminCollection = getAdminAuthCollection(requestConfig);
|
|
1712
1724
|
if (!adminCollection?.auth) {
|
|
1713
1725
|
throw new Error("Admin auth collection is not configured.");
|
|
1714
1726
|
}
|
|
@@ -1719,12 +1731,12 @@ var AdminAuthController = class {
|
|
|
1719
1731
|
where: { email: identity.email },
|
|
1720
1732
|
limit: 1
|
|
1721
1733
|
})).docs[0] : null);
|
|
1722
|
-
const provisioningMode =
|
|
1734
|
+
const provisioningMode = requestConfig.adminAuth?.provisioningMode ?? "jit_plus_membership_management";
|
|
1723
1735
|
const allowJitProvisioning = provisioningMode !== "preprovisioned_only" && provider.allowJitProvisioning !== false;
|
|
1724
1736
|
if (!user && !allowJitProvisioning) {
|
|
1725
1737
|
throw new Error("This account has not been provisioned for admin access.");
|
|
1726
1738
|
}
|
|
1727
|
-
const access = await this.resolveAccess(identity, provider.id, siteId, c, user);
|
|
1739
|
+
const access = await this.resolveAccess(requestConfig, identity, provider.id, siteId, c, user);
|
|
1728
1740
|
if (!access.allowed) {
|
|
1729
1741
|
throw new Error("Access denied for this site.");
|
|
1730
1742
|
}
|
|
@@ -1759,8 +1771,8 @@ var AdminAuthController = class {
|
|
|
1759
1771
|
returnTo: resolved.returnTo
|
|
1760
1772
|
};
|
|
1761
1773
|
}
|
|
1762
|
-
async resolveAccess(identity, providerId, siteId, c, user) {
|
|
1763
|
-
const resolved = await
|
|
1774
|
+
async resolveAccess(requestConfig, identity, providerId, siteId, c, user) {
|
|
1775
|
+
const resolved = await requestConfig.adminAuth?.resolveAccess?.({
|
|
1764
1776
|
identity,
|
|
1765
1777
|
providerId,
|
|
1766
1778
|
siteId,
|
|
@@ -1799,6 +1811,21 @@ var AdminAuthController = class {
|
|
|
1799
1811
|
});
|
|
1800
1812
|
return result.docs[0] ?? null;
|
|
1801
1813
|
}
|
|
1814
|
+
getSiteId(c) {
|
|
1815
|
+
return c.req.header("X-Site-Id") || c.get("siteId");
|
|
1816
|
+
}
|
|
1817
|
+
async getRequestConfig(c) {
|
|
1818
|
+
const siteId = this.getSiteId(c);
|
|
1819
|
+
if (!siteId || !this.config.onSchemaFetch) return this.config;
|
|
1820
|
+
const dynamic = await this.config.onSchemaFetch(siteId);
|
|
1821
|
+
return {
|
|
1822
|
+
...this.config,
|
|
1823
|
+
...dynamic.admin ? { admin: { ...this.config.admin, ...dynamic.admin } } : {},
|
|
1824
|
+
...dynamic.adminAuth ? { adminAuth: { ...this.config.adminAuth, ...dynamic.adminAuth } } : {},
|
|
1825
|
+
collections: dynamic.collections ? [...this.config.collections, ...dynamic.collections] : this.config.collections,
|
|
1826
|
+
globals: dynamic.globals ? [...this.config.globals, ...dynamic.globals] : this.config.globals
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1802
1829
|
async buildOidcStartUrl(provider, returnTo, siteId, origin) {
|
|
1803
1830
|
const discovery = await this.getOidcDiscovery(provider);
|
|
1804
1831
|
const nonce = randomBytes2(16).toString("hex");
|
|
@@ -1951,6 +1978,17 @@ var AdminAuthController = class {
|
|
|
1951
1978
|
defaultCallbackPath(providerId, origin = "") {
|
|
1952
1979
|
return `${origin}/api/admin/auth/${providerId}/callback`;
|
|
1953
1980
|
}
|
|
1981
|
+
buildCustomProviderStartUrl(startUrl, origin) {
|
|
1982
|
+
const value = startUrl.trim();
|
|
1983
|
+
if (!value || /^(undefined|null)(\/|$)/i.test(value)) return null;
|
|
1984
|
+
try {
|
|
1985
|
+
const url = new URL(value, origin);
|
|
1986
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return null;
|
|
1987
|
+
return url;
|
|
1988
|
+
} catch {
|
|
1989
|
+
return null;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1954
1992
|
async signState(payload) {
|
|
1955
1993
|
return new SignJWT2(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime("15m").sign(this.getStateSecret());
|
|
1956
1994
|
}
|