Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BC-8092 - implement config validation #21

Merged
merged 10 commits into from
Oct 16, 2024
Merged

BC-8092 - implement config validation #21

merged 10 commits into from
Oct 16, 2024

Conversation

SevenWaysDP
Copy link
Contributor

@SevenWaysDP SevenWaysDP commented Oct 1, 2024

Description

Links to Tickets or other pull requests

Changes

Datasecurity

Deployment

New Repos, NPM pakages or vendor scripts

Screenshots of UI changes

Approval for review

  • All points were discussed with the ticket creator, support-team or product owner. The code upholds all quality guidelines from the PR-template.

Notice: Please remove the WIP label if the PR is ready to review, otherwise nobody will review it.

@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { ConfigurationModule } from '../configuration/configuration.module.js';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configuration und config sind sich zu ähnlich um ausdrücken zu können was für was ist.

export class XApiKeyConfig {
@Transform(({ value }) => value.split(',').map((part: string) => (part.split(':').pop() ?? '').trim()))
@IsArray()
public ADMIN_API__ALLOWED_API_KEYS = ['randomString'];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sollte der default Wert wirklich bei der Anforderung festgelegt werden? Ich finde das der bessere Ort die Validierung, bzw. das lesen/zuweisen ist.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isDefined() ?

@@ -1,5 +1,4 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-headerapikey/lib/Strategy.js';
import { XApiKeyConfig } from '../config/index.js';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

index ist hier unnötig.


export class AuthorizationConfig {
@IsUrl({ require_tld: false })
public API_HOST = 'http://localhost:3030';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die verschiedenen Werte für prod, test, local sollten aus einer anderen Quelle kommen. Den default als local zu nutzen finde ich nicht gut. Man könnte sicher argumentieren das test eh im test file definiert werden muss. Nur gibt es einzelne envs die immer wieder gesetzt werden müssten und einmalig definiert einfach praktischer sind.

public REDIS!: string;

@IsString()
@IsOptional()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ist das nicht ein Wiederspruch? Es muss string sein, es ist optional, aber ! sagt das es nicht undefined, oder null ist am Ende.

config.REDIS_SENTINEL_SERVICE_NAME = sentinelServiceName;
config.REDIS_PREFIX = redisPrefix;
config.REDIS_SENTINEL_NAME = sentinelName;
config.REDIS_SENTINEL_PASSWORD = sentinelPassword;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wäre ein überschreiben zu einem späteren Zeitpunkt an anderen Stellen auch möglich?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ja mit jest.replaceProperty(config, 'REDIS_SENTINEL_SERVICE_NAME', undefined);

import { App } from 'uws';
import { createMock } from '@golevelup/ts-jest';
import { RedisService } from '../../../../infra/redis/redis.service.js';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Der Pfad ist unglücklich. In dem Repo auch mit @infra zu arbeiten ist denke ich sinnvoller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ja es soll auch so sein, leider wegen ESM Module ist das nicht so einfach wie im server. bzw noch nicht nachgeforscht

}

private validate<T extends object>(config: Record<string, unknown>, Constructor: new () => T): T {
const validatedConfig = plainToInstance(Constructor, config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vs doku
const validatedConfig = plainToInstance(
EnvironmentVariables,
config,
{ enableImplicitConversion: true },
);
const errors = validateSync(validatedConfig, { skipMissingProperties: false });

Comment on lines 10 to 27
public getAllValidConfigsByType<T extends object>(Constructor: new () => T): T {
const config = new Constructor();
const configKeys = Object.keys(config);

const configValues = configKeys.reduce((acc: Record<string, unknown>, key) => {
const value = this.configService.get(key);

if (value) {
acc[key] = value;
}

return acc;
}, {});

const validatedConfig = this.validate(configValues, Constructor);

return validatedConfig;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kompliziert, brauchen wir das wirklich.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wie gesagtes ist nur so möglich auf eingelesene Werte vom ConfigService zuzugreifen und nur die keys zu holen die wir brauchen für dieses Config

@Module({})
export class ConfigurationModule {
public static register<T extends object>(Constructor: new () => T): DynamicModule {
return {
imports: [ConfigModule.forRoot({ cache: true })],
imports: [ConfigModule.forRoot({ cache: true, ...getEnvConfig() })],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hier könnte man das cache: true auch noch nach getEnvConfig verschieben und einfach das ganze object den root übergeben.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Das stimmt

@@ -16,6 +16,6 @@ export class RedisConfig {
public REDIS_SENTINEL_NAME = 'mymaster';

@IsString()
@IsOptional()
@ValidateIf((o) => o.REDIS_SENTINEL_SERVICE_NAME !== undefined)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meintest du hier evtl. o.REDIS_SENTINEL_SERVICE_NAME === undefined

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nein, wenn REDIS_SENTINEL_SERVICE_NAME gesetzt ist soll validieren @ValidateIf

src/infra/storage/storage.config.ts Show resolved Hide resolved
src/infra/storage/storage.service.ts Outdated Show resolved Hide resolved
@SevenWaysDP SevenWaysDP requested a review from CeEv October 16, 2024 10:22
Copy link

@SevenWaysDP SevenWaysDP merged commit 4a25487 into main Oct 16, 2024
61 checks passed
@SevenWaysDP SevenWaysDP deleted the BC-8092 branch October 16, 2024 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants