Skip to content

Commit d53154a

Browse files
authored
Remove old mailer and add Redis based queue system (#736)
* Add BullMQ and send mails to redis queue * Skip tests for now * Include new mailer und configuration * Fix mail tests * Log addition to queue * Fix lint errors
1 parent 3a25e4b commit d53154a

File tree

10 files changed

+483
-284
lines changed

10 files changed

+483
-284
lines changed

docker-compose.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,3 @@ services:
1616
- ./.scripts/mongodb/osem_admin.sh:/docker-entrypoint-initdb.d/osem_admin.sh
1717
# - ./.scripts/mongodb/osem_seed_boxes.sh:/docker-entrypoint-initdb.d/osem_seed_boxes.sh
1818
# - ./.scripts/mongodb/osem_seed_measurements.sh:/docker-entrypoint-initdb.d/osem_seed_measurements.sh
19-

packages/api/lib/controllers/usersController.js

Lines changed: 104 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,19 @@
22

33
const { User } = require('@sensebox/opensensemap-api-models'),
44
{ InternalServerError, ForbiddenError } = require('restify-errors'),
5-
{ checkContentType, redactEmail, clearCache, postToMattermost } = require('../helpers/apiUtils'),
5+
{
6+
checkContentType,
7+
redactEmail,
8+
clearCache,
9+
postToMattermost,
10+
} = require('../helpers/apiUtils'),
611
{ retrieveParameters } = require('../helpers/userParamHelpers'),
712
handleError = require('../helpers/errorHandler'),
8-
{ createToken, refreshJwt, invalidateToken } = require('../helpers/jwtHelpers');
13+
{
14+
createToken,
15+
refreshJwt,
16+
invalidateToken,
17+
} = require('../helpers/jwtHelpers');
918

1019
/**
1120
* define for nested user parameter for box creation request
@@ -47,16 +56,27 @@ const registerUser = async function registerUser (req, res) {
4756
const { email, password, language, name } = req._userParams;
4857

4958
try {
50-
const newUser = await new User({ name, email, password, language })
51-
.save();
52-
postToMattermost(`New User: ${newUser.name} (${redactEmail(newUser.email)})`);
59+
const newUser = await new User({ name, email, password, language }).save();
60+
postToMattermost(
61+
`New User: ${newUser.name} (${redactEmail(newUser.email)})`
62+
);
5363

5464
try {
5565
const { token, refreshToken } = await createToken(newUser);
5666

57-
return res.send(201, { code: 'Created', message: 'Successfully registered new user', data: { user: newUser }, token, refreshToken });
67+
return res.send(201, {
68+
code: 'Created',
69+
message: 'Successfully registered new user',
70+
data: { user: newUser },
71+
token,
72+
refreshToken,
73+
});
5874
} catch (err) {
59-
return Promise.reject(new InternalServerError(`User successfully created but unable to create jwt token: ${err.message}`));
75+
return Promise.reject(
76+
new InternalServerError(
77+
`User successfully created but unable to create jwt token: ${err.message}`
78+
)
79+
);
6080
}
6181
} catch (err) {
6282
return handleError(err);
@@ -82,18 +102,26 @@ const signIn = async function signIn (req, res) {
82102

83103
try {
84104
// lowercase for email
85-
const user = await User
86-
.findOne({ $or: [{ email: emailOrName.toLowerCase() }, { name: emailOrName }] })
87-
.exec();
105+
const user = await User.findOne({
106+
$or: [{ email: emailOrName.toLowerCase() }, { name: emailOrName }],
107+
}).exec();
88108

89109
if (!user) {
90-
return Promise.reject(new ForbiddenError('User and or password not valid!'));
110+
return Promise.reject(
111+
new ForbiddenError('User and or password not valid!')
112+
);
91113
}
92114

93115
if (await user.checkPassword(password)) {
94116
const { token, refreshToken } = await createToken(user);
95117

96-
return res.send(200, { code: 'Authorized', message: 'Successfully signed in', data: { user }, token, refreshToken });
118+
return res.send(200, {
119+
code: 'Authorized',
120+
message: 'Successfully signed in',
121+
data: { user },
122+
token,
123+
refreshToken,
124+
});
97125
}
98126
} catch (err) {
99127
if (err.name === 'ModelError' && err.message === 'Password incorrect') {
@@ -119,8 +147,16 @@ const signIn = async function signIn (req, res) {
119147
*/
120148
const refreshJWT = async function refreshJWT (req, res) {
121149
try {
122-
const { token, refreshToken, user } = await refreshJwt(req._userParams.token);
123-
res.send(200, { code: 'Authorized', message: 'Successfully refreshed auth', data: { user }, token, refreshToken });
150+
const { token, refreshToken, user } = await refreshJwt(
151+
req._userParams.token
152+
);
153+
res.send(200, {
154+
code: 'Authorized',
155+
message: 'Successfully refreshed auth',
156+
data: { user },
157+
token,
158+
refreshToken,
159+
});
124160
} catch (err) {
125161
return handleError(err);
126162
}
@@ -174,7 +210,11 @@ const requestResetPassword = async function requestResetPassword (req, res) {
174210
const resetPassword = async function resetPassword (req, res) {
175211
try {
176212
await User.resetPassword(req._userParams);
177-
res.send(200, { code: 'Ok', message: 'Password successfully changed. You can now login with your new password' });
213+
res.send(200, {
214+
code: 'Ok',
215+
message:
216+
'Password successfully changed. You can now login with your new password',
217+
});
178218
} catch (err) {
179219
return handleError(err);
180220
}
@@ -193,7 +233,10 @@ const resetPassword = async function resetPassword (req, res) {
193233
const confirmEmailAddress = async function confirmEmailAddress (req, res) {
194234
try {
195235
await User.confirmEmail(req._userParams);
196-
res.send(200, { code: 'Ok', message: 'E-Mail successfully confirmed. Thank you' });
236+
res.send(200, {
237+
code: 'Ok',
238+
message: 'E-Mail successfully confirmed. Thank you',
239+
});
197240
} catch (err) {
198241
return handleError(err);
199242
}
@@ -211,7 +254,10 @@ const getUserBoxes = async function getUserBoxes (req, res) {
211254
try {
212255
const boxes = await req.user.getBoxes();
213256
const sharedBoxes = await req.user.getSharedBoxes();
214-
res.send(200, { code: 'Ok', data: { boxes: boxes, sharedBoxes: sharedBoxes } });
257+
res.send(200, {
258+
code: 'Ok',
259+
data: { boxes: boxes, sharedBoxes: sharedBoxes },
260+
});
215261
} catch (err) {
216262
return handleError(err);
217263
}
@@ -242,15 +288,23 @@ const getUser = async function getUser (req, res) {
242288
*/
243289
const updateUser = async function updateUser (req, res) {
244290
try {
245-
const { updated, signOut, messages, updatedUser } = await req.user.updateUser(req._userParams);
291+
const { updated, signOut, messages, updatedUser } =
292+
await req.user.updateUser(req._userParams);
246293
if (updated === false) {
247-
return res.send(200, { code: 'Ok', message: 'No changed properties supplied. User remains unchanged.' });
294+
return res.send(200, {
295+
code: 'Ok',
296+
message: 'No changed properties supplied. User remains unchanged.',
297+
});
248298
}
249299

250300
if (signOut === true) {
251301
invalidateToken(req);
252302
}
253-
res.send(200, { code: 'Ok', message: `User successfully saved.${messages.join('.')}`, data: { me: updatedUser } });
303+
res.send(200, {
304+
code: 'Ok',
305+
message: `User successfully saved.${messages.join('.')}`,
306+
data: { me: updatedUser },
307+
});
254308
} catch (err) {
255309
return handleError(err);
256310
}
@@ -273,9 +327,14 @@ const deleteUser = async function deleteUser (req, res) {
273327
invalidateToken(req);
274328

275329
await req.user.destroyUser();
276-
res.send(200, { code: 'Ok', message: 'User and all boxes of user marked for deletion. Bye Bye!' });
330+
res.send(200, {
331+
code: 'Ok',
332+
message: 'User and all boxes of user marked for deletion. Bye Bye!',
333+
});
277334
clearCache(['getBoxes', 'getStats']);
278-
postToMattermost(`User deleted: ${req.user.name} (${redactEmail(req.user.email)})`);
335+
postToMattermost(
336+
`User deleted: ${req.user.name} (${redactEmail(req.user.email)})`
337+
);
279338
} catch (err) {
280339
return handleError(err);
281340
}
@@ -290,14 +349,20 @@ const deleteUser = async function deleteUser (req, res) {
290349
* @apiSuccess {String} code `Ok`
291350
* @apiSuccess {String} message `Email confirmation has been sent to <emailaddress>`
292351
*/
293-
const requestEmailConfirmation = async function requestEmailConfirmation (req, res) {
352+
const requestEmailConfirmation = async function requestEmailConfirmation (
353+
req,
354+
res
355+
) {
294356
try {
295357
const result = await req.user.resendEmailConfirmation();
296358
let usedAddress = result.email;
297359
if (result.unconfirmedEmail) {
298360
usedAddress = result.unconfirmedEmail;
299361
}
300-
res.send(200, { code: 'Ok', message: `Email confirmation has been sent to ${usedAddress}` });
362+
res.send(200, {
363+
code: 'Ok',
364+
message: `Email confirmation has been sent to ${usedAddress}`,
365+
});
301366
} catch (err) {
302367
return handleError(err);
303368
}
@@ -310,41 +375,39 @@ module.exports = {
310375
{ name: 'email', dataType: 'email', required: true },
311376
{ predef: 'password' },
312377
{ name: 'name', required: true, dataType: 'as-is' },
313-
{ name: 'language', defaultValue: 'en_US' }
378+
{ name: 'language', defaultValue: 'en_US' },
314379
]),
315-
registerUser
380+
registerUser,
316381
],
317382
signIn: [
318383
checkContentType,
319384
retrieveParameters([
320385
{ name: 'email', required: true },
321386
{ predef: 'password' },
322387
]),
323-
signIn
388+
signIn,
324389
],
325390
signOut,
326391
resetPassword: [
327392
checkContentType,
328393
retrieveParameters([
329394
{ name: 'token', required: true },
330-
{ predef: 'password' }
395+
{ predef: 'password' },
331396
]),
332-
resetPassword
397+
resetPassword,
333398
],
334399
requestResetPassword: [
335400
checkContentType,
336-
retrieveParameters([
337-
{ name: 'email', dataType: 'email', required: true }
338-
]),
339-
requestResetPassword
401+
retrieveParameters([{ name: 'email', dataType: 'email', required: true }]),
402+
requestResetPassword,
340403
],
341404
confirmEmailAddress: [
342405
checkContentType,
343406
retrieveParameters([
344407
{ name: 'token', required: true },
345408
{ name: 'email', dataType: 'email', required: true },
346409
]),
347-
confirmEmailAddress
410+
confirmEmailAddress,
348411
],
349412
requestEmailConfirmation,
350413
getUserBoxes,
@@ -355,23 +418,19 @@ module.exports = {
355418
{ predef: 'password', name: 'currentPassword', required: false },
356419
{ predef: 'password', name: 'newPassword', required: false },
357420
{ name: 'name', dataType: 'as-is' },
358-
{ name: 'language' }
421+
{ name: 'language' },
359422
]),
360-
updateUser
423+
updateUser,
361424
],
362425
getUser,
363426
refreshJWT: [
364427
checkContentType,
365-
retrieveParameters([
366-
{ name: 'token', required: true }
367-
]),
368-
refreshJWT
428+
retrieveParameters([{ name: 'token', required: true }]),
429+
refreshJWT,
369430
],
370431
deleteUser: [
371432
checkContentType,
372-
retrieveParameters([
373-
{ predef: 'password' }
374-
]),
375-
deleteUser
376-
]
433+
retrieveParameters([{ predef: 'password' }]),
434+
deleteUser,
435+
],
377436
};

packages/models/index.js

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,44 @@ process.env.SUPPRESS_NO_CONFIG_WARNING = 'y';
77
const config = require('config');
88

99
config.util.setModuleDefaults('openSenseMap-API-models', {
10-
'db': {
11-
'host': 'localhost',
12-
'port': 27017,
13-
'user': 'admin',
14-
'userpass': 'admin',
15-
'authsource': 'OSeM-api',
16-
'db': 'OSeM-api',
17-
'mongo_uri': ''
10+
db: {
11+
host: 'localhost',
12+
port: 27017,
13+
user: 'admin',
14+
userpass: 'admin',
15+
authsource: 'OSeM-api',
16+
db: 'OSeM-api',
17+
mongo_uri: '',
1818
},
19-
'integrations': {
20-
'ca_cert': '',
21-
'cert': '',
22-
'key': '',
23-
'mailer': {
24-
'url': '',
25-
'origin': ''
19+
integrations: {
20+
ca_cert: '',
21+
cert: '',
22+
key: '',
23+
redis: {
24+
host: '',
25+
port: 6379,
26+
username: '',
27+
password: '',
28+
db: 0,
29+
},
30+
mailer: {
31+
url: '',
32+
origin: '',
33+
queue: 'mails',
34+
},
35+
mqtt: {
36+
url: '',
2637
},
27-
'mqtt': {
28-
'url': ''
29-
}
3038
},
31-
'password': {
32-
'min_length': 8,
33-
'salt_factor': 13
39+
password: {
40+
min_length: 8,
41+
salt_factor: 13,
3442
},
35-
'claims_ttl': {
36-
'amount': 1,
37-
'unit': 'd'
43+
claims_ttl: {
44+
amount: 1,
45+
unit: 'd',
3846
},
39-
'image_folder': './userimages/',
47+
image_folder: './userimages/',
4048
});
4149

4250
const { model: Box } = require('./src/box/box'),

packages/models/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"@sensebox/osem-protos": "^1.1.0",
1111
"@sensebox/sketch-templater": "1.13.0",
1212
"bcrypt": "^5.1.0",
13+
"bullmq": "^3.10.1",
1314
"config": "^3.3.6",
1415
"got": "^11.8.2",
1516
"isemail": "^3.0.0",

0 commit comments

Comments
 (0)