From bf48d9e4dc9a7c239b2e0ed5b874cf99ac15ea29 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Sat, 13 Sep 2025 13:22:53 -0700 Subject: [PATCH 1/2] Updated admin model to register auth provider type --- README.md | 45 +++++++++++++++++++++++++++++++---- npm-shrinkwrap.json | 40 +++++++++++++++---------------- package.json | 4 ++-- src/api-docs/schemas/admin.js | 5 ++++ src/models/admin.js | 6 +++++ tests/admin.test.js | 3 +++ 6 files changed, 77 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 197ca48d..ab85c9a7 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,43 @@ Main features: 2. Add .env-cmdrc file into the project directory (use '.env-cmdrc-template') 3. Replace values such as secret keys and URLs +### Auth Providers + +Switcher API supports multiple auth providers such as email/password-based authentication or GitHub, Bitbucket OAuth. + +Follow the steps below to set up your OAuth App in GitHub and Bitbucket. + +#### GitHub OAuth App setup + +1. Open your GitHub account or organization settings +2. Go to Developer settings > OAuth Apps +3. Click on "New OAuth App" +4. Fill in the application details: + - Application name: Switcher API + - Homepage URL: https://switcher-management-url (or your deployed URL) + - Authorization callback URL: https://switcher-management-url/login?platform=github +5. Click on "Register application" +6. Copy the Client ID and Client Secret +7. Update your .env-cmdrc file or ConfigMap/Secret in Kubernetes with the following variables: + - GIT_OAUTH_CLIENT_ID=your_client_id + - GIT_OAUTH_CLIENT_SECRET=your_client_secret +8. Update Switcher Management GITHUB_CLIENTID environment variable with your_client_id + +#### Bitbucket OAuth App setup + +1. Open your Bitbucket account or workspace settings +2. Go to Apps and features > OAuth consumers +3. Fill in the application details: + - Name: Switcher API + - Callback URL: https://switcher-management-url/login?platform=bitbucket +4. Add permissions -> Account: Read +5. Click on "Save" +6. Copy the Key and Secret +7. Update your .env-cmdrc file or ConfigMap/Secret in Kubernetes with the following variables: + - BIT_OAUTH_CLIENT_ID=your_client_id + - BIT_OAUTH_CLIENT_SECRET=your_client_secret +8. Update Switcher Management BITBUCKET_CLIENTID environment variable with your_client_id + ### Running Switcher API from Docker Composer manifest file This option leverages Switcher API and Switcher Management with minimum settings required. @@ -85,8 +122,8 @@ It is equivalent to an organization that can manage multiple projects, users, an - **New domain** - Domain: /domain/create [POST] ### Component -Components are applications that are using Switcher API.
-Each component has its own access token and needs to be linked to Switchers. +Components are applications that will use Switcher API.
+Each component has its own access API key to interact with Switcher API. - **Create a component** - Component: /component/create [POST] - **Generating a new API Key** - Component: /component/generateApiKey [GET] @@ -97,11 +134,11 @@ Groups are used to organize Switchers that share the same feature scope. - **New Group** - GroupConfig: /groupconfig/create [POST] ### Switcher -Switchers are the main entities to control features. +Switchers are the entry point to control features in your application.
- **New Switcher** - Config: /config/create [POST] ### Strategy -Customize the behavior of the Switcher by including strategy rules to your Switchers. +Customize the Switcher behavior by including strategy rules to your Switchers. - **New Strategy** - ConfigStrategy: /configstrategy/create [POST] diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0bca00b5..c639a910 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9,7 +9,7 @@ "version": "1.4.1", "license": "MIT", "dependencies": { - "axios": "^1.11.0", + "axios": "^1.12.0", "bcryptjs": "^3.0.2", "cors": "^2.8.5", "express": "^5.1.0", @@ -24,7 +24,7 @@ "moment": "^2.30.1", "mongodb": "^6.19.0", "mongoose": "^8.18.1", - "pino": "^9.9.4", + "pino": "^9.9.5", "pino-pretty": "^13.1.1", "swagger-ui-express": "^5.0.1", "switcher-client": "^4.4.1", @@ -1291,9 +1291,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1426,9 +1426,9 @@ } }, "node_modules/@tybys/wasm-util": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", - "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, @@ -1989,9 +1989,9 @@ } }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", + "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -2809,9 +2809,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.215", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.215.tgz", - "integrity": "sha512-TIvGp57UpeNetj/wV/xpFNpWGb0b/ROw372lHPx5Aafx02gjTBtWnEEcaSX3W2dLM3OSdGGyHX/cHl01JQsLaQ==", + "version": "1.5.218", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz", + "integrity": "sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==", "dev": true, "license": "ISC" }, @@ -5873,9 +5873,9 @@ } }, "node_modules/pino": { - "version": "9.9.4", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.4.tgz", - "integrity": "sha512-d1XorUQ7sSKqVcYdXuEYs2h1LKxejSorMEJ76XoZ0pPDf8VzJMe7GlPXpMBZeQ9gE4ZPIp5uGD+5Nw7scxiigg==", + "version": "9.9.5", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.5.tgz", + "integrity": "sha512-d1s98p8/4TfYhsJ09r/Azt30aYELRi6NNnZtEbqFw6BoGsdPVf5lKNK3kUwH8BmJJfpTLNuicjUQjaMbd93dVg==", "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", @@ -6878,9 +6878,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.28.1", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.28.1.tgz", - "integrity": "sha512-IvPrtNi8MvjiuDgoSmPYgg27Lvu38fnLD1OSd8Y103xXsPAqezVNnNeHnVCZ/d+CMXJblflGaIyHxAYIF3O71w==", + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.29.0.tgz", + "integrity": "sha512-gqs7Md3AxP4mbpXAq31o5QW+wGUZsUzVatg70yXpUR245dfIis5jAzufBd+UQM/w2xSfrhvA1eqsrgnl2PbezQ==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" diff --git a/package.json b/package.json index a4b39d2f..e22ea6fb 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ ], "license": "MIT", "dependencies": { - "axios": "^1.11.0", + "axios": "^1.12.1", "bcryptjs": "^3.0.2", "cors": "^2.8.5", "express": "^5.1.0", @@ -51,7 +51,7 @@ "moment": "^2.30.1", "mongodb": "^6.19.0", "mongoose": "^8.18.1", - "pino": "^9.9.4", + "pino": "^9.9.5", "pino-pretty": "^13.1.1", "swagger-ui-express": "^5.0.1", "switcher-client": "^4.4.1", diff --git a/src/api-docs/schemas/admin.js b/src/api-docs/schemas/admin.js index 1d9e4ad3..dc9d0e54 100644 --- a/src/api-docs/schemas/admin.js +++ b/src/api-docs/schemas/admin.js @@ -17,6 +17,11 @@ export const admin = { type: 'boolean', description: 'Whether the admin is active or not' }, + auth_provider: { + type: 'string', + enum: ['email', 'github', 'bitbucket'], + description: 'Authentication provider used' + }, teams: { type: 'array', items: { diff --git a/src/models/admin.js b/src/models/admin.js index 0b871a42..61a707f0 100644 --- a/src/models/admin.js +++ b/src/models/admin.js @@ -40,6 +40,11 @@ const adminSchema = new mongoose.Schema({ code: { type: String }, + auth_provider: { + type: String, + enum: ['email', 'github', 'bitbucket'], + default: 'email' + }, _gitid: { type: String }, @@ -176,6 +181,7 @@ adminSchema.statics.createThirdPartyAccount = async ( admin = new Admin({ name: userInfo.name, email: userInfo.email, + auth_provider: platform, [`${attributeIdName}`]: userInfo.id, _avatar: userInfo.avatar, password: hash diff --git a/tests/admin.test.js b/tests/admin.test.js index 77220d03..8728632b 100644 --- a/tests/admin.test.js +++ b/tests/admin.test.js @@ -55,6 +55,7 @@ describe('Testing Admin insertion', () => { // DB validation - document created const admin = await Admin.findById(response.body.admin._id).lean().exec(); expect(admin).not.toBeNull(); + expect(admin.auth_provider).toBe('email'); //used at: ADMIN_SUITE - Should confirm access to a new Admin signedupUser = response.body.admin._id; @@ -282,6 +283,7 @@ describe('Testing Admin insertion', () => { const admin = await Admin.findById(response.body.admin._id).lean().exec(); expect(admin).not.toBeNull(); expect(admin._gitid).toEqual('123456789'); + expect(admin.auth_provider).toBe('github'); // restore axiosPostStub.restore(); @@ -320,6 +322,7 @@ describe('Testing Admin insertion', () => { const admin = await Admin.findById(response.body.admin._id).lean().exec(); expect(admin).not.toBeNull(); expect(admin._bitbucketid).toEqual('123456789'); + expect(admin.auth_provider).toBe('bitbucket'); // restore axiosPostStub.restore(); From a461e1eee487f2070abffad5ead0c35306feee68 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Sat, 13 Sep 2025 13:28:14 -0700 Subject: [PATCH 2/2] fix: sync npm-shrinkwrap file with package.json --- npm-shrinkwrap.json | 49 +++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c639a910..81fe216d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -9,7 +9,7 @@ "version": "1.4.1", "license": "MIT", "dependencies": { - "axios": "^1.12.0", + "axios": "^1.12.1", "bcryptjs": "^3.0.2", "cors": "^2.8.5", "express": "^5.1.0", @@ -1523,9 +1523,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", - "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "version": "24.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.3.tgz", + "integrity": "sha512-GKBNHjoNw3Kra1Qg5UXttsY5kiWMEfoHq2TmXb+b1rcm6N7B3wTrFYIf/oSZ1xNQ+hVVijgLkiDZh7jRRsh+Gw==", "dev": true, "license": "MIT", "dependencies": { @@ -1989,9 +1989,9 @@ } }, "node_modules/axios": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz", - "integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", + "integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -2107,6 +2107,16 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.3.tgz", + "integrity": "sha512-mcE+Wr2CAhHNWxXN/DdTI+n4gsPc5QpXpWnyCQWiQYIYZX+ZMJ8juXZgjRa/0/YPJo/NSsgW15/YgmI4nbysYw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -2192,9 +2202,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", - "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz", + "integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==", "dev": true, "funding": [ { @@ -2212,9 +2222,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001737", - "electron-to-chromium": "^1.5.211", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.2", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -2675,9 +2686,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5519,9 +5530,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.20.tgz", - "integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, "license": "MIT" },