Skip to content

Commit

Permalink
refactor(oidc-provider): use functional DI Api to inject services
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakita committed Oct 7, 2024
1 parent 35cdff0 commit 744d191
Show file tree
Hide file tree
Showing 11 changed files with 127 additions and 108 deletions.
42 changes: 42 additions & 0 deletions packages/di/src/common/fn/refValue.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {DITest} from "../../node/index.js";
import {refValue} from "./refValue.js";

describe("refValue()", () => {
beforeEach(() =>
DITest.create({
logger: {
level: "off"
}
})
);
afterEach(() => DITest.reset());
describe("when decorator is used as property decorator", () => {
it("should create a getter", async () => {
// WHEN
class Test {
test = refValue("logger.level", "default value");
}

// THEN

const test = await DITest.invoke<Test>(Test);

expect(test.test.value).toEqual("off");
});
it("should create a getter with default value", async () => {
expect(DITest.injector.settings.get("logger.test")).toEqual(undefined);

// WHEN
class Test {
test = refValue("logger.test", "default value");
}

// THEN

const test = await DITest.invoke<Test>(Test);

expect(test.test.value).toEqual("default value");
expect(DITest.injector.settings.get("logger.test")).toEqual(undefined);
});
});
});
33 changes: 33 additions & 0 deletions packages/di/src/common/fn/refValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {injector} from "./injector.js";

/**
* Get a value from the `injector.settings`.
*
* ## Example
*
* ```ts
* import {refValue, Injectable} from "@tsed/di";
*
* @Injectable()
* class Test {
* test = refValue("logger.level", "default value");
*
* constructor() {
* console.log(this.test.value); // "off"
* }
* }
*
* @param expression The expression to get the value from the `injector.settings`.
*/
export function refValue<Type>(expression: string): {value: Type | undefined};
export function refValue<Type>(expression: string, defaultValue: Type | undefined): {value: Type};
export function refValue<Type>(expression: string, defaultValue?: Type | undefined): {value: Type | undefined} {
return Object.freeze({
get value() {
return injector().settings.get(expression, defaultValue);
},
set value(value: Type) {
injector().settings.set(expression, value);
}
});
}
1 change: 1 addition & 0 deletions packages/di/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export * from "./fn/inject.js";
export * from "./fn/injectable.js";
export * from "./fn/injectMany.js";
export * from "./fn/injector.js";
export * from "./fn/refValue.js";
export * from "./interfaces/DIConfigurationOptions.js";
export * from "./interfaces/DILogger.js";
export * from "./interfaces/DILoggerOptions.js";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Constant, Inject, Module} from "@tsed/di";
import {Logger} from "@tsed/logger";
import {constant, logger, Module} from "@tsed/di";
import {OidcSettings} from "@tsed/oidc-provider";
import Provider, {errors, type KoaContextWithOIDC} from "oidc-provider";
// @ts-ignore
Expand All @@ -19,11 +18,7 @@ declare global {

@Module()
export class OidcWildcardRedirectUriModule {
@Constant("oidc.plugins.wildcard.enabled", false)
readonly enabled: boolean;

@Inject(Logger)
protected logger: Logger;
readonly enabled = constant<boolean>("oidc.plugins.wildcard.enabled", false);

$onCreateOIDC(provider: Provider) {
if (this.enabled) {
Expand All @@ -34,7 +29,7 @@ export class OidcWildcardRedirectUriModule {
"postLogoutRedirectUris"
);

this.logger.warn("⚠️⚠️⚠️ OIDC Wildcard Uris plugin is ENABLED ⚠️⚠️⚠️");
logger().warn("⚠️⚠️⚠️ OIDC Wildcard Uris plugin is ENABLED ⚠️⚠️⚠️");
}
}

Expand Down
27 changes: 9 additions & 18 deletions packages/security/oidc-provider/src/OidcModule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Inject, InjectorService, PlatformApplication} from "@tsed/common";
import {Constant, Module} from "@tsed/di";
import {PlatformApplication} from "@tsed/common";
import {$injector, constant, inject, Module} from "@tsed/di";
import koaMount from "koa-mount";

import {OidcAdapters} from "./services/OidcAdapters.js";
Expand All @@ -10,20 +10,10 @@ import {OidcProvider} from "./services/OidcProvider.js";
imports: [OidcProvider, OidcAdapters, OidcJwks]
})
export class OidcModule {
@Inject()
protected app: PlatformApplication;

@Constant("PLATFORM_NAME")
protected platformName: string;

@Constant("oidc.path", "/oidc")
protected basePath: string;

@Inject()
protected oidcProvider: OidcProvider;

@Inject()
protected injector: InjectorService;
protected app: PlatformApplication = inject(PlatformApplication);
protected platformName = constant<string>("PLATFORM_NAME");
protected basePath = constant("oidc.path", "/oidc");
protected oidcProvider = inject(OidcProvider);

async $onInit() {
if (this.oidcProvider.hasConfiguration()) {
Expand Down Expand Up @@ -54,8 +44,9 @@ export class OidcModule {
}

$onReady() {
if (this.oidcProvider.hasConfiguration() && "getBestHost" in this.injector.settings) {
const {injector} = this;
const injector = $injector();

if (this.oidcProvider.hasConfiguration() && "getBestHost" in injector.settings) {
// @ts-ignore
const host = injector.settings.getBestHost();
const url = host.toString();
Expand Down
9 changes: 3 additions & 6 deletions packages/security/oidc-provider/src/services/OidcAdapters.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import {Adapter, Adapters} from "@tsed/adapters";
import {Configuration, Inject, Injectable} from "@tsed/di";
import {Configuration, inject, Injectable} from "@tsed/di";
import type {Adapter as OidcAdapter, AdapterConstructor} from "oidc-provider";

export type OidcAdapterMethods<Model = any> = Adapter<Model> & Partial<Omit<OidcAdapter, "upsert">>;

@Injectable()
export class OidcAdapters {
@Inject()
protected adapters: Adapters;

@Configuration()
protected settings: Configuration;
protected adapters = inject(Adapters);
protected settings = inject(Configuration);

createAdapterClass(): AdapterConstructor {
const self = this;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Constant, InjectContext, PlatformContext} from "@tsed/common";
import {PlatformContext} from "@tsed/common";
import {Env} from "@tsed/core";
import {Inject, Injectable} from "@tsed/di";
import {constant, context, inject, Injectable} from "@tsed/di";
import {Unauthorized} from "@tsed/exceptions";
import omit from "lodash/omit.js";
import type {Account, default as Provider, InteractionResults, PromptDetail} from "oidc-provider";
Expand All @@ -24,20 +24,14 @@ import {OidcProvider} from "./OidcProvider.js";

@Injectable()
export class OidcInteractionContext {
@Constant("env")
protected env: Env;
protected env = constant<Env>("env");
protected omitClientProps: string[] = constant("oidc.render.omitClientProps", []);
protected oidcProvider = inject(OidcProvider);
protected oidcInteractions = inject(OidcInteractions);

@Constant("oidc.render.omitClientProps", [])
protected omitClientProps: string[];

@Inject()
protected oidcProvider: OidcProvider;

@Inject()
protected oidcInteractions: OidcInteractions;

@InjectContext()
protected $ctx: PlatformContext;
get $ctx() {
return context<PlatformContext>();
}

get raw(): OidcInteraction {
return this.$ctx.get(INTERACTION_DETAILS)!;
Expand Down
17 changes: 5 additions & 12 deletions packages/security/oidc-provider/src/services/OidcInteractions.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import {Constant, EndpointMetadata, PlatformContext, PlatformHandler, Provider, TokenProvider} from "@tsed/common";
import {PlatformContext, PlatformHandler} from "@tsed/common";
import {Env} from "@tsed/core";
import {Inject, Injectable, InjectorService} from "@tsed/di";
import {constant, Injectable, injector, Provider, TokenProvider} from "@tsed/di";
import {EndpointMetadata} from "@tsed/schema";

import {INTERACTION, INTERACTION_OPTIONS, INTERACTIONS} from "../constants/constants.js";
import {OidcInteractionOptions} from "../domain/OidcInteractionOptions.js";
import {OidcSettings} from "../domain/OidcSettings.js";

@Injectable()
export class OidcInteractions {
@Inject()
protected injector: InjectorService;

@Constant("env")
protected env: Env;

@Constant("oidc")
protected oidcSettings: OidcSettings;

protected injector = injector();
protected env = constant<Env>("env");
protected interactions: Map<string, Provider> = new Map();

$onInit(): void {
Expand Down
9 changes: 3 additions & 6 deletions packages/security/oidc-provider/src/services/OidcPolicy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Inject, Injectable, InjectorService, Provider} from "@tsed/di";
import {inject, Injectable, injector, Provider} from "@tsed/di";
import {interactionPolicy} from "oidc-provider";

import {InteractionMethods} from "../domain/InteractionMethods.js";
Expand All @@ -8,11 +8,8 @@ import Prompt = interactionPolicy.Prompt;

@Injectable()
export class OidcPolicy {
@Inject()
protected injector: InjectorService;

@Inject()
protected oidcInteractions: OidcInteractions;
protected injector = injector();
protected oidcInteractions = inject(OidcInteractions);

public getPolicy() {
let policy = interactionPolicy.base();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe("OidcProvider", () => {

expect((oidcProvider as any).injector.logger.error).toHaveBeenCalledWith({
duration: expect.any(Number),
reqId: "",
reqId: expect.any(String),
account_id: "account_id",
error: {error_description: "error_description", error_detail: "error_detail", error: "error"},
event: "OIDC_ERROR",
Expand Down
60 changes: 18 additions & 42 deletions packages/security/oidc-provider/src/services/OidcProvider.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {InjectContext, PlatformApplication, PlatformContext} from "@tsed/common";
import {PlatformApplication, PlatformContext} from "@tsed/common";
import {Env, setValue} from "@tsed/core";
import {Constant, Inject, Injectable, InjectorService} from "@tsed/di";
import {constant, context, inject, Injectable, InjectorService} from "@tsed/di";
import Provider, {type Configuration, type KoaContextWithOIDC} from "oidc-provider";

import {INTERACTIONS} from "../constants/constants.js";
import {OidcAccountsMethods} from "../domain/OidcAccountsMethods.js";
import {OidcSettings} from "../domain/OidcSettings.js";
import {OIDC_ERROR_EVENTS} from "../utils/events.js";
import {OidcAdapters} from "./OidcAdapters.js";
import {OidcInteractions} from "./OidcInteractions.js";
import {OidcJwks} from "./OidcJwks.js";
import {OidcPolicy} from "./OidcPolicy.js";

Expand All @@ -25,47 +24,24 @@ function mapError(error: any) {
export class OidcProvider {
raw: Provider;

@Constant("env")
protected env: Env;

@Constant("httpPort")
protected httpPort: number | string;

@Constant("httpsPort")
protected httpsPort: number | string;

@Constant("oidc.issuer", "")
protected issuer: string;

@Constant("oidc")
protected oidc: OidcSettings;

@Constant("PLATFORM_NAME")
protected platformName: string;

@Inject()
protected oidcJwks: OidcJwks;

@Inject()
protected oidcInteractions: OidcInteractions;

@Inject()
protected oidcPolicy: OidcPolicy;

@Inject()
protected adapters: OidcAdapters;

@Inject()
protected injector: InjectorService;

@Inject()
protected app: PlatformApplication;

@InjectContext()
protected $ctx?: PlatformContext;
protected env = constant<Env>("env");
protected httpPort = constant<number | string>("httpPort");
protected httpsPort = constant<number | string>("httpsPort");
protected issuer = constant<string>("oidc.issuer", "");
protected oidc = constant<OidcSettings>("oidc")!;
protected platformName = constant<string>("PLATFORM_NAME");
protected oidcJwks = inject(OidcJwks);
protected oidcPolicy = inject(OidcPolicy);
protected adapters = inject(OidcAdapters);
protected injector = inject(InjectorService);
protected app = inject(PlatformApplication);

get logger() {
return this.$ctx?.logger || this.injector.logger;
return this.$ctx.logger;
}

protected get $ctx() {
return context<PlatformContext>();
}

hasConfiguration() {
Expand Down

0 comments on commit 744d191

Please sign in to comment.