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 { errorMiddleware } from "./middlewares/errorMiddleware.js";
import { renderMiddleware } from "./middlewares/renderMiddleware.js";
@@ -7,7 +7,7 @@ import { serveStaticMiddleware } from "./middlewares/serveStaticMiddleware.js";
import { router } from "./routes/routes.js";
const app = new Application();
app.use(Session.initMiddleware());
app.use(errorMiddleware);
app.use(authMiddleware);
app.use(userMiddleware);

View File

@@ -1,8 +1,8 @@
const restrictedPaths = ["/topics", "/quiz"];
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 (
!user &&
restrictedPaths.some((path) =>

View File

@@ -1,7 +1,7 @@
import * as authService from "../services/authService.js";
const userMiddleware = async (context, next) => {
const user = await context.state.session?.get("user");
const user = await context.state.session.get("user");
if (user) {
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 questionId = params.qId;
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 answerData = {
option: formData.get("option"),

View File

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

View File

@@ -10,7 +10,7 @@ const validationRules = {
const addQuestion = async ({ request, response, params, state, render }) => {
const topicId = params.tId;
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 topicName = (await topicService.getTopicByTopicId(topicId)).name;
const questionData = {

View File

@@ -8,7 +8,7 @@ const validationRules = {
const addTopic = async ({ request, response, render, state }) => {
const userId = (await state.session.get("user")).id;
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 topicData = {
admin: admin,
@@ -46,7 +46,7 @@ const listTopics = async ({ render, state }) => {
const user = await state.session.get("user");
render("topics.eta", {
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 result = await sql`SELECT COUNT(id) FROM question_answer_options`;
return result.rows[0].count;
return result[0].count;
};
const getAnswersByQuestionId = async (questionId) => {
const result =
await sql`SELECT * FROM question_answer_options WHERE question_id = ${questionId}`;
return result.rows;
return result;
};
const addAnswer = async (questionId, optionText, isCorrect) => {
@@ -23,13 +23,13 @@ const deleteAnswer = async (questionId, optionId) => {
const getCorrectOptionIds = async (questionId) => {
const result =
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 result =
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) => {

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
<% layout("./layouts/layout.eta") %>
<a href="/">Home</a>
<h1>Login</h1>
<form method="POST" action="/auth/login">
@@ -10,9 +12,13 @@
<input type="submit" value="Login" />
</form>
<% if(it.error){ %>
<b><%= it.error %></b>
<br/>
<% if (it.errors) { %>
<% Object.keys(it.errors).forEach((error) => { %>
<% 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>
<p>Total number of:</p>
<ul>
<li>Topics: <%= it.topics %></li>
<li>Questions: <%= it.questions %></li>
<li>Answers: <%= it.answers %></li>
<li>Topics: <%= it.totalTopics %></li>
<li>Questions: <%= it.totalQuestions %></li>
<li>Answers: <%= it.totalAnswers %></li>
</ul>

View File

@@ -1,5 +1,7 @@
<% layout("./layouts/layout.eta") %>
<a href="/">Home</a>
<h1>New user registration</h1>
<form method="POST" action="/auth/register">
@@ -18,4 +20,5 @@
<% }); %>
<% } %>
<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>
<% } %>
<% if (it.errors) { %>
<h2>Add a Topic</h2>
<% if (it.errors) { %>
<ul>
<% Object.keys(it.errors).forEach((error) => { %>
<% Object.values(it.errors[error]).forEach((err) => { %>