diff --git a/packages/server-nest/src/modules/Settings/Settings.controller.ts b/packages/server-nest/src/modules/Settings/Settings.controller.ts index 51c0cf955..11bbc2857 100644 --- a/packages/server-nest/src/modules/Settings/Settings.controller.ts +++ b/packages/server-nest/src/modules/Settings/Settings.controller.ts @@ -1,16 +1,20 @@ -import { Controller, Get } from '@nestjs/common'; -import { Inject } from '@nestjs/common'; -import { SETTINGS } from './Settings.module'; -import { SettingsStore } from './SettingsStore'; +import { Body, Controller, Get, Post } from '@nestjs/common'; +import { SettingsApplicationService } from './SettingsApplication.service'; +import { ISettingsDTO } from './Settings.types'; +import { PublicRoute } from '../Auth/Jwt.guard'; @Controller('settings') +@PublicRoute() export class SettingsController { constructor( - @Inject(SETTINGS) private readonly settingsStore: SettingsStore, + private readonly settingsApplicationService: SettingsApplicationService, ) {} - @Get('') - async getSettings() { - return this.settingsStore.all(); + @Post('') + async saveSettings(@Body() settingsDTO: ISettingsDTO) { + return this.settingsApplicationService.saveSettings(settingsDTO); } + + @Get('') + async getSettings() {} } diff --git a/packages/server-nest/src/modules/Settings/Settings.module.ts b/packages/server-nest/src/modules/Settings/Settings.module.ts index 9bf9c86b2..a91989511 100644 --- a/packages/server-nest/src/modules/Settings/Settings.module.ts +++ b/packages/server-nest/src/modules/Settings/Settings.module.ts @@ -1,20 +1,25 @@ import { Module } from '@nestjs/common'; import { SettingRepository } from './repositories/Setting.repository'; import { SettingsStore } from './SettingsStore'; - -export const SETTINGS = 'SETTINGS'; +import { SettingsApplicationService } from './SettingsApplication.service'; +import { SaveSettingsService } from './commands/SaveSettings.service'; +import { SettingsController } from './Settings.controller'; +import { SETTINGS_PROVIDER } from './Settings.types'; @Module({ providers: [ SettingRepository, { - provide: SETTINGS, + provide: SETTINGS_PROVIDER, useFactory: (settingRepository: SettingRepository) => { return new SettingsStore(settingRepository); }, inject: [SettingRepository], }, + SettingsApplicationService, + SaveSettingsService, ], - exports: [SETTINGS] + controllers: [SettingsController], + exports: [SETTINGS_PROVIDER], }) export class SettingsModule {} diff --git a/packages/server-nest/src/modules/Settings/Settings.types.ts b/packages/server-nest/src/modules/Settings/Settings.types.ts new file mode 100644 index 000000000..6258fa581 --- /dev/null +++ b/packages/server-nest/src/modules/Settings/Settings.types.ts @@ -0,0 +1,13 @@ + +export interface IOptionDTO { + key: string; + value: string; + group: string; +} + +export interface ISettingsDTO { + options: IOptionDTO[]; +} + + +export const SETTINGS_PROVIDER = 'SETTINGS'; \ No newline at end of file diff --git a/packages/server-nest/src/modules/Settings/SettingsApplication.service.ts b/packages/server-nest/src/modules/Settings/SettingsApplication.service.ts new file mode 100644 index 000000000..578e09c26 --- /dev/null +++ b/packages/server-nest/src/modules/Settings/SettingsApplication.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@nestjs/common'; +import { SaveSettingsService } from './commands/SaveSettings.service'; +import { ISettingsDTO } from './Settings.types'; + +@Injectable() +export class SettingsApplicationService { + constructor(private readonly saveSettingsService: SaveSettingsService) {} + + /** + * Saves the given settings. + * @param {ISettingsDTO} settingsDTO + */ + public async saveSettings(settingsDTO: ISettingsDTO) { + return this.saveSettingsService.saveSettings(settingsDTO); + } +} diff --git a/packages/server-nest/src/modules/Settings/SettingsStore.ts b/packages/server-nest/src/modules/Settings/SettingsStore.ts index d798a5bab..56c0adff5 100644 --- a/packages/server-nest/src/modules/Settings/SettingsStore.ts +++ b/packages/server-nest/src/modules/Settings/SettingsStore.ts @@ -1,6 +1,6 @@ import { EntityRepository } from '@/common/repository/EntityRepository'; -import { MetableDBStore } from '../Metable/MetableStoreDB'; import { SettingsOptions } from '@/constants/metable-options'; +import { MetableDBStore } from '../Metable/MetableStoreDB'; export class SettingsStore extends MetableDBStore { /** @@ -13,4 +13,5 @@ export class SettingsStore extends MetableDBStore { this.setExtraColumns(['group']); this.setRepository(repository); } + } diff --git a/packages/server-nest/src/modules/Settings/commands/SaveSettings.service.ts b/packages/server-nest/src/modules/Settings/commands/SaveSettings.service.ts new file mode 100644 index 000000000..0fd83d769 --- /dev/null +++ b/packages/server-nest/src/modules/Settings/commands/SaveSettings.service.ts @@ -0,0 +1,58 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { pick } from 'lodash'; +import { SettingsStore } from '../SettingsStore'; +import { IOptionDTO, ISettingsDTO, SETTINGS_PROVIDER } from '../Settings.types'; + +@Injectable() +export class SaveSettingsService { + constructor( + @Inject(SETTINGS_PROVIDER) + private readonly settingsStore: SettingsStore, + ) {} + + /** + * Saves the given settings. + * @param {ISettingsDTO} settingsDTO + */ + public async saveSettings(settingsDTO: ISettingsDTO) { + const notDefinedOptions = this.validateNotDefinedSettings( + settingsDTO.options, + ); + const errorReasons: { type: string; code: number; keys: any[] }[] = []; + if (notDefinedOptions.length) { + errorReasons.push({ + type: 'OPTIONS.KEY.NOT.DEFINED', + code: 200, + keys: notDefinedOptions.map((o) => ({ ...pick(o, ['key', 'group']) })), + }); + } + if (errorReasons.length) { + throw new Error(JSON.stringify(errorReasons)); + } + settingsDTO.options.forEach((option: IOptionDTO) => { + this.settingsStore.set({ ...option }); + }); + await this.settingsStore.save(); + } + + /** + * Validates the given options is defined or either not. + * @param {Array} options + * @return {Boolean} + */ + private validateNotDefinedSettings(options) { + const notDefined = []; + + options.forEach((option) => { + const setting = this.settingsStore.config.getMetaConfig( + option.key, + option.group, + ); + + if (!setting) { + notDefined.push(option); + } + }); + return notDefined; + } +} diff --git a/packages/server-nest/src/modules/TransactionsLocking/TransactionsLockingRepository.ts b/packages/server-nest/src/modules/TransactionsLocking/TransactionsLockingRepository.ts index af91a2b2c..d497e82d2 100644 --- a/packages/server-nest/src/modules/TransactionsLocking/TransactionsLockingRepository.ts +++ b/packages/server-nest/src/modules/TransactionsLocking/TransactionsLockingRepository.ts @@ -6,12 +6,12 @@ import { } from './types/TransactionsLocking.types'; import { Inject, Injectable } from '@nestjs/common'; import { SettingsStore } from '../Settings/SettingsStore'; -import { SETTINGS } from '../Settings/Settings.module'; +import { SETTINGS_PROVIDER } from '../Settings/Settings.types'; @Injectable() export class TransactionsLockingRepository { constructor( - @Inject(SETTINGS) private readonly settingsStore: SettingsStore, + @Inject(SETTINGS_PROVIDER) private readonly settingsStore: SettingsStore, ) {} /** diff --git a/packages/server-nest/test/settings.e2e-spec.ts b/packages/server-nest/test/settings.e2e-spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/server-nest/test/transactions-locking.e2e-spec.ts b/packages/server-nest/test/transactions-locking.e2e-spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0ea247aac..fa5655e8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -286,8 +286,8 @@ importers: specifier: ^8.0.0 version: 8.0.0 posthog-node: - specifier: ^4.2.0 - version: 4.2.0 + specifier: ^4.3.2 + version: 4.3.2 pug: specifier: ^3.0.2 version: 3.0.2 @@ -623,8 +623,8 @@ importers: specifier: ^10.3.0 version: 10.9.0 posthog-node: - specifier: ^4.2.0 - version: 4.2.0 + specifier: ^4.3.2 + version: 4.3.2 pug: specifier: ^3.0.2 version: 3.0.2 @@ -28410,8 +28410,8 @@ packages: picocolors: 1.1.1 source-map-js: 1.2.1 - /posthog-node@4.2.0: - resolution: {integrity: sha512-hgyCYMyzMvuF3qWMw6JvS8gT55v7Mtp5wKWcnDrw+nu39D0Tk9BXD7I0LOBp0lGlHEPaXCEVYUtviNKrhMALGA==} + /posthog-node@4.3.2: + resolution: {integrity: sha512-vy8Mt9IEfniUgqQ1rOCQ31CBO1VNqDGd3ZtHlWR9/YfU6RiuK+9pUXPb4h6HTGzQmjL8NFnjd8K8NMXSX8S6MQ==} engines: {node: '>=15.0.0'} dependencies: axios: 1.7.7