Skip to content

Commit a72a2f3

Browse files
dimitriylolnodkz
authored andcommitted
feat: add binary.skipMD5 and MONGOMS_SKIP_MD5_CHECK environment options
* 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
1 parent 4f0e7ca commit a72a2f3

File tree

4 files changed

+95
-4
lines changed

4 files changed

+95
-4
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ const mongod = new MongoMemoryServer({
6262
platform?: string, // by default os.platform()
6363
arch?: string, // by default os.arch()
6464
debug?: boolean, // by default false
65+
skipMD5?: boolean, // by default false OR process.env.MONGOMS_SKIP_MD5_CHECK
6566
},
6667
debug?: boolean, // by default false
6768
autoStart?: boolean, // by default true
@@ -76,6 +77,8 @@ MONGOMS_VERSION=3
7677
MONGOMS_DEBUG=1 # also available case-insensitive values: "on" "yes" "true"
7778
MONGOMS_DOWNLOAD_MIRROR=url # your mirror url to download the mongodb binary
7879
MONGOMS_DISABLE_POSTINSTALL=1 # if you want to skip download binaries on `npm i` command
80+
MONGOMS_SKIP_MD5_CHECK=1 # if you want to skip MD5 check of downloaded binary.
81+
# Passed constructor parameter `binary.skipMD5` has higher priority.
7982
```
8083

8184
### Replica Set start:

postinstall.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ if (isModuleExists('./lib/util/MongoBinary')) {
2727
console.log('mongodb-memory-server: checking MongoDB binaries cache...');
2828
MongoBinary.getPath({}).then(binPath => {
2929
console.log(`mongodb-memory-server: binary path is ${binPath}`);
30+
})
31+
.catch((err) => {
32+
console.log(`failed to download/install MongoDB binaries. The error:
33+
${err}`)
34+
process.exit(1)
3035
});
3136
} else {
3237
console.log("Can't resolve MongoBinary module");

src/util/MongoBinaryDownload.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,38 @@ export type MongoBinaryDownloadOpts = {
1818
platform: string,
1919
arch: string,
2020
debug?: DebugPropT,
21+
skipMD5?: boolean,
2122
};
2223

2324
export default class MongoBinaryDownload {
2425
debug: DebugFn;
2526
dlProgress: DownloadProgressT;
2627

28+
skipMD5: boolean;
2729
downloadDir: string;
2830
arch: string;
2931
version: string;
3032
platform: string;
3133

32-
constructor({ platform, arch, downloadDir, version, debug }: $Shape<MongoBinaryDownloadOpts>) {
34+
constructor({
35+
platform,
36+
arch,
37+
downloadDir,
38+
version,
39+
skipMD5,
40+
debug,
41+
}: $Shape<MongoBinaryDownloadOpts>) {
3342
this.platform = platform || os.platform();
3443
this.arch = arch || os.arch();
3544
this.version = version || 'latest';
3645
this.downloadDir = path.resolve(downloadDir || 'mongodb-download');
46+
if (skipMD5 === undefined) {
47+
this.skipMD5 =
48+
typeof process.env.MONGOMS_SKIP_MD5_CHECK === 'string' &&
49+
['1', 'on', 'yes', 'true'].indexOf(process.env.MONGOMS_SKIP_MD5_CHECK.toLowerCase()) !== -1;
50+
} else {
51+
this.skipMD5 = skipMD5;
52+
}
3753
this.dlProgress = {
3854
current: 0,
3955
length: 0,
@@ -84,20 +100,24 @@ export default class MongoBinaryDownload {
84100
const downloadUrl = await mbdUrl.getDownloadUrl();
85101
const mongoDBArchive = await this.download(downloadUrl);
86102

87-
const mongoDBArchiveMd5 = await this.download(`${downloadUrl}.md5`);
88-
await this.checkMd5(mongoDBArchiveMd5, mongoDBArchive);
103+
await this.checkMD5(`${downloadUrl}.md5`, mongoDBArchive);
89104

90105
return mongoDBArchive;
91106
}
92107

93-
async checkMd5(mongoDBArchiveMd5: string, mongoDBArchive: string) {
108+
async checkMD5(urlForReferenceMD5: string, mongoDBArchive: string): Promise<?boolean> {
109+
if (this.skipMD5) {
110+
return undefined;
111+
}
112+
const mongoDBArchiveMd5 = await this.download(urlForReferenceMD5);
94113
const signatureContent = fs.readFileSync(mongoDBArchiveMd5).toString('UTF-8');
95114
const m = signatureContent.match(/(.*?)\s/);
96115
const md5Remote = m ? m[1] : null;
97116
const md5Local = md5File.sync(mongoDBArchive);
98117
if (md5Remote !== md5Local) {
99118
throw new Error('MongoBinaryDownload: md5 check is failed');
100119
}
120+
return true;
101121
}
102122

103123
async download(downloadUrl: string) {

src/util/__tests__/MongoBinaryDownload-test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,29 @@
11
/* @flow */
22

3+
import fs from 'fs';
4+
import md5file from 'md5-file';
35
import MongoBinaryDownload from '../MongoBinaryDownload';
46

7+
jest.mock('fs');
8+
jest.mock('md5-file');
9+
510
describe('MongoBinaryDownload', () => {
11+
afterEach(() => {
12+
delete process.env.MONGOMS_SKIP_MD5_CHECK;
13+
});
14+
15+
it('skipMD5 attribute can be set via constructor parameter', () => {
16+
expect(new MongoBinaryDownload({ skipMD5: true }).skipMD5).toBe(true);
17+
expect(new MongoBinaryDownload({ skipMD5: false }).skipMD5).toBe(false);
18+
});
19+
20+
it(`if skipMD5 input parameter is missing, then it checks
21+
MONGOMS_SKIP_MD5_CHECK environment variable`, () => {
22+
expect(new MongoBinaryDownload({}).skipMD5).toBe(false);
23+
process.env.MONGOMS_SKIP_MD5_CHECK = '1';
24+
expect(new MongoBinaryDownload({}).skipMD5).toBe(true);
25+
});
26+
627
it('should use direct download', async () => {
728
process.env['yarn_https-proxy'] = '';
829
process.env.yarn_proxy = '';
@@ -34,4 +55,46 @@ describe('MongoBinaryDownload', () => {
3455
expect(callArg1.agent).toBeDefined();
3556
expect(callArg1.agent.options.href).toBe('http://user:pass@proxy:8080/');
3657
});
58+
59+
it(`checkMD5 returns true if md5 of downloaded mongoDBArchive is
60+
the same as in the reference result`, () => {
61+
const someMd5 = 'md5';
62+
fs.readFileSync.mockImplementationOnce(() => `${someMd5} fileName`);
63+
md5file.sync.mockImplementationOnce(() => someMd5);
64+
const mongoDBArchivePath = '/some/path';
65+
const fileWithReferenceMd5 = '/another/path';
66+
const du = new MongoBinaryDownload({});
67+
// $FlowFixMe
68+
du.download = jest.fn(() => Promise.resolve(fileWithReferenceMd5));
69+
const urlToMongoDBArchivePath = 'some-url';
70+
return du.checkMD5(urlToMongoDBArchivePath, mongoDBArchivePath).then(res => {
71+
expect(res).toBe(true);
72+
expect(du.download).toBeCalledWith(urlToMongoDBArchivePath);
73+
expect(fs.readFileSync).toBeCalledWith(fileWithReferenceMd5);
74+
expect(md5file.sync).toBeCalledWith(mongoDBArchivePath);
75+
});
76+
});
77+
78+
it(`checkMD5 throws an error if md5 of downloaded mongoDBArchive is NOT
79+
the same as in the reference result`, () => {
80+
fs.readFileSync.mockImplementationOnce(() => 'someMd5 fileName');
81+
md5file.sync.mockImplementationOnce(() => 'anotherMd5');
82+
const du = new MongoBinaryDownload({});
83+
// $FlowFixMe
84+
du.download = jest.fn(() => Promise.resolve(''));
85+
expect(du.checkMD5('', '')).rejects.toMatchInlineSnapshot(
86+
`[Error: MongoBinaryDownload: md5 check is failed]`
87+
);
88+
});
89+
90+
it('true value of skipMD5 attribute disables checkMD5 validation', () => {
91+
expect.assertions(1);
92+
fs.readFileSync.mockImplementationOnce(() => 'someMd5 fileName');
93+
md5file.sync.mockImplementationOnce(() => 'anotherMd5');
94+
const du = new MongoBinaryDownload({});
95+
du.skipMD5 = true;
96+
return du.checkMD5('', '').then(res => {
97+
expect(res).toBe(undefined);
98+
});
99+
});
37100
});

0 commit comments

Comments
 (0)