Skip to content

Commit 035ad46

Browse files
committed
Updated changelog [ci skip]
2 parents d5f4dd9 + 87084f6 commit 035ad46

File tree

11 files changed

+125
-40
lines changed

11 files changed

+125
-40
lines changed

.env.example

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,5 +193,10 @@ FS_REPO=local
193193
########
194194

195195
# Location of virus scanning binary (ClamAV - https://www.clamav.net/)
196+
<<<<<<< HEAD
196197
#CLAMSCAN_BINARY=/usr/bin/clamscan
197-
RESTRICT_CREATE_ORGANISATION=true
198+
RESTRICT_CREATE_ORGANISATION=true
199+
=======
200+
#CLAMDSCAN_BINARY=/usr/bin/clamdscan
201+
#CLAMDSCAN_CONF=/etc/clamav/clamd.conf
202+
>>>>>>> origin/release/v2.2.5

CHANGELOG.md

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,27 @@ Format based on [Keep a Changelog](http://keepachangelog.com/)
1111

1212
## [2.3.0]
1313
### Added
14-
- Multiple shareable links per dashboard
15-
- Requires migration to be run
16-
- Aggregations now can read from secondary members on replica set
17-
- Sentinel Redis support
18-
- New role to allow organisation creation (via site admin)
14+
- Multiple shareable links per dashboard (#1096)
15+
- Requires migration to be run - `yarn migrate`
16+
- Aggregations now can read from secondary members on replica set (#1095)
17+
- Sentinel Redis support (#1119)
18+
- New role to allow organisation creation (via site admin) (#1110)
19+
- Widgets now auto pick visualisation name when populated (#1126)
1920
### Security
20-
- Passwords can only be changed for the user logged in or by site admins
21+
- Passwords can only be changed for the user logged in or by site admins (#1112)
2122
### Fixes
22-
- Unicode data now pulled from dependency
23-
- Ensure order on personaIdentifier IFI values (fixes issue with multiple personaIdents for the same actor)
23+
- Unicode data now pulled from dependency (#1125)
24+
- Ensure order on personaIdentifier IFI values (fixes issue with multiple personaIdents for the same actor) (#1120)
2425
- Fix for personaIdentifier migration
26+
- Client can select more than 10 xAPI stores (#1130)
27+
- Server side validation of Statement Forward queries (#1138)
28+
- Statement forwards decode `&46;` in statement keys (#1134)
29+
- Persona Attribute and Identifier APIs now parse $oid values for `persona` filters (#1133)
30+
- Fixed issue with hanging file imports on persona data
31+
- Switch to `clamdscan` as primary AV scanner
32+
- Requires updated .env settings - refer to .env.example
2533
### Performance and build
26-
- Webpack 3
34+
- Webpack 3 - improved build speed (#1094)
2735
### Migrations
2836
**This update requires a migration which can be run using `yarn migrate`.**
2937

lib/helpers/getDateFromMongoID.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import isString from 'lodash/isString';
2+
3+
export default (_id) => {
4+
if (!isString(_id) || _id.length !== 24) {
5+
// not a mongo id
6+
throw Error('Not a Mongo ID');
7+
}
8+
const timehex = _id.substring(0, 8);
9+
10+
// convert to a number... base 16
11+
const secondsSinceEpoch = parseInt(timehex, 16);
12+
if (isNaN(secondsSinceEpoch)) {
13+
throw Error('Invalid date in Mongo ID');
14+
}
15+
16+
// convert to milliseconds, and create a new date
17+
return new Date(secondsSinceEpoch * 1000);
18+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { expect } from 'chai';
2+
import getDateFromMongoID from '../getDateFromMongoID';
3+
4+
const _id = '5ad52af00000000000000000';
5+
describe('getDateFromMongoID', () => {
6+
it('should return date for Mongo ID as string', () => {
7+
const date = getDateFromMongoID(_id);
8+
const expectedDate = new Date('2018-04-16T23:00:00');
9+
expect(date.getTime()).to.equal(expectedDate.getTime());
10+
});
11+
12+
it('should error when _id is not a string', () => {
13+
expect(getDateFromMongoID.bind(null, 123)).to.throw(Error);
14+
expect(getDateFromMongoID.bind(null, false)).to.throw(Error);
15+
expect(getDateFromMongoID.bind(null, undefined)).to.throw(Error);
16+
expect(getDateFromMongoID.bind(null, null)).to.throw(Error);
17+
expect(getDateFromMongoID.bind(null, {})).to.throw(Error);
18+
expect(getDateFromMongoID.bind(null, [])).to.throw(Error);
19+
});
20+
21+
it('should error when _id is not 24 chars', () => {
22+
expect(getDateFromMongoID.bind(null, 'abc')).to.throw(Error);
23+
expect(getDateFromMongoID.bind(null, `${_id}0`)).to.throw(Error);
24+
});
25+
26+
it('should error when _id does not contain a valid hex date', () => {
27+
expect(getDateFromMongoID.bind(null, 'Zad52af00000000000000000')).to.throw(Error);
28+
});
29+
});

lib/models/statementForwarding.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,15 @@ const schema = new mongoose.Schema({
166166
query: {
167167
type: String,
168168
validate: {
169-
validator: value => {
169+
validator: (value) => {
170170
try {
171171
JSON.parse(value);
172172
} catch (err) {
173173
return false;
174174
}
175175
return true;
176176
},
177-
message: "Invalid query"
177+
message: 'Invalid query'
178178
}
179179
},
180180
isPublic: { type: Boolean, default: false }

lib/services/files/clamscan.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
11
import Promise from 'bluebird';
22
import logger from 'lib/logger';
3+
import defaultTo from 'lodash/defaultTo';
34

4-
const scanError = err => (
5-
new Error(`Something went wrong when scanning the file. ${err.message}`)
6-
);
75
const virusError = () => (
86
new Error('This file has not passed the virus scan and will be deleted.')
97
);
108
export default filePath => new Promise((resolve, reject) => {
11-
if (!process.env.CLAMSCAN_BINARY) {
12-
logger.warn('CLAMSCAN NOT INSTALLED, SEE DOCS FOR FURTHER INFORMATION.');
9+
if (!process.env.CLAMDSCAN_BINARY) {
10+
logger.warn('CLAMDSCAN NOT INSTALLED, SEE DOCS FOR FURTHER INFORMATION.');
1311
return resolve(filePath);
1412
}
1513
try {
1614
const clam = require('clamscan')({
1715
remove_infected: true,
18-
clamscan: {
19-
path: process.env.CLAMSCAN_BINARY,
16+
clamdscan: {
17+
path: process.env.CLAMDSCAN_BINARY,
18+
config_file: defaultTo(process.env.CLAMDSCAN_CONF, '/etc/clamav/clamd.conf')
2019
},
21-
preference: 'clamscan',
20+
preference: 'clamdscan',
2221
});
2322

2423
clam.is_infected(filePath, (err, file, isInfected) => {
25-
if (err) return reject(scanError(err));
24+
if (err) {
25+
logger.warn('ERROR SCANNING FILE WITH CLAMD - ', err);
26+
return resolve(filePath);
27+
}
2628
if (isInfected) return reject(virusError());
2729
return resolve(filePath);
2830
});
2931
} catch (err) {
30-
return reject(scanError(err));
32+
logger.warn('ERROR SCANNING FILE WITH CLAMD - ', err);
33+
return resolve(filePath);
3134
}
3235
});

lib/services/importPersonas/getCsvHeaders.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
1-
import * as fileService from 'lib/services/files';
21
import csv from 'fast-csv';
32
import { isUndefined, uniq } from 'lodash';
43
import EmptyCsvError from 'lib/errors/EmptyCsvError';
54
import DuplicateCsvHeadersError from 'lib/errors/DuplicateCsvHeadersError';
65

7-
const getCsvHeaders = async (handle) => {
8-
const csvStream = csv.parse({
6+
const getCsvHeaders = async (fileStream) => {
7+
const csvStreamHandler = csv.parse({
98
headers: false,
109
quoteHeaders: true
1110
});
1211

1312
// read the first row.
1413
let headers;
1514

16-
csvStream.on('data', (data) => {
15+
csvStreamHandler.on('data', (data) => {
1716
// we're just interested in the first one.
1817
if (isUndefined(headers)) headers = data;
1918
});
2019

2120
const csvPromise = new Promise((resolve, reject) => {
22-
csvStream.on('error', reject);
23-
csvStream.on('finish', resolve);
21+
csvStreamHandler.on('error', reject);
22+
csvStreamHandler.on('finish', resolve);
2423
});
2524

26-
fileService.downloadToStream(handle)(csvStream);
25+
fileStream.pipe(csvStreamHandler);
2726

2827
await csvPromise;
2928

lib/services/importPersonas/persistPersonas.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'fs';
22
import clamscan from 'lib/services/files/clamscan';
33
import { uploadFromStream } from 'lib/services/files/storage';
44

5-
export const PERSONAS_CSV_PATH = '/personasCsvs';
5+
export const PERSONAS_CSV_PATH = 'personasCsvs';
66

77
export default async ({
88
file,

lib/services/importPersonas/uploadPersonas.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import fs from 'fs';
12
import persistPersonas from 'lib/services/importPersonas/persistPersonas';
23
import PersonasImport from 'lib/models/personasImport';
34
import { STAGE_CONFIGURE_FIELDS } from 'lib/constants/personasImport';
@@ -29,7 +30,10 @@ const uploadPersonas = async ({
2930
id
3031
});
3132

32-
const csvHeaders = await getCsvHeaders(handle);
33+
// instead of going back out to s3, use the local file we already have!
34+
const filePath = file.path;
35+
const fileStream = fs.createReadStream(filePath);
36+
const csvHeaders = await getCsvHeaders(fileStream);
3337

3438
const structure = await getStructure({
3539
csvHeaders,
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import moment from 'moment';
22

3-
export default createdAt =>
4-
`Created ${moment(createdAt).fromNow()} - ${moment(createdAt).format('YYYY-MM-DD HH:mm:ss')}`;
3+
export default (createdAt) => {
4+
if (!createdAt) return '';
5+
return `Created ${moment(createdAt).fromNow()} - ${moment(createdAt).format('YYYY-MM-DD HH:mm:ss')}`;
6+
};

0 commit comments

Comments
 (0)