From 3ca38c3e80a955037bdca26f88e8fa08e43795f9 Mon Sep 17 00:00:00 2001 From: Eduard Dyckman Date: Thu, 2 May 2024 14:09:04 +0300 Subject: [PATCH] fix: validate database name passed to cs command (#212) Inspired by https://github.com/neondatabase/create-branch-action/issues/50 --- .../databases/GET.json | 6 +++- .../branches/br-sunny-branch-123456/GET.json | 2 +- .../br-sunny-branch-123456/databases/GET.json | 3 +- snapshots/commands/branches.test.snap | 4 +-- snapshots/commands/databases.test.snap | 2 ++ snapshots/commands/set_context.test.snap | 2 +- src/commands/connection_string.test.ts | 20 ++++++++++- src/commands/connection_string.ts | 36 +++++++++++-------- 8 files changed, 53 insertions(+), 22 deletions(-) diff --git a/mocks/main/projects/test/branches/br-cloudy-branch-12345678/databases/GET.json b/mocks/main/projects/test/branches/br-cloudy-branch-12345678/databases/GET.json index da3b05e..75f2d79 100644 --- a/mocks/main/projects/test/branches/br-cloudy-branch-12345678/databases/GET.json +++ b/mocks/main/projects/test/branches/br-cloudy-branch-12345678/databases/GET.json @@ -1,6 +1,10 @@ { "databases": [ { "name": "db1", "owner_name": "user1" }, - { "name": "db2", "owner_name": "user2" } + { "name": "db2", "owner_name": "user2" }, + { + "name": "test_db", + "owner_name": "test_user" + } ] } diff --git a/mocks/main/projects/test/branches/br-sunny-branch-123456/GET.json b/mocks/main/projects/test/branches/br-sunny-branch-123456/GET.json index 34731ab..0d72f9b 100644 --- a/mocks/main/projects/test/branches/br-sunny-branch-123456/GET.json +++ b/mocks/main/projects/test/branches/br-sunny-branch-123456/GET.json @@ -1,6 +1,6 @@ { "branch": { - "name": "test-branch-sunny", + "name": "test_branch", "id": "br-sunny-branch-123456", "primary": true, "parent_id": "br-parent-branch-123456", diff --git a/mocks/main/projects/test/branches/br-sunny-branch-123456/databases/GET.json b/mocks/main/projects/test/branches/br-sunny-branch-123456/databases/GET.json index da3b05e..e120a6f 100644 --- a/mocks/main/projects/test/branches/br-sunny-branch-123456/databases/GET.json +++ b/mocks/main/projects/test/branches/br-sunny-branch-123456/databases/GET.json @@ -1,6 +1,7 @@ { "databases": [ { "name": "db1", "owner_name": "user1" }, - { "name": "db2", "owner_name": "user2" } + { "name": "db2", "owner_name": "user2" }, + { "name": "test_db", "owner_name": "test_user" } ] } diff --git a/snapshots/commands/branches.test.snap b/snapshots/commands/branches.test.snap index 7a970cb..e1c21e5 100644 --- a/snapshots/commands/branches.test.snap +++ b/snapshots/commands/branches.test.snap @@ -116,7 +116,7 @@ created_at: 2021-01-01T00:00:00.000Z `; exports[`branches get by id test 1`] = ` -"name: test-branch-sunny +"name: test_branch id: br-sunny-branch-123456 primary: true parent_id: br-parent-branch-123456 @@ -135,7 +135,7 @@ updated_at: 2019-01-01T00:00:00Z `; exports[`branches get by name test 1`] = ` -"name: test-branch-sunny +"name: test_branch id: br-sunny-branch-123456 primary: true parent_id: br-parent-branch-123456 diff --git a/snapshots/commands/databases.test.snap b/snapshots/commands/databases.test.snap index d6e8eac..18e908c 100644 --- a/snapshots/commands/databases.test.snap +++ b/snapshots/commands/databases.test.snap @@ -16,5 +16,7 @@ exports[`databases list test 1`] = ` owner_name: user1 - name: db2 owner_name: user2 +- name: test_db + owner_name: test_user " `; diff --git a/snapshots/commands/set_context.test.snap b/snapshots/commands/set_context.test.snap index 1c6cfab..690a928 100644 --- a/snapshots/commands/set_context.test.snap +++ b/snapshots/commands/set_context.test.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`set_context should set the context get branch id overrides context set branch test 1`] = ` -"name: test-branch-sunny +"name: test_branch id: br-sunny-branch-123456 primary: true parent_id: br-parent-branch-123456 diff --git a/src/commands/connection_string.test.ts b/src/commands/connection_string.test.ts index 7a34295..360d6a3 100644 --- a/src/commands/connection_string.test.ts +++ b/src/commands/connection_string.test.ts @@ -1,4 +1,4 @@ -import { describe } from '@jest/globals'; +import { describe, expect } from '@jest/globals'; import { testCliCommand } from '../test_utils/test_cli_command'; describe('connection_string', () => { @@ -247,4 +247,22 @@ describe('connection_string', () => { snapshot: true, }, }); + + testCliCommand({ + name: 'connection_string fails for non-existing database', + args: [ + 'connection-string', + 'test_branch', + '--project-id', + 'test', + '--database-name', + 'non_existing_db', + '--role-name', + 'test_role', + ], + expected: { + code: 1, + stderr: expect.stringMatching(/Database not found/), + }, + }); }); diff --git a/src/commands/connection_string.ts b/src/commands/connection_string.ts index 3d76bb7..1551d8c 100644 --- a/src/commands/connection_string.ts +++ b/src/commands/connection_string.ts @@ -131,23 +131,29 @@ export const handler = async ( ); })); + const { + data: { databases: branchDatabases }, + } = await props.apiClient.listProjectBranchDatabases(projectId, branchId); + const database = props.databaseName || - (await props.apiClient - .listProjectBranchDatabases(projectId, branchId) - .then(({ data }) => { - if (data.databases.length === 0) { - throw new Error(`No databases found for the branch: ${branchId}`); - } - if (data.databases.length === 1) { - return data.databases[0].name; - } - throw new Error( - `Multiple databases found for the branch, please provide one with the --database-name option: ${data.databases - .map((d) => d.name) - .join(', ')}`, - ); - })); + (() => { + if (branchDatabases.length === 0) { + throw new Error(`No databases found for the branch: ${branchId}`); + } + if (branchDatabases.length === 1) { + return branchDatabases[0].name; + } + throw new Error( + `Multiple databases found for the branch, please provide one with the --database-name option: ${branchDatabases + .map((d) => d.name) + .join(', ')}`, + ); + })(); + + if (!branchDatabases.find((d) => d.name === database)) { + throw new Error(`Database not found: ${database}`); + } const { data: { password },