Skip to content

Commit fd274c4

Browse files
Merge pull request Human-Connection#59 in HC/hc-api-feathers from feature/NEXT-173 to develop
* commit 'fe9d0fcc0d2c899581f5ab3bdcb41c219e9a406e': NEXT-173 - set logging level NEXT-173 - added cross platform comands with the shx npm module (https://github.com/shelljs/shx) NEXT-173 - fixed eslint NEXT-173 - Shout Component removed default avatar generation make avataaars possible try to harden image seeding
2 parents 950ccf9 + fe9d0fc commit fd274c4

File tree

16 files changed

+385
-44
lines changed

16 files changed

+385
-44
lines changed

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"homepage": "https://human-connection.org",
66
"license": "CC-BY-NC-SA-4.0",
77
"repository": {
8-
"type" : "git",
9-
"url" : "https://github.com/Human-Connection/API.git"
8+
"type": "git",
9+
"url": "https://github.com/Human-Connection/API.git"
1010
},
1111
"main": "server",
1212
"keywords": [
@@ -21,8 +21,8 @@
2121
},
2222
"contributors": [],
2323
"bugs": {
24-
"url" : "https://github.com/Human-Connection/API/issues",
25-
"email" : "[email protected]"
24+
"url": "https://github.com/Human-Connection/API/issues",
25+
"email": "[email protected]"
2626
},
2727
"directories": {
2828
"lib": "server",
@@ -33,7 +33,7 @@
3333
"yarn": ">= 0.18.0"
3434
},
3535
"scripts": {
36-
"clear": "rm -Rf tmp",
36+
"clear": "shx rm -Rf tmp",
3737
"test": "npm run eslint && npm run mocha",
3838
"eslint": "eslint server/. test/. --config .eslintrc.json",
3939
"start": "concurrently 'mongod' 'wait-on tcp:27017 && NODE_ENV=production node server/'",
@@ -78,6 +78,7 @@
7878
"handlebars-layouts": "~3.1.4",
7979
"helmet": "~3.10.0",
8080
"html-excerpt": "~0.1.0",
81+
"mime": "^2.2.0",
8182
"mongoose": "~4.13.2",
8283
"multer": "~1.3.0",
8384
"node-sass": "~4.7.2",
@@ -95,6 +96,7 @@
9596
"eslint": "~4.16.0",
9697
"mocha": "~4.0.1",
9798
"nodemon": "~1.14.11",
99+
"shx": "^0.2.2",
98100
"wait-on": "~2.1.0"
99101
}
100102
}

server/hooks/save-remote-images.js

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ const fs = require('fs');
66
const path = require('path');
77
const request = require('request');
88
const faker = require('faker');
9+
const mime = require('mime/lite');
910

1011
module.exports = function (options = []) { // eslint-disable-line no-unused-vars
1112
return function async (hook) {
1213

13-
return new Promise((resolve) => {
14+
return new Promise((resolve, reject) => {
1415

1516
let urls = [];
1617

@@ -27,33 +28,74 @@ module.exports = function (options = []) { // eslint-disable-line no-unused-vars
2728

2829
// save all given fields and update the hook data
2930
options.forEach((field) => {
30-
if (!hook.data[field] || hook.data[field].search(uploadsUrl) >= 0) {
31+
if (!hook.data[field] || (typeof hook.data[field] === 'string' && hook.data[field].search(uploadsUrl) >= 0)) {
3132
// skip invalid and local data
3233
return;
3334
}
3435
loading++;
3536
imgCount++;
3637
// TODO: fix that to use the data _id or somethink similar
3738
let uuid = faker.fake('{{random.uuid}}');
38-
const imgName = `${field}_${uuid}.jpg`;
39-
const imgPath = path.resolve('public', 'uploads/' + imgName);
40-
let stream = fs.createWriteStream(imgPath);
41-
urls.push(imgPath);
42-
stream.on('close', () => {
43-
if (--loading <= 0) {
44-
hook.app.debug('Download(s) finished', imgName);
45-
resolve(hook);
46-
} else {
47-
hook.app.debug('Download finished', imgName);
39+
const imgName = `${field}_${uuid}`;
40+
let imgPath = path.resolve('public', 'uploads/' + imgName);
41+
42+
if (typeof hook.data[field] === 'object') {
43+
try {
44+
hook.app.debug('SAVE REMOTE IMAGES HOOK');
45+
hook.app.debug(typeof hook.data[field]);
46+
47+
fs.writeFileSync(`${imgPath}.png`, hook.data[field], {
48+
encoding: 'binary'
49+
});
50+
loading--;
51+
hook.data[field] = uploadsUrl + imgName + '.png';
52+
53+
if (imgCount > 0 && loading <= 0) {
54+
hook.app.debug('Download(s) finished', urls);
55+
resolve(hook);
56+
}
57+
} catch (err) {
58+
hook.app.error(err);
4859
}
49-
});
50-
stream.on('error', (err) => {
51-
// reject(err);
52-
throw new errors.Unprocessable('Thumbnail download failed', { errors: err, urls: urls });
53-
});
60+
} else {
61+
request({
62+
url: hook.data[field],
63+
encoding: null
64+
}, (err, res, body) => {
65+
if (err) {
66+
hook.app.error(err);
67+
reject(err);
68+
}
69+
try {
70+
const mimeType = res.headers['content-type'];
71+
if (mimeType.indexOf('image') !== 0) {
72+
hook.app.error('its not an image');
73+
reject('its not an image');
74+
}
75+
76+
const ext = mime.getExtension(mimeType);
77+
78+
imgPath += `.${ext}`;
79+
80+
fs.writeFileSync(imgPath, body, {
81+
encoding: 'binary'
82+
});
83+
84+
loading--;
85+
86+
hook.data[field] = uploadsUrl + imgName + `.${ext}`;
87+
88+
if (imgCount > 0 && loading <= 0) {
89+
hook.app.debug('Download(s) finished', urls);
90+
resolve(hook);
91+
}
92+
} catch (err) {
93+
hook.app.error(err);
94+
}
95+
});
96+
}
97+
5498
hook.app.debug('Downloading', hook.data[field]);
55-
request(hook.data[field]).pipe(stream);
56-
hook.data[field] = uploadsUrl + imgName;
5799
});
58100

59101
if (imgCount > 0 && loading <= 0) {

server/logger.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
const { createLogger, format, transports } = require('winston');
2+
const env = process.env.NODE_ENV;
23

34
const logger = createLogger({
4-
level: 'info',
5+
level: 'warn',
56
format: format.json(),
67
transports: [
78
new transports.File({ filename: './data/error.log', level: 'error' }),
89
new transports.File({ filename: './data/combined.log' })
910
]
1011
});
11-
// if (process.env.NODE_ENV !== 'production') {
1212
logger.add(new transports.Console({
1313
format: format.combine(
1414
format.printf((info) => {
@@ -22,8 +22,6 @@ logger.add(new transports.Console({
2222
return `${levelColors[info.level]}${date.toLocaleTimeString()} | ${info.level}: ${JSON.stringify(info.message)}\u001b[39m`;
2323
})
2424
),
25-
level: 'debug'
25+
level: env === 'development' ? 'debug' : 'warn'
2626
}));
27-
// }
28-
2927
module.exports = logger;

server/models/contributions.model.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module.exports = function (app) {
2727
contentExcerpt: { type: String, required: true },
2828
teaserImg: { type: String },
2929
language: { type: String, required: true },
30-
shouts: { type: Array },
30+
shoutCount: { type: Number, default: 0 },
3131
visibility: {
3232
type: String,
3333
enum: ['public', 'friends', 'private'],

server/models/shouts.model.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// users-shouts-model.js - A mongoose model
2+
//
3+
// See http://mongoosejs.com/docs/models.html
4+
// for more of what you can do here.
5+
module.exports = function (app) {
6+
const mongooseClient = app.get('mongooseClient');
7+
const shouts = new mongooseClient.Schema({
8+
userId: { type: String, required: true, index: true },
9+
foreignId: { type: String, required: true, index: true },
10+
foreignService: { type: String, required: true, index: true },
11+
createdAt: { type: Date, default: Date.now },
12+
wasSeeded: { type: Boolean }
13+
});
14+
15+
shouts.index(
16+
{ userId: 1, foreignId: 1 },
17+
{ unique: true }
18+
);
19+
20+
return mongooseClient.model('shouts', shouts);
21+
};

server/seeder/development/contributions.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const seedHelpers = require('../../helper/seed-helpers');
2-
const { size } = require('lodash');
32

43
module.exports = (seederstore) => {
54
return {
@@ -15,7 +14,6 @@ module.exports = (seederstore) => {
1514
content: '{{lorem.text}} {{lorem.text}}',
1615
teaserImg: seedHelpers.randomUnsplashUrl,
1716
language: () => seedHelpers.randomItem(['de', 'en']),
18-
shouts: () => seedHelpers.randomItems(seederstore.users, '_id', 0, Math.floor(size(seederstore.users) / 2)),
1917
visibility: 'public',
2018
createdAt: '{{date.recent}}',
2119
updatedAt: '{{date.recent}}',
@@ -28,7 +26,6 @@ module.exports = (seederstore) => {
2826
categoryIds: () => seedHelpers.randomCategories(seederstore),
2927
content: '{{lorem.text}} {{lorem.text}}',
3028
language: () => seedHelpers.randomItem(['de', 'en']),
31-
shouts: () => seedHelpers.randomItems(seederstore.users, '_id', 0, Math.floor(size(seederstore.users) / 2)),
3229
visibility: 'public',
3330
createdAt: '{{date.recent}}',
3431
updatedAt: '{{date.recent}}',
@@ -41,7 +38,6 @@ module.exports = (seederstore) => {
4138
categoryIds: () => seedHelpers.randomCategories(seederstore),
4239
content: '{{lorem.text}} {{lorem.text}}',
4340
language: () => seedHelpers.randomItem(['de', 'en']),
44-
shouts: () => seedHelpers.randomItems(seederstore.users, '_id', 0, Math.floor(size(seederstore.users) / 2)),
4541
visibility: 'public',
4642
isEnabled: false,
4743
createdAt: '{{date.recent}}',

server/seeder/development/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module.exports = function () {
1414
require('./follows'),
1515
require('./comments'),
1616
require('./emotions'),
17-
require('./invites')
17+
require('./invites'),
18+
require('./shouts')
1819
];
1920
};

server/seeder/development/shouts.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const seedHelpers = require('../../helper/seed-helpers');
2+
3+
module.exports = (seederstore) => {
4+
return {
5+
services: [{
6+
count: 240,
7+
path: 'shouts',
8+
templates: [
9+
{
10+
userId: () => seedHelpers.randomItem(seederstore.users)._id,
11+
foreignId: () => seedHelpers.randomItem(seederstore.contributions)._id,
12+
foreignService: 'contributions',
13+
wasSeeded: true
14+
}
15+
]
16+
}]
17+
};
18+
};

server/services/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const emotions = require('./emotions/emotions.service.js');
1313
const organizations = require('./organizations/organizations.service.js');
1414
const projects = require('./projects/projects.service.js');
1515
const follows = require('./follows/follows.service.js');
16+
const shouts = require('./shouts/shouts.service.js');
1617
const admin = require('./admin/admin.service.js');
1718
const invites = require('./invites/invites.service.js');
1819
const usersCandos = require('./users-candos/users-candos.service.js');
@@ -34,6 +35,7 @@ module.exports = function () {
3435
app.configure(organizations);
3536
app.configure(projects);
3637
app.configure(follows);
38+
app.configure(shouts);
3739
app.configure(admin);
3840
app.configure(usersCandos);
3941
app.configure(invites);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Set done date, when cando is done
2+
module.exports = () => async hook => {
3+
4+
// get count of all shouts on this thing
5+
const shoutCount = await hook.app.service('shouts').find({
6+
query: {
7+
foreignService: hook.result.foreignService,
8+
foreignId: hook.result.foreignId,
9+
$limit: 0
10+
}
11+
});
12+
13+
// update the shoud count on the foreign service
14+
await hook.app.service(hook.result.foreignService)
15+
.patch(hook.result.foreignId, {
16+
$set: {
17+
shoutCount: shoutCount.total
18+
}
19+
});
20+
21+
return hook;
22+
};

0 commit comments

Comments
 (0)