diff --git a/build/swagger.yaml b/build/swagger.yaml index 3126b07..f520030 100644 --- a/build/swagger.yaml +++ b/build/swagger.yaml @@ -22,10 +22,6 @@ components: nullable: true SetStorageForKeyRequestBody: properties: - shared: - type: boolean - previousVersion: - type: string value: type: string required: @@ -97,8 +93,6 @@ components: description: Construct a type with a set of properties K of type T WriteLogRequestBody: properties: - params: - $ref: "#/components/schemas/Record_string.unknown_" error: anyOf: - type: string @@ -110,7 +104,7 @@ components: required: - method type: object - SetEnvironmentForKeyRequestBody: + SetEnvironmentVariableForKeyRequestBody: properties: value: $ref: "#/components/schemas/JsonValue" @@ -210,7 +204,27 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/JsonValue" + anyOf: + - properties: + error: {} + success: + type: boolean + version: + type: string + required: + - success + - version + type: object + - properties: + version: {} + success: + type: boolean + error: + type: string + required: + - success + - error + type: object tags: - Storage security: [] @@ -225,6 +239,16 @@ paths: required: true schema: type: string + - in: query + name: shared + required: false + schema: + type: boolean + - in: query + name: previousVersion + required: false + schema: + type: string requestBody: required: true content: @@ -240,7 +264,32 @@ paths: content: application/json: schema: - type: string + anyOf: + - properties: + newCounterValue: {} + message: {} + success: + type: boolean + error: + type: string + required: + - success + - error + type: object + - properties: + error: {} + success: + type: boolean + newCounterValue: + type: number + format: double + message: + type: string + required: + - success + - newCounterValue + - message + type: object tags: - Storage security: [] @@ -313,7 +362,7 @@ paths: content: application/json: schema: - type: string + type: boolean tags: - SecureStorage security: [] @@ -359,6 +408,22 @@ paths: required: true schema: type: string + /secrets: + get: + operationId: getSecretKeys + responses: + "200": + description: OK + content: + application/json: + schema: + items: + type: string + type: array + tags: + - Secret + security: [] + parameters: [] /test/secrets/{name}: put: operationId: setSecretTestRoute @@ -446,15 +511,16 @@ paths: application/json: schema: $ref: "#/components/schemas/WriteLogRequestBody" - /environments/{name}: + /environment-variables/{name}: get: - operationId: getEnvironment + operationId: getEnvironmentVariable responses: "200": description: OK content: application/json: - schema: {} + schema: + $ref: "#/components/schemas/JsonValue" "404": description: "" content: @@ -467,7 +533,7 @@ paths: - reason type: object tags: - - Environment + - EnvironmentVariables security: [] parameters: - in: path @@ -475,6 +541,22 @@ paths: required: true schema: type: string + /environment-variables: + get: + operationId: getEnvironmentVariableKeys + responses: + "200": + description: Ok + content: + application/json: + schema: + items: + type: string + type: array + tags: + - EnvironmentVariables + security: [] + parameters: [] /test/environments/{name}: put: operationId: setEnvironmentTestRoute @@ -495,7 +577,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/SetEnvironmentForKeyRequestBody" + $ref: "#/components/schemas/SetEnvironmentVariableForKeyRequestBody" servers: - url: http://localhost:59999 description: monday-code Local dev server diff --git a/src/domain/environment/environment-test.controller.ts b/src/domain/environment-variables/environment-variables-test.controller.ts similarity index 53% rename from src/domain/environment/environment-test.controller.ts rename to src/domain/environment-variables/environment-variables-test.controller.ts index f50dbee..86ae57a 100644 --- a/src/domain/environment/environment-test.controller.ts +++ b/src/domain/environment-variables/environment-variables-test.controller.ts @@ -2,21 +2,23 @@ import { OperationId, SuccessResponse } from '@tsoa/runtime'; import { ReasonPhrases, StatusCodes } from 'http-status-codes'; import { Body, Path, Put, Route, Tags } from 'tsoa'; -import { EnvironmentService } from './environment.service'; +import { EnvironmentVariablesService } from './environment-variables.service'; -import type { SetEnvironmentForKeyRequestBody } from 'domain/environment/environment.types'; +import type { SetEnvironmentVariableForKeyRequestBody } from 'domain/environment-variables/environment-variables.types'; @Route('test/environments') @Tags('TestRoutes') -export class EnvironmentTestController { +export class EnvironmentVariablesTestController { @Put('{name}') @OperationId('setEnvironmentTestRoute') @SuccessResponse(StatusCodes.NO_CONTENT, ReasonPhrases.NO_CONTENT) public async setEnvironmentForKey( @Path() name: string, - @Body() body: SetEnvironmentForKeyRequestBody + @Body() body: SetEnvironmentVariableForKeyRequestBody ): Promise { const { value } = body; - EnvironmentService.setEnvironmentForKey(name, value); + EnvironmentVariablesService.setEnvironmentVariableForKey(name, value); } } + +// TODO: what is this? needed? diff --git a/src/domain/environment-variables/environment-variables.consts.ts b/src/domain/environment-variables/environment-variables.consts.ts new file mode 100644 index 0000000..e8b5208 --- /dev/null +++ b/src/domain/environment-variables/environment-variables.consts.ts @@ -0,0 +1,3 @@ +import { VOLUME_PATH } from 'shared/config'; + +export const ENVIRONMENT_VARIABLES_FILE = `${VOLUME_PATH}/env.json`; diff --git a/src/domain/environment-variables/environment-variables.controller.ts b/src/domain/environment-variables/environment-variables.controller.ts new file mode 100644 index 0000000..97b793e --- /dev/null +++ b/src/domain/environment-variables/environment-variables.controller.ts @@ -0,0 +1,36 @@ +import { OperationId, Res, SuccessResponse } from '@tsoa/runtime'; +import { ReasonPhrases, StatusCodes } from 'http-status-codes'; +import { Get, Path, Route, Tags } from 'tsoa'; + +import { EnvironmentVariablesService } from './environment-variables.service'; + +import type { TsoaResponse } from '@tsoa/runtime'; +import type { JsonValue } from 'types/general.type'; + +@Route('environment-variables') +@Tags('EnvironmentVariables') +export class EnvironmentVariablesController { + @Get('{name}') + @OperationId('getEnvironmentVariable') + @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) + public async getEnvironmentVariableForKey( + @Path() name: string, + @Res() notFoundResponse: TsoaResponse + ): Promise { + const value = EnvironmentVariablesService.getEnvironmentVariableForKey(name); + if (value === undefined) { + return notFoundResponse(StatusCodes.NOT_FOUND, { reason: 'Environment variable not found' }); + } + + return value; + } + + @Get() + @OperationId('getEnvironmentVariableKeys') + public async getKeys(): Promise { + const keys = EnvironmentVariablesService.getEnvironmentVariableKeys(); + return keys; + } +} + +// FIXME: in the sidecar, re-check env-vars and secrets are working after my fix to the "falsy" check diff --git a/src/domain/environment/environment.schema.ts b/src/domain/environment-variables/environment-variables.schema.ts similarity index 67% rename from src/domain/environment/environment.schema.ts rename to src/domain/environment-variables/environment-variables.schema.ts index 166e58f..415a575 100644 --- a/src/domain/environment/environment.schema.ts +++ b/src/domain/environment-variables/environment-variables.schema.ts @@ -2,13 +2,13 @@ import { z } from 'zod'; import { jsonValueSchema } from 'shared/schemas/general.schema'; -export const getEnvironmentForKeyRequestSchema = { +export const getEnvironmentVariableForKeyRequestSchema = { params: z.object({ key: z.string() }) }; -export const setEnvironmentForKeyRequestSchema = { +export const setEnvironmentVariableForKeyRequestSchema = { params: z.object({ key: z.string() }), diff --git a/src/domain/environment-variables/environment-variables.service.ts b/src/domain/environment-variables/environment-variables.service.ts new file mode 100644 index 0000000..a9d5482 --- /dev/null +++ b/src/domain/environment-variables/environment-variables.service.ts @@ -0,0 +1,36 @@ +import { ENVIRONMENT_VARIABLES_FILE } from 'domain/environment-variables/environment-variables.consts'; +import { initFileIfNotExists, readJsonFile, writeJsonFile } from 'utils/files'; + +import type { JsonValue } from 'types/general.type'; + +export class EnvironmentVariablesService { + private static isInitialized = false; + + private static initialize() { + if (this.isInitialized) { + return; + } + + initFileIfNotExists(ENVIRONMENT_VARIABLES_FILE); + this.isInitialized = true; + } + + static getEnvironmentVariableForKey(key: string) { + this.initialize(); + const environmentFile = readJsonFile(ENVIRONMENT_VARIABLES_FILE); + return environmentFile[key]; + } + + static setEnvironmentVariableForKey(key: string, value: JsonValue) { + this.initialize(); + const environmentFile = readJsonFile(ENVIRONMENT_VARIABLES_FILE); + environmentFile[key] = value; + writeJsonFile(ENVIRONMENT_VARIABLES_FILE, environmentFile); + } + + static getEnvironmentVariableKeys(): Array { + this.initialize(); + const environmentFile = readJsonFile(ENVIRONMENT_VARIABLES_FILE); + return Object.keys(environmentFile); + } +} diff --git a/src/domain/environment/environment.types.ts b/src/domain/environment-variables/environment-variables.types.ts similarity index 57% rename from src/domain/environment/environment.types.ts rename to src/domain/environment-variables/environment-variables.types.ts index 989558d..31aa263 100644 --- a/src/domain/environment/environment.types.ts +++ b/src/domain/environment-variables/environment-variables.types.ts @@ -1,5 +1,5 @@ import type { JsonValue } from 'types/general.type'; -export type SetEnvironmentForKeyRequestBody = { +export type SetEnvironmentVariableForKeyRequestBody = { value: JsonValue; }; diff --git a/src/domain/environment/environment.consts.ts b/src/domain/environment/environment.consts.ts deleted file mode 100644 index 4ed9541..0000000 --- a/src/domain/environment/environment.consts.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { VOLUME_PATH } from 'shared/config'; - -export const ENVIRONMENT_FILE = `${VOLUME_PATH}/env.json`; diff --git a/src/domain/environment/environment.controller.ts b/src/domain/environment/environment.controller.ts deleted file mode 100644 index 49a5b7f..0000000 --- a/src/domain/environment/environment.controller.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { OperationId, Res, SuccessResponse } from '@tsoa/runtime'; -import { ReasonPhrases, StatusCodes } from 'http-status-codes'; -import { Get, Path, Route, Tags } from 'tsoa'; - -import { EnvironmentService } from './environment.service'; - -import type { TsoaResponse } from '@tsoa/runtime'; - -@Route('environments') -@Tags('Environment') -export class EnvironmentController { - @Get('{name}') - @OperationId('getEnvironment') - @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) - public async getEnvironmentForKey( - @Path() name: string, - @Res() notFoundResponse: TsoaResponse<404, { reason: string }> - ): Promise { - const value = EnvironmentService.getEnvironmentForKey(name); - if (!value) { - return notFoundResponse(404, { reason: 'Environment variable not found' }); - } - - return value; - } -} diff --git a/src/domain/environment/environment.service.ts b/src/domain/environment/environment.service.ts deleted file mode 100644 index dcbe799..0000000 --- a/src/domain/environment/environment.service.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SECRETS_FILE } from 'domain/secrets/secrets.consts'; -import { initFileIfNotExists, readJsonFile, writeJsonFile } from 'utils/files'; - -import { ENVIRONMENT_FILE } from './environment.consts'; - -import type { JsonValue } from 'types/general.type'; - -export class EnvironmentService { - private static isInitialized = false; - - private static initialize() { - if (this.isInitialized) { - return; - } - - initFileIfNotExists(SECRETS_FILE); - this.isInitialized = true; - } - - static getEnvironmentForKey(key: string) { - this.initialize(); - const environmentFile = readJsonFile(ENVIRONMENT_FILE); - return environmentFile[key]; - } - - static setEnvironmentForKey(key: string, value: JsonValue) { - this.initialize(); - const environmentFile = readJsonFile(ENVIRONMENT_FILE); - environmentFile[key] = value; - writeJsonFile(ENVIRONMENT_FILE, environmentFile); - } -} diff --git a/src/domain/log/logs.controller.ts b/src/domain/log/logs.controller.ts index 84d87ba..70c93e1 100644 --- a/src/domain/log/logs.controller.ts +++ b/src/domain/log/logs.controller.ts @@ -13,7 +13,7 @@ export class LogsController { @OperationId('writeLog') @SuccessResponse(StatusCodes.NO_CONTENT, ReasonPhrases.NO_CONTENT) public async writeLog(@Body() body: WriteLogRequestBody): Promise { - const { params, message, method, error } = body; - UserLogsService.log(method, message, error, params); + const { message, method, error } = body; + UserLogsService.log(method, message, error); } } diff --git a/src/domain/log/logs.service.ts b/src/domain/log/logs.service.ts index 6d97d3c..84a6575 100644 --- a/src/domain/log/logs.service.ts +++ b/src/domain/log/logs.service.ts @@ -4,7 +4,7 @@ import { Logger } from 'utils/logger'; const logger = new Logger('user-logs'); export class UserLogsService { - static log(method = LogMethods.INFO, message?: string, error?: string | object, params?: object) { - logger[method]({ ...params, ...(error && { error }) }, message); + static log(method = LogMethods.INFO, message?: string, error?: string | object) { + logger[method]({ ...(error && { error }) }, message); } } diff --git a/src/domain/log/logs.types.ts b/src/domain/log/logs.types.ts index 63e2bf0..f61bae8 100644 --- a/src/domain/log/logs.types.ts +++ b/src/domain/log/logs.types.ts @@ -4,5 +4,4 @@ export type WriteLogRequestBody = { method: LogMethods; message?: string; error?: string | Record; - params?: Record; }; diff --git a/src/domain/pub-sub/pub-sub.consts.ts b/src/domain/pub-sub/pub-sub.consts.ts deleted file mode 100644 index f1a3474..0000000 --- a/src/domain/pub-sub/pub-sub.consts.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { TIME_IN_SECONDS } from 'utils/time-enum'; - -export const APP_SERVICE_URL = process.env.PUB_SUB_DEV_APP_SERVICE_URL; -export const APP_SERVICE_PUB_SUB_ENDPOINT = '/mndy-queue'; -export const PUB_SUB_RETRY_INTERVAL_IN_SECONDS = - Number(process.env.PUB_SUB_RETRY_INTERVAL_IN_SECONDS) || TIME_IN_SECONDS.MINUTE * 10; diff --git a/src/domain/queue/queue.consts.ts b/src/domain/queue/queue.consts.ts new file mode 100644 index 0000000..5d8e22e --- /dev/null +++ b/src/domain/queue/queue.consts.ts @@ -0,0 +1,6 @@ +import { TIME_IN_SECONDS } from 'utils/time-enum'; + +export const APP_SERVICE_URL = process.env.QUEUE_DEV_APP_SERVICE_URL; +export const APP_SERVICE_QUEUE_ENDPOINT = '/mndy-queue'; +export const QUEUE_RETRY_INTERVAL_IN_SECONDS = + Number(process.env.QUEUE_RETRY_INTERVAL_IN_SECONDS) || TIME_IN_SECONDS.MINUTE * 10; diff --git a/src/domain/pub-sub/pub-sub.controller.ts b/src/domain/queue/queue.controller.ts similarity index 70% rename from src/domain/pub-sub/pub-sub.controller.ts rename to src/domain/queue/queue.controller.ts index ccf2828..a314667 100644 --- a/src/domain/pub-sub/pub-sub.controller.ts +++ b/src/domain/queue/queue.controller.ts @@ -2,19 +2,19 @@ import { OperationId, Post, SuccessResponse } from '@tsoa/runtime'; import { ReasonPhrases, StatusCodes } from 'http-status-codes'; import { Body, Route, Tags } from 'tsoa'; -import { PubSubService } from './pub-sub.service'; +import { QueueService } from './queue.service'; -import type { QueueRequestBody, ValidateSecretRequestBody } from 'domain/pub-sub/pub-sub.types'; +import type { QueueRequestBody, ValidateSecretRequestBody } from 'domain/queue/queue.types'; @Route('queue') @Tags('Queue') -export class PubSubController { +export class QueueController { @Post() @OperationId('publishMessage') @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) - public queue(@Body() body: QueueRequestBody) { + public publishMessage(@Body() body: QueueRequestBody) { const { message } = body; - const id = PubSubService.publishMessage(message); + const id = QueueService.publishMessage(message); return { id }; } @@ -24,7 +24,7 @@ export class PubSubController { @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) public validateSecret(@Body() body: ValidateSecretRequestBody) { const { secret } = body; - const valid = PubSubService.validateSecret(secret); + const valid = QueueService.validateSecret(secret); return { valid }; } diff --git a/src/domain/pub-sub/pub-sub.schema.ts b/src/domain/queue/queue.schema.ts similarity index 100% rename from src/domain/pub-sub/pub-sub.schema.ts rename to src/domain/queue/queue.schema.ts diff --git a/src/domain/pub-sub/pub-sub.service.ts b/src/domain/queue/queue.service.ts similarity index 91% rename from src/domain/pub-sub/pub-sub.service.ts rename to src/domain/queue/queue.service.ts index 04156de..87a5e38 100644 --- a/src/domain/pub-sub/pub-sub.service.ts +++ b/src/domain/queue/queue.service.ts @@ -5,10 +5,10 @@ import { AsyncTask, SimpleIntervalJob, ToadScheduler } from 'toad-scheduler'; import { v4 as uuidv4 } from 'uuid'; import { - APP_SERVICE_PUB_SUB_ENDPOINT, + APP_SERVICE_QUEUE_ENDPOINT, APP_SERVICE_URL, - PUB_SUB_RETRY_INTERVAL_IN_SECONDS -} from 'domain/pub-sub/pub-sub.consts'; + QUEUE_RETRY_INTERVAL_IN_SECONDS +} from 'domain/queue/queue.consts'; import { BadRequestError } from 'shared/errors'; import { generateBase64Secret } from 'utils/cipher'; import { Logger } from 'utils/logger'; @@ -41,7 +41,7 @@ const createNewTask = (message: string) => { const task = new AsyncTask( taskId, async () => { - const response = await fetch(`${APP_SERVICE_URL}/${APP_SERVICE_PUB_SUB_ENDPOINT}?secret=${taskSecret}`, { + const response = await fetch(`${APP_SERVICE_URL}/${APP_SERVICE_QUEUE_ENDPOINT}?secret=${taskSecret}`, { method: 'POST', body: JSON.stringify({ message }), @@ -90,11 +90,11 @@ const removeJobIdAndSecret = (taskSecret: string) => { jobsStore.delete(taskSecret); }; -export class PubSubService { +export class QueueService { static publishMessage(message: string) { validateAppServiceUrl(); const { taskId, task } = createNewTask(message); - const job = new SimpleIntervalJob({ seconds: PUB_SUB_RETRY_INTERVAL_IN_SECONDS }, task, { + const job = new SimpleIntervalJob({ seconds: QUEUE_RETRY_INTERVAL_IN_SECONDS }, task, { id: taskId, preventOverrun: true }); diff --git a/src/domain/pub-sub/pub-sub.types.ts b/src/domain/queue/queue.types.ts similarity index 100% rename from src/domain/pub-sub/pub-sub.types.ts rename to src/domain/queue/queue.types.ts diff --git a/src/domain/secrets/secrets.controller.ts b/src/domain/secrets/secrets.controller.ts index c28b0be..7557b34 100644 --- a/src/domain/secrets/secrets.controller.ts +++ b/src/domain/secrets/secrets.controller.ts @@ -12,12 +12,29 @@ export class SecretsController { @Get('{name}') @OperationId('getSecret') @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) - public getSecretForKey(@Path() name: string, @Res() notFoundResponse: TsoaResponse<404, { reason: string }>): string { + public getSecretForKey( + @Path() name: string, + @Res() + notFoundResponse: TsoaResponse< + StatusCodes.NOT_FOUND, + { + reason: string; + } + > + ): string { const secret = SecretService.getSecretForKey(name); if (!secret) { - return notFoundResponse(404, { reason: 'Secret not found' }); + return notFoundResponse(StatusCodes.NOT_FOUND, { reason: 'Secret not found' }); } return secret; } + + @Get() + @OperationId('getSecretKeys') + @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) + public async getKeys(): Promise { + const keys = SecretService.getSecretKeys(); + return keys; + } } diff --git a/src/domain/secrets/secrets.service.ts b/src/domain/secrets/secrets.service.ts index 2e71ecd..e8c46ce 100644 --- a/src/domain/secrets/secrets.service.ts +++ b/src/domain/secrets/secrets.service.ts @@ -18,14 +18,19 @@ export class SecretService { static getSecretForKey(key: string): string { this.initialize(); - const environmentFile = readJsonFile(SECRETS_FILE); - return environmentFile[key] as string; + const secretsFile = readJsonFile(SECRETS_FILE); + return secretsFile[key] as string; } static setSecretForKey(key: string, value: JsonValue) { this.initialize(); - const environmentFile = readJsonFile(SECRETS_FILE); - environmentFile[key] = value; - writeJsonFile(SECRETS_FILE, environmentFile); + const secretsFile = readJsonFile(SECRETS_FILE); + secretsFile[key] = value; + writeJsonFile(SECRETS_FILE, secretsFile); + } + + static getSecretKeys() { + const secretsFile = readJsonFile(SECRETS_FILE); + return Object.keys(secretsFile); } } diff --git a/src/domain/secure-storage/secure-storage.controller.ts b/src/domain/secure-storage/secure-storage.controller.ts index 30b72b7..b14bf75 100644 --- a/src/domain/secure-storage/secure-storage.controller.ts +++ b/src/domain/secure-storage/secure-storage.controller.ts @@ -18,7 +18,7 @@ export class SecureStorageController { @SuccessResponse(StatusCodes.OK, ReasonPhrases.OK) public async getSecureValue( @Path() key: string, - @Res() notFoundResponse: TsoaResponse<404, { reason: string }> + @Res() notFoundResponse: TsoaResponse ): Promise<{ value: JsonValue }> { const value = SecureStorageService.getSecureValue(key); @@ -42,9 +42,9 @@ export class SecureStorageController { public async updateSecureValue( @Path() key: string, @Body() body: SetSecureStorageForKeyRequestBody - ): Promise { + ): Promise { const { value } = body; SecureStorageService.setSecureValue(key, value); - return value; + return true; } } diff --git a/src/domain/storage/storage.controller.ts b/src/domain/storage/storage.controller.ts index 19dcd21..3626ce3 100644 --- a/src/domain/storage/storage.controller.ts +++ b/src/domain/storage/storage.controller.ts @@ -18,17 +18,17 @@ export class StorageController { @Path() key: string, @Query() shared: boolean, @Header('x-monday-access-token') accessToken: string, - @Res() notFoundResponse: TsoaResponse<404, { reason: string }>, - @Res() serverError: TsoaResponse<500, { reason?: string }> + @Res() notFoundResponse: TsoaResponse, + @Res() serverError: TsoaResponse ): Promise<{ value: JsonValue; version?: string }> { const storageService = new StorageService(accessToken); const { value, version, success } = await storageService.get(key); if (!success && value === null) { - return notFoundResponse(404, { reason: 'Key not found' }); + return notFoundResponse(StatusCodes.NOT_FOUND, { reason: 'Key not found' }); } if (!success) { - return serverError(500, { reason: 'An error occurred while fetching the key' }); + return serverError(StatusCodes.INTERNAL_SERVER_ERROR, { reason: 'An error occurred while fetching the key' }); } return { value, version }; @@ -48,13 +48,14 @@ export class StorageController { public async updateValue( @Header('x-monday-access-token') accessToken: string, @Path() key: string, - @Body() body: SetStorageForKeyRequestBody - ): Promise { - const { value, previousVersion, shared } = body; + @Body() body: SetStorageForKeyRequestBody, + @Query() shared?: boolean, + @Query() previousVersion?: string + ) { + const { value } = body; const storageService = new StorageService(accessToken); - await storageService.set(key, value, { previousVersion, shared }); - - return value; + const result = await storageService.set(key, value, { previousVersion, shared }); + return result; } @Put('counter/increment') @@ -63,10 +64,10 @@ export class StorageController { public async counterIncrement( @Header('x-monday-access-token') accessToken: string, @Body() body: IncrementStorageForKeyRequestBody - ): Promise { + ) { const { period, incrementBy, renewalDate, kind } = body; const storageService = new StorageService(accessToken); - const value = await storageService.incrementCounter(period, { incrementBy, kind, renewalDate }); - return value?.newCounterValue?.toString(); + const result = await storageService.incrementCounter(period, { incrementBy, kind, renewalDate }); + return result; } } diff --git a/src/domain/storage/storage.types.ts b/src/domain/storage/storage.types.ts index d5f45a8..25b8ab5 100644 --- a/src/domain/storage/storage.types.ts +++ b/src/domain/storage/storage.types.ts @@ -4,7 +4,7 @@ export type SetSecureStorageForKeyRequestBody = { value: string; }; -export type SetStorageForKeyRequestBody = { value: string; previousVersion?: string; shared?: boolean }; +export type SetStorageForKeyRequestBody = { value: string }; export type IncrementStorageForKeyRequestBody = { period: Period; diff --git a/src/routes.ts b/src/routes.ts index 5bb7400..9311cd4 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -11,13 +11,13 @@ import { SecretsController } from './domain/secrets/secrets.controller'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa import { SecretsTestController } from './domain/secrets/secrets-test.controller'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa -import { PubSubController } from './domain/pub-sub/pub-sub.controller'; +import { QueueController } from './domain/queue/queue.controller'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa import { LogsController } from './domain/log/logs.controller'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa -import { EnvironmentController } from './domain/environment/environment.controller'; +import { EnvironmentVariablesController } from './domain/environment-variables/environment-variables.controller'; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa -import { EnvironmentTestController } from './domain/environment/environment-test.controller'; +import { EnvironmentVariablesTestController } from './domain/environment-variables/environment-variables-test.controller'; import type { Request as ExRequest, Response as ExResponse, RequestHandler, Router } from 'express'; @@ -32,7 +32,7 @@ const models: TsoaRoute.Models = { // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "SetStorageForKeyRequestBody": { "dataType": "refAlias", - "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"shared":{"dataType":"boolean"},"previousVersion":{"dataType":"string"},"value":{"dataType":"string","required":true}},"validators":{}}, + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"value":{"dataType":"string","required":true}},"validators":{}}, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "Period": { @@ -77,10 +77,10 @@ const models: TsoaRoute.Models = { // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "WriteLogRequestBody": { "dataType": "refAlias", - "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"params":{"ref":"Record_string.unknown_"},"error":{"dataType":"union","subSchemas":[{"dataType":"string"},{"ref":"Record_string.unknown_"}]},"message":{"dataType":"string"},"method":{"ref":"LogMethods","required":true}},"validators":{}}, + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"error":{"dataType":"union","subSchemas":[{"dataType":"string"},{"ref":"Record_string.unknown_"}]},"message":{"dataType":"string"},"method":{"ref":"LogMethods","required":true}},"validators":{}}, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa - "SetEnvironmentForKeyRequestBody": { + "SetEnvironmentVariableForKeyRequestBody": { "dataType": "refAlias", "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"value":{"ref":"JsonValue","required":true}},"validators":{}}, }, @@ -169,6 +169,8 @@ export function RegisterRoutes(app: Router) { accessToken: {"in":"header","name":"x-monday-access-token","required":true,"dataType":"string"}, key: {"in":"path","name":"key","required":true,"dataType":"string"}, body: {"in":"body","name":"body","required":true,"ref":"SetStorageForKeyRequestBody"}, + shared: {"in":"query","name":"shared","dataType":"boolean"}, + previousVersion: {"in":"query","name":"previousVersion","dataType":"string"}, }; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa @@ -346,6 +348,35 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.get('/secrets', + ...(fetchMiddlewares(SecretsController)), + ...(fetchMiddlewares(SecretsController.prototype.getKeys)), + + function SecretsController_getKeys(request: ExRequest, response: ExResponse, next: any) { + const args: Record = { + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args, request, response }); + + const controller = new SecretsController(); + + templateService.apiHandler({ + methodName: 'getKeys', + controller, + response, + next, + validatedArgs, + successStatus: 200, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.put('/test/secrets/:name', ...(fetchMiddlewares(SecretsTestController)), ...(fetchMiddlewares(SecretsTestController.prototype.setSecretForKey)), @@ -378,10 +409,10 @@ export function RegisterRoutes(app: Router) { }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.post('/queue', - ...(fetchMiddlewares(PubSubController)), - ...(fetchMiddlewares(PubSubController.prototype.queue)), + ...(fetchMiddlewares(QueueController)), + ...(fetchMiddlewares(QueueController.prototype.publishMessage)), - function PubSubController_queue(request: ExRequest, response: ExResponse, next: any) { + function QueueController_publishMessage(request: ExRequest, response: ExResponse, next: any) { const args: Record = { body: {"in":"body","name":"body","required":true,"ref":"QueueRequestBody"}, }; @@ -392,10 +423,10 @@ export function RegisterRoutes(app: Router) { try { validatedArgs = templateService.getValidatedArgs({ args, request, response }); - const controller = new PubSubController(); + const controller = new QueueController(); templateService.apiHandler({ - methodName: 'queue', + methodName: 'publishMessage', controller, response, next, @@ -408,10 +439,10 @@ export function RegisterRoutes(app: Router) { }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.post('/queue/validate-secret', - ...(fetchMiddlewares(PubSubController)), - ...(fetchMiddlewares(PubSubController.prototype.validateSecret)), + ...(fetchMiddlewares(QueueController)), + ...(fetchMiddlewares(QueueController.prototype.validateSecret)), - function PubSubController_validateSecret(request: ExRequest, response: ExResponse, next: any) { + function QueueController_validateSecret(request: ExRequest, response: ExResponse, next: any) { const args: Record = { body: {"in":"body","name":"body","required":true,"ref":"ValidateSecretRequestBody"}, }; @@ -422,7 +453,7 @@ export function RegisterRoutes(app: Router) { try { validatedArgs = templateService.getValidatedArgs({ args, request, response }); - const controller = new PubSubController(); + const controller = new QueueController(); templateService.apiHandler({ methodName: 'validateSecret', @@ -467,11 +498,11 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa - app.get('/environments/:name', - ...(fetchMiddlewares(EnvironmentController)), - ...(fetchMiddlewares(EnvironmentController.prototype.getEnvironmentForKey)), + app.get('/environment-variables/:name', + ...(fetchMiddlewares(EnvironmentVariablesController)), + ...(fetchMiddlewares(EnvironmentVariablesController.prototype.getEnvironmentVariableForKey)), - function EnvironmentController_getEnvironmentForKey(request: ExRequest, response: ExResponse, next: any) { + function EnvironmentVariablesController_getEnvironmentVariableForKey(request: ExRequest, response: ExResponse, next: any) { const args: Record = { name: {"in":"path","name":"name","required":true,"dataType":"string"}, notFoundResponse: {"in":"res","name":"404","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"reason":{"dataType":"string","required":true}}}, @@ -483,10 +514,10 @@ export function RegisterRoutes(app: Router) { try { validatedArgs = templateService.getValidatedArgs({ args, request, response }); - const controller = new EnvironmentController(); + const controller = new EnvironmentVariablesController(); templateService.apiHandler({ - methodName: 'getEnvironmentForKey', + methodName: 'getEnvironmentVariableForKey', controller, response, next, @@ -498,14 +529,43 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.get('/environment-variables', + ...(fetchMiddlewares(EnvironmentVariablesController)), + ...(fetchMiddlewares(EnvironmentVariablesController.prototype.getKeys)), + + function EnvironmentVariablesController_getKeys(request: ExRequest, response: ExResponse, next: any) { + const args: Record = { + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args, request, response }); + + const controller = new EnvironmentVariablesController(); + + templateService.apiHandler({ + methodName: 'getKeys', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.put('/test/environments/:name', - ...(fetchMiddlewares(EnvironmentTestController)), - ...(fetchMiddlewares(EnvironmentTestController.prototype.setEnvironmentForKey)), + ...(fetchMiddlewares(EnvironmentVariablesTestController)), + ...(fetchMiddlewares(EnvironmentVariablesTestController.prototype.setEnvironmentForKey)), - function EnvironmentTestController_setEnvironmentForKey(request: ExRequest, response: ExResponse, next: any) { + function EnvironmentVariablesTestController_setEnvironmentForKey(request: ExRequest, response: ExResponse, next: any) { const args: Record = { name: {"in":"path","name":"name","required":true,"dataType":"string"}, - body: {"in":"body","name":"body","required":true,"ref":"SetEnvironmentForKeyRequestBody"}, + body: {"in":"body","name":"body","required":true,"ref":"SetEnvironmentVariableForKeyRequestBody"}, }; // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa @@ -514,7 +574,7 @@ export function RegisterRoutes(app: Router) { try { validatedArgs = templateService.getValidatedArgs({ args, request, response }); - const controller = new EnvironmentTestController(); + const controller = new EnvironmentVariablesTestController(); templateService.apiHandler({ methodName: 'setEnvironmentForKey', diff --git a/src/shared/middlewares/schema-validation.middleware.ts b/src/shared/middlewares/schema-validation.middleware.ts index 99ee3f0..4f5b7c2 100644 --- a/src/shared/middlewares/schema-validation.middleware.ts +++ b/src/shared/middlewares/schema-validation.middleware.ts @@ -1,3 +1,5 @@ +import { StatusCodes } from 'http-status-codes'; + import { Logger } from 'utils/logger'; import type { RequestHandler } from 'express'; @@ -62,7 +64,7 @@ export const validateZodSchema: { if (!hasDiskWriteAccess()) { throw new InternalServerError('Missing write permissions'); @@ -33,7 +35,7 @@ export const readJsonFile = (fileName: string) => { const data = readFileSync(fileName, 'utf-8'); if (isDefined(data)) { - const parsedData: Record = JSON.parse(data); + const parsedData: Record = JSON.parse(data); return parsedData; }