From c0d110f3867dffb779e6a4c9a45119ca58dcc6ac Mon Sep 17 00:00:00 2001 From: Tobias Zoghaib Date: Thu, 14 Nov 2024 08:09:06 +0100 Subject: [PATCH] Implement exercise 1.1 (open help page) --- software/backend/data/exercises.json | 30 ++--- software/backend/routes/account.routes.ts | 3 +- software/backend/routes/exercise.routes.ts | 53 +++++++-- software/backend/routes/location.routes.ts | 1 - software/backend/scripts/databaseHelper.ts | 1 + .../navigation/navigationAppendItems.vue | 12 +- software/src/pages/misc/helpPage/index.vue | 2 +- software/src/stores/exercise.store.ts | 103 +++++++++++------- 8 files changed, 126 insertions(+), 79 deletions(-) diff --git a/software/backend/data/exercises.json b/software/backend/data/exercises.json index c230bd5..5c98b3a 100644 --- a/software/backend/data/exercises.json +++ b/software/backend/data/exercises.json @@ -10,16 +10,14 @@ "nameEn": "Register", "exerciseNr": 1, "descriptionDe": "Erstelle einen neuen Account im Online Shop", - "descriptionEn": "Create a new account in the online shop", - "solved": false + "descriptionEn": "Create a new account in the online shop" }, { "nameDe": "Ein Ticket kaufen", "nameEn": "Buy a ticket", "exerciseNr": 2, "descriptionDe": "Suche dir ein Event deiner Wahl und kaufe dafür ein Ticket", - "descriptionEn": "Search for an event of choice and buy a ticket for", - "solved": false + "descriptionEn": "Search for an event of choice and buy a ticket for" } ] }, @@ -33,16 +31,14 @@ "nameEn": "Access Help Page", "exerciseNr": 1, "descriptionDe": "Manipuliere die URL so, dass du die Hilfe-Seite erreichen kannst", - "descriptionEn": "Manipulate the URL and access the help page", - "solved": false + "descriptionEn": "Manipulate the URL and access the help page" }, { "nameDe": "Das ausgebuchte Konzert buchen", "nameEn": "Book the unavailable concert", "exerciseNr": 2, "descriptionDe": "Manipuliere die URL so, dass du das ausgebuchte Konzert aufrufen kannst und buche ein Ticket dafür", - "descriptionEn": "Manipulate the URL and access the sold out concert and buy a ticket", - "solved": false + "descriptionEn": "Manipulate the URL and access the sold out concert and buy a ticket" } ] }, @@ -56,24 +52,21 @@ "nameEn": "Readout account names", "exerciseNr": 1, "descriptionDe": "Lasse dir alle Accountnamen über das Suchfeld ausgeben", - "descriptionEn": "Readout all account names via the search field", - "solved": false + "descriptionEn": "Readout all account names via the search field" }, { "nameDe": "Passwort auslesen", "nameEn": "Readout password", "exerciseNr": 2, "descriptionDe": "Versuche ein Passwort aus der Datenbank eines Accounts auszulesen", - "descriptionEn": "Get the password of an account from the database", - "solved": false + "descriptionEn": "Get the password of an account from the database" }, { "nameDe": "Verändere deine Account Berechtigungen", "nameEn": "Change your account role", "exerciseNr": 3, "descriptionDe": "Ändere die Berechtigungen deines Accounts", - "descriptionEn": "Change the privileges of your account", - "solved": false + "descriptionEn": "Change the privileges of your account" } ] }, @@ -87,24 +80,21 @@ "nameEn": "Hello World!", "exerciseNr": 1, "descriptionDe": "Nimm dir eine URL des Shops und erweitere sie mit JavaScript Code so, dass beim Öffnen des Links eine 'Hallo Welt' Nachricht erscheint", - "descriptionEn": "Take an URL of the shop and extend it with JavaScript code so that a 'Hello World' message appears whent the link is opened", - "solved": false + "descriptionEn": "Take an URL of the shop and extend it with JavaScript code so that a 'Hello World' message appears whent the link is opened" }, { "nameDe": "Ein externes Script aufrufen", "nameEn": "Run an external script", "exerciseNr": 2, "descriptionDe": "Bearbeite die URL des Shops so, dass du das Script ausführen kannst", - "descriptionEn": "Create an URL of the shop, which calls the script", - "solved": false + "descriptionEn": "Create an URL of the shop, which calls the script" }, { "nameDe": "Hacken mit eigenem Script", "nameEn": "Hack with your script", "exerciseNr": 3, "descriptionDe": "Schreibe eine JavaScript Datei, lade sie über das Admin Panel hoch und kreiere eine URL, welche es ausführt", - "descriptionEn": "Write our own JavaScript file, upload it via Admin Panel and create an URL to execute it", - "solved": false + "descriptionEn": "Write our own JavaScript file, upload it via Admin Panel and create an URL to execute it" } ] } diff --git a/software/backend/routes/account.routes.ts b/software/backend/routes/account.routes.ts index 181c0d0..262cde5 100644 --- a/software/backend/routes/account.routes.ts +++ b/software/backend/routes/account.routes.ts @@ -21,11 +21,9 @@ account.get("/", (req: Request, res: Response) => { // Login user account.post("/login", async (req: Request, res: Response) => { // Using raw SQL code for SQL injections! - // todo: Inner join const [results, metadata] = await sequelize.query( "SELECT * FROM Accounts " + - "INNER JOIN Addresses ON Accounts.id=Addresses.accountId " + "WHERE (username='" + req.body.username + "' AND password='" + req.body.password + "')") @@ -42,6 +40,7 @@ account.post("/login", async (req: Request, res: Response) => { } if (results.length != 0) { + // Status: 200 OK res.status(200).json(results[0]) } else { diff --git a/software/backend/routes/exercise.routes.ts b/software/backend/routes/exercise.routes.ts index d12bd13..855c3f9 100644 --- a/software/backend/routes/exercise.routes.ts +++ b/software/backend/routes/exercise.routes.ts @@ -1,3 +1,4 @@ +import { Op } from "sequelize"; import { Exercise } from "../models/exercises/exercise.model"; import { ExerciseGroup } from "../models/exercises/exerciseGroup.model"; import { Request, Response, Router } from "express"; @@ -27,19 +28,47 @@ exercises.get("/", (req: Request, res: Response) => { * @param state New state boolean */ exercises.post("/:groupNr/:exerciseNr/:state", (req: Request, res: Response) => { - ExerciseGroup.findOne({ - where: { groupNr: req.params.groupNr } - }) - .then(group => { - Exercise.findOne({ - where: { - exerciseNr: req.params.exerciseNr, - exerciseGroupId: group.id + Exercise.findOne({ + where: { + [Op.and] : [ + { + exerciseNr: req.params.exerciseNr + }, + { + "$exerciseGroup.groupNr$": req.params.groupNr } - }) - .then(exercise => { - exercise.update({ solved: req.params.state == "1"}) - res.status(200).send() + ] + }, + include: [ ExerciseGroup ] + }) + .then(async exercise => { + let changed = false + + if (exercise.dataValues.solved != (req.params.state == "1")) { + await exercise.update({ solved: req.params.state == "1" }) + changed = true + } + + res.status(200).json({ + exercise: exercise, + changed: changed }) }) + + + // ExerciseGroup.findOne({ + // where: { groupNr: req.params.groupNr } + // }) + // .then(group => { + // Exercise.findOne({ + // where: { + // exerciseNr: req.params.exerciseNr, + // exerciseGroupId: group.id + // } + // }) + // .then(exercise => { + // exercise.update({ solved: req.params.state == "1"}) + // res.status(200).send() + // }) + // }) }) \ No newline at end of file diff --git a/software/backend/routes/location.routes.ts b/software/backend/routes/location.routes.ts index 12a4b17..c6d63e5 100644 --- a/software/backend/routes/location.routes.ts +++ b/software/backend/routes/location.routes.ts @@ -131,7 +131,6 @@ location.get("/search", (req: Request, res: Response) => { include: [ City, Concert ] }) .then(locations => { - console.log(locations) res.status(200).json(locations) }) }) \ No newline at end of file diff --git a/software/backend/scripts/databaseHelper.ts b/software/backend/scripts/databaseHelper.ts index ba9886a..20bd5f3 100644 --- a/software/backend/scripts/databaseHelper.ts +++ b/software/backend/scripts/databaseHelper.ts @@ -64,6 +64,7 @@ export async function prepopulateExerciseDatabase() { .then(async dataset => { for (let exercise of exerciseGroup.exercises) { exercise["exerciseGroupId"] = dataset.id + exercise["solved"] = false await Exercise.create(exercise) } diff --git a/software/src/components/navigation/navigationAppendItems.vue b/software/src/components/navigation/navigationAppendItems.vue index 477376b..ab9fb51 100644 --- a/software/src/components/navigation/navigationAppendItems.vue +++ b/software/src/components/navigation/navigationAppendItems.vue @@ -1,9 +1,13 @@ \ No newline at end of file diff --git a/software/src/pages/misc/helpPage/index.vue b/software/src/pages/misc/helpPage/index.vue index 84f7d38..9ecc30f 100644 --- a/software/src/pages/misc/helpPage/index.vue +++ b/software/src/pages/misc/helpPage/index.vue @@ -9,7 +9,7 @@ import { LanguageEnum } from '@/data/enums/languageEnum'; const exerciseStore = useExerciseStore() const preferencesStore = usePreferencesStore() -exerciseStore.getAllExercises() +exerciseStore.solveExercise(1, 1) function getDotColor(exerciseGroupNr: number) { switch(exerciseGroupNr) { diff --git a/software/src/stores/exercise.store.ts b/software/src/stores/exercise.store.ts index 1e98817..f22c2d4 100644 --- a/software/src/stores/exercise.store.ts +++ b/software/src/stores/exercise.store.ts @@ -11,7 +11,9 @@ export const useExerciseStore = defineStore("exerciseStore", { exercises: ref>([]), /** Request to server sent, waiting for data response */ - fetchInProgress: ref(false) + fetchInProgress: ref(false), + + helpPageVisible: ref(false) }), actions: { @@ -24,10 +26,26 @@ export const useExerciseStore = defineStore("exerciseStore", { await fetchAllExerciseGroups() .then(result => { this.exercises = result.data + + this.helpPageVisible = this.getExercise(1, 1).solved this.fetchInProgress = false }) }, + /** + * Get a exercise by group and exercise number + * + * @param exerciseGroupNr Number of group of exercise + * @param exerciseNr Number of exercise in group + * + * @returns ExerciseModel + */ + getExercise(exerciseGroupNr: number, exerciseNr: number): ExerciseModel { + return this.exercises.find((exercise: ExerciseModel) => { + return exercise.exerciseNr == exerciseNr && exercise.exerciseGroup.groupNr == exerciseGroupNr + }) + }, + /** * Mark an exercise as solved * @@ -42,56 +60,57 @@ export const useExerciseStore = defineStore("exerciseStore", { this.fetchInProgress = true // Change only if the exercise is not solved - if(!this.exerciseGroups[exerciseGroupNr].exercises[exerciseNr - 1].solved) { - updateExercise(exerciseGroupNr, exerciseNr, true) - .then(result => { + updateExercise(exerciseGroupNr, exerciseNr, true) + .then(result => { + if (result.data.changed) { + let bannerState = BannerStateEnum.ERROR switch(exerciseGroupNr) { - case 0: { - switch(exerciseNr) { - case 1: bannerState = BannerStateEnum.EXERCISESOLVED01; break; - case 2: bannerState = BannerStateEnum.EXERCISESOLVED02; break; - } - - break; + case 0: { + switch(exerciseNr) { + case 1: bannerState = BannerStateEnum.EXERCISESOLVED01; break; + case 2: bannerState = BannerStateEnum.EXERCISESOLVED02; break; } - case 1: { - switch(exerciseNr) { - case 1: bannerState = BannerStateEnum.EXERCISESOLVED11; break; - case 2: bannerState = BannerStateEnum.EXERCISESOLVED12; break; - case 3: bannerState = BannerStateEnum.EXERCISESOLVED13; break; - } - - break; - } - - case 2: { - switch(exerciseNr) { - case 1: bannerState = BannerStateEnum.EXERCISESOLVED21; break; - case 2: bannerState = BannerStateEnum.EXERCISESOLVED22; break; - case 3: bannerState = BannerStateEnum.EXERCISESOLVED23; break; - } - - break; - } - - case 3: { - switch(exerciseNr) { - case 1: bannerState = BannerStateEnum.EXERCISESOLVED31; break; - case 2: bannerState = BannerStateEnum.EXERCISESOLVED32; break; - case 3: bannerState = BannerStateEnum.EXERCISESOLVED33; break; - } - - break; - } + break; } + case 1: { + switch(exerciseNr) { + case 1: bannerState = BannerStateEnum.EXERCISESOLVED11; break; + case 2: bannerState = BannerStateEnum.EXERCISESOLVED12; break; + case 3: bannerState = BannerStateEnum.EXERCISESOLVED13; break; + } + + break; + } + + case 2: { + switch(exerciseNr) { + case 1: bannerState = BannerStateEnum.EXERCISESOLVED21; break; + case 2: bannerState = BannerStateEnum.EXERCISESOLVED22; break; + case 3: bannerState = BannerStateEnum.EXERCISESOLVED23; break; + } + + break; + } + + case 3: { + switch(exerciseNr) { + case 1: bannerState = BannerStateEnum.EXERCISESOLVED31; break; + case 2: bannerState = BannerStateEnum.EXERCISESOLVED32; break; + case 3: bannerState = BannerStateEnum.EXERCISESOLVED33; break; + } + + break; + } + } + feedbackStore.changeBanner(bannerState) this.getAllExercises() - }) - } + } + }) } } }) \ No newline at end of file