Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions runtime/backend/src/AppConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,44 @@ export class AppConfiguration {
return dappConfig.dappName;
}

/**
* This static helper method returns the configuration section value
* based on the provided section name.
*
* @access public
* @static
* @param {string} section The config section name e.g. `"dapp"`, `"statistics"`.
* @returns {object}
*/
public static getConfig(section: string): object {
switch (section) {
case "assets":
return assetsConfigLoader();
case "dapp":
return dappConfigLoader();
case "network":
return networkConfigLoader();
case "oauth":
return oauthConfigLoader();
case "payout":
return payoutConfigLoader();
case "processor":
return processorConfigLoader();
case "security":
return securityConfigLoader();
case "statistics":
return statisticsConfigLoader();
case "social":
return socialConfigLoader();
case "monitoring":
return monitoringConfigLoader();
case "transport":
return transportConfigLoader();
default:
throw new Error(`Cannot find relevant config for section: ${section}`);
}
}

/**
* This static helper method returns all the configuration loaders. This
* method *does not* interpret the content of configuration objects.
Expand Down
12 changes: 8 additions & 4 deletions runtime/backend/src/common/services/AccountsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import {
} from "../models/AccountSchema";

// configuration resources
import dappConfigLoader from "../../../config/dapp";
import networkConfigLoader from "../../../config/network";
import { DappConfig, NetworkConfig } from "../models";
import { AppConfiguration } from "../../AppConfiguration";

/**
* @class AccountsService
Expand Down Expand Up @@ -218,7 +218,9 @@ export class AccountsService {
*/
public static createAddress(publicKeyOrAddress: string): Address {
// extracts the network type from configuration
const { networkIdentifier } = networkConfigLoader().network;
const { networkIdentifier } = (
AppConfiguration.getConfig("network") as NetworkConfig
).network;
const networkType = networkIdentifier as NetworkType;

// if we have a public key (64 characters in hexadecimal format)
Expand All @@ -238,7 +240,9 @@ export class AccountsService {

// source input is **not** a valid address, return fallback
if (sourceAddress.length !== 39) {
return AccountsService.createAddress(dappConfigLoader().dappPublicKey);
return AccountsService.createAddress(
(AppConfiguration.getConfig("dapp") as DappConfig).dappPublicKey,
);
}

// source input **is a valid address format**
Expand Down
10 changes: 4 additions & 6 deletions runtime/backend/src/common/services/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import { NetworkService } from "./NetworkService";
import { LogService } from "./LogService";
import { AccountsService } from "./AccountsService";
import { ChallengesService } from "./ChallengesService";
import { AppConfiguration } from "../../AppConfiguration";
import { AccountDocument, AccountQuery } from "../models/AccountSchema";
import { AccessTokenDTO } from "../models/AccessTokenDTO";
import {
Expand All @@ -42,11 +41,10 @@ import {
AccountSessionQuery,
} from "../models/AccountSessionSchema";
import { AccountSessionsService } from "./AccountSessionsService";
import { AccessTokenRequest } from "../requests/AccessTokenRequest";

// configuration resources
import dappConfigLoader from "../../../config/dapp";
import { AccessTokenRequest } from "../requests/AccessTokenRequest";
const conf = dappConfigLoader();
import { AppConfiguration } from "../../AppConfiguration";

/**
* @interface CookiePayload
Expand Down Expand Up @@ -172,7 +170,7 @@ export class AuthService {
*/
public static extractToken(
request: Request,
cookieName: string = conf.dappName,
cookieName: string = AppConfiguration.dappName,
): string | null {
// private local helper function to extract
// a key from an object only if it is defined
Expand Down Expand Up @@ -274,7 +272,7 @@ export class AuthService {
*/
public async getAccount(
request: Request,
cookieName: string = conf.dappName,
cookieName: string = AppConfiguration.dappName,
): Promise<AccountDocument> {
// read and decode access token
const token: string = AuthService.extractToken(request, cookieName);
Expand Down
34 changes: 8 additions & 26 deletions runtime/backend/src/common/services/LogService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,7 @@
* @license LGPL-3.0
*/
// external dependencies
import {
Inject,
Injectable,
LoggerService,
LogLevel,
Optional,
} from "@nestjs/common";
import { Injectable, LoggerService, LogLevel, Optional } from "@nestjs/common";
import {
utilities as nestWinstonModuleUtilities,
WinstonModule,
Expand All @@ -26,15 +20,13 @@ import "winston-daily-rotate-file";
import { EventEmitter2 } from "@nestjs/event-emitter";

// internal dependencies
import { AppConfiguration } from "../../AppConfiguration";
import { StorageOptions } from "../models/StorageOptions";
import { DappConfig } from "../models/DappConfig";
import { MonitoringConfig } from "../models/MonitoringConfig";
import { AlertEvent } from "../events/AlertEvent";

// configuration resources
import dappConfigLoader from "../../../config/dapp";
import monitoringConfigLoader from "../../../config/monitoring";
import { AppConfiguration } from "../../AppConfiguration";

/**
* @class LogService
Expand Down Expand Up @@ -83,16 +75,6 @@ export class LogService implements LoggerService {
*/
private module: string;

/**
* An instance of {@link DappConfig} that will be used
* to get necessary dapp information for this class.
*
* @access private
* @readonly
* @var {DappConfig}
*/
private readonly dappConfig: DappConfig;

/**
* An instance of {@link DappConfig} that will be used
* to get necessary monitoring information for this class.
Expand All @@ -115,13 +97,13 @@ export class LogService implements LoggerService {
@Optional() protected context?: string,
@Optional() protected eventEmitter?: EventEmitter2,
) {
// @todo should use AppConfiguration
this.dappConfig = dappConfigLoader();
this.monitoringConfig = monitoringConfigLoader();
this.monitoringConfig = AppConfiguration.getConfig(
"monitoring",
) as MonitoringConfig;

// set context to avoid emptiness
if (!this.context || !this.context.length) {
this.context = this.dappConfig.dappName;
this.context = AppConfiguration.dappName;
}

// create a winston logger instance
Expand Down Expand Up @@ -321,8 +303,8 @@ export class LogService implements LoggerService {
const transports: winston.transport[] = [];

// uses volume/global /logs folder
const logFile = `${this.dappConfig.dappName}.log`;
const errFile = `${this.dappConfig.dappName}-error.log`;
const logFile = `${AppConfiguration.dappName}.log`;
const errFile = `${AppConfiguration.dappName}-error.log`;
const logPath = this.monitoringConfig.logDirectoryPath;

// get storage options from config
Expand Down
21 changes: 10 additions & 11 deletions runtime/backend/src/common/traits/AuthStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,16 @@ import { ExtractJwt, Strategy } from "passport-jwt";
import { Request } from "express";

// internal dependencies
import { AccountDocument, AccountQuery } from "../models/AccountSchema";
import { AccountsService } from "../services/AccountsService";
import { AuthenticationPayload } from "../services/AuthService";

// configuration resources
import dappConfigLoader from "../../../config/dapp";
import securityConfigLoader from "../../../config/security";
import {
AccountSessionDocument,
AccountSessionQuery,
} from "../models/AccountSessionSchema";
import { AccountSessionsService } from "../services/AccountSessionsService";
const conf = dappConfigLoader();
const auth = securityConfigLoader().auth;

// configuration resources
import { AppConfiguration } from "../../AppConfiguration";
import { SecurityConfig } from "../models";

/**
* @class AuthStrategy
Expand All @@ -51,19 +47,22 @@ export class AuthStrategy extends PassportStrategy(Strategy) {
jwtFromRequest: ExtractJwt.fromExtractors([
// do we have a refresh token in the request's *signed*
// httpOnly cookies? (name: "dappName:Refresh")
(request: Request) => request?.signedCookies[conf.dappName] ?? null,
(request: Request) =>
request?.signedCookies[AppConfiguration.dappName] ?? null,

// do we have a refresh token in the request's *unsigned*
// httpOnly cookies? (name: "dappName:Refresh")
(request: Request) => request?.cookies[conf.dappName] ?? null,
(request: Request) =>
request?.cookies[AppConfiguration.dappName] ?? null,

// enables `Authorization` header
ExtractJwt.fromAuthHeaderAsBearerToken(),
]),
// delegates the validation of expiry to Passport
ignoreExpiration: false,
// defines a symmetric secret key for signing tokens
secretOrKey: auth.secret,
secretOrKey: (AppConfiguration.getConfig("security") as SecurityConfig)
.auth.secret,
});
}

Expand Down
16 changes: 8 additions & 8 deletions runtime/backend/src/common/traits/RefreshStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ import {
} from "../models/AccountSessionSchema";

// configuration resources
import dappConfigLoader from "../../../config/dapp";
import securityConfigLoader from "../../../config/security";
const conf = dappConfigLoader();
const auth = securityConfigLoader().auth;
import { AppConfiguration } from "../../AppConfiguration";
import { SecurityConfig } from "../models";

/**
* @class RefreshStrategy
Expand All @@ -51,18 +49,20 @@ export class RefreshStrategy extends PassportStrategy(Strategy, "jwt-refresh") {
// do we have a refresh token in the request's *signed*
// httpOnly cookies? (name: "dappName:Refresh")
(request: Request) =>
request?.signedCookies[conf.dappName + ":Refresh"] ?? null,
request?.signedCookies[AppConfiguration.dappName + ":Refresh"] ??
null,

// do we have a refresh token in the request's *unsigned*
// httpOnly cookies? (name: "dappName:Refresh")
(request: Request) =>
request?.cookies[conf.dappName + ":Refresh"] ?? null,
request?.cookies[AppConfiguration.dappName + ":Refresh"] ?? null,

// do we have a refresh token in Authorization header?
ExtractJwt.fromAuthHeaderAsBearerToken(),
]),
// defines a symmetric secret key for signing tokens
secretOrKey: auth.secret,
secretOrKey: (AppConfiguration.getConfig("security") as SecurityConfig)
.auth.secret,
// permits to access the cookie from validate method
passReqToCallback: true,
});
Expand All @@ -86,7 +86,7 @@ export class RefreshStrategy extends PassportStrategy(Strategy, "jwt-refresh") {
// extracts refresh token from *signed cookies*
const refreshToken = AuthService.extractToken(
request,
`${conf.dappName}:Refresh`,
`${AppConfiguration.dappName}:Refresh`,
);

// finds an `accounts` document using a SHA3-256
Expand Down
59 changes: 59 additions & 0 deletions runtime/backend/tests/unit/AppConfiguration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,65 @@ describe("AppConfiguration", () => {
})
});

describe("static getConfig()", () => {
it("should return correct config section", () => {
// prepare
const configSections = [
"assets",
"dapp",
"network",
"oauth",
"payout",
"processor",
"security",
"statistics",
"social",
"monitoring",
"transport",
];
const loaderCalls = [
mockAssetsConfigLoaderCall,
mockDappConfigLoaderCall,
mockNetworkConfigLoaderCall,
mockOauthConfigLoaderCall,
mockPayoutConfigLoaderCall,
mockProcessorConfigLoaderCall,
mockSecurityConfigLoaderCall,
mockStatisticsConfigLoaderCall,
mockSocialConfigLoaderCall,
mockMonitoringConfigLoaderCall,
mockTransportConfigLoaderCall,
]
configSections.forEach((configSection: string, index: number) => {
// act
const result = AppConfiguration.getConfig(configSection);

// assert
expect(loaderCalls[index]).toHaveBeenCalledTimes(1); // first call was in constructor
expect(result).toBeDefined();
})
});

it("should throw error if section name is not defined/in list", () => {
// prepare
[
undefined,
null,
"",
true,
"some-non-existing-section"
].forEach((configSection: any) => {
const expectedError = new Error(`Cannot find relevant config for section: ${configSection}`);

// act
const result = () => AppConfiguration.getConfig(configSection);

// assert
expect(result).toThrowError(expectedError);
});
});
});

describe("getDatabaseModule()", () => {
it("should create instance using mongoose module", () => {
// act
Expand Down
2 changes: 2 additions & 0 deletions runtime/backend/tests/unit/worker/WorkerModule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
* @license LGPL-3.0
*/
// mock AppConfiguration
import testMonitoringConfigLoader from "../../../config/monitoring";
class MockAppConfiguration {
static getConfig = jest.fn().mockReturnValue(testMonitoringConfigLoader());
static getMailerModule = jest.fn();
static getEventEmitterModule = jest.fn();
static getDatabaseModule = jest.fn();
Expand Down