This commit is contained in:
AndrewTrieu
2023-03-11 18:19:16 +02:00
parent ee0936c8b1
commit f14618b7cc
16 changed files with 70 additions and 59 deletions

View File

@@ -1,3 +0,0 @@
# flyctl launch added from .gitignore
**/.vscode/settings.json
fly.toml

View File

@@ -1,4 +1,4 @@
import { Application } from "./deps.js"; import { Application, Session } from "./deps.js";
import { authMiddleware } from "./middlewares/authMiddleware.js"; import { authMiddleware } from "./middlewares/authMiddleware.js";
import { errorMiddleware } from "./middlewares/errorMiddleware.js"; import { errorMiddleware } from "./middlewares/errorMiddleware.js";
import { renderMiddleware } from "./middlewares/renderMiddleware.js"; import { renderMiddleware } from "./middlewares/renderMiddleware.js";
@@ -7,7 +7,7 @@ import { serveStaticMiddleware } from "./middlewares/serveStaticMiddleware.js";
import { router } from "./routes/routes.js"; import { router } from "./routes/routes.js";
const app = new Application(); const app = new Application();
app.use(Session.initMiddleware());
app.use(errorMiddleware); app.use(errorMiddleware);
app.use(authMiddleware); app.use(authMiddleware);
app.use(userMiddleware); app.use(userMiddleware);

View File

@@ -1,8 +1,8 @@
const restrictedPaths = ["/topics", "/quiz"]; const restrictedPaths = ["/topics", "/quiz"];
const authMiddleware = async (context, next) => { const authMiddleware = async (context, next) => {
const user = await context.state.session?.get("user"); const user = await context.state.session.get("user");
console.log(user);
if ( if (
!user && !user &&
restrictedPaths.some((path) => restrictedPaths.some((path) =>

View File

@@ -1,7 +1,7 @@
import * as authService from "../services/authService.js"; import * as authService from "../services/authService.js";
const userMiddleware = async (context, next) => { const userMiddleware = async (context, next) => {
const user = await context.state.session?.get("user"); const user = await context.state.session.get("user");
if (user) { if (user) {
const userFromDatabase = await authService.findUser(user.email); const userFromDatabase = await authService.findUser(user.email);

View File

@@ -10,7 +10,7 @@ const addAnswer = async ({ request, response, params, state, render }) => {
const topicId = params.tId; const topicId = params.tId;
const questionId = params.qId; const questionId = params.qId;
const userId = (await state.session.get("user")).id; const userId = (await state.session.get("user")).id;
const body = request.body({ type: "form-data" }); const body = request.body({ type: "form" });
const formData = await body.value; const formData = await body.value;
const answerData = { const answerData = {
option: formData.get("option"), option: formData.get("option"),

View File

@@ -15,8 +15,10 @@ const showRegister = ({ render }) => {
}; };
const register = async ({ request, response, render }) => { const register = async ({ request, response, render }) => {
const body = request.body({ type: "form-data" }); const body = request.body({ type: "form" });
console.log(body);
const params = await body.value; const params = await body.value;
console.log(params);
const userData = { const userData = {
email: params.get("email"), email: params.get("email"),
password: params.get("password"), password: params.get("password"),
@@ -29,20 +31,18 @@ const register = async ({ request, response, render }) => {
render("register.eta", userData); render("register.eta", userData);
} else { } else {
const hashedPassword = await bcrypt.hash(userData.password); const hashedPassword = await bcrypt.hash(userData.password);
const user = await authService.createUser(userData.email, hashedPassword); await authService.createUser(userData.email, hashedPassword);
response.direct("/auth/login"); response.redirect("/auth/login");
} }
}; };
const login = async ({ request, response, state, render }) => { const login = async ({ request, response, state, render }) => {
const body = request.body({ type: "form" }); const body = request.body({ type: "form" });
const params = await body.value; const params = await body.value;
const userDatabase = await authService.findUser(params.get("email")); const userDatabase = await authService.findUser(params.get("email"));
if (userDatabase.length < 1) { if (userDatabase.length < 1) {
response.status = 422; response.status = 422;
render("login.eta", { error: "User not found!" }); render("login.eta", { error: { error: "User not found!" } });
return; return;
} }
@@ -54,12 +54,12 @@ const login = async ({ request, response, state, render }) => {
if (!passwordCorrect) { if (!passwordCorrect) {
response.status = 422; response.status = 422;
render("login.eta", { error: "Incorrect password!" }); render("login.eta", { errors: { error: "Incorrect password!" } });
return; return;
} }
await state.session.set("authenticated", user); await state.session.set("user", user);
response.direct("/topics"); response.redirect("/topics");
}; };
export { showLogin, showRegister, register, login }; export { showLogin, showRegister, register, login };

View File

@@ -10,7 +10,7 @@ const validationRules = {
const addQuestion = async ({ request, response, params, state, render }) => { const addQuestion = async ({ request, response, params, state, render }) => {
const topicId = params.tId; const topicId = params.tId;
const userId = (await state.session.get("user")).id; const userId = (await state.session.get("user")).id;
const body = request.body({ type: "form-data" }); const body = request.body({ type: "form" });
const formData = await body.value; const formData = await body.value;
const topicName = (await topicService.getTopicByTopicId(topicId)).name; const topicName = (await topicService.getTopicByTopicId(topicId)).name;
const questionData = { const questionData = {

View File

@@ -8,7 +8,7 @@ const validationRules = {
const addTopic = async ({ request, response, render, state }) => { const addTopic = async ({ request, response, render, state }) => {
const userId = (await state.session.get("user")).id; const userId = (await state.session.get("user")).id;
const admin = (await state.session.get("user")).admin; const admin = (await state.session.get("user")).admin;
const body = request.body({ type: "form-data" }); const body = request.body({ type: "form" });
const params = await body.value; const params = await body.value;
const topicData = { const topicData = {
admin: admin, admin: admin,
@@ -46,7 +46,7 @@ const listTopics = async ({ render, state }) => {
const user = await state.session.get("user"); const user = await state.session.get("user");
render("topics.eta", { render("topics.eta", {
admin: user.admin, admin: user.admin,
allTopics: await topicService.getAllTopics(), topics: await topicService.getAllTopics(),
}); });
}; };

View File

@@ -2,13 +2,13 @@ import { sql } from "../database/database.js";
const countAnswers = async () => { const countAnswers = async () => {
const result = await sql`SELECT COUNT(id) FROM question_answer_options`; const result = await sql`SELECT COUNT(id) FROM question_answer_options`;
return result.rows[0].count; return result[0].count;
}; };
const getAnswersByQuestionId = async (questionId) => { const getAnswersByQuestionId = async (questionId) => {
const result = const result =
await sql`SELECT * FROM question_answer_options WHERE question_id = ${questionId}`; await sql`SELECT * FROM question_answer_options WHERE question_id = ${questionId}`;
return result.rows; return result;
}; };
const addAnswer = async (questionId, optionText, isCorrect) => { const addAnswer = async (questionId, optionText, isCorrect) => {
@@ -23,13 +23,13 @@ const deleteAnswer = async (questionId, optionId) => {
const getCorrectOptionIds = async (questionId) => { const getCorrectOptionIds = async (questionId) => {
const result = const result =
await sql`SELECT id FROM question_answer_options WHERE question_id = ${questionId} AND is_correct = true`; await sql`SELECT id FROM question_answer_options WHERE question_id = ${questionId} AND is_correct = true`;
return result.rows; return result;
}; };
const getCorrectOptions = async (questionId) => { const getCorrectOptions = async (questionId) => {
const result = const result =
await sql`SELECT option_text FROM question_answer_options WHERE question_id = ${questionId} AND is_correct = true`; await sql`SELECT option_text FROM question_answer_options WHERE question_id = ${questionId} AND is_correct = true`;
return result.rows; return result;
}; };
const storeAnswer = async (userId, questionId, optionId) => { const storeAnswer = async (userId, questionId, optionId) => {

View File

@@ -2,17 +2,17 @@ import { sql } from "../database/database.js";
const countQuestions = async () => { const countQuestions = async () => {
const result = await sql`SELECT COUNT(id) FROM questions`; const result = await sql`SELECT COUNT(id) FROM questions`;
return result.rows[0].count; return result[0].count;
}; };
const getQuestionsByTopicId = async (topicId) => { const getQuestionsByTopicId = async (topicId) => {
const result = await sql`SELECT * FROM questions WHERE topic_id = ${topicId}`; const result = await sql`SELECT * FROM questions WHERE topic_id = ${topicId}`;
return result.rows; return result;
}; };
const getQuestionByQuestionId = async (questionId) => { const getQuestionByQuestionId = async (questionId) => {
const result = await sql`SELECT * FROM questions WHERE id = ${questionId}`; const result = await sql`SELECT * FROM questions WHERE id = ${questionId}`;
return result.rows[0]; return result[0];
}; };
const addQuestion = async (userId, topicId, question) => { const addQuestion = async (userId, topicId, question) => {
@@ -26,18 +26,18 @@ const deleteQuestion = async (questionId) => {
const getRandQuestion = async (topicId) => { const getRandQuestion = async (topicId) => {
const result = const result =
await sql`SELECT * FROM questions WHERE topic_id = ${topicId} ORDER BY RANDOM() LIMIT 1`; await sql`SELECT * FROM questions WHERE topic_id = ${topicId} ORDER BY RANDOM() LIMIT 1`;
if (result.rows.length === 0) { if (result.length === 0) {
return null; return null;
} }
return result.rows[0]; return result[0];
}; };
const getRandQuestionAPI = async () => { const getRandQuestionAPI = async () => {
const result = await sql`SELECT * FROM questions ORDER BY RANDOM() LIMIT 1`; const result = await sql`SELECT * FROM questions ORDER BY RANDOM() LIMIT 1`;
if (result.rows.length === 0) { if (result.length === 0) {
return null; return null;
} }
return result.rows[0]; return result[0];
}; };
export { export {

View File

@@ -6,23 +6,27 @@ const addTopic = async (userId, name) => {
const countTopics = async () => { const countTopics = async () => {
const result = await sql`SELECT COUNT(id) FROM topics`; const result = await sql`SELECT COUNT(id) FROM topics`;
return result.rows[0].count; console.log(result);
return result[0].count;
}; };
const getAllTopics = async () => { const getAllTopics = async () => {
await sql`SELECT * FROM topics ORDER BY name ASC`; const result = await sql`SELECT * FROM topics ORDER BY name ASC`;
return result.rows; console.log(result);
return result;
}; };
const getTopicsByUserId = async (userId) => { const getTopicsByUserId = async (userId) => {
const result = const result =
await sql`SELECT * FROM topics WHERE user_id = ${userId} ORDER BY name ASC`; await sql`SELECT * FROM topics WHERE user_id = ${userId} ORDER BY name ASC`;
return result.rows; console.log(result);
return result;
}; };
const getTopicByTopicId = async (topicId) => { const getTopicByTopicId = async (topicId) => {
const result = await sql`SELECT * FROM topics WHERE id = ${topicId}`; const result = await sql`SELECT * FROM topics WHERE id = ${topicId}`;
return result.rows[0]; console.log(result);
return result[0];
}; };
const deleteTopic = async (topicId) => { const deleteTopic = async (topicId) => {

View File

@@ -1,15 +1,15 @@
<!doctype html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>MCQ Application</title> <meta charset="UTF-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="https://unpkg.com/papercss@1.8.2/dist/paper.min.css">
<meta charset="utf-8"> <title>Quizzy Application</title>
</head> </head>
<body> <body>
<div class="container paper"> <div class="paper container">
<%~ it.body %> <%~ it.body %>
</div> </div>
</body> </body>
</html> </html>

View File

@@ -1,5 +1,7 @@
<% layout("./layouts/layout.eta") %> <% layout("./layouts/layout.eta") %>
<a href="/">Home</a>
<h1>Login</h1> <h1>Login</h1>
<form method="POST" action="/auth/login"> <form method="POST" action="/auth/login">
@@ -10,9 +12,13 @@
<input type="submit" value="Login" /> <input type="submit" value="Login" />
</form> </form>
<% if(it.error){ %> <% if (it.errors) { %>
<b><%= it.error %></b> <% Object.keys(it.errors).forEach((error) => { %>
<br/> <% Object.values(it.errors[error]).forEach((err) => { %>
<%= err %>
<% }); %>
<% }); %>
<% } %> <% } %>
<br/>
<a href="/auth/register">Are you a new user?</a> <a href="/auth/register">Are you a new user?</a>

View File

@@ -13,7 +13,7 @@
<h2>Statistics</h2> <h2>Statistics</h2>
<p>Total number of:</p> <p>Total number of:</p>
<ul> <ul>
<li>Topics: <%= it.topics %></li> <li>Topics: <%= it.totalTopics %></li>
<li>Questions: <%= it.questions %></li> <li>Questions: <%= it.totalQuestions %></li>
<li>Answers: <%= it.answers %></li> <li>Answers: <%= it.totalAnswers %></li>
</ul> </ul>

View File

@@ -1,5 +1,7 @@
<% layout("./layouts/layout.eta") %> <% layout("./layouts/layout.eta") %>
<a href="/">Home</a>
<h1>New user registration</h1> <h1>New user registration</h1>
<form method="POST" action="/auth/register"> <form method="POST" action="/auth/register">
@@ -18,4 +20,5 @@
<% }); %> <% }); %>
<% } %> <% } %>
<br/> <br/>
<a href="/auth/login">Are you already registered?</a> <a href="/auth/login">Are you already registered?</a>

View File

@@ -21,8 +21,9 @@
<p>No available topics.</p> <p>No available topics.</p>
<% } %> <% } %>
<% if (it.errors) { %>
<h2>Add a Topic</h2> <h2>Add a Topic</h2>
<% if (it.errors) { %>
<ul> <ul>
<% Object.keys(it.errors).forEach((error) => { %> <% Object.keys(it.errors).forEach((error) => { %>
<% Object.values(it.errors[error]).forEach((err) => { %> <% Object.values(it.errors[error]).forEach((err) => { %>