Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 78 additions & 79 deletions npm-shrinkwrap.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@
"jsonwebtoken": "^9.0.2",
"moment": "^2.30.1",
"mongodb": "^6.9.0",
"mongoose": "^8.7.1",
"pino": "^9.4.0",
"pino-pretty": "^11.2.2",
"mongoose": "^8.7.2",
"pino": "^9.5.0",
"pino-pretty": "^11.3.0",
"swagger-ui-express": "^5.0.1",
"switcher-client": "^4.1.1",
"validator": "^13.12.0"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"eslint": "^9.12.0",
"eslint": "^9.13.0",
"jest": "^29.7.0",
"jest-sonar-reporter": "^2.0.0",
"node-notifier": "^10.0.1",
Expand Down
12 changes: 6 additions & 6 deletions requests/Switcher API.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -5657,7 +5657,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n\t\"repository\": \"{{gitops_github_url}}\",\r\n\t\"token\": \"{{gitops_github_pat}}\",\r\n\t\"branch\": \"staging\",\r\n \"environment\": \"default\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\",\r\n\t\t\"name\": \"GitOps\"\r\n\t},\r\n\t\"settings\": {\r\n\t\t\"active\": true,\r\n\t\t\"window\": \"30s\",\r\n\t\t\"forceprune\": true\r\n\t}\t\r\n}",
"raw": "{\r\n\t\"repository\": \"{{gitops_github_url}}\",\r\n\t\"token\": \"{{gitops_github_pat}}\",\r\n\t\"branch\": \"develop\",\r\n \"path\": \"resources\",\r\n \"environment\": \"default\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\",\r\n\t\t\"name\": \"GitOps\"\r\n\t},\r\n\t\"settings\": {\r\n\t\t\"active\": true,\r\n\t\t\"window\": \"30s\",\r\n\t\t\"forceprune\": true\r\n\t}\t\r\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -5801,7 +5801,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n\t\"repository\": \"{{gitops_github_url}}\",\r\n\t\"branch\": \"staging\",\r\n \"environment\": \"default\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\",\r\n\t\t\"name\": \"GitOps\"\r\n\t},\r\n\t\"settings\": {\r\n\t\t\"active\": true,\r\n\t\t\"window\": \"30s\",\r\n\t\t\"forceprune\": true\r\n\t}\t\r\n}",
"raw": "{\r\n \"environment\": \"default\",\r\n\t\"repository\": \"{{gitops_github_url}}\",\r\n\t\"branch\": \"develop\",\r\n \"token\": \"{{gitops_github_pat}}\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\",\r\n\t\t\"name\": \"GitOps\"\r\n\t},\r\n\t\"settings\": {\r\n\t\t\"active\": true,\r\n\t\t\"window\": \"3m\",\r\n\t\t\"forceprune\": true\r\n\t}\t\r\n}",
"options": {
"raw": {
"language": "json"
Expand All @@ -5823,7 +5823,7 @@
"response": []
},
{
"name": "GitOps Account - Update Token",
"name": "GitOps Account - Update Tokens",
"request": {
"auth": {
"type": "bearer",
Expand All @@ -5839,23 +5839,23 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"environment\": \"default\",\r\n \"token\": \"{{gitops_github_pat}}\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\"\r\n\t}\r\n}",
"raw": "{\r\n \"token\": \"{{gitops_github_pat}}\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\"\r\n\t},\r\n \"environments\": [\r\n \"default\"\r\n ]\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{url}}/gitops/v1/account/token",
"raw": "{{url}}/gitops/v1/account/tokens",
"host": [
"{{url}}"
],
"path": [
"gitops",
"v1",
"account",
"token"
"tokens"
]
}
},
Expand Down
10 changes: 5 additions & 5 deletions src/api-docs/paths/path-gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default {
'/gitops/v1/account': {
put: {
tags: ['Switcher GitOps'],
description: 'Update an account to receive gitops changes',
description: 'Update an account for gitops repository access',
requestBody: {
content: commonSchemaContent('GitOpsAccountUpdateRequest')
},
Expand All @@ -114,12 +114,12 @@ export default {
}
}
},
'/gitops/v1/account/token': {
'/gitops/v1/account/tokens': {
put: {
tags: ['Switcher GitOps'],
description: 'Update an account token to receive gitops changes',
description: 'Update account tokens for gitops repository access',
requestBody: {
content: commonSchemaContent('GitOpsAccountTokenUpdateRequest')
content: commonSchemaContent('GitOpsAccountTokensUpdateRequest')
},
responses: {
200: {
Expand All @@ -140,7 +140,7 @@ export default {
'/gitops/v1/account/forcesync': {
put: {
tags: ['Switcher GitOps'],
description: 'Force sync an account to receive gitops changes',
description: 'Force sync an account to lock up for gitops changes',
requestBody: {
content: commonSchemaContent('GitOpsAccountForceSyncRequest')
},
Expand Down
11 changes: 7 additions & 4 deletions src/api-docs/schemas/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,19 @@ export default {
type: 'object',
properties: accountUpdateRequest
},
GitOpsAccountTokenUpdateRequest: {
GitOpsAccountTokensUpdateRequest: {
type: 'object',
properties: {
token: {
type: 'string',
description: 'The Git token'
},
environment: {
type: 'string',
description: 'The environment name'
environments: {
type: 'array',
items: {
type: 'string'
},
description: 'The environments to update'
},
domain: {
type: 'object',
Expand Down
19 changes: 19 additions & 0 deletions src/external/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@ export async function updateAccount(account) {
}
}

export async function updateAccountTokens(update, domainId) {
try {
const url = `${process.env.SWITCHER_GITOPS_URL}/account/tokens/${domainId}`;
const response = await axios.put(url, update, {
httpsAgent: agent(url),
headers: headers(domainId)
});

if (response.status !== 200) {
throw new GitOpsError(`Failed to update accounts [${response.status}] ${JSON.stringify(response.data)}`,
response.status);
}

return response.data;
} catch (e) {
throw new GitOpsError(`Failed to update account: ${e.message}`, e.status);
}
}

export async function deleteAccount(domainId, environment) {
try {
const url = `${process.env.SWITCHER_GITOPS_URL}/account/${domainId}/${environment}`;
Expand Down
17 changes: 10 additions & 7 deletions src/routers/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ const windowValidation = (value) => {
throw new Error('Invalid window value (minimum 30s)');
}

if (parseInt(value) < 1) {
throw new Error('Invalid window value (minimum 1[m/h])');
}

return true;
};

const accountValidators = [
body('token').isString().optional(),
body('repository').isURL().withMessage('Invalid repository URL'),
body('branch').isString().withMessage('Invalid branch name'),
body('path').isString().optional().withMessage('Invalid path'),
body('environment').isString().withMessage('Invalid environment name'),
body('domain.id').isMongoId().withMessage('Invalid domain ID'),
body('domain.name').isString().withMessage('Invalid domain name'),
Expand Down Expand Up @@ -74,10 +79,8 @@ router.post('/gitops/v1/account/unsubscribe', auth, [
}
});

router.put('/gitops/v1/account', auth, [
body('environment').isString(),
body('domain.id').isMongoId().withMessage('Invalid domain ID'),
], validate, featureFlag, async (req, res) => {
router.put('/gitops/v1/account', auth, accountValidators, validate,
featureFlag, async (req, res) => {
try {
const account = await Service.updateAccount(req.body);
res.status(200).send(account);
Expand All @@ -86,13 +89,13 @@ router.put('/gitops/v1/account', auth, [
}
});

router.put('/gitops/v1/account/token', auth, [
body('environment').isString(),
router.put('/gitops/v1/account/tokens', auth, [
body('token').isString(),
body('environments').isArray(),
body('domain.id').isMongoId().withMessage('Invalid domain ID'),
], validate, featureFlag, async (req, res) => {
try {
const account = await Service.updateAccountToken(req.body);
const account = await Service.updateAccountTokens(req.body);
res.status(200).send(account);
} catch (e) {
responseExceptionSilent(res, e, 500, 'Account token update failed');
Expand Down
11 changes: 4 additions & 7 deletions src/services/gitops/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,11 @@ export async function updateAccount(account) {
return GitOpsFacade.updateAccount(account);
}

export async function updateAccountToken(account) {
return GitOpsFacade.updateAccount({
environment: account.environment,
export async function updateAccountTokens(account) {
return GitOpsFacade.updateAccountTokens({
token: account.token,
domain: {
id: account.domain.id
}
});
environments: account.environments
}, account.domain.id);
}

export async function forceSyncAccount(account) {
Expand Down
59 changes: 30 additions & 29 deletions tests/gitops-account.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,19 @@ describe('GitOps Account - Subscribe', () => {
expect(req.body.errors[0].msg).toBe('Invalid window value (minimum 30s)');
});

test('GITOPS_ACCOUNT_SUITE - Should return error - window cannot be lower than 1(m/h)', async () => {
const payload = JSON.parse(JSON.stringify(VALID_SUBSCRIPTION_REQUEST));
payload.settings.window = "0m";

const req = await request(app)
.post('/gitops/v1/account/subscribe')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(payload)
.expect(422);

expect(req.body.errors[0].msg).toBe('Invalid window value (minimum 1[m/h])');
});

test('GITOPS_ACCOUNT_SUITE - Should return error - window cannot use different units than [s,m,h]', async () => {
const payload = JSON.parse(JSON.stringify(VALID_SUBSCRIPTION_REQUEST));
payload.settings.window = '1d';
Expand All @@ -204,6 +217,7 @@ describe('GitOps Account - Update', () => {
repository: 'https://github.com/switcherapi/switcher-gitops-fixture',
branch: 'main',
environment: EnvType.DEFAULT,
path: 'path/to/file',
domain: {
id: String(domainId),
name: 'Test Domain'
Expand Down Expand Up @@ -294,55 +308,42 @@ describe('GitOps Account - Update', () => {

})

describe('GitOps Account - Update Token', () => {
describe('GitOps Account - Update All Token', () => {
beforeAll(setupDatabase);

const VALID_UPDATE_REQUEST = {
repository: 'https://github.com/switcherapi/switcher-gitops-fixture',
branch: 'main',
environment: EnvType.DEFAULT,
domain: {
id: String(domainId),
name: 'Test Domain'
},
settings: {
active: true,
window: '30s',
forceprune: true
}
};

const VALID_TOKEN_UPDATE_REQUEST = {
environment: EnvType.DEFAULT,
environments: [EnvType.DEFAULT],
token: '123456',
domain: {
id: String(domainId)
}
};

test('GITOPS_ACCOUNT_SUITE - Should update account token', async () => {
// given
const expectedResponse = JSON.parse(JSON.stringify(VALID_UPDATE_REQUEST));
expectedResponse.token = '...123';

test('GITOPS_ACCOUNT_SUITE - Should update account tokens', async () => {
const postStub = sinon.stub(axios, 'put').resolves({
status: 200,
data: expectedResponse
data: {
result: true,
message: 'Account tokens updated successfully'
}
});

// test
const req = await request(app)
.put('/gitops/v1/account/token')
.put('/gitops/v1/account/tokens')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_TOKEN_UPDATE_REQUEST)
.expect(200);

// assert
expect(req.body).toMatchObject(expectedResponse);
expect(req.body).toMatchObject({
result: true,
message: 'Account tokens updated successfully'
});
postStub.restore();
});

test('GITOPS_ACCOUNT_SUITE - Should return error - error updating account token', async () => {
test('GITOPS_ACCOUNT_SUITE - Should return error - error updating account tokens', async () => {
// given
const postStub = sinon.stub(axios, 'put').resolves({
status: 500,
Expand All @@ -353,7 +354,7 @@ describe('GitOps Account - Update Token', () => {

// test
const req = await request(app)
.put('/gitops/v1/account/token')
.put('/gitops/v1/account/tokens')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_TOKEN_UPDATE_REQUEST)
.expect(500);
Expand All @@ -374,7 +375,7 @@ describe('GitOps Account - Update Token', () => {

// test
const req = await request(app)
.put('/gitops/v1/account/token')
.put('/gitops/v1/account/tokens')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_TOKEN_UPDATE_REQUEST)
.expect(500);
Expand All @@ -389,7 +390,7 @@ describe('GitOps Account - Update Token', () => {
delete payload.domain.id;

const req = await request(app)
.put('/gitops/v1/account/token')
.put('/gitops/v1/account/tokens')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(payload)
.expect(422);
Expand Down