diff --git a/packages/api/src/auth/authCommon.js b/packages/api/src/auth/authCommon.js index 1ebeeafdc..824b9baa8 100644 --- a/packages/api/src/auth/authCommon.js +++ b/packages/api/src/auth/authCommon.js @@ -2,10 +2,15 @@ const crypto = require('crypto'); const tokenSecret = crypto.randomUUID(); -export function getTokenLifetime() { +function getTokenLifetime() { return process.env.TOKEN_LIFETIME || '1d'; } -export function getTokenSecret() { +function getTokenSecret() { return tokenSecret; } + +module.exports = { + getTokenLifetime, + getTokenSecret, +}; diff --git a/packages/api/src/auth/authProvider.js b/packages/api/src/auth/authProvider.js index 81eccb9e7..706a5a92e 100644 --- a/packages/api/src/auth/authProvider.js +++ b/packages/api/src/auth/authProvider.js @@ -61,10 +61,19 @@ class AuthProviderBase { return {}; } - getCurrentLogin(req) {} + getCurrentLogin(req) { + const { user } = (req && req.auth) || {}; + return user; + } getCurrentPermissions(req) { - return process.env.PERMISSIONS; + const login = this.getCurrentLogin(req); + const permissions = process.env[`LOGIN_PERMISSIONS_${login}`]; + return permissions || process.env.PERMISSIONS; + } + + isLoginForm() { + return false; } } @@ -123,6 +132,11 @@ class OAuthProvider extends AuthProviderBase { return { error: 'Token not found' }; } + + getCurrentLogin(req) { + const { login } = (req && req.user) || {}; + return login; + } } class ADProvider extends AuthProviderBase { @@ -156,6 +170,10 @@ class ADProvider extends AuthProviderBase { shouldAuthorizeApi() { return true; } + + isLoginForm() { + return true; + } } class LoginsProvider extends AuthProviderBase { @@ -183,9 +201,21 @@ class LoginsProvider extends AuthProviderBase { shouldAuthorizeApi() { return !process.env.BASIC_AUTH; } + + getCurrentPermissions(req) { + const logins = getEnvLogins(); + const loginName = + req && req.user && req.user.login ? req.user.login : req && req.auth && req.auth.user ? req.auth.user : null; + const login = logins && loginName ? logins.find(x => x.login == loginName) : null; + return login ? login.permissions : process.env.PERMISSIONS; + } + + isLoginForm() { + return !process.env.BASIC_AUTH; + } } -export function detectEnvAuthProvider() { +function detectEnvAuthProvider() { if (process.env.AUTH_PROVIDER) { return process.env.AUTH_PROVIDER; } @@ -201,7 +231,7 @@ export function detectEnvAuthProvider() { return 'none'; } -export function createAuthProvider() { +function createAuthProvider() { const authProvider = detectEnvAuthProvider(); switch (authProvider) { case 'oauth': @@ -214,3 +244,8 @@ export function createAuthProvider() { return new AuthProviderBase(); } } + +module.exports = { + detectEnvAuthProvider, + createAuthProvider, +}; diff --git a/packages/api/src/controllers/auth.js b/packages/api/src/controllers/auth.js index aa4df5d74..2b6389216 100644 --- a/packages/api/src/controllers/auth.js +++ b/packages/api/src/controllers/auth.js @@ -1,7 +1,6 @@ const axios = require('axios'); const jwt = require('jsonwebtoken'); const getExpressPath = require('../utility/getExpressPath'); -const { getLogins } = require('../utility/hasPermission'); const { getLogger } = require('dbgate-tools'); const AD = require('activedirectory2').promiseWrapper; const crypto = require('crypto'); diff --git a/packages/api/src/controllers/config.js b/packages/api/src/controllers/config.js index 9960b08bd..6fcb55eb6 100644 --- a/packages/api/src/controllers/config.js +++ b/packages/api/src/controllers/config.js @@ -3,7 +3,7 @@ const os = require('os'); const path = require('path'); const axios = require('axios'); const { datadir, getLogsFilePath } = require('../utility/directories'); -const { hasPermission, getLogins } = require('../utility/hasPermission'); +const { hasPermission } = require('../utility/hasPermission'); const socket = require('../utility/socket'); const _ = require('lodash'); const AsyncLock = require('async-lock'); @@ -11,6 +11,7 @@ const AsyncLock = require('async-lock'); const currentVersion = require('../currentVersion'); const platformInfo = require('../utility/platformInfo'); const connections = require('../controllers/connections'); +const { createAuthProvider } = require('../auth/authProvider'); const lock = new AsyncLock(); @@ -27,11 +28,10 @@ module.exports = { get_meta: true, async get(_params, req) { - const logins = getLogins(); - const loginName = - req && req.user && req.user.login ? req.user.login : req && req.auth && req.auth.user ? req.auth.user : null; - const login = logins && loginName ? logins.find(x => x.login == loginName) : null; - const permissions = login ? login.permissions : process.env.PERMISSIONS; + const authProvider = createAuthProvider(); + const login = authProvider.getCurrentLogin(req); + const permissions = authProvider.getCurrentPermissions(req); + const isLoginForm = authProvider.isLoginForm(); return { runAsPortal: !!connections.portalConnections, @@ -47,7 +47,7 @@ module.exports = { oauthClient: process.env.OAUTH_CLIENT_ID, oauthScope: process.env.OAUTH_SCOPE, oauthLogout: process.env.OAUTH_LOGOUT, - isLoginForm: !!process.env.AD_URL || (!!logins && !process.env.BASIC_AUTH), + isLoginForm, storageDatabase: process.env.STORAGE_DATABASE, logsFilePath: getLogsFilePath(), connectionsFilePath: path.join(datadir(), 'connections.jsonl'), diff --git a/packages/api/src/main.js b/packages/api/src/main.js index 0c295b71a..a95f0d945 100644 --- a/packages/api/src/main.js +++ b/packages/api/src/main.js @@ -32,7 +32,6 @@ const onFinished = require('on-finished'); const { rundir } = require('./utility/directories'); const platformInfo = require('./utility/platformInfo'); const getExpressPath = require('./utility/getExpressPath'); -const { getLogins } = require('./utility/hasPermission'); const _ = require('lodash'); const { getLogger } = require('dbgate-tools'); const { createAuthProvider } = require('./auth/authProvider'); diff --git a/packages/api/src/utility/hasPermission.js b/packages/api/src/utility/hasPermission.js index fc40d3871..2dcc36a9d 100644 --- a/packages/api/src/utility/hasPermission.js +++ b/packages/api/src/utility/hasPermission.js @@ -1,27 +1,37 @@ const { compilePermissions, testPermission } = require('dbgate-tools'); const _ = require('lodash'); +const { createAuthProvider } = require('../auth/authProvider'); -const userPermissions = {}; +const cachedPermissions = {}; function hasPermission(tested, req) { if (!req) { // request object not available, allow all return true; } - const { user } = (req && req.auth) || {}; - const { login } = (process.env.OAUTH_PERMISSIONS && req && req.user) || {}; - const key = user || login || ''; - const logins = getLogins(); - if (!userPermissions[key]) { - if (logins) { - const login = logins.find(x => x.login == user); - userPermissions[key] = compilePermissions(login ? login.permissions : null); - } else { - userPermissions[key] = compilePermissions(process.env.PERMISSIONS); - } + const permissions = createAuthProvider().getCurrentPermissions(req); + + if (!cachedPermissions[permissions]) { + cachedPermissions[permissions] = compilePermissions(permissions); } - return testPermission(tested, userPermissions[key]); + + return testPermission(tested, cachedPermissions[permissions]); + + // const { user } = (req && req.auth) || {}; + // const { login } = (process.env.OAUTH_PERMISSIONS && req && req.user) || {}; + // const key = user || login || ''; + // const logins = getLogins(); + + // if (!userPermissions[key]) { + // if (logins) { + // const login = logins.find(x => x.login == user); + // userPermissions[key] = compilePermissions(login ? login.permissions : null); + // } else { + // userPermissions[key] = compilePermissions(process.env.PERMISSIONS); + // } + // } + // return testPermission(tested, userPermissions[key]); } // let loginsCache = null; @@ -86,7 +96,6 @@ function testConnectionPermission(connection, req) { module.exports = { hasPermission, - getLogins, connectionHasPermission, testConnectionPermission, };