Update
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
# flyctl launch added from .gitignore
|
|
||||||
**/.vscode/settings.json
|
|
||||||
fly.toml
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) =>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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) => { %>
|
||||||
|
|||||||
Reference in New Issue
Block a user