Skip to content
This repository has been archived by the owner on Feb 13, 2023. It is now read-only.

Feature/projects #3

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c6111b8
Merged changes from feature/introduce_sass
Oct 31, 2018
a139ebe
Add three dependencies
121593 Nov 25, 2018
13d526f
Add projects public route
121593 Nov 25, 2018
9c6922a
Update model
121593 Nov 25, 2018
bccd9c7
Load express-sanitizer
121593 Nov 25, 2018
c3ebc70
Create custom validation for project
121593 Nov 25, 2018
66cec29
Create public project pages
121593 Nov 25, 2018
2cc2a45
Create menu entries
121593 Nov 25, 2018
f9a5aaa
Add hook to add scripts/stylessheets
121593 Nov 25, 2018
392bf1b
Create partials for project list, form, and user icon
121593 Nov 25, 2018
87c8b2d
Create project-related private pages
121593 Nov 25, 2018
9c3e7f7
Create script for form edition.
121593 Nov 25, 2018
280afec
Adapt members page to the new project architecture
121593 Nov 25, 2018
0dc0996
Various style additions related to projects
121593 Nov 25, 2018
d110711
Add three dependencies
121593 Nov 25, 2018
9f33a5f
Add projects public route
121593 Nov 25, 2018
c729392
Update model
121593 Nov 25, 2018
16dae9b
Load express-sanitizer
121593 Nov 25, 2018
972b924
Create custom validation for project
121593 Nov 25, 2018
ebd7379
Create public project pages
121593 Nov 25, 2018
ffd722c
Create menu entries
121593 Nov 25, 2018
9dea0f1
Add hook to add scripts/stylessheets
121593 Nov 25, 2018
6409fd1
Create partials for project list, form, and user icon
121593 Nov 25, 2018
6836773
Create project-related private pages
121593 Nov 25, 2018
4d571a2
Create script for form edition.
121593 Nov 25, 2018
02fa6cf
Adapt members page to the new project architecture
121593 Nov 25, 2018
f9d31af
Various style additions related to projects
121593 Nov 25, 2018
9f6b1c1
Merge remote-tracking branch 'origin/feature/projects' into feature/p…
121593 Nov 25, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,23 @@
"cookie-session": "1.3.2",
"ejs": "2.5.8",
"express": "4.16.2",
"express-sanitizer": "1.0.4",
"lodash": "4.17.4",
"mailgun-js": "0.21.0",
"node-sass-middleware": "0.11.0",
"passport": "0.4.0",
"pg": "7.4.1",
"pg-hstore": "2.3.2",
"qs": "6.5.0",
"quill-delta-to-html": "0.10.6",
"request": "2.88.0",
"request-promise": "4.2.2",
"saga-logger": "0.0.8",
"saga-managed-error": "1.0.0",
"sequelize": "4.32.2",
"serve-favicon": "2.4.5",
"shortid": "2.2.13"
"shortid": "2.2.13",
"validate.js": "0.12.0"
},
"semistandard": {
"globals": [
Expand Down
1 change: 1 addition & 0 deletions src/authentication/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const publicRoutes = {
'/connexion': ['GET'],
'/contact': ['GET', 'POST'],
'/membres': ['GET'],
'/projets': ['GET'],
'/healthcheck': ['GET'],
'/inscription': ['GET', 'POST']
};
Expand Down
17 changes: 12 additions & 5 deletions src/controllers/membres.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,24 @@ module.exports.read = async (params, meta) => {
where: {
passportId: params.id
},
attributes: { exclude: ['password'] },
raw: true
attributes: { exclude: ['password'] }
});

if (!member) {
return 404;
}

member.hashedEmail = hashEmail.hashMd5(member.email);
const privacyLevel = meta.user ? [models.projects.privacyLevels.MEMBERS, models.projects.privacyLevels.PUBLIC] : models.projects.privacyLevels.PUBLIC;

const projects = await models.projects.findAll({
const projects = await member.getProjects({
where: {
userId: member.id
privacyLevel: privacyLevel
},
raw: true
include: [{
model: models.users,
as: 'users'
}]
});

return views.render('./src/views/membre.ejs', {
Expand Down
160 changes: 160 additions & 0 deletions src/controllers/perso/projets/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
const Sequelize = require('sequelize');
const Op = Sequelize.Op;

const models = require('../../../models');
const validate = require('validate.js');

const views = require('../../../views');
const view = './src/views/perso/projects/edit.ejs';

// Form validation constraints
const {
projectConstraints
} = require('../../../resources/validation/project.constraints');
const editProjectConstraints = projectConstraints('edit');

module.exports.read = async (params, meta) => {
const project = await models.projects.findOne({
where: {
slug: params.id
}
});

if (!project) {
return 404;
}

// Check if logged user belongs to the project
const users = await project.getUsers();
if (!users.find(u => u.id === meta.user.id)) {
return 403;
}
// Store information in the object
project.users = users;

const allUsers = await models.users.findAll({
where: {
id: {
[Op.ne]: meta.user.id
}
},
attributes: {
exclude: ['password']
}
});

return views.render(view, {
user: meta.user,

showLabel: true,
formAction: '.',
privacyLevels: models.projects.privacyLevels,
users: allUsers,

returningNewProject: project,
errors: null
});
};

// Using create hook to keep working directly with <form>
module.exports.create = async (params, meta, req, res) => {
const allUsers = await models.users.findAll({
where: {
id: {
[Op.ne]: meta.user.id
}
},
attributes: {
exclude: ['password']
}
});

// Form validation
try {
await validate.async(params, editProjectConstraints);
} catch (e) {
return views.render(view, {
user: meta.user,
privacyLevels: models.projects.privacyLevels,
users: allUsers,

returningNewProject: req.body,
errors: e
});
}

const project = await models.projects.findOne({
where: {
id: req.body.projectId
}
});

if (!project) {
return 404;
}

// Check if logged user belongs to the project
const users = await project.getUsers();
if (!users.find(u => u.id === meta.user.id)) {
return 403;
}

return models.projects.update({
title: req.body.title,
description: req.body.description,
// Cannot update slug
// slug: req.body.slug,
longDescription: req.body.long_description,
link: req.body.link,
privacyLevel: req.body.privacy_level
}, {
where: {
id: project.id
}
})
.then(result => {
return {
redirect: `/perso/projets/${project.slug}`
// TODO: add succes message
};
})
.catch(async error => {
console.error(error);

return views.render(view, {
user: meta.user,
users: allUsers,
returningNewProject: req.body,
errors: error.original.detail,

showLabel: true,
formAction: '.',
privacyLevels: models.projects.privacyLevels
});
});
};

module.exports.destroy = async (params, meta, req, res) => {
const project = await models.projects.findById(params.id);

if (!project) {
return 400;
}

// Check if logged user belongs to the project
const users = await project.getUsers();
if (!users.find(u => u.id === meta.user.id)) {
return 403;
}

models.projects.destroy({
where: {
id: project.id
}
})
.then(() => 200)
.catch((e) => {
console.error(e);
return 500;
});
};
42 changes: 42 additions & 0 deletions src/controllers/perso/projets/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
var QuillDeltaToHtmlConverter = require('quill-delta-to-html').QuillDeltaToHtmlConverter;

const models = require('../../../models');

const views = require('../../../views');

module.exports.read = async (params, meta) => {
const user = await models.users.findById(meta.user.id);
const projects = await user.getProjects({
include: [{
all: true
}]
});

if (params.id) {
console.log(params.id);
// @TODO: escape param
const filteredProjects = projects.filter((p) => p.slug === params.id);

if (!filteredProjects.length) {
// 404
return 404;
}

const project = filteredProjects[0];
// Convert Quill Delta object to HTML
const converter = new QuillDeltaToHtmlConverter(project.longDescription, {});
const projectLongDescriptionHtml = converter.convert();

console.debug(project);
return views.render('./src/views/perso/projects/project.ejs', {
user: meta.user,
project: project,
projectLongDescriptionHtml
});
}

return views.render('./src/views/perso/projects/index.ejs', {
user: meta.user,
projects: projects
});
};
106 changes: 106 additions & 0 deletions src/controllers/perso/projets/nouveau.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
const models = require('../../../models');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const validate = require('validate.js');
const views = require('../../../views');
const view = './src/views/perso/projects/new.ejs';

// Form validation constraints
const {
projectConstraints
} = require('../../../resources/validation/project.constraints');
const projectCreationConstraints = projectConstraints('create');

module.exports.read = async (params, meta) => {
const allUsers = await models.users.findAll({
where: {
id: {
[Op.ne]: meta.user.id
}
},
attributes: {
exclude: ['password']
}
});

return views.render(view, {
user: meta.user,

privacyLevels: models.projects.privacyLevels,
users: allUsers,

returningNewProject: {users: []},
errors: null
});
};

module.exports.create = async (params, meta, req, res) => {
const allUsers = await models.users.findAll({
where: {
id: {
[Op.ne]: meta.user.id
}
},
attributes: {
exclude: ['password']
}
});

// Validation
try {
await validate.async(params, projectCreationConstraints);
} catch (e) {
console.error(e);
return views.render(view, {
user: meta.user,
privacyLevels: models.projects.privacyLevels,
users: allUsers,

returningNewProject: req.body,
errors: e
});
}

// Create project
return models.projects.create({
title: req.body.title,
description: req.body.description,
slug: req.body.slug,
// No escape on rendering
longDescription: req.sanitize(req.body.long_description),
imageLink: req.body.imageLink,
link: req.body.link,
privacyLevel: req.body.privacy_level
})
.then(async result => {
// Add users relations
// Adding logged user id to the choice from form
const userIds = typeof params.users === 'string' ? [params.users, meta.user.id] : params.users.concat(meta.user.id);
const users = await models.users.findAll({
where: {
id: {
[Op.in]: userIds.map(id => parseInt(id, 10))
}
}
});

result.addUsers(users.map(u => u.id));

return {
redirect: '/perso/projets'
// TODO: add succes message
};
})
.catch(error => {
console.error(error);

return views.render(view, {
user: meta.user,
returningNewProject: req.body,
users: allUsers,
privacyLevels: models.projects.privacyLevels,

errors: 'Erreur'
});
});
};
Loading