mirror of
https://github.com/bknd-io/bknd/
synced 2026-08-02 08:06:00 +00:00
init auth strategy registry
This commit is contained in:
@@ -6,7 +6,7 @@ import type { Entity, EntityManager } from "data";
|
||||
import { em, entity, enumm, type FieldSchema } from "data/prototype";
|
||||
import { Module } from "modules/Module";
|
||||
import { AuthController } from "./api/AuthController";
|
||||
import { type AppAuthSchema, authConfigSchema, STRATEGIES } from "./auth-schema";
|
||||
import { type AppAuthSchema, authConfigSchema, AuthStrategyRegistry } from "./auth-schema";
|
||||
import { AppUserPool } from "auth/AppUserPool";
|
||||
import type { AppEntity } from "core/config";
|
||||
import { usersFields } from "./auth-entities";
|
||||
@@ -65,7 +65,8 @@ export class AppAuth extends Module<AppAuthSchema> {
|
||||
// build strategies
|
||||
const strategies = transformObject(this.config.strategies ?? {}, (strategy, name) => {
|
||||
try {
|
||||
return new STRATEGIES[strategy.type].cls(strategy.config as any);
|
||||
const cls = AuthStrategyRegistry.get(strategy.type as any).cls;
|
||||
return new cls(strategy.config as any);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Could not build strategy ${String(
|
||||
|
||||
+20
-19
@@ -1,24 +1,25 @@
|
||||
import { cookieConfig, jwtConfig } from "auth/authenticate/Authenticator";
|
||||
import { CustomOAuthStrategy, OAuthStrategy, PasswordStrategy } from "auth/authenticate/strategies";
|
||||
import { cookieConfig, jwtConfig, type Strategy } from "auth/authenticate/Authenticator";
|
||||
import { objectTransform } from "core/utils";
|
||||
import { s } from "core/object/schema";
|
||||
import type { ProvidedOAuthConfig } from "./authenticate/strategies/oauth/OAuthStrategy";
|
||||
import type { OAuthConfigCustom } from "./authenticate/strategies/oauth/CustomOAuthStrategy";
|
||||
import { Registry, type Constructor } from "core";
|
||||
import { PasswordStrategy } from "./authenticate/strategies/PasswordStrategy";
|
||||
import { OAuthStrategy } from "./authenticate/strategies/oauth/OAuthStrategy";
|
||||
import { CustomOAuthStrategy } from "./authenticate/strategies/oauth/CustomOAuthStrategy";
|
||||
|
||||
export const Strategies = {
|
||||
password: {
|
||||
cls: PasswordStrategy,
|
||||
schema: PasswordStrategy.prototype.getSchema(),
|
||||
},
|
||||
oauth: {
|
||||
cls: OAuthStrategy,
|
||||
schema: OAuthStrategy.prototype.getSchema(),
|
||||
},
|
||||
custom_oauth: {
|
||||
cls: CustomOAuthStrategy,
|
||||
schema: CustomOAuthStrategy.prototype.getSchema(),
|
||||
},
|
||||
} as const;
|
||||
export const AuthStrategyRegistry = new Registry<{
|
||||
cls: Constructor<Strategy>;
|
||||
schema: s.Schema;
|
||||
}>((cls: Constructor<Strategy>) => ({
|
||||
cls,
|
||||
schema: cls.prototype.getSchema() as s.Schema,
|
||||
}))
|
||||
.register("password", PasswordStrategy)
|
||||
.register("oauth", OAuthStrategy)
|
||||
.register("custom_oauth", CustomOAuthStrategy);
|
||||
|
||||
export const STRATEGIES = Strategies;
|
||||
export const STRATEGIES = AuthStrategyRegistry.all();
|
||||
const strategiesSchemaObject = objectTransform(STRATEGIES, (strategy, name) => {
|
||||
return s.strictObject(
|
||||
{
|
||||
@@ -34,8 +35,8 @@ const strategiesSchemaObject = objectTransform(STRATEGIES, (strategy, name) => {
|
||||
|
||||
const strategiesSchema = s.anyOf(Object.values(strategiesSchemaObject));
|
||||
export type AppAuthStrategies = s.Static<typeof strategiesSchema>;
|
||||
export type AppAuthOAuthStrategy = s.Static<typeof STRATEGIES.oauth.schema>;
|
||||
export type AppAuthCustomOAuthStrategy = s.Static<typeof STRATEGIES.custom_oauth.schema>;
|
||||
export type AppAuthOAuthStrategy = ProvidedOAuthConfig;
|
||||
export type AppAuthCustomOAuthStrategy = OAuthConfigCustom;
|
||||
|
||||
const guardConfigSchema = s.object({
|
||||
enabled: s.boolean({ default: false }).optional(),
|
||||
|
||||
@@ -30,7 +30,7 @@ const oauthSchemaCustom = s.strictObject(
|
||||
{ title: "Custom OAuth" },
|
||||
);
|
||||
|
||||
type OAuthConfigCustom = s.Static<typeof oauthSchemaCustom>;
|
||||
export type OAuthConfigCustom = s.Static<typeof oauthSchemaCustom>;
|
||||
|
||||
export type UserProfile = {
|
||||
sub: string;
|
||||
|
||||
@@ -26,7 +26,7 @@ const schemaProvided = s.object(
|
||||
},
|
||||
{ title: "OAuth" },
|
||||
);
|
||||
type ProvidedOAuthConfig = s.Static<typeof schemaProvided>;
|
||||
export type ProvidedOAuthConfig = s.Static<typeof schemaProvided>;
|
||||
|
||||
export type CustomOAuthConfig = {
|
||||
type: SupportedTypes;
|
||||
|
||||
@@ -23,7 +23,7 @@ export {
|
||||
type BooleanLike,
|
||||
isBooleanLike,
|
||||
} from "./object/query/query";
|
||||
export { Registry, type Constructor } from "./registry/Registry";
|
||||
export { Registry, type Constructor, type ClassThatImplements } from "./registry/Registry";
|
||||
export { getFlashMessage } from "./server/flash";
|
||||
/* export {
|
||||
s,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
export type ClassThatImplements<T> = Constructor<T> & { prototype: T };
|
||||
export type RegisterFn<Item> = (unknown: any) => Item;
|
||||
|
||||
export class Registry<
|
||||
|
||||
@@ -5,7 +5,7 @@ import { type FileUploadedEventData, Storage, type StorageAdapter, MediaPermissi
|
||||
import { Module } from "modules/Module";
|
||||
import { type FieldSchema, em, entity } from "../data/prototype";
|
||||
import { MediaController } from "./api/MediaController";
|
||||
import { buildMediaSchema, type mediaConfigSchema, registry, type TAppMediaConfig } from "./media-schema";
|
||||
import { buildMediaSchema, MediaAdapterRegistry, type TAppMediaConfig } from "./media-schema";
|
||||
import { mediaFields } from "./media-entities";
|
||||
|
||||
export type MediaFieldSchema = FieldSchema<typeof AppMedia.mediaFields>;
|
||||
@@ -35,7 +35,7 @@ export class AppMedia extends Module<Required<TAppMediaConfig>> {
|
||||
let adapter: StorageAdapter;
|
||||
try {
|
||||
const { type, config } = this.config.adapter;
|
||||
const cls = registry.get(type as any).cls;
|
||||
const cls = MediaAdapterRegistry.get(type as any).cls;
|
||||
adapter = new cls(config as any);
|
||||
|
||||
this._storage = new Storage(adapter, this.config.storage, this.ctx.emgr);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { type Constructor, Registry } from "core";
|
||||
|
||||
export { guess as guessMimeType } from "./storage/mime-types-tiny";
|
||||
export {
|
||||
Storage,
|
||||
@@ -15,7 +13,6 @@ import {
|
||||
StorageCloudinaryAdapter,
|
||||
} from "./storage/adapters/cloudinary/StorageCloudinaryAdapter";
|
||||
import { type S3AdapterConfig, StorageS3Adapter } from "./storage/adapters/s3/StorageS3Adapter";
|
||||
import type { s } from "core/object/schema";
|
||||
|
||||
export { StorageAdapter };
|
||||
export { StorageS3Adapter, type S3AdapterConfig, StorageCloudinaryAdapter, type CloudinaryConfig };
|
||||
@@ -25,27 +22,4 @@ export * as MediaPermissions from "./media-permissions";
|
||||
export type { FileUploadedEventData } from "./storage/events";
|
||||
export * from "./utils";
|
||||
|
||||
type ClassThatImplements<T> = Constructor<T> & { prototype: T };
|
||||
|
||||
export const MediaAdapterRegistry = new Registry<{
|
||||
cls: ClassThatImplements<StorageAdapter>;
|
||||
schema: s.Schema;
|
||||
}>((cls: ClassThatImplements<StorageAdapter>) => ({
|
||||
cls,
|
||||
schema: cls.prototype.getSchema() as s.Schema,
|
||||
}))
|
||||
.register("s3", StorageS3Adapter)
|
||||
.register("cloudinary", StorageCloudinaryAdapter);
|
||||
|
||||
export const Adapters = {
|
||||
s3: {
|
||||
cls: StorageS3Adapter,
|
||||
schema: StorageS3Adapter.prototype.getSchema(),
|
||||
},
|
||||
cloudinary: {
|
||||
cls: StorageCloudinaryAdapter,
|
||||
schema: StorageCloudinaryAdapter.prototype.getSchema(),
|
||||
},
|
||||
} as const;
|
||||
|
||||
export { adapterTestSuite } from "./storage/adapters/adapter-test-suite";
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import { objectTransform } from "core/utils";
|
||||
import { Adapters } from "media";
|
||||
import { registries } from "modules/registries";
|
||||
import { type StorageAdapter, StorageS3Adapter, StorageCloudinaryAdapter } from "media";
|
||||
import { s } from "core/object/schema";
|
||||
import { Registry, type ClassThatImplements } from "core";
|
||||
|
||||
export const ADAPTERS = {
|
||||
...Adapters,
|
||||
} as const;
|
||||
|
||||
export const registry = registries.media;
|
||||
export const MediaAdapterRegistry = new Registry<{
|
||||
cls: ClassThatImplements<StorageAdapter>;
|
||||
schema: s.Schema;
|
||||
}>((cls: ClassThatImplements<StorageAdapter>) => ({
|
||||
cls,
|
||||
schema: cls.prototype.getSchema() as s.Schema,
|
||||
}))
|
||||
.register("s3", StorageS3Adapter)
|
||||
.register("cloudinary", StorageCloudinaryAdapter);
|
||||
|
||||
export function buildMediaSchema() {
|
||||
const adapterSchemaObject = objectTransform(registry.all(), (adapter, name) => {
|
||||
const adapterSchemaObject = objectTransform(MediaAdapterRegistry.all(), (adapter, name) => {
|
||||
return s.strictObject(
|
||||
{
|
||||
type: s.literal(name),
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { MediaAdapterRegistry } from "media";
|
||||
import { AuthStrategyRegistry } from "auth/auth-schema";
|
||||
import { MediaAdapterRegistry } from "media/media-schema";
|
||||
|
||||
const registries = {
|
||||
media: MediaAdapterRegistry,
|
||||
auth: AuthStrategyRegistry,
|
||||
} as const;
|
||||
|
||||
export { registries };
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
TbBrandX,
|
||||
TbSettings,
|
||||
} from "react-icons/tb";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useBknd } from "ui/client/bknd";
|
||||
import { useBkndAuth } from "ui/client/schema/auth/use-bknd-auth";
|
||||
import { Button } from "ui/components/buttons/Button";
|
||||
@@ -76,7 +75,7 @@ function AuthStrategiesListInternal() {
|
||||
|
||||
return (
|
||||
<Form
|
||||
schema={schema.toJSON()}
|
||||
schema={JSON.parse(JSON.stringify(schema))}
|
||||
initialValues={config}
|
||||
onSubmit={handleSubmit}
|
||||
options={formOptions}
|
||||
|
||||
Reference in New Issue
Block a user