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
707 changes: 328 additions & 379 deletions npm-shrinkwrap.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
"jsonwebtoken": "^9.0.2",
"moment": "^2.30.1",
"mongodb": "^6.20.0",
"mongoose": "^8.18.2",
"mongoose": "^8.19.0",
"passport": "^0.7.0",
"@node-saml/passport-saml": "^5.1.0",
"pino": "^9.11.0",
"pino": "^9.13.0",
"pino-pretty": "^13.1.1",
"swagger-ui-express": "^5.0.1",
"switcher-client": "^4.4.1",
Expand All @@ -64,7 +64,7 @@
"devDependencies": {
"env-cmd": "^11.0.0",
"eslint": "^9.36.0",
"jest": "^30.1.3",
"jest": "^30.2.0",
"jest-sonar-reporter": "^2.0.0",
"node-notifier": "^10.0.1",
"nodemon": "^3.1.10",
Expand Down
6 changes: 3 additions & 3 deletions src/aggregator/permission-resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export async function resolvePermission(args, admin) {
for (const action_perm of args.actions) {
try {
await verifyOwnership(admin, element, args.domain, action_perm, args.router, false, args.environment);
result[result.length - 1].permissions.push({ action: action_perm.toString(), result: 'ok' });
result.at(-1).permissions.push({ action: action_perm.toString(), result: 'ok' });
} catch (e) {
Logger.debug('resolvePermission', e);
result[result.length - 1].permissions.push({ action: action_perm.toString(), result: 'nok' });
result.at(-1).permissions.push({ action: action_perm.toString(), result: 'nok' });
}
}
}
Expand All @@ -50,5 +50,5 @@ const getElements = async (domain, parent, router) => {
return getConfigs({ domain, group: parent }, true);
}

return Promise.resolve([]);
return [];
};
4 changes: 2 additions & 2 deletions src/aggregator/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ export const resolveConfigByKey = async (domain, key) => Config.findOne({ domain
export function resolveEnvValue(source, field, keys) {
const arrValue = [];

keys.forEach(k => {
for (const k of keys) {
arrValue.push({
env: k,
value: source[field][k]
});
});
}

return arrValue;
}
Expand Down
6 changes: 3 additions & 3 deletions src/app-server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import https from 'https';
import http from 'http';
import fs from 'fs';
import https from 'node:https';
import http from 'node:http';
import fs from 'node:fs';
import Logger from './helpers/logger.js';

export const createServer = (app) => {
Expand Down
2 changes: 1 addition & 1 deletion src/external/gitops.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from 'axios';
import https from 'https';
import https from 'node:https';
import jwt from 'jsonwebtoken';

const agent = (url) => {
Expand Down
32 changes: 16 additions & 16 deletions src/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const PATTERN_ALPHANUMERIC = /^[a-zA-Z0-9_-]*$/;

export async function checkEnvironmentStatusRemoval(domainId, environmentName, strategy = false) {
const environment = await getEnvironments({ domain: domainId }, ['_id', 'name']);
const isValidOperation = environment.filter((e) =>
const isValidOperation = environment.some((e) =>
e.name === environmentName &&
!strategy ? environmentName !== EnvType.DEFAULT : strategy).length > 0;
!strategy ? environmentName !== EnvType.DEFAULT : strategy);

if (!isValidOperation) {
throw new BadRequestError('Invalid environment');
Expand All @@ -32,33 +32,33 @@ export function containsValue(arr, value) {
}

export function formatInput(input,
options = {
toUpper: false,
toLower: false,
autoUnderscore: false,
allowSpace: false
}) {
{
toUpper = false,
toLower = false,
autoUnderscore = false,
allowSpace = false
} = {}) {

let regexStr;
if (options.autoUnderscore) {
if (autoUnderscore) {
regexStr = PATTERN_ALPHANUMERIC_SPACE;
} else {
regexStr = options.allowSpace ? PATTERN_ALPHANUMERIC_SPACE : PATTERN_ALPHANUMERIC;
regexStr = allowSpace ? PATTERN_ALPHANUMERIC_SPACE : PATTERN_ALPHANUMERIC;
}

const regex = new RegExp(regexStr);
if (!regex.test(input)) {
throw new Error('Invalid input format. Use only alphanumeric digits.');
}

if (options.toUpper) {
if (toUpper) {
input = input.toUpperCase();
} else if (options.toLower) {
} else if (toLower) {
input = input.toLowerCase();
}

if (options.autoUnderscore) {
input = input.replace(/\s/g, '_');
if (autoUnderscore) {
input = input.replaceAll(' ', '_');
}

return input.trim();
Expand All @@ -76,11 +76,11 @@ export function sortBy(args) {
}

export function validatePagingArgs(args) {
if (args.limit && !Number.isInteger(parseInt(args.limit)) || parseInt(args.limit) < 1) {
if (args.limit && !Number.isInteger(Number.parseInt(args.limit)) || Number.parseInt(args.limit) < 1) {
return false;
}

if (args.skip && !Number.isInteger(parseInt(args.skip)) || parseInt(args.skip) < 0) {
if (args.skip && !Number.isInteger(Number.parseInt(args.skip)) || Number.parseInt(args.skip) < 0) {
return false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/middleware/gitops.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ function validateChangesContent(changes) {
for (const change of changes) {
if (CONTENT_TYPE_ARRAY.includes(change.diff)) {
if (!Array.isArray(change.content)) {
throw new Error('Request has invalid content type [object]');
throw new TypeError('Request has invalid content type [object]');
}
} else if (Array.isArray(change.content)) {
throw new Error('Request has invalid content type [array]');
throw new TypeError('Request has invalid content type [array]');
}
}
}
4 changes: 2 additions & 2 deletions src/middleware/limiter.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ERROR_MESSAGE = {

const getMaxRate = (rate_limit) => {
if (rate_limit === 0) {
return parseInt(DEFAULT_RATE_LIMIT);
return Number.parseInt(DEFAULT_RATE_LIMIT);
}

return rate_limit;
Expand All @@ -17,7 +17,7 @@ export const DEFAULT_RATE_LIMIT = 1000;

export const defaultLimiter = rateLimit({
windowMs: DEFAULT_WINDOWMS,
limit: getMaxRate(parseInt(process.env.MAX_REQUEST_PER_MINUTE)),
limit: getMaxRate(Number.parseInt(process.env.MAX_REQUEST_PER_MINUTE)),
skip: (request) => request.rate_limit === 0,
standardHeaders: 'draft-7',
legacyHeaders: false,
Expand Down
2 changes: 1 addition & 1 deletion src/middleware/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export async function checkEnvironmentStatusChange(args, domain, field) {
const environment = await getEnvironments({ domain }, ['_id', 'name']);
const updates = Object.keys(field || args);
const isValidOperation = updates.every((update) => {
return environment.filter((e) => e.name === update).length > 0;
return environment.some((e) => e.name === update);
});

if (!isValidOperation) {
Expand Down
34 changes: 14 additions & 20 deletions src/models/admin.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose from 'mongoose';
import moment from 'moment';
import bcryptjs from 'bcryptjs';
import crypto from 'crypto';
import crypto from 'node:crypto';
import jwt from 'jsonwebtoken';
import { Team } from './team.js';
import { notifyAcCreation, notifyAcDeletion } from '../external/switcher-api-facade.js';
Expand Down Expand Up @@ -120,22 +120,20 @@ adminSchema.options.toJSON = {
};

adminSchema.methods.generateAuthToken = async function () {
const admin = this;

const options = {
expiresIn: process.env.JWT_ADMIN_TOKEN_RENEW_INTERVAL,
issuer: 'switcher-api'
};

const token = jwt.sign(({ _id: admin.id.toString(), issued: Date.now() }), process.env.JWT_SECRET, options);
const token = jwt.sign(({ _id: this.id.toString(), issued: Date.now() }), process.env.JWT_SECRET, options);
const refreshToken = jwt.sign(({
subject: Admin.extractTokenPart(token)
}), process.env.JWT_SECRET);

admin.code = null;
admin.active = true;
admin.token = Admin.extractTokenPart(token);
await admin.save();
this.code = null;
this.active = true;
this.token = Admin.extractTokenPart(token);
await this.save();

return {
token,
Expand All @@ -144,9 +142,8 @@ adminSchema.methods.generateAuthToken = async function () {
};

adminSchema.methods.generateAuthCode = async function () {
const admin = this;
admin.code = Math.random().toString(36).slice(-8);
return admin.code;
this.code = Math.random().toString(36).slice(-8);
return this.code;
};

adminSchema.statics.findByCredentials = async (email, password) => {
Expand Down Expand Up @@ -222,11 +219,9 @@ adminSchema.statics.extractTokenPart = (token) => {
};

adminSchema.pre('save', async function (next) {
const admin = this;

if (admin.isModified('password')) {
admin.password = await bcryptjs.hash(admin.password, EncryptionSalts.ADMIN);
notifyAcCreation(admin._id);
if (this.isModified('password')) {
this.password = await bcryptjs.hash(this.password, EncryptionSalts.ADMIN);
notifyAcCreation(this._id);
}

next();
Expand All @@ -241,15 +236,14 @@ adminSchema.post('save', function(error, _doc, next) {
});

adminSchema.pre('deleteOne', { document: true, query: false }, async function (next) {
const admin = this;
const teams = await Team.find({ members: admin._id }).exec();
const teams = await Team.find({ members: this._id }).exec();
for (const team of teams) {
let indexMmeber = team.members.indexOf(admin._id);
let indexMmeber = team.members.indexOf(this._id);
team.members.splice(indexMmeber, 1);
await team.save();
}

notifyAcDeletion(admin._id);
notifyAcDeletion(this._id);
next();
});

Expand Down
2 changes: 1 addition & 1 deletion src/models/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export async function recordHistory(modifiedField, oldDocument, newDocument, dom
modifiedField.forEach(keys => {
const keyArr = keys.split('.');
checkDifference(diff, documents, defaultIgnoredFields,
keyArr, keys.replace(/\./g, '/'), 0);
keyArr, keys.replaceAll('.', '/'), 0);
});

if (diff.newValues.size > 0) {
Expand Down
24 changes: 9 additions & 15 deletions src/models/component.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose from 'mongoose';
import moment from 'moment';
import bcryptjs from 'bcryptjs';
import { randomUUID } from 'crypto';
import { randomUUID } from 'node:crypto';
import { Config } from './config.js';
import { EncryptionSalts } from './common/index.js';

Expand Down Expand Up @@ -52,12 +52,10 @@ componentSchema.options.toJSON = {
};

componentSchema.methods.generateApiKey = async function () {
const component = this;

const apiKey = randomUUID();
const hash = await bcryptjs.hash(apiKey, EncryptionSalts.COMPONENT);
component.apihash = hash;
await component.save();
this.apihash = hash;
await this.save();

return apiKey;
};
Expand All @@ -71,26 +69,22 @@ const existComponent = async ({ domain, name, __v }) => {
};

componentSchema.pre('validate', async function (next) {
const component = this;

// Verify if component already exists
if (await existComponent(component)) {
const err = new Error(`Unable to complete the operation. Component '${component.name}' already exists for this Domain`);
if (await existComponent(this)) {
const err = new Error(`Unable to complete the operation. Component '${this.name}' already exists for this Domain`);
next(err);
}

next();
});

componentSchema.pre('deleteOne', { document: true, query: false }, async function (next) {
const component = this;

const configsToRemoveFrom = await Config.find({ components: { $in: [component._id] } }).exec();
configsToRemoveFrom.forEach(config => {
const indexValue = config.components.indexOf(component._id);
const configsToRemoveFrom = await Config.find({ components: { $in: [this._id] } }).exec();
for (const config of configsToRemoveFrom) {
const indexValue = config.components.indexOf(this._id);
config.components.splice(indexValue, 1);
config.save();
});
}

next();
});
Expand Down
Loading