Compare commits

...

30 Commits

Author SHA1 Message Date
e4cf3cb00d Mermaid Diagramme hinzugefügt
Some checks failed
Word Count / count-words (push) Failing after 30s
2026-03-19 14:30:37 +01:00
fd51d7c79e Bei mir Scrum entfernt
Some checks failed
Word Count / count-words (push) Failing after 31s
2026-03-19 13:38:58 +01:00
1611ca620e Projektmanagment mit scrum hinzugefügt
Some checks failed
Word Count / count-words (push) Failing after 31s
2026-03-19 13:37:29 +01:00
d410f72fb8 Ki review eingearbeitet
Some checks failed
Word Count / count-words (push) Failing after 30s
2026-03-19 13:22:14 +01:00
c421a4fd8f Merge pull request 'New: Danksagung' (#68) from danksagung into main
Some checks failed
Word Count / count-words (push) Failing after 30s
Reviewed-on: #68
2026-03-19 07:23:55 +00:00
0b774f00b7 Dassler...
All checks were successful
Word Count / count-words (pull_request) Successful in 31s
2026-03-19 07:23:43 +00:00
a2c756e4de Merge pull request 'kh-blazor-razor' (#66) from kh-blazor-razor into main
Some checks failed
Word Count / count-words (push) Failing after 32s
Reviewed-on: #66
2026-03-19 07:22:46 +00:00
4559b758a7 Fix: Broken commit marker
All checks were successful
Word Count / count-words (pull_request) Successful in 31s
2026-03-18 22:17:17 +01:00
43f5104a4e Fix: Typos and move Sources into the end
All checks were successful
Word Count / count-words (pull_request) Successful in 33s
2026-03-18 22:13:25 +01:00
bc9835567d Update Diplomarbeitsbuch-individueller-teil-Konstantin-Hintermayer.md 2026-03-18 22:11:40 +01:00
53e6ca0205 New: Schwarzes Brett 2026-03-18 22:11:40 +01:00
fd61a18141 Update: Überschriftsnummerierung 2026-03-18 22:11:40 +01:00
f14d39be25 New: EventRegistration Modul 2026-03-18 22:11:40 +01:00
a9d2d3626b New: Projektmanagement: Git und Gitea 2026-03-18 22:11:30 +01:00
6b5c524f36 Update: Motivation 2026-03-18 22:10:48 +01:00
7970ec6a9d Update: TOC / Struktur in dem Buch 2026-03-18 22:10:33 +01:00
05125e8b86 Quellen: Tokenlifetime und E-Mail Tippfehler und Workaround tippfehler 2026-03-18 22:08:16 +01:00
7d22c3281f New: Dependency Injection Grundlagen & Einleitung 2026-03-18 22:00:48 +01:00
3949ff6c19 Umschreiben der CMS Vergleiche 2026-03-18 22:00:48 +01:00
0d4ccdaa47 Individueller Teil - Konstantin Hintermayer: Korrektur 1/x 2026-03-18 22:00:16 +01:00
1c1949381b Update: Reporting System 2026-03-18 21:58:19 +01:00
a535e73c3f New: Reporting System 2026-03-18 21:58:19 +01:00
4df7cc1cf7 New: Token Lifetime 2026-03-18 21:58:19 +01:00
978f5579fb Update Diplomarbeitsbuch-individueller-teil-Konstantin-Hintermayer.md 2026-03-18 21:58:19 +01:00
46808af2b7 Update Diplomarbeitsbuch-individueller-teil-Konstantin-Hintermayer.md 2026-03-18 21:58:19 +01:00
02ad58b97b Arbeitszeiteinschätzung 2026-03-18 21:58:19 +01:00
d59aa847f1 Kommunikations zwischen FE und BE, SignalR, Produktion != Staging und Teamleitung und Downsing 2026-03-18 21:58:19 +01:00
e57e821ead KH: Blazor beschreibung 2026-03-18 21:58:19 +01:00
6485ed6149 Update Diplomarbeitsbuch-individueller-teil-Konstantin-Hintermayer.md 2026-03-18 21:58:19 +01:00
d6b360a0f8 New: Danksagung
All checks were successful
Word Count / count-words (pull_request) Successful in 32s
Gemini Writing Review / gemini-review (pull_request) Successful in 1m9s
2026-03-13 22:25:12 +00:00
3 changed files with 616 additions and 172 deletions

79
Allgemein.md Normal file
View File

@@ -0,0 +1,79 @@
## Danksagung
Obwohl die Umsetzung dieses Projektes durch das Projektteam selbst erfolgte, gab es eine Reihe an Personen, die uns tatkräftig unterstützt haben.
An erster Stelle möchten wir uns bei Herrn Prof. Thomas Gürth und Herrn Prof. Johannes Kreuzer bedanken. Ohne Ihre umfangreiche Unterstützung, Kreativität und fachliche Kompetenz wäre das Projekt in dieser Form nicht realisierbar gewesen. Sie beide haben uns durch dieses Projekt begleitet, uns mit wertvollen Ideen und Hilfestellungen versorgt und uns gleichzeitig den notwendigen Freiraum für eigenständiges Lernen und Arbeiten gelassen.
Neben einer exzellenten Betreuung bedarf eine Diplomarbeit auch eines engagierten Auftraggebers. Bei Lukas Aigner bedanken wir uns für das Vertrauen in unser Team und die Ermöglichung dieses Projektes. Trotz zeitlicher Verzögerungen im Rahmen der Arbeit, erfuhren wir von seiner Seite großes Verständnis und fanden stets eine konstruktive Basis für Diskussionen vor.
Ein besonders komplexer Aspekt dieser Arbeit war die Infrastruktur, für die im Prozess drei verschiedene Lösungen evaluiert wurden. Wir danken Stefan Reinel und dem Team von LiveDesign für die bereitwillige Unterstützung. Ohne die aktuelle Infrastruktur hätten wir bis heute keine zufriedenstellende Lösung für unsere Homepage gefunden.
Als wir im Oktober kurzfristig eine neue Produktionsumgebung benötigten, wurde uns unbürokratisch durch die Schule geholfen. Herr Prof. Harald Dassler und Herr Prof. Andreas Resch haben uns zur Weiterentwicklung eine virtuelle Maschine zur Verfügung gestellt und den externen Zugriff ermöglicht. Es ist nicht selbstverständlich, dass in einer Institution dieser Größe ein solcher Wunsch so schnell und unkompliziert umgesetzt wird.
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.
# Projektmanagement mit Scrum
## Grundlagen der Scrum-Methode
Für die Organisation und Umsetzung des Projekts wurde das agile Projektmanagement-Framework Scrum verwendet. Scrum ist ein weit verbreitetes Vorgehensmodell in der Softwareentwicklung, das besonders für Projekte geeignet ist, bei denen sich Anforderungen im Laufe der Entwicklung verändern können. Im Gegensatz zu klassischen Projektmanagementmethoden arbeitet Scrum nicht mit einer vollständig im Voraus geplanten Entwicklung, sondern mit kurzen, wiederkehrenden Entwicklungszyklen.
Das zentrale Element von Scrum ist der sogenannte Sprint. Ein Sprint stellt einen fest definierten Zeitraum dar, in dem bestimmte Funktionen oder Anforderungen umgesetzt werden. In diesem Projekt betrug die Dauer eines Sprints zwei Wochen. Innerhalb dieses Zeitraums arbeitete das Entwicklungsteam daran, ausgewählte Aufgaben zu implementieren und am Ende des Sprints ein funktionsfähiges Ergebnis zu präsentieren.
Die agile Arbeitsweise von Scrum basiert auf einer iterativen und inkrementellen Entwicklung. Das bedeutet, dass die Software Schritt für Schritt erweitert wird. Nach jedem Sprint steht eine neue Version der Anwendung zur Verfügung, die zusätzliche Funktionen enthält. Dadurch können Änderungen oder neue Anforderungen flexibel in zukünftige Sprints integriert werden.
Die grundlegende Struktur und der Ablauf eines Scrum-Projekts sind in Abbildung X dargestellt.
![Scrum-Framework](image-2.png)
*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.
Während der Sprintplanung wählt das Entwicklungsteam gemeinsam mit dem Product Owner jene Aufgaben aus dem Product Backlog aus, die im nächsten Sprint umgesetzt werden sollen. Diese Aufgaben werden anschließend im Sprint Backlog gesammelt und bilden die Grundlage für die Arbeit während des Sprints.
Im Zentrum der Abbildung befindet sich der Sprint-Zyklus, der typischerweise zwischen einer und vier Wochen dauert. In diesem Projekt wurde eine Sprintdauer von zwei Wochen festgelegt. Während dieser Phase arbeitet das Entwicklungsteam an der Umsetzung der definierten Aufgaben. Dabei durchläuft die Entwicklung mehrere Schritte, wie beispielsweise Design, Entwicklung, Testen und Deployment.
Ein wichtiger Bestandteil des Scrum-Prozesses ist das Daily Scrum, ein kurzes tägliches Meeting des Teams. In diesem Meeting berichten die Teammitglieder über ihren aktuellen Fortschritt, geplante Aufgaben sowie mögliche Hindernisse im Entwicklungsprozess. Ziel dieses Meetings ist es, den Arbeitsfortschritt zu koordinieren und Probleme frühzeitig zu erkennen.
Am Ende jedes Sprints findet das Sprint Review statt. Dabei präsentiert das Entwicklungsteam die umgesetzten Funktionen des Produkts. Stakeholder und Projektbeteiligte haben in diesem Meeting die Möglichkeit, Feedback zu geben und neue Anforderungen einzubringen.
Anschließend folgt die Sprint Retrospective, in der das Team den Ablauf des vergangenen Sprints reflektiert. Dabei wird analysiert, welche Aspekte des Arbeitsprozesses gut funktioniert haben und welche Verbesserungen für zukünftige Sprints möglich sind.
Durch diese strukturierte Vorgehensweise ermöglicht Scrum eine kontinuierliche Weiterentwicklung der Software sowie eine regelmäßige Überprüfung des Projektfortschritts.
## Rollenverteilung im Projektteam
Das Scrum-Framework definiert drei zentrale Rollen, die jeweils unterschiedliche Aufgaben innerhalb des Projekts übernehmen. Diese Rollen tragen dazu bei, Verantwortlichkeiten klar zu strukturieren und den Entwicklungsprozess effizient zu gestalten.
Der Product Owner ist für die inhaltliche Planung des Produkts verantwortlich. Zu seinen Aufgaben gehört die Verwaltung und Priorisierung des Product Backlogs. Er entscheidet, welche Funktionen oder Anforderungen für das Produkt am wichtigsten sind und sorgt dafür, dass das Entwicklungsteam stets an den relevantesten Aufgaben arbeitet. Außerdem fungiert der Product Owner als Verbindung zwischen Stakeholdern und Entwicklungsteam.
Der Scrum Master unterstützt das Team bei der Anwendung der Scrum-Methodik und stellt sicher, dass die Scrum-Prinzipien im Projekt eingehalten werden. Zu seinen Aufgaben gehört unter anderem die Organisation und Moderation der Scrum-Meetings. Darüber hinaus hilft er dem Team dabei, Hindernisse im Entwicklungsprozess zu identifizieren und zu beseitigen.
Das Entwicklungsteam ist für die technische Umsetzung der Anforderungen verantwortlich. Es besteht aus den Entwicklern, die die Software planen, implementieren, testen und integrieren. Das Team organisiert seine Arbeit weitgehend selbstständig und entscheidet gemeinsam über die technische Umsetzung der Aufgaben.
Durch diese klar definierten Rollen wird sichergestellt, dass organisatorische und technische Aufgaben effizient verteilt werden können und der Entwicklungsprozess strukturiert abläuft.
## Sprintplanung und Umsetzung
Die Sprintplanung stellt einen wichtigen Bestandteil des Scrum-Prozesses dar. Zu Beginn jedes neuen Sprints trifft sich das Team, um gemeinsam zu entscheiden, welche Aufgaben innerhalb des kommenden Zeitraums umgesetzt werden sollen.
Als Grundlage dient das Product Backlog, in dem alle bekannten Anforderungen des Projekts gesammelt werden. Während der Sprintplanung wählt das Team jene Aufgaben aus, die innerhalb der nächsten zwei Wochen realistisch umgesetzt werden können. Diese Aufgaben werden anschließend in das Sprint Backlog übernommen.
Während des Sprints arbeitet das Entwicklungsteam an der Umsetzung dieser Aufgaben. Die Arbeit wird dabei häufig in kleinere Teilaufgaben unterteilt, um die Fortschritte besser verfolgen zu können.
Zur Koordination der täglichen Arbeit findet das sogenannte Daily Scrum statt. Dieses kurze Meeting dauert in der Regel maximal 15 Minuten und dient dazu, den aktuellen Stand der Entwicklung zu besprechen. Jedes Teammitglied beantwortet dabei typischerweise drei Fragen:
• Was habe ich seit dem letzten Meeting erledigt?
• Woran werde ich heute arbeiten?
• Welche Hindernisse gibt es aktuell?
Durch diese regelmäßige Abstimmung wird sichergestellt, dass alle Teammitglieder über den aktuellen Projektstand informiert sind und mögliche Probleme frühzeitig erkannt werden.
Am Ende eines Sprints werden die entwickelten Funktionen im Sprint Review präsentiert. In diesem Meeting wird überprüft, welche Anforderungen erfolgreich umgesetzt wurden und ob weitere Anpassungen notwendig sind. Anschließend reflektiert das Team im Rahmen der Sprint Retrospective den Arbeitsprozess und identifiziert mögliche Verbesserungen für zukünftige Sprints.
## Vorteile von Scrum für die Webentwicklung
Die Verwendung von Scrum bietet insbesondere für Webentwicklungsprojekte zahlreiche Vorteile. Webanwendungen entwickeln sich häufig dynamisch weiter, da sich Anforderungen, Technologien oder Benutzerbedürfnisse im Laufe der Zeit verändern können.
Durch die Aufteilung der Entwicklung in kurze Sprints kann das Projekt flexibel auf solche Veränderungen reagieren. Neue Anforderungen können einfach in zukünftige Sprints integriert werden, ohne den gesamten Projektplan neu strukturieren zu müssen.
Ein weiterer Vorteil liegt in der kontinuierlichen Überprüfung der entwickelten Funktionen. Da am Ende jedes Sprints ein funktionierender Teil der Software präsentiert wird, können Fehler oder Verbesserungsmöglichkeiten frühzeitig erkannt werden. Dies reduziert das Risiko größerer Probleme in späteren Projektphasen.
Darüber hinaus fördert Scrum die Zusammenarbeit innerhalb des Teams. Regelmäßige Meetings und eine transparente Aufgabenverteilung sorgen dafür, dass alle Teammitglieder stets über den aktuellen Stand des Projekts informiert sind.
Insgesamt ermöglicht Scrum eine strukturierte, flexible und transparente Vorgehensweise bei der Entwicklung von Webanwendungen. Dadurch kann die Qualität der entwickelten Software verbessert und der Entwicklungsprozess effizienter gestaltet werden.

View File

@@ -2,83 +2,16 @@
include_toc: true
gitea: none
---
# 2. Projektmanagement mit Scrum
## 2.1 Grundlagen der Scrum-Methode
Für die Organisation und Umsetzung des Projekts wurde das agile Projektmanagement-Framework Scrum verwendet. Scrum ist ein weit verbreitetes Vorgehensmodell in der Softwareentwicklung, das besonders für Projekte geeignet ist, bei denen sich Anforderungen im Laufe der Entwicklung verändern können. Im Gegensatz zu klassischen Projektmanagementmethoden arbeitet Scrum nicht mit einer vollständig im Voraus geplanten Entwicklung, sondern mit kurzen, wiederkehrenden Entwicklungszyklen.
Das zentrale Element von Scrum ist der sogenannte Sprint. Ein Sprint stellt einen fest definierten Zeitraum dar, in dem bestimmte Funktionen oder Anforderungen umgesetzt werden. In diesem Projekt betrug die Dauer eines Sprints zwei Wochen. Innerhalb dieses Zeitraums arbeitete das Entwicklungsteam daran, ausgewählte Aufgaben zu implementieren und am Ende des Sprints ein funktionsfähiges Ergebnis zu präsentieren.
Die agile Arbeitsweise von Scrum basiert auf einer iterativen und inkrementellen Entwicklung. Das bedeutet, dass die Software Schritt für Schritt erweitert wird. Nach jedem Sprint steht eine neue Version der Anwendung zur Verfügung, die zusätzliche Funktionen enthält. Dadurch können Änderungen oder neue Anforderungen flexibel in zukünftige Sprints integriert werden.
Die grundlegende Struktur und der Ablauf eines Scrum-Projekts sind in Abbildung X dargestellt.
![Scrum-Framework](image-2.png)
*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.
Während der Sprintplanung wählt das Entwicklungsteam gemeinsam mit dem Product Owner jene Aufgaben aus dem Product Backlog aus, die im nächsten Sprint umgesetzt werden sollen. Diese Aufgaben werden anschließend im Sprint Backlog gesammelt und bilden die Grundlage für die Arbeit während des Sprints.
Im Zentrum der Abbildung befindet sich der Sprint-Zyklus, der typischerweise zwischen einer und vier Wochen dauert. In diesem Projekt wurde eine Sprintdauer von zwei Wochen festgelegt. Während dieser Phase arbeitet das Entwicklungsteam an der Umsetzung der definierten Aufgaben. Dabei durchläuft die Entwicklung mehrere Schritte, wie beispielsweise Design, Entwicklung, Testen und Deployment.
Ein wichtiger Bestandteil des Scrum-Prozesses ist das Daily Scrum, ein kurzes tägliches Meeting des Teams. In diesem Meeting berichten die Teammitglieder über ihren aktuellen Fortschritt, geplante Aufgaben sowie mögliche Hindernisse im Entwicklungsprozess. Ziel dieses Meetings ist es, den Arbeitsfortschritt zu koordinieren und Probleme frühzeitig zu erkennen.
Am Ende jedes Sprints findet das Sprint Review statt. Dabei präsentiert das Entwicklungsteam die umgesetzten Funktionen des Produkts. Stakeholder und Projektbeteiligte haben in diesem Meeting die Möglichkeit, Feedback zu geben und neue Anforderungen einzubringen.
Anschließend folgt die Sprint Retrospective, in der das Team den Ablauf des vergangenen Sprints reflektiert. Dabei wird analysiert, welche Aspekte des Arbeitsprozesses gut funktioniert haben und welche Verbesserungen für zukünftige Sprints möglich sind.
Durch diese strukturierte Vorgehensweise ermöglicht Scrum eine kontinuierliche Weiterentwicklung der Software sowie eine regelmäßige Überprüfung des Projektfortschritts.
## 2.2 Rollenverteilung im Projektteam
Das Scrum-Framework definiert drei zentrale Rollen, die jeweils unterschiedliche Aufgaben innerhalb des Projekts übernehmen. Diese Rollen tragen dazu bei, Verantwortlichkeiten klar zu strukturieren und den Entwicklungsprozess effizient zu gestalten.
Der Product Owner ist für die inhaltliche Planung des Produkts verantwortlich. Zu seinen Aufgaben gehört die Verwaltung und Priorisierung des Product Backlogs. Er entscheidet, welche Funktionen oder Anforderungen für das Produkt am wichtigsten sind und sorgt dafür, dass das Entwicklungsteam stets an den relevantesten Aufgaben arbeitet. Außerdem fungiert der Product Owner als Verbindung zwischen Stakeholdern und Entwicklungsteam.
Der Scrum Master unterstützt das Team bei der Anwendung der Scrum-Methodik und stellt sicher, dass die Scrum-Prinzipien im Projekt eingehalten werden. Zu seinen Aufgaben gehört unter anderem die Organisation und Moderation der Scrum-Meetings. Darüber hinaus hilft er dem Team dabei, Hindernisse im Entwicklungsprozess zu identifizieren und zu beseitigen.
Das Entwicklungsteam ist für die technische Umsetzung der Anforderungen verantwortlich. Es besteht aus den Entwicklern, die die Software planen, implementieren, testen und integrieren. Das Team organisiert seine Arbeit weitgehend selbstständig und entscheidet gemeinsam über die technische Umsetzung der Aufgaben.
Durch diese klar definierten Rollen wird sichergestellt, dass organisatorische und technische Aufgaben effizient verteilt werden können und der Entwicklungsprozess strukturiert abläuft.
## 2.3 Sprintplanung und Umsetzung
Die Sprintplanung stellt einen wichtigen Bestandteil des Scrum-Prozesses dar. Zu Beginn jedes neuen Sprints trifft sich das Team, um gemeinsam zu entscheiden, welche Aufgaben innerhalb des kommenden Zeitraums umgesetzt werden sollen.
Als Grundlage dient das Product Backlog, in dem alle bekannten Anforderungen des Projekts gesammelt werden. Während der Sprintplanung wählt das Team jene Aufgaben aus, die innerhalb der nächsten zwei Wochen realistisch umgesetzt werden können. Diese Aufgaben werden anschließend in das Sprint Backlog übernommen.
Während des Sprints arbeitet das Entwicklungsteam an der Umsetzung dieser Aufgaben. Die Arbeit wird dabei häufig in kleinere Teilaufgaben unterteilt, um die Fortschritte besser verfolgen zu können.
Zur Koordination der täglichen Arbeit findet das sogenannte Daily Scrum statt. Dieses kurze Meeting dauert in der Regel maximal 15 Minuten und dient dazu, den aktuellen Stand der Entwicklung zu besprechen. Jedes Teammitglied beantwortet dabei typischerweise drei Fragen:
• Was habe ich seit dem letzten Meeting erledigt?
• Woran werde ich heute arbeiten?
• Welche Hindernisse gibt es aktuell?
Durch diese regelmäßige Abstimmung wird sichergestellt, dass alle Teammitglieder über den aktuellen Projektstand informiert sind und mögliche Probleme frühzeitig erkannt werden.
Am Ende eines Sprints werden die entwickelten Funktionen im Sprint Review präsentiert. In diesem Meeting wird überprüft, welche Anforderungen erfolgreich umgesetzt wurden und ob weitere Anpassungen notwendig sind. Anschließend reflektiert das Team im Rahmen der Sprint Retrospective den Arbeitsprozess und identifiziert mögliche Verbesserungen für zukünftige Sprints.
## 2.4 Vorteile von Scrum für die Webentwicklung
Die Verwendung von Scrum bietet insbesondere für Webentwicklungsprojekte zahlreiche Vorteile. Webanwendungen entwickeln sich häufig dynamisch weiter, da sich Anforderungen, Technologien oder Benutzerbedürfnisse im Laufe der Zeit verändern können.
Durch die Aufteilung der Entwicklung in kurze Sprints kann das Projekt flexibel auf solche Veränderungen reagieren. Neue Anforderungen können einfach in zukünftige Sprints integriert werden, ohne den gesamten Projektplan neu strukturieren zu müssen.
Ein weiterer Vorteil liegt in der kontinuierlichen Überprüfung der entwickelten Funktionen. Da am Ende jedes Sprints ein funktionierender Teil der Software präsentiert wird, können Fehler oder Verbesserungsmöglichkeiten frühzeitig erkannt werden. Dies reduziert das Risiko größerer Probleme in späteren Projektphasen.
Darüber hinaus fördert Scrum die Zusammenarbeit innerhalb des Teams. Regelmäßige Meetings und eine transparente Aufgabenverteilung sorgen dafür, dass alle Teammitglieder stets über den aktuellen Stand des Projekts informiert sind.
Insgesamt ermöglicht Scrum eine strukturierte, flexible und transparente Vorgehensweise bei der Entwicklung von Webanwendungen. Dadurch kann die Qualität der entwickelten Software verbessert und der Entwicklungsprozess effizienter gestaltet werden.
# 1. Einleitung des individuellen Teils
In diesem Abschnitt wird meine persönliche Aufgabenstellung im Rahmen des Projektes (Alumnihub) beschrieben.
## 1.1 Ausgangssituation
Der Absolventenverein der HTL Ungargasse hatte keine digitale Infrastruktur zur Vernetzung seiner Mitglieder. AlumniHub soll das ändern: eine zentrale Plattform für Mitgliederverwaltung, Veranstaltungen und Netzwerkfunktionen.
**Auftrag / persönliche Aufgabenstellungen**
## 1.2 Zielsetzung
Mein persönlicher Beitrag umfasst die DSGVO-konforme Datenschutzimplementierung, ein automatisiertes Backup- und Restore-System, die Anbindung von LinkedIn als externem Identitätsanbieter sowie den Premium-Bereich.
Meine Zuständigkeiten und Verantwortlichkeiten:
## 1.3 Nutzen für den Absolventenverein
Für den Verein bedeutet das: rechtskonforme Datenverarbeitung, gesicherte Datenverfügbarkeit und ein niedrigschwelliger Login für Absolventinnen und Absolventen mit bestehendem LinkedIn-Konto.
• Datenschutzerklärung
• Backup und Restore Systeme
• Entwicklung
• Premiumbereich
• LinkedIn Anmeldung
# 2. Anforderungen an das entwickelte Modul bzw. die Funktionalität
funktionale / nichtfunktionale Anforderungen
@@ -88,7 +21,7 @@ Use Cases
# 3. Individuelle Themenstellung & Zielsetzung
## 3.1 Themenstellung
### Entwicklung von einem CMS-Modul
### Entwicklung eines CMS-Moduls
**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.
@@ -97,11 +30,11 @@ Ein Schwerpunkt der Arbeit ist die Entwicklung eines Oqtane-Moduls, das einen Pr
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
### LinkedIn-Anmeldung
Zur Verbesserung der Benutzerfreundlichkeit und zur vereinfachten Anmeldung wird eine Anmeldung über LinkedIn mithilfe OAuths implementiert. Diese ermöglicht es Benutzerinnen und Benutzern, sich mit einem bestehenden LinkedIn-Konto zu registrieren oder anzumelden.
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
### 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.
@@ -149,7 +82,7 @@ Die DSGVO verfolgt mehrere grundsätzliche Ziele:
• 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 (§ 5 DSGVO), die sicherstellen, dass personenbezogene Daten nur rechtmäßig, zweckgebunden und in transparentem Umfang verarbeitet werden. Dazu gehören unter anderem:
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
@@ -186,7 +119,7 @@ Gemäß Art. 5 Abs. 1 lit. c DSGVO gilt der Grundsatz der Datenminimierung, wona
Darüber hinaus wird der Grundsatz der Zweckbindung gemäß Art. 5 Abs. 1 lit. b DSGVO eingehalten. Die erhobenen Daten werden ausschließlich für die in der Datenschutzerklärung definierten Zwecke verarbeitet, insbesondere zur Organisation der Vereinstätigkeit und zur Durchführung von Absolvententreffen.
Eine darüberhinausgehende Weitergabe an Dritte erfolgt grundsätzlich nicht, außer wenn dies zur Erfüllung der Vereinszwecke erforderlich ist oder eine gesetzliche Verpflichtung besteht.
Eine darüber hinausgehende Weitergabe an Dritte erfolgt grundsätzlich nicht, außer wenn dies zur Erfüllung der Vereinszwecke erforderlich ist oder eine gesetzliche Verpflichtung besteht.
Zur Gewährleistung der Integrität und Vertraulichkeit gemäß Art. 5 Abs. 1 lit. f DSGVO werden geeignete technische und organisatorische Maßnahmen eingesetzt. Dazu zählen insbesondere der Betrieb der Website auf einem Server innerhalb Österreichs, der Abschluss von Auftragsverarbeitungsverträgen gemäß Art. 28 DSGVO mit externen Dienstleistern sowie Maßnahmen zum Schutz vor unbefugtem Zugriff, Verlust oder Missbrauch von Daten.
@@ -199,29 +132,61 @@ Durch die Kombination aus klar definierten Rechtsgrundlagen, transparenten Infor
# 5. Automatisierung von Serverprozessen
## 5.1 Notwendigkeit von Datensicherung [^4][^5]
Die Datensicherung ist ein wesentlicher Bestandteil der Website des Absolventenvereins. Sie dient dazu, die auf der Website gespeicherten Daten vor Verlust oder Beschädigung zu schützen.Digitale Daten bilden die Grundlage für die Funktion der Website und müssen daher regelmäßig gesichert werden. Ein Verlust oder eine Beschädigung der Daten kann zu erheblichen Problemen führen.
Die Datensicherung ist ein wesentlicher Bestandteil der Website des Absolventenvereins. Sie dient dazu, die auf der Website gespeicherten Daten vor Verlust oder Beschädigung zu schützen. Digitale Daten bilden die Grundlage für die Funktion der Website 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 unwiederruflich verloren gehen oder nur mit erheblichen Kosten wiederhergestellt werden können.
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.
Neben der technischen besteht ebennfalls eine rechtliche und organisatorische Notwendigkeit der Datensicherung. Gemäß Art. 5 Abs. 1 lit. f DSGVO müssen personenbezogene Daten gesichert werden, um die Integrität und Vertraulichkeit der Daten zu gewährleisten. Dazu zählt auch der Schutz vor unbeabsichtigtem Verlust. Eine Backup-Sicherung ist daher ein notwendiger Schritt, um die Daten vor Verlust zu schützen.
Neben der technischen besteht ebenfalls eine rechtliche und organisatorische Notwendigkeit der Datensicherung. Gemäß Art. 5 Abs. 1 lit. f DSGVO müssen personenbezogene Daten gesichert werden, um die Integrität und Vertraulichkeit der Daten zu gewährleisten. Dazu zählt auch der Schutz vor unbeabsichtigtem Verlust. Eine Backup-Sicherung ist daher ein notwendiger Schritt, um die Daten vor Verlust zu schützen.
## 5.2 Konzeption des Backup-Systems
Ziel des Backu-Systems war es im Falle eines DAtenverlustes oder eines Systemausfalls die Daten wiederherstellen zu können. Es wurde eine Startegie enwickelt die es ermöglicht sowohl die Datenbank als auch die Dateien auf dem Server zu sichern.
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:
1. Die Postgres Datenbank
1. Die PostgreSQL-Datenbank
2. Der Ordner "oqtane.server" auf dem Server
Damit wird eine vollständige Sicherung der Website ermöglicht, da bei einer reinen Datenbanksicherung wichtige Anwendungsdatein fehlen würden
Damit wird eine vollständige Sicherung der Website ermöglicht, da bei einer reinen Datenbanksicherung wichtige Anwendungsdateien fehlen würden.
```mermaid
graph TD
%% Styling
classDef startEnd fill:#f9f,stroke:#333,stroke-width:2px;
classDef process fill:#d1e8ff,stroke:#0056b3,stroke-width:1px;
classDef critical fill:#ffcccb,stroke:#b30000,stroke-width:1px;
Start((Start: Cronjob 02:30)) --> Init[Initialisierung: set -euo pipefail]
Init --> Vars[Definiere Pfade & PG-Credentials]
subgraph Sicherungsphase
Dir[Erstelle Verzeichnis: /var/backups/UTC_TS] --> DB[pg_dump -Fc: Custom Format Dump]
DB --> Files[tar -cvpzf: Komprimierung oqtane.server]
end
Files --> Check{Fehler aufgetreten?}
Check -- Ja --> Mail[Log Error & Abbruch]
Check -- Nein --> Rotate[Lade Liste der Backup-Ordner]
subgraph Speicherverwaltung [Retention Management]
Rotate --> Count{Anzahl > 30?}
Count -- Ja --> Delete[rm -rf: Lösche älteste Ordner]
Count -- Nein --> Finish[Schließe Log-Eintrag ab]
Delete --> Finish
end
Finish --> Ende((Ende))
%% Zuweisung Klassen
class Start,Ende startEnd;
class Init,Vars,Dir,DB,Files,Rotate,Delete,Finish process;
class Mail critical;
```
Alle Backups werden lokal auf dem Server gespeichert. Diese Backups sind alle zu finden unter: /var/backups
Für jedes Backup wird in diesem Verzeichnis ein Unterordner erstellt,dessen Name einen UTC-Zeitstempel enthält.Das ermöglicht eine saubere Trennung der Sicherungsstände und einfache chronologische Zuordnung.
Für jedes Backup wird in diesem Verzeichnis ein Unterordner erstellt, dessen Name einen UTC-Zeitstempel enthält. Das ermöglicht eine saubere Trennung der Sicherungsstände und einfache chronologische Zuordnung.
```bash
TS="$(date -u +'%Y%m%dT%H%M%SZ')"
DEST_DIR="${BACKUP_ROOT}/${TS}"
```
date -u erzeugt einen Zeitstempel in UTC, wodurch die Bennenung unabhängig von Zeitzonen eindeutig bleibt.
date -u erzeugt einen Zeitstempel in UTC, wodurch die Benennung unabhängig von Zeitzonen eindeutig bleibt.
Der Zeitstempel wird als Ordnername verwendet, sodass jedes Backup separat abgelegt wird (z. B. 20260226T023000Z).
Die Sicherung der PostgreSQL-Datenbank erfolgt mithilfe des Programms pg_dump, welches ein vollständiges Abbild der Datenbank erzeugt:
@@ -420,7 +385,7 @@ Insgesamt stellt das entwickelte Backup-System eine robuste und praxisnahe Lösu
# 6. Benutzerverwaltung und Authentifizierung per LinkedIn
## 6.1 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. Dieses Verfahren ermöglicht es, Benutzer über externe Identitätsanbieter zu authentifizieren, ohne dass deren Zugangsdaten direkt an die Webanwendung übertragen werden müssen.
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 [^6]. 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.
@@ -428,16 +393,16 @@ Der grundlegende Ablauf einer OAuth-Authentifizierung ist in Abbildung X dargest
![OAuth-Authentifizierungsablauf](image.png)
*Abbildung: Ablauf der OAuth-Authentifizierung (Erstellt mit ChatGPT)*
Die Abbildung zeigt den Ablauf der OAuth-Authentifizierung. Zunächst erfolgt die Weiterleitung zur LinkedIn-Anmeldeseite, anschließend wird ein Autorisierungscode an die Webanwendung zurückgegeben, welcher gegen einen Zugriffstoken ausgetauscht wird.
Die Abbildung zeigt den Ablauf der OAuth-Authentifizierung. Zunächst erfolgt die Weiterleitung zur LinkedIn-Anmeldeseite, anschließend wird ein Autorisierungscode (Authorization Code) an die Webanwendung zurückgegeben, welcher gegen einen Zugriffstoken (Access Token) ausgetauscht wird.
Nach der Autorisierung sendet LinkedIn einen sogenannten Authorization Code an die Webanwendung zurück. Dieser Code wird anschließend vom Server der Anwendung gegen einen Access Token ausgetauscht. Mit Hilfe dieses Tokens kann die Webanwendung anschließend die freigegebenen Benutzerdaten vom LinkedIn-Server abrufen.
Nach der Autorisierung sendet LinkedIn einen solchen Autorisierungscode an die Webanwendung zurück. Dieser Code wird anschließend vom Server der Anwendung gegen ein Zugriffstoken ausgetauscht. Mit Hilfe dieses Tokens kann die Webanwendung anschließend die freigegebenen Benutzerdaten vom LinkedIn-Server abrufen.
Der Vorteil dieses Verfahrens liegt darin, dass die Webanwendung zu keinem Zeitpunkt Zugriff auf das Passwort des Benutzers erhält. Dadurch wird ein höheres Sicherheitsniveau erreicht und gleichzeitig die Benutzerfreundlichkeit verbessert, da sich Benutzer mit ihrem bestehenden LinkedIn-Konto anmelden können.
## 6.2 Technische Umsetzung der LinkedIn-Anmeldung in Oqtane
Die technische Umsetzung der LinkedIn-Authentifizierung erfolgte über das integrierte External Login System des Content-Management-Systems Oqtane. Dieses System ermöglicht die Integration externer Identitätsanbieter über standardisierte Protokolle wie OAuth 2.0.
Die technische Umsetzung der LinkedIn-Authentifizierung erfolgte über das integrierte External Login System [^8] 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 erstellt. Dabei werden zwei zentrale Zugangsdaten generiert:
Für die Verbindung mit LinkedIn wurde zunächst eine Entwickleranwendung im LinkedIn Developer Portal [^7] erstellt. Dabei werden zwei zentrale Zugangsdaten generiert:
• Client ID
• Client Secret
@@ -454,7 +419,7 @@ Nach erfolgreicher Anmeldung stellt LinkedIn über folgenden Endpunkt ein Zugrif
https://www.linkedin.com/oauth/v2/accessToken
Zusätzlich wurde eine sogenannte Redirect URL definiert. Diese URL wird von LinkedIn verwendet, um den Benutzer nach erfolgreicher Authentifizierung wieder zurück zur Webanwendung zu leiten.
Zusätzlich wurde eine sogenannte Redirect-URL definiert. Diese URL wird von LinkedIn verwendet, um den Benutzer nach erfolgreicher Authentifizierung wieder zurück zur Webanwendung zu leiten.
In der Konfiguration wurde außerdem festgelegt, welche Benutzerdaten von LinkedIn übernommen werden sollen. Dazu gehören unter anderem:
@@ -471,9 +436,9 @@ Der eigentliche Anmeldevorgang erfolgt in mehreren aufeinanderfolgenden Schritte
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 einen Access Token ausgetauscht wird.
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.
Mit Hilfe dieses Tokens kann die Anwendung anschließend die freigegebenen Benutzerdaten vom LinkedIn-Server abrufen. Diese Daten werden verwendet, um den Benutzer in der lokalen Datenbank zu identifizieren oder ein neues Benutzerkonto zu erstellen.
Wie in Abschnitt 6.1 beschrieben, werden die abgerufenen Profildaten zur Identifikation oder Neuanlage des Benutzerkontos in der lokalen Datenbank verwendet.
# 7. Implementierung des Premium-Bereichs
## 7.1 Ziel und Zweck des Premium-Bereichs
@@ -483,6 +448,31 @@ Der zentrale Zweck besteht darin, einen Anreiz für aktives Engagement im Verein
Die Entwicklung erfolgte als eigenständiges Oqtane-Modul, wodurch eine nahtlose Integration in die bestehende Vereinswebsite 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
graph TD
subgraph Client [Client-Seite / WebAssembly]
UI[Index.razor / Apply.razor] --> SvcC[IApplicationService]
end
subgraph Server [ASP.NET Core Server]
SvcC --> Ctrl[ApplicationController]
Ctrl --> SvcS[IServerApplicationService]
SvcS --> Prem[IPremiumService]
SvcS --> Rep[IApplicationRepository]
end
subgraph Data [Persistence Layer]
Rep --> EF[EF Core Context]
EF --> DB[(PostgreSQL)]
Prem --> DB
end
%% Styles
style Client fill:#e1f5fe,stroke:#01579b
style Server fill:#fff3e0,stroke:#e65100
style Data fill:#f1f8e9,stroke:#33691e
```
## 7.2 Funktionalität und Features des Premium-Bereichs
Der Premium-Bereich umfasst mehrere miteinander verknüpfte Funktionen, die gemeinsam ein geschlossenes System bilden.
@@ -508,6 +498,30 @@ public class EngineerApplication : ModelBase
Die Klasse erbt von `ModelBase`, wodurch automatisch die Audit-Felder `CreatedBy`, `CreatedOn`, `ModifiedBy` und `ModifiedOn` zur Verfügung stehen. Das Feld `Status` bildet den aktuellen Workflow-Schritt ab und kann die Werte „Draft", „Submitted", „Approved" oder „Rejected" annehmen. Die hochgeladene PDF-Datei wird nicht direkt gespeichert, sondern über eine `FileId` im Oqtane-Dateisystem referenziert.
```mermaid
classDiagram
class EngineerApplication {
+int ApplicationId
+int UserId
+int ModuleId
+int FileId
+string Title
+string ShortDescription
+string Status
+DateTime? SubmittedOn
+DateTime? ApprovedOn
}
class ModelBase {
+int CreatedBy
+DateTime CreatedOn
+int ModifiedBy
+DateTime ModifiedOn
}
EngineerApplication --|> ModelBase : inherits
```
Der Lebenszyklus eines Antrags durchläuft mehrere Phasen. Der Benutzer beginnt auf der Antragsseite `Apply.razor`, wo ein Formular mit Feldern für Titel, Kurzbeschreibung und einer Dateiauswahl über den integrierten Oqtane FileManager bereitgestellt wird. Der FileManager stellt eine benutzerfreundliche Upload-Oberfläche mit Fortschrittsanzeige bereit und akzeptiert ausschließlich PDF-Dateien. Die hochgeladene Datei wird dabei im Oqtane-Dateisystem abgelegt und das Modul speichert lediglich die resultierende Datei-ID in der Antragstabelle.
Beim Absenden des Formulars erstellt die clientseitige Methode `SubmitApplication` ein neues `EngineerApplication`-Objekt und befüllt es mit den Formulardaten. Der Status wird dabei automatisch auf „Published" gesetzt, zusammen mit den Zeitstempeln für Einreichung und Genehmigung. Die Methode unterscheidet anhand der `ApplicationId`, ob ein neuer Antrag über den Service `AddApplicationAsync` erstellt oder ein bestehender über `UpdateApplicationAsync` aktualisiert werden soll. Falls keine Datei ausgewählt wurde, wird der Vorgang mit einer entsprechenden Fehlermeldung abgebrochen. Die Kommunikation mit dem Server erfolgt über den injizierten `ApplicationService`, der als HTTP-Client die Anfragen an den REST-Controller weiterleitet.
@@ -680,6 +694,29 @@ private bool IsUserPremium(System.Security.Claims.ClaimsPrincipal user)
}
```
```mermaid
flowchart TD
Req([Anfrage auf Premium-Inhalt]) --> Auth{User.Identity.IsAuthenticated?}
Auth -- Nein --> Guest[Login-Seite anzeigen]
Auth -- Ja --> Admin{Ist Administrator?}
Admin -- Ja --> Grant[Zugriff gewährt]
Admin -- Nein --> Role{In Rolle 'Premium Member'?}
Role -- Ja --> Grant
Role -- Nein --> DB{Eintrag in SZUAbsolventenvereinUserPremium?}
DB -- Nein --> Deny[Premium-Upgrade-Seite anzeigen]
DB -- Ja --> Valid{Ablaufdatum > Heute?}
Valid -- Ja --> Grant
Valid -- Nein --> Deny
style Grant fill:#c8e6c9,stroke:#2e7d32
style Deny fill:#ffcdd2,stroke:#c62828
```
Zuerst wird die Oqtane-Rollenzugehörigkeit geprüft, anschließend der datenbankbasierte Premium-Status mit Ablaufdatum. Das kumulative System sorgt dafür, dass bei mehrfacher Vergabe die Laufzeiten addiert und nicht überschrieben werden — ein Mitglied, das während einer laufenden Premium-Mitgliedschaft einen weiteren Antrag genehmigt bekommt, erhält die zusätzlichen 12 Monate auf das bestehende Ablaufdatum aufgeschlagen.
Die Zugriffsbeschränkung wird konsequent auf beiden Seiten durchgesetzt: Clientseitig entscheidet die Blazor-Komponente anhand der Benutzerrolle, welche UI-Elemente angezeigt werden. Serverseitig prüft jeder Service-Aufruf die Berechtigung des anfragenden Benutzers über das `[Authorize]`-Attribut mit Policies wie `PolicyNames.ViewModule` und `PolicyNames.EditModule`, bevor Daten zurückgegeben oder Änderungen vorgenommen werden. Dadurch wird sichergestellt, dass selbst bei einer Manipulation der Client-Anfrage keine unberechtigten Zugriffe möglich sind.
@@ -736,6 +773,9 @@ Ein weiterer wichtiger Vorteil besteht darin, dass PostgreSQL sehr gut mit moder
Da die Plattform personenbezogene Daten von Benutzern speichert, wurde zusätzlich ein Backup-System implementiert, das regelmäßige Sicherungen der Datenbank erstellt. Dadurch können Daten im Falle eines Fehlers oder eines Systemausfalls wiederhergestellt werden.
## 8.3 OAuth 2.0
Für die sichere Anmeldung über externe Identitätsanbieter wurde das Protokoll OAuth 2.0 implementiert. OAuth 2.0 ist ein branchenweiter Standard für die Autorisierung, der es Benutzern ermöglicht, Anwendungen von Drittanbietern Zugriff auf ihre Daten zu gewähren, ohne ihre Passwörter für das jeweilige Portal preiszugeben. Im Rahmen dieses Projekts wurde OAuth 2.0 als Authentifizierungsverfahren mit LinkedIn gewählt, um den Registrierungsprozess der Benutzer signifikant zu vereinfachen, da bestehende LinkedIn-Accounts genutzt werden können. Gleichzeitig wird dadurch ein hohes Sicherheitsniveau sichergestellt.
# 9. Learnings
## 9.1 Technische und fachliche Erkenntnisse
Während der Umsetzung meiner Diplomarbeit konnte ich umfangreiche technische Erfahrungen in der Entwicklung moderner Webanwendungen sammeln. Ein zentraler Bestandteil der Arbeit war die Implementierung einer Alumni-Plattform, die ehemaligen Studierenden eine Möglichkeit bietet, sich zu vernetzen, Profile zu verwalten und sich für Veranstaltungen anzumelden.
@@ -817,12 +857,18 @@ Langfristig kann die Plattform zu einem zentralen digitalen Treffpunkt für Abso
Insgesamt besitzt die entwickelte Plattform ein großes Zukunftspotenzial. Durch kontinuierliche Erweiterungen und die aktive Nutzung durch die Mitglieder kann sie zu einem wichtigen Instrument für die Vernetzung und Weiterentwicklung des Absolventenvereins werden.
# 11. Quellenverzeichnis
[^1]: DSGVO Datenschutz-Grundverordnung: https://eur-lex.europa.eu/eli/reg/2016/679/
[^1]: DSGVO Datenschutz-Grundverordnung: https://eur-lex.europa.eu/eli/reg/2016/679/ [Zugriff: 19.03.2026]
[^2]: RIS Rechtsinformationssystem des Bundes: https://www.ris.bka.gv.at/
[^2]: RIS Rechtsinformationssystem des Bundes: https://www.ris.bka.gv.at/ [Zugriff: 19.03.2026]
[^3]: DSB Österreichische Datenschutzbehörde: https://dsb.gv.at/
[^3]: DSB Österreichische Datenschutzbehörde: https://dsb.gv.at/ [Zugriff: 19.03.2026]
[^4]: Datensicherung und Datenverlust: https://www.bsi.bund.de/DE/Themen/Verbraucherinnen-und-Verbraucher/Informationen-und-Empfehlungen/Cyber-Sicherheitsempfehlungen/Daten-sichern-verschluesseln-und-loeschen/Datensicherung-und-Datenverlust/Datensicherung-wie-geht-das/datensicherung-wie-geht-das_node.html
[^4]: Datensicherung und Datenverlust: https://www.bsi.bund.de/DE/Themen/Verbraucherinnen-und-Verbraucher/Informationen-und-Empfehlungen/Cyber-Sicherheitsempfehlungen/Daten-sichern-verschluesseln-und-loeschen/Datensicherung-und-Datenverlust/Datensicherung-wie-geht-das/datensicherung-wie-geht-das_node.html [Zugriff: 19.03.2026]
[^5]: ChatGPT Notwendigkeit der Datensicherung: https://chatgpt.com/c/69a06632-e4fc-8384-bd6c-a543d7bbd00d
[^5]: BSI Bundesamt für Sicherheit in der Informationstechnik: *IT-Grundschutz-Kompendium CON.3: Datensicherungskonzept.* URL: https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Grundschutz/Kompendium/IT_Grundschutz_Kompendium_Edition2023.pdf [Zugriff: 19.03.2026]
[^6]: IETF RFC 6749 The OAuth 2.0 Authorization Framework: https://datatracker.ietf.org/doc/html/rfc6749 [Zugriff: 19.03.2026]
[^7]: LinkedIn Developer Documentation Authorization Code Flow: https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow [Zugriff: 19.03.2026]
[^8]: Oqtane Framework External Login: https://docs.oqtane.org/ [Zugriff: 19.03.2026]

View File

@@ -7,73 +7,90 @@ gitea: none
In diesem Abschnitt wird meine persönliche Aufgabenstellung im Rahmen des Projektes (`Alumnihub`) beschrieben.
### Auftrag / persönliche Aufgabenstellungen
### 1.1 Auftrag / persönliche Aufgabenstellungen
Meine Zuständigkeiten und Verantwortlichkeiten:
- Product Owner
- Infrastruktur
- Entwicklung
- Auswertungen
- Schwarzes Brett
### Motivation
### 1.2 Motivation
Lernen von ASP.NET und der Entwicklung mit Blazor und Oqtane. Ich habe Interesse an dem Thema Webentwicklung. Privat entwickle ich schon seit Jahren viel mit React.JS.
Gegenstand der Diplomarbeit ist die Entwicklung modularer Webanwendungen mit Blazor und Oqtane. Aufbauend auf fundierten Kenntnissen in der Fullstack-Entwicklung (React, Node.js, Golang), welche privat bei diversen Projekten gesammelt worden sind, fokussiert sich die Arbeit auf die Architekturvorteile des .NET-Stacks. Besonders im Fokus stehen die Konsistenz durch statische Typisierung sowie das Zusammenspiel modularer Komponenten in verteilten Systemen.
Mein Untersuchungsanliegen: Inwieweit optimiert die Integration von Blazor und dem Oqtane-Framework die Konsistenz und Wartbarkeit modularer Web-Architekturen im Vergleich zu den für mich gewohnten Technologie-Stacks (React/Node.js)?
## 2. Anforderungen an das entwickelte Modul bzw. die Funktionalität
### 2.1 Modulanforderungen / funktionale Anforderungen
### 2.2 Infrastrukturanforderungen / nichtfunktionale Anforderungen
- funktionale / nichtfunktionale Anforderungen
- Use Cases
## 3. Technische Grundlagen
Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie das Bereitstellen des Services. Als Betriebssystem habe ich mich für Linux entschieden, einfach, da ich mit Linux im Serverumfeld die meisten und besten Erfahrungen gemacht habe.
## 3. Technisches Umfeld
Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie das Bereitstellen des Services.
### 3.1 Auswahlverfahren
#### 3.1.1 Entscheidungsfindung CMS
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:
(Diese Entscheidung wurde gemeinsam getroffen:)
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 Webentwicklung mit ASP.NET Core 9 und (Upgrade im Lauf der Diplomarbeit auf .NET Core 10) dem CMS Oqtane entschieden. Auch hier gab es einige Kandidaten:
- Piranha CMS
>Piranha erscheint auf den ersten Blick nicht so flexibel wie Oqtane, basiert auf .NET 8.0 und wird nicht so aktiv gewartet.
> Piranha erscheint auf den ersten Blick nicht so flexibel wie Oqtane, es basiert auf .NET 8.0 und wird nicht so aktiv gewartet.
- Umbraco
>Viel Arbeit mit Partials, welche in der Admin Oberfläche geschieht, aber sehr gut dokumentiert. Im großen und ganzen wirkt Umbraco nicht so flexibel.
> 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!
- DNN / Dot Net Nuke
>Platzhirsch. Kennt man, wird von der DNN Foundation gewartet. Arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Und ein Windows Server würde ich ich nicht einfach so ins Internet, abgesehen von den Lizenzkosten, die das kosten würde.
> 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.
- Oqtane
>Schlecht dokumentiert, auf den ersten Blick sehr modular und flexibel.
> 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.
Am Ende haben wir uns für das Oqtane Framework trotz seiner schlechten Dokumentation entschieden.
Insbesondere aufgrund seiner sehr hohen Flexibilität, haben wir uns am Ende für Oqtane entschieden.
#### 3.1.2 Entscheidungsfindung restliche Infrastruktur
Als Betriebssystem habe ich mich für Linux entschieden, einfach, da ich mit Linux im Serverumfeld die meisten und besten Erfahrungen gemacht habe.
Im Bereich der Datenbanken musste ich mir ein paar Fragen stellen:
Im Bereich der Datenbanken musste ich mir ein paar Fragen stellen.
1. Auf welche Art Datenbank setzen wir? SQL, NoSQL, Graph, ...
2. Mit welcher speziellen implementiereung bekommen wir Support und haben Wissen im Team?
3. Ist das auserkorene System kompatibel mit dem CMS auf dem wir aufbauen?
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 Datenbanken in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem DBMS, welche ich im Nebenjob errungen 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-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.
### 3.2 Beschreibung und Architektur von Oqtane
# Technologie
## Entwicklung mit ASP.NET (Was ist Blazor? / Was ist Razor? / Kestrel)
## Was ist Oqtane? Architektur von Oqtane?
Oqtane ist ein Framework und CMS zur Entwicklung von Webseiten mithilfe von ASP.NET und Blazor. [^5] Ein Oqtane-System besteht aus mehreren Komponenten.
In dieser Diplomarbeit fokussieren wir uns hauptsächlich auf `Themes` und `Modules`, aber es gibt auch `Language Packs` und `Pure Extensions`. [^6]
Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Website (die Shell) festlegen. [^6]
Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Webseite (die Shell) festlegen. [^6]
[^5]: https://www.oqtane.org/#about
[^6]: https://docs.oqtane.org/dev/extensions/index.html
#### 3.2.1 Architektur eines Moduls
### Architektur eines Moduls
Ein Modul in Oqtane besteht aus 4 Projekten. Server, Client, Shared und Package.
Ein Modul in Oqtane besteht aus vier Projekten:
Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. In der Praxis bedeutet das: alle Repositories, Controller, Manager, Migrationen und Server-Services (entwickelt nach einem Interface definiert im Client) und Server-Startuplogik.
- 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-Staruplogik, Client-Services (+ Inferfaces dafür, die Services hier sollen lediglich die Server-Services über HTTP aufrufen), 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 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.
- Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der 3 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 (DB Migrationen werden gemacht und die Pakete entpackt).
- 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).
### 3.3 Zusammenspiel der Infrastruktur
In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen. Wir verwenden NginX als Reverse Proxy, welcher bei uns die SSL Terminierung macht. Das Zertifikat, welches verwendet wird, wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert und verwaltet. 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.
## Systemarchitektur (Postgres / Oqtane / Nginx )
```mermaid
architecture-beta
group server(server)[Server]
@@ -88,15 +105,80 @@ architecture-beta
nginx:R <--> L:oqtane
oqtane:R <--> L:db
```
## Websockets und HTTP 1.1
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.
## Dependency injection
| Umgebung | Administrationszugang |
| ---------- | --------------------- |
| Hetzner | Wireguard |
| Schule | Highport |
| LiveDesign | IPSEC VPN |
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.
### 3.4 Entwicklung mit ASP.NET
#### 3.4.1 Blazor [^7]
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 hat mehrere Hosting-Modelle:
- Blazor Web App: Hier wird die Web App als Teil einer ASP.NET Core Anwendung bereitgestellt. Dabei gibt es mehrere Render Modi:
- Static Server: Die Komponente wird serverseitig gerendert und besitzt keine Interaktivität. Es ist der standardmäßige `RenderMode`
- Interactive Server: Die Komponente wird serverseitig gerendert, diesmal ist sie jedoch interaktiv. Das bedeutet, man kann mithilfe von C# den Zustand der Seite dynamisch bearbeiten. Diese Zustandsänderungen werden serverseitig bearbeitet. Hierbei kommunizieren Server und Client mithilfe von SignalR über WebSockets miteinander.
- Interactive WebAssembly: Die Komponente wird clientseitig, also im Browser, gerendert. Damit der Blazor C# Code auch im Browser ausgeführt werden kann, wird dieser in WebAssembly kompiliert.
- Interactive Auto: Im `Interactive Auto` Modul wird bei dem initialen Besuch der Website der `Interactive Server` Modus gewählt und im Hintergrund wird der WebAssembly-Build heruntergeladen, damit bei weiteren Besuchen der Seite der `Interactive WebAssembly` Modus gewählt werden kann.
- Hybrid: Dieser Modus ist der Einzige, welcher nicht innerhalb einer Blazor Web App läuft, sondern in einem WebView in einer Nativen App. Dabei wird innerhalb des Mutterprozesses, ganz ohne WebServer, der C# und Razor-Code ausgeführt. Das Ganze funktioniert in WPF und WinForms Apps und in nativen mobilen Apps für Android und iOS mithilfe von .NET MAUI.
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. Das 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
<h1>Counter</h1>
<p>Count: @count</p>
<button @onclick="Increment">Increment</button>
@code
{
private int count = 0;
private void Increment()
{
count++;
}
}
```
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):
- namespace: Gibt den aktuellen Namespace in der Razor Datei an.
- inherits: Gibt die Superklasse der generierten C# Klasse an.
- using: Gibt die im C# Code benutzen/verfügbaren Namespaces an
- foreach: Für Wiederholungen im Markup
- if: Für Verzweigungen im Markup
#### 3.4.2 Kommunikation zwischen Front- und Backend
Wie Front- und Backend miteinander interagieren hängt hauptsächlich vom Render-Modus ab. Oqtane kann auf verschiedene Arten betrieben werden. Hierbei ist es dem Modulentwickler ziemlich egal, welche Art der Kommunikation (WebSockets, HTTP Long-Polling, REST) verwendet wird. SignalR ist eine Library aus dem ASP.NET Framework, welche es möglich macht, Server zu Client Kommunikation zu betreiben. Oqtane verwendet SignalR im `Interactive Server (SignalR)` Render-Modus.
### 3.5 Dependency Injection
Dependency Injection ist ein Entwurfsmuster, bei dem die Abhängigkeiten eines Objekts nicht von diesem selbst erzeugt, sondern von außen „injiziert“ werden.
Wie der Software-Architekt Martin Fowler, der den Begriff im Jahr 2004 maßgeblich prägte, beschreibt, geht es im Kern darum, die Erzeugung von Objekten von deren Nutzung zu trennen [^9]. Anstatt dass eine Klasse ihre Hilfsobjekte mittels des new-Operators selbst instanziiert, werden ihr diese meist über den Konstruktor zur Verfügung gestellt.
In den folgenden beiden Kapiteln wird das Dependency Inversion Principle und das Microsoft Dependency Injection Framework genauer vorgestellt.
#### 3.5.1 Dependency Inversion Principle [^1]
### Dependency Inversion Principle [^1]
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines von den fünf `SOLID` Prinzipien in der Softwareentwicklung.
Das DIP unterscheidet zwischen high-level und low-level Modulen.
- Die High-Level-Module beschreiben die Applikations- / Businesslogik, ohne direkt mit den Low-Level-Modulen zu interagieren, sondern lediglich auf Abstraktionen. [^3]
- Die Abstraktionen sollen nicht von Implementierungsdetails abhängig sein, sondern die Low-Level-Implementierung sollen gemäß der Abstraktionsschicht implementiert werden. [^3]
@@ -109,6 +191,7 @@ architecture-beta
a:R --> L:b
```
Bei diesem Beispiel ist die Klasse A ein high-level Modul, welches direkt auf die Klasse B referenziert, was das DI-Prinzip verbietet.
Das Problem dabei: Die einzelnen Klassen sind eng gekoppelt, was das Austauschen von B mit einer anderen Klasse unmöglich macht. Genau dieses Problem wird vom DIP gelöst.
@@ -121,16 +204,19 @@ architecture-beta
a:B --> T:ib
ib:R <-- L:b
```
Das High-Level-Modul ruft lediglich eine Abstraktion eines Low-Level-Moduls auf, welche von einem, oder mehreren Low-Level-Modulen implementiert wurde. Für das High-Level-Modul ist es hier egal, welches Low-Level-Modul die Implementierung bereitstellt. Dadurch erhält man einen viel modulareren Aufbau in der Software. Die einzelnen Module sind auch leichter austauschbar und testbar. Genau diese Modularität macht Dependency Injection möglich.
### Microsoft Dependency Injection Framework
Dependency Injektion ist in .NET genau so wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
#### 3.5.2 Microsoft Dependency Injection Framework
Dependency Injection ist in .NET genau so wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
Alle Dependencies werden in einem `Service-Container` zur Verwaltung registriert. .NET hat einen eingebauten `Service-Container` (eine Implementierung des `IServiceProvider`). [^4]
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt, oder wieder entsorgt (sofern das Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt, bzw. selbst instanziiert und dannach bereitgestellt. [^4]
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt, oder wieder entsorgt (sofern das Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt, bzw. selbst instanziiert und danach bereitgestellt. [^4]
Hier ein Beispiel aus der Dokumentation von Microsoft: [^4]
```c#
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
@@ -166,9 +252,10 @@ public sealed class Worker(IMessageWriter messageWriter) : BackgroundService
}
}
```
Das ist ein simples Beispiel, welches Teile des DI Frameworks zeigt. Wir haben einen Service (Klasse Worker), ein Dependency (Klasse MessageWriter) und eine Abstraktionsebene, von dem Dependency (Interface IMessageWriter).
Bei Programmstart wird zuerst manuell der `Service-Container` erstellt, dannach alle Module registriert (entweder als HostedService, oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
Bei Programmstart wird zuerst manuell der `Service-Container` erstellt, danach alle Module registriert (entweder als HostedService, oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
Mit dem Aufruf von `builder.Build()` wird intern ein Dependency Graph erstellt und mit `host.Run()` wird versucht die Klasse Worker zu instanziieren und zu starten. Nachdem Worker ein Dependency auf IMessageWriter hat, wird über den zuvor erstellten Dependency-Graph die Implementierung von IMessageWriter gesucht. Jetzt wird MessageWriter instanziiert und dem Konstruktor von Worker übergeben, damit seine Dependencies befriedigt werden.
@@ -184,17 +271,7 @@ architecture-beta
ib:R <-- L:b
```
[^1]: https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/architectural-principles#dependency-inversion
[^2]: https://blog.logrocket.com/dependency-inversion-principle/
[^3]: https://www.oodesign.com/dependency-inversion-principle
[^4]: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection/overview
# Continuous Integration
## Automatisierter Build und Release Prozess mithilfe von Gitea Actions.
### 3.6 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.
@@ -214,21 +291,263 @@ Anwendungen von Gitea Actions bei dieser Diplomarbeit:
- PM Repository:
> Zum automatischen Überprüfen der Dokumente, unter anderem, mithilfe von KI, wie zum Beispiel Gemini.
# Projektmanagement
## Scrum
## YouTrack
## Gitea (mit Issues)
## Git
## Kommunikation
### 3.7 Debian Paket
# Learnings
## Probleme mit Oqtane
## Arbeitszeiteinschätzung (Zeitverzug)
## Teamleitung (Motivation / Downsizing)
## Produktion != Staging
## Sprints und Meetings (in Zukunft ja asynchron)
TODO
# Modules
## Mass Mailer
## Event Registration
## Schwarzes Brett
## 4 Projektmanagement & Tools
### 4.1 Scrum
### 4.2 YouTrack
### 4.3 Git
Git fungierte im Rahmen dieser Diplomarbeit als zentrales Werkzeug zur Versionskontrolle und Koordination sämtlicher Entwicklungsschritte. Die wichtigste Komponente stellt dabei der Commit dar, welcher als eindeutiger Snapshot des Projektzustands dient und über eine spezifische Commit-SHA (Secure Hash Algorithm) referenziert werden kann. Um eine lückenlose Nachvollziehbarkeit zu gewährleisten, wurde für jeden abgeschlossenen Arbeitsschritt ein eigener Commit erstellt.
Im Gegensatz zu zentralisierten Systemen wie SVN, welches wir im Unterricht beigebracht bekommen haben, speichert Git die vollständige Historie eines Projekts lokal auf dem Rechner jedes Beteiligten. Dies ermöglicht nicht nur ein Offline-Arbeiten, sondern bietet auch eine hohe Ausfallsicherheit.
Der Workflow in Git basiert auf drei Hauptbereichen:
1. Working Directory: Der aktuelle Zustand der Dateien auf der Festplatte.
2. Staging Area (Index): Eine Zwischenebene, in der Änderungen für den nächsten Snapshot vorgemerkt werden.
3. Repository (HEAD): Der dauerhafte Speicher der versionierten Stände (Commits).
Eines der mächtigsten Features von Git ist das Branching. Es erlaubt es, isolierte Entwicklungszweige zu erstellen, um neue Features oder experimentelle Analysen zu implementieren, ohne die Stabilität des Hauptzweigs `main` zu gefährden.
Sobald eine Änderung erfolgreich getestet wurde, wird sie durch einen Merge wieder in den Hauptzweig integriert. Sollten dabei widersprüchliche Änderungen an denselben Dateizeilen auftreten, unterstützt Git den Nutzer bei der Auflösung dieser sogenannten Merge-Konflikte.
Für die Sicherung und Zusammenarbeit wurde im Rahmen dieser Arbeit Remote-Repositories auf einer Gitea Instanz verwendet. Durch die Befehle push und pull wird der lokale Stand mit dem Server synchronisiert. Dies gewährleistet eine konsistente Datenbasis und dient gleichzeitig als kontinuierliches Backup des Projektfortschritts.
### 4.4 Gitea
Als schlanke und selbst gehostete Open-Source-Alternative zu Plattformen wie GitHub oder GitLab wurde für die Verwaltung der Repositories Gitea eingesetzt. Hauptgrund für die Benutzung von Gitea war meine bereits aufgesetzte Instanz, welche schon mehrere Jahre in Verwendung war und mit der es im Team auch schon Erfahrungen gab. Gitea bietet neben der reinen Git-Verwaltung essenzielle Werkzeuge für den Software-Lebenszyklus, wie ein integriertes Issue-Tracking, Code-Reviews über Pull-Requests sowie eine Benutzerverwaltung, und unterstützt somit die strukturierte Umsetzung der Diplomarbeit im Team.[^12]
#### 4.4.1 Repositories
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. [^12]
#### 4.4.2 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. [^12][^13]
#### 4.4.3 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. [^12][^14]
#### 4.4.4 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. [^12][^15]
#### 4.4.5 Releases
Ü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. [^12]
#### 4.4.6 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. [^12][^16]
### 4.5 Kommunikation
## 5 Module
### 5.1 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.
#### 5.1.1 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.
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.
#### 5.1.2 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.
Technisch bedeutet das, dass die standardmäßig vorkonfigurierten `DataProtectionTokenProviderOptions` explizit konfiguriert werden müssen. [^10] 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:
- `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. [^11] 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. [^11] 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.
`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.
#### 5.1.3 Reporting System
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.
Angestrebt wurde folgender Ablauf für das Melden eines Eintrags:
```mermaid
sequenceDiagram
participant Module
actor User
participant ReportingComponent
participant ReportingHandler
User->>+Module: View: Entity
User->>+ReportingComponent: Report current Entity
rect rgba(0, 0, 0, 0)
ReportingComponent->>+User: Ask for reason
User->>-ReportingComponent: Enters Reason
end
ReportingComponent->>+ReportingHandler: New Report (includes entity and reason)
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.
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. Dieses Nuget Paket wird dann in jedem notwendigen Modul als Dependency hinzugefügt und damit kann man Modulübergreifend auf die Services und das IReporting Component zugreifen.
Die Implementierung des IReportingComponents stellt nur eine Property (`ReportType`, welche den TypeName der Razor Komponente zurückliefert, damit Dynamic Component sie laden kann) und eine Methode (`ConstructParameterList`, welche das Parameter Dictionary erstellt. Nur zwecks Typensicherheit eingefügt) bereit. Mit dem Dynamic Component von Razor ist es möglich, per C# Code unterschiedliche Komponenten zu rendern und damit auch die per DI injizierte Klasse.
```razor
@inject IReportUI ReportingComponent
<DynamicComponent Type="@ReportingComponent.ReportType" Parameters="@ReportingComponent.ConstructParameterList(_item, RenderModeBoundary)"/>
@code {
private IReportable _item;
}
```
Die Bereitstellung des Moduls geschieht im `AdminModules` Modul.
### 5.2 Event Registration
Dieses Modul ermöglicht es Administratoren und Absolventen, Veranstaltungen zu erstellen, auf der Seite zu veröffentlichen und zu verwalten, während Mitglieder ihre Teilnahme direkt über das Portal bestätigen oder absagen können. Dieses Modul dient der organisatorischen Unterstützung von Absolvententreffen und anderen Vereinsaktivitäten. Dieses Modul wurde gemeinsam mit Adam Gaiswinkler geschrieben, wobei er sich um die Darstellung der Events im Frontend gekümmert hat, während ich mich der Infrastruktur im Hintergrund angenommen habe.
#### 5.2.1 Backend und Datenhaltung
Die serverseitige Implementierung basiert auf dem Repository-Pattern des Oqtane-Frameworks. Hierbei kommen zwei zentrale Repositories zum Einsatz:
Das `EventRepository` verwaltet die Metadaten der Veranstaltungen wie Name, Beschreibung, Datum und Ort.
Das `ResponseRepository` speichert die Rückmeldungen der Benutzer. Ein Eintrag verknüpft dabei die UserId mit der EventId und dem Status der Rückmeldung.
Die Kommunikation zwischen dem Client und dem Server erfolgt über einen REST-API-Controller `EventRegistrationController`, der sicherstellt, dass nur autorisierte Benutzer Änderungen vornehmen oder detaillierte Statistiken einsehen können.
#### 5.2.2 Statistik und Visualisierung
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 Ablauf der grafischen Darstellung gestaltet sich wie folgt:
1. Datenaufbereitung: In der Edit-Komponente werden alle Rückmeldungen zu einem Event geladen und nach ihrem Typ, oder beliebigen anderen Merkmalen aggregiert.
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.
### 5.3 Schwarzes Brett
Das Modul "Schwarzes Brett" dient als digitale Anschlagtafel für den Absolventenverein. Mitglieder können hier Gesuche, Angebote oder allgemeine Informationen veröffentlichen. Es stellt eine zentrale Informationsdrehscheibe dar, die den informellen Austausch innerhalb des Vereins fördern soll.
#### 5.3.1 Struktur und Anzeige
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, die über einen Rich-Text-Editor gepflegt werden kann. Ergänzt wird dies durch Metadaten wie Erstellungsdatum und Autor.
#### 5.3.2 Automatisierter E-Mail-Digest
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
#### 5.3.3 Reporting System
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.
#### 5.3.4 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.
## 6 Learnings
### 6.1 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-und-verzug) gekommen. Hätte ich mich vor dem Start der Diplomarbeit mit dem Deployment von Oqtane auseinander gesetzt, dann wäre das in [Probleme mit Oqtane](#Probleme mit Oqtane) beschriebene Problem früher aufgekommen und der Zeitverzug wäre nicht so groß, oder noch ganz vermeidbar gewesen.
### 6.2 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.
### 6.3 Arbeitszeiteinschätzung (Zeitverzug)
Ein wesentliches Learning aus dem Projektverlauf war die Diskrepanz zwischen der initialen Planung und dem tatsächlichen Aufwand. Ursprünglich wurde der Zeitaufwand für das Aufsetzen der Infrastruktur und die Einarbeitung in das Oqtane-Framework auf etwa drei Wochen geschätzt. In der Realität nahm dieser Prozess jedoch mehrere Monate in Anspruch.
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.
- `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.
Reaktion auf den Verzug:
Um das Projektziel dennoch zu erreichen, wurde der Zeitplan im Herbst 2025 massiv gestrafft. Durch die Umstellung auf einen strikteren 14-tägigen Sprint-Rhythmus und die Priorisierung von Core-Funktionalitäten (MVP-Ansatz) konnte der Rückstand teilweise aufgeholt werden.
> Fazit: Die Erfahrung zeigt, dass gerade bei "Nischen-Frameworks" wie Oqtane ein deutlich höherer Puffer für die Einarbeitungs- und Infrastrukturphase (Faktor 2 bis 3 der ursprünglichen Schätzung) eingeplant werden muss.
`90% fertig, oder fertig?`: Es gibt einige "Regeln", wie: das `Paretoprinzip`, `Hofstadters 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), 896901. https://doi.org/10.1145/4284.315122) [^8]
> Diese Diplomarbeit liefert weitere Evidenz, dass diese Faustregel stimmt.
### 6.4 Sprints und Meetings (in Zukunft ja asynchron)
Ein zentrales Problem in unserer ursprünglichen Arbeitsweise war die Kopplung von Besprechungsterminen mit festen „Commit-Deadlines“ (dem Ende des aktuellen Sprint zyklusses). Da wir uns einmal pro Woche für sechs Stunden am Stück trafen, entstand ein destruktives Muster:
- Der "Last-Minute-Commit"-Druck: In den Stunden unmittelbar vor dem Meeting wurden Aufgaben unter Zeitdruck abgeschlossen, um im Meeting Fortschritte präsentieren zu können. Dies führte dazu, dass unfertiger oder unzureichend getesteter Code („Quick and Dirty“) in das Repository gepusht wurde.
- Fehlende Review-Kultur: Da die Commits erst kurz vor dem Meeting eintrafen, blieb dem restlichen Team keine Zeit für fundierte Code-Reviews. Die Besprechungszeit wurde somit für die Fehlersuche statt für strategische Planung genutzt.
- Ineffizienz: Lange Präsenz-Meetings blockierten wertvolle Entwicklungszeit, ohne die technische Qualität zu steigern.
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)
- 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.
# Quellen
[^1]: https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/architectural-principles#dependency-inversion
[^2]: https://blog.logrocket.com/dependency-inversion-principle/
[^3]: https://www.oodesign.com/dependency-inversion-principle
[^4]: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection/overview
[^5]: https://www.oqtane.org/#about
[^6]: https://docs.oqtane.org/dev/extensions/index.html
[^7]: https://en.wikipedia.org/wiki/Blazor
[^8]: https://dl.acm.org/doi/10.1145/4284.315122
[^9]: https://martinfowler.com/articles/injection.html
[^10]: https://andrewlock.net/implementing-custom-token-providers-for-passwordless-authentication-in-asp-net-core-identity/#changing-the-default-token-lifetime
[^11]: https://www.cs.umd.edu/projects/syschat/raceConditions.pdf
[^12]: https://docs.gitea.com/
[^13]: https://docs.gitea.com/installation/comparison#issue-tracker
[^14]: https://docs.gitea.com/usage/pull-request
[^15]: https://docs.gitea.com/usage/actions/overview
[^16]: https://docs.gitea.com/usage/packages/overview