diff --git a/.github/workflows/build-app-pro-beta.yaml b/.github/workflows/build-app-pro-beta.yaml index 5285c9be9..0379a00fc 100644 --- a/.github/workflows/build-app-pro-beta.yaml +++ b/.github/workflows/build-app-pro-beta.yaml @@ -39,6 +39,7 @@ jobs: repository: dbgate/dbgate-pro token: '${{ secrets.GH_TOKEN }}' path: dbgate-pro + ref: a770b7e7a4d0ced5f1ade7cba4ba516220765648 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-app-pro.yaml b/.github/workflows/build-app-pro.yaml index 7529f45b0..bf7615383 100644 --- a/.github/workflows/build-app-pro.yaml +++ b/.github/workflows/build-app-pro.yaml @@ -39,6 +39,7 @@ jobs: repository: dbgate/dbgate-pro token: '${{ secrets.GH_TOKEN }}' path: dbgate-pro + ref: a770b7e7a4d0ced5f1ade7cba4ba516220765648 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-aws-pro.yaml b/.github/workflows/build-aws-pro.yaml index 2d2e41fdb..cecc55926 100644 --- a/.github/workflows/build-aws-pro.yaml +++ b/.github/workflows/build-aws-pro.yaml @@ -36,6 +36,7 @@ jobs: repository: dbgate/dbgate-pro token: '${{ secrets.GH_TOKEN }}' path: dbgate-pro + ref: a770b7e7a4d0ced5f1ade7cba4ba516220765648 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-docker-pro.yaml b/.github/workflows/build-docker-pro.yaml index a11f32f4e..b650bde46 100644 --- a/.github/workflows/build-docker-pro.yaml +++ b/.github/workflows/build-docker-pro.yaml @@ -44,6 +44,7 @@ jobs: repository: dbgate/dbgate-pro token: '${{ secrets.GH_TOKEN }}' path: dbgate-pro + ref: a770b7e7a4d0ced5f1ade7cba4ba516220765648 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-npm-pro.yaml b/.github/workflows/build-npm-pro.yaml index 53b982a59..cb378c1d1 100644 --- a/.github/workflows/build-npm-pro.yaml +++ b/.github/workflows/build-npm-pro.yaml @@ -32,6 +32,7 @@ jobs: repository: dbgate/dbgate-pro token: '${{ secrets.GH_TOKEN }}' path: dbgate-pro + ref: a770b7e7a4d0ced5f1ade7cba4ba516220765648 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-test-containers.yaml b/.github/workflows/build-test-containers.yaml index 19620ff0a..af2c5bc81 100644 --- a/.github/workflows/build-test-containers.yaml +++ b/.github/workflows/build-test-containers.yaml @@ -8,6 +8,7 @@ name: Build test containers - master - develop - feature/** + - hotfix/** paths: - e2e-tests/containers/** jobs: diff --git a/.github/workflows/e2e-pro.yaml b/.github/workflows/e2e-pro.yaml index a26365e00..0edb18b8b 100644 --- a/.github/workflows/e2e-pro.yaml +++ b/.github/workflows/e2e-pro.yaml @@ -8,6 +8,7 @@ name: Cypress tests with screenshots PREMIUM - master - develop - feature/** + - hotfix/** jobs: e2e-tests: runs-on: ubuntu-latest @@ -25,6 +26,7 @@ jobs: repository: dbgate/dbgate-pro token: '${{ secrets.GH_TOKEN }}' path: dbgate-pro + ref: a770b7e7a4d0ced5f1ade7cba4ba516220765648 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro @@ -84,7 +86,7 @@ jobs: mysql-ssh-login: image: 'ghcr.io/dbgate/mysql-ssh-login:latest' ports: - - '16006:22' + - '16012:22' mysql-ssh-keyfile: image: 'ghcr.io/dbgate/mysql-ssh-keyfile:latest' ports: diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index e52bbaa59..5cc63f1da 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -8,6 +8,7 @@ name: Integration and unit tests - master - develop - feature/** + - hotfix/** jobs: all-tests: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 4855fb782..6d428a673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ Builds: - linux - application for linux - win - application for Windows +### 6.1.6 +- FIXED: Hotfix build process for premium edition + +### 6.1.5 +- FIXED: Serious security hotfix (for Docker and NPM, when using LOGIN and PASSWORD environment variables or LOGIN_PASSWORD_xxx) +- no changes for desktop app and for Team premium edition, when using storage DB + ### 6.1.4 - CHANGED: Show Data/Structure button in one place #1015 - ADDED: Data view coloring (every second row) #1014 diff --git a/e2e-tests/containers/dex/dex-config.yaml b/e2e-tests/containers/dex/dex-config.yaml index 190200844..f93a58323 100644 --- a/e2e-tests/containers/dex/dex-config.yaml +++ b/e2e-tests/containers/dex/dex-config.yaml @@ -17,6 +17,11 @@ staticClients: enablePasswordDB: true staticPasswords: - email: "test@example.com" + emailVerified: true hash: "$2y$10$JcmlXnV1y7.egUdKwYNbseOnqYVIGc323gtvvHh4ZuSPZB30veYZy" username: "test" userID: "1234" + allowedScopes: + - openid + - email + - profile diff --git a/e2e-tests/cypress/e2e/add-connection.cy.js b/e2e-tests/cypress/e2e/add-connection.cy.js index 69fb1b96b..3b71770fb 100644 --- a/e2e-tests/cypress/e2e/add-connection.cy.js +++ b/e2e-tests/cypress/e2e/add-connection.cy.js @@ -47,7 +47,7 @@ describe('Add connection', () => { cy.get('[data-testid=ConnectionSshTunnelFields_useSshTunnel]').check(); cy.get('[data-testid=ConnectionSshTunnelFields_sshLogin]').clear().type('root'); cy.get('[data-testid=ConnectionSshTunnelFields_sshPassword]').clear().type('root'); - cy.get('[data-testid=ConnectionSshTunnelFields_sshPort]').clear().type('16006'); + cy.get('[data-testid=ConnectionSshTunnelFields_sshPort]').clear().type('16012'); cy.get('[data-testid=ConnectionTab_buttonSave]').click(); cy.get('[data-testid=ConnectionTab_buttonConnect]').click(); cy.contains('performance_schema'); diff --git a/e2e-tests/cypress/e2e/team.cy.js b/e2e-tests/cypress/e2e/team.cy.js index f60d7c597..a1f03a2d4 100644 --- a/e2e-tests/cypress/e2e/team.cy.js +++ b/e2e-tests/cypress/e2e/team.cy.js @@ -4,7 +4,7 @@ beforeEach(() => { }); describe('Team edition tests', () => { - it('Data archive editor - macros', () => { + it('Team edition screens', () => { cy.testid('LoginPage_linkAdmin').click(); cy.testid('LoginPage_password').type('adminpwd'); cy.testid('LoginPage_submitLogin').click(); @@ -27,4 +27,56 @@ describe('Team edition tests', () => { cy.contains('OAuth 2.0').click(); cy.themeshot('authadmin'); }); + + it('OAuth authentication', () => { + cy.testid('LoginPage_linkAdmin').click(); + cy.testid('LoginPage_password').type('adminpwd'); + cy.testid('LoginPage_submitLogin').click(); + cy.testid('AdminMenuWidget_itemAuthentication').click(); + // cy.testid('AdminAuthForm_disableButton_local').click(); + // cy.testid('AdminAuthForm_disableButton_none').click(); + + // fill OAuth + cy.contains('Add authentication').click(); + cy.contains('OAuth 2.0').click(); + cy.testid('AdminAuthForm_oauthAuth_oauth').type('http://localhost:16009/dex/auth'); + cy.testid('AdminAuthForm_oauthToken_oauth').type('http://localhost:16009/dex/token'); + cy.testid('AdminAuthForm_oauthScope_oauth').type('openid email profile'); + cy.testid('AdminAuthForm_oauthClient_oauth').type('my-app'); + cy.testid('AdminAuthForm_oauthClientSecret_oauth').type('my-secret'); + cy.testid('AdminAuthForm_oauthLoginField_oauth').type('name'); + cy.testid('AdminAuthForm_oauthSaveNotDefinedLogins_oauth').click(); + cy.testid('AdminAuthForm_oauthEmailField_oauth').type('email'); + cy.testid('AdminAuthTab_saveButton').click(); + + cy.testid('WidgetIconPanel_menu').click(); + cy.contains('File').click(); + cy.contains('Logout').click(); + cy.testid('LoginPage_linkRegularUser').click(); + + // login two times + for (let index of [1, 2]) { + // login as OAuth + cy.testid('LoginPage_loginButton_OAuth 2.0').click(); + + // login on DEX + cy.get('#login').clear().type('test@example.com'); + cy.get('#password').clear().type('test'); + cy.get('#submit-login').click(); + + // logout + cy.testid('WidgetIconPanel_menu').click(); + cy.contains('File').click(); + cy.contains('Logout').click(); + cy.testid('NotLoggedPage_loginButton').click(); + } + + // Logout and login again as admin + cy.testid('LoginPage_linkAdmin').click(); + cy.testid('LoginPage_password').type('adminpwd'); + cy.testid('LoginPage_submitLogin').click(); + cy.testid('AdminMenuWidget_itemUsers').click(); + cy.contains('test@example.com'); + cy.contains('Rows: 1'); + }); }); diff --git a/e2e-tests/docker-compose.yaml b/e2e-tests/docker-compose.yaml index 8bc848bc4..63b4c2ee1 100644 --- a/e2e-tests/docker-compose.yaml +++ b/e2e-tests/docker-compose.yaml @@ -22,7 +22,7 @@ services: restart: always ports: - 16005:3306 - - "16006:22" + - "16012:22" mysql-ssh-keyfile: build: containers/mysql-ssh-keyfile diff --git a/package.json b/package.json index b70137b3d..4594262e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "6.1.5-beta.3", + "version": "6.1.7-premium-beta.1", "name": "dbgate-all", "workspaces": [ "packages/*", @@ -23,6 +23,7 @@ "start:api:storage": "yarn workspace dbgate-api start:storage | pino-pretty", "start:api:storage:built": "yarn workspace dbgate-api start:storage:built | pino-pretty", "start:api:azure": "yarn workspace dbgate-api start:azure | pino-pretty", + "start:api:e2e:team": "yarn workspace dbgate-api start:e2e:team | pino-pretty", "sync:pro": "cd sync && yarn start", "start:web": "yarn workspace dbgate-web dev", "start:sqltree": "yarn workspace dbgate-sqltree start", diff --git a/packages/api/package.json b/packages/api/package.json index 8a4523b2f..0e1399f98 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -75,6 +75,7 @@ "start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api", "start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api", "start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api", + "start:e2e:team": "cross-env DEVWEB=1 DEVMODE=1 env-cmd -f ../../e2e-tests/env/team/.env node src/index.js --listen-api", "ts": "tsc", "build": "webpack", "build:doc": "jsdoc2md --template doctpl.hbs ./src/shell/* > ../../../dbgate.github.io/_docs/apidoc.md" diff --git a/packages/api/src/auth/authProvider.js b/packages/api/src/auth/authProvider.js index c13628ce8..00fa04d81 100644 --- a/packages/api/src/auth/authProvider.js +++ b/packages/api/src/auth/authProvider.js @@ -218,7 +218,7 @@ class LoginsProvider extends AuthProviderBase { }; } - if (password == process.env[`LOGIN_PASSWORD_${login}`]) { + if (password && password == process.env[`LOGIN_PASSWORD_${login}`]) { return { accessToken: jwt.sign( { diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index 0de25bb06..fd51b5b32 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -401,6 +401,10 @@ module.exports = { structure_meta: true, async structure({ conid, database, modelTransFile = null }, req) { + if (!conid || !database) { + return {}; + } + testConnectionPermission(conid, req); if (conid == '__model') { const model = await importDbModel(database); diff --git a/packages/tools/src/driverBase.ts b/packages/tools/src/driverBase.ts index 585822c3c..7f1cbe6e2 100644 --- a/packages/tools/src/driverBase.ts +++ b/packages/tools/src/driverBase.ts @@ -63,6 +63,12 @@ export function formatQueryWithoutParams(driver: EngineDriver, sql: string) { return dmp.s; } +export async function runQueryFmt(driver, conn, query, ...args) { + const dmp = driver.createDumper(); + dmp.put(query, ...args); + await driver.query(conn, dmp.s); +} + export const driverBase = { analyserClass: null, dumperClass: SqlDumper, diff --git a/packages/web/src/NotLoggedPage.svelte b/packages/web/src/NotLoggedPage.svelte index b1783226b..6bf542f1a 100644 --- a/packages/web/src/NotLoggedPage.svelte +++ b/packages/web/src/NotLoggedPage.svelte @@ -30,8 +30,8 @@ {/if}
diff --git a/packages/web/src/appobj/ArchiveFolderAppObject.svelte b/packages/web/src/appobj/ArchiveFolderAppObject.svelte index 27ee13d42..dbd0ede98 100644 --- a/packages/web/src/appobj/ArchiveFolderAppObject.svelte +++ b/packages/web/src/appobj/ArchiveFolderAppObject.svelte @@ -97,6 +97,10 @@ await dbgateApi.deployDb(${JSON.stringify( title: 'Compare', icon: 'img compare', tabComponent: 'CompareModelTab', + props: { + conid: $currentDatabase?.connection?._id, + database: $currentDatabase?.name, + } }, { editor: { diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte index dec53e73a..277f3d2a3 100644 --- a/packages/web/src/appobj/DatabaseAppObject.svelte +++ b/packages/web/src/appobj/DatabaseAppObject.svelte @@ -196,13 +196,17 @@ title: 'Compare', icon: 'img compare', tabComponent: 'CompareModelTab', + props: { + conid: $currentDatabase?.connection?._id, + database: $currentDatabase?.name, + }, }, { editor: { - sourceConid: _.get($currentDatabase, 'connection._id'), - sourceDatabase: _.get($currentDatabase, 'name'), - targetConid: _.get(connection, '_id'), - targetDatabase: name, + sourceConid: connection?._id, + sourceDatabase: name, + targetConid: $currentDatabase?.connection?._id, + targetDatabase: $currentDatabase?.name, }, } ); diff --git a/packages/web/src/buttons/ToolStripButton.svelte b/packages/web/src/buttons/ToolStripButton.svelte index 07b302207..327abea16 100644 --- a/packages/web/src/buttons/ToolStripButton.svelte +++ b/packages/web/src/buttons/ToolStripButton.svelte @@ -16,7 +16,7 @@