mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 14:44:48 +00:00
refactor(oauth): remove redirect URI settings from system configuration
- Removed oauthGoogleRedirectUri and oauthGithubRedirectUri from SYSTEM_SETTING_DEFINITIONS and related service logic. - Updated SystemSettingService to eliminate handling of redirect URIs for Google and GitHub. - Adjusted UI schema and types to reflect the removal of redirect URI fields. - Cleaned up associated validation and parsing logic to streamline OAuth configuration. Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -58,12 +58,6 @@ export const SYSTEM_SETTING_DEFINITIONS = {
|
|||||||
defaultValue: null as string | null,
|
defaultValue: null as string | null,
|
||||||
isSensitive: true,
|
isSensitive: true,
|
||||||
},
|
},
|
||||||
oauthGoogleRedirectUri: {
|
|
||||||
key: 'system.auth.oauth.google.redirectUri',
|
|
||||||
schema: nullableUrl,
|
|
||||||
defaultValue: null as string | null,
|
|
||||||
isSensitive: false,
|
|
||||||
},
|
|
||||||
oauthGithubClientId: {
|
oauthGithubClientId: {
|
||||||
key: 'system.auth.oauth.github.clientId',
|
key: 'system.auth.oauth.github.clientId',
|
||||||
schema: nullableNonEmptyString,
|
schema: nullableNonEmptyString,
|
||||||
@@ -76,12 +70,6 @@ export const SYSTEM_SETTING_DEFINITIONS = {
|
|||||||
defaultValue: null as string | null,
|
defaultValue: null as string | null,
|
||||||
isSensitive: true,
|
isSensitive: true,
|
||||||
},
|
},
|
||||||
oauthGithubRedirectUri: {
|
|
||||||
key: 'system.auth.oauth.github.redirectUri',
|
|
||||||
schema: nullableUrl,
|
|
||||||
defaultValue: null as string | null,
|
|
||||||
isSensitive: false,
|
|
||||||
},
|
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type SystemSettingField = keyof typeof SYSTEM_SETTING_DEFINITIONS
|
export type SystemSettingField = keyof typeof SYSTEM_SETTING_DEFINITIONS
|
||||||
|
|||||||
@@ -71,14 +71,6 @@ export class SystemSettingService {
|
|||||||
SYSTEM_SETTING_DEFINITIONS.oauthGoogleClientSecret.schema,
|
SYSTEM_SETTING_DEFINITIONS.oauthGoogleClientSecret.schema,
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGoogleClientSecret.defaultValue,
|
SYSTEM_SETTING_DEFINITIONS.oauthGoogleClientSecret.defaultValue,
|
||||||
)
|
)
|
||||||
const oauthGoogleRedirectUri = this.normalizeRedirectPath(
|
|
||||||
this.parseSetting(
|
|
||||||
rawValues[SYSTEM_SETTING_DEFINITIONS.oauthGoogleRedirectUri.key],
|
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGoogleRedirectUri.schema,
|
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGoogleRedirectUri.defaultValue,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
const oauthGithubClientId = this.parseSetting(
|
const oauthGithubClientId = this.parseSetting(
|
||||||
rawValues[SYSTEM_SETTING_DEFINITIONS.oauthGithubClientId.key],
|
rawValues[SYSTEM_SETTING_DEFINITIONS.oauthGithubClientId.key],
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGithubClientId.schema,
|
SYSTEM_SETTING_DEFINITIONS.oauthGithubClientId.schema,
|
||||||
@@ -89,14 +81,6 @@ export class SystemSettingService {
|
|||||||
SYSTEM_SETTING_DEFINITIONS.oauthGithubClientSecret.schema,
|
SYSTEM_SETTING_DEFINITIONS.oauthGithubClientSecret.schema,
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGithubClientSecret.defaultValue,
|
SYSTEM_SETTING_DEFINITIONS.oauthGithubClientSecret.defaultValue,
|
||||||
)
|
)
|
||||||
const oauthGithubRedirectUri = this.normalizeRedirectPath(
|
|
||||||
this.parseSetting(
|
|
||||||
rawValues[SYSTEM_SETTING_DEFINITIONS.oauthGithubRedirectUri.key],
|
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGithubRedirectUri.schema,
|
|
||||||
SYSTEM_SETTING_DEFINITIONS.oauthGithubRedirectUri.defaultValue,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allowRegistration,
|
allowRegistration,
|
||||||
maxRegistrableUsers,
|
maxRegistrableUsers,
|
||||||
@@ -105,10 +89,8 @@ export class SystemSettingService {
|
|||||||
oauthGatewayUrl,
|
oauthGatewayUrl,
|
||||||
oauthGoogleClientId,
|
oauthGoogleClientId,
|
||||||
oauthGoogleClientSecret,
|
oauthGoogleClientSecret,
|
||||||
oauthGoogleRedirectUri,
|
|
||||||
oauthGithubClientId,
|
oauthGithubClientId,
|
||||||
oauthGithubClientSecret,
|
oauthGithubClientSecret,
|
||||||
oauthGithubRedirectUri,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,13 +177,6 @@ export class SystemSettingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch.oauthGoogleRedirectUri !== undefined) {
|
|
||||||
const sanitized = this.normalizeRedirectPath(patch.oauthGoogleRedirectUri)
|
|
||||||
if (sanitized !== current.oauthGoogleRedirectUri) {
|
|
||||||
enqueueUpdate('oauthGoogleRedirectUri', sanitized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patch.oauthGithubClientId !== undefined) {
|
if (patch.oauthGithubClientId !== undefined) {
|
||||||
const sanitized = this.normalizeNullableString(patch.oauthGithubClientId)
|
const sanitized = this.normalizeNullableString(patch.oauthGithubClientId)
|
||||||
if (sanitized !== current.oauthGithubClientId) {
|
if (sanitized !== current.oauthGithubClientId) {
|
||||||
@@ -216,13 +191,6 @@ export class SystemSettingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch.oauthGithubRedirectUri !== undefined) {
|
|
||||||
const sanitized = this.normalizeRedirectPath(patch.oauthGithubRedirectUri)
|
|
||||||
if (sanitized !== current.oauthGithubRedirectUri) {
|
|
||||||
enqueueUpdate('oauthGithubRedirectUri', sanitized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updates.length === 0) {
|
if (updates.length === 0) {
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
@@ -291,7 +259,6 @@ export class SystemSettingService {
|
|||||||
providers.google = {
|
providers.google = {
|
||||||
clientId: settings.oauthGoogleClientId,
|
clientId: settings.oauthGoogleClientId,
|
||||||
clientSecret: settings.oauthGoogleClientSecret,
|
clientSecret: settings.oauthGoogleClientSecret,
|
||||||
redirectPath: settings.oauthGoogleRedirectUri,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +266,6 @@ export class SystemSettingService {
|
|||||||
providers.github = {
|
providers.github = {
|
||||||
clientId: settings.oauthGithubClientId,
|
clientId: settings.oauthGithubClientId,
|
||||||
clientSecret: settings.oauthGithubClientSecret,
|
clientSecret: settings.oauthGithubClientSecret,
|
||||||
redirectPath: settings.oauthGithubRedirectUri,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,36 +303,6 @@ export class SystemSettingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private normalizeRedirectPath(value: string | null | undefined): string | null {
|
|
||||||
if (value === undefined || value === null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const trimmed = value.trim()
|
|
||||||
if (trimmed.length === 0) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const ensureLeadingSlash = (input: string): string | null => {
|
|
||||||
if (!input.startsWith('/')) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return input
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
|
|
||||||
const url = new URL(trimmed)
|
|
||||||
const pathWithQuery = `${url.pathname}${url.search ?? ''}`
|
|
||||||
return ensureLeadingSlash(pathWithQuery) ?? null
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// fall through to path handling
|
|
||||||
}
|
|
||||||
|
|
||||||
return ensureLeadingSlash(trimmed)
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildStats(settings: SystemSettings, totalUsers: number): SystemSettingStats {
|
private buildStats(settings: SystemSettings, totalUsers: number): SystemSettingStats {
|
||||||
const remaining =
|
const remaining =
|
||||||
settings.maxRegistrableUsers === null ? null : Math.max(settings.maxRegistrableUsers - totalUsers, 0)
|
settings.maxRegistrableUsers === null ? null : Math.max(settings.maxRegistrableUsers - totalUsers, 0)
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ export interface SystemSettings {
|
|||||||
oauthGatewayUrl: string | null
|
oauthGatewayUrl: string | null
|
||||||
oauthGoogleClientId: string | null
|
oauthGoogleClientId: string | null
|
||||||
oauthGoogleClientSecret: string | null
|
oauthGoogleClientSecret: string | null
|
||||||
oauthGoogleRedirectUri: string | null
|
|
||||||
oauthGithubClientId: string | null
|
oauthGithubClientId: string | null
|
||||||
oauthGithubClientSecret: string | null
|
oauthGithubClientSecret: string | null
|
||||||
oauthGithubRedirectUri: string | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SystemSettingValueMap = {
|
export type SystemSettingValueMap = {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { UiNode, UiSchema } from 'core/modules/ui/ui-schema/ui-schema.type'
|
|||||||
|
|
||||||
import type { SystemSettingField } from './system-setting.constants'
|
import type { SystemSettingField } from './system-setting.constants'
|
||||||
|
|
||||||
export const SYSTEM_SETTING_UI_SCHEMA_VERSION = '1.2.0'
|
export const SYSTEM_SETTING_UI_SCHEMA_VERSION = '1.3.0'
|
||||||
|
|
||||||
export const SYSTEM_SETTING_UI_SCHEMA: UiSchema<SystemSettingField> = {
|
export const SYSTEM_SETTING_UI_SCHEMA: UiSchema<SystemSettingField> = {
|
||||||
version: SYSTEM_SETTING_UI_SCHEMA_VERSION,
|
version: SYSTEM_SETTING_UI_SCHEMA_VERSION,
|
||||||
@@ -74,7 +74,7 @@ export const SYSTEM_SETTING_UI_SCHEMA: UiSchema<SystemSettingField> = {
|
|||||||
type: 'field',
|
type: 'field',
|
||||||
id: 'oauth-gateway-url',
|
id: 'oauth-gateway-url',
|
||||||
title: 'OAuth 网关地址',
|
title: 'OAuth 网关地址',
|
||||||
description: '统一的 OAuth 回调入口,例如 https://auth.afilmory.art。留空则直接回调到租户域名。',
|
description: '所有第三方登录统一走该回调入口(例如 https://auth.afilmory.art)。留空则回退到租户域名。',
|
||||||
helperText: '必须包含 http/https 协议,结尾无需斜杠。',
|
helperText: '必须包含 http/https 协议,结尾无需斜杠。',
|
||||||
key: 'oauthGatewayUrl',
|
key: 'oauthGatewayUrl',
|
||||||
component: {
|
component: {
|
||||||
@@ -113,17 +113,6 @@ export const SYSTEM_SETTING_UI_SCHEMA: UiSchema<SystemSettingField> = {
|
|||||||
autoComplete: 'off',
|
autoComplete: 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'field',
|
|
||||||
id: 'oauth-google-redirect-uri',
|
|
||||||
title: 'Redirect URI',
|
|
||||||
description: 'OAuth 回调路径,域名会自动使用当前租户如 slug.主域名。',
|
|
||||||
key: 'oauthGoogleRedirectUri',
|
|
||||||
component: {
|
|
||||||
type: 'text',
|
|
||||||
placeholder: '/api/auth/callback/google',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -157,17 +146,6 @@ export const SYSTEM_SETTING_UI_SCHEMA: UiSchema<SystemSettingField> = {
|
|||||||
autoComplete: 'off',
|
autoComplete: 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'field',
|
|
||||||
id: 'oauth-github-redirect-uri',
|
|
||||||
title: 'Redirect URI',
|
|
||||||
description: 'GitHub 回调路径,域名会自动使用租户的 subdomain。',
|
|
||||||
key: 'oauthGithubRedirectUri',
|
|
||||||
component: {
|
|
||||||
type: 'text',
|
|
||||||
placeholder: '/api/auth/callback/github',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { injectable } from 'tsyringe'
|
|||||||
export interface SocialProviderOptions {
|
export interface SocialProviderOptions {
|
||||||
clientId: string
|
clientId: string
|
||||||
clientSecret: string
|
clientSecret: string
|
||||||
redirectPath?: string | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SocialProvidersConfig {
|
export interface SocialProvidersConfig {
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ function resolveSocialProviderMetadata(id: string): { name: string; icon: string
|
|||||||
function buildProviderResponse(socialProviders: SocialProvidersConfig) {
|
function buildProviderResponse(socialProviders: SocialProvidersConfig) {
|
||||||
return Object.entries(socialProviders)
|
return Object.entries(socialProviders)
|
||||||
.filter(([, config]) => Boolean(config))
|
.filter(([, config]) => Boolean(config))
|
||||||
.map(([id, config]) => {
|
.map(([id]) => {
|
||||||
const metadata = resolveSocialProviderMetadata(id)
|
const metadata = resolveSocialProviderMetadata(id)
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
name: metadata.name,
|
name: metadata.name,
|
||||||
icon: metadata.icon,
|
icon: metadata.icon,
|
||||||
callbackPath: config?.redirectPath ?? null,
|
callbackPath: `/api/auth/callback/${id}`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ export class AuthController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!tenantContext || isPlaceholderTenantContext(tenantContext)) {
|
if (!tenantContext || isPlaceholderTenantContext(tenantContext)) {
|
||||||
const {tenantId} = (authContext.user as { tenantId?: string | null })
|
const { tenantId } = authContext.user as { tenantId?: string | null }
|
||||||
if (tenantId) {
|
if (tenantId) {
|
||||||
try {
|
try {
|
||||||
const aggregate = await this.tenantService.getById(tenantId)
|
const aggregate = await this.tenantService.getById(tenantId)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { createHash } from 'node:crypto'
|
||||||
|
|
||||||
import { authAccounts, authSessions, authUsers, authVerifications, generateId } from '@afilmory/db'
|
import { authAccounts, authSessions, authUsers, authVerifications, generateId } from '@afilmory/db'
|
||||||
import type { OnModuleInit } from '@afilmory/framework'
|
import type { OnModuleInit } from '@afilmory/framework'
|
||||||
import { createLogger, HttpContext } from '@afilmory/framework'
|
import { createLogger, HttpContext } from '@afilmory/framework'
|
||||||
@@ -21,7 +23,6 @@ const logger = createLogger('Auth')
|
|||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class AuthProvider implements OnModuleInit {
|
export class AuthProvider implements OnModuleInit {
|
||||||
private moduleOptionsPromise?: Promise<AuthModuleOptions>
|
|
||||||
private instances = new Map<string, Promise<BetterAuthInstance>>()
|
private instances = new Map<string, Promise<BetterAuthInstance>>()
|
||||||
private placeholderTenantId: string | null = null
|
private placeholderTenantId: string | null = null
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async onModuleInit(): Promise<void> {
|
async onModuleInit(): Promise<void> {
|
||||||
await this.getAuth()
|
await this.config.getOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveTenantIdFromContext(): string | null {
|
private resolveTenantIdFromContext(): string | null {
|
||||||
@@ -71,13 +72,6 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
return sanitizedSlug ? `better-auth-${sanitizedSlug}` : 'better-auth'
|
return sanitizedSlug ? `better-auth-${sanitizedSlug}` : 'better-auth'
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getModuleOptions(): Promise<AuthModuleOptions> {
|
|
||||||
if (!this.moduleOptionsPromise) {
|
|
||||||
this.moduleOptionsPromise = this.config.getOptions()
|
|
||||||
}
|
|
||||||
return this.moduleOptionsPromise
|
|
||||||
}
|
|
||||||
|
|
||||||
private async resolveFallbackTenantId(): Promise<string | null> {
|
private async resolveFallbackTenantId(): Promise<string | null> {
|
||||||
if (this.placeholderTenantId) {
|
if (this.placeholderTenantId) {
|
||||||
return this.placeholderTenantId
|
return this.placeholderTenantId
|
||||||
@@ -152,7 +146,7 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
|
|
||||||
return entries.reduce<Record<string, { clientId: string; clientSecret: string; redirectURI?: string }>>(
|
return entries.reduce<Record<string, { clientId: string; clientSecret: string; redirectURI?: string }>>(
|
||||||
(acc, [key, value]) => {
|
(acc, [key, value]) => {
|
||||||
const redirectUri = this.buildRedirectUri(tenantSlug, key, value, oauthGatewayUrl)
|
const redirectUri = this.buildRedirectUri(tenantSlug, key, oauthGatewayUrl)
|
||||||
acc[key] = {
|
acc[key] = {
|
||||||
clientId: value.clientId,
|
clientId: value.clientId,
|
||||||
clientSecret: value.clientSecret,
|
clientSecret: value.clientSecret,
|
||||||
@@ -167,13 +161,10 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
private buildRedirectUri(
|
private buildRedirectUri(
|
||||||
tenantSlug: string | null,
|
tenantSlug: string | null,
|
||||||
provider: keyof SocialProvidersConfig,
|
provider: keyof SocialProvidersConfig,
|
||||||
options: SocialProviderOptions,
|
|
||||||
oauthGatewayUrl: string | null,
|
oauthGatewayUrl: string | null,
|
||||||
): string | null {
|
): string | null {
|
||||||
const basePath = options.redirectPath ?? `/api/auth/callback/${provider}`
|
const basePath = `/api/auth/callback/${provider}`
|
||||||
if (!basePath.startsWith('/')) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
if (oauthGatewayUrl) {
|
if (oauthGatewayUrl) {
|
||||||
return this.buildGatewayRedirectUri(oauthGatewayUrl, basePath, tenantSlug)
|
return this.buildGatewayRedirectUri(oauthGatewayUrl, basePath, tenantSlug)
|
||||||
}
|
}
|
||||||
@@ -193,8 +184,10 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
return `${normalizedBase}${basePath}${query ? `?${query}` : ''}`
|
return `${normalizedBase}${basePath}${query ? `?${query}` : ''}`
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createAuthForEndpoint(tenantSlug: string | null): Promise<BetterAuthInstance> {
|
private async createAuthForEndpoint(
|
||||||
const options = await this.getModuleOptions()
|
tenantSlug: string | null,
|
||||||
|
options: AuthModuleOptions,
|
||||||
|
): Promise<BetterAuthInstance> {
|
||||||
const db = this.drizzleProvider.getDb()
|
const db = this.drizzleProvider.getDb()
|
||||||
const socialProviders = this.buildBetterAuthProvidersForHost(
|
const socialProviders = this.buildBetterAuthProvidersForHost(
|
||||||
tenantSlug,
|
tenantSlug,
|
||||||
@@ -323,7 +316,7 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAuth(): Promise<BetterAuthInstance> {
|
async getAuth(): Promise<BetterAuthInstance> {
|
||||||
const options = await this.getModuleOptions()
|
const options = await this.config.getOptions()
|
||||||
const endpoint = this.resolveRequestEndpoint()
|
const endpoint = this.resolveRequestEndpoint()
|
||||||
const fallbackHost = options.baseDomain.trim().toLowerCase()
|
const fallbackHost = options.baseDomain.trim().toLowerCase()
|
||||||
const requestedHost = (endpoint.host ?? fallbackHost).trim().toLowerCase()
|
const requestedHost = (endpoint.host ?? fallbackHost).trim().toLowerCase()
|
||||||
@@ -331,10 +324,11 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
const host = this.applyTenantSlugToHost(requestedHost || fallbackHost, fallbackHost, tenantSlug)
|
const host = this.applyTenantSlugToHost(requestedHost || fallbackHost, fallbackHost, tenantSlug)
|
||||||
const protocol = this.determineProtocol(host, endpoint.protocol)
|
const protocol = this.determineProtocol(host, endpoint.protocol)
|
||||||
const slugKey = tenantSlug ?? 'global'
|
const slugKey = tenantSlug ?? 'global'
|
||||||
const cacheKey = `${protocol}://${host}::${slugKey}`
|
const optionSignature = this.computeOptionsSignature(options)
|
||||||
|
const cacheKey = `${protocol}://${host}::${slugKey}::${optionSignature}`
|
||||||
|
|
||||||
if (!this.instances.has(cacheKey)) {
|
if (!this.instances.has(cacheKey)) {
|
||||||
const instancePromise = this.createAuthForEndpoint(tenantSlug).then((instance) => {
|
const instancePromise = this.createAuthForEndpoint(tenantSlug, options).then((instance) => {
|
||||||
logger.info(`Better Auth initialized for ${cacheKey}`)
|
logger.info(`Better Auth initialized for ${cacheKey}`)
|
||||||
return instance
|
return instance
|
||||||
})
|
})
|
||||||
@@ -344,6 +338,29 @@ export class AuthProvider implements OnModuleInit {
|
|||||||
return await this.instances.get(cacheKey)!
|
return await this.instances.get(cacheKey)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private computeOptionsSignature(options: AuthModuleOptions): string {
|
||||||
|
const hash = createHash('sha256')
|
||||||
|
hash.update(options.baseDomain)
|
||||||
|
hash.update('|gateway=')
|
||||||
|
hash.update(options.oauthGatewayUrl ?? 'null')
|
||||||
|
|
||||||
|
const providerEntries = Object.entries(options.socialProviders)
|
||||||
|
.sort(([a], [b]) => a.localeCompare(b))
|
||||||
|
.map(([provider, config]) => {
|
||||||
|
const secretHash = config?.clientSecret
|
||||||
|
? createHash('sha256').update(config.clientSecret).digest('hex')
|
||||||
|
: 'null'
|
||||||
|
return {
|
||||||
|
provider,
|
||||||
|
clientId: config?.clientId ?? '',
|
||||||
|
secretHash,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
hash.update(JSON.stringify(providerEntries))
|
||||||
|
return hash.digest('hex')
|
||||||
|
}
|
||||||
|
|
||||||
async handler(context: Context): Promise<Response> {
|
async handler(context: Context): Promise<Response> {
|
||||||
const auth = await this.getAuth()
|
const auth = await this.getAuth()
|
||||||
return auth.handler(context.req.raw)
|
return auth.handler(context.req.raw)
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import { createZodDto } from '@afilmory/framework'
|
import { createZodDto } from '@afilmory/framework'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
const redirectPathInputSchema = z
|
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.refine((value) => value.length === 0 || value.startsWith('/'), {
|
|
||||||
message: '路径必须以 / 开头',
|
|
||||||
})
|
|
||||||
|
|
||||||
const updateSuperAdminSettingsSchema = z
|
const updateSuperAdminSettingsSchema = z
|
||||||
.object({
|
.object({
|
||||||
allowRegistration: z.boolean().optional(),
|
allowRegistration: z.boolean().optional(),
|
||||||
@@ -30,10 +23,8 @@ const updateSuperAdminSettingsSchema = z
|
|||||||
.optional(),
|
.optional(),
|
||||||
oauthGoogleClientId: z.string().trim().min(1).nullable().optional(),
|
oauthGoogleClientId: z.string().trim().min(1).nullable().optional(),
|
||||||
oauthGoogleClientSecret: z.string().trim().min(1).nullable().optional(),
|
oauthGoogleClientSecret: z.string().trim().min(1).nullable().optional(),
|
||||||
oauthGoogleRedirectUri: redirectPathInputSchema.nullable().optional(),
|
|
||||||
oauthGithubClientId: z.string().trim().min(1).nullable().optional(),
|
oauthGithubClientId: z.string().trim().min(1).nullable().optional(),
|
||||||
oauthGithubClientSecret: z.string().trim().min(1).nullable().optional(),
|
oauthGithubClientSecret: z.string().trim().min(1).nullable().optional(),
|
||||||
oauthGithubRedirectUri: redirectPathInputSchema.nullable().optional(),
|
|
||||||
})
|
})
|
||||||
.refine((value) => Object.values(value).some((entry) => entry !== undefined), {
|
.refine((value) => Object.values(value).some((entry) => entry !== undefined), {
|
||||||
message: '至少需要更新一项设置',
|
message: '至少需要更新一项设置',
|
||||||
|
|||||||
1
photos
Submodule
1
photos
Submodule
Submodule photos added at 906be11f8e
Reference in New Issue
Block a user