From e2c45c6be05dfbf429c8b344bf920ba1c1465813 Mon Sep 17 00:00:00 2001 From: TobiZog Date: Mon, 18 Nov 2024 15:41:33 +0100 Subject: [PATCH] Exercisegroup 0 and 1 complete implemented --- software/backend/data/accountRoles.json | 16 ++++- software/backend/data/bands-concerts.json | 64 +++++++++---------- software/backend/data/exercises.json | 34 ++++++++-- software/backend/data/orders.json | 10 +-- .../models/exercises/exerciseGroup.model.ts | 6 ++ .../backend/models/user/accountRole.model.ts | 3 + software/backend/routes/account.routes.ts | 18 +----- software/backend/scripts/databaseHelper.ts | 5 +- software/src/data/enums/bannerStateEnum.ts | 2 + .../models/exercises/exerciseGroupModel.ts | 2 + software/src/locales/de.json | 1 + software/src/locales/en.json | 1 + .../src/pages/admin/dashboardPage/index.vue | 4 ++ .../concerts/concertBookingPage/index.vue | 9 ++- software/src/stores/account.store.ts | 11 ++++ software/src/stores/basket.store.ts | 13 ++-- software/src/stores/exercise.store.ts | 1 + software/src/stores/feedback.store.ts | 18 +++--- 18 files changed, 138 insertions(+), 80 deletions(-) diff --git a/software/backend/data/accountRoles.json b/software/backend/data/accountRoles.json index e795819..6961582 100644 --- a/software/backend/data/accountRoles.json +++ b/software/backend/data/accountRoles.json @@ -4,19 +4,29 @@ "id": 0, "name": "Unregistered", "privilegeBuy": false, - "privilegeAdminPanel": false + "privilegeAdminPanel": false, + "privilegeFileAccess": false }, { "id": 1, "name": "User", "privilegeBuy": true, - "privilegeAdminPanel": false + "privilegeAdminPanel": false, + "privilegeFileAccess": false }, { "id": 2, "name": "Admin", "privilegeBuy": true, - "privilegeAdminPanel": true + "privilegeAdminPanel": true, + "privilegeFileAccess": false + }, + { + "id": 3, + "name": "Super-Admin", + "privilegeBuy": true, + "privilegeAdminPanel": true, + "privilegeFileAccess": true } ] } \ No newline at end of file diff --git a/software/backend/data/bands-concerts.json b/software/backend/data/bands-concerts.json index 34171da..99f010d 100644 --- a/software/backend/data/bands-concerts.json +++ b/software/backend/data/bands-concerts.json @@ -72,31 +72,31 @@ "image": "concerts/unlimited-love-tour.jpg", "concerts": [ { - "date": "2024-10-18", - "price": 92, - "inStock": 0, - "location": "Swiss Life Hall" - }, - { - "date": "2024-10-20", + "date": "1", "price": 92, "inStock": 170, "location": "Swiss Life Hall" }, { - "date": "2024-11-02", + "date": "4", + "price": 92, + "inStock": 170, + "location": "Swiss Life Hall" + }, + { + "date": "8", "price": 119.90, "inStock": 8736, "location": "Olympiahalle München" }, { - "date": "2024-11-05", + "date": "12", "price": 114.90, "inStock": 2793, "location": "Barclays Arena" }, { - "date": "2024-11-09", + "date": "13", "price": 124.90, "inStock": 3079, "location": "Uber Arena Berlin" @@ -162,19 +162,19 @@ "image": "concerts/the-bends-tour.jpg", "concerts": [ { - "date": "2024-11-30", + "date": "10", "price": 108, "inStock": 1200, "location": "Capitol" }, { - "date": "2024-12-01", + "date": "14", "price": 104, "inStock": 1800, "location": "Schlachthof München" }, { - "date": "2024-12-07", + "date": "16", "price": 99.90, "inStock": 2438, "location": "Waldbühne Berlin" @@ -242,20 +242,20 @@ "image": "concerts/european-tour-arctic-monkeys.jpg", "concerts": [ { - "date": "2025-01-21", + "date": "18", "price": 67.90, "inStock": 994, "location": "Kulturzentrum Faust" }, { - "date": "2024-10-30", + "date": "21", "price": 79.90, "inStock": 1073, "location": "LANXESS arena", "offered": false }, { - "date": "2024-10-23", + "date": "24", "price": 74.90, "inStock": 100, "location": "Columbiahalle" @@ -318,19 +318,19 @@ "image": "concerts/music-of-the-spheres.png", "concerts": [ { - "date": "2024-12-07", + "date": "8", "price": 124.90, "inStock": 765, "location": "Astra Kulturhaus" }, { - "date": "2025-01-17", + "date": "15", "price": 129.90, "inStock": 989, "location": "Waldbühne Berlin" }, { - "date": "2025-02-01", + "date": "22", "price": 134.90, "inStock": 827, "location": "Olympiahalle München" @@ -393,7 +393,7 @@ "image": "concerts/but-here-we-are.jpg", "concerts": [ { - "date": "2024-12-05", + "date": "30", "price": 80, "inStock": 99, "location": "ZAG Arena" @@ -462,13 +462,13 @@ "image": "concerts/crisis-of-faith-tour.jpg", "concerts": [ { - "date": "2025-01-12", + "date": "3", "price": 81.90, "inStock": 173, "location": "ZAG Arena" }, { - "date": "2025-02-01", + "date": "6", "price": 84.90, "inStock": 192, "location": "Muffatwerk" @@ -523,19 +523,19 @@ "image": "concerts/back-to-the-water-below.jpg", "concerts": [ { - "date": "2024-10-19", + "date": "10", "price": 64.90, "inStock": 245, "location": "E-Werk" }, { - "date": "2025-02-27", + "date": "20", "price": 67.90, "inStock": 847, "location": "Kulturzentrum Faust" }, { - "date": "2025-03-06", + "date": "29", "price": 64.90, "inStock": 245, "location": "Waldbühne Berlin" @@ -595,13 +595,13 @@ "image": "concerts/simulation-theory.jpg", "concerts": [ { - "date": "2024-10-21", + "date": "7", "price": 67.90, "inStock": 847, "location": "Volksparkstadion" }, { - "date": "2024-10-20", + "date": "17", "price": 67.90, "inStock": 847, "location": "LANXESS arena" @@ -613,31 +613,31 @@ "image": "concerts/will-of-the-people-tour.jpg", "concerts": [ { - "date": "2025-01-15", + "date": "32", "price": 67.90, "inStock": 847, "location": "ZAG Arena" }, { - "date": "2025-01-15", + "date": "39", "price": 67.90, "inStock": 847, "location": "ZAG Arena" }, { - "date": "2025-01-23", + "date": "41", "price": 64.90, "inStock": 245, "location": "Olympiastadion Berlin" }, { - "date": "2025-02-02", + "date": "45", "price": 64.90, "inStock": 245, "location": "Astra Kulturhaus" }, { - "date": "2025-02-05", + "date": "50", "price": 64.90, "inStock": 245, "location": "Astra Kulturhaus" diff --git a/software/backend/data/exercises.json b/software/backend/data/exercises.json index 08558c2..76d3cd7 100644 --- a/software/backend/data/exercises.json +++ b/software/backend/data/exercises.json @@ -12,10 +12,17 @@ "descriptionDe": "Erstelle einen neuen Account im Online Shop", "descriptionEn": "Create a new account in the online shop" }, + { + "nameDe": "Profil vervollständigen", + "nameEn": "Complete profile", + "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" + }, { "nameDe": "Ein Ticket kaufen", "nameEn": "Buy a ticket", - "exerciseNr": 2, + "exerciseNr": 3, "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" } @@ -25,6 +32,8 @@ "nameDe": "Broken Access Control", "nameEn": "Broken Access Control", "groupNr": 1, + "descriptionDe": "Eine Webseite beinhaltet oft öffentlich einsehbare und einige Seiten, die nur mit passenden Berechtigungen erreicht werden dürfen, z.B. ein Admin-Panel oder einen Account-Bereich. Jede Seite ist über einen Suffix (z.B. '/concerts') erreichbar. Der Zugriff wird oft über Cookies oder eine Authentifizierung an einem Backend-Server geregelt. Bei Broken Access Control ist dieser Sicherheits-Mechanismus nicht oder fehlerhaft implementiert. Somit lassen sich Seiten unberechtigterweise über die URL erreichen.", + "descriptionEn": "todo", "exercises": [ { "nameDe": "Hilfe-Seite aufrufen", @@ -39,6 +48,13 @@ "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" + }, + { + "nameDe": "Das Admin-Panel aufrufen", + "nameEn": "Access the Admin-Panel", + "exerciseNr": 3, + "descriptionDe": "Manipuliere die URL so, dass du das Admin-Panel erreichen kannst", + "descriptionEn": "Manipulate the URL and access the admin page" } ] }, @@ -46,23 +62,25 @@ "nameDe": "SQL Injections", "nameEn": "SQL Injections", "groupNr": 2, + "descriptionDe": "HTML und CSS sind für die Struktur und die Gestaltung einer Webseite verantwortlich. Um jedoch Programmcode für dynamische Inhalte auszuführen wird die Programmiersprache JavaScript verwendet, welche Programmcode direkt im Browser ausführen kann. Diese Scripts können nun aber auch Schaden anrichten, wenn sie im Rahmen eines Angriffs eingeschmuggelt werden.", + "descriptionEn": "todo", "exercises": [ { - "nameDe": "Accountnamen auslesen", - "nameEn": "Readout account names", + "nameDe": "Einen fremden Account übernehmen", + "nameEn": "Capture an account", "exerciseNr": 1, - "descriptionDe": "Lasse dir alle Accountnamen über das Suchfeld ausgeben", - "descriptionEn": "Readout all account names via the search field" + "descriptionDe": "Führe auf der Login-Seite eine SQL-Injection durch, so dass du Zugriff auf einen Account mit 'Super Admin'-Berechtigungen erlangst", + "descriptionEn": "Execute an SQL-Injection on the Login page. Try to capture an account with 'Super Admin' privilege." }, { - "nameDe": "Passwort auslesen", + "nameDe": "Bestellungen abfragen", "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" }, { - "nameDe": "Verändere deine Account Berechtigungen", + "nameDe": "Band-Bewertungen manipulieren", "nameEn": "Change your account role", "exerciseNr": 3, "descriptionDe": "Ändere die Berechtigungen deines Accounts", @@ -74,6 +92,8 @@ "nameDe": "Cross-Site Scripting (XSS)", "nameEn": "Cross-Site Scripting (XSS)", "groupNr": 3, + "descriptionDe": "todo", + "descriptionEn": "todo", "exercises": [ { "nameDe": "Hallo Welt!", diff --git a/software/backend/data/orders.json b/software/backend/data/orders.json index 20f13e8..df1ed50 100644 --- a/software/backend/data/orders.json +++ b/software/backend/data/orders.json @@ -5,7 +5,7 @@ "shipped": true, "tickets": [ { - "date": "2024-10-18", + "date": "1", "concertGroupName": "Unlimited Love", "orderPrice": 184, "seatGroup": "A", @@ -18,7 +18,7 @@ "username": "duranduran", "tickets": [ { - "date": "2024-10-18", + "date": "4", "concertGroupName": "Unlimited Love", "orderPrice": 184, "seatGroup": "A", @@ -26,7 +26,7 @@ "seat": 2 }, { - "date": "2024-10-18", + "date": "4", "concertGroupName": "Unlimited Love", "orderPrice": 184, "seatGroup": "A", @@ -39,8 +39,8 @@ "username": "duranduran", "tickets": [ { - "date": "2024-10-18", - "concertGroupName": "Unlimited Love", + "date": "14", + "concertGroupName": "The Bends", "orderPrice": 184, "seatGroup": "A", "seatRow": 0, diff --git a/software/backend/models/exercises/exerciseGroup.model.ts b/software/backend/models/exercises/exerciseGroup.model.ts index 06c985a..6171ce3 100644 --- a/software/backend/models/exercises/exerciseGroup.model.ts +++ b/software/backend/models/exercises/exerciseGroup.model.ts @@ -12,6 +12,12 @@ export class ExerciseGroup extends Model { @Column groupNr: number + @Column + descriptionDe: string + + @Column + descriptionEn: string + // Relations diff --git a/software/backend/models/user/accountRole.model.ts b/software/backend/models/user/accountRole.model.ts index 9828480..d4a401e 100644 --- a/software/backend/models/user/accountRole.model.ts +++ b/software/backend/models/user/accountRole.model.ts @@ -12,6 +12,9 @@ export class AccountRole extends Model { @Column privilegeAdminPanel: boolean + @Column + privilegeFileAccess: boolean + // Relations @HasMany(() => Account) diff --git a/software/backend/routes/account.routes.ts b/software/backend/routes/account.routes.ts index 63cd8a7..7f3cb6c 100644 --- a/software/backend/routes/account.routes.ts +++ b/software/backend/routes/account.routes.ts @@ -30,26 +30,14 @@ account.get("/login", async (req: Request, res: Response) => { "' AND password='" + req.query.password + "')" ) - // Mechanism to check exercise solved - if (results.length > 1) { - Exercise.update( - { solved: true }, - { - where: { - nameEn: "Register" - } - } - ) - } - if (results.length != 0) { // Creating session token const token = jwt.sign({ userId: results[0]["id"] }, 'sjcucjdkdf') // Status: 200 OK res.status(200).json({ - "success": true, - "token": token + success: true, + token: token }) } else { // Status: 401 Unauthorized @@ -124,7 +112,7 @@ account.patch("/", verifyToken, (req: Request, res: Response) => { { where: { id: req.body.id } }) - .then(async account => { + .then(async result => { for (let payment of req.body.payments) { if (payment.id == undefined) { payment["accountId"] = req.body.id diff --git a/software/backend/scripts/databaseHelper.ts b/software/backend/scripts/databaseHelper.ts index 1beffdf..b8d811d 100644 --- a/software/backend/scripts/databaseHelper.ts +++ b/software/backend/scripts/databaseHelper.ts @@ -296,9 +296,8 @@ export async function prepopulateDatabase() { } }) .then(async location => { - console.log(concert.offered) concerts.push({ - date: concert.date, + date: moment().add(concert.date, "days").format("YYYY-MM-DD"), name: concertGroup.name, price: concert.price, image: "http://localhost:3000/static/" + concertGroup.image, @@ -354,7 +353,7 @@ export async function prepopulateDatabase() { where: { [Op.and] : [ { name: ticket.concertGroupName }, - { date: ticket.date } + { date: moment().add(ticket.date, "days").format("YYYY-MM-DD") } ] } }) diff --git a/software/src/data/enums/bannerStateEnum.ts b/software/src/data/enums/bannerStateEnum.ts index 03e7308..e0f322b 100644 --- a/software/src/data/enums/bannerStateEnum.ts +++ b/software/src/data/enums/bannerStateEnum.ts @@ -15,6 +15,8 @@ export enum BannerStateEnum { EXERCISESOLVED02, + EXERCISESOLVED03, + EXERCISESOLVED11, EXERCISESOLVED12, diff --git a/software/src/data/models/exercises/exerciseGroupModel.ts b/software/src/data/models/exercises/exerciseGroupModel.ts index f6ab589..86de31d 100644 --- a/software/src/data/models/exercises/exerciseGroupModel.ts +++ b/software/src/data/models/exercises/exerciseGroupModel.ts @@ -3,4 +3,6 @@ export class ExerciseGroupModel { nameDe: string = "" nameEn: string = "" groupNr: number = 0 + descriptionDe: string = "" + descriptionEn: string = "" } \ No newline at end of file diff --git a/software/src/locales/de.json b/software/src/locales/de.json index c1c1bf2..8b5a122 100644 --- a/software/src/locales/de.json +++ b/software/src/locales/de.json @@ -172,6 +172,7 @@ "databaseResetSuccessful": "Datenbank erfolgreich zurück gesetzt!", "exerciseProgressResetSuccessful": "Aufgabenfortschritt erfolgreich zurück gesetzt!", "registerSuccessful": "Account erfolgreich erstellt!", + "registerError": "Fehler beim Erstellen des Accounts", "usernameInUse": "Der Accountname ist bereits vergeben!", "accountUpdated": "Account erfolgreich aktualisiert", "logoutSuccessful": "Logout erfolgreich", diff --git a/software/src/locales/en.json b/software/src/locales/en.json index e17cbc6..0748929 100644 --- a/software/src/locales/en.json +++ b/software/src/locales/en.json @@ -172,6 +172,7 @@ "databaseResetSuccessful": "Database successfully resetted!", "exerciseProgressResetSuccessful": "Exercise progress successfully resetted!", "registerSuccessful": "Account successfully created!", + "registerError": "Error on register account", "usernameInUse": "The username is already in use!", "accountUpdated": "Account successfully updated", "logoutSuccessful": "Logout successfull", diff --git a/software/src/pages/admin/dashboardPage/index.vue b/software/src/pages/admin/dashboardPage/index.vue index f5b29c8..2eeb2bd 100644 --- a/software/src/pages/admin/dashboardPage/index.vue +++ b/software/src/pages/admin/dashboardPage/index.vue @@ -8,6 +8,7 @@ import { usePreferencesStore } from '@/stores/preferences.store'; import dashboardCard from './dashboardCard.vue'; import { useOrderStore } from '@/stores/order.store'; import { useFilesStore } from '@/stores/files.store'; +import { useExerciseStore } from '@/stores/exercise.store'; const concertStore = useConcertStore() const bandStore = useBandStore() @@ -17,6 +18,9 @@ const locationStore = useLocationStore() const preferencesStore = usePreferencesStore() const orderStore = useOrderStore() const filesStore = useFilesStore() +const exerciseStore = useExerciseStore() + +exerciseStore.solveExercise(1, 3) filesStore.getStaticFolders() bandStore.getBands() diff --git a/software/src/pages/concerts/concertBookingPage/index.vue b/software/src/pages/concerts/concertBookingPage/index.vue index ed84dcb..423f7a7 100644 --- a/software/src/pages/concerts/concertBookingPage/index.vue +++ b/software/src/pages/concerts/concertBookingPage/index.vue @@ -21,7 +21,14 @@ onMounted(async () => { ) }) -watch(() => router.currentRoute.value.params.id, () => { +watch(() => router.currentRoute.value.params.locationUrl, () => { + concertStore.getConcert( + String(router.currentRoute.value.params.locationUrl), + String(router.currentRoute.value.params.date) + ) +}) + +watch(() => router.currentRoute.value.params.date, () => { concertStore.getConcert( String(router.currentRoute.value.params.locationUrl), String(router.currentRoute.value.params.date) diff --git a/software/src/stores/account.store.ts b/software/src/stores/account.store.ts index 8a96a53..dcfb234 100644 --- a/software/src/stores/account.store.ts +++ b/software/src/stores/account.store.ts @@ -139,9 +139,20 @@ export const useAccountStore = defineStore("accountStore", { */ async updateAccount() { const feedbackStore = useFeedbackStore() + const exerciseStore = useExerciseStore() + // Check for exercise 0.2 completion + let accountComplete = this.userAccount.firstName != "" && this.userAccount.lastName != "" && + this.userAccount.addresses.length != 0 && this.userAccount.payments.length != 0 + + if (accountComplete) { + exerciseStore.solveExercise(0, 2) + } + + // Update in backend await updateAccount(this.userAccount, this.userAccountToken) .then(res => { + if (res.status == 200) { feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTUPDATESUCCESSFUL) diff --git a/software/src/stores/basket.store.ts b/software/src/stores/basket.store.ts index 57795fa..4576449 100644 --- a/software/src/stores/basket.store.ts +++ b/software/src/stores/basket.store.ts @@ -109,18 +109,21 @@ export const useBasketStore = defineStore('basketStore', { if (result.status == 201) { await accountStore.refreshOrders() - this.itemsInBasket = [] feedbackStore.addSnackbar(BannerStateEnum.ORDERPLACESUCCESSFUL) - // Exercise 0.2 is solved - exerciseStore.solveExercise(0, 2) + // Exercise 0.3 is solved + exerciseStore.solveExercise(0, 3) - for (let ticket of this.itemsInBasket) { - if (!ticket.concert.offered) { + console.log(this.itemsInBasket) + + for (let item of this.itemsInBasket) { + if (!item.concert.offered) { exerciseStore.solveExercise(1, 2) feedbackStore.addSnackbar(BannerStateEnum.EXERCISESOLVED12) } } + + this.itemsInBasket = [] } else { feedbackStore.addSnackbar(BannerStateEnum.ERROR) } diff --git a/software/src/stores/exercise.store.ts b/software/src/stores/exercise.store.ts index ef6b7fb..37d4492 100644 --- a/software/src/stores/exercise.store.ts +++ b/software/src/stores/exercise.store.ts @@ -71,6 +71,7 @@ export const useExerciseStore = defineStore("exerciseStore", { switch(exerciseNr) { case 1: bannerState = BannerStateEnum.EXERCISESOLVED01; break; case 2: bannerState = BannerStateEnum.EXERCISESOLVED02; break; + case 3: bannerState = BannerStateEnum.EXERCISESOLVED03; break; } break; diff --git a/software/src/stores/feedback.store.ts b/software/src/stores/feedback.store.ts index 00e3dca..76d8714 100644 --- a/software/src/stores/feedback.store.ts +++ b/software/src/stores/feedback.store.ts @@ -6,6 +6,7 @@ import { Composer } from 'vue-i18n'; /** * Logic of the bubble notifications * Includes an i18n object for translation + * Includes a variable for redirecting to 404 page */ export const useFeedbackStore = defineStore("feedbackStore", { state: () => ({ @@ -14,15 +15,6 @@ export const useFeedbackStore = defineStore("feedbackStore", { /** Show notification banner in top right corner */ showSnackbar: ref(false), - /** Text in the notification banner */ - title: ref(""), - - /** Color of the notification banner */ - color: ref(""), - - /** Prepend icon of the notification banner */ - icon: ref(""), - /** Programmatically access to language translation module */ $i18n: {}, @@ -69,6 +61,9 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.EXERCISESOLVED02: return this.i18n.t("bannerMessages.exerciseSolvedNr", [0, 2]) + + case BannerStateEnum.EXERCISESOLVED03: + return this.i18n.t("bannerMessages.exerciseSolvedNr", [0, 3]) case BannerStateEnum.EXERCISESOLVED11: @@ -131,6 +126,9 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL: return this.i18n.t("bannerMessages.registerSuccessful") + case BannerStateEnum.ACCOUNTREGISTERERROR: + return this.i18n.t("bannerMessages.registerSuccessful") + case BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE: return this.i18n.t("bannerMessages.usernameInUse") @@ -207,6 +205,7 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.EXERCISESOLVED01: case BannerStateEnum.EXERCISESOLVED02: + case BannerStateEnum.EXERCISESOLVED03: case BannerStateEnum.EXERCISESOLVED11: case BannerStateEnum.EXERCISESOLVED12: case BannerStateEnum.EXERCISESOLVED13: @@ -237,6 +236,7 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.EXERCISESOLVED01: case BannerStateEnum.EXERCISESOLVED02: + case BannerStateEnum.EXERCISESOLVED03: case BannerStateEnum.EXERCISESOLVED11: case BannerStateEnum.EXERCISESOLVED12: case BannerStateEnum.EXERCISESOLVED13: