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
19 changes: 13 additions & 6 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 { randomBytes } from 'crypto';
import { randomUUID } from 'crypto';
import jwt from 'jsonwebtoken';
import { Config } from './config';
import Domain from './domain';
Expand Down Expand Up @@ -55,13 +55,12 @@ componentSchema.options.toJSON = {
componentSchema.methods.generateApiKey = async function () {
const component = this;

const buffer = randomBytes(32);
const apiKey = Buffer.from(buffer).toString('base64');
const apiKey = randomUUID();
const hash = await bcryptjs.hash(apiKey, 8);
component.apihash = hash;
await component.save();

return Buffer.from(apiKey).toString('base64');
return apiKey;
};

componentSchema.methods.generateAuthToken = async function (environment) {
Expand All @@ -86,8 +85,16 @@ componentSchema.statics.findByCredentials = async (domainName, componentName, ap
throw new Error('Unable to find this Component');
}

let decoded = Buffer.from(apiKey, 'base64').toString('ascii');
const isMatch = await bcryptjs.compare(decoded, component.apihash);
let isMatch = false;

// Validate API Key type
if (apiKey.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i)) {
isMatch = await bcryptjs.compare(apiKey, component.apihash);
} else {
// Must be deprecated by date
let decoded = Buffer.from(apiKey, 'base64').toString('ascii');
isMatch = await bcryptjs.compare(decoded, component.apihash);
}

if (!isMatch) {
throw new Error('Unable to find this Component');
Expand Down
18 changes: 6 additions & 12 deletions tests/client-api.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import mongoose from 'mongoose';
import request from 'supertest';
import bcryptjs from 'bcryptjs';
import app from '../src/app';
import Domain from '../src/models/domain';
import GroupConfig from '../src/models/group-config';
Expand Down Expand Up @@ -548,21 +547,16 @@ describe('Testing criteria [REST] ', () => {
});

test('CLIENT_SUITE - Should NOT return success on a entry-based CRITERIA response - Component not registered', async () => {
//given
const component = {
// Given
const component = new Component({
_id: new mongoose.Types.ObjectId(),
name: 'Temp Component',
description: 'Temporary component',
domain: domainId,
owner: adminMasterAccountId
};

const hashApiKey = await bcryptjs.hash(component._id + component.name, 8);
const hash = await bcryptjs.hash(hashApiKey, 8);
component.apihash = hash;
await new Component(component).save();
const generatedApiKey = Buffer.from(hashApiKey).toString('base64');

});

const generatedApiKey = await component.generateApiKey();
const response = await request(app)
.post('/criteria/auth')
.set('switcher-api-key', `${generatedApiKey}`)
Expand All @@ -574,7 +568,7 @@ describe('Testing criteria [REST] ', () => {

const tempToken = response.body.token;

//test
// Test
const req = await request(app)
.post(`/criteria?key=${keyConfig}&showReason=true&showStrategy=true`)
.set('Authorization', `Bearer ${tempToken}`)
Expand Down
14 changes: 7 additions & 7 deletions tests/component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('Insertion tests', () => {
}).expect(201);

// DB validation - document created
const component = await Component.findById(response.body.component._id).lean();
const component = await Component.findById(response.body.component._id).exec();
expect(component).not.toBeNull();

// Response validation
Expand Down Expand Up @@ -95,8 +95,8 @@ describe('Insertion tests', () => {

expect(response.body.apiKey).not.toBeNull();
// DB validation - current Domain token should not be as the same as the generated
const apiKey = Buffer.from(response.body.apiKey, 'base64').toString('ascii');
const component = await Component.findById(component1Id).lean();
const apiKey = response.body.apiKey;
const component = await Component.findById(component1Id).exec();
const isMatch = await bcryptjs.compare(apiKey, component.apihash);
expect(isMatch).toEqual(true);
});
Expand Down Expand Up @@ -194,7 +194,7 @@ describe('Updating tests', () => {
}).expect(201);

// DB validation - document created
let component = await Component.findById(response.body.component._id).lean();
let component = await Component.findById(response.body.component._id).exec();
expect(component.description).toBe('This is my Web App using this wonderful API');

response = await request(app)
Expand All @@ -205,7 +205,7 @@ describe('Updating tests', () => {
}).expect(200);

// DB validation - document updated
component = await Component.findById(response.body._id).lean();
component = await Component.findById(response.body._id).exec();
expect(component.description).toBe('Wow, this is my updated description');
});

Expand Down Expand Up @@ -257,7 +257,7 @@ describe('Deletion tests', () => {
component: response.body.component._id
}).expect(200);

const configsToRemoveFrom = await Config.find({ components: { $in: [response.body.component._id] } }).lean();
const configsToRemoveFrom = await Config.find({ components: { $in: [response.body.component._id] } }).exec();
expect(configsToRemoveFrom[0]._id).toEqual(configId1);

response = await request(app)
Expand All @@ -266,7 +266,7 @@ describe('Deletion tests', () => {
.send().expect(200);

// DB validation - document deleted
const component = await Component.findById(response.body._id).lean();
const component = await Component.findById(response.body._id).exec();
expect(component).toBeNull();
});

Expand Down
5 changes: 2 additions & 3 deletions tests/fixtures/db_api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mongoose from 'mongoose';
import bcryptjs from 'bcryptjs';
import { randomBytes } from 'crypto';
import { randomUUID } from 'crypto';
import jwt from 'jsonwebtoken';
import Admin from '../../src/models/admin';
import Domain from '../../src/models/domain';
Expand Down Expand Up @@ -272,8 +272,7 @@ export const setupDatabase = async () => {
await new Permission(permissionAll3).save();
await new Permission(permissionAll4).save();

const buffer = randomBytes(32);
const apiKey = Buffer.from(buffer).toString('base64');
const apiKey = randomUUID();
const hash = await bcryptjs.hash(apiKey, 8);
component1.apihash = hash;
await new Component(component1).save();
Expand Down
7 changes: 3 additions & 4 deletions tests/fixtures/db_client.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose from 'mongoose';
import jwt from 'jsonwebtoken';
import bcryptjs from 'bcryptjs';
import { randomBytes } from 'crypto';
import { randomUUID } from 'crypto';
import Admin from '../../src/models/admin';
import Domain from '../../src/models/domain';
import GroupConfig from '../../src/models/group-config';
Expand Down Expand Up @@ -227,10 +227,9 @@ export const setupDatabase = async () => {
await new ConfigStrategy(configStrategyTIME_BETWEENDocument).save();
await new ConfigStrategy(configStrategyTIME_GREATDocument).save();

const buffer = randomBytes(32);
const newApiKey = Buffer.from(buffer).toString('base64');
const newApiKey = randomUUID();
const hash = await bcryptjs.hash(newApiKey, 8);
component1.apihash = hash;
await new Component(component1).save();
apiKey = Buffer.from(newApiKey).toString('base64');
apiKey = newApiKey;
};
7 changes: 3 additions & 4 deletions tests/fixtures/db_client_payload.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose from 'mongoose';
import jwt from 'jsonwebtoken';
import bcryptjs from 'bcryptjs';
import { randomBytes } from 'crypto';
import { randomUUID } from 'crypto';
import Admin from '../../src/models/admin';
import Domain from '../../src/models/domain';
import GroupConfig from '../../src/models/group-config';
Expand Down Expand Up @@ -116,10 +116,9 @@ export const setupDatabase = async () => {
await new Config(configPayloadDocument).save();
await new ConfigStrategy(configStrategyPAYLOAD_HAS_ONEDocument).save();

const buffer = randomBytes(32);
const newApiKey = Buffer.from(buffer).toString('base64');
const newApiKey = randomUUID();
const hash = await bcryptjs.hash(newApiKey, 8);
component1.apihash = hash;
await new Component(component1).save();
apiKey = Buffer.from(newApiKey).toString('base64');
apiKey = newApiKey;
};
5 changes: 2 additions & 3 deletions tests/fixtures/db_metrics.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose from 'mongoose';
import jwt from 'jsonwebtoken';
import bcryptjs from 'bcryptjs';
import { randomBytes } from 'crypto';
import { randomUUID } from 'crypto';
import { Metric } from '../../src/models/metric';
import Admin from '../../src/models/admin';
import { EnvType } from '../../src/models/environment';
Expand Down Expand Up @@ -170,8 +170,7 @@ export const setupDatabase = async () => {
await new Metric(entry3).save();
await new Metric(entry4).save();

const buffer = randomBytes(32);
const newApiKey = Buffer.from(buffer).toString('base64');
const newApiKey = randomUUID();
const hash = await bcryptjs.hash(newApiKey, 8);
component1.apihash = hash;
await new Component(component1).save();
Expand Down
74 changes: 74 additions & 0 deletions tests/model/component.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require('../../src/db/mongoose');

import { randomBytes } from 'crypto';
import bcryptjs from 'bcryptjs';
import mongoose from 'mongoose';
import {
setupDatabase,
adminMasterAccountId,
domainId,
domainDocument
} from '../fixtures/db_api';
import Component from '../../src/models/component';

afterAll(async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
await mongoose.disconnect();
});

describe('(Deprecated) Testing component authentication', () => {
beforeAll(async () => await setupDatabase());

/**
* Generates API key using old method
*/
const generateApiKeyDeprecated = async (component) => {
const buffer = randomBytes(32);
const apiKey = Buffer.from(buffer).toString('base64');
const hash = await bcryptjs.hash(apiKey, 8);
component.apihash = hash;
await component.save();

const generatedApiKey = Buffer.from(apiKey).toString('base64');
return generatedApiKey;
}

test('COMPONENT_MODEL - Should authenticate component using old API key format', async () => {
// Given
const componentId = new mongoose.Types.ObjectId();
const component = new Component({
_id: componentId,
name: 'TestDeprecatedAPIKey',
description: 'Test app with depracated API key',
domain: domainId,
owner: adminMasterAccountId
});

// That
const generatedApiKey = await generateApiKeyDeprecated(component);

// Test
const result = await Component.findByCredentials(domainDocument.name, component.name, generatedApiKey);
expect(result.component).not.toBe(undefined);
});

test('COMPONENT_MODEL - Should authenticate component using new API key format', async () => {
// Given
const componentId = new mongoose.Types.ObjectId();
const component = new Component({
_id: componentId,
name: 'TestNewAPIKey',
description: 'Test app with New API key',
domain: domainId,
owner: adminMasterAccountId
});

// That
const generatedApiKey = await component.generateApiKey();

// Test
const result = await Component.findByCredentials(domainDocument.name, component.name, generatedApiKey);
expect(result.component).not.toBe(undefined);
});

});