Archived
1
0
Fork 0

Setup login/register/logout in layout, move more from index to layout, add more columns to user model, use logged user to fill oder form

This commit is contained in:
Ethanell 2020-08-17 16:54:43 +02:00
parent ffe31c6af9
commit 2ca80e5300
15 changed files with 210 additions and 78 deletions

2
app.js
View file

@ -6,6 +6,7 @@ let logger = require("morgan");
let config = require("./config/config.json"); let config = require("./config/config.json");
let indexRouter = require("./routes/index"); let indexRouter = require("./routes/index");
let registerRouter = require("./routes/register");
let loginRouter = require("./routes/login"); let loginRouter = require("./routes/login");
let logoutRouter = require("./routes/logout"); let logoutRouter = require("./routes/logout");
let commandRouter = require("./routes/command"); let commandRouter = require("./routes/command");
@ -36,6 +37,7 @@ app.use(session(sess));
app.use(express.static(path.join(__dirname, "public"))); app.use(express.static(path.join(__dirname, "public")));
app.use("/", indexRouter); app.use("/", indexRouter);
app.use("/register", registerRouter);
app.use("/login", loginRouter); app.use("/login", loginRouter);
app.use("/logout", logoutRouter); app.use("/logout", logoutRouter);
app.use("/command", commandRouter); app.use("/command", commandRouter);

View file

@ -6,6 +6,7 @@ module.exports = (sequelize, DataTypes) => {
class Department extends Model { class Department extends Model {
static associate(models) { static associate(models) {
Department.hasMany(models.Command); Department.hasMany(models.Command);
Department.hasMany(models.User);
} }
} }
Department.init({ Department.init({

View file

@ -5,6 +5,7 @@ const {
module.exports = (sequelize, DataTypes) => { module.exports = (sequelize, DataTypes) => {
class User extends Model { class User extends Model {
static associate(models) { static associate(models) {
User.belongsTo(models.Department);
} }
checkPassword(password) { checkPassword(password) {
@ -19,6 +20,23 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.STRING, type: DataTypes.STRING,
primaryKey: true primaryKey: true
}, },
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
isEmail: true
}
},
firstName: {
type: DataTypes.STRING,
allowNull: false,
unique: "userFullName"
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
unique: "userFullName"
},
passwordHash: { passwordHash: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false, allowNull: false,

View file

@ -1,9 +1,5 @@
const commandAction = document.getElementById("command-action"); const commandAction = document.getElementById("command-action");
const rmButton = document.getElementById("remove-command"); const rmButton = document.getElementById("remove-command");
const more = document.getElementById("more");
const dark = document.getElementById("dark");
const about = document.getElementById("about");
const contact = document.getElementById("contact");
function lastCommandId() { function lastCommandId() {
let list = document.querySelectorAll("div.command h2"); let list = document.querySelectorAll("div.command h2");
@ -33,21 +29,3 @@ rmButton.addEventListener("click", () => {
if (id === 2) if (id === 2)
rmButton.classList.add("hide"); rmButton.classList.add("hide");
}); });
more.firstChild.addEventListener("click", () => {
dark.classList.remove("hide");
about.classList.remove("hide");
});
more.lastChild.addEventListener("click", () => {
dark.classList.remove("hide");
contact.classList.remove("hide")
});
dark.addEventListener("click", () => {
dark.classList.add("hide");
if (! about.classList.contains("hide"))
about.classList.add("hide");
else
contact.classList.add("hide");
});

View file

@ -0,0 +1,23 @@
const more = document.getElementById("more");
const dark = document.getElementById("dark");
const about = document.getElementById("about");
const contact = document.getElementById("contact");
more.firstChild.addEventListener("click", () => {
dark.classList.remove("hide");
about.classList.remove("hide");
});
more.lastChild.addEventListener("click", () => {
dark.classList.remove("hide");
contact.classList.remove("hide")
});
dark.addEventListener("click", () => {
dark.classList.add("hide");
if (! about.classList.contains("hide"))
about.classList.add("hide");
else
contact.classList.add("hide");
});

View file

@ -56,8 +56,8 @@ a {
font-size: 100%; font-size: 100%;
} }
.field input[type="text"], .field input[type="list"], .field input[type="date"], .field input[type="number"], .field input[type="text"], .field input[type="list"], .field input[type="date"], .field input[type="password"],
.field input[type="checkbox"] { .field input[type="number"], .field input[type="checkbox"], .field input[type="email"] {
height: 2.5vh; height: 2.5vh;
border-top: none; border-top: none;
border-left: none; border-left: none;
@ -165,6 +165,26 @@ p.before-link a::before {
justify-content: space-around; justify-content: space-around;
} }
#user {
position: fixed;
top: 0;
right: 0;
display: flex;
padding: 0.3em;
background-color: white;
border-radius: 0 0 0.3em 0.3em;
box-shadow: 0.5em 0.5em 0.5em rgba(0, 0, 255, .2);
}
#user>p, #user>a {
margin: 0.1em;
}
#user>a {
text-decoration: underline;
color: black;
}
@media (hover: none) and (pointer: coarse) { @media (hover: none) and (pointer: coarse) {
body { body {
font-size: xx-large; font-size: xx-large;

View file

@ -5,7 +5,7 @@ let models = require("../models");
router.get("/", sessionCheck(3), async (req, res) => { router.get("/", sessionCheck(3), async (req, res) => {
res.render("admin", {title: "SOD", sandwiches: await models.Sandwich.findAll(), users: await models.User.findAll()}); res.render("admin", {title: "SOD", user: req.session.user, sandwiches: await models.Sandwich.findAll(), users: await models.User.findAll()});
}); });
module.exports = router; module.exports = router;

View file

@ -5,7 +5,7 @@ let models = require("../models");
router.get("/", async (req, res) => { router.get("/", async (req, res) => {
let departments = await models.Department.findAll(); let departments = await models.Department.findAll();
let sandwiches = await models.Sandwich.findAll(); let sandwiches = await models.Sandwich.findAll();
res.render("index", { title: "SOD", departments: departments, sandwiches: sandwiches }); res.render("index", { title: "SOD", user: req.session.user, departments: departments, sandwiches: sandwiches });
}); });
module.exports = router; module.exports = router;

View file

@ -23,7 +23,7 @@ router.get("/", sessionCheck(2), async (req, res) => {
commands[i.Command.DepartmentName][name][i.Command.id] = [] commands[i.Command.DepartmentName][name][i.Command.id] = []
commands[i.Command.DepartmentName][name][i.Command.id].push(i); commands[i.Command.DepartmentName][name][i.Command.id].push(i);
} }
res.render("orders", {title: "SOD", commands: commands, date: date}); res.render("orders", {title: "SOD", user: req.session.user, commands: commands, date: date});
}); });
module.exports = router; module.exports = router;

50
routes/register.js Normal file
View file

@ -0,0 +1,50 @@
let express = require("express");
let router = express.Router();
let models = require("../models");
router.get("/", async (req, res) => {
if (req.session.user)
res.redirect("/");
else
res.render("register", {title: "SOD", 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)
res.render("error", {message: "Invalid register !", error: {status: "Missing args"}});
else if (await models.User.findByPk(req.body.username))
res.render("error", {message: "Invalid register !",
error: {status: "Username already taken"}});
else if (await models.User.findOne({where: {firstName: req.body.firstName,
lastName: req.body.lastName}}))
res.render("error", {message: "Invalid register !",
error: {status: "First & last name already register"}});
else if (await models.User.findOne({where: {email: req.body.email}}))
res.render("error", {message: "Invalid register !", error: {status: "Email already used"}});
else {
let department = await models.Department.findByPk(req.body.department);
if (!department)
res.render("error", {message: "Invalid register !",
error: {status: "Invalid department"}});
else {
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);
req.session.user = user;
res.redirect("/");
} catch (e) {
res.render("error", {message: "Registration fail !", error: {}});
throw e;
}
}
}
});
module.exports = router;

View file

@ -10,6 +10,7 @@ router.get("/", sessionCheck(1), async (req, res) => {
res.render("sandwiches", { res.render("sandwiches", {
title: "SOD", title: "SOD",
user: req.session.user,
sandwiches: await models.SandwichCommand.findAll({ sandwiches: await models.SandwichCommand.findAll({
attributes: ["SandwichName", [sequelize.fn("COUNT", sequelize.col("SandwichName")), "number"]], attributes: ["SandwichName", [sequelize.fn("COUNT", sequelize.col("SandwichName")), "number"]],
where: {date: date}, where: {date: date},

View file

@ -7,17 +7,17 @@ block content
form#command(action="/command" method="POST") form#command(action="/command" method="POST")
div.field div.field
label(for="department") Department: label(for="department") Department:
input#department(type="list" list="department-list" name="department" autocomplete="off" required) input#department(type="list" list="department-list" name="department" value=user ? user.DepartmentName : "" autocomplete="off" required)
datalist#department-list datalist#department-list
each department in departments each department in departments
option(value=department.name) option(value=department.name)
div.field div.field
label(for="firstname") First name: label(for="firstname") First name:
input#firstname(type="text" name="firstName" required) input#firstname(type="text" name="firstName" value=user ? user.firstName : "" required)
div.field div.field
label(for="lastname") Last name: label(for="lastname") Last name:
input#lastname(type="text" name="lastName" required) input#lastname(type="text" name="lastName" value=user ? user.lastName : "" required)
div#command1.command div#command1.command
h2 Command 1 h2 Command 1
@ -39,50 +39,4 @@ block content
each sandwich in sandwiches each sandwich in sandwiches
option(value=sandwich.name) option(value=sandwich.name)
div#more
a About
a Contact
div#dark.hide
div#about.popup.card.hide
h1 About
p This software respond to the COVID-19 health crisis for the following students' offices food supply
div.images
div
img(src="images/logoBio.png")
p Bio student office
div
img(src="images/logoChimie.png")
p Chemical student office
div
img(src="images/logoGC.png")
p Civil engineering student office
div
img(src="images/logoGCGP.png")
p Chemical and process engineering student office
div
img(src="images/logoGEA.png")
p Management of companies and administrations student office
div
img(src="images/logoInfo.png")
p IT student office
p.before-link Made with ❤️ by
a(href="https://www.linkedin.com/in/florian-charlaix" target="_blank") Florian Charlaix
div#contact.popup.card.hide
h1 Contact
p.before-link Order issue:
a(href="mailto: ") test@test.fr
p.before-link Bio student office:
a(href="mailto: ")
p.before-link Chemical student office:
a(href="mailto: ")
p.before-link Civil engineering student office:
a(href="mailto: ")
p.before-link Chemical and process engineering student office:
a(href="mailto: bde.gcgp.lyon1@gmail.com") bde.gcgp.lyon1@gmail.com
p.before-link Management of companies and administrations student office:
a(href="mailto: ")
p.before-link IT student office:
a(href="mailto: contact@bde-info.org") contact@bde-info.org
script(src="javascripts/index.js") script(src="javascripts/index.js")

View file

@ -5,3 +5,59 @@ html
link(rel="stylesheet", href="/stylesheets/style.css") link(rel="stylesheet", href="/stylesheets/style.css")
body body
block content block content
div#user
if user
p=user.username
a(href="/logout") Logout
else
a(href="/login") Login
a(href="/register") Register
div#more
a About
a Contact
div#dark.hide
div#about.popup.card.hide
h1 About
p This software respond to the COVID-19 health crisis for the following students' offices food supply
div.images
div
img(src="images/logoBio.png")
p Bio student office
div
img(src="images/logoChimie.png")
p Chemical student office
div
img(src="images/logoGC.png")
p Civil engineering student office
div
img(src="images/logoGCGP.png")
p Chemical and process engineering student office
div
img(src="images/logoGEA.png")
p Management of companies and administrations student office
div
img(src="images/logoInfo.png")
p IT student office
p.before-link Made with ❤️ by
a(href="https://www.linkedin.com/in/florian-charlaix" target="_blank") Florian Charlaix
div#contact.popup.card.hide
h1 Contact
p.before-link Order issue:
a(href="mailto: ") test@test.fr
p.before-link Bio student office:
a(href="mailto: ")
p.before-link Chemical student office:
a(href="mailto: ")
p.before-link Civil engineering student office:
a(href="mailto: ")
p.before-link Chemical and process engineering student office:
a(href="mailto: bde.gcgp.lyon1@gmail.com") bde.gcgp.lyon1@gmail.com
p.before-link Management of companies and administrations student office:
a(href="mailto: ")
p.before-link IT student office:
a(href="mailto: contact@bde-info.org") contact@bde-info.org
script(src="javascripts/layout.js")

View file

@ -6,8 +6,8 @@ block content
div.field div.field
label(for="username") Username: label(for="username") Username:
input#username(type="text" name="username" required) input#username(type="text" name="username" required)
dov.field div.field
label(for="password") Username: label(for="password") Password:
input#password(type="password" name="password" required) input#password(type="password" name="password" required)
div.field div.field
input(type="submit" value="Login") input(type="submit" value="Login")

29
views/register.pug Normal file
View file

@ -0,0 +1,29 @@
extends layout
block content
form.card(action="/register" method="POST")
h1 Register
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") First name:
input#firstName(type="text" name="firstName" required)
div.field
label(for="lastName") Last name:
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
input(type="submit" value="Register")
datalist#department-list
each department in departments
option(value=department.name)