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
39 changes: 39 additions & 0 deletions requests/Switcher API.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -5679,6 +5679,45 @@
},
"response": []
},
{
"name": "GitOps Account - Unsubscribe",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{authToken}}",
"type": "string"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"environment\": \"default\",\r\n\t\"domain\": {\r\n\t\t\"id\": \"{{gitops_domain_id}}\"\r\n\t}\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{url}}/gitops/v1/account/unsubscribe",
"host": [
"{{url}}"
],
"path": [
"gitops",
"v1",
"account",
"unsubscribe"
]
}
},
"response": []
},
{
"name": "GitOps Account - Update",
"request": {
Expand Down
18 changes: 18 additions & 0 deletions src/api-docs/paths/path-gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,24 @@ export default {
}
}
},
'/gitops/v1/account/unsubscribe': {
post: {
tags: ['Switcher GitOps'],
description: 'Unsubscribe an account from receiving gitops changes',
requestBody: {
content: commonSchemaContent('GitOpsAccountUnsubscribeRequest')
},
responses: {
200: {
description: 'Account unsubscribed successfully'
},
500: {
description: 'Something went wrong while unsubscribing the account',
content: commonSchemaContent('ErrorResponse')
}
}
}
},
'/gitops/v1/account': {
put: {
tags: ['Switcher GitOps'],
Expand Down
13 changes: 13 additions & 0 deletions src/api-docs/schemas/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,19 @@ export default {
}
}
},
GitOpsAccountUnsubscribeRequest: {
type: 'object',
properties: {
environment: {
type: 'string',
description: 'The environment name'
},
domain: {
type: 'object',
properties: domain
}
}
},
GitOpsAccountForceSyncRequest: {
type: 'object',
properties: {
Expand Down
12 changes: 12 additions & 0 deletions src/external/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ export async function updateAccount(account) {
return response.data;
}

export async function deleteAccount(domainId, environment) {
const url = `${process.env.SWITCHER_GITOPS_URL}/account/${domainId}/${environment}`;
const response = await axios.delete(url, {
httpsAgent: agent(url),
headers: headers(domainId)
});

if (response.status !== 204) {
throw new GitOpsError(`Failed to delete account [${response.status}] ${JSON.stringify(response.data)}`);
}
}

function generateToken(subject) {
const options = {
expiresIn: '1m'
Expand Down
12 changes: 12 additions & 0 deletions src/routers/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ router.post('/gitops/v1/account/subscribe', auth, accountValidators, validate,
}
});

router.post('/gitops/v1/account/unsubscribe', auth, [
body('environment').isString(),
body('domain.id').isMongoId().withMessage('Invalid domain ID'),
], validate, featureFlag, async (req, res) => {
try {
await Service.unsubscribeAccount(req.body);
res.status(200).send();
} catch (e) {
responseExceptionSilent(res, e, 500, 'Account unsubscription failed');
}
});

router.put('/gitops/v1/account', auth, [
body('environment').isString(),
body('domain.id').isMongoId().withMessage('Invalid domain ID'),
Expand Down
4 changes: 4 additions & 0 deletions src/services/gitops/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@ export async function forceSyncAccount(account) {
id: account.domain.id
}
});
}

export async function unsubscribeAccount(account) {
return GitOpsFacade.deleteAccount(account.domain.id, account.environment);
}
208 changes: 160 additions & 48 deletions tests/gitops-account.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,53 +11,6 @@ import {
adminMasterAccountToken
} from './fixtures/db_client';

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

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,
token: '123456',
domain: {
id: String(domainId)
}
};

const VALID_FORCE_SYNC_REQUEST = {
environment: EnvType.DEFAULT,
domain: {
id: String(domainId)
}
};


afterAll(async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
await mongoose.disconnect();
Expand All @@ -78,7 +31,21 @@ describe('GitOps Account - Feature Toggle', () => {
const req = await request(app)
.post('/gitops/v1/account/subscribe')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_SUBSCRIPTION_REQUEST)
.send({
repository: 'https://github.com/switcherapi/switcher-gitops-fixture',
token: '{{github_pat}}',
branch: 'main',
environment: EnvType.DEFAULT,
domain: {
id: String(domainId),
name: 'Test Domain'
},
settings: {
active: true,
window: '30s',
forceprune: true
}
})
.expect(400);

expect(req.body.error).toBe('GitOps Integration is not available.');
Expand All @@ -88,6 +55,22 @@ describe('GitOps Account - Feature Toggle', () => {
describe('GitOps Account - Subscribe', () => {
beforeAll(setupDatabase);

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

test('GITOPS_ACCOUNT_SUITE - Should subscribe account', async () => {
// given
const expectedResponse = JSON.parse(JSON.stringify(VALID_SUBSCRIPTION_REQUEST));
Expand Down Expand Up @@ -208,6 +191,21 @@ describe('GitOps Account - Subscribe', () => {
describe('GitOps Account - Update', () => {
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
}
};

test('GITOPS_ACCOUNT_SUITE - Should update account', async () => {
// given
const expectedResponse = JSON.parse(JSON.stringify(VALID_UPDATE_REQUEST));
Expand Down Expand Up @@ -290,6 +288,29 @@ describe('GitOps Account - Update', () => {
describe('GitOps Account - Update 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,
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));
Expand Down Expand Up @@ -371,6 +392,13 @@ describe('GitOps Account - Update Token', () => {
describe('GitOps Account - Force sync', () => {
beforeAll(setupDatabase);

const VALID_FORCE_SYNC_REQUEST = {
environment: EnvType.DEFAULT,
domain: {
id: String(domainId)
}
};

test('GITOPS_ACCOUNT_SUITE - Should force sync account', async () => {
// given
const expectedResponse = JSON.parse(JSON.stringify(VALID_FORCE_SYNC_REQUEST));
Expand Down Expand Up @@ -448,3 +476,87 @@ describe('GitOps Account - Force sync', () => {
expect(req.body.errors[0].msg).toBe('Invalid domain ID');
});
});

describe('GitOps Account - Unsubscribe', () => {
beforeAll(setupDatabase);

const VALID_DELETE_REQUEST = {
environment: EnvType.DEFAULT,
domain: {
id: String(domainId)
}
};

test('GITOPS_ACCOUNT_SUITE - Should subscribe account', async () => {
// given
const postStub = sinon.stub(axios, 'delete').resolves({
status: 204,
data: null
});

// test
await request(app)
.post(`/gitops/v1/account/unsubscribe`)
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_DELETE_REQUEST)
.expect(200);

postStub.restore();
});

test('GITOPS_ACCOUNT_SUITE - Should return error - error deleting account', async () => {
// given
const postStub = sinon.stub(axios, 'delete').resolves({
status: 500,
data: {
error: 'Error deleting account'
}
});

// test
const req = await request(app)
.post('/gitops/v1/account/unsubscribe')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_DELETE_REQUEST)
.expect(500);

// assert
expect(req.body.error).toBe('Account unsubscription failed');
postStub.restore();
});

test('GITOPS_ACCOUNT_SUITE - Should return error - unauthorized', async () => {
// given
const postStub = sinon.stub(axios, 'delete').resolves({
status: 401,
data: {
error: 'Invalid token'
}
});

// test
const req = await request(app)
.post('/gitops/v1/account/unsubscribe')
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send(VALID_DELETE_REQUEST)
.expect(500);

// assert
expect(req.body.error).toBe('Account unsubscription failed');
postStub.restore();
});

test('GITOPS_ACCOUNT_SUITE - Should return error - missing domain.id', async () => {
const payload = JSON.parse(JSON.stringify(VALID_DELETE_REQUEST));
delete payload.domain.id;

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

expect(req.body.errors[0].msg).toBe('Invalid domain ID');
});

});