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"
},