Compare commits
85 Commits
faebc05a2f
...
doc-0.0.0-
| Author | SHA1 | Date | |
|---|---|---|---|
| c19ae8a982 | |||
| 26d56c0d24 | |||
| f5223405a5 | |||
| 7ab7e9e25d | |||
| 370942efe1 | |||
| 490912aaca | |||
| 6d15ab6b0a | |||
| aa1353adce | |||
| bbb2f94944 | |||
| f25d6be858 | |||
| b2d89e7830 | |||
| c4d0bb1a9a | |||
| 2aeb5f2f8f | |||
| 8a150208dd | |||
| 6798cbf877 | |||
| 63f9f721a2 | |||
| ea9479628c | |||
| 4ddb7d8904 | |||
| aa704577ad | |||
| 15eb9d9d5e | |||
| f11fcb68fe | |||
| 37262ff470 | |||
| 8da8374a1b | |||
| d397f0cd60 | |||
| b450fd6475 | |||
| 6789fa6f9d | |||
| 2061cdc218 | |||
| 6b0c4f7884 | |||
| ad47997aab | |||
| b337833410 | |||
| 69d898bc86 | |||
| 29fda2257b | |||
| caedd3ba9e | |||
| 710667481b | |||
| 2e4353bf8e | |||
| a38cbd0dfe | |||
| 9aad0c5394 | |||
| e774cec6d5 | |||
| 9a0cb1ffa0 | |||
| 4e0861147a | |||
| 35a0ebd15a | |||
| 04bc48133b | |||
| 0551792aca | |||
| efaf02156c | |||
| 6e7d30b1d6 | |||
| 1e230b67e4 | |||
| e1743aeb94 | |||
| f673460e07 | |||
| 69c01af8d4 | |||
| 3be7fd4123 | |||
| 90294a0503 | |||
| 29b29fe49d | |||
| e4c7cab347 | |||
| 8612e13f2a | |||
| 6995fa35f0 | |||
| 9f0bd16ec9 | |||
| a32f395822 | |||
| cda4491ac0 | |||
| ad8de7141f | |||
| dee5d67484 | |||
| 8be72b130f | |||
| 907eada0f5 | |||
| bc4044803e | |||
| 9f77612cc4 | |||
| 97730868cd | |||
| 3460dd34b6 | |||
| 6482c6230c | |||
| 2c9936edd6 | |||
| 81162c2a4b | |||
| ef35a13a4f | |||
| b70e514a09 | |||
| 870b8a8da9 | |||
| 8e45423242 | |||
| 968d16592c | |||
| 0baccc63d7 | |||
| 86df0be0f4 | |||
| 96d0d50e4e | |||
| ab8d146b3c | |||
| 4da2d616a4 | |||
| 7b6a6ec35b | |||
| 1dd5df5ba8 | |||
| fb756a9b76 | |||
| 7e533e67c9 | |||
| d7ee355109 | |||
| 1f640802f2 |
43
.gitea/workflows/create-presentation.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
name: build-debian-package
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "doc-*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build the debian package
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: "Git clone"
|
||||
run: git clone ${{ gitea.server_url }}/${{ gitea.repository }}.git .
|
||||
- name: "Git checkout"
|
||||
run: git checkout "${{ gitea.sha }}"
|
||||
- name: "Submodules auschecken"
|
||||
run: git submodule update --init
|
||||
- uses: docker://git.kocoder.xyz/docker/ga-pandoc:c6eaa45b623c284e80f37434872621defc00f864
|
||||
working_directory: Defensio
|
||||
with:
|
||||
env: TEXINPUTS=.:./libs/awesome-beamer/:./libs/smile/
|
||||
command: pandoc
|
||||
args: >-
|
||||
01_Praesentation_Allgemein.md \
|
||||
02_Praesentation_Konstantin_Hintermayer.md \
|
||||
03_Praesentation_Florian_Edlmayer.md \
|
||||
04_Praesentation_Adam_Gaiswinkler.md \
|
||||
-t beamer \
|
||||
--template 00_preamble.tex \
|
||||
--pdf-engine=pdflatex \
|
||||
--slide-level=2 \
|
||||
--number-sections \
|
||||
--lua-filter ../_extensions/diagram/diagram.lua \
|
||||
--syntax-definition ../_extensions/razor/razor.xml \
|
||||
--syntax-definition ../_extensions/nginx/nginx.xml \
|
||||
-o defensio.pdf
|
||||
- name: "Create release"
|
||||
uses: akkuman/gitea-release-action@v1
|
||||
with:
|
||||
files: |-
|
||||
./Defensio/defensio.pdf
|
||||
./Defensio/Images/*
|
||||
@@ -1,8 +1,6 @@
|
||||
name: Word Count
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "master" ]
|
||||
pull_request:
|
||||
branches: [ "main", "master" ]
|
||||
|
||||
|
||||
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "Defensio/libs/awesome-beamer"]
|
||||
path = Defensio/libs/awesome-beamer
|
||||
url = https://git.kocoder.xyz/kocoded/awesome-beamer
|
||||
[submodule "Defensio/libs/smile"]
|
||||
path = Defensio/libs/smile
|
||||
url = https://codeberg.org/LukasPietzschmann/smile
|
||||
34
Artikel_Schulhomepage.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# AlumniHub – Die neue digitale Plattform des Absolventenvereins
|
||||
|
||||
Im Rahmen ihrer Diplomarbeit an der HTL SZU Ungargasse haben **Konstantin Hintermayer**, **Florian Edlmayer** und **Adam Gaiswinkler** (5BHITN, Schuljahr 2025/26) eine moderne Webanwendung für den Absolventenverein entwickelt: den **AlumniHub**.
|
||||
|
||||
## Worum geht es?
|
||||
|
||||
Der Absolventenverein der HTL Ungargasse verwaltet rund 300 Alumni – bisher über Excel-Tabellen und abgelaufene Softwarelizenzen. Das Diplomarbeitsteam hat eine zentrale Plattform geschaffen, die Mitgliederverwaltung, Event-Organisation und Kommunikation unter einem Dach vereint.
|
||||
|
||||
## Was kann der AlumniHub?
|
||||
|
||||
- **Anmeldetool für Treffen** – Veranstaltungen erstellen, Einladungen verschicken und Anmeldungen verwalten
|
||||
- **Hall of Fame** – Absolventen können ihre Erfolge präsentieren, inklusive PDF-Export
|
||||
- **Schwarzes Brett** – Ein interaktiver Feed für Neuigkeiten, Events und Jobangebote
|
||||
- **Premiumbereich** – Exklusive Inhalte für Premiummitglieder mit eigenem Freigabe-Workflow
|
||||
- **LinkedIn-Login** – Sichere Anmeldung über OAuth 2.0
|
||||
- **DSGVO-konform** – Datenschutz von Anfang an mitgedacht
|
||||
|
||||
## Die Technik dahinter
|
||||
|
||||
Die Anwendung basiert auf dem Content-Management-System **Oqtane** mit **ASP.NET Core** und **Blazor**. Gehostet wird das Ganze auf einem Linux-Server mit PostgreSQL-Datenbank – betrieben in der Schulinfrastruktur. Gearbeitet wurde agil nach **Scrum** in zweiwöchigen Sprints.
|
||||
|
||||
## Das Team
|
||||
|
||||
| Name | Schwerpunkt |
|
||||
| :---------------------- | :----------------------------------------------------------------- |
|
||||
| Konstantin Hintermayer | Projektleitung, Serverinfrastruktur, Schwarzes Brett, Auswertungen |
|
||||
| Florian Edlmayer | Premiumbereich, LinkedIn-OAuth, Datenschutz (DSGVO) |
|
||||
| Adam Gaiswinkler | Anmeldetool, Hall of Fame, CMS-Konfiguration, UI/UX-Design |
|
||||
|
||||
**Betreuung:** Ing. Thomas Gürth & Johannes Kreuzer
|
||||
|
||||
---
|
||||
|
||||
*Das Projektteam bedankt sich bei allen Unterstützern – insbesondere beim Absolventenverein als Auftraggeber und bei der Schule für die Bereitstellung der Infrastruktur.*
|
||||
103
Defensio/00_preamble.tex
Normal file
@@ -0,0 +1,103 @@
|
||||
\documentclass[aspectratio=169]{beamer}
|
||||
|
||||
\providecommand{\tightlist}{%
|
||||
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
||||
\makeatletter
|
||||
\newsavebox\pandoc@box
|
||||
\newcommand*\pandocbounded[1]{% scales image to fit the slide if it's too large
|
||||
\sbox\pandoc@box{#1}%
|
||||
\ifdim\wd\pandoc@box>\linewidth
|
||||
\makebox[\linewidth][c]{\resizebox{\linewidth}{!}{\usebox\pandoc@box}}%
|
||||
\else
|
||||
\usebox\pandoc@box
|
||||
\fi
|
||||
}
|
||||
\makeatother
|
||||
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage{lmodern}
|
||||
\usepackage{multimedia}
|
||||
\usepackage{graphicx}
|
||||
|
||||
\newcommand{\imagepath}{Images}
|
||||
|
||||
\definecolor{orange}{HTML}{f87a01}
|
||||
\usetheme[german, color, coloraccent=orange, notoc]{awesome}
|
||||
\makeatletter
|
||||
\newcommand{\nonumberson}{\awesome@nonumbersinframetitletrue}
|
||||
\newcommand{\nonumbersoff}{\awesome@nonumbersinframetitlefalse}
|
||||
\makeatother
|
||||
|
||||
% \usepackage{firamath-otf}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{pgfplotstable}
|
||||
% \usepackage{fontawesome}
|
||||
\usepackage{tikzpingus}
|
||||
\usepackage{tikzducks}
|
||||
\usepackage{pdfpc}
|
||||
\usepackage{amsmath}
|
||||
|
||||
\usepgfplotslibrary{dateplot}
|
||||
\usetikzlibrary{shapes,tikzmark}
|
||||
\tikzset{pipelinestep/.style={lw,rnd,shape=signal,signal from=west,signal pointer angle=130,minimum width=3cm,minimum height=2cm,draw=black,fill=lightgray!30}}
|
||||
|
||||
\def\info#1{\begingroup\color{gray}\scriptsize#1\endgroup}
|
||||
|
||||
\newcommand<>{\talknote}[1]{\only#2{\pdfpcnote{- #1}\relax}}
|
||||
|
||||
\makeatletter
|
||||
\newlength\beamerleftmargin
|
||||
\setlength\beamerleftmargin{\Gm@lmargin}
|
||||
\makeatother
|
||||
|
||||
|
||||
% \addbibresource{refs.bib}
|
||||
|
||||
% \addtobeamertemplate{title page}{}{
|
||||
% \begin{tikzpicture}[overlay, remember picture]
|
||||
% \node[anchor=south east,outer sep=0pt] at (current page.south east) {\fontsize{3}{3}\selectfont\color{white}This image was generated by AI};
|
||||
% \end{tikzpicture}
|
||||
% }
|
||||
|
||||
\pgfplotsset{
|
||||
every axis legend/.append style={style={roundednode,fill=accent!10,lcr}},
|
||||
every axis plot/.append style={lw,lcr},
|
||||
}
|
||||
|
||||
\title[AlumniHub]{AlumniHub}
|
||||
\subtitle{Web-Entwicklung für den Absolventenverein}
|
||||
\author{Konstantin Hintermayer \\ Florian Edlmayer \\ Adam Gaiswinkler}
|
||||
\email{}
|
||||
\institute{Schulzentrum HTL HAK Ungargasse}
|
||||
\uni{Schulzentrum HTL HAK Ungargasse}
|
||||
\location{Wien}
|
||||
\background{./Images/images/background/title-slide/background.png}
|
||||
\logo{\includegraphics[width=3cm]{\imagepath/images/logos/logo.png}}
|
||||
\date{22. April 2026}
|
||||
|
||||
|
||||
\AtBeginSection[]
|
||||
{
|
||||
\begingroup
|
||||
\nonumberson
|
||||
\begin{frame}[noframenumbering,plain]{Agenda}
|
||||
\tableofcontents[currentsection]
|
||||
\end{frame}
|
||||
\endgroup
|
||||
}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\maketitle
|
||||
|
||||
\begingroup
|
||||
\nonumberson
|
||||
\begin{frame}[noframenumbering,plain]{Agenda}
|
||||
\tableofcontents
|
||||
\end{frame}
|
||||
\endgroup
|
||||
|
||||
$body$
|
||||
|
||||
\end{document}
|
||||
11
Defensio/01_Praesentation_Allgemein.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Allgemein Alumnihub
|
||||
|
||||
---
|
||||
|
||||
## {.plain}
|
||||
|
||||
\begin{tikzpicture}[remember picture,overlay]
|
||||
\node[anchor=center] at (current page.center) {
|
||||
\movie[width=\paperwidth, height=\paperheight, poster, showcontrols=false, autostart]{}{\imagepath/video/introduction/sample-10s.mp4}
|
||||
};
|
||||
\end{tikzpicture}
|
||||
102
Defensio/02_Praesentation_Konstantin_Hintermayer.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Konstantin Hintermayer
|
||||
|
||||
## Rolle im Projekt
|
||||
|
||||
::: columns
|
||||
|
||||
:::: column
|
||||
Aufgabenbereiche:
|
||||
|
||||
- Infrastruktur & CI/CD
|
||||
- Product Owner
|
||||
- Kundenschnittstelle
|
||||
- Softwareentwicklung:
|
||||
- Event Registration
|
||||
- Black Board
|
||||
- Report System
|
||||
- Mass Mailer
|
||||
::::
|
||||
|
||||
:::: column
|
||||
|
||||
\begin{tikzpicture}
|
||||
\clip (0,0) circle (3em);
|
||||
\node at (0,0) {\includegraphics[width=6em]{./Images/images/konstantin/profile.jpg}};
|
||||
\draw[accent, line width=3pt] (0,0) circle (3em);
|
||||
\end{tikzpicture}
|
||||
|
||||
::::
|
||||
|
||||
:::
|
||||
|
||||
## Infrastruktur
|
||||
|
||||
::: columns
|
||||
:::: column
|
||||
|
||||
Systemaufbau:
|
||||
|
||||
- Debian Linux
|
||||
- PostgreSQL
|
||||
- NginX
|
||||
- Asp.Net Core
|
||||
|
||||
::::
|
||||
:::: column
|
||||
|
||||
Entwicklungsumgebung:
|
||||
|
||||
- Gitea Server
|
||||
- Wireguard
|
||||
- Docker
|
||||
- Transfer: GitHub
|
||||
- Gitea Actions
|
||||
|
||||
::::
|
||||
:::
|
||||
|
||||
|
||||
## CI/CD
|
||||
|
||||
CI:
|
||||
|
||||
- Gitea Actions
|
||||
- Debian Packages (.deb)
|
||||
- Code-Reviewing:
|
||||
- KI
|
||||
- Git-Flow
|
||||
|
||||
## Softwarearchitektur
|
||||
|
||||
- Open-Closed Principle
|
||||
- Strategy Pattern
|
||||
- Dependency Injection
|
||||
|
||||
## Technischer Vergleich
|
||||
|
||||
Bisherige Erfahrungen:
|
||||
|
||||
- Go
|
||||
- Typescript
|
||||
- GRPC (interprozess Kommunikation)
|
||||
|
||||
Untersuchungsgebiete:
|
||||
|
||||
- Typisierung
|
||||
- Konsistenz
|
||||
|
||||
## Teamleitung
|
||||
|
||||
::: columns
|
||||
|
||||
:::: column
|
||||
left
|
||||
::::
|
||||
|
||||
:::: column
|
||||
right
|
||||
::::
|
||||
|
||||
:::
|
||||
|
||||
## Fazit
|
||||
130
Defensio/03_Praesentation_Florian_Edlmayer.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Florian Edlmayer
|
||||
|
||||
## Individueller Teil: Florian Edlmayer
|
||||
**Datensicherheit, Backup-Systeme & Premium-Bereich**
|
||||
|
||||
---
|
||||
|
||||
## Ausgangslage & Zielsetzung
|
||||
- **Ausgangssituation**:
|
||||
- Keine digitale, sichere Absolventen-Vernetzung.
|
||||
- **Mein Beitrag**:
|
||||
- Datenschutz (DSGVO).
|
||||
- Automatisierte Backups & Restore.
|
||||
- LinkedIn-Login (OAuth 2.0).
|
||||
- Premium-Bereich.
|
||||
- **Nutzen**: Rechtssicherheit, Ausfallsicherheit, hohes Engagement.
|
||||
|
||||
---
|
||||
|
||||
## Eingesetzte Technologien
|
||||
- **Framework**: ASP.NET Core & .NET 8
|
||||
- **Datenbanksystem**: PostgreSQL
|
||||
- **Authentifizierung**: OAuth 2.0 (LinkedIn)
|
||||
- **Scripting & Automation**: Bash-Skripte für Linux Cronjobs
|
||||
|
||||
---
|
||||
|
||||
## DSGVO & Datenschutz
|
||||
- **Rechtliche Basis**: Einhaltung von DSGVO & DSG.
|
||||
- **Umsetzung**:
|
||||
- **Datenschutzerklärung**: Rechtskonform integriert.
|
||||
- **Datenminimierung**: Nur zwingend benötigte Daten.
|
||||
- **Vertraulichkeit**: TLS/HTTPS & lokales Austria-Hosting.
|
||||
- **Betroffenenrechte**: Auskunft & Löschung garantiert.
|
||||
|
||||
---
|
||||
|
||||
## Backup- & Restore-Systeme (1)
|
||||
- **Problem**: Datenverlust (Hardware, Software, Cyberangriffe).
|
||||
- **Lösung**: Vollautomatisiertes Backup-Skript.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Start((Start: Cronjob 02:30)) --> Init[Initialisierung]
|
||||
Init --> Vars[Konfiguration laden]
|
||||
|
||||
subgraph Sicherungsphase
|
||||
Dir[Erstelle Backup-Ordner] --> DB[Datenbank-Backup]
|
||||
DB --> Files[Dateisystem sichern]
|
||||
end
|
||||
|
||||
Files --> Check{Fehler?}
|
||||
Check -- Ja --> Mail[Log Error & Abbruch]
|
||||
Check -- Nein --> Rotate[Lade Backups-Liste]
|
||||
|
||||
subgraph Speicherverwaltung
|
||||
Rotate --> Count{Anzahl > 30?}
|
||||
Count -- Ja --> Delete[Älteste löschen]
|
||||
Count -- Nein --> Finish[Abschluss]
|
||||
Delete --> Finish
|
||||
end
|
||||
|
||||
Finish --> Ende((Ende))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backup- & Restore-Systeme (2)
|
||||
- **Speichermanagement (Retention)**:
|
||||
- Automatische Backup-Rotation.
|
||||
- Limit: Letzte 30 Tage (Speicherplatz-Optimierung).
|
||||
- **Restore-Skript**:
|
||||
- Kontrollierter Wiederherstellungsprozess.
|
||||
- Sicherheitsabfrage vor Überschreiben.
|
||||
- Backup als "Rückversicherung" vor Import.
|
||||
- DB-Neuanlage & automatischer Import.
|
||||
|
||||
---
|
||||
|
||||
## Authentifizierung mit LinkedIn (OAuth 2.0)
|
||||
- **Ziel**:
|
||||
- Abbau von Registrierungshürden.
|
||||
- Keine sensiblen Passwörter im eigenen System.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Der Premium-Bereich (1)
|
||||
**Zweck**: Motivation für aktives Mitglieder-Engagement.
|
||||
|
||||
{width=20em}
|
||||
|
||||
{width=20em}
|
||||
|
||||
---
|
||||
|
||||
## Der Premium-Bereich (2)
|
||||
**Architektur des Premium-Bereich-Moduls:**
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph Client [WebAssembly]
|
||||
UI[Benutzeroberfläche] --> SvcC[Service Client]
|
||||
end
|
||||
|
||||
subgraph Server [ASP.NET Core]
|
||||
SvcC --> Ctrl[API Controller]
|
||||
Ctrl --> SvcS[Service Schicht]
|
||||
end
|
||||
|
||||
subgraph Data [Datenbank]
|
||||
SvcS --> EF[EF Core]
|
||||
EF --> DB[(PostgreSQL)]
|
||||
end
|
||||
```
|
||||
|
||||
**Datensparsame Mitgliedersuche & Kontaktfunktion:**
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Fazit & Ausblick
|
||||
- **Erreichtes**:
|
||||
- DSGVO-konformer Datenschutz.
|
||||
- Hohe Ausfallsicherheit (automatisierte Bash-Backups).
|
||||
- Barrierefreier Zugang (LinkedIn-Login).
|
||||
- Echter Mehrwert durch Premium-Funktionen.
|
||||
- **Ausblick**:
|
||||
- Weitere OAuth-Anbieter (z.B. Google, Microsoft).
|
||||
- Ausbau zukünftiger Premium-Features.
|
||||
88
Defensio/04_Praesentation_Adam_Gaiswinkler.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Adam Gaiswinkler
|
||||
|
||||
## Individueller Teil: Adam Gaiswinkler
|
||||
**Entwicklung von CMS‑Modulen & Frontend-Design**
|
||||
|
||||
- Schwerpunkt: Oqtane-Theme, Hall-of-Fame-Modul & Anmeldetool
|
||||
- Ziel: Moderne, responsive Website für den HTL-Absolventenverein
|
||||
|
||||
<!-- BILD: Logo HTL Ungargasse + Vereinslogo nebeneinander -->
|
||||
|
||||
---
|
||||
|
||||
## Ausgangslage & Motivation
|
||||
- **Ausgangssituation**: Moderne Frontend‑Plattform für den Absolventenverein (responsive, neue Features).
|
||||
- **Persönliche Motivation**:
|
||||
- Team‑Verkleinerung (6 → 3) → mehr Verantwortung.
|
||||
- Projektidentifikation & Praxis‑Blazor/ASP.NET.
|
||||
- **Ziele**:
|
||||
- Oqtane‑Module (Anmeldetool, Hall‑of‑Fame).
|
||||
- Responsives UI/UX.
|
||||
|
||||
---
|
||||
|
||||
## Eingesetzte Technologien
|
||||
- **Tech‑Stack**: Bootstrap + Custom‑CSS, QuestPDF, Gitea, VS 2022 wechsel zu VS Code (macOS).
|
||||
|
||||
<!-- BILD: Logos der verwendeten Tools (Bootstrap, QuestPDF, Gitea, VS Code) nebeneinander -->
|
||||
|
||||
---
|
||||
|
||||
## Umsetzung: Oqtane Theme
|
||||
- Eigen‑Navigation (bootstrap Komponenten haben nicht gepasst ).
|
||||
- Systemseiten per LINQ ausblenden.
|
||||
- Responsive CSS‑Media‑Queries + reines CSS‑Burger‑Menu.
|
||||
- ControlPanel & Cookie‑Consent.
|
||||

|
||||
<!-- BILD: Screenshot der Website-Navigation auf Desktop (volle Menüleiste) -->
|
||||
<!-- BILD: Screenshot des Burger-Menüs auf Mobile (aufgeklappt) -->
|
||||
|
||||
---
|
||||
|
||||
## Umsetzung: Hall of Fame
|
||||
- **Karten‑Grid**: Responsive Übersicht, Live‑Suche & Sortierung **in Echtzeit – kein Seitenreload** (Blazor).
|
||||
- **Detail‑Seite**: Glasmorphismus‑Design (halbtransparente Karten mit Blur-Effekt).
|
||||
- **Workflow**: Rich‑Text‑Editor, Bild‑Upload mit **Live-Vorschau** (max 5 MB), Status (Entwurf/Veröffentlicht) inkl. Eigentümer‑Check.
|
||||
- **PDF‑Export**: Professionelle Profil-PDFs server-seitig mit QuestPDF.
|
||||
- **Moderation**: Meldesystem über separates Interfaces‑Paket → saubere Logik-Trennung.
|
||||

|
||||

|
||||
<!-- BILD: Screenshot des Karten-Grids mit mehreren Alumni-Einträgen -->
|
||||
<!-- BILD: Screenshot der Detailseite (Glasmorphismus-Design) -->
|
||||
<!-- BILD: Screenshot eines generierten PDFs -->
|
||||
|
||||
---
|
||||
|
||||
## Umsetzung: Anmeldetool
|
||||
- Klar getrennte Ja/Nein‑Buttons (grün/rot).
|
||||
- **Live‑Feedback via Blazor**: Statusänderungen sofort sichtbar – andere Teilnehmer sehen Updates direkt.
|
||||
- Mobile-optimiert: kein Overlay-Clipping, sauberes Touch-Handling.
|
||||
- Saubere Trennung: UI-Komponente & Backend-API getrennt.
|
||||
|
||||
<!-- BILD: Screenshot Anmeldetool mit gruenem Ja- und rotem Nein-Button -->
|
||||
<!-- BILD: Screenshot auf Mobile (Overlay-Ansicht) -->
|
||||
|
||||
---
|
||||
|
||||
## Herausforderungen & Lösungen
|
||||
- **Plattformwechsel** Windows → macOS: Oqtane stark an Windows gebunden → **Visual Studio Code** als plattformübergreifende Lösung.
|
||||
- **Hosting-Ausfall** (Hetzner, Sommer 2025): kurz vor einem Event → schnelle **Node.js/HTML-Übergangslösung** sicherte Event-Anmeldung.
|
||||
|
||||
<!-- BILD: Screenshot von Visual Studio Code auf macOS -->
|
||||
|
||||
---
|
||||
|
||||
## Learnings
|
||||
- **Technisch**: Git, CSS‑Flexbox, Blazor.
|
||||
- **Methodisch**: Aufgabenverteilung, regelmäßige Meetings.
|
||||
- **Persönlich**: Eigeninitiative & Verantwortung.
|
||||
|
||||
---
|
||||
|
||||
## Fazit & Ausblick
|
||||
- Theme final, mobil, Hall of Fame & Anmeldetool funktionsfähig.
|
||||
- **Erweiterungen**: Teilnehmer‑Auswertung, Anmelde‑Limit, automatische E‑Mail‑Erinnerungen.
|
||||
|
||||
<!-- BILD: Gesamtansicht der fertigen Website (Desktop) als Abschluss-Screenshot -->
|
||||
|
||||
|
||||
BIN
Defensio/Images/HallOfFame.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
Defensio/Images/HallOfFameBeispiel.png
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
BIN
Defensio/Images/ThemeBurgerMenu.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
Defensio/Images/images/background/title-slide/background.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
Defensio/Images/images/konstantin/profile.jpg
Normal file
|
After Width: | Height: | Size: 985 KiB |
BIN
Defensio/Images/images/logos/logo-short.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
BIN
Defensio/Images/oauth-flow-new.png
Normal file
|
After Width: | Height: | Size: 235 KiB |
BIN
Defensio/Images/video/introduction/sample-10s.mp4
Normal file
BIN
Defensio/background.png
Normal file
|
After Width: | Height: | Size: 352 KiB |
1
Defensio/libs/awesome-beamer
Submodule
1
Defensio/libs/smile
Submodule
16
Defensio/pandoc.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
export TEXINPUTS=".:./libs/awesome-beamer/:./libs/smile/:$TEXINPUTS"
|
||||
pandoc \
|
||||
01_Praesentation_Allgemein.md \
|
||||
02_Praesentation_Konstantin_Hintermayer.md \
|
||||
03_Praesentation_Florian_Edlmayer.md \
|
||||
04_Praesentation_Adam_Gaiswinkler.md \
|
||||
-t beamer \
|
||||
--template 00_preamble.tex \
|
||||
--pdf-engine=pdflatex \
|
||||
--slide-level=2 \
|
||||
--number-sections \
|
||||
--lua-filter ../_extensions/diagram/diagram.lua \
|
||||
--syntax-definition ../_extensions/razor/razor.xml \
|
||||
--syntax-definition ../_extensions/nginx/nginx.xml \
|
||||
-o defensio.pdf
|
||||
20
Defensio/texput.log
Normal file
@@ -0,0 +1,20 @@
|
||||
This is LuaHBTeX, Version 1.24.0 (TeX Live 2026/Arch Linux) (format=lualatex 2026.4.6) 13 APR 2026 22:05
|
||||
restricted system commands enabled.
|
||||
**
|
||||
|
||||
! Emergency stop.
|
||||
<*>
|
||||
|
||||
End of file on the terminal!
|
||||
|
||||
|
||||
|
||||
Here is how much of LuaTeX's memory you used:
|
||||
5 strings out of 476076
|
||||
100000,460012 words of node,token memory allocated 270 words of node memory still in use:
|
||||
1 hlist, 39 glue_spec nodes
|
||||
avail lists: 2:12,3:3,4:1,5:1
|
||||
22567 multiletter control sequences out of 65536+600000
|
||||
14 fonts using 591679 bytes
|
||||
0i,0n,0p,0b,6s stack positions out of 10000i,1000n,20000p,200000b,200000s
|
||||
! ==> Fatal error occurred, no output PDF file produced!
|
||||
376
Defensio/ulem.sty
Normal file
@@ -0,0 +1,376 @@
|
||||
%
|
||||
% U L E M . S T Y [2019-11-18]
|
||||
%
|
||||
% The ulem package provides various types of underlining that can stretch
|
||||
% between words and be broken across lines in LaTeX or plain TeX.
|
||||
% In LaTeX ulem replaces italics with underlining in \em-phasized text.
|
||||
% It is most suitable for simple text such as {\em ibid.} or \emph{\LaTeX:
|
||||
% A Document Preparation System} that may need to be underlined in a
|
||||
% manuscript submitted for publication. A declaration of \normalem (or
|
||||
% the \usepackage option "normalem") restores the normal \em behavior.
|
||||
%
|
||||
% Full instructions appear in ulem.ltx (ulem.pdf). In summary:
|
||||
%
|
||||
% \uline{important} underlined text
|
||||
% \uuline{urgent} double-underlined text
|
||||
% \uwave{boat} wavy underline
|
||||
% \sout{wrong} line drawn through word
|
||||
% \xout{removed} marked over with //////.
|
||||
% \dashuline{dashing} dash underline
|
||||
% \dotuline{dotty} dotted underline
|
||||
%
|
||||
% {\em phasized\/} | In LaTeX, by default, these are underlined; use
|
||||
% \emph{asized} | \normalem or [normalem] to restore italics
|
||||
% \useunder{\uwave}{\bf}{\textbf}
|
||||
% use wavy underline in place of bold face
|
||||
% Use \markoverwith for defining new types of underlining.
|
||||
%
|
||||
% Copyright (c) 1989-2011 by Donald Arseneau (Vancouver, Canada; asnd@triumf.ca)
|
||||
%
|
||||
% This software may be freely transmitted, reproduced, or modified for any
|
||||
% purpose provided that this copyright notice is left intact.
|
||||
% (Small excerpts may be taken and used without any restriction.)
|
||||
%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Defend against multiple loading.
|
||||
\expandafter \ifx \csname UL@box\endcsname \relax \else
|
||||
\immediate\write16{ulem.sty refuses to load twice. }\endinput \fi
|
||||
|
||||
% Set catcode of @ in case it isn't a "letter" already
|
||||
\chardef\ULthickness\catcode\string`\@ % hold catcode temporarily
|
||||
\catcode\string`\@=11
|
||||
|
||||
% \UL@protected = \protected, if available, else \relax
|
||||
|
||||
\begingroup
|
||||
\global\expandafter\let\expandafter\UL@protected\csname protected\endcsname
|
||||
\endgroup
|
||||
|
||||
\UL@protected\def\uline{\relax \ifmmode\expandafter\underline
|
||||
\else \bgroup\expandafter\ULset\fi}
|
||||
|
||||
\newbox\UL@box
|
||||
\newbox\UL@hyphenbox
|
||||
\newskip\UL@skip
|
||||
\newtoks\UL@hook
|
||||
\newdimen\UL@height \UL@height=\maxdimen % flags being unused
|
||||
\newcount\UL@pe
|
||||
|
||||
\UL@protected\def\UL@end *{\relax\relax}% something harmless but unique
|
||||
|
||||
% For regular underlines, set the depth based on the font, or retain
|
||||
% the preset value, then start underlining.
|
||||
\def\ULset{\UL@setULdepth
|
||||
\def\UL@leadtype{\leaders \hrule \@height\UL@height \@depth\ULdepth}%
|
||||
\ifmmode \ULdepth-4\p@ \fi
|
||||
\UL@height-\ULdepth \advance\UL@height\ULthickness \ULon}
|
||||
|
||||
% Automatically set \ULdepth if it is to be automatic (flagged by \maxdimen)
|
||||
\def\UL@setULdepth{\relax
|
||||
\ifdim\ULdepth=\maxdimen % Set depth based on font, if not set already
|
||||
\setbox\UL@box\hbox{{(j}}\ULdepth\dp\UL@box\advance\ULdepth.4\p@
|
||||
% use setbox to support plain TeX
|
||||
\fi}
|
||||
|
||||
% \ULon simply calls \UL@on (possibly \UL@on=\UL@onin) for text mode, but
|
||||
% \UL@onmath if it is math mode.
|
||||
\def\ULon{\ifmmode \expandafter\UL@onmath\else \expandafter\UL@on\fi}
|
||||
|
||||
% \UL@on sets the engine of underline running, and tells it
|
||||
% where to stop. #1 = the relevant text.
|
||||
\long\def\UL@on#1{\leavevmode\UL@ender \let\UL@on\UL@onin
|
||||
\everymath{\UL@hrest}\everyvbox{\UL@hrest}\let\hskip\UL@hskip
|
||||
\let\\\UL@cr \let\-\UL@dischyp \let\newline\UL@newline \let\ \UL@space
|
||||
\def\hfil{\hskip\z@ plus1fil\relax}\def\hfill{\hskip\z@ plus1fill\relax}%
|
||||
\def\hss{\hskip\z@ plus1filminus1fil\relax}\let\penalty\UL@penalty
|
||||
\the\UL@hook
|
||||
\UL@word\@empty#1\xdef\UL@spfactor{\the\spacefactor} \UL@end * }
|
||||
|
||||
% This is what \ULon does when it appears nested in an inner place.
|
||||
\long\def\UL@onin#1{\leavevmode\UL@ender % when nested, do multiple underlining
|
||||
\ifdim\ULdepth=\maxdimen\else
|
||||
\UL@height\ULthickness \advance\ULdepth\thr@@\UL@height \advance\UL@height-\ULdepth
|
||||
\fi
|
||||
\setbox\UL@box\hbox{{#1}}%
|
||||
\let\UL@start\relax\UL@putbox\egroup}
|
||||
% \UL@putbox is disabled in inner mode, so re-enable it by changing \UL@start
|
||||
% \UL@hrest is implicit due to \everyhbox. Double braces for \hbox are in
|
||||
% lieu of \color@begin(end)group.
|
||||
|
||||
% This is what \ULon does in math mode.
|
||||
\def\UL@onmath#1{\UL@ender\mathord{\UL@hrest\mathop{\kern\z@#1}\limits\sb
|
||||
{\UL@leadtype\LA@hskip\p@ plus1fill}}\egroup}
|
||||
|
||||
\def\UL@unegroup{}
|
||||
\gdef\UL@ender{}
|
||||
% end-brace matching hack for when command is used as a font declaration:
|
||||
\def\UL@swender{\ifnum`{=\z@\fi\aftergroup}\gdef\UL@ender{}}
|
||||
|
||||
% must expand to nothing outside the ifs for syntactical spaces to work.
|
||||
% the \expandafters get rid of the \@empty inserted at the beg. of word
|
||||
\long\def\UL@word#1 {\expandafter\UL@start#1 %
|
||||
\expandafter\ifx\expandafter\UL@end#1\egroup\egroup
|
||||
\unskip \unskip \unskip % remove extra leader at end
|
||||
\spacefactor\UL@spfactor \let\UL@word\egroup
|
||||
\else % not finished
|
||||
\ifmmode\else \ifdim\lastskip=\z@\else % allow syntactical spaces
|
||||
\global\UL@skip\lastskip \unskip
|
||||
\UL@stop \UL@leaders
|
||||
\fi\fi
|
||||
\fi \UL@word\@empty}% \@empty preserves braces in param
|
||||
|
||||
% \UL@start: start of each chunk. It gives two levels of grouping.
|
||||
% Each chunk is ended by \UL@stop. Local intermissions go like
|
||||
% \UL@stop...\UL@start.
|
||||
\def\UL@start{\setbox\UL@box\hbox\bgroup\everyhbox{\UL@hrest}%
|
||||
% the following are to cope with stops (\ ,\- etc) within extra braces
|
||||
\let\UL@start\@empty \def\UL@unegroup{\bgroup\bgroup}\let\UL@leadtype\@empty
|
||||
\bgroup \kern-3sp\kern3sp % kerns so I can test for beginning of list
|
||||
\if@ignore \global\@ignorefalse \ignorespaces \fi}
|
||||
|
||||
\def\UL@stop{\global\UL@pe\lastpenalty \unpenalty % penalty in \UL@pe
|
||||
\ifnum\lastkern=\thr@@ \egroup\egroup % Nothing in hbox...but make sure:
|
||||
\ifdim\wd\UL@box=\z@ \else \UL@putbox \fi % something in box so print it
|
||||
\else \egroup\egroup \UL@putbox % something in box so print it
|
||||
\fi \ifnum\UL@pe=\z@ \else \LA@penalty\UL@pe \fi % use penalty from inside box
|
||||
\UL@unegroup}
|
||||
% notice that a box with only a penalty in it is discarded, but the penalty
|
||||
% is still used! This is so a series of discardable glues and penalties
|
||||
% behaves properly.
|
||||
|
||||
\def\UL@putbox{\ifx\UL@start\@empty \else % not inner
|
||||
\vrule\@width\z@ \LA@penalty\@M
|
||||
{\UL@skip\wd\UL@box \UL@leaders \kern-\UL@skip}%
|
||||
\box\UL@box
|
||||
\fi}
|
||||
|
||||
% With interword leaders, give some overlap to avoid gaps caused by
|
||||
% round-off errors in the printing program. Needs \unskip \unskip \unskip
|
||||
% above. This version overlaps 1/300 inch, which looks good at high
|
||||
% resolution, and will still work down to ~150 dpi. Change the value
|
||||
% of \UL@pixel if necessary.
|
||||
|
||||
\newdimen\UL@pixel \UL@pixel=1in \divide\UL@pixel 300
|
||||
|
||||
\def\UL@leaders{{\LA@hskip-\UL@pixel \advance\UL@skip\tw@\UL@pixel
|
||||
\UL@leadtype\LA@hskip\UL@skip \LA@hskip-\UL@pixel}}
|
||||
|
||||
% restore some things for inside math or \mbox
|
||||
\def\UL@hrest{\let\ \LA@space \let\-\@empty \let\penalty\LA@penalty}
|
||||
|
||||
\let\LA@space\ %
|
||||
\UL@protected\def\UL@space{\LA@space \global\UL@skip\lastskip \unskip \UL@reskip}%
|
||||
|
||||
% Hyphenation is done by explicit \discretionary. The overlapping melds
|
||||
% with the running overlap because it *is* part of the running overlap:
|
||||
% The word fragment is extended by the width of the hyphenation which is
|
||||
% then overlapped by leaders. The discretionary may occupy this space
|
||||
% if a break occurs; otherwise the next syllable gets doubly-overlapped
|
||||
% (in registration) for a distance of the hyphen's width.
|
||||
\UL@protected\def\UL@dischyp{\global\setbox\UL@hyphenbox\hbox
|
||||
{\ifnum \hyphenchar\font<\z@ \string-\else \char\hyphenchar\font \fi}%
|
||||
\kern\wd\UL@hyphenbox \LA@penalty\@M
|
||||
\UL@stop \kern-\wd\UL@hyphenbox
|
||||
\discretionary{\box\UL@hyphenbox}{}{}\UL@start}
|
||||
|
||||
\let\LA@penalty\penalty
|
||||
\UL@protected\def\UL@penalty{\relax\ifhmode \afterassignment\UL@@penalty\count@
|
||||
\else\LA@penalty\fi}
|
||||
\def\UL@@penalty{\LA@penalty \ifnum\count@=\z@
|
||||
\@ne \else \count@ \fi % zero penalty => no penalty, so use 1 instead.
|
||||
\UL@stop \UL@start}
|
||||
|
||||
% The test \ifx\ \LA@space \else means we are neither in math mode nor an
|
||||
% \mbox, so it is safe to stop the current \UL@box. \ , \- , and \penalty
|
||||
% (= \linebreak or \nolinebreak) are common enough that they are restored
|
||||
% directly (by \UL@hrest); \\, \newline, \hskip (= \hspace) are rare enough
|
||||
% that the test is incorporated in their UL versions. This adds processing
|
||||
% when they're used, but saves processing in \UL@hrest called by \everymath
|
||||
% \everyvbox and \everyhbox.
|
||||
|
||||
\let\LA@hskip\hskip
|
||||
\UL@protected\def\UL@hskip{\ifx\ \LA@space \LA@hskip \else
|
||||
\afterassignment\UL@reskip \global\UL@skip \fi}
|
||||
|
||||
\def\UL@reskip{\UL@stop \UL@leaders \UL@start}
|
||||
|
||||
% Redefine \\ and \newline so the vertical space from \\[ ] is not lost
|
||||
% and so the \hfil is not underlined! \\ and \newline do nothing if inside
|
||||
% inner braces.
|
||||
|
||||
\UL@protected\def\UL@cr{\unskip \ifx\ \LA@space \let\UL@vad\@gobble
|
||||
\else \UL@stop \unskip\unskip\unskip \let\UL@vad\vadjust \fi
|
||||
\@ifstar{\UL@vad{\LA@penalty\@M}\UL@cra}\UL@cra}
|
||||
\def\UL@cra{\@ifnextchar[\UL@crb\UL@newline}
|
||||
\def\UL@crb[#1]{\UL@vad{\vskip#1}\UL@newline}
|
||||
|
||||
\UL@protected\def\UL@newline{\ifx\UL@start\@empty % (\UL@cr may have \UL@stop-ed already)
|
||||
\unskip \ifx\ \LA@space \else \UL@stop \unskip\unskip\unskip \fi\fi
|
||||
\LA@hskip \z@\@plus.0001fil\LA@penalty -\@M \UL@start}
|
||||
|
||||
% That concludes the basic underlining. To put various other objects
|
||||
% (characters) under (or over) text we need to define \markoverwith
|
||||
% to set the overlay material in a box, and use leaders of that box for
|
||||
% overlaying the text. Here, the meaning of \UL@pixel is changed so
|
||||
% that `pixel' size = box size. Note that we generally need \leaders
|
||||
% (not \cleaders) for text, because an underline will be a patchwork
|
||||
% of small \leaders, and the characters must stay in registration.
|
||||
% However, we "hook" the leaders command so specific applications can
|
||||
% reassign it (\let\ULleaders\xleaders or \let\ULleaders\cleaders).
|
||||
%
|
||||
\newbox\ULC@box
|
||||
\let\ULleaders\leaders
|
||||
|
||||
\UL@protected\def\markoverwith#1{\leavevmode
|
||||
\setbox\ULC@box\hbox{{#1}}\UL@pixel.5\wd\ULC@box
|
||||
\ifmmode \setbox\ULC@box\hbox{\raise1.4ex\box\ULC@box}%
|
||||
\dp\ULC@box-1.4ex\ht\ULC@box\z@ \def\UL@leadtype{\cleaders\copy\ULC@box}%
|
||||
\else
|
||||
\def\UL@leadtype{\ULleaders\copy\ULC@box}%
|
||||
\fi}
|
||||
|
||||
% Now define various special underlines. All the definitions go like
|
||||
% \def \command {\bgroup \markoverwith{something} \ULon}
|
||||
|
||||
% For drawing a wavey underline instead of a straight one the command
|
||||
% is \uwave (under-wave) which uses the wiggle from 6-pt lasy font:
|
||||
|
||||
\UL@protected\def\uwave{\leavevmode \bgroup
|
||||
\ifdim \ULdepth=\maxdimen \ULdepth 3.5\p@
|
||||
\else \advance\ULdepth2\p@
|
||||
\fi \markoverwith{\lower\ULdepth\hbox{\sixly \char58}}\ULon}
|
||||
\font\sixly=lasy6 % does not re-load if already loaded, so no memory drain.
|
||||
|
||||
% To draw a double underline under text, use \uuline{text}
|
||||
|
||||
\UL@protected\def\uuline{\leavevmode \bgroup
|
||||
\UL@setULdepth
|
||||
\ifx\UL@on\UL@onin \advance\ULdepth2.8\p@\fi
|
||||
\markoverwith{\lower\ULdepth\hbox
|
||||
{\kern-.03em\vbox{\hrule width.2em\kern1\p@\hrule}\kern-.03em}}%
|
||||
\ULon}
|
||||
|
||||
% To draw a line through text instead of under it (strike out) do
|
||||
% `under'-line with negative depth. Note that this one uses a real
|
||||
% line, not characters, so there is no \markoverwith.
|
||||
|
||||
\UL@protected\def\sout{\leavevmode \bgroup \ULdepth=-.55ex \ULset}
|
||||
|
||||
% To mark //// over text instead of underlining (x-out)
|
||||
%
|
||||
\UL@protected\def\xout{\leavevmode \bgroup
|
||||
\markoverwith{\hbox to.35em{\hss/\hss}}\ULon}
|
||||
|
||||
\UL@protected\def\dotuline{\leavevmode \bgroup
|
||||
\UL@setULdepth
|
||||
\ifx\UL@on\UL@onin \advance\ULdepth2\p@\fi
|
||||
\markoverwith{\begingroup
|
||||
%\advance\ULdepth0.08ex
|
||||
\lower\ULdepth\hbox{\kern.06em .\kern.04em}%
|
||||
\endgroup}%
|
||||
\ULon}
|
||||
|
||||
\UL@protected\def\dashuline{\leavevmode \bgroup
|
||||
\UL@setULdepth
|
||||
\ifx\UL@on\UL@onin \advance\ULdepth2\p@\fi
|
||||
\markoverwith{\kern.13em
|
||||
\vtop{\kern\ULdepth \hrule width .3em}%
|
||||
\kern.13em}\ULon}
|
||||
|
||||
% A command to declare that an underline command should be used in
|
||||
% place of a particular font selection:
|
||||
% \useunder {underline_command}{font_declaration}{font_command}
|
||||
% e.g.: \useunder{\uuline}{\bfseries}{\textbf}
|
||||
% \useunder{\uwave}{\bf}{}
|
||||
|
||||
\UL@protected\def\useunder#1#2#3{\relax
|
||||
\ifx\relax#2\relax\else % declaration command given
|
||||
\UL@protected\def#2{\def\@tempa{#1}\global\let\UL@ender\UL@swender
|
||||
\expandafter\@tempa\expandafter{\ifnum\z@=\string`}\fi}%
|
||||
\fi
|
||||
\ifx\relax#3\relax\else % argumentative command
|
||||
\UL@protected\def#3{#1}%
|
||||
\fi}
|
||||
|
||||
\expandafter\ifx \csname @ifundefined\endcsname \relax
|
||||
|
||||
% Allow plain TeX to use ulem.sty:
|
||||
\def\@height{height}
|
||||
\def\@depth{depth}
|
||||
\def\@width{width}
|
||||
\def\@empty{}
|
||||
\long\def\@gobble#1{}
|
||||
\long\def\@firstoftwo#1#2{#1}%
|
||||
\long\def\@secondoftwo#1#2{#2}%
|
||||
% Do non-outer \newif with no visible \if's or \fi's when skipping
|
||||
\csname newif\expandafter\endcsname \csname if@ignore\endcsname
|
||||
|
||||
\else
|
||||
|
||||
\let\LA@em\em \let\LA@emph\emph
|
||||
\expandafter\let\expandafter\LA@Pem \csname em \endcsname
|
||||
\expandafter\let\expandafter\LA@Pemph \csname emph \endcsname
|
||||
\def\ULforem{\useunder{\uline}{\em}{\emph}}
|
||||
\def\normalem{\let\em\LA@em \let\emph\LA@emph
|
||||
\expandafter\let\csname em \endcsname\LA@Pem
|
||||
\expandafter\let\csname emph \endcsname\LA@Pemph}
|
||||
\ULforem % default is to use underlining for \em,
|
||||
|
||||
\fi
|
||||
|
||||
% Process LaTeX \package options; plain TeX skips this section
|
||||
|
||||
\expandafter\ifx\csname ProvidesPackage\endcsname \relax \else
|
||||
\ProvidesPackage{ulem}[2019/11/18]
|
||||
\DeclareOption{normalem}{\normalem}
|
||||
\DeclareOption{ULforem}{\ULforem}
|
||||
\DeclareOption{normalbf}{}
|
||||
\DeclareOption{UWforbf}{\useunder{\uwave}{\bf}{\textbf}}
|
||||
\ProcessOptions
|
||||
%
|
||||
\newcommand\UL@marpar[2][\ULmp@opt@arg]{\gdef\ULmp@opt@arg{#2}%
|
||||
\ifx\ \LA@space \@latexerr{Marginpar lost}%
|
||||
\else \UL@stop \LA@marginpar[#1]{#2}\UL@start \fi}
|
||||
%
|
||||
\AtBeginDocument{\let\LA@marginpar\marginpar}%
|
||||
%
|
||||
\addto@hook\UL@hook{\let\marginpar\UL@marpar}
|
||||
\fi
|
||||
|
||||
\catcode`@=\ULthickness % Scratch meaning: restore catcode of @
|
||||
|
||||
\def\ULthickness{.4pt}% can change this with \renewcommand
|
||||
\newdimen\ULdepth \ULdepth=\maxdimen
|
||||
% "maxdimen" depth causes the depth to be set according to the font. You
|
||||
% can change \ULdepth for a permanent setting or a special effect (\sout).
|
||||
|
||||
\endinput
|
||||
|
||||
|
||||
% Previous bug-finders: Esther Hu (\hfill in plain); Lones Smith (\tt\-);
|
||||
% Steve Anderson (\ooalign accents); Thanassi Protopapas ( { in tables).
|
||||
% The bug finders' fee is now $0.00; it will double for each new bug found.
|
||||
% Version (identified by year)
|
||||
% 1994:
|
||||
% Many changes! Notably: LaTeX2e options and \emph. Nesting works (somewhat).
|
||||
% Behavior with inner braces is more consistent (not stripped). \useunder.
|
||||
% Better underwave (using lasy6). Special underlines are not commented out.
|
||||
% patch 1995: fix \UL@swender to work in {tabular}; make hyphenation join
|
||||
% well; crude math support; eliminate \@clb
|
||||
% 1996: use "\csname ProvidesPackage\endcsname", tidying.
|
||||
% 1997: fix \\ when LaTeX changed; remove extra overlap in putbox.
|
||||
% 2000: hook (and marginpar)
|
||||
% 2004: Fix spacing in \uwave and \xout. \ULleaders hook.
|
||||
% 2009: Accept \par in argument (\long)
|
||||
% 2010: Include \dotuline and \dashuline, typeset documentation, add \UL@setULdepth
|
||||
% 2011: Change \dimen@ to \UL@height
|
||||
% 2012: Removed \let\par garbage
|
||||
% 2017: Remove \makerobust
|
||||
% 2019: Handle \ULdepth better. Some tweaks.
|
||||
%
|
||||
% Send problem reports to asnd@triumf.ca
|
||||
%
|
||||
% test integrity:
|
||||
% brackets: round, square, curly, angle: () [] {} <>
|
||||
% backslash, slash, vertical, at, dollar, and: \ / | @ $ &
|
||||
% hat, grave, acute (apostrophe), quote, tilde, under: ^ ` ' " ~ _
|
||||
@@ -1,4 +1,4 @@
|
||||
\newpage
|
||||
\cleardoublepage
|
||||
|
||||
# Kurzfassung {.unnumbered .unlisted}
|
||||
|
||||
@@ -7,13 +7,17 @@ In dieser Diplomarbeit geht es um die Entwicklung von „AlumniHub“ – einer
|
||||
Die technische Arbeit haben wir uns im Team aufgeteilt: Konstantin Hintermayer hat als Product Owner die Linux-Serverinfrastruktur, die PostgreSQL-Datenbank und die CI/CD-Pipelines aufgesetzt sowie das digitale „Schwarze Brett“ programmiert. Adam Gaiswinkler hat das responsive Design im Stil der Schule entworfen und das Event-Anmeldetool sowie die „Hall of Fame“ inklusive PDF-Export umgesetzt. Florian Edlmayer war für den Premiumbereich mit seinem Freigabe-Workflow verantwortlich, hat die DSGVO-Vorgaben umgesetzt und den sicheren Login über LinkedIn (OAuth 2.0) eingebaut. Das Ergebnis ist eine leistungsstarke Plattform, die dem Verein die tägliche Verwaltungsarbeit deutlich erleichtert.
|
||||
\cleardoublepage
|
||||
|
||||
|
||||
\cleardoublepage
|
||||
|
||||
# Abstract {.unnumbered .unlisted}
|
||||
|
||||
This diploma thesis covers the development of "AlumniHub," a web platform designed for the alumni association of the HTL Ungargasse. Our goal was to replace their old, manual administration with an automated system using ASP.NET Core, Blazor, and the Oqtane CMS. The platform now handles communication, event planning, and networking in one central place.
|
||||
|
||||
The technical work was split between the team: Konstantin Hintermayer (Product Owner) was responsible for the Linux server infrastructure, the PostgreSQL database, and CI/CD pipelines, while also building the digital "Blackboard." Adam Gaiswinkler created the responsive UI in the school’s style and implemented the event registration tool and the "Hall of Fame" with automated PDF exports. Florian Edlmayer developed the premium area and its approval workflow, ensured GDPR compliance, and integrated the LinkedIn Login (OAuth 2.0). Overall, we built a high-performance system that significantly simplifies the association’s daily administrative work.
|
||||
|
||||
\newpage
|
||||
|
||||
\cleardoublepage
|
||||
|
||||
# Danksagung {.unnumbered .unlisted}
|
||||
|
||||
@@ -29,13 +33,14 @@ Als wir im Oktober kurzfristig eine neue Produktionsumgebung benötigten, wurde
|
||||
|
||||
Für den „frischen Wind“ und das sorgfältige Korrekturlesen der Arbeit bedanken wir uns herzlich bei Frau Prof. Gertrude Brindlmayer. Ihr geschulter Blick auf Details, die dem Team im Arbeitsprozess entgangen waren, stellte eine große Bereicherung für die finale Qualität dieser Arbeit dar.
|
||||
|
||||
\newpage
|
||||
\cleardoublepage
|
||||
|
||||
# Vorwort {.unnumbered .unlisted}
|
||||
|
||||
Diese Diplomarbeit ist im Schuljahr 2025/2026 an der HTL SZU Ungargasse im Rahmen des Projekts Alumnihub entstanden. Unser Ziel war es, zusammen mit dem Absolventenverein die veraltete Mitgliederverwaltung zu modernisieren und eine neue digitale Plattform für ehemalige Schülerinnen und Schüler zu entwickeln. Was am Anfang nur eine Pflichtaufgabe für die Schule war, wurde für uns schnell zu einem Projekt, mit dem wir uns voll identifiziert haben. Besonders herausfordernd war, dass unser Team im Laufe der Zeit kleiner wurde und wir am Ende nur noch zu dritt waren. Konstantin Hintermayer, Florian Edlmayer und Adam Gaiswinkler mussten deshalb viel mehr Verantwortung übernehmen und technisches Wissen schneller aufbauen als eigentlich geplant. Die Arbeit am AlumniHub war für uns die ideale Chance, das Wissen aus der Theorie endlich mal in einem echten und anspruchsvollen Softwareprojekt einzusetzen. Es war eine stressige, aber sehr lehrreiche Zeit, und wir sind stolz auf das, was wir am Ende als Team abgeliefert haben.
|
||||
|
||||
\newpage
|
||||
|
||||
\cleardoublepage
|
||||
|
||||
# Einsatz Künstlicher Intelligenz (KI-Disclaimer) {.unnumbered .unlisted}
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
\vspace{1cm}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=0.6\textwidth]{images/preamble/logo.png} \\
|
||||
\vspace{1.5cm}
|
||||
|
||||
\textbf{\Huge DIPLOMARBEIT} \\
|
||||
\vspace{1cm}
|
||||
\textbf{\huge AlumniHub} \\
|
||||
\vspace{0.75cm}
|
||||
\textit{\Large Plattform für den Absolventenverein des Schulzentrums HTL HAK Ungargasse} \\
|
||||
\vspace{0.5cm}
|
||||
\textit{\Large Plattform für den Absolventenverein des SZ HTL HAK Ungargasse}
|
||||
\includegraphics[width=0.25\textwidth]{images/preamble/logo-short.png} \\
|
||||
\end{center}
|
||||
|
||||
\vspace{1.75cm}
|
||||
\vspace{2.5cm}
|
||||
|
||||
\begin{minipage}[t]{0.5\textwidth}
|
||||
\textbf{Verfasser:} \\
|
||||
@@ -66,9 +66,9 @@
|
||||
\hrulefill
|
||||
\end{titlepage}
|
||||
|
||||
\newpage
|
||||
\pagenumbering{Roman}
|
||||
\thispagestyle{empty}
|
||||
\cleardoublepage
|
||||
\pagenumbering{Roman}
|
||||
\section*{Eidesstattliche Erklärung}
|
||||
Ich erkläre, dass ich die vorliegende Diplomarbeit selbstständig und ohne fremde Hilfe verfasst, andere als die angegebenen Quellen und Hilfsmittel nicht benutzt, sowie die aus anderen Werken übernommene Inhalte durch Quellenangaben erkenntlich gemacht habe.
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
# Inhaltsverzeichnis {.unnumbered .unlisted}
|
||||
|
||||
\tableofcontents
|
||||
\tableofcontents
|
||||
@@ -26,7 +26,7 @@ Florian Edlmayer entwickelte ein funktionierendes CMS-Modul für den Premiumbere
|
||||
|
||||
## Das Team
|
||||
|
||||
Konstantin Hintermayer
|
||||
**Konstantin Hintermayer**
|
||||
|
||||
Geboren am: 25.05.2007
|
||||
|
||||
@@ -34,7 +34,8 @@ E-Mail: [konstantin.hintermayer@edu.szu.at]
|
||||
|
||||
Individuelle Themenstellung: Projektleitung (Product Owner), (Server-) Infrastruktur, Aufsetzen und Installieren der Server / Linux / Datenbank, Adminzugriff, Skripten, Entwicklung der Auswertungen und des schwarzen Bretts.
|
||||
|
||||
Florian Edlmayer
|
||||
|
||||
**Florian Edlmayer**
|
||||
|
||||
Geboren am: 20.08.2006
|
||||
|
||||
@@ -42,7 +43,8 @@ E-Mail: [florian.edlmayer@edu.szu.at]
|
||||
|
||||
Individuelle Themenstellung: Entwicklung eines CMS-Moduls für den Premiumbereich des Absolventenvereins,Verfassung der Datenschutzerklärung und zuständig für Informationssicherheit, Implementierung von OAuth, Datenbankmanagement.
|
||||
|
||||
Adam Gaiswinkler
|
||||
|
||||
**Adam Gaiswinkler**
|
||||
|
||||
Geboren am: 11.10.2006
|
||||
|
||||
@@ -168,28 +170,28 @@ Die Datenbank wird zur Ausfallsicherheit redundant geführt und nutzt automatisc
|
||||
|
||||
### Konstantin Hintermayer
|
||||
|
||||
| | |
|
||||
| :----------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Themenstellung: | Die individuelle Themenstellung umfasst die Konzeption und Umsetzung der Infrastruktur sowie die Entwicklung von Modulen für Auswertungen und ein Schwarzes Brett innerhalb der Plattform. |
|
||||
| Auflistung der einzelnen Ziele und Anforderungen | HW01, HW02, HW03, HW04/05, HW07, RED-1, SW-4, ScB-1–4 |
|
||||
| | |
|
||||
| :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Themenstellung: | Die individuelle Themenstellung umfasst die Konzeption und Umsetzung der Infrastruktur sowie die Entwicklung von Modulen für Auswertungen und ein Schwarzes Brett innerhalb der Plattform. |
|
||||
| Ziele und Anforderungen | HW01, HW02, HW03, HW04/05, HW07, RED-1, SW-4, ScB-1–4 |
|
||||
|
||||
Table: Aufgabenverteilung Konstantin Hintermayer
|
||||
|
||||
### Florian Edlmayer
|
||||
|
||||
| | |
|
||||
| :----------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Themenstellung: | Die individuelle Themenstellung umfasst die Entwicklung eines Premiumbereichs sowie die Umsetzung von Datenschutz- und Informationssicherheitsmaßnahmen, einschließlich Zugriffs- und Profilverwaltung. |
|
||||
| Auflistung der einzelnen Ziele und Anforderungen | HZ01, HZ05, HW12/13, SnT-3, ZUG-1–4, ZUG-6/7, PRE-1–3, Pro-1–4, DB-1 |
|
||||
| | |
|
||||
| :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| Themenstellung: | Die individuelle Themenstellung umfasst die Entwicklung eines Premiumbereichs sowie die Umsetzung von Datenschutz- und Informationssicherheitsmaßnahmen, einschließlich Zugriffs- und Profilverwaltung. |
|
||||
| Ziele und Anforderungen | HZ01, HZ05, HW12/13, SnT-3, ZUG-1–4, ZUG-6/7, PRE-1–3, Pro-1–4, DB-1 |
|
||||
|
||||
Table: Aufgabenverteilung Florian Edlmayer
|
||||
|
||||
### Adam Gaiswinkler
|
||||
|
||||
| | |
|
||||
| :----------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Themenstellung: | Die individuelle Themenstellung umfasst die Entwicklung einer Hall of Fame, die Implementierung eines Anmeldetools für Treffen sowie die Konfiguration des Content-Management-Systems. |
|
||||
| Auflistung der einzelnen Ziele und Anforderungen | HZ02, HZ03, HZ06, SnT-2, SW-1/2, HoF-1/2, AfT-1–5 |
|
||||
| | |
|
||||
| :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Themenstellung: | Die individuelle Themenstellung umfasst die Entwicklung einer Hall of Fame, die Implementierung eines Anmeldetools für Treffen sowie die Konfiguration des Content-Management-Systems. |
|
||||
| Ziele und Anforderungen | HZ02, HZ03, HZ06, SnT-2, SW-1/2, HoF-1/2, AfT-1–5 |
|
||||
|
||||
Table: Aufgabenverteilung Adam Gaiswinkler
|
||||
|
||||
@@ -198,13 +200,13 @@ Table: Aufgabenverteilung Adam Gaiswinkler
|
||||
### Meilensteine
|
||||
|
||||
| # | Datum | Beschreibung |
|
||||
| :-- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| :-- | :------------- | --------------------------------------------------------- |
|
||||
| _1_ | _19.09.2025_ | Fertigstellung und Abgabe des Diplomarbeitsantrags. |
|
||||
| _2_ | _30.10.2025_ | [cite_start]Server-Setup mit SSH-Zugriff [cite: 83][cite_start], CMS-Grundkonfiguration (Oqtane) im SZU-Design [cite: 69, 83][cite_start], Implementierung der Eingabemaske und API für das Anmeldetool [cite: 137] [cite_start]sowie Erstellung der DSGVO-Richtlinien [cite: 38] [cite_start]und Backupstrategie[cite: 55, 62]. |
|
||||
| _3_ | _27.11.2025_ | [cite_start]Entwicklung grafischer Auswertungen für Anmeldedaten [cite: 120] [cite_start]und Integration der OAuth-Authentifizierung zum automatisierten Abruf von Profildaten[cite: 78, 148]. |
|
||||
| _4_ | _18.12.2025_ | Realisierung des Schwarzen Bretts inkl. [cite_start]Sperrfunktion für Administratoren [cite: 133][cite_start], Entwicklung des Hall of Fame Moduls mit PDF-Generierung [cite: 105] [cite_start]sowie Aufbau der Premiumkunden-Verwaltung[cite: 113]. |
|
||||
| _5_ | _21.01.2026_ | [cite_start]Erstellung der technischen Systemdokumentation [cite: 155][cite_start], Durchführung von Modultests und Implementierung der Premium-Serviceverwaltung[cite: 113]. |
|
||||
| _6_ | _08.02.2026_ | [cite_start]Projektabschluss der Infrastruktur-Tasks, Übergabe der Disaster-Recovery-Skripte [cite: 58] [cite_start]und Finalisierung der gesamten Projektdokumentation[cite: 155]. |
|
||||
| _2_ | _30.10.2025_ | Server-Setup mit SSH-Zugriff, CMS-Grundkonfiguration (Oqtane) im SZU-Design, Implementierung der Eingabemaske und API für das Anmeldetool sowie Erstellung der DSGVO-Richtlinien und Backupstrategie. |
|
||||
| _3_ | _27.11.2025_ | Entwicklung grafischer Auswertungen für Anmeldedaten und Integration der OAuth-Authentifizierung zum automatisierten Abruf von Profildaten. |
|
||||
| _4_ | _18.12.2025_ | Realisierung des Schwarzen Bretts inkl. Sperrfunktion für Administratoren, Entwicklung des Hall of Fame Moduls mit PDF-Generierung sowie Aufbau der Premiumkunden-Verwaltung. |
|
||||
| _5_ | _21.01.2026_ | Erstellung der technischen Systemdokumentation, Durchführung von Modultests und Implementierung der Premium-Serviceverwaltung. |
|
||||
| _6_ | _08.02.2026_ | Projektabschluss der Infrastruktur-Tasks, Übergabe der Disaster-Recovery-Skripte und Finalisierung der gesamten Projektdokumentation. |
|
||||
| _7_ | _12.03.2026_ | Finale Abgabe des Diplomarbeitsbuchs. |
|
||||
| _8_ | _22.04.2026_ | Defensio (Projektabschluss). |
|
||||
|
||||
@@ -212,20 +214,20 @@ Table: Meilensteine
|
||||
|
||||
### Sprints
|
||||
|
||||
| # | Beginn | Ende | Hinweis | Meilensteine |
|
||||
| :-- | :--------- | :--------- | :--------------- | :------------- |
|
||||
| 1 | 02.10.2025 | 16.10.2025 | | |
|
||||
| 2 | 16.10.2025 | 30.10.2025 | | 1. Meilenstein |
|
||||
| 3 | 30.10.2025 | 13.11.2025 | Herbstferien | |
|
||||
| 4 | 13.11.2025 | 27.11.2025 | | 2. Meilenstein |
|
||||
| 5 | 27.11.2025 | 11.12.2025 | | |
|
||||
| 6 | 11.12.2025 | 25.12.2025 | Weihnachtsferien | 3. Meilenstein |
|
||||
| 7 | 25.12.2025 | 08.01.2026 | Weihnachtsferien | |
|
||||
| 8 | 08.01.2026 | 22.01.2026 | | 4. Meilenstein |
|
||||
| 9 | 22.01.2026 | 05.02.2026 | Semesterferien | |
|
||||
| 10 | 05.02.2026 | 19.02.2026 | | 5. Meilenstein |
|
||||
| 11 | 19.02.2026 | 05.03.2026 | | |
|
||||
| 12 | 05.03.2026 | 19.03.2026 | | 6. Meilenstein |
|
||||
| # | Beginn | Ende | Hinweis | Meilensteine |
|
||||
| :--- | :--------- | :--------- | :--------------- | :------------- |
|
||||
| 1 | 02.10.2025 | 16.10.2025 | | |
|
||||
| 2 | 16.10.2025 | 30.10.2025 | | 1. Meilenstein |
|
||||
| 3 | 30.10.2025 | 13.11.2025 | Herbstferien | |
|
||||
| 4 | 13.11.2025 | 27.11.2025 | | 2. Meilenstein |
|
||||
| 5 | 27.11.2025 | 11.12.2025 | | |
|
||||
| 6 | 11.12.2025 | 25.12.2025 | Weihnachtsferien | 3. Meilenstein |
|
||||
| 7 | 25.12.2025 | 08.01.2026 | Weihnachtsferien | |
|
||||
| 8 | 08.01.2026 | 22.01.2026 | | 4. Meilenstein |
|
||||
| 9 | 22.01.2026 | 05.02.2026 | Semesterferien | |
|
||||
| 10 | 05.02.2026 | 19.02.2026 | | 5. Meilenstein |
|
||||
| 11 | 19.02.2026 | 05.03.2026 | | |
|
||||
| 12 | 05.03.2026 | 19.03.2026 | | 6. Meilenstein |
|
||||
|
||||
Table: Sprints und deren Schwerpunkte
|
||||
|
||||
@@ -234,6 +236,8 @@ Table: Sprints und deren Schwerpunkte
|
||||
### Grafische Darstellung
|
||||
|
||||
```mermaid
|
||||
%%| fig-cap: Projektumfeld Analyse
|
||||
%%| filename: projektumfeld-analyse
|
||||
|
||||
flowchart TD
|
||||
%% Interne Umwelten (Oben)
|
||||
@@ -284,29 +288,40 @@ Table: Sprints und deren Schwerpunkte
|
||||
|
||||
### Beschreibung der wichtigsten Umfelder
|
||||
|
||||
| 8 | Konkurrenz | Potenziell vorhandene Konkurrenz | - |
|
||||
| # | Bezeichnung | Beschreibung | Bewertung |
|
||||
| :--- | :--------------------- | :------------------------------- | :-------- |
|
||||
| 1 | Konstantin Hintermayer | Projektleiter | + |
|
||||
| 2 | Florian Edlmayer | Projektmitarbeiter | + |
|
||||
| 3 | Adam Gaiswinkler | Projektmitarbeiter | + |
|
||||
| 4 | Ing. Thomas Gürth | Projektbetreuer | + |
|
||||
| 5 | Absolventenverein | Auftraggeber des Alumnihubs | +/- |
|
||||
| 6 | Schülerinnen/Schüler | Zielgruppe der SZU Ungargasse | +/- |
|
||||
| 7 | Lehrerinnen/Lehrer | Lehrpersonal der SZU Ungargasse | +/- |
|
||||
| 8 | Konkurrenz | Potenziell vorhandene Konkurrenz | - |
|
||||
|
||||
Table: Projektumfelder und deren Bewertung
|
||||
|
||||
## Risikoanalyse
|
||||
|
||||
| # | Bezeichnung | Beschreibung | Wahrscheinlichkeit (%) | Auswirkung (%) | Risikowert |
|
||||
| :-- | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------- | :--------------------: | :------------: | :--------: |
|
||||
| 1 | Infrastruktur | [cite_start]Instabilität oder Fehlkonfiguration der Cloud-Server (Hetzner CX22), die den Live-Betrieb unterbrechen[cite: 45, 51]. | 60 | 90 | 5400 |
|
||||
| 2 | Datenverlust | [cite_start]Kritischer Ausfall der Datenbank ohne erfolgreiche Wiederherstellung durch automatisierte Backups[cite: 51, 62]. | 15 | 95 | 1425 |
|
||||
| 3 | DSGVO-Verstoß | [cite_start]Fehlende Konformität bei der Speicherung personenbezogener Daten oder beim Opt-In-Verfahren[cite: 38, 39, 128]. | 10 | 100 | 1000 |
|
||||
| 4 | Sicherheitslücke | [cite_start]Unbefugter Zugriff auf das System durch Schwachstellen in der VPN- oder SSH-Verbindung[cite: 83]. | 15 | 85 | 1275 |
|
||||
| 5 | API-Schnittstellen | [cite_start]Ausfall oder Inkompatibilität externer Dienste wie LinkedIn OAuth oder Brevo Mailservice[cite: 74, 78]. | 30 | 50 | 1500 |
|
||||
| 6 | Performance | [cite_start]Beeinträchtigung der Systemleistung bei steigenden Zugriffszahlen in Phase 2[cite: 44, 46]. | 40 | 40 | 1600 |
|
||||
| 7 | Wiederherstellung | [cite_start]Überschreitung des geplanten Disaster-Recovery-Zeitraums von 24 Stunden[cite: 51, 66]. | 25 | 70 | 1750 |
|
||||
| 8 | Oqtane-Integration | [cite_start]Komplexität bei der Entwicklung und Einbindung benutzerdefinierter CMS-Module[cite: 69, 72]. | 30 | 45 | 1350 |
|
||||
| 9 | Dokumentation | [cite_start]Lückenhafte technische Dokumentation erschwert die Wartung durch den Absolventenverein[cite: 155]. | 20 | 30 | 600 |
|
||||
| # | Bezeichnung | Beschreibung | Warsch. (%) | Ausw. (%) | Risikowert |
|
||||
| :-- | :----------------- | :-------------------------------------------------------- | :-------: | :-------: | :-----: |
|
||||
| 1 | Infrastruktur | Instabilität oder Fehlkonfiguration der Cloud-Server (Hetzner CX22), die den Live-Betrieb unterbrechen. | 60 | 90 | 5400 |
|
||||
| 2 | Datenverlust | Kritischer Ausfall der Datenbank ohne erfolgreiche Wiederherstellung durch automatisierte Backups. | 20 | 92 | 1425 |
|
||||
| 3 | DSGVO-Verstoß | Fehlende Konformität bei der Speicherung personenbezogener Daten oder beim Opt-In-Verfahren. | 10 | 89 | 1000 |
|
||||
| 4 | Sicherheitslücke | Unbefugter Zugriff auf das System durch Schwachstellen in der VPN- oder SSH-Verbindung. | 15 | 85 | 1275 |
|
||||
| 5 | API-Schnittstellen | Ausfall oder Inkompatibilität externer Dienste wie LinkedIn OAuth oder Brevo Mailservice. | 30 | 50 | 1500 |
|
||||
| 6 | Performance | Beeinträchtigung der Systemleistung bei steigenden Zugriffszahlen in Phase 2. | 40 | 40 | 1600 |
|
||||
| 7 | Wieder-herstellung | Überschreitung des geplanten Disaster-Recovery-Zeitraums von 24 Stunden. | 25 | 70 | 1750 |
|
||||
| 8 | Oqtane-Integration | Komplexität bei der Entwicklung und Einbindung benutzerdefinierter CMS-Module. | 55 | 45 | 1350 |
|
||||
| 9 | Dokumentation | Lückenhafte technische Dokumentation erschwert die Wartung durch den Absolventenverein. | 20 | 30 | 600 |
|
||||
|
||||
Table: Risikoanalyse und Bewertung
|
||||
|
||||
### Grafische Darstellung
|
||||
|
||||
```mermaid
|
||||
%%| fig-cap: Risikoportfolio Alumnihub
|
||||
%%| filename: risikoportfolio-alumnihub
|
||||
quadrantChart
|
||||
title Risikoportfolio Alumnihub
|
||||
x-axis Geringe Auswirkung --> Hohe Auswirkung
|
||||
@@ -316,19 +331,19 @@ quadrantChart
|
||||
quadrant-3 Akzeptabel
|
||||
quadrant-4 Handlungsbedarf
|
||||
Infrastruktur: [0.9, 0.6]
|
||||
Datenverlust: [0.95, 0.15]
|
||||
DSGVO_Verstoss: [0.99, 0.1]
|
||||
Datenverlust: [0.92, 0.2]
|
||||
DSGVO_Verstoss: [0.89, 0.1]
|
||||
Sicherheitsluecke: [0.85, 0.15]
|
||||
API_Schnittstellen: [0.5, 0.3]
|
||||
Performance: [0.4, 0.4]
|
||||
Wiederherstellung: [0.7, 0.25]
|
||||
Oqtane_Integration: [0.45, 0.3]
|
||||
Oqtane_Integration: [0.55, 0.45]
|
||||
Dokumentation: [0.3, 0.2]
|
||||
```
|
||||
|
||||
## Projektressourcen
|
||||
|
||||
### 2.6.3 Personelle Ressourcen (geplant)
|
||||
### Personelle Ressourcen (geplant)
|
||||
|
||||
| Teammitglied | Personenstunden |
|
||||
| :------------------------- | :-------------: |
|
||||
@@ -337,9 +352,7 @@ quadrantChart
|
||||
| **Adam Gaiswinkler** | 180 |
|
||||
| **SUMME** | **540** |
|
||||
|
||||
_Tabelle 7: Personelle Ressourcen_
|
||||
|
||||
Table: Geplante persönliche Zeitressourcen
|
||||
Table: Personelle Ressourcen
|
||||
|
||||
### Persönliche Ressourcen(real)
|
||||
|
||||
@@ -382,8 +395,7 @@ Die agile Arbeitsweise von Scrum basiert auf einer iterativen und inkrementellen
|
||||
|
||||
Die grundlegende Struktur und der Ablauf eines Scrum-Projekts sind in Abbildung X dargestellt.
|
||||
|
||||

|
||||
_Abbildung X: Übersicht des Scrum-Frameworks mit Rollen, Artefakten und Ereignissen_
|
||||

|
||||
|
||||
Die Abbildung zeigt die wichtigsten Elemente des Scrum-Frameworks. Auf der linken Seite sind die Anforderungen des Projekts dargestellt, die im sogenannten Product Backlog gesammelt werden. Dieses Backlog enthält alle geplanten Funktionen, Verbesserungen und Aufgaben des Projekts. Diese Anforderungen stammen häufig von Stakeholdern oder zukünftigen Benutzern der Anwendung.
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
# Adam Gaiswinkler
|
||||
|
||||
## 1. Einleitung des individuellen Teils
|
||||
## Einleitung des individuellen Teils
|
||||
|
||||
### 1.1 Motivation
|
||||
### Motivation
|
||||
|
||||
Zu Beginn des Projekts war meine persönliche Motivation überschaubar. Wie viele Schulprojekte startete auch AlumniHub zunächst als eine Pflichtaufgabe – ich war zwar von Anfang an dabei, jedoch ohne besonders großes Interesse am Thema. Das Projekt war zu Beginn eine von vielen schulischen Anforderungen, und ich sah es zunächst nicht als etwas, mit dem ich mich wirklich identifizieren würde. Die Aufgabenstellung klang zwar interessant, aber der persönliche Bezug fehlte noch.
|
||||
|
||||
@@ -14,71 +14,71 @@ Genau in diesem Moment begann mein Interesse zu wachsen. Je mehr Verantwortung i
|
||||
|
||||
Die technische Herausforderung, eine moderne Webanwendung mit Blazor und ASP.NET umzusetzen, sowie die Möglichkeit, ein echtes System für eine reale Organisation zu entwickeln, wurden zur echten Motivation. Die Aufgabenstellung bot mir die Chance, theoretisches Wissen aus dem Unterricht in einem praxisnahen Umfeld anzuwenden und gleichzeitig einen konkreten Mehrwert für den Absolventenverein zu schaffen. Rückblickend war die Teamverkleinerung – obwohl sie damals als Problem wahrgenommen wurde – einer der wichtigsten Faktoren für meine persönliche Entwicklung im Rahmen dieses Projekts.
|
||||
|
||||
### 1.2 Individuelle Themenstellung
|
||||
### Individuelle Themenstellung
|
||||
|
||||
Entwicklung des Anmeldetools und Hall-of-Fame-Moduls für Oqtane, Integration in das bestehende CMS-System, Responsive UI-Entwicklung mit Blazor und ASP.NET Core
|
||||
|
||||
### 1.3 Teamrolle
|
||||
### Teamrolle
|
||||
|
||||
Developer, Tester der eigenen Module
|
||||
|
||||
### 1.4 Untersuchungsanliegen
|
||||
### Untersuchungsanliegen
|
||||
|
||||
Modulentwicklung mit Blazor und ASP.NET Core, Integration eigenständiger Module in die Oqtane-Architektur, Entwicklung reaktiver Benutzeroberflächen mit Blazor-Komponenten, Responsive UI-Design mit Bootstrap und eigenem CSS, PDF-Generierung mit QuestPDF, Fehlerbehebung und Optimierung der mobilen Darstellung
|
||||
|
||||
### 1.5 Persönlicher Aufgabenbereich
|
||||
### Persönlicher Aufgabenbereich
|
||||
|
||||
Der persönliche Aufgabenbereich umfasste die Entwicklung der beiden zentralen CMS-Module der Plattform: das Anmeldetool für Veranstaltungen sowie das Hall-of-Fame-Modul. Beide Module wurden als eigenständige, wiederverwendbare Oqtane-Module konzipiert und vollständig in C# und Blazor implementiert. Neben der technischen Umsetzung lag ein besonderer Fokus auf der Benutzerfreundlichkeit, der responsiven Darstellung und der nahtlosen Integration in das bestehende CMS-System.
|
||||
|
||||
### 1.6 Abgrenzung der Arbeit
|
||||
### Abgrenzung der Arbeit
|
||||
|
||||
Das Datenbankdesign sowie die Infrastruktur und das Server-Setup waren nicht Teil meines persönlichen Aufgabenbereichs und wurden von anderen Teammitgliedern verantwortet. Mein persönlicher Anteil beschränkt sich auf die Entwicklung der Anwendungsschicht, konkret auf die Implementierung der beiden CMS-Module – das Anmeldetool und das Hall-of-Fame-Modul – sowie deren Integration in das bestehende System.
|
||||
|
||||
## 2. Technologien
|
||||
## Technologien
|
||||
|
||||
In diesem Kapitel werden die Technologien und Werkzeuge vorgestellt, die für die Entwicklung des Anmeldetools, des Hall-of-Fame-Moduls und des Oqtane-Themes eingesetzt wurden. Die Beschreibungen sind dabei so gestaltet, dass sie auch für Leserinnen und Leser ohne technischen Hintergrund verständlich sind.
|
||||
|
||||
### 2.1 C# und ASP.NET Core
|
||||
### C# und ASP.NET Core
|
||||
|
||||
C# ist eine moderne Programmiersprache von Microsoft, die besonders für die Entwicklung von Webanwendungen und Softwaresystemen geeignet ist. Sie ist klar strukturiert, gut lesbar und weit verbreitet in der professionellen Softwareentwicklung. ASP.NET Core ist ein Framework – also eine Art Werkzeugkasten – das auf C# aufbaut und die Entwicklung von Webseiten und Webanwendungen vereinfacht. Es stellt vorgefertigte Bausteine bereit, sodass man nicht alles von Grund auf neu programmieren muss. Für AlumniHub bildete ASP.NET Core die technische Grundlage aller entwickelten Module.
|
||||
C# ist eine moderne Programmiersprache von Microsoft, die besonders für die Entwicklung von Webanwendungen und Softwaresystemen geeignet ist. Sie ist klar strukturiert, gut lesbar und weit verbreitet in der professionellen Softwareentwicklung. ASP.NET Core ist ein Framework – also eine Art Werkzeugkasten – das auf C# aufbaut und die Entwicklung von Webseiten und Webanwendungen vereinfacht [@aspnet_core_docs]. Es stellt vorgefertigte Bausteine bereit, sodass man nicht alles von Grund auf neu programmieren muss. Für AlumniHub bildete ASP.NET Core die technische Grundlage aller entwickelten Module.
|
||||
|
||||
### 2.2 Blazor
|
||||
### Blazor
|
||||
|
||||
Blazor ist ein Framework, das es ermöglicht, interaktive Weboberflächen direkt in C# zu entwickeln. Normalerweise werden solche Oberflächen – also alles, was der Benutzer auf dem Bildschirm sieht und mit dem er interagiert – mit einer anderen Programmiersprache namens JavaScript umgesetzt. Blazor erlaubt es, dasselbe in C# zu schreiben, was die Entwicklung vereinheitlicht und übersichtlicher macht. Konkret bedeutet das: Wenn ein Benutzer beispielsweise auf den „Zusagen"-Button klickt, reagiert die Seite sofort und aktualisiert sich automatisch – ohne dass die gesamte Seite neu geladen werden muss.
|
||||
Blazor ist ein Framework, das es ermöglicht, interaktive Weboberflächen direkt in C# zu entwickeln [@blazor_docs]. Normalerweise werden solche Oberflächen – also alles, was der Benutzer auf dem Bildschirm sieht und mit dem er interagiert – mit einer anderen Programmiersprache namens JavaScript umgesetzt. Blazor erlaubt es, dasselbe in C# zu schreiben, was die Entwicklung vereinheitlicht und übersichtlicher macht. Konkret bedeutet das: Wenn ein Benutzer beispielsweise auf den „Zusagen"-Button klickt, reagiert die Seite sofort und aktualisiert sich automatisch – ohne dass die gesamte Seite neu geladen werden muss.
|
||||
|
||||
### 2.3 Oqtane
|
||||
### Oqtane
|
||||
|
||||
Oqtane ist ein Content-Management-System (CMS) – also eine Software, mit der Webseiten und deren Inhalte verwaltet werden können, ähnlich wie WordPress oder Typo3. Das Besondere an Oqtane ist, dass es vollständig auf Blazor und C# aufbaut und eine modulare Architektur besitzt: Man kann eigene Erweiterungen – sogenannte Module – entwickeln und in das System einbinden, ohne den Kern der Software verändern zu müssen. Für AlumniHub wurde Oqtane als Grundlage gewählt, weil es Benutzerverwaltung, Seitenstruktur und viele weitere Standardfunktionen bereits mitbringt und somit viel Entwicklungsaufwand spart.
|
||||
Oqtane ist ein Content-Management-System (CMS) – also eine Software, mit der Webseiten und deren Inhalte verwaltet werden können, ähnlich wie WordPress oder Typo3 [@oqtane_framework_site]. Das Besondere an Oqtane ist, dass es vollständig auf Blazor und C# aufbaut und eine modulare Architektur besitzt: Man kann eigene Erweiterungen – sogenannte Module – entwickeln und in das System einbinden, ohne den Kern der Software verändern zu müssen [@oqtane_docs_dev]. Für AlumniHub wurde Oqtane als Grundlage gewählt, weil es Benutzerverwaltung, Seitenstruktur und viele weitere Standardfunktionen bereits mitbringt und somit viel Entwicklungsaufwand spart.
|
||||
|
||||
### 2.4 Bootstrap und CSS
|
||||
### Bootstrap und CSS
|
||||
|
||||
CSS (Cascading Style Sheets) ist die Sprache, mit der das Aussehen einer Webseite festgelegt wird – also Farben, Schriftarten, Abstände und das Layout. Bootstrap ist eine fertige Sammlung von CSS-Regeln und Hilfsmitteln, die von Twitter entwickelt wurde und kostenlos verfügbar ist. Der große Vorteil von Bootstrap ist, dass es sogenanntes Responsive Design einfach umsetzbar macht: Die Webseite passt sich automatisch an verschiedene Bildschirmgrößen an – egal ob Desktop, Tablet oder Smartphone. Für AlumniHub wurde Bootstrap als Basis verwendet, ergänzt durch eigenes CSS für das individuelle Erscheinungsbild der Plattform.
|
||||
CSS (Cascading Style Sheets) ist die Sprache, mit der das Aussehen einer Webseite festgelegt wird – also Farben, Schriftarten, Abstände und das Layout. Bootstrap ist eine fertige Sammlung von CSS-Regeln und Hilfsmitteln, die von Twitter entwickelt wurde und kostenlos verfügbar ist [@bootstrap]. Der große Vorteil von Bootstrap ist, dass es sogenanntes Responsive Design einfach umsetzbar macht: Die Webseite passt sich automatisch an verschiedene Bildschirmgrößen an – egal ob Desktop, Tablet oder Smartphone. Für AlumniHub wurde Bootstrap als Basis verwendet, ergänzt durch eigenes CSS für das individuelle Erscheinungsbild der Plattform.
|
||||
|
||||
### 2.5 QuestPDF
|
||||
### QuestPDF
|
||||
|
||||
QuestPDF ist eine kostenlose Open-Source-Bibliothek – also eine fertige Programmsammlung – die es ermöglicht, PDF-Dokumente direkt aus C#-Code heraus zu erstellen. Anstatt ein PDF manuell zu gestalten, beschreibt man im Code wie das Dokument aussehen soll, und QuestPDF generiert daraus automatisch eine fertige PDF-Datei. Im Hall-of-Fame-Modul wurde QuestPDF eingesetzt, um jedem Absolventen zu ermöglichen, sein eigenes Profil als visuell ansprechendes PDF herunterzuladen.
|
||||
QuestPDF ist eine kostenlose Open-Source-Bibliothek – also eine fertige Programmsammlung – die es ermöglicht, PDF-Dokumente direkt aus C#-Code heraus zu erstellen [@questpdf]. Anstatt ein PDF manuell zu gestalten, beschreibt man im Code wie das Dokument aussehen soll, und QuestPDF generiert daraus automatisch eine fertige PDF-Datei. Im Hall-of-Fame-Modul wurde QuestPDF eingesetzt, um jedem Absolventen zu ermöglichen, sein eigenes Profil als visuell ansprechendes PDF herunterzuladen.
|
||||
|
||||
### 2.6 Gitea
|
||||
### Gitea
|
||||
|
||||
Wenn mehrere Personen gemeinsam an einem Softwareprojekt arbeiten, braucht man ein System, das alle Änderungen am Code nachverfolgt und verhindert, dass sich Änderungen verschiedener Personen gegenseitig überschreiben. Dieses Konzept nennt sich Versionskontrolle. Gitea ist eine selbst gehostete Plattform für genau diesen Zweck – ähnlich wie GitHub, aber auf einem eigenen Server betrieben. Jede Änderung am Code wird als sogenannter „Commit" gespeichert, sodass man jederzeit nachvollziehen kann, wer wann was geändert hat, und bei Bedarf auf eine ältere Version zurückwechseln kann.
|
||||
Wenn mehrere Personen gemeinsam an einem Softwareprojekt arbeiten, braucht man ein System, das alle Änderungen am Code nachverfolgt und verhindert, dass sich Änderungen verschiedener Personen gegenseitig überschreiben. Dieses Konzept nennt sich Versionskontrolle. Gitea ist eine selbst gehostete Plattform für genau diesen Zweck – ähnlich wie GitHub, aber auf einem eigenen Server betrieben [@gitea_about]. Jede Änderung am Code wird als sogenannter „Commit" gespeichert, sodass man jederzeit nachvollziehen kann, wer wann was geändert hat, und bei Bedarf auf eine ältere Version zurückwechseln kann.
|
||||
|
||||
### 2.7 Entwicklungsumgebung
|
||||
### Entwicklungsumgebung
|
||||
|
||||
Eine Entwicklungsumgebung – auch IDE (Integrated Development Environment) genannt – ist ein Programm, das Entwicklerinnen und Entwickler beim Schreiben von Code unterstützt. Sie bietet unter anderem Funktionen wie automatische Vervollständigung, Fehlererkennung und integrierte Debugging-Werkzeuge, die das Auffinden und Beheben von Fehlern im Code erleichtern.
|
||||
|
||||
Zu Beginn des Projekts wurde Visual Studio 2022 auf Windows verwendet. Visual Studio 2022 ist die führende Entwicklungsumgebung von Microsoft für .NET-Projekte und bietet eine umfangreiche Unterstützung für ASP.NET Core und Blazor. Im Laufe des Projekts erfolgte jedoch ein Wechsel von Windows auf macOS. Da Visual Studio 2022 auf Mac nicht mehr verfügbar ist – Microsoft hat die Mac-Version eingestellt – wurde als Ersatz JetBrains Rider eingesetzt. JetBrains Rider ist eine next-generation IDE von Google, die plattformübergreifend funktioniert und eine moderne Entwicklungsumgebung für .NET-Projekte auf macOS bietet. Der Umstieg auf JetBrains Rider ermöglichte es, die Entwicklung auf dem neuen System ohne größere Unterbrechungen fortzusetzen.
|
||||
Zu Beginn des Projekts wurde Visual Studio 2022 auf Windows verwendet. Visual Studio 2022 ist die führende Entwicklungsumgebung von Microsoft für .NET-Projekte und bietet eine umfangreiche Unterstützung für ASP.NET Core und Blazor. Im Laufe des Projekts erfolgte jedoch ein Wechsel von Windows auf macOS. Da Visual Studio 2022 auf Mac nicht mehr verfügbar ist – Microsoft hat die Mac-Version eingestellt – wurde als Ersatz JetBrains Rider eingesetzt [@jetbrains_rider]. JetBrains Rider ist eine next-generation IDE von JetBrains, die plattformübergreifend funktioniert und eine moderne Entwicklungsumgebung für .NET-Projekte auf macOS bietet. Der Umstieg auf JetBrains Rider ermöglichte es, die Entwicklung auf dem neuen System ohne größere Unterbrechungen fortzusetzen.
|
||||
|
||||
### 2.8 Plattformwechsel: Windows zu macOS
|
||||
### Plattformwechsel: Windows zu macOS
|
||||
|
||||
Ein besonderer Aspekt der Entwicklung war der Wechsel von Windows auf macOS während des Projektverlaufs. Unter Plattform versteht man in der Softwareentwicklung das Betriebssystem, auf dem eine Anwendung läuft – also etwa Windows, macOS oder Linux. Dieser Wechsel brachte spezifische Herausforderungen mit sich, da Oqtane primär für Windows entwickelt wurde. Obwohl Oqtane grundsätzlich auch auf macOS und Linux lauffähig ist, ist die Unterstützung für diese Plattformen veraltet und nicht vollständig angepasst. In der Praxis bedeutete das: Der Code ließ sich teilweise nicht fehlerfrei kompilieren – also in ein lauffähiges Programm umwandeln – und Oqtane startete zunächst nur mit Fehlermeldungen. Durch den Einsatz von JetBrains Rider als IDE konnten diese Probleme weitgehend gelöst werden, da JetBrains Rider eine bessere plattformübergreifende Integration bietet als die ursprünglich verwendete Entwicklungsumgebung.
|
||||
|
||||
---
|
||||
## Module
|
||||
|
||||
## 3. Module
|
||||
### Entwicklung des Oqtane Themes
|
||||
|
||||
### 3.1 Entwicklung des Oqtane Themes
|
||||
#### Ziel des Themes
|
||||
|
||||
#### 3.1.1 Ziel des Themes
|
||||
\
|
||||
|
||||
Im Rahmen des Projekts AlumniHub wurde ein eigenes Theme für das Content-Management-System Oqtane entwickelt. Ziel dieser Entwicklung war es, das Standarddesign von Oqtane vollständig durch eine projektspezifische Benutzeroberfläche zu ersetzen, die den Anforderungen des Absolventenvereins der HTL Ungargasse entspricht. Das Standardtheme von Oqtane ist funktional, jedoch generisch gehalten und bietet keinen Bezug zur Schule oder zum Projekt. Aus diesem Grund wurde frühzeitig die Entscheidung getroffen, ein vollständig eigenes Theme zu entwickeln, das sowohl optisch als auch technisch auf die Bedürfnisse der Plattform zugeschnitten ist.
|
||||
|
||||
@@ -86,11 +86,15 @@ Das visuelle Design orientiert sich dabei am bestehenden Erscheinungsbild der of
|
||||
|
||||
Neben der visuellen Gestaltung standen auch technische Anforderungen im Mittelpunkt. Das Theme sollte auf unterschiedlichen Endgeräten – sowohl auf Desktop-Computern als auch auf Smartphones und Tablets – zuverlässig und benutzerfreundlich funktionieren. Responsive Design war daher von Anfang an eine zentrale Anforderung. Darüber hinaus sollte das Theme vollständig in die Oqtane-Architektur integriert sein, sodass alle Standardfunktionen des CMS wie Benutzerverwaltung, Seitenverwaltung und Modulintegration weiterhin ohne Einschränkungen genutzt werden können.
|
||||
|
||||
#### 3.1.2 Technische Umsetzung
|
||||
#### Technische Umsetzung
|
||||
|
||||
\
|
||||
|
||||
Als technische Grundlage diente die Theme-Architektur von Oqtane. Das Layout wurde in einer zentralen Razor-Datei (`Theme.razor`) definiert, welche von der Basisklasse `ThemeBase` erbt. Durch diese Vererbung stehen im Theme automatisch zentrale Funktionen des Frameworks zur Verfügung, darunter der Seitenzustand (`PageState`), Navigationsdaten, Systemeinstellungen sowie Informationen über den aktuell angemeldeten Benutzer. Dies ermöglicht eine tiefe Integration des Themes in das CMS, ohne dass zusätzliche Schnittstellen oder externe Datenzugriffe notwendig sind.
|
||||
|
||||
##### 3.1.2.1 Navigationsleiste
|
||||
##### Navigationsleiste
|
||||
|
||||
\
|
||||
|
||||
Ein zentrales Element des Themes ist die fixierte Navigationsleiste am oberen Rand der Seite. Sie ist in drei klar voneinander getrennte Bereiche gegliedert: Auf der linken Seite befindet sich das Logo der HTL Ungargasse, das als visuelles Erkennungsmerkmal der Schule dient und beim Klick zur Startseite führt. In der Mitte werden die Navigationspunkte der Plattform angezeigt, die dynamisch aus der Seitenstruktur des CMS generiert werden. Auf der rechten Seite befinden sich die Benutzerfunktionen, also Login, Registrierung und bei angemeldeten Benutzern ein Link zum eigenen Profil.
|
||||
|
||||
@@ -115,10 +119,34 @@ foreach (var item in PageState.Pages
|
||||
|
||||
Durch diesen Ansatz werden ausschließlich die für Benutzer relevanten Inhaltsseiten in der Navigation angezeigt. Gleichzeitig bleibt die Navigation vollständig dynamisch: Werden im CMS neue Seiten angelegt und als Navigationsseiten markiert, erscheinen diese automatisch im Menü, ohne dass eine Anpassung am Theme-Code notwendig ist.
|
||||
|
||||
![Abbildung 4.2: Filterlogik der Oqtane-Navigation] (./images/06-Adam/navigationsfilter_v2.svg)
|
||||
*Abbildung 4.2: Filterlogik zur Bereinigung der Oqtane-Navigation (Theme.razor)* Dies reduziert den Wartungsaufwand erheblich und stellt sicher, dass die Navigation stets dem aktuellen Stand der Plattform entspricht.
|
||||
<!--  -->
|
||||
|
||||
##### 3.1.2.2 Responsive Design und Burger-Menü
|
||||
``` {.mermaid width=75%}
|
||||
graph TD
|
||||
%%| filename: navigationsfilter_v2
|
||||
%%| fig-cap: Filterlogik der Oqtane-Navigation (Theme.razor)
|
||||
|
||||
Start[PageState.Pages<br/>Alle CMS-Seiten ~12 Seiten] --> Filter1[Filter 1: ParentId == null<br/>Nur Root-Seiten]
|
||||
Filter1 -- Unterseiten --> Rejected1[Aussortiert]
|
||||
Filter1 --> Filter2[Filter 2: hiddenNames<br/>Systemseiten ausblenden]
|
||||
Filter2 -- "Login, Register, Admin, Privacy, ..." --> Rejected2[Aussortiert]
|
||||
Filter2 --> Result[Sichtbare Navigation<br/>~3 Inhaltsseiten im Menü]
|
||||
Result -.-> Note[Neue Seiten im CMS erscheinen automatisch im Menü – kein Code nötig]
|
||||
|
||||
style Start fill:#F5F5F3,stroke:#B4B2A9,color:#000000
|
||||
style Filter1 fill:#E8E6FF,stroke:#3C3489,color:#000000
|
||||
style Filter2 fill:#E8E6FF,stroke:#3C3489,color:#000000
|
||||
style Rejected1 fill:#FFE8E8,stroke:#791F1F,color:#000000
|
||||
style Rejected2 fill:#FFE8E8,stroke:#791F1F,color:#000000
|
||||
style Result fill:#E6FFF9,stroke:#085041,color:#000000
|
||||
style Note fill:none,stroke:#B4B2A9,stroke-dasharray: 5 5,color:#000000
|
||||
```
|
||||
|
||||
Dies reduziert den Wartungsaufwand erheblich und stellt sicher, dass die Navigation stets dem aktuellen Stand der Plattform entspricht.
|
||||
|
||||
##### Responsive Design und Burger-Menü
|
||||
|
||||
\
|
||||
|
||||
Da die Plattform auch auf mobilen Endgeräten genutzt werden soll, war die Umsetzung eines responsiven Layouts eine wichtige Anforderung. Auf Desktop-Geräten werden alle Navigationspunkte direkt in der Navigationsleiste angezeigt. Auf kleineren Bildschirmen wie Smartphones oder Tablets würde dies jedoch zu Platzproblemen führen, da die Anzahl der Navigationspunkte die verfügbare Breite überschreiten kann.
|
||||
|
||||
@@ -126,52 +154,65 @@ Aus diesem Grund wurde für mobile Endgeräte ein sogenanntes Burger-Menü imple
|
||||
|
||||
Die technische Umsetzung des Burger-Menüs basiert auf einer CSS-Checkbox-Lösung. Das Öffnen und Schließen der Sidebar wird über den Zustand einer versteckten Checkbox gesteuert, der mittels CSS-Selektoren ausgewertet wird. Dieser Ansatz ermöglicht eine funktionsfähige mobile Navigation ohne den Einsatz zusätzlicher JavaScript-Frameworks oder komplexer Logik. Die gesamte Darstellungslogik – also welche Elemente auf welcher Bildschirmgröße sichtbar sind – wird über CSS Media Queries gesteuert, die zwischen der Desktop- und der mobilen Ansicht unterscheiden.
|
||||
|
||||
##### 3.1.2.3 Pane-Struktur
|
||||
##### Pane-Struktur
|
||||
|
||||
\
|
||||
|
||||
Für den Inhaltsbereich der Plattform wurden mehrere sogenannte Panes definiert. Panes sind in Oqtane Platzhalter-Bereiche innerhalb eines Themes, in die später Module oder Inhalte eingefügt werden können. Durch die Definition mehrerer Panes mit unterschiedlichen Breiten und Positionen können Seiten sehr flexibel und ohne Änderungen am Theme-Code strukturiert werden.
|
||||
|
||||
Im entwickelten Theme stehen unter anderem folgende Panes zur Verfügung: ein vollbreiter Bereich oben (`Top 100%`), ein linker Bereich (`Left 50%`), eine rechte Seitenleiste (`Right Sidebar 33%`) sowie ein vollbreiter Bereich am unteren Rand (`Bottom 100%`). Diese Struktur ermöglicht es, Seiten sowohl ein- als auch mehrspaltig aufzubauen, je nach den Anforderungen des jeweiligen Inhalts.
|
||||
|
||||
##### 3.1.2.4 Weitere Integrationen
|
||||
##### Weitere Integrationen
|
||||
|
||||
\
|
||||
|
||||
Neben Navigation und Layout wurden weitere Funktionen in das Theme integriert. Die Cookie-Consent-Komponente von Oqtane wurde eingebunden, sodass beim ersten Besuch der Plattform ein Hinweis zur Verwendung von Cookies angezeigt wird. Diese Funktion ist über die Site-Einstellungen von Oqtane steuerbar, das Theme rendert lediglich die entsprechende Komponente.
|
||||
|
||||
Darüber hinaus wurde das ControlPanel von Oqtane integriert, das Administratorinnen und Administratoren direkten Zugriff auf Verwaltungsfunktionen bietet. Login- und Registrierungsoptionen werden über den `SettingService` aus den Site-Einstellungen geladen, sodass diese Funktionen ohne Anpassungen am Code aktiviert oder deaktiviert werden können.
|
||||
|
||||
#### 3.1.3 Herausforderungen
|
||||
#### Herausforderungen
|
||||
|
||||
\
|
||||
|
||||
Die eigene Implementierung der Navigation über `PageState.Pages` und eine LINQ-basierte Filterlogik erwies sich als die richtige Entscheidung. Sie löste nicht nur das Problem der fehlenden Anpassbarkeit der Standardkomponente, sondern brachte gleichzeitig einen wesentlichen Mehrwert: Die Navigation ist vollständig wartungsfrei. Werden im CMS neue Seiten angelegt, erscheinen diese automatisch im Menü – ohne dass eine einzige Zeile Code angepasst werden muss. Zudem ermöglichte dieser Ansatz die vollständige Kontrolle über das Erscheinungsbild des Burger-Menüs, was mit der Standardkomponente nicht möglich gewesen wäre.
|
||||
|
||||
---
|
||||
### Anmeldetool
|
||||
|
||||
#### Ziel des Moduls
|
||||
|
||||
### 3.2 Anmeldetool
|
||||
|
||||
#### 3.2.1 Ziel des Moduls
|
||||
\
|
||||
|
||||
Das Anmeldetool wurde entwickelt, um Mitgliedern des Absolventenvereins eine einfache und strukturierte Möglichkeit zu bieten, sich zu Veranstaltungen und Treffen an- oder abzumelden. Ziel des Moduls ist es, den organisatorischen Aufwand bei der Planung und Verwaltung von Treffen deutlich zu reduzieren und gleichzeitig eine benutzerfreundliche Oberfläche für alle Beteiligten bereitzustellen.
|
||||
|
||||
Das Modul wurde als zusätzliche Funktionserweiterung in das bestehende Content-Management-System integriert. Es ermöglicht sowohl die Verwaltung der Veranstaltungen auf Seiten der Organisatoren als auch eine intuitive Interaktion für die Teilnehmerinnen und Teilnehmer. Durch den Einsatz moderner Webtechnologien konnte dabei eine reaktionsschnelle und geräteübergreifend nutzbare Lösung geschaffen werden.
|
||||
|
||||
#### 3.2.2 Frontend (Eingabemaske)
|
||||
#### Frontend (Eingabemaske)
|
||||
|
||||
\
|
||||
|
||||
Die Benutzeroberfläche des Anmeldetools wurde mithilfe von Blazor realisiert, einem Framework der ASP.NET-Technologieplattform, das die Entwicklung interaktiver Weboberflächen in C# ermöglicht. Die Eingabemaske wurde als eigenständige Blazor-Komponente implementiert, die flexibel in verschiedene Seiten der Anwendung eingebettet werden kann.
|
||||
|
||||
Beim Aufruf der Seite wird dem Benutzer zunächst eine kurze Beschreibung der jeweiligen Veranstaltung angezeigt. Im Anschluss stehen zwei klar gekennzeichnete Schaltflächen zur Verfügung: Zusagen zur Bestätigung der Teilnahme sowie Absagen zur Ablehnung. Die Schaltflächen wurden farblich differenziert gestaltet – eine grüne Hervorhebung signalisiert die Zusage, eine rote Darstellung steht für die Absage. Diese Gestaltung orientiert sich an etablierten Designkonventionen moderner Webanwendungen und verbessert die intuitive Bedienbarkeit erheblich. Darüber hinaus wurde besonderer Wert auf eine responsive Darstellung gelegt, damit das Tool sowohl auf Desktop-Geräten als auch auf Smartphones und Tablets problemlos genutzt werden kann.
|
||||
|
||||
#### 3.2.3 API-Schnittstelle
|
||||
#### API-Schnittstelle
|
||||
|
||||
\
|
||||
|
||||
Die Anbindung des Anmeldetools an das bestehende CMS erfolgt über klar definierte Schnittstellen innerhalb der ASP.NET-Architektur. Die Komponente kommuniziert mit dem Backend, um Veranstaltungsdaten abzurufen sowie Anmelde- und Absagestatus der Teilnehmenden zu übermitteln und zu persistieren.
|
||||
|
||||
Die Datenübertragung erfolgt nach dem Prinzip der sauberen Komponentenarchitektur: Die Blazor-Komponente ist als eigenständige Einheit konzipiert, die über Parameter und Rückruffunktionen mit übergeordneten Seitenkomponenten kommuniziert. Diese Struktur gewährleistet eine klare Trennung zwischen Darstellungslogik und Datenzugriff und erleichtert zukünftige Erweiterungen der Schnittstelle erheblich.
|
||||
|
||||
#### 3.2.4 Datenauswertung
|
||||
#### Datenauswertung
|
||||
|
||||
\
|
||||
|
||||
Die im Anmeldetool erfassten Daten bilden die Grundlage für die Verwaltung und Auswertung von Veranstaltungsteilnahmen. Organisatoren können auf Basis der gespeicherten An- und Abmeldungen die Teilnehmerzahlen einsehen und die Planung entsprechend anpassen.
|
||||
|
||||
Die Architektur des Moduls ist bereits auf zukünftige Erweiterungen ausgelegt. Geplante Erweiterungen umfassen eine übersichtliche Teilnehmerliste mit Namen und Anmeldestatus, die Möglichkeit, eine maximale Teilnehmeranzahl je Veranstaltung festzulegen sowie eine direkte Speicherung und Auswertung der Anmeldedaten in einer Datenbank. Durch diese Erweiterungen soll das Anmeldetool künftig nicht nur als Interaktionselement für Teilnehmer, sondern auch als vollwertiges Verwaltungswerkzeug für Veranstaltungsorganisatoren dienen.
|
||||
|
||||
#### 3.2.5 UX-Überlegungen (User Experience)
|
||||
#### UX-Überlegungen (User Experience)
|
||||
|
||||
\
|
||||
|
||||
Ein zentraler Aspekt bei der Entwicklung des Anmeldetools war die Benutzerfreundlichkeit der Oberfläche. UX (User Experience) bezeichnet dabei die Gesamtheit aller Erfahrungen, die ein Benutzer bei der Interaktion mit einer Anwendung macht – von der visuellen Gestaltung über die Bedienbarkeit bis hin zur allgemeinen Zufriedenheit mit dem System. Die Module wurden so gestaltet, dass Benutzerinnen und Benutzer die Funktionen ohne zusätzliche Schulung verwenden können. Eine klare Struktur, eine intuitive Bedienung sowie ein konsistentes Erscheinungsbild innerhalb des bestehenden Systems standen dabei im Vordergrund.
|
||||
|
||||
@@ -179,15 +220,19 @@ Während der Testphase wurden mehrere visuelle Darstellungsprobleme identifizier
|
||||
|
||||
Diese Maßnahmen stellen einen ersten Schritt in der kontinuierlichen Verbesserung der mobilen Benutzeroberfläche dar. Weitere Feinabstimmungen sind geplant, um das Anmeldetool langfristig als stabile, benutzerfreundliche und geräteübergreifend konsistente Lösung zu etablieren.
|
||||
|
||||
### 3.3 Hall of Fame
|
||||
### Hall of Fame
|
||||
|
||||
Das Hall-of-Fame-Modul ist ein zentrales Modul der AlumniHub-Plattform. Es dient dazu, ehemalige Absolventinnen und Absolventen der HTL Ungargasse sichtbar zu machen und ihre beruflichen Werdegänge zu präsentieren. Das Modul wurde als eigenständiges, wiederverwendbares Oqtane-Modul entwickelt und ermöglicht es registrierten Benutzerinnen und Benutzern, sich selbst mit einem persönlichen Profil einzutragen.
|
||||
|
||||
#### 3.3.1 Benutzeroberfläche
|
||||
#### Benutzeroberfläche
|
||||
|
||||
\
|
||||
|
||||
Die Benutzeroberfläche des Moduls besteht aus mehreren Komponenten, die zusammen eine vollständige und benutzerfreundliche Verwaltung der Hall-of-Fame-Einträge ermöglichen.
|
||||
|
||||
##### 3.3.1.1 Übersichtsseite (Index.razor)
|
||||
##### Übersichtsseite (Index.razor)
|
||||
|
||||
\
|
||||
|
||||
Die Hauptseite der Hall of Fame ist die erste Seite, die Besucherinnen und Besucher zu sehen bekommen. Sie zeigt alle veröffentlichten Einträge in einem responsiven Kartenlayout. Auf Desktop-Geräten werden die Karten in drei Spalten nebeneinander dargestellt, auf kleineren Bildschirmen passt sich das Layout automatisch an und zeigt die Karten einspaltig untereinander an.
|
||||
|
||||
@@ -197,7 +242,9 @@ Jede Karte enthält das Foto der jeweiligen Person als großes Vorschaubild im o
|
||||
|
||||
Für angemeldete Benutzerinnen und Benutzer wird im oberen rechten Bereich der Seite ein zusätzlicher Button angezeigt. Hat die Person noch keinen eigenen Eintrag erstellt, erscheint ein „Eintragen"-Button. Existiert bereits ein Eintrag, ändert sich der Button automatisch zu „Mein Eintrag", über den der bestehende Eintrag bearbeitet werden kann. Administratorinnen und Administratoren sehen zusätzlich Warnhinweise bei gemeldeten Einträgen sowie einen Lösch-Button bei jedem Eintrag.
|
||||
|
||||
##### 3.3.1.2 Detailseite (Details.razor)
|
||||
##### Detailseite (Details.razor)
|
||||
|
||||
\
|
||||
|
||||
Die Detailseite zeigt einen einzelnen Hall-of-Fame-Eintrag in seiner vollständigen Form. Das Layout ist zweispaltig aufgebaut: Auf der linken Seite befindet sich das Foto der Person, eingebettet in einen unscharfen Bildhintergrund, der dasselbe Foto in einer größeren, weichgezeichneten Version als Hintergrund verwendet. Dieser Effekt verleiht der Seite eine moderne und ansprechende Optik. Das eigentliche Foto ist dabei als klar umrandetes Porträtbild in der Mitte des linken Bereichs positioniert.
|
||||
|
||||
@@ -205,7 +252,9 @@ Auf der rechten Seite werden zunächst eine Breadcrumb-Navigation („Hall of Fa
|
||||
|
||||
Am unteren Rand der Seite befinden sich je nach Konfiguration des Eintrags bis zu vier Buttons. Der „PDF Vorschau"-Button öffnet einen modalen Dialog mit einer vollständigen Vorschau des generierten PDFs sowie einem „Herunterladen"-Button. Der „Zurück"-Button führt zurück zur Übersichtsseite. Falls die Person einen optionalen Link hinterlegt hat, wird zusätzlich ein „Webseite besuchen"-Button angezeigt, der die Besucherin oder den Besucher direkt zur externen Webseite der Person führt. Für eingeloggte Benutzer gibt es außerdem einen „Melden"-Button, über den ein Eintrag gemeldet werden kann.
|
||||
|
||||
##### 3.3.1.3 Edit-Seite (Edit.razor)
|
||||
##### Edit-Seite (Edit.razor)
|
||||
|
||||
\
|
||||
|
||||
Die Edit-Komponente dient sowohl zum Erstellen eines neuen Eintrags als auch zum Bearbeiten eines bestehenden. Das Formular ist klar strukturiert und enthält alle notwendigen Felder für einen vollständigen Hall-of-Fame-Eintrag.
|
||||
|
||||
@@ -217,19 +266,67 @@ Am unteren Rand des Formulars befinden sich zwei Speicheroptionen: „Als Entwur
|
||||
|
||||
Der folgende Lebenszyklus zeigt die möglichen Zustände eines Eintrags und die Übergänge zwischen ihnen:
|
||||
|
||||
![Abbildung 4.1: Lebenszyklus eines Hall-of-Fame-Eintrags] (./images/06-Adam/hall_of_fame_lebenszyklus_v4.svg)
|
||||
*Abbildung 4.1: Lebenszyklus eines Hall-of-Fame-Eintrags*
|
||||
<!--  -->
|
||||
|
||||
##### 3.3.1.4 Meldefunktion
|
||||
``` {.mermaid width=75%}
|
||||
graph TD
|
||||
%%| filename: hall_of_fame_lebenszyklus_v4
|
||||
%%| fig-cap: Lebenszyklus eines Hall-of-Fame-Eintrags
|
||||
|
||||
Start([Benutzer eingeloggt]) --> Create[Eintrag erstellen<br/>Duplikat- & Eigentümerprüfung]
|
||||
Create -- Fehler --> Rejected[Abgelehnt]
|
||||
Create --> Draft[Draft<br/>Nur für Eigentümer sichtbar]
|
||||
Draft -- Veröffentlichen --> Published[Published<br/>Öffentlich sichtbar]
|
||||
Published -- Meldung --> Reported[Gemeldet<br/>IsReported = true]
|
||||
Reported --> Admin[Admin-Entscheidung]
|
||||
Admin -- OK --> Approved[Freigegeben]
|
||||
Admin -- Verstoß --> Deleted[Gelöscht<br/>→ neuer Eintrag möglich]
|
||||
|
||||
%% Styling to match original SVG
|
||||
style Start fill:#F5F5F3,stroke:#B4B2A9,color:#000000
|
||||
style Create fill:#E8E6FF,stroke:#3C3489,color:#000000
|
||||
style Rejected fill:#FFE8E8,stroke:#791F1F,color:#000000
|
||||
style Draft fill:#E6FFF9,stroke:#085041,color:#000000
|
||||
style Published fill:#E6FFF9,stroke:#085041,color:#000000
|
||||
style Reported fill:#FFF2E0,stroke:#633806,color:#000000
|
||||
style Admin fill:#F5F5F3,stroke:#B4B2A9,color:#000000
|
||||
style Approved fill:#F0FFE6,stroke:#27500A,color:#000000
|
||||
style Deleted fill:#FFE8E8,stroke:#791F1F,color:#000000
|
||||
```
|
||||
|
||||
##### Meldefunktion
|
||||
|
||||
\
|
||||
|
||||
Die Meldefunktion ermöglicht es angemeldeten Benutzerinnen und Benutzern, einen Hall-of-Fame-Eintrag zu melden, wenn dieser unangemessene oder falsche Inhalte enthält. Durch Klicken auf den „Melden"-Button auf der Detailseite öffnet sich ein kleines Popup-Fenster, in das der Meldegrund eingetragen werden kann. Nach dem Absenden wird die Meldung in der Datenbank gespeichert und im Admin-Modul angezeigt. Administratorinnen und Administratoren können dort alle eingegangenen Meldungen einsehen und bei Bedarf den betreffenden Eintrag löschen oder freigeben.
|
||||
|
||||
Die Meldefunktion ist dabei nicht direkt im Hall-of-Fame-Modul implementiert, sondern wird über eine zentrale Schnittstelle aus einem gemeinsamen Interfaces-Paket eingebunden. Dieses Konzept ermöglicht es, dieselbe Melde-Oberfläche in beliebig vielen weiteren Modulen wiederzuverwenden, ohne die Logik mehrfach implementieren zu müssen.
|
||||
|
||||
![Abbildung 6.1: Ablauf des globalen Reporting-Systems] (./images/06-Adam/reporting_sequence_diagram.svg)
|
||||
*Abbildung 6.1: Ablauf des globalen Reporting-Systems (Sequenzdiagramm)*
|
||||
<!---->
|
||||
```mermaid
|
||||
%%{init: {'theme': 'neutral'}}%%
|
||||
sequenceDiagram
|
||||
%%| filename: reporting_sequence_diagram
|
||||
%%| fig-cap: Ablauf des globalen Reporting-Systems
|
||||
participant User
|
||||
participant Module
|
||||
participant ReportingComponent
|
||||
participant ReportingHandler
|
||||
|
||||
##### 3.3.1.5 PDF-Export
|
||||
User-->>+Module: View entity
|
||||
Module-->>+ReportingComponent: Report current entity
|
||||
ReportingComponent-->>User: Ask for reason
|
||||
User-->>ReportingComponent: Enters reason
|
||||
ReportingComponent-->>+ReportingHandler: New report (entity + reason)
|
||||
ReportingHandler-->>-ReportingComponent: Done
|
||||
ReportingComponent-->>-Module: Report saved
|
||||
Module-->>-User: Report saved
|
||||
```
|
||||
|
||||
|
||||
##### PDF-Export
|
||||
|
||||
\
|
||||
|
||||
Der PDF-Export ist eine besondere Funktion des Hall-of-Fame-Moduls. Er ermöglicht es Benutzerinnen und Benutzern, ihren Eintrag als visuell ansprechendes PDF-Dokument herunterzuladen. Die PDF-Generierung wird über die Open-Source-Bibliothek QuestPDF in der Community-Edition realisiert.
|
||||
|
||||
@@ -237,7 +334,9 @@ Das generierte PDF folgt einem Glasmorphismus-Design und ist im Format DIN A4 ge
|
||||
|
||||
Die PDF-Vorschau kann direkt auf der Detailseite über den „PDF Vorschau"-Button geöffnet werden. Es öffnet sich ein modaler Dialog, der das generierte PDF in einer Vorschau anzeigt. Über einen „Herunterladen"-Button kann das PDF direkt auf das Gerät gespeichert werden.
|
||||
|
||||
#### 3.3.2 Datenmodell
|
||||
#### Datenmodell
|
||||
|
||||
\
|
||||
|
||||
Das Modul verwendet zwei Entitäten, die in der Datenbank als Tabellen abgebildet werden.
|
||||
|
||||
@@ -246,7 +345,7 @@ Das Modul verwendet zwei Entitäten, die in der Datenbank als Tabellen abgebilde
|
||||
Die zentrale Entität repräsentiert einen einzelnen Absolventeneintrag und wird in der Datenbanktabelle `SZUAbsolventenvereinHallOfFame` gespeichert.
|
||||
|
||||
| Spalte | Datentyp | Beschreibung |
|
||||
|------------|----------|--------------|
|
||||
| :----------------- | :----------------- | :----------------------------------------------------------- |
|
||||
| `HallOfFameId` | `int` (PK, Auto-Inkrement) | Primärschlüssel |
|
||||
| `ModuleId` | `int` (FK → `Module`) | Fremdschlüssel zur Oqtane-Modulinstanz |
|
||||
| `Name` | `string` | Name der Person |
|
||||
@@ -263,6 +362,8 @@ Die zentrale Entität repräsentiert einen einzelnen Absolventeneintrag und wird
|
||||
| `ModifiedBy` | `string` | Zuletzt geändert von (Audit) |
|
||||
| `ModifiedOn` | `DateTime` | Zeitpunkt der letzten Änderung (Audit) |
|
||||
|
||||
Table: Entität HallOfFame
|
||||
|
||||
Die Entität implementiert das Oqtane-Interface `IAuditable`, wodurch die Audit-Felder automatisch vom Framework befüllt werden. Der Fremdschlüssel `ModuleId` verknüpft jeden Eintrag mit einer bestimmten Modulinstanz und ermöglicht so den Multi-Tenant-Betrieb.
|
||||
|
||||
**Entität HallOfFameReport**
|
||||
@@ -270,7 +371,7 @@ Die Entität implementiert das Oqtane-Interface `IAuditable`, wodurch die Audit-
|
||||
Die zweite Entität bildet einzelne Meldungen zu einem Eintrag ab und wird in der Tabelle `SZUAbsolventenvereinHallOfFameReport` gespeichert.
|
||||
|
||||
| Spalte | Datentyp | Beschreibung |
|
||||
|----------------------|----------|--------------|
|
||||
| :---------------------- | :----------------- | :----------------------------------------------------------- |
|
||||
| `HallOfFameReportId` | `int` (PK, Auto-Inkrement) | Primärschlüssel |
|
||||
| `HallOfFameId` | `int` (FK → `SZUAbsolventenvereinHallOfFame`) | Zugehöriger Eintrag |
|
||||
| `Reason` | `string` | Meldegrund |
|
||||
@@ -279,21 +380,29 @@ Die zweite Entität bildet einzelne Meldungen zu einem Eintrag ab und wird in de
|
||||
| `ModifiedBy` | `string` | Zuletzt geändert von (Audit) |
|
||||
| `ModifiedOn` | `DateTime` | Zeitpunkt der letzten Änderung (Audit) |
|
||||
|
||||
Table: Entität HallOfFameReport
|
||||
|
||||
Der Fremdschlüssel zu `SZUAbsolventenvereinHallOfFame` ist mit kaskadierendem Löschen konfiguriert, sodass beim Löschen eines Eintrags automatisch alle zugehörigen Meldungen entfernt werden. Zwischen den beiden Entitäten besteht eine 1:n-Beziehung: Ein Eintrag kann beliebig viele Meldungen besitzen.
|
||||
|
||||
#### 3.3.3 Datenbankmigrationen
|
||||
#### Datenbankmigrationen
|
||||
|
||||
Die Datenbankstruktur wird über Entity Framework Core Migrationen versioniert verwaltet.
|
||||
\
|
||||
|
||||
Die Datenbankstruktur wird über Entity Framework Core Migrationen versioniert verwaltet [@ef_core_migrations].
|
||||
|
||||
| Migration | Versionsnummer | Inhalt |
|
||||
|--------------------|----------------|--------|
|
||||
| ------- | ------ | ------------ |
|
||||
| `InitializeModule` | `01.00.00.00` | Erstellt die Haupttabelle mit allen Grundspalten sowie den Audit-Spalten |
|
||||
| `AddReportingColumns` | `01.00.00.02` | Erweitert die Haupttabelle um die Spalten `IsReported` und `ReportReason` |
|
||||
|
||||
> **Hinweis:** Version `01.00.00.01` wurde im Entwicklungsprozess übersprungen, da eine fehlerhafte Migration erstellt und anschließend wieder gelöscht werden musste.
|
||||
| `AddReportTable` | `01.00.00.03` | Erstellt die eigenständige Report-Tabelle mit Fremdschlüssel zur Haupttabelle |
|
||||
|
||||
#### 3.3.4 Implementierungsdetails und Problemlösungen
|
||||
Table: Datenbankmigrationen im Hall-of-Fame-Modul
|
||||
|
||||
> **Hinweis:** Version `01.00.00.01` wurde im Entwicklungsprozess übersprungen, da eine fehlerhafte Migration erstellt und anschließend wieder gelöscht werden musste.
|
||||
|
||||
#### Implementierungsdetails und Problemlösungen
|
||||
|
||||
\
|
||||
|
||||
Während der Entwicklung traten mehrere technische Herausforderungen auf, die im Folgenden zusammen mit ihren Lösungen beschrieben werden.
|
||||
|
||||
@@ -313,13 +422,13 @@ Karten hatten ursprünglich unterschiedliche Höhen durch variierende Beschreibu
|
||||
|
||||
Die ursprünglich fest codierten Sortierrichtungen wurden durch einen Toggle-Button neben dem Sortier-Dropdown ersetzt, der mit einem dynamischen Pfeil-Icon zwischen aufsteigender und absteigender Sortierung umschaltet. Die Sortierlogik ist in einer berechneten Eigenschaft gekapselt, die Suche und Sortierung kombiniert.
|
||||
|
||||
---
|
||||
## Übergangslösung & Probleme
|
||||
|
||||
## 4. Übergangslösung & Probleme
|
||||
### Übergangslösung (Sommer 2025)
|
||||
|
||||
### 4.1 Übergangslösung (Sommer 2025)
|
||||
#### Gründe & Technische Umsetzung
|
||||
|
||||
#### 4.1.1 Gründe & Technische Umsetzung
|
||||
\
|
||||
|
||||
Da AlumniHub zum Zeitpunkt des ersten Absolvententreffens im Sommer 2025 noch nicht vollständig fertiggestellt war und das Hosting von Oqtane auf dem Hetzner-Server zu unerwarteten technischen Problemen geführt hatte, wurde im Team die Entscheidung getroffen, eine eigenständige Übergangslösung zu entwickeln. Diese sollte pünktlich zur Veranstaltung einsatzbereit sein und die wichtigsten Funktionen abdecken: die Möglichkeit für Absolventinnen und Absolventen, ihre Teilnahme am Treffen zu bestätigen oder abzusagen, sowie die Möglichkeit, direktes Feedback zum Diplomprojekt AlumniHub abzugeben.
|
||||
|
||||
@@ -331,7 +440,9 @@ Für die Verarbeitung von Zu- und Absagen zum Absolvententreffen wurden zusätzl
|
||||
|
||||
Das Backend der Lösung, das für die Verarbeitung der Formulardaten und den Versand von Bestätigungs-E-Mails zuständig war, wurde von einem Teammitglied entwickelt und war nicht Teil des eigenen Aufgabenbereichs. Es wurde mit Node.js und dem Framework Express umgesetzt und auf einem virtuellen Server bei Hetzner Cloud gehostet.
|
||||
|
||||
#### 4.1.2 Differenzen zur finalen Lösung
|
||||
#### Differenzen zur finalen Lösung
|
||||
|
||||
\
|
||||
|
||||
Im direkten Vergleich zur finalen AlumniHub-Plattform unterscheidet sich die Übergangslösung in mehreren wesentlichen Punkten. Während AlumniHub auf dem vollständigen CMS Oqtane basiert und eine umfangreiche Funktionspalette bietet – darunter Benutzerverwaltung, Hall of Fame, Anmeldetool, Datenauswertung und ein individuelles Theme – beschränkte sich die Übergangslösung bewusst auf das absolut Notwendige.
|
||||
|
||||
@@ -339,9 +450,11 @@ Es gab keine Benutzerkonten und keine Authentifizierung. Jede Person, die die Se
|
||||
|
||||
Diese bewusste Reduktion auf das Wesentliche war jedoch kein Nachteil, sondern eine pragmatische Entscheidung: Die Lösung musste schnell funktionieren und zuverlässig sein – und das war sie. Nach dem Absolvententreffen wurde die Seite nicht einfach abgeschaltet, sondern zu einer reinen Feedback-Seite für das Diplomprojekt umfunktioniert. Über diese Seite konnten Interessierte – darunter Lehrkräfte, Mitschülerinnen und Mitschüler sowie externe Besucher der Präsentation – weiterhin direktes Feedback zum Projekt abgeben. Die Seite blieb so lange in Betrieb, bis die vollständig entwickelte AlumniHub-Plattform diese Funktion nativ übernahm.
|
||||
|
||||
### 4.2 Probleme
|
||||
### Probleme
|
||||
|
||||
#### 4.2.1 Technische Probleme
|
||||
#### Technische Probleme
|
||||
|
||||
\
|
||||
|
||||
Eine der größten technischen Herausforderungen im gesamten Projektverlauf war der Zeitdruck, der insbesondere im Vorfeld des ersten Absolvententreffens spürbar war. Da AlumniHub zu diesem Zeitpunkt noch nicht einsatzbereit war, musste die Übergangslösung in sehr kurzer Zeit konzipiert, entwickelt und in Betrieb genommen werden. Dieser Zeitdruck führte dazu, dass keine ausreichende Zeit für gründliches Testen oder für die Umsetzung zusätzlicher Funktionen blieb.
|
||||
|
||||
@@ -349,9 +462,11 @@ Ein weiteres technisches Problem ergab sich durch den Wechsel von Windows auf ma
|
||||
|
||||
Ein weiteres technisches Problem betraf das Hosting von Oqtane auf dem Hetzner-Server. Die Einrichtung und der Betrieb von Oqtane auf dem Server bereiteten unerwartete Schwierigkeiten, die den regulären Entwicklungsfortschritt verlangsamten. Da dieser Bereich nicht zum eigenen Aufgabengebiet gehörte, konnten die genauen Ursachen nicht vollständig nachvollzogen werden. Die Probleme wirkten sich jedoch auf den gesamten Zeitplan des Projekts aus und waren mitverantwortlich dafür, dass AlumniHub zum Zeitpunkt des ersten Treffens noch nicht fertig war.
|
||||
|
||||
In den letzten Monaten des Projekts wurde daher ein Wechsel des Hosting-Anbieters vorgenommen. Statt Hetzner wird die Plattform nun bei LiveDesign gehostet, einem österreichischen Unternehmen, das sich auf Hosting, Webdesign und individuelle Webservices spezialisiert hat. LiveDesign betreibt seine Datacenter ausschließlich in Österreich und bietet eine zuverlässige Infrastruktur für CMS-Systeme wie Oqtane. Durch diesen Wechsel konnten die bestehenden Stabilitätsprobleme behoben und der Betrieb der Plattform deutlich verbessert werden.
|
||||
In den letzten Monaten des Projekts wurde daher ein Wechsel des Hosting-Anbieters vorgenommen. Statt Hetzner wird die Plattform nun bei LiveDesign gehostet, einem österreichischen Unternehmen, das sich auf Hosting, Webdesign und individuelle Webservices spezialisiert hat [@livedesign]. LiveDesign betreibt seine Datacenter ausschließlich in Österreich und bietet eine zuverlässige Infrastruktur für CMS-Systeme wie Oqtane. Durch diesen Wechsel konnten die bestehenden Stabilitätsprobleme behoben und der Betrieb der Plattform deutlich verbessert werden.
|
||||
|
||||
#### 4.2.2 Kontakt mit Oqtane- und Hetzner-Support
|
||||
#### Kontakt mit Oqtane- und Hetzner-Support
|
||||
|
||||
\
|
||||
|
||||
Im Verlauf des Projekts wurde sowohl der Support von Oqtane als auch der Support von Hetzner kontaktiert, um Hilfe bei den aufgetretenen technischen Problemen zu erhalten.
|
||||
|
||||
@@ -359,15 +474,17 @@ Der Kontakt mit dem Oqtane-Support erfolgte über GitHub Issues sowie per E-Mail
|
||||
|
||||
Auch der Hetzner-Support wurde bezüglich der Serverprobleme kontaktiert. Die Anfragen bezogen sich auf die Serverkonfiguration und mögliche Ursachen für die Instabilität beim Betrieb von Oqtane. Auch hier führten die Rückmeldungen nicht zu einer vollständigen Lösung des Problems. Die Erfahrung zeigte, dass bei der Nutzung spezialisierter Frameworks auf externen Hosting-Plattformen mit eingeschränktem Support gerechnet werden muss und eine intensive Eigenrecherche oft unumgänglich ist.
|
||||
|
||||
#### 4.2.3 Organisatorische Probleme
|
||||
#### Organisatorische Probleme
|
||||
|
||||
\
|
||||
|
||||
Neben den technischen Herausforderungen gab es auch auf organisatorischer Ebene ein zentrales Problem, das den Projektverlauf im Sommer 2025 erheblich beeinflusste. Während der Sommermonate war die aktive Mitarbeit innerhalb des Teams sehr ungleich verteilt. Ein Großteil der Teammitglieder war urlaubsbedingt nicht oder nur eingeschränkt erreichbar und beteiligte sich in dieser Zeit kaum am Projekt. Nur ein kleiner Teil des Teams arbeitete in dieser Phase aktiv weiter und trieb den Fortschritt voran.
|
||||
|
||||
Diese Situation führte zu einer deutlichen Ungleichverteilung der Arbeitsbelastung. Wenige Personen mussten in dieser Zeit deutlich mehr Verantwortung übernehmen als ursprünglich geplant, was zu Frustration und Verzögerungen führte. Im Nachhinein zeigt sich, dass klarere Absprachen und verbindlichere Vereinbarungen zu Beginn des Sommers dazu beigetragen hätten, diese Situation zu vermeiden oder zumindest abzumildern.
|
||||
|
||||
## 5. Learnings
|
||||
## Learnings
|
||||
|
||||
### 5.1 Technisch
|
||||
### Technisch
|
||||
|
||||
Das Projekt hat auf technischer Ebene wertvolle praktische Kenntnisse vermittelt, die über den schulischen Rahmen hinausgehen. Der konsequente Einsatz von Git zur Versionskontrolle war dabei eine der wichtigsten Erfahrungen. Durch die tägliche Arbeit mit Branches, Commits und Merges wurde ein tiefes Verständnis für kollaborative Softwareentwicklung aufgebaut. Es wurde deutlich, wie wichtig aussagekräftige Commit-Nachrichten, regelmäßige Commits und eine saubere Branch-Struktur für die Zusammenarbeit im Team sind.
|
||||
|
||||
@@ -375,41 +492,37 @@ Im Bereich Responsive Design wurden durch die praktische Umsetzung des Themes un
|
||||
|
||||
Auch der Umgang mit JavaScript zur Steuerung von UI-Elementen wurde durch die Arbeit am Projekt verbessert. Die Implementierung der Overlay-Steuerung in der Übergangslösung sowie die Menü-Logik im Theme haben gezeigt, wie JavaScript gezielt und effizient eingesetzt werden kann, um eine bessere Benutzererfahrung zu schaffen.
|
||||
|
||||
### 5.2 Methodisch
|
||||
### Methodisch
|
||||
|
||||
Auf methodischer Ebene hat das Projekt gezeigt, wie wichtig eine klare und verbindliche Aufgabenverteilung von Beginn an ist. In Phasen, in denen nicht klar war, wer welche Aufgaben übernimmt, entstanden Lücken und Verzögerungen. Eine strukturiertere Planung mit klar definierten Zuständigkeiten hätte in solchen Situationen geholfen, den Überblick zu behalten und die Arbeit effizienter aufzuteilen.
|
||||
|
||||
Darüber hinaus hat sich gezeigt, dass regelmäßige Team-Meetings ein wichtiges Werkzeug für den Projekterfolg sind. In Phasen, in denen der Austausch im Team spärlicher war, dauerte es länger, bis Probleme erkannt und gelöst wurden. Kurze, regelmäßige Abstimmungen hätten dazu beigetragen, den aktuellen Stand besser zu kommunizieren und gemeinsam schneller auf Hindernisse zu reagieren.
|
||||
|
||||
### 5.3 Persönlich
|
||||
### Persönlich
|
||||
|
||||
Auf persönlicher Ebene war die wichtigste Erkenntnis aus diesem Projekt die Bedeutung von Eigeninitiative. In einem größeren Teamprojekt kann man sich nicht immer darauf verlassen, dass andere Aufgaben erledigen oder Entscheidungen treffen. Gerade in den Phasen, in denen nicht alle Teammitglieder aktiv waren, hat sich gezeigt, dass proaktives Handeln entscheidend ist, um das Projekt voranzubringen. Diese Erfahrung hat das Bewusstsein dafür gestärkt, Verantwortung nicht nur für den eigenen Bereich, sondern auch für das Gesamtprojekt zu übernehmen und bei Bedarf auch Aufgaben außerhalb des ursprünglich geplanten Bereichs zu übernehmen.
|
||||
|
||||
---
|
||||
## Testen & Qualitätssicherung
|
||||
|
||||
## 6. Testen & Qualitätssicherung
|
||||
|
||||
### 6.1 Funktionstests der Module
|
||||
### Funktionstests der Module
|
||||
|
||||
Alle entwickelten Module – das Anmeldetool und das Hall-of-Fame-Modul – wurden manuell auf ihre korrekte Funktionsweise getestet. Dabei wurden sämtliche Benutzeraktionen systematisch durchgegangen, darunter das An- und Abmelden zu Veranstaltungen, das Erstellen, Bearbeiten und Veröffentlichen von Hall-of-Fame-Einträgen, das Hochladen von Bildern sowie die Melde- und Löschfunktionen. Fehler und unerwartetes Verhalten wurden dokumentiert und im Anschluss behoben.
|
||||
|
||||
Beim Anmeldetool wurde insbesondere geprüft, ob die Zusage- und Absage-Buttons korrekt reagieren und der Status unmittelbar in der Oberfläche angezeigt wird. Beim Hall-of-Fame-Modul lag ein besonderer Fokus auf dem Bild-Upload: Es wurde getestet, ob die Größenbeschränkung von 5 MB korrekt greift, ob die Vorschau sofort erscheint und ob ungültige Dateiformate abgelehnt werden. Auch die Duplikatprüfung – also die Sicherstellung, dass pro Person nur ein Eintrag erstellt werden kann – sowie die Eigentümerprüfung wurden gezielt getestet.
|
||||
|
||||
### 6.2 Theme-Tests
|
||||
### Theme-Tests
|
||||
|
||||
Das entwickelte Oqtane-Theme wurde auf verschiedenen Browsern und Geräten getestet, um eine konsistente Darstellung sicherzustellen. Getestet wurde unter anderem auf aktuellen Versionen von Chrome, Firefox und Safari sowie auf mobilen Geräten mit unterschiedlichen Bildschirmgrößen. Ein besonderer Fokus lag dabei auf der korrekten Darstellung des Burger-Menüs auf mobilen Endgeräten sowie auf der Funktionsfähigkeit der dynamischen Navigation.
|
||||
|
||||
### 6.3 Usability-Tests
|
||||
### Usability-Tests
|
||||
|
||||
Neben den technischen Tests wurde die Plattform auch von weiteren Personen – darunter Mitschülerinnen und Mitschüler sowie Lehrkräfte – auf ihre Benutzerfreundlichkeit geprüft. Das Feedback aus diesen Tests floss in die weitere Entwicklung ein und führte unter anderem zu Anpassungen in der Darstellung und Bedienung einzelner Elemente.
|
||||
|
||||
Ein häufiges Feedback war, dass die Unterscheidung zwischen Zusage und Absage auf den ersten Blick nicht immer sofort klar war. Daraufhin wurden die Schaltflächen farblich deutlicher gestaltet – Grün für die Zusage, Rot für die Absage – und die Beschriftungen präzisiert. Solche Rückmeldungen aus echten Nutzertests sind wertvoll, weil Entwicklerinnen und Entwickler ihre eigene Anwendung oft anders wahrnehmen als Personen, die das System zum ersten Mal sehen.
|
||||
|
||||
## Fazit und Ausblick
|
||||
|
||||
---
|
||||
## 7. Fazit und Ausblick
|
||||
|
||||
### 7.1 Zielerreichung
|
||||
### Zielerreichung
|
||||
|
||||
Rückblickend auf das Projekt AlumniHub lässt sich festhalten, dass die zentralen Ziele meines individuellen Aufgabenbereichs erfolgreich umgesetzt wurden.
|
||||
|
||||
@@ -421,34 +534,10 @@ Das **Theme** wurde von einem anderen Teammitglied entwickelt und ist ebenfalls
|
||||
|
||||
Insgesamt bin ich mit dem erreichten Stand zufrieden – insbesondere angesichts der Herausforderungen durch die Teamverkleinerung, den Plattformwechsel von Windows auf macOS und die technischen Probleme mit dem ursprünglichen Hosting.
|
||||
|
||||
### 7.2 Ausblick
|
||||
### Ausblick
|
||||
|
||||
Für die Weiterentwicklung der Plattform gibt es mehrere sinnvolle nächste Schritte. Im Bereich des Anmeldetools wäre die Implementierung einer vollständigen Teilnehmerliste mit direkter Datenbankanbindung der wichtigste nächste Schritt. Ergänzend dazu sollte die Möglichkeit geschaffen werden, maximale Teilnehmerzahlen pro Veranstaltung festzulegen, sodass Organisatoren die Kapazität von Treffen besser steuern können.
|
||||
|
||||
Langfristig könnte die Plattform um eine automatische E-Mail-Benachrichtigung erweitert werden, die Mitglieder an bevorstehende Veranstaltungen erinnert. Auch eine Exportfunktion für die Anmeldedaten – beispielsweise als CSV oder PDF – wäre für die Vereinsverwaltung hilfreich.
|
||||
|
||||
AlumniHub bietet als Plattform eine solide Grundlage, die in den kommenden Jahren kontinuierlich erweitert werden kann, um den Absolventenverein der HTL Ungargasse langfristig digital zu unterstützen.
|
||||
|
||||
---
|
||||
|
||||
## 8. Quellen
|
||||
|
||||
Microsoft: ASP.NET Core Documentation. https://learn.microsoft.com/en-us/aspnet/core/ [Zugriff: 17.03.2026]
|
||||
|
||||
Microsoft: Blazor Documentation. https://learn.microsoft.com/en-us/aspnet/core/blazor/ [Zugriff: 17.03.2026]
|
||||
|
||||
Microsoft: Entity Framework Core – Migrations. https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/ [Zugriff: 17.03.2026]
|
||||
|
||||
Oqtane Framework: https://www.oqtane.org/ [Zugriff: 17.03.2026]
|
||||
|
||||
Oqtane Developer Documentation: https://docs.oqtane.org/ [Zugriff: 17.03.2026]
|
||||
|
||||
QuestPDF Open Source Library: https://www.questpdf.com/ [Zugriff: 17.03.2026]
|
||||
|
||||
Bootstrap Framework: https://getbootstrap.com/ [Zugriff: 17.03.2026]
|
||||
|
||||
Gitea – Open Source Git Service: https://about.gitea.com/ [Zugriff: 17.03.2026]
|
||||
|
||||
LiveDesign – Hosting, Design & Branding: https://livedesign.at/ [Zugriff: 17.03.2026]
|
||||
|
||||
JetBrains Rider: https://www.jetbrains.com/rider/ [Zugriff: 17.03.2026]
|
||||
@@ -20,19 +20,27 @@ Für den Verein bedeutet das: rechtskonforme Datenverarbeitung, gesicherte Daten
|
||||
|
||||
#### Entwicklung eines CMS-Moduls
|
||||
|
||||
• **Premiumbereich:**
|
||||
\
|
||||
|
||||
- **Premiumbereich:**
|
||||
Ein Schwerpunkt der Arbeit ist die Entwicklung eines Oqtane-Moduls, das einen Premiumbereich bereitstellt. Dieser Bereich soll ausschließlich autorisierten Benutzerinnen und Benutzern zugänglich sein und spezielle Inhalte oder Funktionen anbieten wie zum Beispiel das hochladen und ansehen von Ingeneuranträgen als Vorlage oder das finden und Kontakt aufnehmen mit anderen Benutzern. Dabei werden grundlegende Konzepte wie Benutzerrollen, Zugriffsrechte und die Integration in das bestehende CMS eingebunden.
|
||||
|
||||
##### Erstellung einer Datenschutzerklärung
|
||||
|
||||
\
|
||||
|
||||
Eine weitere wichtige Aufgabe war die Erstellung einer gesetzeskonformen Datenschutzerklärung. Diese ist erforderlich, um die Nutzerinnen und Nutzer unserer Webanwendung transparent und verständlich darüber zu informieren, welche personenbezogenen Daten erhoben, verarbeitet und gespeichert werden, zu welchem Zweck dies geschieht und welche Rechte ihnen in Bezug auf ihre Daten zustehen.
|
||||
|
||||
#### LinkedIn-Anmeldung
|
||||
|
||||
\
|
||||
|
||||
Zur Verbesserung der Benutzerfreundlichkeit und zur vereinfachten Anmeldung wird eine Anmeldung über LinkedIn mithilfe des OAuth-2.0-Protokolls implementiert. Diese ermöglicht es Benutzerinnen und Benutzern, sich mit einem bestehenden LinkedIn-Konto zu registrieren oder anzumelden.
|
||||
|
||||
#### Datenbank-Backup und Restore
|
||||
|
||||
\
|
||||
|
||||
Abschließend wurde das Thema Datensicherung umfassend behandelt, da die Sicherstellung der Datenintegrität und Systemverfügbarkeit einen zentralen Bestandteil moderner Webanwendungen darstellt. In diesem Zusammenhang wurde ein Skript zur automatisierten Erstellung von Datenbank-Backups entwickelt, das in regelmäßigen Abständen Sicherungskopien der relevanten Daten erzeugt. Zusätzlich wurde ein weiteres Skript implementiert, das im Falle eines Datenverlusts oder Systemausfalls eine strukturierte und zuverlässige Wiederherstellung der gesicherten Daten ermöglicht.
|
||||
|
||||
Ziel dieser Maßnahmen ist es, das Risiko von Datenverlusten zu minimieren und einen stabilen sowie sicheren Betrieb der Webanwendung zu gewährleisten. Die Backup- und Restore-Prozesse sollen automatisiert ablaufen, um menschliche Fehler zu reduzieren und eine kontinuierliche, regelmäßige Datensicherung sicherzustellen. Dadurch wird eine hohe Ausfallsicherheit sowie die langfristige Verfügbarkeit der gespeicherten Informationen gewährleistet.
|
||||
@@ -41,8 +49,12 @@ Ziel dieser Maßnahmen ist es, das Risiko von Datenverlusten zu minimieren und e
|
||||
|
||||
#### Zielsetzung
|
||||
|
||||
\
|
||||
|
||||
##### Technische Zielsetzung
|
||||
|
||||
\
|
||||
|
||||
Die technische Zielsetzung dieses Diplomarbeitsprojekts bestand darin, eine stabile und sichere Webplattform für Alumni zu entwickeln. Als technische Grundlage wurde das Content-Management-System Oqtane verwendet, welches auf modernen Webtechnologien basiert und eine modulare Erweiterung von Funktionen ermöglicht. Die Implementierung erfolgte innerhalb der von Oqtane bereitgestellten Architektur, wodurch verschiedene Funktionen effizient integriert werden konnten.
|
||||
|
||||
Ein zentraler Bestandteil der technischen Umsetzung war die Integration einer externen Authentifizierung über LinkedIn mithilfe des Protokolls OAuth 2.0. Dadurch können sich Benutzer direkt mit ihrem LinkedIn-Konto auf der Plattform anmelden, ohne ein separates Benutzerkonto erstellen zu müssen. Dies vereinfacht den Registrierungsprozess und erhöht gleichzeitig die Sicherheit, da sensible Zugangsdaten ausschließlich beim externen Anbieter verbleiben.
|
||||
@@ -53,6 +65,8 @@ Ein weiterer wichtiger Aspekt der technischen Zielsetzung war die Einhaltung rec
|
||||
|
||||
##### Funktionale Zielsetzung
|
||||
|
||||
\
|
||||
|
||||
Die funktionale Zielsetzung des Projekts bestand darin, eine Onlineplattform zu entwickeln, die ehemaligen Schülerinnen und Schülern die Möglichkeit bietet, miteinander in Kontakt zu bleiben und sich über aktuelle Veranstaltungen zu informieren. Die Plattform dient somit als digitales Netzwerk für Alumni und soll den Austausch zwischen ehemaligen Mitgliedern der Bildungseinrichtung fördern.
|
||||
|
||||
Eine zentrale Funktion der Anwendung ist die Anmeldung über LinkedIn, wodurch Benutzer schnell und unkompliziert Zugriff auf die Plattform erhalten können. Nach der erfolgreichen Anmeldung wird automatisch ein Benutzerkonto erstellt oder ein bestehendes Konto zugeordnet.
|
||||
@@ -65,6 +79,8 @@ Durch diese Funktionen entsteht eine Plattform, die nicht nur als Informationsqu
|
||||
|
||||
##### Gestalterische Zielsetzung
|
||||
|
||||
\
|
||||
|
||||
Neben den technischen und funktionalen Anforderungen spielte auch die Gestaltung der Plattform eine wichtige Rolle. Ziel war es, eine übersichtliche und benutzerfreundliche Oberfläche zu entwickeln, die eine einfache Navigation und intuitive Bedienung ermöglicht.
|
||||
|
||||
Die Struktur der Webseite wurde so aufgebaut, dass wichtige Funktionen wie Login, Benutzerprofil oder Eventübersicht schnell erreichbar sind. Ein klares Layout und eine strukturierte Seitenaufteilung tragen dazu bei, dass sich Benutzer auf der Plattform leicht orientieren können.
|
||||
@@ -75,9 +91,50 @@ Insgesamt verfolgt die gestalterische Zielsetzung das Ziel, eine Plattform zu sc
|
||||
|
||||
## Anforderungen an das entwickelte Modul bzw. die Funktionalität
|
||||
|
||||
funktionale / nicht‑funktionale Anforderungen
|
||||
### Modulanforderungen / funktionale Anforderungen
|
||||
|
||||
Use Cases
|
||||
Die funktionalen Anforderungen beschreiben die spezifischen Dienste und Funktionen, die das System für die Benutzer bereitstellen muss. Im Rahmen der individuellen Aufgabenstellung wurden Anforderungen für vier Teilbereiche definiert:
|
||||
|
||||
#### Premium-Bereich
|
||||
|
||||
\
|
||||
|
||||
Das Ziel des Premium-Bereichs ist die Bereitstellung exklusiver Funktionen und Inhalte für berechtigte Absolventinnen und Absolventen, um einen Anreiz für aktives Engagement zu schaffen.
|
||||
|
||||
- **Antragsworkflow**: Benutzer müssen die Möglichkeit haben, einen Ingenieur-Antrag in Form eines PDF-Dokuments hochzuladen und mit einem Titel sowie einer Kurzbeschreibung zu versehen.
|
||||
- **Genehmigungsprüfung**: Eine Berechtigungsstruktur muss es ermöglichen, eingereichte Anträge zu sichten und entweder zu genehmigen oder abzulehnen. Bei Genehmigung wird der Premium-Status vergeben.
|
||||
- **Antrags-Bibliothek**: Premium-Mitglieder müssen auf eine Übersicht aller genehmigten Anträge zugreifen und die zugehörigen Dokumente einsehen können.
|
||||
- **Mitgliedersuche & Kontakt**: Premium-Mitglieder sollen gezielt nach anderen Benutzern suchen und diesen über eine interne Funktion Nachrichten senden können, ohne dass E-Mail-Adressen für Benutzer sichtbar werden.
|
||||
|
||||
#### Authentifizierung mittels LinkedIn (OAuth 2.0)
|
||||
|
||||
\
|
||||
|
||||
Diese Anforderung zielt darauf ab, den Registrierungs- und Anmeldeprozess für Benutzer signifikant zu vereinfachen und sicherer zu gestalten.
|
||||
|
||||
- **Externe Anmeldung**: Benutzer müssen sich über ihr bestehendes LinkedIn-Konto auf der Plattform registrieren und anmelden können.
|
||||
- **Sichere Token-Verarbeitung**: Die Anwendung muss das OAuth 2.0-Protokoll korrekt implementieren und den Autorisierungscode sicher gegen ein Zugriffstoken austauschen.
|
||||
- **Account-Zuordnung**: Bei der Anmeldung über LinkedIn muss im CMS automatisch ein neues Benutzerprofil erstellt und mit den abgerufenen Daten befüllt werden, sofern kein bestehender Account vorliegt.
|
||||
|
||||
#### Backup- und Restore-System
|
||||
|
||||
\
|
||||
|
||||
Das System dient der Sicherstellung der Datenverfügbarkeit und dem Schutz vor Datenverlust durch Hardwarefehler oder sonstige Ausfälle.
|
||||
|
||||
- **Automatisierte Sicherung**: Täglich muss automatisch ein Backup der gesamten PostgreSQL-Datenbank sowie aller wichtigen System- und Anwendungsdateien als komprimiertes Archiv erstellt werden.
|
||||
- **Chronologische Ablage und Speichermanagement**: Die Backup-Archive müssen chronologisch und versioniert abgelegt werden. Eine Automatisierung sorgt dafür, dass alte Backups routinemäßig bereinigt werden.
|
||||
- **Strukturierte Wiederherstellung**: Ein eigenes Restore-Skript muss existieren, um ein ausgewähltes Backup kontrolliert wiederherstellen zu können. Sicherheits- und Bestätigungsmechanismen müssen etabliert werden, um Überschreiben aktueller Daten versehentlich zu vermeiden.
|
||||
|
||||
#### Datenschutz und DSGVO-Konformität
|
||||
|
||||
\
|
||||
|
||||
Die Umsetzung rechtlicher Rahmenbedingungen ist notwendig, um die Privatsphäre der Benutzer zu schützen und einen rechtskonformen Betrieb der Webplattform zu gewährleisten.
|
||||
|
||||
- **Datenschutzerklärung**: Eine umfassende, gesetzeskonforme Datenschutzerklärung muss auf der Webseite integriert werden, die über Verwendungszweck, Speicherdauer und Betroffenenrechte aufklärt.
|
||||
- **Datenminimierung**: Die Plattform darf nur jene Daten erheben, die zur Bereitstellung der Dienste (Verwaltung von Mitgliedschaften, Eventorganisation, Kommunikation) erforderlich sind.
|
||||
- **Sichere Verarbeitung**: Personenbezogene Daten müssen verschlüsselt übertragen (HTTPS) und bei Suchvorgängen (z. B. in der Mitgliedersuche) muss auf die Zurückhaltung sensibler Daten geachtet werden.
|
||||
|
||||
## Technologien
|
||||
|
||||
@@ -95,9 +152,9 @@ Durch diese Architektur wird sichergestellt, dass die eigentliche Logik der Anwe
|
||||
|
||||
Ein weiterer Vorteil von ASP.NET besteht in der klar strukturierten Architektur moderner Webanwendungen. Typischerweise wird eine Anwendung in mehrere Schichten unterteilt, beispielsweise:
|
||||
|
||||
• Präsentationsschicht (Benutzeroberfläche)
|
||||
• Geschäftslogik
|
||||
• Datenzugriffsschicht
|
||||
- Präsentationsschicht (Benutzeroberfläche)
|
||||
- Geschäftslogik
|
||||
- Datenzugriffsschicht
|
||||
|
||||
Diese Struktur erleichtert die Wartung und Erweiterung der Anwendung erheblich, da Änderungen gezielt innerhalb einzelner Komponenten vorgenommen werden können.
|
||||
|
||||
@@ -109,16 +166,16 @@ Eine relationale Datenbank speichert Informationen in Tabellen, die aus Zeilen u
|
||||
|
||||
Durch diese Struktur kann beispielsweise gespeichert werden:
|
||||
|
||||
• welcher Benutzer existiert
|
||||
• welche Veranstaltungen geplant sind
|
||||
• welcher Benutzer sich für welches Event angemeldet hat
|
||||
- welcher Benutzer existiert
|
||||
- welche Veranstaltungen geplant sind
|
||||
- welcher Benutzer sich für welches Event angemeldet hat
|
||||
|
||||
PostgreSQL bietet darüber hinaus zahlreiche Funktionen, die für moderne Webanwendungen wichtig sind. Dazu gehören unter anderem:
|
||||
|
||||
• hohe Stabilität und Zuverlässigkeit
|
||||
• Unterstützung komplexer Datenabfragen mittels SQL
|
||||
• Transaktionssicherheit zur Vermeidung von Datenverlust
|
||||
• Erweiterbarkeit durch zusätzliche Module
|
||||
- hohe Stabilität und Zuverlässigkeit
|
||||
- Unterstützung komplexer Datenabfragen mittels SQL
|
||||
- Transaktionssicherheit zur Vermeidung von Datenverlust
|
||||
- Erweiterbarkeit durch zusätzliche Module
|
||||
|
||||
Ein weiterer wichtiger Vorteil besteht darin, dass PostgreSQL sehr gut mit modernen Webframeworks wie ASP.NET zusammenarbeitet. Dadurch kann die Anwendung effizient auf gespeicherte Daten zugreifen und diese verarbeiten.
|
||||
|
||||
@@ -134,49 +191,55 @@ Für die sichere Anmeldung über externe Identitätsanbieter wurde das Protokoll
|
||||
|
||||
#### Bedeutung der Datenschutz-Grundverordnung (DSGVO) [@dsgvo]
|
||||
|
||||
\
|
||||
|
||||
Die Datenschutz-Grundverordnung (DSGVO) ist eine rechtsverbindliche Verordnung der Europäischen Union, die seit dem 25. Mai 2018 unmittelbar in allen EU-Mitgliedstaaten gilt und den Schutz personenbezogener Daten regelt. Sie wurde erlassen, um die Rechte natürlicher Personen bei der Verarbeitung ihrer Daten zu stärken und ein einheitliches Datenschutzniveau innerhalb der EU zu gewährleisten.
|
||||
|
||||
Der Anwendungsbereich der DSGVO umfasst alle Verarbeitungen personenbezogener Daten, unabhängig davon, ob diese automatisiert oder in nicht-automatisierten Akten erfolgt. Personenbezogene Daten sind dabei definiert als alle Informationen, die sich auf eine identifizierte oder identifizierbare natürliche Person beziehen.
|
||||
|
||||
Die DSGVO verfolgt mehrere grundsätzliche Ziele:
|
||||
|
||||
• Schutz der Grundrechte natürlicher Personen bei der Verarbeitung ihrer personenbezogenen Daten sowie die Gewährleistung ihrer Grundfreiheiten.
|
||||
• Einheitlicher Datenschutz in der EU, sodass sowohl Unternehmen innerhalb als auch außerhalb der EU, die Daten von EU-Bürgern verarbeiten, denselben Regeln unterliegen.
|
||||
• Schaffung klarer Pflichten für Datenverantwortliche und -verarbeiter zur rechtskonformen Datenverarbeitung.
|
||||
- Schutz der Grundrechte natürlicher Personen bei der Verarbeitung ihrer personenbezogenen Daten sowie die Gewährleistung ihrer Grundfreiheiten.
|
||||
- Einheitlicher Datenschutz in der EU, sodass sowohl Unternehmen innerhalb als auch außerhalb der EU, die Daten von EU-Bürgern verarbeiten, denselben Regeln unterliegen.
|
||||
- Schaffung klarer Pflichten für Datenverantwortliche und -verarbeiter zur rechtskonformen Datenverarbeitung.
|
||||
|
||||
Die DSGVO enthält dabei zentral die Grundsätze der Datenverarbeitung (Art. 5 DSGVO), die sicherstellen, dass personenbezogene Daten nur rechtmäßig, zweckgebunden und in transparentem Umfang verarbeitet werden. Dazu gehören unter anderem:
|
||||
|
||||
• Rechtmäßigkeit, Fairness und Transparenz der Verarbeitung
|
||||
• Zweckbindung der Datenerhebung
|
||||
• Datenminimierung und Speicherbegrenzung
|
||||
• Integrität und Vertraulichkeit der Datenverarbeitung
|
||||
- Rechtmäßigkeit, Fairness und Transparenz der Verarbeitung
|
||||
- Zweckbindung der Datenerhebung
|
||||
- Datenminimierung und Speicherbegrenzung
|
||||
- Integrität und Vertraulichkeit der Datenverarbeitung
|
||||
|
||||
Die Einhaltung dieser Prinzipien ist für jede Organisation verpflichtend, die personenbezogene Daten verarbeitet – unabhängig von ihrer Größe oder Branche. Dies umfasst sowohl technische Aspekte der Datenverarbeitung als auch die Informationspflichten gegenüber Betroffenen, wie sie etwa in Datenschutzerklärungen umgesetzt werden müssen.
|
||||
|
||||
#### Umsetzung der Datenschutzanforderungen auf der Webseite [@ris]
|
||||
|
||||
\
|
||||
|
||||
Im Rahmen der Diplomarbeit wurde eine umfassende Analyse der Datenschutzanforderungen durchgeführt und entsprechende Maßnahmen zur Umsetzung auf der Webseite implementiert. Dabei wurden insbesondere die Vorgaben der DSGVO berücksichtigt, um sicherzustellen, dass die Webseite den geltenden Datenschutzbestimmungen entspricht.
|
||||
|
||||
Ein zentrales Element der Umsetzung war die Erstellung einer gesetzeskonformen Datenschutzerklärung. Diese informiert die Nutzerinnen und Nutzer über:
|
||||
|
||||
• die Art der verarbeiteten personenbezogenen Daten,
|
||||
• den Zweck der Datenverarbeitung,
|
||||
• die Rechtsgrundlagen der Verarbeitung,
|
||||
• die Speicherdauer der Daten,
|
||||
• die Weitergabe von Daten an Dritte
|
||||
• sowie über die Rechte der Betroffenen gemäß Art. 15–22 DSGVO.
|
||||
- die Art der verarbeiteten personenbezogenen Daten,
|
||||
- den Zweck der Datenverarbeitung,
|
||||
- die Rechtsgrundlagen der Verarbeitung,
|
||||
- die Speicherdauer der Daten,
|
||||
- die Weitergabe von Daten an Dritte
|
||||
- sowie über die Rechte der Betroffenen gemäß Art. 15–22 DSGVO.
|
||||
|
||||
Die Datenschutzerklärung wird auf der Webseite gut sichtbar eingebunden und ist für alle Nutzerinnen und Nutzer jederzeit zugänglich.
|
||||
|
||||
Neben der Informationspflicht wurden auch technische und organisatorische Maßnahmen umgesetzt, um die Sicherheit der verarbeiteten Daten zu gewährleisten. Dazu gehören unter anderem:
|
||||
|
||||
• Verschlüsselte Übertragung von Daten mittels HTTPS
|
||||
• Passwortgeschützter Zugriff auf sensible Daten
|
||||
• Regelmäßige Sicherheitsupdates der eingesetzten Software
|
||||
• Minimierung der Datenerhebung auf das Notwendige: Es werden nur die Daten erhoben, die für die Funktion der Webseite unbedingt erforderlich sind. (Grundprinzip der Datenminimierung nach Art. 5 Abs. 1 lit. c DSGVO)
|
||||
- Verschlüsselte Übertragung von Daten mittels HTTPS
|
||||
- Passwortgeschützter Zugriff auf sensible Daten
|
||||
- Regelmäßige Sicherheitsupdates der eingesetzten Software
|
||||
- Minimierung der Datenerhebung auf das Notwendige: Es werden nur die Daten erhoben, die für die Funktion der Webseite unbedingt erforderlich sind. (Grundprinzip der Datenminimierung nach Art. 5 Abs. 1 lit. c DSGVO)
|
||||
|
||||
#### Schutz personenbezogener Daten der Benutzer [@dsb]
|
||||
|
||||
\
|
||||
|
||||
Der Schutz personenbezogener Daten der Benutzer stellt einen zentralen Bestandteil der Webseite des Absolventenvereins dar. Sämtliche Datenverarbeitungen erfolgen unter Berücksichtigung der Vorgaben der Datenschutz-Grundverordnung (DSGVO) sowie des österreichischen Datenschutzgesetzes (DSG).
|
||||
|
||||
Gemäß Art. 5 Abs. 1 lit. c DSGVO gilt der Grundsatz der Datenminimierung, wonach nur jene personenbezogenen Daten erhoben werden dürfen, die für den jeweiligen Zweck erforderlich sind. Auf der Webseite werden daher ausschließlich solche Daten verarbeitet, die für die Verwaltung der Mitgliedschaft, die Organisation von Veranstaltungen sowie die Kommunikation mit Absolventinnen und Absolventen notwendig sind.
|
||||
@@ -197,6 +260,8 @@ Durch die Kombination aus klar definierten Rechtsgrundlagen, transparenten Infor
|
||||
|
||||
#### Notwendigkeit von Datensicherung [@bsi_datensicherung][@bsi_grundschutz]
|
||||
|
||||
\
|
||||
|
||||
Die Datensicherung ist ein wesentlicher Bestandteil der Webseite des Absolventenvereins. Sie dient dazu, die auf der Webseite gespeicherten Daten vor Verlust oder Beschädigung zu schützen. Digitale Daten bilden die Grundlage für die Funktion der Webseite und müssen daher regelmäßig gesichert werden. Ein Verlust oder eine Beschädigung der Daten kann zu erheblichen Problemen führen.
|
||||
|
||||
Mögliche Ursachen für einen Datenverlust sind unter anderem Hardwaredefekte, Softwarefehler, menschliches Versagen oder Cyberangriffe. Ohne geeignete Sicherheitsmaßnahmen besteht das Risiko, dass Daten unwiederbringlich verloren gehen oder nur mit erheblichen Kosten wiederhergestellt werden können.
|
||||
@@ -205,6 +270,8 @@ Neben der technischen besteht ebenfalls eine rechtliche und organisatorische Not
|
||||
|
||||
#### Konzeption des Backup-Systems
|
||||
|
||||
\
|
||||
|
||||
Ziel des Backup-Systems war es im Falle eines Datenverlustes oder eines Systemausfalls die Daten wiederherstellen zu können. Es wurde eine Strategie entwickelt die es ermöglicht sowohl die Datenbank als auch die Dateien auf dem Server zu sichern.
|
||||
Der Umfang des Backups besteht aus zwei zentralen Komponenten:
|
||||
|
||||
@@ -213,7 +280,7 @@ Der Umfang des Backups besteht aus zwei zentralen Komponenten:
|
||||
|
||||
Damit wird eine vollständige Sicherung der Webseite ermöglicht, da bei einer reinen Datenbanksicherung wichtige Anwendungsdateien fehlen würden.
|
||||
|
||||
```mermaid
|
||||
``` {.mermaid width=80% height=70%}
|
||||
%%| filename: flowchart-backup-system
|
||||
%%| fig-cap: Ablaufdiagramm des Backup-Systems
|
||||
graph TD
|
||||
@@ -316,6 +383,8 @@ Die gewählte Anzahl von 30 Sicherungen ermöglicht es, bei täglicher Ausführu
|
||||
|
||||
#### Implementierung der Backup-Skripte
|
||||
|
||||
\
|
||||
|
||||
Die Implementierung des Backup-Systems erfolgte mittels eines Bash-Skripts, das auf dem Linux-Server ausgeführt wird. Bash eignet sich besonders für administrative Aufgaben, da sie direkten Zugriff auf Systembefehle, Dateien und Prozesse bietet. Das Skript wurde so aufgebaut, dass es robust, automatisierbar und nachvollziehbar arbeitet.
|
||||
|
||||
Zu Beginn des Skripts wird folgende Konfiguration gesetzt:
|
||||
@@ -329,9 +398,9 @@ Die erste Zeile definiert den Interpreter, mit dem das Skript ausgeführt wird.
|
||||
|
||||
Die Anweisung set -euo pipefail erhöht die Sicherheit und Stabilität des Skripts:
|
||||
|
||||
• `-e` beendet das Skript sofort, wenn ein Befehl fehlschlägt
|
||||
• `-u` verhindert die Verwendung nicht definierter Variablen
|
||||
• `-o pipefail` sorgt dafür, dass auch Fehler innerhalb von Befehls-Pipelines erkannt werden
|
||||
- `-e` beendet das Skript sofort, wenn ein Befehl fehlschlägt
|
||||
- `-u` verhindert die Verwendung nicht definierter Variablen
|
||||
- `-o pipefail` sorgt dafür, dass auch Fehler innerhalb von Befehls-Pipelines erkannt werden
|
||||
|
||||
Diese Einstellungen verhindern, dass das Backup bei Fehlern unbemerkt unvollständig ausgeführt wird.
|
||||
|
||||
@@ -365,16 +434,18 @@ Diese Meldungen werden bei automatischer Ausführung über den Cronjob in eine L
|
||||
|
||||
Die Implementierung zeichnet sich durch folgende Eigenschaften aus:
|
||||
|
||||
• vollständige Sicherung von Datenbank und Anwendungsdateien
|
||||
• automatische tägliche Ausführung
|
||||
• integrierte Fehlerbehandlung
|
||||
• strukturierte Archivierung mit Zeitstempel
|
||||
• automatische Speicherverwaltung durch Rotationsmechanismus
|
||||
- vollständige Sicherung von Datenbank und Anwendungsdateien
|
||||
- automatische tägliche Ausführung
|
||||
- integrierte Fehlerbehandlung
|
||||
- strukturierte Archivierung mit Zeitstempel
|
||||
- automatische Speicherverwaltung durch Rotationsmechanismus
|
||||
|
||||
Durch diese Umsetzung wurde ein zuverlässiges und wartbares Backup-System geschaffen, das den kontinuierlichen Betrieb der Webanwendung unterstützt und im Fehlerfall eine schnelle Wiederherstellung ermöglicht.
|
||||
|
||||
#### Wiederherstellung von Daten mittels Restore-Skripten
|
||||
|
||||
\
|
||||
|
||||
Neben der Datensicherung stellt die strukturierte Wiederherstellung der Daten einen zentralen Bestandteil des Backup-Systems dar. Zu diesem Zweck wurde ein eigenes Bash-Skript implementiert, das sowohl die PostgreSQL-Datenbank als auch die Anwendungsdateien aus einem gewählten Backup-Ordner wiederherstellt (Restore-Skript). Ziel war es, einen klar definierten und kontrollierten Prozess zu schaffen, der im Fehlerfall eine vollständige Rücksetzung des Systems ermöglicht.
|
||||
|
||||
Das Skript beginnt – analog zum Backup-Skript – mit einer sicheren Ausführungskonfiguration:
|
||||
@@ -448,6 +519,8 @@ Zusammenfassend ermöglicht das Restore-Skript eine vollständige Rücksetzung d
|
||||
|
||||
#### Fazit zur Datensicherung
|
||||
|
||||
\
|
||||
|
||||
Durch die Implementierung eines automatisierten Backup- und Restore-Systems wurde eine zuverlässige Grundlage für die Datensicherheit der Webanwendung geschaffen. Das entwickelte System ermöglicht eine regelmäßige Sicherung sowohl der PostgreSQL-Datenbank als auch der vollständigen Anwendungsdateien. Durch die automatisierte Ausführung mittels Cronjob wird sichergestellt, dass die Backups ohne manuelles Eingreifen täglich erstellt werden.
|
||||
|
||||
Zusätzlich sorgt das integrierte Rotationsprinzip dafür, dass ältere Sicherungen automatisch entfernt werden und der verfügbare Speicherplatz effizient genutzt wird. Die strukturierte Ablage der Backups mit Zeitstempeln erleichtert die Auswahl eines bestimmten Sicherungsstandes.
|
||||
@@ -460,6 +533,8 @@ Insgesamt stellt das entwickelte Backup-System eine robuste und praxisnahe Lösu
|
||||
|
||||
#### Authentifizierung mittels OAuth 2.0
|
||||
|
||||
\
|
||||
|
||||
Zur Anmeldung auf der entwickelten Webplattform wurde eine Authentifizierung über das Business-Netzwerk LinkedIn implementiert. Dabei kommt das standardisierte Autorisierungsprotokoll OAuth 2.0 zum Einsatz [@rfc6749]. Dieses Verfahren ermöglicht es, Benutzer über externe Identitätsanbieter zu authentifizieren, ohne dass deren Zugangsdaten direkt an die Webanwendung übertragen werden müssen.
|
||||
|
||||
OAuth 2.0 basiert auf dem Prinzip der delegierten Autorisierung. Dabei erlaubt ein Benutzer einer Anwendung, bestimmte Informationen seines Kontos bei einem externen Dienst zu verwenden. Die eigentlichen Zugangsdaten – beispielsweise das LinkedIn-Passwort – verbleiben dabei ausschließlich beim Identitätsanbieter.
|
||||
@@ -476,12 +551,14 @@ Der Vorteil dieses Verfahrens liegt darin, dass die Webanwendung zu keinem Zeitp
|
||||
|
||||
#### Technische Umsetzung der LinkedIn-Anmeldung in Oqtane
|
||||
|
||||
\
|
||||
|
||||
Die technische Umsetzung der LinkedIn-Authentifizierung erfolgte über das integrierte External Login System [@oqtane_about] des Content-Management-Systems Oqtane. Dieses System ermöglicht die Integration externer Identitätsanbieter über standardisierte Protokolle wie OAuth 2.0.
|
||||
|
||||
Für die Verbindung mit LinkedIn wurde zunächst eine Entwickleranwendung im LinkedIn Developer Portal [@linkedin_auth_flow] erstellt. Dabei werden zwei zentrale Zugangsdaten generiert:
|
||||
|
||||
• Client ID
|
||||
• Client Secret
|
||||
- Client ID
|
||||
- Client Secret
|
||||
|
||||
Diese dienen zur Identifikation der Webanwendung gegenüber den LinkedIn-Servern.
|
||||
|
||||
@@ -499,9 +576,9 @@ Zusätzlich wurde eine sogenannte Redirect-URL definiert. Diese URL wird von Lin
|
||||
|
||||
In der Konfiguration wurde außerdem festgelegt, welche Benutzerdaten von LinkedIn übernommen werden sollen. Dazu gehören unter anderem:
|
||||
|
||||
• Benutzername
|
||||
• E-Mail-Adresse
|
||||
• eindeutige Benutzer-ID
|
||||
- Benutzername
|
||||
- E-Mail-Adresse
|
||||
- eindeutige Benutzer-ID
|
||||
|
||||
Diese Daten werden von Oqtane als sogenannte Claims verarbeitet und anschließend dem Benutzerkonto der Plattform zugeordnet.
|
||||
|
||||
@@ -509,25 +586,31 @@ Darüber hinaus wurde in den Einstellungen aktiviert, dass bei der ersten Anmeld
|
||||
|
||||
#### Ablauf des Anmeldeprozesses
|
||||
|
||||
\
|
||||
|
||||
Der eigentliche Anmeldevorgang erfolgt in mehreren aufeinanderfolgenden Schritten. Zunächst wählt der Benutzer auf der Login-Seite der Webplattform die Option zur Anmeldung über LinkedIn aus.
|
||||
|
||||
Daraufhin wird der Benutzer zur LinkedIn-Authentifizierungsseite weitergeleitet. Dort meldet sich der Benutzer mit seinem LinkedIn-Konto an und bestätigt die Autorisierung der Anwendung.
|
||||
|
||||
Nach erfolgreicher Authentifizierung sendet LinkedIn eine Antwort an die zuvor definierte Redirect-URL der Webanwendung. Diese Antwort enthält einen Autorisierungscode, der anschließend vom Server der Webanwendung gegen ein Zugriffstoken ausgetauscht wird.
|
||||
|
||||
Wie in Abschnitt 4.3.1 beschrieben, werden die abgerufenen Profildaten zur Identifikation oder Neuanlage des Benutzerkontos in der lokalen Datenbank verwendet.
|
||||
Wie in Abschnitt 4.4.3.1 beschrieben, werden die abgerufenen Profildaten zur Identifikation oder Neuanlage des Benutzerkontos in der lokalen Datenbank verwendet.
|
||||
|
||||
### Implementierung des Premium-Bereichs
|
||||
|
||||
\
|
||||
|
||||
#### Ziel und Zweck des Premium-Bereichs
|
||||
|
||||
\
|
||||
|
||||
Der Premium-Bereich wurde mit dem Ziel entwickelt, den Mitgliedern des SZU Absolventenvereins einen klar abgegrenzten, exklusiven Bereich innerhalb der VereinsWebseite bereitzustellen. Das Premium-Bereich-Modul ist eine Erweiterung für das Content-Management-System Oqtane und bildet das Kernstück des digitalen Mitgliederbereichs. Es ermöglicht Mitgliedern, sich über das Hochladen eines Ingenieur-Antrags als PDF-Dokument für eine zeitlich begrenzte Premium-Mitgliedschaft zu qualifizieren. Premium-Mitglieder erhalten Zugang zu exklusiven Funktionen wie dem Einsehen genehmigter Anträge anderer Mitglieder sowie einer Mitgliedersuche mit integrierter Kontaktfunktion.
|
||||
|
||||
Der zentrale Zweck besteht darin, einen Anreiz für aktives Engagement im Verein zu schaffen. Dadurch entsteht ein Kreislauf, in dem qualitativ hochwertige Anträge die Wissensbasis der Gemeinschaft bereichern und gleichzeitig den einreichenden Mitgliedern einen konkreten Gegenwert in Form von Premium-Funktionen bieten. Der Premium-Bereich dient darüber hinaus als digitales Netzwerk-Instrument. Durch die Kombination aus Antrags-Einsicht, Mitgliedersuche und Kontaktfunktion wird eine Plattform geschaffen, die den fachlichen Austausch zwischen Absolventen fördert und die Vernetzung innerhalb der Gemeinschaft stärkt. Die zeitliche Begrenzung der Premium-Mitgliedschaft auf 12 Monate sorgt dafür, dass Mitglieder regelmäßig aktiv bleiben und neue Inhalte beitragen, um ihren Premium-Status aufrechtzuerhalten.
|
||||
|
||||
Die Entwicklung erfolgte als eigenständiges Oqtane-Modul, wodurch eine nahtlose Integration in die bestehende VereinsWebseite gewährleistet wird. Das Modul nutzt dabei die vom Framework bereitgestellten Mechanismen für Authentifizierung, Autorisierung, Datenbankzugriff und Dateiverwaltung. Die Architektur folgt etablierten Entwurfsmustern wie dem Repository-Pattern, Dependency Injection und dem Service-Layer-Muster. Das kumulative Premium-System mit vollständigem Audit-Trail stellt sicher, dass alle Statusänderungen transparent und nachvollziehbar sind. Die modulare Struktur erlaubt eine einfache Erweiterung um zusätzliche Funktionen, ohne die bestehende Codebasis grundlegend verändern zu müssen.
|
||||
|
||||
```mermaid
|
||||
``` {.mermaid width=80% height=70%}
|
||||
%%| filename: architecture-premium-module
|
||||
%%| fig-cap: Architektur des Premium-Bereich-Moduls
|
||||
graph TD
|
||||
@@ -556,6 +639,8 @@ graph TD
|
||||
|
||||
#### Funktionalität und Features des Premium-Bereichs
|
||||
|
||||
\
|
||||
|
||||
Der Premium-Bereich umfasst mehrere miteinander verknüpfte Funktionen, die gemeinsam ein geschlossenes System bilden.
|
||||
|
||||
**Ingenieur-Antrags-Workflow**
|
||||
@@ -690,10 +775,14 @@ public class PremiumAreaContext : DBContextBase, ITransientService, IMultiDataba
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
builder.Entity<Models.PremiumArea>().ToTable(ActiveDatabase.RewriteName("SZUAbsolventenvereinPremiumArea"));
|
||||
builder.Entity<Models.EngineerApplication>().ToTable(ActiveDatabase.RewriteName("SZUAbsolventenvereinEngineerApplications"));
|
||||
builder.Entity<Models.UserPremium>().ToTable(ActiveDatabase.RewriteName("SZUAbsolventenvereinUserPremium"));
|
||||
builder.Entity<Models.PremiumEvent>().ToTable(ActiveDatabase.RewriteName("SZUAbsolventenvereinPremiumEvents"));
|
||||
builder.Entity<Models.PremiumArea>().ToTable(
|
||||
ActiveDatabase.RewriteName("SZUAbsolventenvereinPremiumArea"));
|
||||
builder.Entity<Models.EngineerApplication>().ToTable(
|
||||
ActiveDatabase.RewriteName("SZUAbsolventenvereinEngineerApplications"));
|
||||
builder.Entity<Models.UserPremium>().ToTable(
|
||||
ActiveDatabase.RewriteName("SZUAbsolventenvereinUserPremium"));
|
||||
builder.Entity<Models.PremiumEvent>().ToTable(
|
||||
ActiveDatabase.RewriteName("SZUAbsolventenvereinPremiumEvents"));
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -740,6 +829,8 @@ Insgesamt definieren vier Migrationen die Datenbankstruktur: Die erste erstellt
|
||||
|
||||
#### Zugriffsbeschränkung und Benutzerrechte
|
||||
|
||||
\
|
||||
|
||||
Der Zugriff auf den Premium-Bereich wird durch ein mehrstufiges Berechtigungssystem gesteuert, das sowohl auf Server- als auch auf Client-Seite durchgesetzt wird. Die verfügbaren Berechtigungen werden in der `ModuleInfo`-Klasse registriert:
|
||||
|
||||
```C#
|
||||
@@ -748,7 +839,7 @@ public class ModuleInfo : IModule
|
||||
public ModuleDefinition ModuleDefinition => new ModuleDefinition
|
||||
{
|
||||
Name = "PremiumArea",
|
||||
Description = "This module adds a premium member system to Octane.",
|
||||
Description = "This module adds a premium member system to Oqtane.",
|
||||
Version = "1.0.3",
|
||||
ServerManagerType = "SZUAbsolventenverein.Module.PremiumArea.Manager.PremiumAreaManager, SZUAbsolventenverein.Module.PremiumArea.Server.Oqtane",
|
||||
ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3",
|
||||
@@ -786,7 +877,7 @@ private bool IsUserPremium(System.Security.Claims.ClaimsPrincipal user)
|
||||
}
|
||||
```
|
||||
|
||||
```mermaid
|
||||
``` {.mermaid width=80% height=70%}
|
||||
%%| filename: flowchart-premium-access
|
||||
%%| fig-cap: Zugriffsprüfung für Premium-Inhalte
|
||||
flowchart TD
|
||||
@@ -817,6 +908,8 @@ Die Zugriffsbeschränkung wird konsequent auf beiden Seiten durchgesetzt: Client
|
||||
|
||||
#### Mehrwert für registrierte Mitglieder
|
||||
|
||||
\
|
||||
|
||||
Der Premium-Bereich schafft einen konkreten Mehrwert für registrierte Mitglieder auf mehreren Ebenen. Auf fachlicher Ebene entsteht durch die gesammelten Ingenieur-Anträge eine wachsende Wissensbasis, die allen Premium-Mitgliedern zugänglich ist. Absolventen können von den Arbeiten anderer Mitglieder lernen, sich inspirieren lassen und fachliche Ansätze vergleichen. Durch die Möglichkeit, Titel und Kurzbeschreibungen zu hinterlegen, können Mitglieder gezielt nach relevanten Themen suchen, ohne jedes PDF-Dokument einzeln öffnen zu müssen.
|
||||
|
||||
Auf sozialer Ebene fördert der Premium-Bereich die Vernetzung innerhalb der Absolventengemeinschaft. Die Mitgliedersuche mit integrierter Kontaktfunktion ermöglicht es, gezielt nach ehemaligen Kommilitonen oder Fachkollegen zu suchen und direkt Kontakt aufzunehmen. Der duale Benachrichtigungsmechanismus — bestehend aus In-App-Nachricht und E-Mail — stellt sicher, dass Kontaktanfragen zuverlässig zugestellt werden und kein Mitglied eine Nachricht verpasst.
|
||||
@@ -19,6 +19,7 @@ Mein Aufgabenbereich in diesem Projekt war vielseitig und umfasste sowohl leiten
|
||||
\
|
||||
|
||||
Als Product Owner war ich für die Definition der Produktvision und die Priorisierung des Backlogs verantwortlich. Dies beinhaltete:
|
||||
|
||||
- **Anforderungsmanagement**: Erhebung und Strukturierung der Anforderungen in Zusammenarbeit mit den Betreuern und dem Team.
|
||||
- **Sprint-Planung**: Organisation der 14-tägigen Sprints in YouTrack, um einen kontinuierlichen Entwicklungsfluss sicherzustellen.
|
||||
- **Qualitätssicherung**: Definition der *Definition of Done* (DoD) und Durchführung von Code-Reviews zur Einhaltung von Architekturstandards.
|
||||
@@ -28,6 +29,7 @@ Als Product Owner war ich für die Definition der Produktvision und die Priorisi
|
||||
\
|
||||
|
||||
Ein wesentlicher Teil meiner Arbeit lag in der Bereitstellung der technischen Basis für das gesamte Team:
|
||||
|
||||
- **Deployment-Strategie**: Konzeption und Umsetzung der Server-Infrastruktur auf Basis von Debian Linux und NginX als Reverse-Proxy.
|
||||
- **Datenbankdesign**: Entwurf des relationalen Datenmodells in PostgreSQL, inklusive der Absicherung durch SSL/TLS.
|
||||
- **CI/CD-Pipeline**: Automatisierung der Build- und Deployment-Prozesse mittels Gitea Actions für eine effiziente Integration der Teambeiträge.
|
||||
@@ -36,10 +38,10 @@ Ein wesentlicher Teil meiner Arbeit lag in der Bereitstellung der technischen Ba
|
||||
|
||||
\
|
||||
|
||||
Zusätzlich zur Infrastruktur habe ich drei zentrale Module für den Alumnihub entworfen und implementiert:
|
||||
Zusätzlich zur Infrastruktur habe ich drei zentrale Module für den AlumniHub entworfen und implementiert:
|
||||
|
||||
1. **Anmeldetool (EventRegistration)**: Ein Modul zum verwalten von Anmeldungen für Veranstaltungen. Es ermöglicht die einfache Erstellung von Einladungen zu Veranstaltungen und die Verwaltung von Anmeldungen.
|
||||
2. **Reporting System**: Ein generisches System zur Meldung von Inhalten, das nach dem *Open-Closed-Prinzip* entworfen wurde, um eine einfache Erweiterbarkeit für alle anderen Module zu bieten.
|
||||
1. **Anmeldetool (EventRegistration)**: Ein Modul zum Verwalten von Anmeldungen für Veranstaltungen. Es ermöglicht die einfache Erstellung von Einladungen sowie die Verwaltung von Anmeldungen.
|
||||
2. **Reporting-System**: Ein generisches System zur Meldung von Inhalten, das nach dem *Open-Closed-Prinzip* entworfen wurde, um eine einfache Erweiterbarkeit für alle anderen Module zu bieten.
|
||||
3. **Schwarzes Brett (BlackBoard)**: Ein Community-Modul für den Austausch von Informationen, inklusive eines automatisierten E-Mail-Digest-Systems zur Nutzerbenachrichtigung.
|
||||
|
||||
|
||||
@@ -60,11 +62,11 @@ Das Ziel des Anmeldetools ist die effiziente Organisation von Vereinsveranstaltu
|
||||
- **Teilnehmerliste**: Für jede Veranstaltung muss eine Übersicht der Rückmeldungen (Anmeldungen/Absagen) für Administratoren einsehbar sein.
|
||||
- **Statistische Auswertung**: Die Rückmeldungen sollen grafisch (z. B. als Tortendiagramm) aufbereitet werden, um die Planung zu erleichtern.
|
||||
|
||||
#### Globales Reporting System
|
||||
#### Reporting-System
|
||||
|
||||
\
|
||||
|
||||
Das Reporting System dient der Qualitätssicherung von Benutzerinhalten über alle Module hinweg.
|
||||
Das Reporting-System dient der Qualitätssicherung von Benutzerinhalten über alle Module hinweg.
|
||||
|
||||
- **Inhalte melden**: Benutzer müssen die Möglichkeit haben, unangemessene Einträge (z. B. am Schwarzen Brett) zu melden. Dabei muss ein Grund für die Meldung angegeben werden können.
|
||||
- **Generische Schnittstelle**: Das System muss so entworfen sein, dass beliebige andere Module (z. B. Hall of Fame) die Meldefunktion ohne Änderungen am Kern des Reporting-Systems einbinden können.
|
||||
@@ -85,7 +87,7 @@ Das Schwarze Brett fungiert als digitale Kommunikationsplattform für den Verein
|
||||
|
||||
\
|
||||
|
||||
Dieses Modul ermöglicht die direkte Kommunikation des Vorstands mit allen Mitgliedern.
|
||||
Dieses Modul ermöglicht die direkte Kommunikation des Vorstandes mit allen Mitgliedern.
|
||||
|
||||
- **Rundmails verfassen**: Administratoren müssen E-Mails mit Betreff und Inhalt an alle registrierten Benutzer verfassen können.
|
||||
- **Personalisierung**: Die E-Mails sollen automatisch mit dem Namen des Empfängers personalisiert werden können.
|
||||
@@ -105,19 +107,19 @@ Dies dient der Konfiguration sicherheitsrelevanter Parameter.
|
||||
Um die Interaktion der Benutzer mit den Modulen zu verdeutlichen, wurden folgende Use Cases definiert:
|
||||
|
||||
| ID | Name | Akteur | Beschreibung |
|
||||
| --- | --- | --- | ------ |
|
||||
| UC-01 | Veranstaltung erstellen | Administrator | Ein Administrator legt ein neues Absolvententreffen mit Ort und Datum an. |
|
||||
| UC-02 | Zu Event anmelden | Mitglied | Ein Absolvent bestätigt seine Teilnahme an einem Event über die Weboberfläche. |
|
||||
| UC-03 | Inhalt melden | Mitglied | Ein Benutzer meldet einen beleidigenden Post am Schwarzen Brett über den "Melden"-Button. |
|
||||
| UC-04 | Meldung bearbeiten | Moderator | Ein Vorstandsmitglied sichtet eine Meldung und löscht den entsprechenden Beitrag. |
|
||||
| UC-05 | Rundmail versenden | Administrator | Der Vorstand erstellt eine Einladung zur Generalversammlung für alle 500 Mitglieder. |
|
||||
| :---- | :---------------------- | :----------------- | :----------------------------------------------------------- |
|
||||
| 1 | Veranstaltung erstellen | Administrator | Ein Administrator legt ein neues Absolvententreffen mit Ort und Datum an. |
|
||||
| 2 | Zu Event anmelden | Mitglied | Ein Absolvent bestätigt seine Teilnahme an einem Event über die Weboberfläche. |
|
||||
| 3 | Inhalt melden | Mitglied | Ein Benutzer meldet einen beleidigenden Post am Schwarzen Brett über den "Melden"-Button. |
|
||||
| 4 | Meldung bearbeiten | Moderator | Ein Vorstandsmitglied sichtet eine Meldung und löscht den entsprechenden Beitrag. |
|
||||
| 5 | Rundmail versenden | Administrator | Der Vorstand erstellt eine Einladung zur Generalversammlung für alle 500 Mitglieder. |
|
||||
|
||||
Table: Wesentliche Use Cases der entwickelten Module
|
||||
|
||||
Es ist zu beachten, dass es sich hierbei um eine Auswahl handelt und nicht alle Use Cases der Module abgebildet werden.
|
||||
|
||||
|
||||
## Technisches Umfeld
|
||||
## Technologien
|
||||
|
||||
Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie das Bereitstellen des Services.
|
||||
|
||||
@@ -127,18 +129,18 @@ Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie da
|
||||
|
||||
\
|
||||
|
||||
Auch steht die Wahl der Programmiersprache und des CMS an. Nachdem wir im Unterricht fast ausschließlich mit C# entwickelt haben und nicht in eine komplett unbekannte Entwicklungsumgebung abdriften wollten, haben wir uns für die Webentwicklung mit ASP.NET Core 9 (Upgrade im Lauf der Diplomarbeit auf .NET Core 10) und dem CMS Oqtane entschieden. Auch hier gab es einige Kandidaten:
|
||||
Auch steht die Wahl der Programmiersprache und des CMS an. Nachdem wir im Unterricht fast ausschließlich mit C# entwickelt haben und nicht in eine komplett unbekannte Entwicklungsumgebung abdriften wollten, haben wir uns für die Webentwicklung mit ASP.NET Core 9 (Upgrade im Laufe der Diplomarbeit auf .NET Core 10) und dem CMS Oqtane entschieden. Auch hier gab es einige Kandidaten:
|
||||
|
||||
- Piranha CMS
|
||||
> Piranha erscheint auf den ersten Blick nicht so flexibel wie Oqtane, es basiert auf .NET 8.0 und wird nicht so aktiv gewartet.
|
||||
- Umbraco
|
||||
> Bei Umbraco muss viel in der Admin Oberfläche von dem CMS gearbeitet werden, im Großen und Ganzen wirkt dieses CMS nicht so flexibel. Die Dokumentation wirkt auf den ersten Blick sehr gut!
|
||||
> Bei Umbraco muss viel in der Admin-Oberfläche vom CMS gearbeitet werden, im Großen und Ganzen wirkt dieses CMS nicht so flexibel. Die Dokumentation wirkt auf den ersten Blick sehr gut!
|
||||
- DNN / Dot Net Nuke
|
||||
> Dieses CMS ist der Platzhirsch. Es wird von der DNN Foundation gewartet, arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Und ein Windows Server ist im Betrieb teurer und in der Absicherung aufwändiger.
|
||||
> Dieses CMS ist der Platzhirsch. Es wird von der DNN Foundation gewartet und arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Ein Windows Server ist im Betrieb teurer und in der Absicherung aufwändiger.
|
||||
- Oqtane
|
||||
> Oqtane wirkt auf sehr modular und flexibel, auch innerhalb von Modulen kann man auf alle Funktionen des ASP.NET Core Frameworks verwenden. Die Dokumentation wirkt nicht besonders gut, aber ausreichend. Die enthaltenen Fehlinformationen und mangelnden Anleitungen für den Betrieb mit Linux sind erst im Nachhinein aufgefallen.
|
||||
> Oqtane wirkt sehr modular und flexibel, auch innerhalb von Modulen kann man alle Funktionen des ASP.NET Core Frameworks verwenden. Die Dokumentation wirkt nicht besonders gut, aber ausreichend. Die enthaltenen Fehlinformationen und mangelnden Anleitungen für den Betrieb mit Linux sind erst im Nachhinein aufgefallen.
|
||||
|
||||
Insbesondere aufgrund seiner sehr hohen Flexibilität, haben wir uns am Ende für Oqtane entschieden.
|
||||
Insbesondere aufgrund seiner sehr hohen Flexibilität haben wir uns am Ende für Oqtane entschieden.
|
||||
|
||||
#### Entscheidungsfindung restliche Infrastruktur
|
||||
|
||||
@@ -152,7 +154,7 @@ Im Bereich der Datenbanken musste ich mir ein paar Fragen stellen:
|
||||
2. Mit welcher speziellen Implementierung bekommen wir Support und bei welcher haben wir Vorwissen im Team?
|
||||
3. Ist das auserkorene System kompatibel mit dem CMS, auf dem wir aufbauen?
|
||||
|
||||
Es war von Anfang an klar, dass es ein SQL-basiertes System wird, da wir im Team nur mit SQL-basierten Systemen Erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL-basierte Systeme. In der Linuxwelt kommen jetzt nur noch ein paar Datenbankmanagementsysteme in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem Datenbankmanagementsystem, welche ich in meinem Nebenjob erlangt habe.
|
||||
Es war von Anfang an klar, dass es ein SQL-basiertes System wird, da wir im Team nur mit SQL-basierten Systemen Erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL-basiierte Systeme. In der Linux-Welt kommen jetzt nur noch ein paar Datenbankmanagementsysteme in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem Datenbankmanagementsystem, welche ich in meinem Nebenjob erlangt habe.
|
||||
|
||||
### Beschreibung und Architektur von Oqtane
|
||||
|
||||
@@ -170,17 +172,18 @@ Ein Modul in Oqtane besteht aus vier Projekten:
|
||||
|
||||
- Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. Dazu gehören unter anderem alle Repositories, Controller, Manager, Migrationen und Server-Services und Server-Startuplogik.
|
||||
|
||||
- Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services, Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
|
||||
- Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services, Ressourcendateien (.resx), die Komponenten / das User-Interface und die Moduldefinitionen für jedes Modul.
|
||||
|
||||
- Im Shared-Projekt wird geteilter Sourcecode abgelegt, der server- und clientseitig verwendet wird. In der Praxis bleibt es hierbei bei den EntityFramework-Modellen zum Speichern der Daten im Arbeitsspeicher.
|
||||
|
||||
- Im Package Projekt findet man Skripte zum Debuggen und Releasen eines Moduls und die NuGet-Spezifikation.
|
||||
- Im Package-Projekt findet man Skripte zum Debuggen und Releasen eines Moduls und die NuGet-Spezifikation.
|
||||
- Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der drei anderen Projekte in den bereits gebauten Oqtane.Server `oqtane.framework/oqtane.server/bin/debug/net10.0/...` kopiert.
|
||||
- Beim Release wird ein NuGet-Paket erstellt und unter oqtane.framework/oqtane.server/Packages abgelegt. Dort abgelegte NuGet-Pakete werden beim nächsten Start des Oqtane Servers installiert (Datenbank Migrationen werden gemacht und die Pakete entpackt).
|
||||
- Beim Release wird ein NuGet-Paket erstellt und unter \
|
||||
oqtane.framework/oqtane.server/Packages abgelegt. Dort abgelegte NuGet-Pakete werden beim nächsten Start des Oqtane-Servers installiert (Datenbank-Migrationen werden gemacht und die Pakete entpackt).
|
||||
|
||||
### Zusammenspiel der Infrastruktur
|
||||
|
||||
In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen.
|
||||
In diesem Kapitel erkläre ich, wie die ausgewählten Komponenten zusammenspielen.
|
||||
|
||||
#### NginX as Reverse Proxy
|
||||
|
||||
@@ -189,12 +192,12 @@ In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen
|
||||
NginX fungiert in unserer Infrastruktur als `Reverse Proxy`. Ein Reverse Proxy nimmt Anfragen aus dem Internet entgegen und leitet sie an interne Server (wie Kestrel) weiter. Dies bietet mehrere Vorteile:
|
||||
|
||||
- **Sicherheit**: Die interne Applikation ist nicht direkt dem Internet ausgesetzt.
|
||||
- **SSL-Terminierung**: NginX übernimmt die rechenintensive Verschlüsselung (HTTPS), während die Applikation dahinter über einfaches HTTP kommuniziert.
|
||||
- **Statische Inhalte**: NginX kann statische Dateien (Bilder, CSS) effizienter ausliefern als ein Applikationsserver.
|
||||
- **SSL-Terminierung**: Nginx übernimmt die rechenintensive Verschlüsselung (HTTPS), während die Applikation dahinter über einfaches HTTP kommuniziert.
|
||||
- **Statische Inhalte**: Nginx kann statische Dateien (Bilder, CSS) effizienter ausliefern als ein Applikationsserver.
|
||||
|
||||
Wir verwenden NginX für die SSL Terminierung. Das Zertifikat wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert.
|
||||
Wir verwenden Nginx für die SSL-Terminierung. Das Zertifikat wird von Let’s Encrypt bereitgestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert.
|
||||
|
||||
Hier ist ein Auszug der NginX-Konfiguration (`nginx.conf`) für den Alumnihub:
|
||||
Hier ist ein Auszug der NginX-Konfiguration (`nginx.conf`) für den AlumniHub:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
@@ -215,10 +218,12 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
Oqtane selber läuft als Systemd-Service im Kestrel Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback IP und Port 5000. Damit ist Oqtane nur durch NginX erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback IP und Port 5432. In der folgenden Grafik ist das System Schematisch dargestellt.
|
||||
Oqtane selbst läuft als Systemd-Service im Kestrel-Backend. Kestrel ist ein kleiner Webserver, welcher in das ASP.NET Core Framework eingebaut worden ist. Oqtane (bzw. der ASP.NET Core Server "Kestrel") hört auf der Loopback-IP und Port 5000. Damit ist Oqtane nur durch Nginx erreichbar. PostgreSQL ist die Datenbank in dem System: Sie hört wieder auf der Loopback-IP und Port 5432. In der folgenden Grafik ist das System schematisch dargestellt.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
%%| filename: sequence-diagram-system-architecture
|
||||
%%| fig-cap: Schematische Darstellung der Systemarchitektur
|
||||
participant browser as Client
|
||||
participant nginx as NginX
|
||||
participant oqtane as Oqtane
|
||||
@@ -236,14 +241,14 @@ sequenceDiagram
|
||||
Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Der SSH Service ist in jeder Umgebung anders erreichbar gewesen.
|
||||
|
||||
| Umgebung | Administrationszugang |
|
||||
| ---------- | --------------------- |
|
||||
| :--------------------------- | :----------------------------------------------------------- |
|
||||
| Hetzner | Wireguard |
|
||||
| Schule | Highport |
|
||||
| LiveDesign | IPSEC VPN |
|
||||
|
||||
Table: SSH Zugänge in den unterschiedlichen Umgebungen
|
||||
|
||||
Die VPN basierten Zugänge sind tendenziell schwieriger zu finden und auszunutzen, während die Lösung in der Schule mittels Highport den SSH Service öffentlich erreichbar macht. Durch den `Highport` ist der SSH Service schwieriger zu finden. Zur Authentifizierung mit SSH verwenden wir SSH-Keys, da diese durch ihre komplexität sicherer sind, als Passwörter.
|
||||
Die VPN-basierten Zugänge sind tendenziell schwieriger zu finden und auszunutzen, während die Lösung in der Schule mittels Highport den SSH-Service öffentlich erreichbar macht. Durch den `Highport` ist der SSH-Service schwieriger zu finden. Zur Authentifizierung mit SSH verwenden wir SSH-Keys, da diese durch ihre Komplexität sicherer sind als Passwörter.
|
||||
|
||||
### Entwicklung mit ASP.NET
|
||||
|
||||
@@ -251,12 +256,12 @@ Die VPN basierten Zugänge sind tendenziell schwieriger zu finden und auszunutze
|
||||
|
||||
\
|
||||
|
||||
Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es möglich macht Benutzeroberflächen für Web-Browser, basierend auf C# und HTML, zu erstellen. Es wird von Microsoft als teil des ASP.NET Core Frameworks entwickelt.
|
||||
Blazor ist ein kostenloses und quelloffenes Web-Framework, welches es ermöglicht, Benutzeroberflächen für Web-Browser basierend auf C# und HTML zu erstellen. Es wird von Microsoft als Teil des ASP.NET Core Frameworks entwickelt.
|
||||
|
||||
Blazor hat mehrere Hosting-Modelle:
|
||||
|
||||
| Hosting-Modell | Ausführungsort | Interaktivität | Kommunikation |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| :-------------------------- | :----------------- | :----------------- | :--------------------------- |
|
||||
| **Static Server** | Server | Keine | HTTP (Initialer Load) |
|
||||
| **Interactive Server** | Server | Hoch (Echtzeit) | SignalR / WebSockets |
|
||||
| **Interactive WebAssembly** | Client (Browser) | Hoch (Lokal) | REST API / HTTP |
|
||||
@@ -265,9 +270,9 @@ Blazor hat mehrere Hosting-Modelle:
|
||||
|
||||
Table: Vergleich der Blazor Hosting-Modelle
|
||||
|
||||
Im Rahmen dieser Diplomarbeit haben wir und für den RenderModus Interactive Server entschieden. Dieser Modus ist für Oqtane die Standardeinstellung und bietet eine gute Balance zwischen Leistung und Benutzerfreundlichkeit. Das ist für unseren Anwendungsfall auch die Empfehlung von Oqtane selbst. [@oqtane_docs_rendermodes]
|
||||
Im Rahmen dieser Diplomarbeit haben wir uns für den Rendermodus Interactive Server entschieden. Dieser Modus ist für Oqtane die Standardeinstellung und bietet eine gute Balance zwischen Leistung und Benutzerfreundlichkeit. Das ist für unseren Anwendungsfall auch die Empfehlung von Oqtane selbst. [@oqtane_docs_rendermodes]
|
||||
|
||||
Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von inline C# beeinflusst werden kann. Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Datei liegen, oder in einer seperaten Code-Behind-Datei. Inline C# Code wird mithilfe von `@`- Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter:
|
||||
Razor-Komponenten (in dieser Arbeit sowie umgangssprachlich auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von Inline-C# beeinflusst werden kann. Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor-Datei liegen oder in einer separaten Code-Behind-Datei. Inline-C#-Code wird mithilfe von `@`-Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter:
|
||||
|
||||
```razor
|
||||
<h1>Counter</h1>
|
||||
@@ -289,7 +294,7 @@ Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Kompo
|
||||
|
||||
Mit`@count` in Zeile 3 wird der Wert der Variablen count in den `<p>` Tag mit eingebaut. Mit `@onclick="Increment"` in Zeile 5 wird die onclick Property vom `<button>`Tag auf die Increment Methode im C# Code gesetzt. Der `@code` Block in Zeile 7 ist der C# Code, welcher diese Komponente dynamisch macht. Hier ist die Variable count und die Methode Increment definiert, welche dieser Komponente interaktiv macht.
|
||||
|
||||
Razor hat auch eine Reihe an Keywords, wie zum Beispiel (nur Auszugsweise, bzw. die die wir verwendet haben):
|
||||
Razor hat auch eine Reihe an Keywords, wie zum Beispiel (nur auszugsweise bzw. die, die wir verwendet haben):
|
||||
|
||||
- namespace: Gibt den aktuellen Namespace in der Razor Datei an.
|
||||
- inherits: Gibt die Superklasse der generierten C# Klasse an.
|
||||
@@ -310,7 +315,8 @@ Der folgende Ablauf zeigt die Kommunikation bei einer typischen Datenabfrage in
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
%
|
||||
%%| filename: sequence-diagram-data-query
|
||||
%%| fig-cap: Schematische Darstellung der Systemarchitektur
|
||||
participant C as Blazor Client (Razor)
|
||||
participant S as Oqtane Server (Controller)
|
||||
participant R as Repository (EntityFramework)
|
||||
@@ -334,11 +340,11 @@ Wie der Software-Architekt Martin Fowler, der den Begriff im Jahr 2004 maßgebli
|
||||
|
||||
In den folgenden beiden Kapiteln wird das Dependency Inversion Principle und das Microsoft Dependency Injection Framework genauer vorgestellt.
|
||||
|
||||
#### Dependency Inversion Principle [@ms_dependency_inversion][@logrocket_dependency_inversion]
|
||||
#### Dependency Inversion Principle [@ms_dependency_inversion] [@logrocket_dependency_inversion]
|
||||
|
||||
\
|
||||
|
||||
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines von den fünf `SOLID` Prinzipien in der Softwareentwicklung.
|
||||
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines der fünf SOLID-Prinzipien in der Softwareentwicklung.
|
||||
|
||||
Das DIP unterscheidet zwischen high-level und low-level Modulen.
|
||||
|
||||
@@ -349,6 +355,8 @@ Ausgangslage ist eine Softwarearchitektur im Direct-Dependency-Graph-Modell.
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
%%| filename: architecture-beta
|
||||
%%| fig-cap: DIP: Direct Dependency Graph
|
||||
service a(mdi:package-variant-closed)[Klasse A]
|
||||
service b(mdi:package-variant-closed)[Klasse B]
|
||||
|
||||
@@ -360,6 +368,8 @@ Das Problem dabei: Die einzelnen Klassen sind eng gekoppelt, was das Austauschen
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
%%| filename: architecture-beta
|
||||
%%| fig-cap: DIP: Dependency Inversion Principle
|
||||
service a(mdi:package-variant-closed)[Klasse A]
|
||||
service b(mdi:package-variant-closed)[Klasse B]
|
||||
service ib(mdi:car-clutch)[Interface B]
|
||||
@@ -427,6 +437,7 @@ Mit dem Aufruf von `builder.Build()` wird intern ein Dependency Graph erstellt u
|
||||
So sieht der Abhängigkeitsgraph bei diesem Beispiel aus.
|
||||
|
||||
```mermaid
|
||||
%%| fig-cap: DIP: Dependency Inversion Principle Beispiel
|
||||
architecture-beta
|
||||
service a(mdi:package-variant-closed)[Worker]
|
||||
service b(mdi:package-variant-closed)[MessageWriter]
|
||||
@@ -438,27 +449,61 @@ architecture-beta
|
||||
|
||||
```
|
||||
|
||||
### Continuous Integration
|
||||
### Continuous Integration {#sec:continuous-integration}
|
||||
|
||||
Gitea, das Versionskontrollsystem dieser Diplomarbeit, hat einen Continuous-Integration-System eingebaut. Im Kern ist es baugleich zu den GitHub-Pipelines. Man kann im `.gitea/workflow` Ordner `.yml` Dateien ablegen, welche dann das Verhalten der Workflows definieren.
|
||||
|
||||
Man kann definieren auf welcher Änderung im Git Repository die Pipeline losgetreten wird (Keyword: `on`) und entweder eigene Kommandos aufreihen, oder auf bestehende `actions` zurückgreifen, welche dann der Reihe nach ausgeführt werden (Keyword: `jobs`).
|
||||
|
||||
Die meisten Pipelines sind folgendermaßen Aufgebaut:
|
||||
Clone -> Checkout -> Submodule Checkout (optional) -> Dependencies einrichten (zum Beispiel das dotnet SDK) -> Build ausführen. -> Release erstellen und Artefakte veröffentlichen (z.B. in Registries). Aber man kann auch andere Dinge tun, z.B. mithilfe von Künstlicher Intelligenz Code und Dokumentation überprüfen.
|
||||
Die meisten Pipelines sind folgendermaßen aufgebaut:
|
||||
Clone -> Checkout -> Submodule-Checkout (optional) -> Dependencies einrichten (zum Beispiel das dotnet SDK) -> Build ausführen -> Release erstellen und Artefakte veröffentlichen (z. B. in Registries). Aber man kann auch andere Dinge tun, z. B. mithilfe von künstlicher Intelligenz Code und Dokumentation überprüfen.
|
||||
|
||||
Anwendungen von Gitea Actions bei dieser Diplomarbeit:
|
||||
|
||||
- APT-Package Repository:
|
||||
> Zum Bauen von Oqtane und allen Modulen, verpacken in ein .deb Paket und in die Registry pushen.
|
||||
- Interfaces Projekt
|
||||
> Zum Bauen vom Interfaces-Projekt, verpacken in ein NuGet Paket und in die Registry pushen. Die Versionierung des NuGet-Pakets erfolgt dabei automatisiert über Git-Tags, was eine konsistente Verknüpfung zwischen Quellcode-Stand und Paketversion sicherstellt.
|
||||
- ursprünglich: oqtane.framework
|
||||
> Zum bauen und Verpacken in einen Docker Container und in die Registry pushen.
|
||||
- PM Repository:
|
||||
> Zum automatischen Überprüfen der Dokumente, unter anderem, mithilfe von KI, wie zum Beispiel Gemini.
|
||||
- **APT-Package Repository**: Zum Bauen von Oqtane und allen Modulen, Verpacken in ein .deb-Paket und Pushen in die Registry.
|
||||
- **Interfaces-Projekt**: Zum Bauen vom Interfaces-Projekt, Verpacken in ein NuGet-Paket und Pushen in die Registry. Die Versionierung des NuGet-Pakets erfolgt dabei automatisiert über Git-Tags, was eine konsistente Verknüpfung zwischen Quellcode-Stand und Paketversion sicherstellt.
|
||||
- **ursprünglich: oqtane.framework**: Zum Bauen und Verpacken in einen Docker-Container und Pushen in die Registry.
|
||||
- **PM Repository**: Zum automatischen Überprüfen der Dokumente unter anderem mithilfe von KI, wie zum Beispiel Gemini.
|
||||
|
||||
# Gitea Actions YAML einfügen und erklären
|
||||
Ein Beispiel für eine Konfiguration einer Gitea Action:
|
||||
|
||||
```yaml
|
||||
name: build-debian-package
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build the debian package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Git clone"
|
||||
run: git clone ${{ gitea.server_url }}/${{ gitea.repository }}.git .
|
||||
- name: "Git checkout"
|
||||
run: git checkout "${{ gitea.sha }}"
|
||||
- name: "Submodules auschecken"
|
||||
run: git submodule update --init
|
||||
- name: "Dotnet SDK einrichten"
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: "10.0.x"
|
||||
- name: "Configure nuget source"
|
||||
run: dotnet nuget add source --name DAV --username kocoder --password ${{ secrets.REGISTRY_TOKEN_KOCODER }} https://git.kocoder.xyz/api/packages/Diplomarbeit-Absolventenverein/nuget/index.json --store-password-in-clear-text
|
||||
- name: "Build .deb"
|
||||
run: ./run-build.sh "${{ gitea.ref_name }}" "./alumnihub" "Release"
|
||||
- name: "Upload .deb"
|
||||
run: curl --user kocoder:${{ secrets.REGISTRY_TOKEN_KOCODER }} --upload-file ./alumnihub.deb https://git.kocoder.xyz/api/packages/Diplomarbeit-Absolventenverein/debian/pool/trixie/main/upload
|
||||
- name: "Create release"
|
||||
uses: akkuman/gitea-release-action@v1
|
||||
with:
|
||||
files: |-
|
||||
./alumnihub.deb
|
||||
./alumnihub/opt/alumnihub/Packages/*.nupkg
|
||||
```
|
||||
|
||||
Die Konfiguration führt teilweise vorgefertigte Actions aus, wie zum Beispiel das Einrichten des .NET SDKs oder das Erstellen eines Releases. Aber es werden auch eigene Skripte ausgeführt, wie zum Beispiel das Bauen des .deb-Pakets. Dieses ist im Repository unter `./run-build.sh` zu finden. Dieses Skript ist für die Automatisierung des Build-Prozesses zuständig und kümmert sich um das Kompilieren der Anwendung, das Erstellen des Debian-Pakets und das Hochladen in die Registry. Abgelegt ist es im APT-Package-Repository unter `./gitea/workflows`.
|
||||
|
||||
### Debian Paket
|
||||
|
||||
@@ -491,7 +536,7 @@ Durch diesen Prozess wird sichergestellt, dass jede Version der Software eindeut
|
||||
|
||||
### Scrum
|
||||
|
||||
Zum verwalten des Projektes haben wir uns an den Grundprinzipien von Scrum orientiert, um flexibel auf Änderungen reagieren zu können. Die Arbeit wurde in 14-tägige Sprints unterteilt.
|
||||
Zum Verwalten des Projektes haben wir uns an den Grundprinzipien von Scrum orientiert, um flexibel auf Änderungen reagieren zu können. Die Arbeit wurde in 14-tägige Sprints unterteilt.
|
||||
|
||||
- **Sprint Planning**: Zu Beginn jedes Sprints wurden die Aufgaben aus dem Product Backlog in das Sprint Backlog übernommen.
|
||||
- **Dailies/Weekly**: Wir hielten wöchentliche Treffen ab, um den Fortschritt zu synchronisieren und Blocker zu identifizieren.
|
||||
@@ -501,15 +546,11 @@ Zum verwalten des Projektes haben wir uns an den Grundprinzipien von Scrum orien
|
||||
|
||||
Mehr zum Projektmanagementprozess steht im allgemeinen Teil [Projektmanagement mit Scrum](#projektmanagement-mit-scrum).
|
||||
|
||||
### YouTrack
|
||||
|
||||
Zur Verwaltung des Backlogs und der Sprints wurde YouTrack von JetBrains eingesetzt. Im Vergleich zu einfachen To-Do-Listen bietet YouTrack mächtige Features für Softwareteams:
|
||||
|
||||
- **Agile Boards**: Visualisierung des Aufgabenstatus (To Do, In Progress, Review, Done).
|
||||
- **Time Tracking**: Erfassung der aufgewendeten Zeit für die einzelnen Arbeitspakete.
|
||||
- **Gantt-Diagramme**: Zur groben zeitlichen Orientierung und Überprüfung von Meilensteinen.
|
||||
|
||||
Die Integration von YouTrack half uns dabei, die Verantwortlichkeiten klar zuzuweisen und den Überblick über den "Burndown" der Aufgaben zu behalten.
|
||||
### Projektmanagement-Tools (YouTrack & Gitea)
|
||||
|
||||
Für die initiale Planung und die ersten Sprints wurde YouTrack von JetBrains eingesetzt. Im Vergleich zu einfachen To-Do-Listen bietet YouTrack mächtige Features für Softwareteams wie agile Boards, Time Tracking und Gantt-Diagramme.
|
||||
|
||||
Im weiteren Verlauf der Diplomarbeit sind wir jedoch auf die integrierten Projektmanagement-Funktionen von Gitea umgestiegen. [Siehe Issues](#issues). Dieser Wechsel erfolgte, um den gesamten Entwicklungsprozess — von der Aufgabenverwaltung (Issues/Boards) über die Versionskontrolle bis hin zur CI/CD-Pipeline (Gitea Actions) — an einem zentralen Ort zu bündeln. Dies verbesserte die Übersichtlichkeit und reduzierte den administrativen Aufwand für die Pflege unterschiedlicher Systeme.
|
||||
|
||||
### Git
|
||||
|
||||
@@ -537,37 +578,45 @@ Als schlanke und selbst gehostete Open-Source-Alternative zu Plattformen wie Git
|
||||
|
||||
\
|
||||
|
||||
Ein Repository bildet den zentralen Speicherort für einen Projektteil. In Gitea wurden separate Repositories für die einzelnen Module und Themes, das Oqtane Framework, Skripte, die Dokumentation angelegt. Ein zusätzliches Repository bindet alle übrigen Quellcode-Repositories als Submodule ein, das macht die Einrichtung einer neuen Entwicklungsumgebung sehr kompfortabel. Dies ermöglichte eine saubere Trennung der verschiedenen Projektkomponenten. [@gitea_docs]
|
||||
Ein Repository bildet den zentralen Speicherort für einen Projektteil. In Gitea wurden separate Repositories für die einzelnen Module und Themes, das Oqtane Framework, Skripte, die Dokumentation angelegt. Ein zusätzliches Repository bindet alle übrigen Quellcode-Repositories als Submodule ein, das macht die Einrichtung einer neuen Entwicklungsumgebung sehr komfortabel. Dies ermöglichte eine saubere Trennung der verschiedenen Projektkomponenten. [@gitea_docs]
|
||||
|
||||
#### Issues
|
||||
|
||||
\
|
||||
|
||||
Zur Aufgabenplanung und Fehlerverfolgung wurde das integrierte Issue-System genutzt. Jede anstehende Aufgabe oder entdeckte Schwachstelle wurde als „Issue“ erfasst, einem Verantwortlichen zugewiesen und mit Labels (z. B. „Bug“, „Feature“ oder „Dokumentation“) versehen. Dies half dabei, den Überblick über den Projektfortschritt zu behalten und die Anforderungen aus dem Lastenheft strukturiert abzuarbeiten. [@gitea_docs][@gitea_issue_tracker]
|
||||
{ width=70% }
|
||||
|
||||
Zur Aufgabenplanung und Fehlerverfolgung wurde das integrierte Issue-System genutzt. Jede anstehende Aufgabe oder entdeckte Schwachstelle wurde als „Issue“ erfasst, einem Verantwortlichen zugewiesen und mit Labels (z. B. „Bug“, „Feature“ oder „Dokumentation“) versehen. Dies half dabei, den Überblick über den Projektfortschritt zu behalten und die Anforderungen aus dem Lastenheft strukturiert abzuarbeiten. [@gitea_docs] [@gitea_issue_tracker]
|
||||
|
||||
#### Pull Requests
|
||||
|
||||
\
|
||||
|
||||
Um die Qualität des Codes zu sichern, wurden Änderungen nicht direkt in den Hauptzweig eingespielt, sondern über Pull Requests eingereicht. Ein Teammitglied konnte so die Änderungen eines anderen sichten, kommentieren und bei Bedarf Korrekturen anfordern. Erst nach einer erfolgreichen Überprüfung wurde der Code in den main-Branch gemergt. [@gitea_docs][@gitea_pull_requests]
|
||||
Um die Qualität des Codes zu sichern, wurden Änderungen nicht direkt in den Hauptzweig eingespielt, sondern über Pull Requests eingereicht. Ein Teammitglied konnte so die Änderungen eines anderen sichten, kommentieren und bei Bedarf Korrekturen anfordern. Erst nach einer erfolgreichen Überprüfung wurde der Code in den main-Branch gemergt. [@gitea_docs] [@gitea_pull_requests]
|
||||
|
||||
#### Actions
|
||||
|
||||
\
|
||||
|
||||
Gitea Actions wurden eingesetzt, um CI/CD-Pipelines (Continuous Integration / Continuous Deployment) zu realisieren. Bei jedem Push oder Pull Request wurden automatisierte Skripte ausgeführt, die das Projekt bauten. Dies reduzierte manuelle Fehlerquellen erheblich. Außerdem konnten wir mithilfe von CI/CD den Release Prozess einmalig festlegen und automatisieren, ohne bei jedem Update manuell den selben Prozess wiederholt durchgehen zu müssen. Das APT-Package Projekt enthält die CI/CD Konfiguration für das bauen von Oqtane, der Module und Themes, sowie das verpacken in ein APT Paket und dem veröffentlichen aller Pakete als eingenes Gitea Release. [@gitea_docs][@gitea_actions]
|
||||
{ width=70% }
|
||||
|
||||
Gitea Actions wurden eingesetzt, um CI/CD-Pipelines (Continuous Integration / Continuous Deployment) zu realisieren. Bei jedem Push oder Pull Request wurden automatisierte Skripte ausgeführt, die das Projekt bauten. Dies reduzierte manuelle Fehlerquellen erheblich. Außerdem konnten wir mithilfe von CI/CD den Release Prozess einmalig festlegen und automatisieren, ohne bei jedem Update manuell den selben Prozess wiederholt durchgehen zu müssen. Das APT-Package Projekt enthält die CI/CD Konfiguration für das bauen von Oqtane, der Module und Themes, sowie das verpacken in ein APT Paket und dem veröffentlichen aller Pakete als eingenes Gitea Release. [Siehe Abschnitt \ref{sec:continuous-integration}] [@gitea_docs] [@gitea_actions]
|
||||
|
||||
#### Releases
|
||||
|
||||
\
|
||||
|
||||
{ width=70% }
|
||||
|
||||
Über die Release-Funktion wurden wichtige Meilensteine der Diplomarbeit festgeschrieben. Hierbei wird ein spezifischer Git-Tag mit einer Versionsnummer versehen und die dazugehörigen Binärdateien, Pakete und Dokumente archiviert. So lässt sich jederzeit auf einen stabilen, abgabebereiten Stand des Projekts zugreifen. [@gitea_docs]
|
||||
|
||||
#### Package Repositories
|
||||
|
||||
\
|
||||
|
||||
Gitea fungierte zusätzlich als Register für Pakete und Container-Images. Selbst erstellte Artefakte, wie das Debian Paket für die Bereitstellung der Anwendung, wurden direkt in der Gitea-Instanz versioniert gespeichert. Dadurch waren alle notwendigen Komponenten für das Deployment an einem zentralen Ort verfügbar und abrufbar. Gitea selbst unterstützt verschiedenste Pakettypen. Darunter fallen unteranderem NuGet- und Debianpakete. Für beide haben wir in dieser Arbeit verwendung gefunden. [@gitea_docs][@gitea_packages]
|
||||
{ width=70% }
|
||||
|
||||
Gitea fungierte zusätzlich als Register für Pakete und Container-Images. Selbst erstellte Artefakte, wie das Debian Paket für die Bereitstellung der Anwendung, wurden direkt in der Gitea-Instanz versioniert gespeichert. Dadurch waren alle notwendigen Komponenten für das Deployment an einem zentralen Ort verfügbar und abrufbar. Gitea selbst unterstützt verschiedenste Pakettypen. Darunter fallen unteranderem NuGet- und Debianpakete. Für beide haben wir in dieser Arbeit verwendung gefunden. [@gitea_docs] [@gitea_packages]
|
||||
|
||||
### Kommunikation
|
||||
|
||||
@@ -575,32 +624,36 @@ Gitea fungierte zusätzlich als Register für Pakete und Container-Images. Selbs
|
||||
|
||||
### Admin Modules
|
||||
|
||||
Eine C#-Solution, welche einige Module, welche für den Admineinsatz geschrieben worden sind beinhaltet. Dieses Modul besteht aus 3 Teilmodulen. Einem Modul für den Versand von Rundmails, eines für die Einstellung von der Token Lebenszeit bei Tokens, welche per E-Mail verschickt werden und eines, welches das Reporting-System übernimmt.
|
||||
Eine C#-Solution, welche einige für den Admin-Einsatz geschriebene Module beinhaltet. Dieses Modul besteht aus drei Teilmodulen: einem Modul für den Versand von Rundmails, eines für die Einstellung der Token-Lebenszeit bei Tokens, welche per E-Mail verschickt werden, und eines, welches das Reporting-System übernimmt.
|
||||
|
||||
#### Mass Mailing
|
||||
|
||||
\
|
||||
|
||||
Das Mass Mailer Modul ist eine administrative Erweiterung für den Alumnihub, die es dem Vorstand ermöglicht, personalisierte Rundschreiben an alle registrierten Mitglieder zu versenden. Da die Pflege der Mitgliederdaten direkt im CMS erfolgt, bietet dieses Modul eine nahtlose Integration ohne den Export von CSV-Listen in externe Newsletter-Tools.
|
||||
Das Mass-Mailer-Modul ist eine administrative Erweiterung für den AlumniHub, die es dem Vorstand ermöglicht, personalisierte Rundschreiben an alle registrierten Mitglieder zu versenden. Da die Pflege der Mitgliederdaten direkt im CMS erfolgt, bietet dieses Modul eine nahtlose Integration ohne den Export von CSV-Listen in externe Newsletter-Tools.
|
||||
|
||||
Integration von Brevo
|
||||
##### Integration von Brevo
|
||||
|
||||
Für den tatsächlichen Versand der E-Mails nutzen wir den Cloud-Dienst Brevo. Dieser bietet eine zuverlässige Zustellung (hohe Reputation der Mailserver), stellt uns jedoch in der kostenlosen Variante vor eine Herausforderung: nur 300 E-Mails pro Tag.
|
||||
\
|
||||
|
||||
`Batch-Processing`: Mails werden nicht sofort ("Fire and Forget") versendet, sondern in eine Versandwarteschlange geschrieben. Nachdem schon die Notifications Infrastruktur, welche sich auch um den Mail versand kümmert, ins Framework eingebaut worden ist, wird diese gleich zum `schedulen` unserer E-Mails genutzt. Immer 100 Mails alle 24 Stunden bis alle Ziele die Mails erhalten haben. Das Limit von 100 / Tag ist konservativ sehr niedrig angesetzt, damit Funktionen wie Passwort Reset Mails nicht (leicht) dadurch beeinflusst werden können.
|
||||
{ width=70% }
|
||||
|
||||
Für den tatsächlichen Versand der E-Mails nutzen wir den Cloud-Dienst Brevo. Dieser bietet eine zuverlässige Zustellung (hohe Reputation der Mailserver), sowie die Möglichkeit die Zustell-, Öffnungs- und Klickraten zu beobachten. Das Limit von 300 E-Mails pro Tag stellt uns jedoch in der kostenlosen Variante vor eine Herausforderung.
|
||||
|
||||
`Batch-Processing`: Mails werden nicht sofort ("Fire and Forget") versendet, sondern in eine Versandwarteschlange geschrieben. Nachdem schon die Notifications-Infrastruktur, welche sich auch um den Mailversand kümmert, ins Framework eingebaut worden ist, wird diese gleich zum `schedulen` unserer E-Mails genutzt. Immer 100 Mails alle 24 Stunden, bis alle Ziele die Mails erhalten haben. Das Limit von 100 / Tag ist konservativ sehr niedrig angesetzt, damit Funktionen wie Passwort-Reset-Mails nicht (leicht) dadurch beeinflusst werden können.
|
||||
|
||||
#### Token Lifetime
|
||||
|
||||
\
|
||||
|
||||
Das Token Lifetime Modul wurde geschrieben, um die Token-Lebenszeit konfigurierbar zu machen. Notwendig war das, um die Passwort Reset Links im initialen Mail versand länger gültig sein zu lassen. Durch das `Batch Processing` war es möglich, dass eine Mail erst Tage nach erstellen des Links hinaus geschickt wird und bei einer Standard Ablaufdauer von 2 Tagen sind manche Links schon ungültig, bis sie den Mail Server erreichen. Ziel war es, die Änderung der Lebenszeit für Administratoren im User Interface im Admin Bereich möglich zu machen.
|
||||
Das Token-Lifetime-Modul wurde geschrieben, um die Token-Lebenszeit konfigurierbar zu machen. Notwendig war das, um die Passwort-Reset-Links im initialen Mailversand länger gültig sein zu lassen. Durch das `Batch-Processing` war es möglich, dass eine Mail erst Tage nach Erstellen des Links hinausgeschickt wird, und bei einer Standard-Ablaufdauer von zwei Tagen sind manche Links schon ungültig, bis sie den Mailserver erreichen. Ziel war es, die Änderung der Lebenszeit für Administratoren im User-Interface im Admin-Bereich möglich zu machen.
|
||||
|
||||
Technisch bedeutet das, dass die standardmäßig vorkonfigurierten `DataProtectionTokenProviderOptions` explizit konfiguriert werden müssen. [@andrewlock_token_lifetime] Der ASP.NET Core `UserManager`, welcher das generieren der Tokens übernimmt, verwendet einen `DataProtectorTokenProvider` und dieser wiederum kann mithilfe der `DataProtectionTokenProviderOptions` konfiguriert werden.
|
||||
|
||||
Es gibt 2 Möglichkeiten, wie man dieses Problem Lösen kann:
|
||||
Es gibt zwei Möglichkeiten, wie man dieses Problem lösen kann:
|
||||
|
||||
- `der Workaround`: Ein eigenes Modul, welches in seiner `Server/Startup.cs` die benötigten Werte korrekt setzt. Das hat den Vorteil, dass wir keine Änderungen im CMS selbst haben, sondern nur unsere eigene Erweiterung dafür schreiben. Andererseits könnte durch die undeterministische Ladereihenfolge eine `race-condition` auftreten. [@race_conditions_pdf] Darüber hinaus besteht kein gleichzeitiger Zugriff auf die appsettings.json und den IServiceProvider, in dem die Konfiguration gesetzt werden muss. => Nachdem wir in der Konfigurationsphase auch noch keinen Datenbankzugriff haben, können die Werte nicht aus der Datenbank geladen werden, sondern wir müssen auf eine Textdatei zurückgreifen.
|
||||
- `die saubere Lösung`: Eine Änderung im Kern von Oqtane. Also wird in unserem Fork von Oqtane die Konfigurationslogik für die Tokenlifetime implementiert. In diesem Fall könnte die Konfigurationslogik direkt in `OqtaneServiceCollectionExtensions.cs` hinzugefügt werden, da hier auch alle anderen Oqtane Spezifischen Konfigurationen gesetzt werden. Das hat den Vorteil, dass der Code aufgeräumter und sauberer ist und die `race-condition` verhindert werden kann. [@race_conditions_pdf] Der initiale Grund dagegen ist, dass wir ein weiteres Git Repository zum warten haben (den Fork vom Oqtane.Framework), welches jetzt nicht mehr mit Upstream Commit-gleich ist.
|
||||
- `die saubere Lösung`: Eine Änderung im Kern von Oqtane. Also wird in unserem Fork von Oqtane die Konfigurationslogik für die Token-Lifetime implementiert. In diesem Fall könnte die Konfigurationslogik direkt in `OqtaneServiceCollectionExtensions.cs` hinzugefügt werden, da hier auch alle anderen Oqtane-spezifischen Konfigurationen gesetzt werden. Das hat den Vorteil, dass der Code aufgeräumter und sauberer ist und die `race-condition` verhindert werden kann. [@race_conditions_pdf] Der initiale Grund dagegen ist, dass wir ein weiteres Git-Repository zu warten haben (den Fork vom Oqtane.Framework), welches jetzt nicht mehr mit Upstream commitgleich ist.
|
||||
|
||||
`Der Workaround` ist die Möglichkeit für die wir uns entschieden haben, allerdings ist das nicht die schönste Lösung. Eine eventuell nachfolgende Diplomarbeit kann an dieser Stelle ansetzen und `die saubere Lösung` implementieren.
|
||||
|
||||
@@ -608,11 +661,12 @@ Es gibt 2 Möglichkeiten, wie man dieses Problem Lösen kann:
|
||||
|
||||
\
|
||||
|
||||
Eine weitere Anforderung der Diplomarbeit war es Einträge in Modulen wie der `Hall of Fame`, dem `Schwarzen Brett` und dem Premium Bereich (`Engineer Applications`) melden zu können. Am Anfang war es wichtig, dass jeder schnell vorankommt, allerdings haben wir die Kommunikation Teamintern ein wenig verschlafen und dadurch ein paar Funktionen doppelt geschrieben. Dadurch kam es zu Inkonsistenzen in der Verwendung der unterschiedlichen Reporting Systeme. Deswegen haben wir uns am Ende für eine globales Reporting System entschieden.
|
||||
Eine weitere Anforderung der Diplomarbeit war es Einträge in Modulen wie der `Hall of Fame`, dem `Schwarzen Brett` und dem Premium Bereich (`Engineer Applications`) melden zu können. Am Anfang war es wichtig, dass jeder schnell vorankommt, allerdings haben wir die Kommunikation Teamintern ein wenig verschlafen und dadurch ein paar Funktionen doppelt geschrieben. Dadurch kam es zu Inkonsistenzen in der Verwendung der unterschiedlichen Reporting Systeme. Deswegen haben wir uns am Ende für ein globales Reporting-System entschieden.
|
||||
|
||||
Angestrebt wurde folgender Ablauf für das Melden eines Eintrags:
|
||||
|
||||
```mermaid
|
||||
%%| fig-cap: Reporting System: Ablaufdiagramm
|
||||
sequenceDiagram
|
||||
participant Module
|
||||
actor User
|
||||
@@ -630,11 +684,11 @@ sequenceDiagram
|
||||
ReportingComponent->>-User: Done
|
||||
```
|
||||
|
||||
Im oben dargestellten Ablaufdiagram werden das ReportingComponent und der ReportingHandler vom Reporting System über Dependency Injection bereitgestellt, nicht vom Modul selbst. Dadurch erreichen wir eine bessere Trennung der Zuständigkeiten und halten das S in SOLID ein: `Single responsibility`. Die Module sind jetzt nicht mehr für das Reporting selber verantwortlich, sondern müssen nur das Reportings System einbinden.
|
||||
Im oben dargestellten Ablaufdiagramm werden das Reporting-Component und der Reporting-Handler vom Reporting-System über Dependency Injection bereitgestellt, nicht vom Modul selbst. Dadurch erreichen wir eine bessere Trennung der Zuständigkeiten und halten das S in SOLID ein: `Single responsibility`. Die Module sind jetzt nicht mehr für das Reporting selbst verantwortlich, sondern müssen nur das Reporting-System einbinden.
|
||||
|
||||
Darüber hinaus erfüllt dieses Design das **Open/Closed Principle**: Das Reporting-System ist offen für Erweiterungen (neue Module können einfach andocken), aber geschlossen für Modifikationen (der Kern des Reporting-Systems muss nicht für jedes neue Modul geändert werden).
|
||||
|
||||
Damit DI funktioniert muss für den DI Consumer (`also das Modul, welches das Reporting System einbinden möchte`) das Interface zur Kompilierzeit zur Verfügung stehen. Um das zu erreichen habe ich eine neue Klassenbibliothek erstellt: Sie heißt `Interfaces`, wird per Gitea Actions automatisch in ein NuGet-Paket gebaut und in der `Gitea Actions NuGet Registry` veröffentlicht. Die Versionierung folgt dabei strikt den Git-Tags im Repository, was eine saubere Release-History ermöglicht. Dieses NuGet-Paket wird dann in jedem notwendigen Modul als Dependency hinzugefügt und damit kann man Modulübergreifend auf die Services und das `IReportingComponent` zugreifen.
|
||||
Damit DI funktioniert, muss für den DI-Consumer (also das Modul, welches das Reporting-System einbinden möchte) das Interface zur Kompilierzeit zur Verfügung stehen. Um das zu erreichen, habe ich eine neue Klassenbibliothek erstellt: Sie heißt `Interfaces`, wird per Gitea Actions automatisch in ein NuGet-Paket gebaut und in der `Gitea Actions NuGet Registry` veröffentlicht. Die Versionierung folgt dabei strikt den Git-Tags im Repository, was eine saubere Release-History ermöglicht. Dieses NuGet-Paket wird dann in jedem notwendigen Modul als Dependency hinzugefügt, und damit kann man modulübergreifend auf die Services und das `IReportingComponent` zugreifen.
|
||||
|
||||
Die Implementierung des `IReportingComponents` stellt nur eine Property (`ReportType`, welche den TypeName der Razor Komponente zurückliefert, damit `DynamicComponent` sie laden kann) und eine Methode (`ConstructParameterList`, welche das Parameter Dictionary erstellt. Nur zwecks Typensicherheit eingefügt) bereit. Mit dem `DynamicComponent` von Razor ist es möglich, per C# Code unterschiedliche Komponenten zu rendern und damit auch die per DI injizierte Klasse.
|
||||
|
||||
@@ -671,11 +725,11 @@ Die Kommunikation zwischen dem Client und dem Server erfolgt über einen REST-AP
|
||||
|
||||
\
|
||||
|
||||
```mermaid
|
||||
%%| filename: erd-event-registration
|
||||
%%| fig-cap: ER Diagramm des Event Registration Moduls
|
||||
``` {.mermaid width=50%}
|
||||
erDiagram
|
||||
direction LR
|
||||
%%| filename: erd-event-registration
|
||||
%%| fig-cap: ER Diagramm des Event Registration Moduls
|
||||
EVENT ||--o{ RESPONSE : "has"
|
||||
EVENT {
|
||||
int EventId PK
|
||||
@@ -710,8 +764,6 @@ erDiagram
|
||||
|
||||
\
|
||||
|
||||
# TODO: Bild vom Grafen hier einfügen
|
||||
|
||||
Ein wesentlicher Teil der administrativen Ansicht ist die Visualisierung der Anmeldezahlen. Hierfür wurde eine Integration von Chart.js realisiert, um den aktuellen Stand der Rückmeldungen grafisch aufzubereiten.
|
||||
|
||||
Um die Brücke zwischen dem C#-basierten Blazor-Frontend und der JavaScript-Bibliothek Chart.js zu schlagen, wurde ein dedizierter Interop-Service implementiert. Der JS-Interop-Layer ist zwar standardmäßig in Oqtane-Modulen vorgesehen, wurde jedoch in diesem Modul zum ersten Mal angepasst und produktiv eingesetzt. Der Ablauf der grafischen Darstellung gestaltet sich wie folgt:
|
||||
@@ -720,7 +772,9 @@ Um die Brücke zwischen dem C#-basierten Blazor-Frontend und der JavaScript-Bibl
|
||||
2. JS-Interop: Über die `CreateChart`-Methode der Interop-Klasse wird die JavaScript-Funktion `createChart` in der `Module.js` aufgerufen. Dabei werden die aggregierten Daten, Beschriftungen und Konfigurationsoptionen übergeben.
|
||||
3. Canvas-Rendering: Die JavaScript-Logik erzeugt dynamisch ein HTML5-canvas-Element innerhalb eines Container-Divs und initialisiert daraufhin die Chart.js-Instanz, welche ein übersichtliches Pie-Chart mit den Registrierungsstatistiken rendert.
|
||||
|
||||
Durch diese Trennung bleibt die Geschäftslogik im C#-Code, während für die performante und ansprechende Darstellung auf etablierte Web-Technologien zurückgegriffen wird.
|
||||
Durch diese Trennung bleibt die Geschäftslogik im C#-Code, während für die performante und ansprechende Darstellung auf etablierte Web-Technologien zurückgegriffen wird.
|
||||
|
||||
{ width=40% fig-pos=H }
|
||||
|
||||
### Schwarzes Brett
|
||||
|
||||
@@ -730,16 +784,15 @@ Das Modul "Schwarzes Brett" dient als digitale Anschlagtafel für den Absolvente
|
||||
|
||||
\
|
||||
|
||||
{ latex-placement="ht" }
|
||||
|
||||
<!-- ![Detailansicht eines Eintrags auf dem Schwarzen Brett][img-ref] -->
|
||||
|
||||
Die Anzeige der Einträge erfolgt in einer responsiven Grid-Ansicht (Index-Komponente), wobei jeder Eintrag als Karte (Card) dargestellt wird. Dieses Design sorgt für eine übersichtliche Präsentation auch bei einer größeren Anzahl von Mitteilungen.
|
||||
|
||||
- Bilderunterstützung: Das Modul nutzt die Oqtane-interne Dateiverwaltung. Wenn ein Bild für einen Eintrag hochgeladen wurde, wird dieses über einen Image-Proxy skaliert und als Vorschaubild angezeigt. Fehlt ein Bild, wird ein konsistenter Platzhalter verwendet, um das visuelle Gleichgewicht der Grid-Ansicht zu wahren.
|
||||
- Detailansicht: Die Details-Komponente bietet eine fokussierte Ansicht des Eintrags mit vollständiger HTML-Beschreibung. Für die Eingabe und Formatierung der Texte wird auf die von Oqtane standardmäßig bereitgestellten Rich-Text-Editoren zurückgegriffen, was eine konsistente Nutzerführung im gesamten CMS gewährleistet. Ergänzt wird dies durch Metadaten wie Erstellungsdatum und Autor.
|
||||
{ width=70% fig-pos=H }
|
||||
|
||||
<!-- [img-ref]: BlackBoard-Details.png "Detailansicht eines Eintrags auf dem Schwarzen Brett" -->
|
||||
Bilderunterstützung: Das Modul nutzt die Oqtane-interne Dateiverwaltung. Wenn ein Bild für einen Eintrag hochgeladen wurde, wird dieses über einen Image-Proxy skaliert und als Vorschaubild angezeigt. Fehlt ein Bild, wird ein konsistenter Platzhalter verwendet, um das visuelle Gleichgewicht der Grid-Ansicht zu wahren.
|
||||
|
||||
Detailansicht: Die Details-Komponente bietet eine fokussierte Ansicht des Eintrags mit vollständiger HTML-Beschreibung. Für die Eingabe und Formatierung der Texte wird auf die von Oqtane standardmäßig bereitgestellten Rich-Text-Editoren zurückgegriffen, was eine konsistente Nutzerführung im gesamten CMS gewährleistet. Ergänzt wird dies durch Metadaten wie Erstellungsdatum und Autor.
|
||||
|
||||
{ width=70% fig-pos=H }
|
||||
|
||||
#### Automatisierter E-Mail-Digest
|
||||
|
||||
@@ -747,33 +800,34 @@ Die Anzeige der Einträge erfolgt in einer responsiven Grid-Ansicht (Index-Kompo
|
||||
|
||||
Um die Mitglieder regelmäßig über neue Inhalte zu informieren, wurde ein automatisierter `Cronjob` implementiert. Dieser Job läuft im Hintergrund des Oqtane-Frameworks und führt folgende Schritte aus:
|
||||
|
||||
- Filterung: Der Job identifiziert alle Einträge, die seit dem letzten Versand erstellt wurden.
|
||||
- Zielgruppenselektion: Es werden alle Benutzer identifiziert, die der Rolle "Absolventen" angehören.
|
||||
- Zusammenstellung: Für jeden dieser Benutzer wird eine personalisierte Email-Notification generiert, welche eine Zusammenfassung der neuen Einträge enthält.
|
||||
- Versand: Die generierten Notifications werden in die Warteschlange der Notification-Infrastruktur eingereiht und sukzessive versendet.
|
||||
Integration des Reporting-Systems
|
||||
- **Filterung**: Der Job identifiziert alle Einträge, die seit dem letzten Versand erstellt wurden.
|
||||
- **Zielgruppenselektion**: Es werden alle Benutzer identifiziert, die der Rolle "Absolventen" angehören.
|
||||
- **Zusammenstellung**: Für jeden dieser Benutzer wird eine personifizierte E-Mail-Notification generiert, welche eine Zusammenfassung der neuen Einträge enthält.
|
||||
- **Versand**: Die generierten Notifications werden in die Warteschlange der Notification-Infrastruktur eingereiht und sukzessive versendet.
|
||||
|
||||
#### Reporting System
|
||||
#### Integration des Reporting-Systems
|
||||
|
||||
\
|
||||
|
||||
Ein wichtiges Merkmal des Schwarzen Bretts zur Sicherstellung der Inhaltsqualität ist die Anbindung an das globale Reporting-System (siehe 5.4). In der Detailansicht wird über Dependency Injection die IReportUI-Komponente eingebunden. Mithilfe der DynamicComponent von Blazor wird die Melde-Funktion nahtlos in die Oberfläche des Moduls integriert. Dadurch können unangemessene Inhalte direkt von Benutzern gemeldet werden.
|
||||
|
||||
{ width=70% fig-pos=H }
|
||||
|
||||
#### Technischer Hintergrund
|
||||
|
||||
\
|
||||
|
||||
Auf der Serverseite folgt das Modul dem etablierten Muster mit einem `BlackBoardRepository` für den effizienten Datenbankzugriff und einem `BlackBoardController` für die API-Bereitstellung. Die Implementierung des Scheduled Jobs als HostedServiceBase ermöglicht eine tiefe Integration in die Oqtane-Infrastruktur bei gleichzeitig geringem Ressourcenverbrauch.
|
||||
|
||||
## Learnings
|
||||
## Learnings {#sec:kh-learnings}
|
||||
|
||||
### Produktion != Staging
|
||||
|
||||
Ein Learning, welches doch relativ schnell aufkam ist im Bereich der IT eigentlich kein unbekanntes. Wir hatten dieses Learning relativ bald, im Frühling 2025, als die ersten Probleme mit dem Deployment von Oqtane aufkamen. Oqtane war zwar in unserer Entwicklungsumgebung sehr einfach zum einrichten gewesen, das Deployment in der Cloud vom Hetzner war jedoch geplagt von Problemen. Im Zeitraum von Mai bis Okober hatten wir keine laufende Produktivumgebung. Dadurch sind wir mit dieser Diplomarbeit auch in [Zeitverzug](#arbeitszeiteinschätzung-zeitverzug) gekommen. Hätte ich mich vor dem Start der Diplomarbeit mit dem Deployment von Oqtane auseinander gesetzt, dann wäre das in [Fehlende Dokumentation](#fehlende-dokumentation) beschriebene Problem früher aufgekommen und der Zeitverzug wäre nicht so groß, oder noch ganz vermeidbar gewesen.
|
||||
Ein Learning, welches doch relativ schnell aufkam, ist im Bereich der IT eigentlich kein unbekanntes. Wir hatten dieses Learning relativ bald, im Frühling 2025, als die ersten Probleme mit dem Deployment von Oqtane aufkamen. Oqtane war zwar in unserer Entwicklungsumgebung sehr einfach einzurichten gewesen, das Deployment in der Cloud von Hetzner war jedoch geplagt von Problemen. Im Zeitraum von Mai bis Oktober hatten wir keine laufende Produktivumgebung. Dadurch sind wir mit dieser Diplomarbeit auch in [Zeitverzug](#arbeitszeiteinschätzung-zeitverzug) gekommen. Hätte ich mich vor dem Start der Diplomarbeit mit dem Deployment von Oqtane auseinandergesetzt, dann wäre das in [Fehlende Dokumentation](#fehlende-dokumentation) beschriebene Problem früher aufgekommen und der Zeitverzug wäre nicht so groß oder noch ganz vermeidbar gewesen.
|
||||
|
||||
### Teamleitung (Motivation / Downsizing)
|
||||
|
||||
Nachdem ich mich von Anfang an volkommen in das Deploymentproblem von Oqtane gestürzt habe, habe ich meine Rolle als Teamleitung etwas schleifen lassen. Dadurch fehlte bei einigen Teammitgliedern initial die Identifikation mit dem Projekt und in weitererfolge auch die Motivation an diesem Projekt mitzuarbeiten. Nachdem im Verlauf des Frühlings und über den Sommer von der hälfte des Teams trotz Besprechungen und Mahnungen keine Beiträge zu dem Projekt kamen, haben Hr. Prof. Gürth und ich uns dazu entschieden uns von 2 Personen vor unterschreiben des Projektantrages zu trennen. Grund dazu war die Angst, die mangelnde Motivation zieht das restliche Team mit hinunter. Wir wollten uns trotz des Downsizings nicht an Funktionalitäten sparen und haben uns für das nächste halbe bis dreiviertel Jahr einen ziemlich strikten Zeitplan vorgenommen.
|
||||
Nachdem ich mich von Anfang an vollkommen in das Deploymentproblem von Oqtane gestürzt habe, habe ich meine Rolle als Teamleitung etwas schleifen lassen. Dadurch fehlte bei einigen Teammitgliedern initial die Identifikation mit dem Projekt und in weiterer Folge auch die Motivation, an diesem Projekt mitzuarbeiten. Nachdem im Verlauf des Frühlings und über den Sommer von der Hälfte des Teams trotz Besprechungen und Mahnungen keine Beiträge zu dem Projekt kamen, haben Hr. Prof. Gürth und ich uns dazu entschieden, uns von zwei Personen vor dem Unterschreiben des Projektantrages zu trennen. Grund dazu war die Angst, die mangelnde Motivation zieht das restliche Team mit hinunter. Wir wollten uns trotz des Downsizings nicht an Funktionalitäten sparen und haben uns für das nächste halbe bis dreiviertel Jahr einen ziemlich strikten Zeitplan vorgenommen.
|
||||
|
||||
### Arbeitszeiteinschätzung (Zeitverzug)
|
||||
|
||||
@@ -785,7 +839,7 @@ Es gibt mehrere Gründe dafür:
|
||||
|
||||
\
|
||||
|
||||
- `Fehlende oder nur schlechte Dokumentation von Oqtane`: Einige Probleme im Deployment wurden in langer und mühseliger Arbeit auseinander gebrochen und in weitere immer kleinere Probleme unterteilt. Dadurch, dass wir alle keine Erfahrung mit der Entwicklung und dem Deployment von ASP.NET Code Anwendungen hatten und die Dokumentation doch schlecht war, blieb uns manchmal nichts anderes übrig als mit WireShark den Netzwerktraffic mit zu schneiden und nebenbei im Git Repository die geloggten Zeilen Code zu finden und so das Framework von innen heraus kennen zu lernen. Dadurch hatte ich dann nach einer Einarbeitungszeit von 4 Monaten ziemlich jede Stelle im Sourcecode von Oqtane gesehen und finde mich um das schneller zurecht.
|
||||
- `Fehlende oder nur schlechte Dokumentation von Oqtane`: Einige Probleme im Deployment wurden in langer und mühseliger Arbeit auseinandergebrochen und in weitere immer kleinere Probleme unterteilt. Dadurch, dass wir alle keine Erfahrung mit der Entwicklung und dem Deployment von ASP.NET-Core-Anwendungen hatten und die Dokumentation doch schlecht war, blieb uns manchmal nichts anderes übrig, als mit WireShark den Netzwerktraffic mitzuschneiden und nebenbei im Git-Repository die geloggten Codezeilen zu finden und so das Framework von innen heraus kennenzulernen. Dadurch hatte ich dann nach einer Einarbeitungszeit von vier Monaten ziemlich jede Stelle im Sourcecode von Oqtane gesehen und finde mich umso schneller zurecht.
|
||||
- `Team-Konsolidierung`: Durch das notwendige Downsizing des Teams mussten Aufgaben neu verteilt werden, was die individuelle Arbeitslast erhöhte und die Konzentration auf die Kernentwicklung zeitweise verzögert hat.
|
||||
- `Abhängigkeit von der Infrastruktur`: Dadurch, dass wir bis in den Oktober / November hinein nicht wussten, ob wir weiter bei Oqtane bleiben können, haben die anderen Teammitglieder nicht mit der sinnvollen Entwicklung ihrer Module starten können. Zitat: "Und was wenn wir am Ende doch noch das CMS umstellen müssen?" => Auch wenn der Auftrag war, mit der Modulentwicklung zu starten war die Motivation meiner Teammitglieder nicht so hoch. Selbst wenn sie nicht direkt von der Infrastruktur mit der Ausführung ihrer Aufgaben abhängig waren, motiviert waren sie wegen der Umstände auch nicht.
|
||||
|
||||
@@ -797,7 +851,7 @@ Um das Projektziel dennoch zu erreichen, wurde der Zeitplan im Herbst 2025 massi
|
||||
`90% fertig, oder fertig?`: Es gibt einige "Regeln", wie: das `Paretoprinzip`, `Hofstadter’s Law` und die `90-90 Regel`. Letztere wurde im Jahr 1985 von Jon Bentley in einer Kolumne "Programming pearls" veröffentlicht. Ausgeschrieben lautet sie:
|
||||
|
||||
> [Rule of Credibility] The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.
|
||||
> (Jon Bentley. 1985. Programmimg pearls. Commun. ACM 28, 9 (Sept. 1985), 896–901. https://doi.org/10.1145/4284.315122) [@bentley1985programming]
|
||||
> [@bentley1985programming]
|
||||
> Diese Diplomarbeit liefert weitere Evidenz, dass diese Faustregel stimmt.
|
||||
|
||||
### Sprints und Meetings (in Zukunft ja asynchron)
|
||||
@@ -810,8 +864,21 @@ Ein zentrales Problem in unserer ursprünglichen Arbeitsweise war die Kopplung v
|
||||
|
||||
Lösungsansatz: Meetings und Besprechungen asynchron zueinander setzen.
|
||||
|
||||
- Asynchrone Daily-Updates: Statusberichte erfolgen schriftlich (z. B. in Gitea Issues oder YouTrack), nicht mehr in stundenlangen Call-Marathons. Das nimmt den zeitlichen Druck vom einzelnen Entwickler. Oder zumindest in kurzen Commitnachrichten, welche am Ende des Tages automatisch an alle Teammitglieder zum Überblick gesendet werden (eventuell mit \@username tagging, um eine Person nochmal genau anzusprechen)
|
||||
- Asynchrone Daily-Updates: Statusberichte erfolgen schriftlich (z. B. in Gitea Issues oder YouTrack), nicht mehr in stundenlangen Call-Marathons. Das nimmt den zeitlichen Druck vom einzelnen Entwickler. Oder zumindest in kurzen Commitnachrichten, welche am Ende des Tages automatisch an alle Teammitglieder zum Überblick gesendet werden (eventuell mit \@username-Tagging, um eine Person nochmal genau anzusprechen).
|
||||
- Review-First-Policy: Ein Feature gilt erst dann als „fertig“, wenn es einen asynchronen Code-Review-Prozess durchlaufen hat. Das Meeting dient nur noch der Klärung von Blockern, nicht der Präsentation von Code. Das war eigentlich schon von Anfang an in unserer `Definition of Done` festgelegt worden.
|
||||
- Entkoppelung von Meeting und Deadline: Meetings sollten der Synchronisation dienen, während die Abgabe von Arbeitspaketen kontinuierlich (Continuous Integration) erfolgen muss, um Lastspitzen (in der [Gitea Actions](#continuous-integration) Pipeline) am Tag der Besprechung zu vermeiden.
|
||||
- Entkoppelung von Meeting und Deadline: Meetings sollten der Synchronisation dienen, während die Abgabe von Arbeitspaketen kontinuierlich (Continuous Integration) erfolgen muss, um Lastspitzen (in der [Gitea Actions](#sec:continuous-integration) Pipeline) am Tag der Besprechung zu vermeiden.
|
||||
|
||||
\pagebreak
|
||||
## Fazit
|
||||
|
||||
Die Entwicklung des AlumniHubs auf Basis von Blazor und Oqtane war eine Reise geprägt von technischer Tiefe, organisatorischen Herausforderungen und wertvollen Erkenntnissen über moderne Software-Architektur. Rückblickend lässt sich festhalten, dass die Wahl des .NET-Stacks sowohl die erwarteten Stärken als auch unerwartete Hürden mit sich brachte.
|
||||
|
||||
Technisch gesehen haben sich die statische Typisierung von C# und das integrierte Dependency Injection Framework als äußerst wertvolle Werkzeuge erwiesen. Sie haben die Entwicklung komplexer, modularer Strukturen – wie des generischen *Reporting Systems* – erheblich vereinfacht und für eine hohe Konsistenz gesorgt. Dennoch zeigt der Vergleich zu anderen Stacks wie React und Go, dass Architektur-Vorteile nicht exklusiv an ein einzelnes Ökosystem gebunden sein müssen. Die Erfahrung mit Protobufs in anderen Kontexten verdeutlicht, dass eine sprachenagnostische Typisierung oft flexibler ist, ohne die Bindung an ein spezifisches Framework-Ökosystem zu erzwingen. .NET bleibt jedoch eine absolut valide und stabile Wahl für Projekte dieser Größenordnung.
|
||||
|
||||
Ein zentraler Aspekt der Reflexion betrifft den Entwicklungsprozess. Die Erkenntnis, dass eine strikte Review-Kultur und eine frühzeitige CI/CD-Automatisierung essenziell sind, kam erst im Verlauf des Projekts voll zum Tragen. Initial fehlende Strukturen führten dazu, dass Module oft unreflektiert hochgeladen wurden, was die Qualitätssicherung erschwerte. Für zukünftige Projekte wäre ein „Automation-First“-Ansatz die oberste Priorität.
|
||||
|
||||
In organisatorischer Hinsicht war die Verkleinerung des Teams ein Wendepunkt. Trotz der gestiegenen individuellen Arbeitslast führte das „Downsizing“ zu einer signifikant höheren Identifikation mit dem Projekt und einer gesteigerten Effizienz. Die klarere Verantwortung jedes einzelnen Mitglieds sorgte für eine Dynamik, die im größeren, weniger fokussierten Team nicht erreicht werden konnte.
|
||||
|
||||
Persönlich bleibt vor allem die fünfmonatige Auseinandersetzung mit der Deployment-Problematik im Gedächtnis. Dass die Lösung für eine komplexe Infrastruktur-Hürde schließlich in einem unerwarteten Moment außerhalb der Arbeitsumgebung – fast schon ironisch – auftauchte, unterstreicht eine wichtige Lektion für jeden Entwickler: Beharrlichkeit ist notwendig, aber oft braucht es auch den nötigen Abstand, um den entscheidenden Blickwinkel zu finden.
|
||||
|
||||
Abschließend lässt sich sagen, dass der AlumniHub nicht nur eine funktionsfähige Plattform für den Absolventenverein darstellt, sondern für mich persönlich als Beweis für die Bedeutung von technischer Neugier, architektonischer Weitsicht und der Fähigkeit zur kritischen Selbstreflexion dient.
|
||||
(Mehr dazu unter [Learnings](#sec:kh-learnings))
|
||||
|
Before Width: | Height: | Size: 351 KiB After Width: | Height: | Size: 351 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 471 KiB After Width: | Height: | Size: 471 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
BIN
Diplomarbeitsbuch/images/05-Konstantin/BlackBoard-Details.png
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
Diplomarbeitsbuch/images/05-Konstantin/BlackBoard-Overview.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
Diplomarbeitsbuch/images/05-Konstantin/Brevo.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 12 KiB |
BIN
Diplomarbeitsbuch/images/05-Konstantin/GiteaActions-Overview.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
Diplomarbeitsbuch/images/05-Konstantin/GiteaActions-Releases.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
Diplomarbeitsbuch/images/05-Konstantin/GiteaIssues-TaskBoard.png
Normal file
|
After Width: | Height: | Size: 459 KiB |
|
After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 344 KiB After Width: | Height: | Size: 344 KiB |
BIN
Diplomarbeitsbuch/images/preamble/logo-short.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
Diplomarbeitsbuch/images/preamble/logo.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
Diplomarbeitsbuch/images/preamble/szu.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
28
Diplomarbeitsbuch/pandoc-cmd.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
pandoc \
|
||||
00-praemble.md \
|
||||
01-toc.md \
|
||||
02-Allgemein.md \
|
||||
03-Diplomarbeitsbuch-individueller-teil-Adam-Gaiswinkler.md \
|
||||
04-Diplomarbeitsbuch-individueller-teil-Florian-Edlmayer.md \
|
||||
05-Diplomarbeitsbuch-individueller-teil-Konstantin-Hintermayer.md \
|
||||
97-tabellenverzeichnis.md \
|
||||
98-abbildungsverzeichnis.md \
|
||||
99-bibliographie.md \
|
||||
--number-sections \
|
||||
--lua-filter ../_extensions/diagram/diagram.lua \
|
||||
--syntax-definition ../_extensions/razor/razor.xml \
|
||||
--syntax-definition ../_extensions/nginx/nginx.xml \
|
||||
--citeproc \
|
||||
--bibliography sources.bib \
|
||||
--csl ../_extensions/sources/tgm.csl \
|
||||
--include-before-body 00_preamble.tex \
|
||||
-H ../_extensions/header/header.tex \
|
||||
-V geometry:"top=2.5cm, bottom=2cm, left=3cm, right=2cm, a4paper" \
|
||||
-V toc-title="Inhaltsverzeichnis" \
|
||||
-V classoption=twoside \
|
||||
-V fontsize=12pt \
|
||||
-V linestretch=1.5 \
|
||||
-o diplomarbeitsbuch.pdf
|
||||
# --toc \
|
||||
# --toc-depth=3 \
|
||||
@@ -257,3 +257,26 @@
|
||||
year = {2024},
|
||||
urldate = {2026-03-19}
|
||||
}
|
||||
@online{jetbrains_rider,
|
||||
title = {JetBrains Rider},
|
||||
url = {https://www.jetbrains.com/rider/},
|
||||
author = {{JetBrains}},
|
||||
year = {2026},
|
||||
urldate = {2026-03-17}
|
||||
}
|
||||
|
||||
@online{oqtane_framework_site,
|
||||
title = {Oqtane Framework},
|
||||
url = {https://www.oqtane.org/},
|
||||
author = {{Oqtane Foundation}},
|
||||
year = {2026},
|
||||
urldate = {2026-03-17}
|
||||
}
|
||||
|
||||
@online{oqtane_docs_dev,
|
||||
title = {Oqtane Developer Documentation},
|
||||
url = {https://docs.oqtane.org/},
|
||||
author = {{Oqtane Foundation}},
|
||||
year = {2026},
|
||||
urldate = {2026-03-17}
|
||||
}
|
||||
22
Video_Text_Skript.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Video Text Skript
|
||||
|
||||
Anfang: Willkommen zu unserem Video über den AlumniHub. Wir sind Konstantin Hintermayer, Florian Edlmayer und Adam Gaiswinkler und wir haben im Rahmen unserer Diplomarbeit an der HTL SZU Ungargasse eine moderne Webanwendung für den Absolventenverein entwickelt.
|
||||
Zu beginn unseres Projekts sind wir auf viele Probleme gestoßen. Im Sommer beschäftigten wir uns mit einer Übergangslösung um das kommende Treffen der Absolventen im Jahr 2025 zu ermöglichen. Ein weiteres Problem war unser Team Downsizing von 6 auf 3 Mitglieder. Dadurch mussten wir unsere ursprünglichen Pläne stark überdenken und uns auf das Wesentliche konzentrieren.
|
||||
Außerdem sind wir immer wieder auf Probleme mit unserer Serverinfrastruktur gestoßen.
|
||||
|
||||
Ein zentraler Teil unserer Arbeit ist die kontinuierliche Integration unserer Software. Wir haben uns für Git als Versionsverwaltungssystem entschieden und hosten eine Gitea Instanz. Bei veröffentlichen eines tags wird automatisch ein neues Debian Paket gebaut und in unsererem Debian Package Registry bereitgestellt.Durch diese automatisierung ist die veröffentlichung von neuen Softwareversionen stark vereinfacht worden.
|
||||
|
||||
Das Hauptziel des Projektes war es eine moderne Webanwendung für den Absolvenntenverein zu kreieren. Die es ermöglicht einfach Events und treffen zu organisieren mithilfe unseres EventRegistration Moduls. Weiter Funktionen sind die Hall of Fame, wo Absolventen ihre Erfolge präsentieren können, das Schwarze Brett für Neuigkeiten und Jobangebote und der Premiumbereich für exklusive Inhalte. Diese sind im Laufe der Entwicklung hinzugekommen.
|
||||
|
||||
Nun wollen wir Ihnen unsere Webanwendung genauer vorstellen.
|
||||
|
||||
EventRegistration Modul:
|
||||
|
||||
|
||||
Hall of Fame Modul:
|
||||
|
||||
|
||||
Schwarzes Brett Modul:
|
||||
|
||||
|
||||
Premiumbereich Modul:
|
||||
@@ -564,6 +564,7 @@ local function code_to_figure (conf)
|
||||
-- Check if a converter exists for this block. If not, return the block
|
||||
-- unchanged.
|
||||
local diagram_type = block.classes[1]
|
||||
print("Diagram type: ", diagram_type)
|
||||
if not diagram_type then
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
\usepackage{float}
|
||||
\floatplacement{figure}{H}
|
||||
\raggedbottom
|
||||
\usepackage{etoolbox}
|
||||
\makeatletter
|
||||
\patchcmd{\LT@array}{\tabskip\z@}{\tabskip\fill}{}{}
|
||||
@@ -12,7 +15,9 @@
|
||||
|
||||
\usepackage[hyphens]{url}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\setlength{\emergencystretch}{3em} % Prevent overfull lines
|
||||
\usepackage[htt]{hyphenat}
|
||||
\usepackage{microtype}
|
||||
\setlength{\emergencystretch}{5em} % Increased to solve overfull lines
|
||||
|
||||
\usepackage{tocloft}
|
||||
|
||||
|
||||
31
defensio.md
Normal file
@@ -0,0 +1,31 @@
|
||||
% Habits
|
||||
% John Doe
|
||||
% March 22, 2005
|
||||
|
||||
# In the morning
|
||||
|
||||
## Getting up
|
||||
|
||||
- Turn off alarm
|
||||
- Get out of bed
|
||||
|
||||
## Breakfast
|
||||
|
||||
- Eat eggs
|
||||
- Drink coffee
|
||||
|
||||
# In the evening
|
||||
|
||||
## Dinner
|
||||
|
||||
- Eat spaghetti
|
||||
- Drink wine
|
||||
|
||||
------------------
|
||||
|
||||

|
||||
|
||||
## Going to sleep
|
||||
|
||||
- Get in bed
|
||||
- Count sheep
|
||||
|
Before Width: | Height: | Size: 508 KiB |
4
pandoc-cmd.sh → pandoc-tex.sh
Executable file → Normal file
@@ -23,6 +23,4 @@ pandoc \
|
||||
-V classoption=twoside \
|
||||
-V fontsize=12pt \
|
||||
-V linestretch=1.5 \
|
||||
-o diplomarbeitsbuch.pdf
|
||||
# --toc \
|
||||
# --toc-depth=3 \
|
||||
-o diplomarbeitsbuch.tex
|
||||