Skip to content

Commit

Permalink
feat: add binary.skipMD5 and MONGOMS_SKIP_MD5_CHECK environment o…
Browse files Browse the repository at this point in the history
…ptions

* fix: add error handling in postinstall

* feat: add MONGOMS_SKIP_MD5_CHECK for skipping md5 check

* refactor: add return type in checkMd5 signature

Response to the comment #114 (comment)

* refactor: add checkMD5 parameter to the MongoBinaryDownload constructor

For details see #114 (comment)

* refactor: style changes and function renaming

For details see #114 (comment)
and nodkz comment after approving pull request
  • Loading branch information
dimitriylol authored and nodkz committed Dec 7, 2018
1 parent 4f0e7ca commit a72a2f3
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 4 deletions.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -62,6 +62,7 @@ const mongod = new MongoMemoryServer({
platform?: string, // by default os.platform()
arch?: string, // by default os.arch()
debug?: boolean, // by default false
skipMD5?: boolean, // by default false OR process.env.MONGOMS_SKIP_MD5_CHECK
},
debug?: boolean, // by default false
autoStart?: boolean, // by default true
Expand All @@ -76,6 +77,8 @@ MONGOMS_VERSION=3
MONGOMS_DEBUG=1 # also available case-insensitive values: "on" "yes" "true"
MONGOMS_DOWNLOAD_MIRROR=url # your mirror url to download the mongodb binary
MONGOMS_DISABLE_POSTINSTALL=1 # if you want to skip download binaries on `npm i` command
MONGOMS_SKIP_MD5_CHECK=1 # if you want to skip MD5 check of downloaded binary.
# Passed constructor parameter `binary.skipMD5` has higher priority.
```

### Replica Set start:
Expand Down
5 changes: 5 additions & 0 deletions postinstall.js
Expand Up @@ -27,6 +27,11 @@ if (isModuleExists('./lib/util/MongoBinary')) {
console.log('mongodb-memory-server: checking MongoDB binaries cache...');
MongoBinary.getPath({}).then(binPath => {
console.log(`mongodb-memory-server: binary path is ${binPath}`);
})
.catch((err) => {
console.log(`failed to download/install MongoDB binaries. The error:
${err}`)
process.exit(1)
});
} else {
console.log("Can't resolve MongoBinary module");
Expand Down
28 changes: 24 additions & 4 deletions src/util/MongoBinaryDownload.js
Expand Up @@ -18,22 +18,38 @@ export type MongoBinaryDownloadOpts = {
platform: string,
arch: string,
debug?: DebugPropT,
skipMD5?: boolean,
};

export default class MongoBinaryDownload {
debug: DebugFn;
dlProgress: DownloadProgressT;

skipMD5: boolean;
downloadDir: string;
arch: string;
version: string;
platform: string;

constructor({ platform, arch, downloadDir, version, debug }: $Shape<MongoBinaryDownloadOpts>) {
constructor({
platform,
arch,
downloadDir,
version,
skipMD5,
debug,
}: $Shape<MongoBinaryDownloadOpts>) {
this.platform = platform || os.platform();
this.arch = arch || os.arch();
this.version = version || 'latest';
this.downloadDir = path.resolve(downloadDir || 'mongodb-download');
if (skipMD5 === undefined) {
this.skipMD5 =
typeof process.env.MONGOMS_SKIP_MD5_CHECK === 'string' &&
['1', 'on', 'yes', 'true'].indexOf(process.env.MONGOMS_SKIP_MD5_CHECK.toLowerCase()) !== -1;
} else {
this.skipMD5 = skipMD5;
}
this.dlProgress = {
current: 0,
length: 0,
Expand Down Expand Up @@ -84,20 +100,24 @@ export default class MongoBinaryDownload {
const downloadUrl = await mbdUrl.getDownloadUrl();
const mongoDBArchive = await this.download(downloadUrl);

const mongoDBArchiveMd5 = await this.download(`${downloadUrl}.md5`);
await this.checkMd5(mongoDBArchiveMd5, mongoDBArchive);
await this.checkMD5(`${downloadUrl}.md5`, mongoDBArchive);

return mongoDBArchive;
}

async checkMd5(mongoDBArchiveMd5: string, mongoDBArchive: string) {
async checkMD5(urlForReferenceMD5: string, mongoDBArchive: string): Promise<?boolean> {
if (this.skipMD5) {
return undefined;
}
const mongoDBArchiveMd5 = await this.download(urlForReferenceMD5);
const signatureContent = fs.readFileSync(mongoDBArchiveMd5).toString('UTF-8');
const m = signatureContent.match(/(.*?)\s/);
const md5Remote = m ? m[1] : null;
const md5Local = md5File.sync(mongoDBArchive);
if (md5Remote !== md5Local) {
throw new Error('MongoBinaryDownload: md5 check is failed');
}
return true;
}

async download(downloadUrl: string) {
Expand Down
63 changes: 63 additions & 0 deletions src/util/__tests__/MongoBinaryDownload-test.js
@@ -1,8 +1,29 @@
/* @flow */

import fs from 'fs';
import md5file from 'md5-file';
import MongoBinaryDownload from '../MongoBinaryDownload';

jest.mock('fs');
jest.mock('md5-file');

describe('MongoBinaryDownload', () => {
afterEach(() => {
delete process.env.MONGOMS_SKIP_MD5_CHECK;
});

it('skipMD5 attribute can be set via constructor parameter', () => {
expect(new MongoBinaryDownload({ skipMD5: true }).skipMD5).toBe(true);
expect(new MongoBinaryDownload({ skipMD5: false }).skipMD5).toBe(false);
});

it(`if skipMD5 input parameter is missing, then it checks
MONGOMS_SKIP_MD5_CHECK environment variable`, () => {
expect(new MongoBinaryDownload({}).skipMD5).toBe(false);
process.env.MONGOMS_SKIP_MD5_CHECK = '1';
expect(new MongoBinaryDownload({}).skipMD5).toBe(true);
});

it('should use direct download', async () => {
process.env['yarn_https-proxy'] = '';
process.env.yarn_proxy = '';
Expand Down Expand Up @@ -34,4 +55,46 @@ describe('MongoBinaryDownload', () => {
expect(callArg1.agent).toBeDefined();
expect(callArg1.agent.options.href).toBe('http://user:pass@proxy:8080/');
});

it(`checkMD5 returns true if md5 of downloaded mongoDBArchive is
the same as in the reference result`, () => {
const someMd5 = 'md5';
fs.readFileSync.mockImplementationOnce(() => `${someMd5} fileName`);
md5file.sync.mockImplementationOnce(() => someMd5);
const mongoDBArchivePath = '/some/path';
const fileWithReferenceMd5 = '/another/path';
const du = new MongoBinaryDownload({});
// $FlowFixMe
du.download = jest.fn(() => Promise.resolve(fileWithReferenceMd5));
const urlToMongoDBArchivePath = 'some-url';
return du.checkMD5(urlToMongoDBArchivePath, mongoDBArchivePath).then(res => {
expect(res).toBe(true);
expect(du.download).toBeCalledWith(urlToMongoDBArchivePath);
expect(fs.readFileSync).toBeCalledWith(fileWithReferenceMd5);
expect(md5file.sync).toBeCalledWith(mongoDBArchivePath);
});
});

it(`checkMD5 throws an error if md5 of downloaded mongoDBArchive is NOT
the same as in the reference result`, () => {
fs.readFileSync.mockImplementationOnce(() => 'someMd5 fileName');
md5file.sync.mockImplementationOnce(() => 'anotherMd5');
const du = new MongoBinaryDownload({});
// $FlowFixMe
du.download = jest.fn(() => Promise.resolve(''));
expect(du.checkMD5('', '')).rejects.toMatchInlineSnapshot(
`[Error: MongoBinaryDownload: md5 check is failed]`
);
});

it('true value of skipMD5 attribute disables checkMD5 validation', () => {
expect.assertions(1);
fs.readFileSync.mockImplementationOnce(() => 'someMd5 fileName');
md5file.sync.mockImplementationOnce(() => 'anotherMd5');
const du = new MongoBinaryDownload({});
du.skipMD5 = true;
return du.checkMD5('', '').then(res => {
expect(res).toBe(undefined);
});
});
});

0 comments on commit a72a2f3

Please sign in to comment.