From ceca3d617c95ab104fb2ea93fc6961dbd9bffac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danil=20Shaymurzin=20=E2=9A=A1=EF=B8=8F?= Date: Tue, 13 Feb 2024 01:05:07 +0500 Subject: [PATCH] fix(server): the provided password must use unique value (#1506) --- src/shadowbox/model/errors.ts | 8 ++++++++ src/shadowbox/server/server_access_key.spec.ts | 10 ++++++++++ src/shadowbox/server/server_access_key.ts | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/src/shadowbox/model/errors.ts b/src/shadowbox/model/errors.ts index a6445ba10..a71646a91 100644 --- a/src/shadowbox/model/errors.ts +++ b/src/shadowbox/model/errors.ts @@ -52,3 +52,11 @@ export class AccessKeyConflict extends OutlineError { super(`Access key "${accessKeyId}" conflict`); } } + +export class PasswordConflict extends OutlineError { + constructor(accessKeyId?: AccessKeyId) { + super( + `Access key ${accessKeyId} has the same password. Please specify a unique password for each access key` + ); + } +} diff --git a/src/shadowbox/server/server_access_key.spec.ts b/src/shadowbox/server/server_access_key.spec.ts index 8f6e98df4..d752aec43 100644 --- a/src/shadowbox/server/server_access_key.spec.ts +++ b/src/shadowbox/server/server_access_key.spec.ts @@ -81,6 +81,16 @@ describe('ServerAccessKeyRepository', () => { done(); }); + it('createNewAccessKey throws on creating keys with existing passwords', async (done) => { + const repo = new RepoBuilder().build(); + await repo.createNewAccessKey({password: 'P@$$w0rd'}); + await expectAsyncThrow( + repo.createNewAccessKey.bind(repo, {password: 'P@$$w0rd'}), + errors.PasswordConflict + ); + done(); + }); + it('New access keys have the correct default encryption method', (done) => { const repo = new RepoBuilder().build(); repo.createNewAccessKey().then((accessKey) => { diff --git a/src/shadowbox/server/server_access_key.ts b/src/shadowbox/server/server_access_key.ts index ad85ee337..3f513948e 100644 --- a/src/shadowbox/server/server_access_key.ts +++ b/src/shadowbox/server/server_access_key.ts @@ -204,6 +204,15 @@ export class ServerAccessKeyRepository implements AccessKeyRepository { } else { id = this.generateId(); } + + const isPasswordConflict = this.listAccessKeys().some( + (accessKey) => accessKey.proxyParams.password == params?.password + ); + + if (isPasswordConflict) { + throw new errors.PasswordConflict(id); + } + const metricsId = uuidv4(); const password = params?.password ?? generatePassword();