@igea/oac_backend 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/config/development.json +10 -4
- package/src/config/production.json +8 -3
- package/src/controllers/auth.js +39 -0
- package/src/index.js +1 -1
- package/src/models/EmailSender.js +52 -0
- package/src/models/users.js +35 -37
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"protocol": "http",
|
|
3
3
|
"url_register": "http://localhost:4001/register",
|
|
4
4
|
"port_range": {
|
|
5
|
-
"min":
|
|
5
|
+
"min": 4100, "max": 4199
|
|
6
6
|
},
|
|
7
7
|
"database": {
|
|
8
8
|
"host": "127.0.0.1",
|
|
@@ -23,12 +23,18 @@
|
|
|
23
23
|
},
|
|
24
24
|
"jwt_secret": "@igea#",
|
|
25
25
|
"smtp": {
|
|
26
|
-
"host": "
|
|
26
|
+
"host": "smtps.aruba.it",
|
|
27
27
|
"port": 465,
|
|
28
28
|
"secure": true,
|
|
29
29
|
"auth": {
|
|
30
|
-
"user": "
|
|
31
|
-
"pass": "your_smtp_password"
|
|
30
|
+
"user": "supporto@igea-soluzioni.it",
|
|
31
|
+
"pass": "<your_smtp_password>"
|
|
32
32
|
}
|
|
33
|
+
},
|
|
34
|
+
"exposed":{
|
|
35
|
+
"protocol": "http",
|
|
36
|
+
"host": "localhost",
|
|
37
|
+
"port": "4000"
|
|
33
38
|
}
|
|
39
|
+
|
|
34
40
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"protocol": "http",
|
|
3
3
|
"url_register": "http://localhost:4001/register",
|
|
4
4
|
"port_range": {
|
|
5
|
-
"min":
|
|
5
|
+
"min": 4100, "max": 4199
|
|
6
6
|
},
|
|
7
7
|
"database": {
|
|
8
8
|
"host": "127.0.0.1",
|
|
@@ -27,8 +27,13 @@
|
|
|
27
27
|
"port": 465,
|
|
28
28
|
"secure": true,
|
|
29
29
|
"auth": {
|
|
30
|
-
"user": "
|
|
31
|
-
"pass": "your_smtp_password"
|
|
30
|
+
"user": "supporto@igea-soluzioni.it",
|
|
31
|
+
"pass": "<your_smtp_password>"
|
|
32
32
|
}
|
|
33
|
+
},
|
|
34
|
+
"exposed":{
|
|
35
|
+
"protocol": "http",
|
|
36
|
+
"host": "localhost",
|
|
37
|
+
"port": "4000"
|
|
33
38
|
}
|
|
34
39
|
}
|
package/src/controllers/auth.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const router = express.Router();
|
|
3
3
|
const Users = require('../models/users');
|
|
4
|
+
const EmailSender = require('../models/EmailSender');
|
|
5
|
+
const config = require('../config');
|
|
6
|
+
const EXPOSED = config.exposed || {};
|
|
7
|
+
const { randomUUID } = require('crypto');
|
|
8
|
+
|
|
9
|
+
|
|
4
10
|
|
|
5
11
|
module.exports = function(jwtLib){
|
|
6
12
|
/**
|
|
@@ -67,6 +73,39 @@ module.exports = function(jwtLib){
|
|
|
67
73
|
});
|
|
68
74
|
});
|
|
69
75
|
|
|
76
|
+
router.post('/password_recovery', (req, res) => {
|
|
77
|
+
let body = req.body
|
|
78
|
+
let user_or_email = body.user
|
|
79
|
+
Users.fromUserOrEmail(user_or_email)
|
|
80
|
+
.then(async response => {
|
|
81
|
+
let email = response.email
|
|
82
|
+
console.log(`Send email to ${email} with recovery instructions`)
|
|
83
|
+
const token = randomUUID();
|
|
84
|
+
await Users.setPasswordRecoveryToken(response.id, token)
|
|
85
|
+
const activationLink = `${EXPOSED.protocol}://${EXPOSED.host}:${EXPOSED.port}/frontend/users/reset_password/${response.id}/${token}`
|
|
86
|
+
EmailSender.sendPasswordRecoveryEmail(
|
|
87
|
+
email, activationLink
|
|
88
|
+
).then( () => {
|
|
89
|
+
console.log("Email sent")
|
|
90
|
+
res.json({
|
|
91
|
+
success: true
|
|
92
|
+
});
|
|
93
|
+
}).catch( err => {
|
|
94
|
+
console.log("Error sending email", err)
|
|
95
|
+
res.json({
|
|
96
|
+
success: false,
|
|
97
|
+
message: `${ err }`
|
|
98
|
+
});
|
|
99
|
+
})
|
|
100
|
+
}).catch(err => {
|
|
101
|
+
console.log(err)
|
|
102
|
+
res.json({
|
|
103
|
+
success: false,
|
|
104
|
+
message: `${ err }`
|
|
105
|
+
});
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
70
109
|
return router
|
|
71
110
|
|
|
72
111
|
}
|
package/src/index.js
CHANGED
|
@@ -9,10 +9,10 @@ const jwtLib = jwtLibFactory({
|
|
|
9
9
|
secret: process.env.JWT_SECRET || config.jwt_secret,
|
|
10
10
|
excludePaths: [
|
|
11
11
|
`/${serviceName}/auth/authenticate`,
|
|
12
|
+
`/${serviceName}/auth/password_recovery`,
|
|
12
13
|
`/${serviceName}/auth/echo`,
|
|
13
14
|
`/${serviceName}/health`,
|
|
14
15
|
`/${serviceName}/fuseki/upload/vocabularies`
|
|
15
|
-
|
|
16
16
|
],
|
|
17
17
|
signOptions: { expiresIn: '15m' }
|
|
18
18
|
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const nodemailer = require('nodemailer');
|
|
2
|
+
const config = require('../config');
|
|
3
|
+
const SMTP = config.smtp || {};
|
|
4
|
+
|
|
5
|
+
class EmailSender {
|
|
6
|
+
|
|
7
|
+
static sendPasswordRecoveryEmail(userEmail, recoveryLink) {
|
|
8
|
+
// Logic to send email
|
|
9
|
+
console.log(`Sending password recovery email to ${userEmail} with link: ${recoveryLink}`);
|
|
10
|
+
return this.sendEmail(userEmail, {
|
|
11
|
+
subject: 'Password Recovery Instructions',
|
|
12
|
+
text: `Please use the following link to recover your password: ${recoveryLink}`,
|
|
13
|
+
html: `<p>Please use the following link to recover your password:</p><a href="${recoveryLink}">${recoveryLink}</a>`
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static sendEmail(email, message) {
|
|
18
|
+
return new Promise(async (resolve, reject) => {
|
|
19
|
+
try {
|
|
20
|
+
const smtpOptions = {
|
|
21
|
+
host: SMTP.host,
|
|
22
|
+
port: SMTP.port,
|
|
23
|
+
secure: SMTP.secure, // true for 465, false for other ports
|
|
24
|
+
auth: {
|
|
25
|
+
user: SMTP.auth.user,
|
|
26
|
+
pass: SMTP.auth.pass,
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
console.log(smtpOptions)
|
|
30
|
+
let transporter = nodemailer.createTransport(smtpOptions);
|
|
31
|
+
|
|
32
|
+
let mailOptions = {
|
|
33
|
+
from: `"OAC" <${SMTP.auth.user}>`, // sender address
|
|
34
|
+
to: email, // list of receivers
|
|
35
|
+
subject: message.subject, // Subject line
|
|
36
|
+
text: message.text, // plain text body
|
|
37
|
+
html: message.html, // html body
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let info = await transporter.sendMail(mailOptions);
|
|
41
|
+
console.log('Message sent: %s', info.messageId);
|
|
42
|
+
resolve(info);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Error sending email:', error);
|
|
45
|
+
reject(error);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = EmailSender;
|
package/src/models/users.js
CHANGED
|
@@ -34,6 +34,30 @@ class Users {
|
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
static fromUserOrEmail(userOrEmail){
|
|
39
|
+
|
|
40
|
+
return new Promise(async (resolve, reject) => {
|
|
41
|
+
try{
|
|
42
|
+
let userFound = await db(table)
|
|
43
|
+
.where(function() {
|
|
44
|
+
this.whereRaw(
|
|
45
|
+
'(username = ? OR email = ?)',
|
|
46
|
+
[userOrEmail, userOrEmail]
|
|
47
|
+
);
|
|
48
|
+
})
|
|
49
|
+
.first();
|
|
50
|
+
if(userFound && userFound["is_active"]) {
|
|
51
|
+
delete userFound["password"]
|
|
52
|
+
resolve(userFound)
|
|
53
|
+
}else{
|
|
54
|
+
reject(new Error("User not found or not active"))
|
|
55
|
+
}
|
|
56
|
+
}catch(e){
|
|
57
|
+
reject(e)
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
37
61
|
|
|
38
62
|
static find(id){
|
|
39
63
|
return new Promise(async (resolve, reject) => {
|
|
@@ -99,46 +123,20 @@ class Users {
|
|
|
99
123
|
});
|
|
100
124
|
}
|
|
101
125
|
|
|
102
|
-
static
|
|
126
|
+
static setPasswordRecoveryToken(id, resetToken) {
|
|
103
127
|
return new Promise(async (resolve, reject) => {
|
|
104
|
-
let user = null;
|
|
105
128
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
.
|
|
112
|
-
} catch (e) {
|
|
113
|
-
return reject(e);
|
|
114
|
-
}
|
|
115
|
-
if(!user){
|
|
116
|
-
return resolve();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// TODO:
|
|
120
|
-
// Here we have to store the resetToken and expiration date (utc)
|
|
121
|
-
// in the database associated with the user
|
|
122
|
-
|
|
123
|
-
// Send the email
|
|
124
|
-
try{
|
|
125
|
-
const smtpConfig = config.smtp;
|
|
126
|
-
let transporter = nodemailer.createTransport(smtpConfig);
|
|
127
|
-
let mailOptions = {
|
|
128
|
-
from: smtpConfig.auth.user,
|
|
129
|
-
to: user.email,
|
|
130
|
-
subject: 'Password Reset',
|
|
131
|
-
text: `Hello ${user.name},\n\nYou can reset your password using the following link:\n${resetLink}\n\nIf you did not request a password reset, please ignore this email.\n\nBest regards,\nYour Company`
|
|
132
|
-
};
|
|
133
|
-
transporter.sendMail(mailOptions, (error, info) => {
|
|
134
|
-
if (error) {
|
|
135
|
-
return reject(error);
|
|
136
|
-
}
|
|
137
|
-
resolve();
|
|
129
|
+
let count = await db(table)
|
|
130
|
+
.where({ id })
|
|
131
|
+
.update({
|
|
132
|
+
id,
|
|
133
|
+
reset_token: resetToken,
|
|
134
|
+
reset_token_expiration: Math.ceil((new Date().getTime())/1000)
|
|
138
135
|
});
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
resolve();
|
|
137
|
+
} catch (e) {
|
|
138
|
+
reject(e);
|
|
139
|
+
}
|
|
142
140
|
});
|
|
143
141
|
}
|
|
144
142
|
|