updating dynamic module to configurable module builder
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
export interface AuthOptions {
|
||||
export interface AuthModuleOptions {
|
||||
tenantId: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
|
||||
4
libs/modules/src/auth/auth.module-definition.ts
Normal file
4
libs/modules/src/auth/auth.module-definition.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ConfigurableModuleBuilder } from '@nestjs/common';
|
||||
import { AuthModuleOptions } from './auth.interface';
|
||||
|
||||
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder<AuthModuleOptions>().build()
|
||||
@@ -1,26 +1,14 @@
|
||||
import { Module, DynamicModule } from '@nestjs/common';
|
||||
import { AuthOptions } from './auth.interface';
|
||||
import { AUTH_OPTIONS } from './auth.constants';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { AzureAdStrategy } from './auth.strategy';
|
||||
import { ConfigurableModuleClass } from './auth.module-definition';
|
||||
|
||||
@Module({})
|
||||
export class AuthModule {
|
||||
static register(options: AuthOptions): DynamicModule {
|
||||
return {
|
||||
module: AuthModule,
|
||||
imports: [
|
||||
PassportModule.register({
|
||||
defaultStrategy: 'azure-ad'
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: AUTH_OPTIONS,
|
||||
useValue: options
|
||||
},
|
||||
AzureAdStrategy
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
@Module({
|
||||
imports: [
|
||||
PassportModule.register({
|
||||
defaultStrategy: 'azure-ad'
|
||||
})
|
||||
],
|
||||
providers: [AzureAdStrategy]
|
||||
})
|
||||
export class AuthModule extends ConfigurableModuleClass {}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { PassportStrategy } from "@nestjs/passport";
|
||||
import { BearerStrategy } from 'passport-azure-ad';
|
||||
import { AuthOptions } from './auth.interface'
|
||||
import { AUTH_OPTIONS } from "./auth.constants";
|
||||
import { AuthModuleOptions } from './auth.interface'
|
||||
import { MODULE_OPTIONS_TOKEN } from "./auth.module-definition";
|
||||
|
||||
@Injectable()
|
||||
export class AzureAdStrategy extends PassportStrategy(
|
||||
BearerStrategy,
|
||||
'azure-ad'
|
||||
) {
|
||||
constructor(@Inject(AUTH_OPTIONS) authOptions: AuthOptions) {
|
||||
constructor(@Inject(MODULE_OPTIONS_TOKEN) authModuleOptions: AuthModuleOptions) {
|
||||
console.log(authModuleOptions)
|
||||
super({
|
||||
identityMetadata: `https://login.microsoftonline.com/${authOptions.tenantId}/.well-known/openid-configuration`,
|
||||
clientID: authOptions.clientId,
|
||||
audience: `api://${authOptions.clientId}`,
|
||||
identityMetadata: `https://login.microsoftonline.com/${authModuleOptions.tenantId}/.well-known/openid-configuration`,
|
||||
clientID: authModuleOptions.clientId,
|
||||
audience: `api://${authModuleOptions.clientId}`,
|
||||
loggingLevel: 'info',
|
||||
loggingNoPII: false
|
||||
})
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const APP_CONFIG_OPTIONS = 'APP_CONFIG_OPTIONS';
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface AppConfigOptions {
|
||||
url: string;
|
||||
tenantId: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Module, DynamicModule } from '@nestjs/common';
|
||||
import { AppConfigService } from './az-app-config.service';
|
||||
import { AppConfigOptions } from './az-app-config.interface';
|
||||
import { APP_CONFIG_OPTIONS } from './az-app-config.constants';
|
||||
|
||||
@Module({})
|
||||
export class AppConfigModule {
|
||||
static register(options: AppConfigOptions): DynamicModule {
|
||||
return {
|
||||
module: AppConfigModule,
|
||||
providers: [
|
||||
{
|
||||
provide: APP_CONFIG_OPTIONS,
|
||||
useValue: options
|
||||
},
|
||||
AppConfigService
|
||||
],
|
||||
exports: [AppConfigService]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { AppConfigOptions } from './az-app-config.interface';
|
||||
import { APP_CONFIG_OPTIONS } from './az-app-config.constants';
|
||||
import axios, { AxiosResponse } from 'axios';
|
||||
import { AppConfigurationClient, ConfigurationSetting, FeatureFlagValue, GetConfigurationSettingResponse, featureFlagPrefix, isFeatureFlag, parseFeatureFlag } from '@azure/app-configuration';
|
||||
import { ClientSecretCredential } from '@azure/identity';
|
||||
|
||||
@Injectable()
|
||||
export class AppConfigService {
|
||||
constructor(
|
||||
@Inject(APP_CONFIG_OPTIONS)
|
||||
private appConfigOptions: AppConfigOptions
|
||||
) { }
|
||||
|
||||
async getFeatureFlags(keys: string[], label: string): Promise<{ key: string, enabled: boolean }[]> {
|
||||
const credential: ClientSecretCredential = new ClientSecretCredential(this.appConfigOptions.tenantId, this.appConfigOptions.clientId, this.appConfigOptions.clientSecret);
|
||||
const client: AppConfigurationClient = new AppConfigurationClient(this.appConfigOptions.url, credential);
|
||||
const featureFlags: { key: string, enabled: boolean }[] = await Promise.all(
|
||||
keys.map(async (key: string) => {
|
||||
const configSetting: GetConfigurationSettingResponse = await client.getConfigurationSetting({
|
||||
key: `${featureFlagPrefix}${key}`,
|
||||
label: label
|
||||
});
|
||||
|
||||
if (isFeatureFlag(configSetting)) {
|
||||
const parsedFeatureFlag: ConfigurationSetting<FeatureFlagValue> = parseFeatureFlag(configSetting);
|
||||
|
||||
return {
|
||||
key: parsedFeatureFlag.value.id,
|
||||
enabled: parsedFeatureFlag.value.enabled
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return featureFlags;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export const TABLE_OPTIONS = 'TABLE_OPTIONS';
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface TableOptions {
|
||||
accountName: string;
|
||||
accountKey: string;
|
||||
accountUrl: string;
|
||||
allowInsecureConnection: boolean;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { Module, DynamicModule } from '@nestjs/common';
|
||||
import { TableService } from './az-table.service';
|
||||
import { TableOptions } from './az-table.interface';
|
||||
import { TABLE_OPTIONS } from './az-table.constants';
|
||||
|
||||
@Module({})
|
||||
export class TableModule {
|
||||
static register(options: TableOptions): DynamicModule {
|
||||
return {
|
||||
module: TableModule,
|
||||
providers: [
|
||||
{
|
||||
provide: TABLE_OPTIONS,
|
||||
useValue: options
|
||||
},
|
||||
TableService
|
||||
],
|
||||
exports: [TableService]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TableOptions } from './az-table.interface';
|
||||
import { TABLE_OPTIONS } from './az-table.constants';
|
||||
import { TableClient, AzureNamedKeyCredential, TableServiceClient, TableServiceClientOptions } from '@azure/data-tables';
|
||||
|
||||
@Injectable()
|
||||
export class TableService {
|
||||
constructor(
|
||||
@Inject(TABLE_OPTIONS)
|
||||
private tablesOptions: TableOptions
|
||||
) {}
|
||||
|
||||
async checkTableExists(tableName: string, tableServiceClient: TableServiceClient): Promise<boolean> {
|
||||
const tables = tableServiceClient.listTables();
|
||||
let tableExists: boolean = false;
|
||||
|
||||
for await (const table of tables) {
|
||||
if (table.name === tableName) {
|
||||
tableExists = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tableExists;
|
||||
}
|
||||
|
||||
async getTableClient(tableName: string): Promise<TableClient> {
|
||||
try {
|
||||
const credential: AzureNamedKeyCredential = new AzureNamedKeyCredential(this.tablesOptions.accountName, this.tablesOptions.accountKey);
|
||||
const options: TableServiceClientOptions = { allowInsecureConnection: this.tablesOptions.allowInsecureConnection };
|
||||
const tableServiceClient: TableServiceClient = new TableServiceClient(this.tablesOptions.accountUrl, credential, options);
|
||||
const tableExists: boolean = await this.checkTableExists(tableName, tableServiceClient);
|
||||
|
||||
if (!tableExists) {
|
||||
await tableServiceClient.createTable(tableName);
|
||||
}
|
||||
|
||||
const tableClient: TableClient = new TableClient(this.tablesOptions.accountUrl, tableName, credential, options);
|
||||
|
||||
return tableClient;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
libs/modules/src/dapr/dapr.logger.ts
Normal file
28
libs/modules/src/dapr/dapr.logger.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// import { Logger } from '@nestjs/common';
|
||||
// import { LoggerService } from '@dapr/dapr';
|
||||
|
||||
// export class DaprLogger implements LoggerService {
|
||||
// private readonly logger = new Logger(DaprLogger.name);
|
||||
|
||||
// constructor() {}
|
||||
|
||||
// error(message: any, ...optionalParams: any[]): void {
|
||||
// this.logger.error(message, ...optionalParams);
|
||||
// }
|
||||
|
||||
// warn(message: any, ...optionalParams: any[]): void {
|
||||
// this.logger.warn(message, ...optionalParams);
|
||||
// }
|
||||
|
||||
// info(message: any, ...optionalParams: any[]): void {
|
||||
// this.logger.log(message, ...optionalParams);
|
||||
// }
|
||||
|
||||
// verbose(message: any, ...optionalParams: any[]): void {
|
||||
// this.logger.verbose(message, ...optionalParams);
|
||||
// }
|
||||
|
||||
// debug(message: any, ...optionalParams: any[]): void {
|
||||
// this.logger.debug(message, ...optionalParams);
|
||||
// }
|
||||
// }
|
||||
8
libs/modules/src/dapr/dapr.module.ts
Normal file
8
libs/modules/src/dapr/dapr.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { DaprService } from "./dapr.service";
|
||||
|
||||
@Module({
|
||||
providers: [ DaprService ],
|
||||
exports: [ DaprService ]
|
||||
})
|
||||
export class DaprModule {}
|
||||
13
libs/modules/src/dapr/dapr.service.ts
Normal file
13
libs/modules/src/dapr/dapr.service.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { DaprClient } from '@dapr/dapr';
|
||||
|
||||
@Injectable()
|
||||
export class DaprService {
|
||||
daprClient: DaprClient;
|
||||
private readonly logger = new Logger(DaprService.name);
|
||||
|
||||
constructor() {
|
||||
this.logger.log('Initializing DaprClient')
|
||||
this.daprClient = new DaprClient();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,20 @@
|
||||
// Azure App Configuration
|
||||
|
||||
export * from './azAppConfig/az-app-config.module';
|
||||
export * from './azAppConfig/az-app-config.service';
|
||||
|
||||
// Azure Data Tables
|
||||
|
||||
export * from './azTable/az-table.module';
|
||||
export * from './azTable/az-table.service';
|
||||
export { TableClient } from '@azure/data-tables';
|
||||
|
||||
// Auth
|
||||
|
||||
export * from './auth/auth.module';
|
||||
export * from './auth/auth.gaurd';
|
||||
export * from './auth/public.decorator';
|
||||
|
||||
// Dapr
|
||||
|
||||
export * from './dapr/dapr.module'
|
||||
export * from './dapr/dapr.service'
|
||||
|
||||
// MS Graph
|
||||
|
||||
export * from './msGraph/ms-graph.module';
|
||||
export * from './msGraph/ms-graph.service';
|
||||
export { Client as MsGraphClient } from '@microsoft/microsoft-graph-client';
|
||||
|
||||
// Custom Error
|
||||
|
||||
export * from './util/customError';
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const MS_GRAPH_OPTIONS = 'MS_GRAPH_OPTIONS';
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface MsGraphOptions {
|
||||
export interface MsGraphModuleOptions {
|
||||
tenantId: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
|
||||
4
libs/modules/src/msGraph/ms-graph.module-definition.ts
Normal file
4
libs/modules/src/msGraph/ms-graph.module-definition.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ConfigurableModuleBuilder } from '@nestjs/common';
|
||||
import { MsGraphModuleOptions } from './ms-graph.interface';
|
||||
|
||||
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder<MsGraphModuleOptions>().build()
|
||||
@@ -1,21 +1,9 @@
|
||||
import { Module, DynamicModule } from '@nestjs/common';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MsGraphService } from './ms-graph.service';
|
||||
import { MsGraphOptions } from './ms-graph.interface';
|
||||
import { MS_GRAPH_OPTIONS } from './ms-graph.constants';
|
||||
import { ConfigurableModuleClass } from './ms-graph.module-definition';
|
||||
|
||||
@Module({})
|
||||
export class MsGraphModule {
|
||||
static register(options: MsGraphOptions): DynamicModule {
|
||||
return {
|
||||
module: MsGraphModule,
|
||||
providers: [
|
||||
{
|
||||
provide: MS_GRAPH_OPTIONS,
|
||||
useValue: options
|
||||
},
|
||||
MsGraphService
|
||||
],
|
||||
exports: [MsGraphService]
|
||||
}
|
||||
}
|
||||
}
|
||||
@Module({
|
||||
providers: [MsGraphService],
|
||||
exports: [MsGraphService]
|
||||
})
|
||||
export class MsGraphModule extends ConfigurableModuleClass {}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { MsGraphOptions } from './ms-graph.interface';
|
||||
import { MS_GRAPH_OPTIONS } from './ms-graph.constants';
|
||||
import { MsGraphModuleOptions } from './ms-graph.interface';
|
||||
import { Client } from '@microsoft/microsoft-graph-client';
|
||||
import { AuthenticationResult, ConfidentialClientApplication, OnBehalfOfRequest } from '@azure/msal-node';
|
||||
import { MODULE_OPTIONS_TOKEN } from './ms-graph.module-definition';
|
||||
|
||||
@Injectable()
|
||||
export class MsGraphService {
|
||||
constructor(@Inject(MS_GRAPH_OPTIONS) private msGraphOptions: MsGraphOptions) {}
|
||||
constructor(@Inject(MODULE_OPTIONS_TOKEN) private msGraphModuleOptions: MsGraphModuleOptions) {}
|
||||
|
||||
async getMsGraphAuth(accessToken: string, scopes: string[]): Promise<string> {
|
||||
try {
|
||||
@@ -16,9 +16,9 @@ export class MsGraphService {
|
||||
}
|
||||
const cca = new ConfidentialClientApplication({
|
||||
auth: {
|
||||
clientId: this.msGraphOptions.clientId,
|
||||
clientSecret: this.msGraphOptions.clientSecret,
|
||||
authority: `https://login.microsoftonline.com/${this.msGraphOptions.tenantId}`
|
||||
clientId: this.msGraphModuleOptions.clientId,
|
||||
clientSecret: this.msGraphModuleOptions.clientSecret,
|
||||
authority: `https://login.microsoftonline.com/${this.msGraphModuleOptions.tenantId}`
|
||||
}
|
||||
});
|
||||
const authenticationResult: AuthenticationResult = await cca.acquireTokenOnBehalfOf(oboRequest);
|
||||
|
||||
9
libs/modules/src/util/customError.ts
Normal file
9
libs/modules/src/util/customError.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export class CustomError extends Error {
|
||||
statusCode: number;
|
||||
|
||||
constructor(message, name, statusCode) {
|
||||
super(message);
|
||||
this.name = name;
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user