Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreBrisorgueil committed Apr 25, 2020
2 parents 47c6f28 + 755804a commit 9bf07b5
Show file tree
Hide file tree
Showing 18 changed files with 2,209 additions and 2,220 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>
2 changes: 0 additions & 2 deletions modules/core/tests/core.config.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ describe('Configuration Tests:', () => {
email: 'user_config_test_@localhost.com',
firstName: 'User',
lastName: 'Local',
displayName: 'User Local',
roles: ['user'],
};

Expand All @@ -63,7 +62,6 @@ describe('Configuration Tests:', () => {
email: 'admin_config_test_@localhost.com',
firstName: 'Admin',
lastName: 'Local',
displayName: 'Admin Local',
roles: ['user', 'admin'],
};

Expand Down
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);
};
1 change: 0 additions & 1 deletion modules/tasks/tests/tasks.crud.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ describe('Tasks CRUD Tests :', () => {
_user = {
firstName: 'Full',
lastName: 'Name',
displayName: 'Full Name',
email: credentials.email,
password: credentials.password,
provider: 'local',
Expand Down
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 @@ -150,7 +150,6 @@ exports.saveOAuthUserProfile = async (req, providerUserProfile, done) => {
user = {
firstName: providerUserProfile.firstName,
lastName: providerUserProfile.lastName,
displayName: providerUserProfile.displayName,
profileImageURL: providerUserProfile.profileImageURL,
provider: providerUserProfile.provider,
providerData: providerUserProfile.providerData,
Expand Down
4 changes: 2 additions & 2 deletions modules/users/controllers/users/users.password.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ exports.forgot = async (req, res) => {
to: user.email,
subject: 'Password Reset',
params: {
displayName: user.displayName,
displayName: `${user.firstName} ${user.lastName}`,
url: `${config.cors.protocol}://${config.cors.host}:${config.cors.port}/auth/password-reset?token=${user.resetPasswordToken}`,
appName: config.app.title,
appContact: config.app.contact,
Expand Down Expand Up @@ -115,7 +115,7 @@ exports.reset = async (req, res) => {
to: user.email,
subject: 'Your password has been changed',
params: {
displayName: user.displayName,
displayName: `${user.firstName} ${user.lastName}`,
appName: config.app.title,
appContact: config.app.contact,
},
Expand Down
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
1 change: 0 additions & 1 deletion modules/users/models/user.model.mongoose.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const UserMongoose = new Schema({
sub: String,
firstName: String,
lastName: String,
displayName: String,
email: {
type: String,
unique: 'Email already exists',
Expand Down
1 change: 0 additions & 1 deletion modules/users/models/user.schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const UserSchema = Joi.object().keys({
lastName: Joi.string().alphanum().min(1).max(30)
.trim()
.required(),
displayName: Joi.string().trim(),
email: Joi.string().email({ minDomainAtoms: 2 }),
profileImageURL: Joi.string(),
roles: Joi.array().items(Joi.string().valid(config.whitelists.users.roles)).min(1).default(['user']),
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
1 change: 0 additions & 1 deletion modules/users/services/user.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ exports.update = async (user, body, option) => {
else if (option === 'recover') user = _.assignIn(user, _.pick(body, config.whitelists.users.recover));

user.updated = Date.now();
user.displayName = `${user.firstName} ${user.lastName}`;

const result = await UserRepository.update(user);
return Promise.resolve(removeSensitive(result));
Expand Down
1 change: 0 additions & 1 deletion modules/users/tests/user.crud.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ describe('User CRUD Tests :', () => {
_user = {
firstName: 'Full',
lastName: 'Name',
displayName: 'Full Name',
email: credentials[0].email,
password: credentials[0].password,
provider: 'local',
Expand Down
2 changes: 0 additions & 2 deletions modules/users/tests/user.schema.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ describe('User Schema Tests :', () => {
user = {
firstName: 'Full',
lastName: 'Name',
displayName: 'Full Name',
email: 'test@test.com',
password: 'M3@n.jsI$Aw3$0m3',
provider: 'local',
Expand All @@ -33,7 +32,6 @@ describe('User Schema Tests :', () => {
// user3 = {
// firstName: 'Different',
// lastName: 'User',
// displayName: 'Full Different Name',
// email: 'test3@test.com',
// password: 'Different_Password1!',
// provider: 'local',
Expand Down
Loading

0 comments on commit 9bf07b5

Please sign in to comment.