Skip to content

Commit

Permalink
feat(users, tasks): init data privacy management example ✨
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreBrisorgueil committed Apr 25, 2020
1 parent d315875 commit 58edcab
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 6 deletions.
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions config/templates/data-privacy-email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
<title></title>
</head>

<body>
<p>Dear {{displayName}},</p>
<p>You have asked to get all your data. We are happy to transfer it to you below, do not hesitate to contact <a href="mailto:{{appContact}}">us</a> if us with any questions.</p>
<p>The {{appName}} Support Team.</p>
<br/>
<i style='color:#9b9b9b'>Please do not reply to this email, you can contact us <a href="mailto:{{appContact}}">here</a>.</i>
<br />
<pre style='background: #f5f2f0; color:#72972c; padding: 15px; border-radius: 7px;'>{{result}}</pre>
</body>

</html>
13 changes: 13 additions & 0 deletions modules/tasks/repositories/tasks.repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
24 changes: 24 additions & 0 deletions modules/tasks/services/tasks.data.service.js
Original file line number Diff line number Diff line change
@@ -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);
};
81 changes: 81 additions & 0 deletions modules/users/controllers/users.data.controller.js
Original file line number Diff line number Diff line change
@@ -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);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions modules/users/routes/users.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 58edcab

Please sign in to comment.