Skip to content

Commit

Permalink
feat(security): Create security check based on lts; add test;
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Rothweil committed Oct 30, 2020
1 parent 7743513 commit 86096b7
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 6 deletions.
52 changes: 52 additions & 0 deletions __tests__/security.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/// <reference types="@types/jest" />

jest.mock('execa');
jest.mock('node-fetch');
jest.mock('fs-extra');

import execa from 'execa';
import fetch from 'node-fetch';
import { logMessages } from '../src/log-messages';
import { getNodeSecurityChecker } from '../src/security';

const { Response } = jest.requireActual('node-fetch');


const exampleNodeList = [
{ version: 'v12.14.0', date: '2019-12-16', npm: '6.13.4', security: true, lts: 'Erbium' },
{ version: 'v14.7.0', date: '2020-07-29', npm: '6.14.7', security: false, lts: false },
];
const nodeVersionListURL = 'https://nodejs.org/dist/index.json';

describe('getNodeSecurityChecker', () => {
it('should return success-text if Security version is used', async () => {
(execa as any).mockReturnValue(Promise.resolve({ stdout: '12.14.0' }));
(fetch as any).mockReturnValue(Promise.resolve(new Response(JSON.stringify(exampleNodeList))));
expect(await getNodeSecurityChecker()).toMatchObject({
error: false,
text: logMessages.success.nodeVersionSecurity('12.14.0'),
});
});
it('should return error-text if none Security version is used', async () => {
(execa as any).mockReturnValue(Promise.resolve({ stdout: '14.7.0' }));
(fetch as any).mockReturnValue(Promise.resolve(new Response(JSON.stringify(exampleNodeList))));
expect(await getNodeSecurityChecker()).toMatchObject({
error: true,
text: logMessages.error.nodeVersionNotSecurityError('14.7.0'),
});
});
it('should return warning-text if we can not receive node-list', async () => {
(fetch as any).mockReturnValue(Promise.reject());
expect(await getNodeSecurityChecker()).toMatchObject({
error: false,
text: logMessages.warning.fetchNodeListErrorNodeSecurity(nodeVersionListURL),
});
});
it('should return error-text if we can not receive installed node version', async () => {
(execa as any).mockReturnValue(Promise.reject());
expect(await getNodeSecurityChecker()).toMatchObject({
error: true,
text: logMessages.error.readProgramVersionError('node'),
});
});
});
19 changes: 13 additions & 6 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import chalk from 'chalk';
import { isCI } from 'ci-info';
import { getCwd } from './get-cwd';
import { getVersionCheckers } from './version-checker';
import { getSaveExactChecker } from './save-exact';
import { IOptions, ILogMessage } from './const';
import { getHooksInstalledChecker } from './hooks-installed';
import { splitVersions } from './fetch-options';
import { getExactDependencyVersionsChecker } from './exact-dependency-versions';
import { getHooksInstalledChecker } from './hooks-installed';
import { getNodeLTSChecker } from './lts';
import { getNodeSecurityChecker } from './security';
import { getSaveExactChecker } from './save-exact';
import { getVersionCheckers } from './version-checker';
import { ILogMessage, IOptions } from './const';
import { isCI } from 'ci-info';
import { splitVersions } from './fetch-options';

export interface IApiOptions {
cwd?: string;
versions?: string[];
lts?: boolean;
security?: boolean;
hooksInstalled?: boolean;
saveExact?: boolean;
dependenciesExactVersion?: boolean;
Expand All @@ -24,6 +26,7 @@ export async function api(apiOptions: IApiOptions) {
cwd,
versions: splitVersions(apiOptions.versions),
lts: apiOptions.lts,
security: apiOptions.security,
hooksInstalled: apiOptions.hooksInstalled,
saveExact: apiOptions.saveExact,
dependenciesExactVersion: apiOptions.dependenciesExactVersion,
Expand All @@ -45,6 +48,10 @@ export async function api(apiOptions: IApiOptions) {
checkers.push(getNodeLTSChecker());
}

if (options.security) {
checkers.push(getNodeSecurityChecker());
}

if (options.hooksInstalled) {
checkers.push(getHooksInstalledChecker());
}
Expand Down
1 change: 1 addition & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface IOptions {
cwd?: string;
versions?: string[];
lts?: boolean;
security?: boolean;
hooksInstalled?: boolean;
saveExact?: boolean;
dependenciesExactVersion?: boolean;
Expand Down
3 changes: 3 additions & 0 deletions src/fetch-node-versions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export const getNodeList = async (purpose: string) => {
if (purpose === 'lts') {
return { error: true, text: logMessages.warning.fetchNodeListErrorNodeLTS(nodeVersionListURL) };
}
if (purpose === 'security') {
return { error: true, text: logMessages.warning.fetchNodeListErrorNodeSecurity(nodeVersionListURL) };
}
return { error: true, text: logMessages.warning.fetchNodeListErrorMatchingNPM(nodeVersionListURL) };
}
};
10 changes: 10 additions & 0 deletions src/log-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const logMessages = {
),
nodeVersionLTS: (usedNodeVersion: string) =>
chalk.green(`${logSymbols.success} Your node version ${usedNodeVersion} is a LTS version.`),
nodeVersionSecurity: (usedNodeVersion: string) =>
chalk.green(`${logSymbols.success} Your node version ${usedNodeVersion} is a Security version.`),
programVersionSatisfies: (program: string, usedVersion: string, expectedVersion: string) =>
chalk.green(
`${logSymbols.success} Your ${program} version ${usedVersion} works with the required version (${expectedVersion}) of your project.`
Expand All @@ -26,6 +28,10 @@ export const logMessages = {
chalk.red(
`${logSymbols.error} Change node-version! You are using node ${usedNodeVersion} which is not a LTS (long term support) version.`
),
nodeVersionNotSecurityError: (usedNodeVersion: string) =>
chalk.red(
`${logSymbols.error} Change node-version! You are using node ${usedNodeVersion} which is not a Security version.`
),
wrongNPMVersionError: (usedNodeVersion: string) =>
chalk.red(
`${logSymbols.error} Change npm version! You are using node ${usedNodeVersion}, keep node and npm in sync! https://nodejs.org/dist/index.json`
Expand Down Expand Up @@ -69,5 +75,9 @@ export const logMessages = {
chalk.yellow(
`${logSymbols.warning} Could not fetch node-list from ${nodeVersionListURL}. Your node version might not be a LTS version.`
),
fetchNodeListErrorNodeSecurity: (nodeVersionListURL: string) =>
chalk.yellow(
`${logSymbols.warning} Could not fetch node-list from ${nodeVersionListURL}. Your node version might not be a Security version.`
),
},
};
26 changes: 26 additions & 0 deletions src/security.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getInstalledVersion } from './get-version';
import { getNodeList } from './fetch-node-versions';
import { ILogMessage, INodeVersion } from './const';
import { logMessages } from './log-messages';

export const hasNodeVersionSecurity = (nodeList: INodeVersion[], usedNodeVersion: string) => {
return nodeList.some((nodeVersion) => {
return nodeVersion.version.slice(1) === usedNodeVersion && nodeVersion.security !== false;
});
};

export const getSecurityNodeLog = async (usedNodeVersion: string) => {
const nodeList = await getNodeList('security');
if (nodeList.error) {
return { error: false, text: nodeList.text };
}

return hasNodeVersionSecurity(JSON.parse(nodeList.text), usedNodeVersion)
? { error: false, text: logMessages.success.nodeVersionSecurity(usedNodeVersion) }
: { error: true, text: logMessages.error.nodeVersionNotSecurityError(usedNodeVersion) };
};

export const getNodeSecurityChecker = async () => {
const usedNodeVersion: ILogMessage = await getInstalledVersion('node');
return usedNodeVersion.error ? usedNodeVersion : getSecurityNodeLog(usedNodeVersion.text);
};

0 comments on commit 86096b7

Please sign in to comment.