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
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = {
coveragePathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/src/api-docs/',
'<rootDir>/src/app-server.js'
],

// A list of reporter names that Jest uses when writing coverage reports
Expand Down
15 changes: 10 additions & 5 deletions requests/Switcher API.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -3882,14 +3882,23 @@
"method": "GET",
"header": [],
"url": {
"raw": "{{url}}/config?group=5e0ece916f4f994eac9007b0",
"raw": "{{url}}/config?group=groupid",
"host": [
"{{url}}"
],
"path": [
"config"
],
"query": [
{
"key": "group",
"value": "groupid"
},
{
"key": "fields",
"value": "key",
"disabled": true
},
{
"key": "sortBy",
"value": "createdAt:asc",
Expand All @@ -3904,10 +3913,6 @@
"key": "skip",
"value": "2",
"disabled": true
},
{
"key": "group",
"value": "5e0ece916f4f994eac9007b0"
}
]
}
Expand Down
3 changes: 2 additions & 1 deletion src/api-docs/paths/path-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,8 @@ export default {
security: [{ bearerAuth: [] }],
parameters: [
...pagination,
queryParameter('group', 'Group ID', true)
queryParameter('group', 'Group ID', true),
queryParameter('fields', 'Fields to return', false, 'string', 'E.g.: key,description,activated.default')
],
responses: {
'200': {
Expand Down
7 changes: 4 additions & 3 deletions src/app-server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import https from 'https';
import http from 'http';
import fs from 'fs';
import Logger from './helpers/logger';

export const createServer = (app) => {
if (process.env.SSL_CERT && process.env.SSL_KEY) {
Expand All @@ -9,10 +10,10 @@ export const createServer = (app) => {
cert: fs.readFileSync(process.env.SSL_CERT)
};

console.log('SSL enabled');
Logger.info('SSL enabled');
return https.createServer(options, app);
}

console.log('SSL disabled');
Logger.info('SSL disabled');
return http.createServer(app);
};
6 changes: 2 additions & 4 deletions src/exceptions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,15 @@ export class FeatureUnavailableError extends Error {
}

export function responseException(res, err, code, feature = undefined) {
if (process.env.SWITCHER_API_LOGGER == 'true' && feature) {
if (feature) {
Logger.info(`Feature [${feature}]`, { log: Switcher.getLogger(feature) });
}

responseExceptionSilent(res, err, code, err.message);
}

export function responseExceptionSilent(res, err, code, message) {
if (process.env.SWITCHER_API_LOGGER == 'true') {
Logger.httpError(err.constructor.name, err.code, err.message, err);
}
Logger.httpError(err.constructor.name, err.code, err.message, err);

if (err.code) {
return res.status(err.code).send({ error: message });
Expand Down
14 changes: 10 additions & 4 deletions src/helpers/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ const logger = pino({
});

export default class Logger {

static get logger() {
return logger;
}

static info(message, obj) {
logger.info(obj, message);
if (process.env.SWITCHER_API_LOGGER == 'true')
logger.info(obj, message);
}

static error(message, err) {
logger.error(err, message);
if (process.env.SWITCHER_API_LOGGER == 'true')
logger.error(err, message);
}

static httpError(name, code, message, err) {
logger.error(err, `${name} [${code}]: ${message}`);
if (process.env.SWITCHER_API_LOGGER == 'true')
logger.error(err, `${name} [${code}]: ${message}`);
}
}
29 changes: 29 additions & 0 deletions src/routers/common/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export function getFields(elements, fields) {
return elements.map(element => {
const newElement = {};
fields.split(',').forEach(field => {
if (field.includes('.')) {
const nestedFields = field.split('.');
const nextNestedFields = field.substring(field.indexOf('.') + 1);

const nestedElement = getElement(element, nestedFields[0]);
newElement[nestedFields[0]] = getFields([nestedElement], nextNestedFields)[0];
} else {
newElement[field] = getElement(element, field);
}
});
return newElement;
});
}

function getElement(element, field) {
if (!element) {
return undefined;
}

if (element.get) {
return element.get(field);
}

return element[field];
}
14 changes: 12 additions & 2 deletions src/routers/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as Services from '../services/config';
import { getHistory, deleteHistory } from '../services/history';
import { getGroupConfigById } from '../services/group-config';
import { SwitcherKeys } from '../external/switcher-api-facade';
import { getFields } from './common';

const router = new express.Router();

Expand All @@ -30,9 +31,14 @@ router.post('/config/create',

// GET /config?group=ID&limit=10&skip=20
// GET /config?group=ID&sortBy=createdAt:desc
// GET /config?group=ID&fields=key,description
// GET /config?group=ID
router.get('/config', auth, [
query('group').isMongoId()
query('group').isMongoId(),
query('fields').isString().optional(),
query('limit').isInt().optional(),
query('skip').isInt().optional(),
query('sortBy').isString().optional()
], validate, async (req, res) => {
try {
const groupConfig = await getGroupConfigById(req.query.group);
Expand All @@ -46,8 +52,12 @@ router.get('/config', auth, [
});

let configs = groupConfig.config;

configs = await verifyOwnership(req.admin, configs, groupConfig.domain, ActionTypes.READ, RouterTypes.CONFIG, true);

if (req.query.fields) {
configs = getFields(configs, req.query.fields);
}

res.send(configs);
} catch (e) {
responseException(res, e, 500);
Expand Down
5 changes: 1 addition & 4 deletions src/services/slack.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,7 @@ export async function checkAvailability(admin, feature) {
SwitcherKeys.SLACK_UPDATE
]);

if (process.env.SWITCHER_API_LOGGER == 'true') {
Logger.info(`checkAvailability [${feature}]`, { log: Switcher.getLogger(feature) });
}

Logger.info(`checkAvailability [${feature}]`, { log: Switcher.getLogger(feature) });
return result;
}

Expand Down
15 changes: 15 additions & 0 deletions tests/config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,21 @@ describe('Testing fetch configuration info', () => {
expect(response.body[0].activated[EnvType.DEFAULT]).toEqual(config1Document.activated.get(EnvType.DEFAULT));
});

test('CONFIG_SUITE - Should get Config information - only fields (key, activated.default)', async () => {
let response = await request(app)
.get(`/config?group=${groupConfigId}&fields=key,activated.default`)
.set('Authorization', `Bearer ${adminMasterAccountToken}`)
.send().expect(200);

expect(response.body.length).toEqual(2);
expect(response.body[0]).toMatchObject({
key: config1Document.key,
activated: {
default: config1Document.activated.get(EnvType.DEFAULT)
}
});
});

test('CONFIG_SUITE - Should get Configs by sorting ascending and descending', async () => {
// given a config that was sent to the past
const configKey1 = await Config.findOne({ key: 'TEST_CONFIG_KEY_1' }).exec();
Expand Down
49 changes: 49 additions & 0 deletions tests/unit-test/helpers/logger.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Logger from '../../../src/helpers/logger';

describe('Helper: Logger', () => {
beforeAll(() => {
process.env.SWITCHER_API_LOGGER = 'true';
});

test('Should call logger.info', () => {
const spy = jest.spyOn(Logger.logger, 'info');
Logger.info('test');
expect(spy).toHaveBeenCalled();
});

test('Should call logger.error', () => {
const spy = jest.spyOn(Logger.logger, 'error');
Logger.error('test');
expect(spy).toHaveBeenCalled();
});

test('Should call logger.httpError', () => {
const spy = jest.spyOn(Logger.logger, 'error');
Logger.httpError('test');
expect(spy).toHaveBeenCalled();
});
});

describe('Helper: Logger (disabled)', () => {
beforeAll(() => {
process.env.SWITCHER_API_LOGGER = 'false';
});

test('Should call logger.info', () => {
const spy = jest.spyOn(Logger.logger, 'info');
Logger.info('test');
expect(spy).not.toHaveBeenCalled();
});

test('Should call logger.error', () => {
const spy = jest.spyOn(Logger.logger, 'error');
Logger.error('test');
expect(spy).not.toHaveBeenCalled();
});

test('Should call logger.httpError', () => {
const spy = jest.spyOn(Logger.logger, 'error');
Logger.httpError('test');
expect(spy).not.toHaveBeenCalled();
});
});
55 changes: 55 additions & 0 deletions tests/unit-test/routers/common-index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { getFields } from '../../../src/routers/common/index.js';

/* Fixtures */

const switcherActivated = new Map();
switcherActivated.set('default', true);

const relayActivated = new Map();
relayActivated.set('default', true);
relayActivated.set('staging', false);

const config1 = {
key: 'SWITCHER_KEY_1',
description: '[description]',
activated: switcherActivated,
relay: {
description: '[relay description]',
activated: relayActivated
}
};

const config2 = {
key: 'SWITCHER_KEY_2',
description: '[description]',
activated: switcherActivated
};

/* Tests */

describe('Helper: Router::common::getFields', () => {
test('Should return the fields from the object', () => {
const result = getFields([config1], 'key,activated.default,relay.activated.default');
expect(result).toEqual([{
key: 'SWITCHER_KEY_1',
activated: {
default: true
},
relay: {
activated: {
default: true
}
}
}]);
});

test('Should return the fields from the object - with non-existing field path', () => {
const result = getFields([config2], 'key,relay.activated.default');
expect(result).toEqual([{
key: 'SWITCHER_KEY_2',
relay: {
activated: {}
}
}]);
});
});