diff --git a/locales/en.json b/locales/en.json index b4459dd..164330b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -49,7 +49,9 @@ "price": "Price", "new": "New", "departmentsManagement": "Departments management", - "manageDepartments": "Manage departments" + "manageDepartments": "Manage departments", + "user": "User", + "permissions": "Permissions" }, "firstName": "First name", "lastName": "Last name", diff --git a/locales/fr.json b/locales/fr.json index a85d267..4269810 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -49,7 +49,9 @@ "price": "Prix", "new": "Nouveau", "departmentsManagement": "Gestion des départements", - "manageDepartments": "Gérer les départements" + "manageDepartments": "Gérer les départements", + "user": "Utilisateur", + "permissions": "Autorisations" }, "firstName": "Prénom", "lastName": "Nom de famille", diff --git a/models/user.js b/models/user.js index e7c80b1..8f321a4 100644 --- a/models/user.js +++ b/models/user.js @@ -26,7 +26,8 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, validate: { isEmail: true - } + }, + unique: true }, firstName: { type: DataTypes.STRING, diff --git a/public/javascripts/admin/users.js b/public/javascripts/admin/users.js new file mode 100644 index 0000000..fffb243 --- /dev/null +++ b/public/javascripts/admin/users.js @@ -0,0 +1,5 @@ +document.querySelectorAll("a.remove") + .forEach(e => e.addEventListener("click", ev => { + if (!confirm("Do you really want to remove this user ?")) + ev.preventDefault(); + })); diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 1820216..81c5bfa 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -217,7 +217,7 @@ p.before-link a::before { cursor: pointer; } -#sandwichesManagement>a>button, #departmentsManagement>a>button { +#sandwichesManagement>a>button, #departmentsManagement>a>button, #usersManagement>a>button { width: 100%; } diff --git a/routes/admin/index.js b/routes/admin/index.js index b296b5e..d031186 100644 --- a/routes/admin/index.js +++ b/routes/admin/index.js @@ -14,6 +14,7 @@ router.get("/", sessionCheck(3), async (req, res) => { }) .use("/orders", require("./orders")) .use("/sandwiches", require("./sandwiches")) - .use("/departments", require("./departments")); + .use("/departments", require("./departments")) + .use("/users", require("./users")); module.exports = router; diff --git a/routes/admin/users/add.js b/routes/admin/users/add.js new file mode 100644 index 0000000..e2b8fc8 --- /dev/null +++ b/routes/admin/users/add.js @@ -0,0 +1,24 @@ +let express = require("express"); +let router = express.Router(); +let sessionCheck = require("../../../middlewares/sessionCheck"); +let models = require("../../../models"); +let userCreate = require("../../utils/userCreate"); + +router.get("/", sessionCheck(3), async (req, res) => { + res.render("admin/users/add", { + title: "SOD - Users administration", + user: req.session.user, + departments: await models.Department.findAll() + }); +}).post("/", sessionCheck(3), async (req, res) => { + let user = await userCreate(req, res); + if (user) { + if (req.body.permissions && 0 >= req.body.permissions <= 3) { + user.permissions = req.body.permissions; + await user.save(); + } + res.redirect("/admin/users"); + } +}); + +module.exports = router; diff --git a/routes/admin/users/edit.js b/routes/admin/users/edit.js new file mode 100644 index 0000000..db038fc --- /dev/null +++ b/routes/admin/users/edit.js @@ -0,0 +1,39 @@ +let express = require("express"); +let router = express.Router(); +let sessionCheck = require("../../../middlewares/sessionCheck"); +let models = require("../../../models"); +let error = require("../../utils/error"); +let userUpdate = require("../../utils/userUpdate"); + +router.get("/", sessionCheck(3), async (req, res) => { + if (!req.query.name) + return error(req, res, "Can't edit user !", 400, "Missing arg"); + + let user = await models.User.findByPk(req.query.name); + if (!user) + return error(req, res, "Can't edit user !", 400, "user not found"); + + res.render("admin/users/edit", { + title: "SOD - Users administration", + user: req.session.user, + targetUser: user, + departments: await models.Department.findAll() + }); +}).post("/", sessionCheck(3), async (req, res) => { + if (!req.body.oldUsername) + return error(req, res, "Fail to edit user !", 400, "Missing arg"); + + let user = await models.User.findByPk(req.body.oldUsername); + + user = await userUpdate(req, res, user); + + if (user) { + if (req.body.permissions && 0 >= req.body.permissions <= 3) { + user.permissions = req.body.permissions; + await user.save(); + } + res.redirect("/admin/users"); + } +}); + +module.exports = router; diff --git a/routes/admin/users/index.js b/routes/admin/users/index.js new file mode 100644 index 0000000..fa99688 --- /dev/null +++ b/routes/admin/users/index.js @@ -0,0 +1,29 @@ +let express = require("express"); +let router = express.Router(); +let sessionCheck = require("../../../middlewares/sessionCheck"); +let models = require("../../../models"); +let error = require("../../utils/error"); + + +router.get("/", sessionCheck(3), async (req, res) => { + res.render("admin/users/index", { + title: "SOD - Users administration", + user: req.session.user, + users: await models.User.findAll() + }); +}) + .use("/edit", require("./edit")) + .use("/add", require("./add")) + .get("/delete", sessionCheck(3), async (req, res) => { + if (!req.query.name) + return error(req, res, "Can't remove user !", 400, "Missing arg"); + + let user = await models.User.findByPk(req.query.name); + if (!user) + return error(req, res, "Can't remove user !", 400, "Invalid user"); + + await user.destroy(); + res.redirect("/admin/users"); + }); + +module.exports = router; diff --git a/routes/profile.js b/routes/profile.js index 5e3a48e..ad1f167 100644 --- a/routes/profile.js +++ b/routes/profile.js @@ -2,7 +2,7 @@ let express = require("express"); let router = express.Router(); let sessionCheck = require("../middlewares/sessionCheck"); let models = require("../models"); -let error = require("./utils/error"); +let userUpdate = require("./utils/userUpdate"); router.get("/", sessionCheck(0), async (req, res) => { res.render("profile", { @@ -18,46 +18,11 @@ router.get("/", sessionCheck(0), async (req, res) => { }).post("/", sessionCheck(0), async (req, res) => { let user = await models.User.findByPk(req.session.user.username); - /*if (req.body.username && req.body.username !== user.username) - if (await models.User.findByPk(req.body.username)) - return error(req, res, "Invalid profile update !", 400, "Username already taken"); - else - user.username = req.body.username;*/ - - if (req.body.email && req.body.email !== user.email) - if (await models.User.findOne({where: {email: req.body.email}})) - return error(req, res, "Invalid profile update !", 400, "Email already used"); - else - user.email = req.body.email; - - if (req.body.firstName && req.body.lastName && - (req.body.firstName !== user.firstName || req.body.lastName !== user.lastName)) - if (await models.User.findOne({where: {firstName: req.body.firstName, lastName: req.body.lastName}})) - return error(req, res, "Invalid profile update !", 400, "First & last name already register"); - else { - user.firstName = req.body.firstName; - user.lastName = req.body.lastName; - for (let c of await models.Order.findAll({where: { - firstName: req.session.user.firstName, - lastName: req.session.user.lastName}})) { - c.firstName = user.firstName; - c.lastName = user.lastName; - await c.save() - } - } - - if (req.body.department && req.body.department !== user.DepartmentName) - if (!await models.Department.findByPk(req.body.department)) - return error(req, res, "Invalid profile update !", 400, "Invalid department"); - else - user.DepartmentName = req.body.department; - - if (req.body.password && !user.checkPassword(req.body.password)) - user.passwordHash = req.body.password; - - await user.save(); - req.session.user = user; - res.redirect("/profile"); + user = await userUpdate(req, res, user); + if (user) { + req.session.user = user; + res.redirect("/profile"); + } }); module.exports = router; diff --git a/routes/register.js b/routes/register.js index 3dae715..3650c6b 100644 --- a/routes/register.js +++ b/routes/register.js @@ -1,7 +1,7 @@ let express = require("express"); let router = express.Router(); let models = require("../models"); -let error = require("./utils/error"); +let userCreate = require("./utils/userCreate"); router.get("/", async (req, res) => { @@ -11,45 +11,10 @@ router.get("/", async (req, res) => { res.render("register", {title: "SOD - register", departments: await models.Department.findAll()}); }) .post("/", async (req, res) => { - if (!req.body.username || !req.body.email || !req.body.firstName || !req.body.lastName || - !req.body.department || !req.body.password) - return error(req, res, "", 400, "Missing args"); - - if (await models.User.findByPk(req.body.username)) - return error(req, res, "Invalid register !", 400, "Username already taken"); - - if (await models.User.findOne({where: {firstName: req.body.firstName, - lastName: req.body.lastName}})) - return error(req, res, "Invalid register !", 400, "First & last name already register"); - - if (await models.User.findOne({where: {email: req.body.email}})) - return error(req, res, "Invalid register !", 400, "Email already used"); - - let department = await models.Department.findByPk(req.body.department); - if (!department) - return error(req, res, "Invalid register !", 400, "Invalid department"); - - try { - let user = await models.User.create({ - username: req.body.username, - email: req.body.email, - firstName: req.body.firstName, - lastName: req.body.lastName, - passwordHash: req.body.password - }); - - await user.setDepartment(department); + let user = await userCreate(req, res); + if (user) { req.session.user = user; res.redirect("/"); - for (let c of await models.Order.findAll({where: { - firstName: user.firstName, - lastName: user.lastName, - UserUsername: null - }})) - await c.setUser(user); - } catch (e) { - error(req, res, "Registration fail !"); - throw e; } }); diff --git a/routes/utils/userCreate.js b/routes/utils/userCreate.js new file mode 100644 index 0000000..6800e47 --- /dev/null +++ b/routes/utils/userCreate.js @@ -0,0 +1,46 @@ +let models = require("../../models"); +let error = require("../utils/error"); + + +module.exports = async (req, res) => { + if (!req.body.username || !req.body.email || !req.body.firstName || !req.body.lastName || + !req.body.department || !req.body.password) + return error(req, res, "Invalid register !", 400, "Missing args"); + + if (await models.User.findByPk(req.body.username)) + return error(req, res, "Invalid register !", 400, "Username already taken"); + + if (await models.User.findOne({where: {firstName: req.body.firstName, + lastName: req.body.lastName}})) + return error(req, res, "Invalid register !", 400, "First & last name already register"); + + if (await models.User.findOne({where: {email: req.body.email}})) + return error(req, res, "Invalid register !", 400, "Email already used"); + + let department = await models.Department.findByPk(req.body.department); + if (!department) + return error(req, res, "Invalid register !", 400, "Invalid department"); + + try { + let user = await models.User.create({ + username: req.body.username, + email: req.body.email, + firstName: req.body.firstName, + lastName: req.body.lastName, + passwordHash: req.body.password + }); + + await user.setDepartment(department); + + for (let c of await models.Order.findAll({where: { + firstName: user.firstName, + lastName: user.lastName, + UserUsername: null + }})) + await c.setUser(user); + return user; + } catch (e) { + error(req, res, "Registration fail !"); + throw e; + } +}; diff --git a/routes/utils/userUpdate.js b/routes/utils/userUpdate.js new file mode 100644 index 0000000..3b0631a --- /dev/null +++ b/routes/utils/userUpdate.js @@ -0,0 +1,47 @@ +let models = require("../../models"); +let error = require("./error"); + + +module.exports = async (req, res, user) => { + if (req.body.username && req.body.username !== user.username) + if (await models.User.findByPk(req.body.username)) + return error(req, res, "Invalid profile update !", 400, "Username already taken"); + else { + await models.User.update({username: req.body.username}, {where: {username: user.username}}); + user = await models.User.findByPk(req.body.username); + } + + if (req.body.email && req.body.email !== user.email) + if (await models.User.findOne({where: {email: req.body.email}})) + return error(req, res, "Invalid profile update !", 400, "Email already used"); + else + user.email = req.body.email; + + if (req.body.firstName && req.body.lastName && + (req.body.firstName !== user.firstName || req.body.lastName !== user.lastName)) + if (await models.User.findOne({where: {firstName: req.body.firstName, lastName: req.body.lastName}})) + return error(req, res, "Invalid profile update !", 400, "First & last name already register"); + else { + user.firstName = req.body.firstName; + user.lastName = req.body.lastName; + for (let c of await models.Order.findAll({where: { + firstName: req.session.user.firstName, + lastName: req.session.user.lastName}})) { + c.firstName = user.firstName; + c.lastName = user.lastName; + await c.save() + } + } + + if (req.body.department && req.body.department !== user.DepartmentName) + if (!await models.Department.findByPk(req.body.department)) + return error(req, res, "Invalid profile update !", 400, "Invalid department"); + else + user.DepartmentName = req.body.department; + + if (req.body.password && !user.checkPassword(req.body.password)) + user.passwordHash = req.body.password; + + await user.save(); + return user; +}; diff --git a/views/admin/users/add.pug b/views/admin/users/add.pug new file mode 100644 index 0000000..70872bd --- /dev/null +++ b/views/admin/users/add.pug @@ -0,0 +1,34 @@ +extends ../../layout + +block content + div.card#usersManagement + h1=__("admin.new")+" "+__("admin.user") + form(action="/admin/users/add" method="POST") + h1=__("register.title") + div.field + label(for="username")=__("username") + ":" + input#username(type="text" name="username" required) + div.field + label(for="email")=__("email") + ":" + input#email(type="email" name="email" required) + div.field + label(for="firstName")=__("firstName") + ":" + input#firstName(type="text" name="firstName" required) + div.field + label(for="lastName")=__("lastName") + ":" + input#lastName(type="text" name="lastName" required) + div.field + label(for="department")=__("department") + ":" + input#department(type="list" list="department-list" name="department" required) + div.field + label(for="password")=__("password") + ":" + input#password(type="password" name="password" required) + div.field + label(for="permissions")=__("admin.permissions") + input#permissions(type="number" min="0" max="3" value="0" name="permissions") + div.field + input(type="submit" value=__("register.submit")) + + datalist#department-list + each department in departments + option(value=department.name) diff --git a/views/admin/users/edit.pug b/views/admin/users/edit.pug new file mode 100644 index 0000000..5528b26 --- /dev/null +++ b/views/admin/users/edit.pug @@ -0,0 +1,35 @@ +extends ../../layout + +block content + div.card#sandwichesManagement + h1=__("admin.edit")+" "+targetUser.username + form(action="/admin/users/edit" method="POST") + h2=__("profile.infos") + input.hide(type="text" name="oldUsername" value=targetUser.username required) + div.field + label(for="username")=__("username") + ":" + input#username(type="text" name="username" value=targetUser.username required) + div.field + label(for="email")=__("email") + ":" + input#email(type="email" name="email" value=targetUser.email required) + div.field + label(for="firstName")=__("firstName") + ":" + input#firstName(type="text" name="firstName" value=targetUser.firstName required) + div.field + label(for="lastName")=__("lastName") + ":" + input#lastName(type="text" name="lastName" value=targetUser.lastName required) + div.field + label(for="department")=__("department") + ":" + input#department(type="list" list="department-list" name="department" value=targetUser.DepartmentName required) + div.field + label(for="password")=__("password") + ":" + input#password(type="password" name="password") + div.field + label(for="permissions")=__("admin.permissions") + input#permissions(type="number" min="0" max="3" value=targetUser.permissions name="permissions") + div.field + input(type="submit" value=__("save")) + + datalist#department-list + each department in departments + option(value=department.name) diff --git a/views/admin/users/index.pug b/views/admin/users/index.pug new file mode 100644 index 0000000..3ddf142 --- /dev/null +++ b/views/admin/users/index.pug @@ -0,0 +1,18 @@ +extends ../../layout + +block content + div.card#usersManagement + h1=__("admin.userManagement") + a.add(href="/admin/users/add") + button=__("admin.add") + div + each user in users + div.user + h2=user.username + div.buttons + a.edit(href="/admin/users/edit?name="+user.username) + button=__("admin.edit") + a.remove(href="/admin/users/delete?name="+user.username) + button=__("admin.remove") + + script(src="/javascripts/admin/users.js") diff --git a/views/sandwiches.pug b/views/sandwiches.pug index 72c2e81..90f3ff1 100644 --- a/views/sandwiches.pug +++ b/views/sandwiches.pug @@ -10,4 +10,4 @@ block content div.sandwich h2 #{sandwich.SandwichName}: #{sandwich.dataValues.number} - script(src="/javascripts/index.js") + script(src="/javascripts/sandwiches.js")