From c1dac67d7655a5e82e6f91803a8caa5eff59acb8 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sat, 10 Oct 2020 13:32:08 +0200
Subject: Updated installation instructions
---
README.md | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 1592e41..1ab28fe 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,12 @@
# Abizeugs
-These are some tools for our Abitur (2021). They are very poorly written and should never be used by anyone except me.
+These are some tools for our Abitur (2021). They are very poorly written and should never be used by anyone except us (RBS TG13).
+
+## Installation
+* Install `nodejs`, `npm`, `redis` and `mariadb`. As the installation instructions vary depending on the platform, please look it up on your own
+* Start `redis` and `mariadb`
+* Create a `mariadb` database
+* Copy `.env.example` to `.env` and edit the file accordingly
+* Edit `mottos.txt`, `poll.txt` and `name.csv` (not published due to data protection)
+* Run `npm i`
+* Start the server with `node app`
--
cgit v1.2.3
From 167600b52eb03801bb7051a09dcb0e4f159cfb2a Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sat, 10 Oct 2020 13:51:42 +0200
Subject: Added note if finished
---
poll/public/script.js | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/poll/public/script.js b/poll/public/script.js
index 8c56894..09f8c93 100644
--- a/poll/public/script.js
+++ b/poll/public/script.js
@@ -29,7 +29,19 @@ fetch("/auth/api/list" + (type == "teacher" ? "?class=teacher" : ""))
.then((response) => appendOption(response));
fetch("/poll/api/get?type=" + type)
- .then((response) => response.json())
+ .then(async (response) => {
+ let json;
+ try {
+ return await response.json();
+ } catch (e) {
+ document.querySelector("p").innerText = "";
+ question_label.innerText = "Du hast bereits alle Fragen beantwortet.";
+ document.querySelectorAll("label")[1].innerText = "Danke!";
+ document.querySelector("select").style.display = "none";
+ document.querySelector("button").style.display = "none";
+ throw "Oh nein, alle beantwortet!"; // :^)
+ }
+ })
.then((response) => {
question_label.innerText = response["question"];
question_input.setAttribute("value", response["id"]);
--
cgit v1.2.3
From 72f5731adeebf8d76c5c2dcc266f600ba57812d8 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sat, 10 Oct 2020 17:05:27 +0200
Subject: Added basic admin interface
---
admin/index.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
admin/public/index.html | 32 +++++++++++++++++++++++++++++
admin/public/script.js | 22 ++++++++++++++++++++
admin/public/style.css | 33 ++++++++++++++++++++++++++++++
app.js | 4 +++-
auth/index.js | 18 +++++++++++++----
mottovote/index.js | 8 --------
tables.sql | 1 +
8 files changed, 158 insertions(+), 13 deletions(-)
create mode 100644 admin/index.js
create mode 100644 admin/public/index.html
create mode 100644 admin/public/script.js
create mode 100644 admin/public/style.css
diff --git a/admin/index.js b/admin/index.js
new file mode 100644
index 0000000..4cea14d
--- /dev/null
+++ b/admin/index.js
@@ -0,0 +1,53 @@
+const express = require("express");
+const db = require("../db");
+const app = express.Router();
+const { checkUser, checkAdmin } = require("../auth");
+
+app.use("/", checkAdmin, express.static(__dirname + "/public"));
+
+// For debugging ig
+app.get("/api/all", checkAdmin, async (req, res) => {
+ const all = [];
+
+ const types = await db.query("SELECT * FROM types ORDER BY id");
+ const clazz = await db.query("SELECT * FROM class ORDER BY id");
+ const users = await db.query("SELECT * FROM users ORDER BY id");
+ const quotes = await db.query("SELECT * FROM quotes ORDER BY id");
+ const ranking_questions = await db.query("SELECT * FROM ranking_questions ORDER BY id");
+ const ranking_answers = await db.query("SELECT * FROM ranking_answers ORDER BY id");
+ const mottos = await db.query("SELECT * FROM mottos ORDER BY id");
+ const motto_votes = await db.query("SELECT * FROM motto_votes ORDER BY id");
+
+ all.push(
+ { quotes },
+ { clazz },
+ { users },
+ { quotes },
+ { ranking_questions },
+ { ranking_answers },
+ { mottos },
+ { motto_votes },
+ );
+ res.json(all);
+});
+
+app.get("/api/questions", checkAdmin, async (req, res) => {
+ const questions = await db.query("SELECT q.id, question, t.name type FROM ranking_questions q INNER JOIN types t on type_id = t.id ORDER BY q.id");
+ res.json(questions);
+});
+
+app.get("/api/answers", checkAdmin, async (req, res) => {
+ const answers = await db.query(
+ "SELECT question_id, name, middlename, surname, count(*) count FROM ranking_questions q INNER JOIN ranking_answers a ON q.id = a.question_id INNER JOIN users u ON answer_id = u.id GROUP BY question_id, answer_id ORDER BY count DESC"
+ );
+ res.json(answers);
+});
+
+app.get("/api/votes", checkAdmin, async (req, res) => {
+ const votes = await db.query(
+ "SELECT m.id, m.name, m.description, SUM(votes) votes FROM motto_votes mv RIGHT JOIN mottos m on mv.motto_id = m.id GROUP BY m.id, m.name, m.description ORDER BY SUM(votes) DESC",
+ );
+ res.json(votes);
+});
+
+module.exports = app;
diff --git a/admin/public/index.html b/admin/public/index.html
new file mode 100644
index 0000000..cf5d286
--- /dev/null
+++ b/admin/public/index.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ Home
+
+
+
+
+
+
+ Welche/r Schüler/in...
+
+ Welche/r Lehrer/in...
+
+
+
+
+
+
diff --git a/admin/public/script.js b/admin/public/script.js
new file mode 100644
index 0000000..ff6fa2b
--- /dev/null
+++ b/admin/public/script.js
@@ -0,0 +1,22 @@
+fetch("api/questions").then(questions => questions.json()).then(questions => {
+ fetch("api/answers").then(answers => answers.json()).then(answers => {
+ questions.forEach(question => question.answers = []);
+ answers.forEach(answer => questions[answer.question_id - 1].answers.push(answer));
+ render(questions);
+ });
+});
+
+function render(questions)
+{
+ console.log(questions);
+ const teacher = document.querySelector("ul#teacher");
+ const pupil = document.querySelector("ul#pupil");
+ questions.forEach(question => {
+ const list = question.type === "teacher" ? teacher : pupil;
+ let answers = "";
+ question.answers.forEach(answer => {
+ answers += `${answer.name} ${answer.middlename ? answer.middlename + " " : ""}${answer.surname}: ${answer.count}`
+ });
+ list.insertAdjacentHTML("beforeend", `${question.question}
${answers}
`);
+ });
+}
diff --git a/admin/public/style.css b/admin/public/style.css
new file mode 100644
index 0000000..77853bf
--- /dev/null
+++ b/admin/public/style.css
@@ -0,0 +1,33 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ height: 100%;
+ width: 100%;
+ background-color: #eec0c6;
+ background-image: linear-gradient(315deg, #eec0c6 0%, #7ee8fa 74%);
+}
+
+.card {
+ position: absolute;
+ max-height: 80%;
+ overflow: auto;
+ width: 30%;
+ left: 50%;
+ top: 50%;
+ -webkit-transform: translate(-50%, -50%);
+ transform: translate(-50%, -50%);
+ padding: 20px;
+ border-radius: 10px;
+ background: white;
+}
+
+div {
+ background: white;
+}
+
+@media only screen and (max-width: 600px) {
+ .card {
+ width: calc(100% - 50px);
+ }
+}
diff --git a/app.js b/app.js
index 5ddfdb7..e07aaaa 100644
--- a/app.js
+++ b/app.js
@@ -2,10 +2,11 @@ require("dotenv").config();
const express = require("express");
const session = require("express-session");
-const { auth, checkUser } = require("./auth");
+const { auth, checkUser, checkAdmin } = require("./auth");
const mottovote = require("./mottovote");
const quotes = require("./quotes");
const poll = require("./poll");
+const admin = require("./admin");
const app = express();
@@ -30,6 +31,7 @@ app.use("/", express.static(__dirname + "/overview/public"));
app.use("/mottovote", checkUser, mottovote);
app.use("/quotes", checkUser, quotes);
app.use("/poll", checkUser, poll);
+app.use("/admin", checkAdmin, admin);
app.use("/auth", auth);
app.listen(process.env.PORT || 5005, () => console.log("Server started on http://localhost:5005"));
diff --git a/auth/index.js b/auth/index.js
index 1ea6290..40062cc 100644
--- a/auth/index.js
+++ b/auth/index.js
@@ -4,14 +4,24 @@ const db = require("../db");
const app = express.Router();
-// TODO: Change passwords
-// TODO: Login (+ Frontend, cookie, etc)
-
function checkUser(req, res, next) {
if (req.session.loggedIn) next();
else res.redirect("/auth");
}
+function checkAdmin(req, res, next) {
+ if (!req.session.loggedIn) res.redirect("/auth");
+
+ try {
+ db.query("SELECT is_admin FROM users WHERE id = ?", [req.session.uid]).then((ret) => {
+ if (ret[0].is_admin == 1) next();
+ else res.redirect("/");
+ });
+ } catch (e) {
+ res.redirect("/");
+ }
+}
+
app.use(
"/",
(req, res, next) => {
@@ -81,4 +91,4 @@ app.get("/api/list", checkUser, async (req, res) => {
app.get("/api/status", (req, res) => res.json({ loggedIn: req.session.loggedIn }));
-module.exports = { auth: app, checkUser };
+module.exports = { auth: app, checkUser, checkAdmin };
diff --git a/mottovote/index.js b/mottovote/index.js
index d0af6e3..2df985d 100644
--- a/mottovote/index.js
+++ b/mottovote/index.js
@@ -34,12 +34,4 @@ app.put("/api/vote", checkUser, async (req, res) => {
}
});
-// Vote result - admin
-app.get("/api/get", checkUser, async (req, res) => {
- const votes = await db.query(
- "SELECT m.id, m.name, m.description, SUM(votes) votes FROM motto_votes mv RIGHT JOIN mottos m on mv.motto_id = m.id GROUP BY m.id, m.name, m.description ORDER BY SUM(votes) DESC",
- );
- res.json(votes);
-});
-
module.exports = app;
diff --git a/tables.sql b/tables.sql
index e0bc160..9f139f2 100644
--- a/tables.sql
+++ b/tables.sql
@@ -27,6 +27,7 @@ CREATE TABLE IF NOT EXISTS users(
password VARCHAR(255) NOT NULL,
class_id INTEGER NOT NULL,
type_id INTEGER NOT NULL,
+ is_admin BOOLEAN DEFAULT FALSE,
UNIQUE KEY uk_name (name, middlename, surname),
CONSTRAINT `fk_class_user` FOREIGN KEY (class_id) REFERENCES class (id),
--
cgit v1.2.3
From b2d9cf884f2aff3445d6619939186e48a683e5a9 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sat, 10 Oct 2020 17:10:01 +0200
Subject: Welp, formatting :D
---
admin/index.js | 6 ++++--
admin/public/index.html | 14 +++++++-------
admin/public/script.js | 45 +++++++++++++++++++++++++--------------------
3 files changed, 36 insertions(+), 29 deletions(-)
diff --git a/admin/index.js b/admin/index.js
index 4cea14d..407bbcf 100644
--- a/admin/index.js
+++ b/admin/index.js
@@ -32,13 +32,15 @@ app.get("/api/all", checkAdmin, async (req, res) => {
});
app.get("/api/questions", checkAdmin, async (req, res) => {
- const questions = await db.query("SELECT q.id, question, t.name type FROM ranking_questions q INNER JOIN types t on type_id = t.id ORDER BY q.id");
+ const questions = await db.query(
+ "SELECT q.id, question, t.name type FROM ranking_questions q INNER JOIN types t on type_id = t.id ORDER BY q.id",
+ );
res.json(questions);
});
app.get("/api/answers", checkAdmin, async (req, res) => {
const answers = await db.query(
- "SELECT question_id, name, middlename, surname, count(*) count FROM ranking_questions q INNER JOIN ranking_answers a ON q.id = a.question_id INNER JOIN users u ON answer_id = u.id GROUP BY question_id, answer_id ORDER BY count DESC"
+ "SELECT question_id, name, middlename, surname, count(*) count FROM ranking_questions q INNER JOIN ranking_answers a ON q.id = a.question_id INNER JOIN users u ON answer_id = u.id GROUP BY question_id, answer_id ORDER BY count DESC",
);
res.json(answers);
});
diff --git a/admin/public/index.html b/admin/public/index.html
index cf5d286..a611291 100644
--- a/admin/public/index.html
+++ b/admin/public/index.html
@@ -19,14 +19,14 @@
-
+
- Welche/r Schüler/in...
-
- Welche/r Lehrer/in...
-
-
+ Welche/r Schüler/in...
+
+ Welche/r Lehrer/in...
+
+
-
+