diff --git a/README.md b/README.md index f32a432db..4a6293d6d 100644 --- a/README.md +++ b/README.md @@ -52,14 +52,10 @@ Our stack node is actually in Beta. #### Available -* **User** : classic register / auth or oAuth(microsoft, google) - profile management (update, avatar upload ...) +* **User** : classic register / auth or oAuth(microsoft, google) - profile management (update, avatar upload ...) - **data privacy** (delete all, get all, send all by mail) * **Admin** : list users - edit user - delete user * **Tasks** : list tasks - add tasks - edit tasks - delete tasks -#### In reflexion - -RGPD conpliance - ## Prerequisites Make sure you have installed all of the following prerequisites on your development machine: diff --git a/config/templates/data-privacy-email.html b/config/templates/data-privacy-email.html new file mode 100644 index 000000000..7e8eb03d0 --- /dev/null +++ b/config/templates/data-privacy-email.html @@ -0,0 +1,18 @@ + + + + + + + + +

Dear {{displayName}},

+

You have asked to get all your data. We are happy to transfer it to you below, do not hesitate to contact us if us with any questions.

+

The {{appName}} Support Team.

+
+ Please do not reply to this email, you can contact us here. +
+
{{result}}
+ + + \ No newline at end of file diff --git a/modules/tasks/repositories/tasks.repository.js b/modules/tasks/repositories/tasks.repository.js index 2fe5bc4ce..4a41ad07a 100644 --- a/modules/tasks/repositories/tasks.repository.js +++ b/modules/tasks/repositories/tasks.repository.js @@ -11,6 +11,12 @@ const Task = mongoose.model('Task'); */ exports.list = () => Task.find().sort('-createdAt').exec(); +/** + * @desc Function to get all task of one user in db + * @return {Array} All tasks + */ +exports.userlist = (user) => Task.find({ user: user._id }).sort('-createdAt').exec(); + /** * @desc Function to create a task in db * @param {Object} task @@ -41,3 +47,10 @@ exports.update = (task) => new Task(task).save(); * @return {Object} confirmation of delete */ exports.delete = (task) => Task.deleteOne({ _id: task.id }).exec(); + +/** + * @desc Function to delete all task of one user in db + * @param {Object} task + * @return {Object} confirmation of delete + */ +exports.userdelete = (user) => Task.deleteMany({ user: user._id }).exec(); diff --git a/modules/tasks/services/tasks.data.service.js b/modules/tasks/services/tasks.data.service.js new file mode 100644 index 000000000..4f7274b56 --- /dev/null +++ b/modules/tasks/services/tasks.data.service.js @@ -0,0 +1,24 @@ +/** + * Module dependencies + */ +const TasksRepository = require('../repositories/tasks.repository'); + +/** + * @desc Function to ask repository to get all task from a specific user + * @param {Object} user + * @return {Promise} user tasks + */ +exports.userList = async (user) => { + const result = await TasksRepository.userlist(user); + return Promise.resolve(result); +}; + +/** + * @desc Function to ask repository to delete all task from a specific user + * @param {Object} user + * @return {Promise} confirmation of delete + */ +exports.userDelete = async (user) => { + const result = await TasksRepository.userdelete(user); + return Promise.resolve(result); +}; diff --git a/modules/users/controllers/users.data.controller.js b/modules/users/controllers/users.data.controller.js new file mode 100644 index 000000000..912557719 --- /dev/null +++ b/modules/users/controllers/users.data.controller.js @@ -0,0 +1,81 @@ +/** + * Module dependencies + */ +const path = require('path'); + +const errors = require(path.resolve('./lib/helpers/errors')); +const responses = require(path.resolve('./lib/helpers/responses')); +const mails = require(path.resolve('./lib/helpers/mails')); +const config = require(path.resolve('./config')); +const UserService = require('../services/user.service'); + + +const TaskDataService = require(path.resolve('./modules/tasks/services/tasks.data.service')); + +/** + * @desc Endpoint to ask the service to delete the user connected and all his data + * @param {Object} req - Express request object + * @param {Object} res - Express response object + */ +exports.delete = async (req, res) => { + try { + const result = { + user: await UserService.delete(req.user), + tasks: await TaskDataService.userDelete(req.user), + }; + result.user.id = req.user.id; + responses.success(res, 'user and his data were deleted')(result); + } catch (err) { + responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); + } +}; + +/** + * @desc Endpoint to ask the service to get all user data + * @param {Object} req - Express request object + * @param {Object} res - Express response object + */ +exports.get = async (req, res) => { + try { + const result = { + user: await UserService.get(req.user), + tasks: await TaskDataService.userList(req.user), + }; + responses.success(res, 'user data')(result); + } catch (err) { + responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); + } +}; + +/** + * @desc Endpoint to ask the service to get all user data and send it to user mail + * @param {Object} req - Express request object + * @param {Object} res - Express response object + */ +exports.getMail = async (req, res) => { + try { + const result = { + user: await UserService.get(req.user), + tasks: await TaskDataService.userList(req.user), + }; + + // send mail + const mail = await mails.sendMail({ + template: 'data-privacy-email', + from: config.mailer.from, + to: req.user.email, + subject: `${config.app.title}: your data`, + params: { + result: JSON.stringify(result), + displayName: `${req.user.firstName} ${req.user.lastName}`, + appName: config.app.title, + appContact: config.app.contact, + }, + }); + + if (!mail.accepted) return responses.error(res, 400, 'Bad Request', 'Failure sending email')(); + responses.success(res, 'An email has been sent to the user email with data')(); + } catch (err) { + responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err))(err); + } +}; diff --git a/modules/users/controllers/users/users.profile.controller.js b/modules/users/controllers/users/users.profile.controller.js index c82655486..711d7fa97 100644 --- a/modules/users/controllers/users/users.profile.controller.js +++ b/modules/users/controllers/users/users.profile.controller.js @@ -43,7 +43,6 @@ exports.delete = async (req, res) => { } }; - /** * @desc Endpoint to ask the service to update a user profile picture * @param {Object} req - Express request object diff --git a/modules/users/routes/users.routes.js b/modules/users/routes/users.routes.js index b7a896e13..8a3084ec0 100644 --- a/modules/users/routes/users.routes.js +++ b/modules/users/routes/users.routes.js @@ -10,6 +10,7 @@ const usersSchema = require('../models/user.schema'); module.exports = (app) => { const users = require('../controllers/users.controller'); + const usersData = require('../controllers/users.data.controller'); // Setting up the users profile api app.route('/api/users/me').get(passport.authenticate('jwt'), users.me); @@ -18,6 +19,10 @@ module.exports = (app) => { .put(passport.authenticate('jwt'), model.isValid(usersSchema.User), users.update) .delete(passport.authenticate('jwt'), users.delete); + app.route('/api/users/data') + .get(passport.authenticate('jwt'), usersData.getMail) + .delete(passport.authenticate('jwt'), usersData.delete); + app.route('/api/users/accounts') .delete(users.removeOAuthProvider) .post(model.isValid(usersSchema.User), users.addOAuthProviderUserProfile);