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 6c43b1a commit c2a779d
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 121 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 @@ -33,6 +33,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
4 changes: 2 additions & 2 deletions packages/platform/platform-params/vitest.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ export default defineConfig(
...presets.test.coverage,
thresholds: {
statements: 99.2,
branches: 90.69,
branches: 90.62,
functions: 100,
lines: 99.2
}
}
}
}
);
);
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
12 changes: 4 additions & 8 deletions packages/security/oidc-provider/src/services/OidcAdapters.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import {Adapter, Adapters} from "@tsed/adapters";
import {Configuration, Inject, Injectable} from "@tsed/di";
import {constant, 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);

createAdapterClass(): AdapterConstructor {
const self = this;
const adapterBase = this.settings.get("oidc.Adapter", this.settings.get("adapters.Adapter"));
const connectionName = this.settings.get("oidc.connectionName", "default");
const adapterBase = constant("oidc.Adapter", constant("adapters.Adapter"));
const connectionName = constant("oidc.connectionName", "default");

return class CustomAdapter implements OidcAdapter {
adapter: OidcAdapterMethods;
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,13 @@ import {OidcProvider} from "./OidcProvider.js";

@Injectable()
export class OidcInteractionContext {
@Constant("env")
protected env: Env;
protected env = constant<Env>("env");
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 Expand Up @@ -115,8 +108,10 @@ export class OidcInteractionContext {
async interactionPrompt({client, ...options}: Record<string, any>): Promise<OidcInteractionPromptProps> {
client = client || (await this.findClient());

const omitClientProps = constant("oidc.render.omitClientProps", []);

return {
client: omit(client, ["clientSecret", ...this.omitClientProps]),
client: omit(client, ["clientSecret", ...omitClientProps]),
uid: this.uid,
grantId: this.grantId,
details: this.prompt.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
12 changes: 4 additions & 8 deletions packages/security/oidc-provider/src/services/OidcJwks.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import {Constant, Injectable} from "@tsed/di";
import {constant, Injectable} from "@tsed/di";
import {getJwks, JwksKeyParameters} from "@tsed/jwks";
import {join} from "path";

@Injectable()
export class OidcJwks {
@Constant("oidc.jwksPath", join(process.cwd(), "keys", "jwks.json"))
jwksPath: string;

@Constant("oidc.certificates")
certificates?: JwksKeyParameters[];

keys: string;
public jwksPath: string = constant("oidc.jwksPath", join(process.cwd(), "keys", "jwks.json"));
public certificates?: JwksKeyParameters[] = constant("oidc.certificates");
public keys: string;

$onInit() {
return this.getJwks();
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
Loading

0 comments on commit c2a779d

Please sign in to comment.