\cleardoublepage # Konstantin Hintermayer ## Einleitung ### Motivation 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)? ### Auftrag und persönliche Aufgabenstellungen Mein Aufgabenbereich in diesem Projekt war vielseitig und umfasste sowohl leitende als auch tiefgreifende technische Aspekte. Die Rollen lassen sich in drei Kerngebiete unterteilen: #### Projektleitung und Organisation (Product Owner) \ Als Product Owner war ich für die Definition der Produktvision und die Priorisierung des Backlogs verantwortlich. Dies beinhaltete: - **Anforderungsmanagement**: Erhebung und Strukturierung der Anforderungen in Zusammenarbeit mit den Betreuern und dem Team. - **Sprint-Planung**: Organisation der 14-tägigen Sprints in YouTrack, um einen kontinuierlichen Entwicklungsfluss sicherzustellen. - **Qualitätssicherung**: Definition der *Definition of Done* (DoD) und Durchführung von Code-Reviews zur Einhaltung von Architekturstandards. #### Infrastruktur und Systemarchitektur \ Ein wesentlicher Teil meiner Arbeit lag in der Bereitstellung der technischen Basis für das gesamte Team: - **Deployment-Strategie**: Konzeption und Umsetzung der Server-Infrastruktur auf Basis von Debian Linux und NginX als Reverse-Proxy. - **Datenbankdesign**: Entwurf des relationalen Datenmodells in PostgreSQL, inklusive der Absicherung durch SSL/TLS. - **CI/CD-Pipeline**: Automatisierung der Build- und Deployment-Prozesse mittels Gitea Actions für eine effiziente Integration der Teambeiträge. #### Modulentwicklung \ Zusätzlich zur Infrastruktur habe ich drei zentrale Module für den Alumnihub entworfen und implementiert: 1. **Anmeldetool (EventRegistration)**: Ein Modul zum verwalten von Anmeldungen für Veranstaltungen. Es ermöglicht die einfache Erstellung von Einladungen zu Veranstaltungen und die Verwaltung von Anmeldungen. 2. **Reporting System**: Ein generisches System zur Meldung von Inhalten, das nach dem *Open-Closed-Prinzip* entworfen wurde, um eine einfache Erweiterbarkeit für alle anderen Module zu bieten. 3. **Schwarzes Brett (BlackBoard)**: Ein Community-Modul für den Austausch von Informationen, inklusive eines automatisierten E-Mail-Digest-Systems zur Nutzerbenachrichtigung. ## Anforderungen an das entwickelte Modul bzw. die Funktionalität ### Modulanforderungen / funktionale Anforderungen Die funktionalen Anforderungen beschreiben die spezifischen Dienste und Funktionen, die das System für die Benutzer bereitstellen muss. Im Rahmen der individuellen Aufgabenstellung wurden Anforderungen für fünf Teilbereiche definiert: #### Anmeldetool (EventRegistration) \ Das Ziel des Anmeldetools ist die effiziente Organisation von Vereinsveranstaltungen. - **Veranstaltungsmanagement**: Administratoren müssen in der Lage sein, neue Veranstaltungen anzulegen. Dabei müssen Name, Beschreibung, Datum, Zeit und Ort festlegbar sein. - **Anmeldeprozess**: Registrierte Benutzer müssen sich für eine Veranstaltung an- oder abmelden können. - **Teilnehmerliste**: Für jede Veranstaltung muss eine Übersicht der Rückmeldungen (Anmeldungen/Absagen) für Administratoren einsehbar sein. - **Statistische Auswertung**: Die Rückmeldungen sollen grafisch (z. B. als Tortendiagramm) aufbereitet werden, um die Planung zu erleichtern. #### Globales Reporting System \ Das Reporting System dient der Qualitätssicherung von Benutzerinhalten über alle Module hinweg. - **Inhalte melden**: Benutzer müssen die Möglichkeit haben, unangemessene Einträge (z. B. am Schwarzen Brett) zu melden. Dabei muss ein Grund für die Meldung angegeben werden können. - **Generische Schnittstelle**: Das System muss so entworfen sein, dass beliebige andere Module (z. B. Hall of Fame) die Meldefunktion ohne Änderungen am Kern des Reporting-Systems einbinden können. - **Administrations-Dashboard**: Gemeldete Inhalte müssen in einer zentralen Übersicht für Administratoren aufgelistet werden. - **Moderationsaktionen**: Administratoren müssen gemeldete Inhalte löschen, die Meldung ignorieren oder den Ersteller verwarnen/sperren können. #### Schwarzes Brett (BlackBoard) \ Das Schwarze Brett fungiert als digitale Kommunikationsplattform für den Verein. - **Beiträge erstellen**: Benutzer müssen Textbeiträge erstellen können. Die Formatierung der Texte soll über einen Rich-Text-Editor möglich sein. - **Bilder-Upload**: Zu jedem Beitrag soll optional ein Bild hochgeladen werden können, welches automatisch für die Vorschau skaliert wird. - **Benachrichtigungs-System**: Das System soll regelmäßig (täglich/wöchentlich) eine Zusammenfassung neuer Beiträge per E-Mail an alle interessierten Mitglieder versenden. #### Mass Mailing (Admin) \ Dieses Modul ermöglicht die direkte Kommunikation des Vorstandes mit allen Mitgliedern. - **Rundmails verfassen**: Administratoren müssen E-Mails mit Betreff und Inhalt an alle registrierten Benutzer verfassen können. - **Personalisierung**: Die E-Mails sollen automatisch mit dem Namen des Empfängers personalisiert werden können. - **Verspätetes Senden**: Aufgrund von Versandlimits des Providers (Brevo) müssen die E-Mails in eine Warteschlange eingereiht und zeitversetzt in Batches versendet werden. #### Token Lifetime Management (Admin) \ Dies dient der Konfiguration sicherheitsrelevanter Parameter. - **Gültigkeitsdauer**: Administratoren müssen die Gültigkeitsdauer für temporäre Links (z. B. Passwort-Reset, E-Mail-Bestätigung) über eine grafische Oberfläche anpassen können. - **Einstellungs-Persistenz**: Die geänderten Werte müssen dauerhaft gespeichert werden und sofort für neue Token-Generierungen wirksam sein. ### Use Cases Um die Interaktion der Benutzer mit den Modulen zu verdeutlichen, wurden folgende Use Cases definiert: | ID | Name | Akteur | Beschreibung | | :---- | :---------------------- | :----------------- | :----------------------------------------------------------- | | UC-01 | Veranstaltung erstellen | Administrator | Ein Administrator legt ein neues Absolvententreffen mit Ort und Datum an. | | UC-02 | Zu Event anmelden | Mitglied | Ein Absolvent bestätigt seine Teilnahme an einem Event über die Weboberfläche. | | UC-03 | Inhalt melden | Mitglied | Ein Benutzer meldet einen beleidigenden Post am Schwarzen Brett über den "Melden"-Button. | | UC-04 | Meldung bearbeiten | Moderator | Ein Vorstandsmitglied sichtet eine Meldung und löscht den entsprechenden Beitrag. | | UC-05 | Rundmail versenden | Administrator | Der Vorstand erstellt eine Einladung zur Generalversammlung für alle 500 Mitglieder. | Table: Wesentliche Use Cases der entwickelten Module Es ist zu beachten, dass es sich hierbei um eine Auswahl handelt und nicht alle Use Cases der Module abgebildet werden. ## Technisches Umfeld Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, sowie das Bereitstellen des Services. ### Auswahlverfahren #### 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: - Piranha CMS > Piranha erscheint auf den ersten Blick nicht so flexibel wie Oqtane, es basiert auf .NET 8.0 und wird nicht so aktiv gewartet. - Umbraco > Bei Umbraco muss viel in der Admin Oberfläche von dem CMS gearbeitet werden, im Großen und Ganzen wirkt dieses CMS nicht so flexibel. Die Dokumentation wirkt auf den ersten Blick sehr gut! - DNN / Dot Net Nuke > Dieses CMS ist der Platzhirsch. Es wird von der DNN Foundation gewartet, arbeitet mit dem Dotnet Framework, welches nicht unter Linux läuft. Und ein Windows Server ist im Betrieb teurer und in der Absicherung aufwändiger. - Oqtane > Oqtane wirkt auf sehr modular und flexibel, auch innerhalb von Modulen kann man auf alle Funktionen des ASP.NET Core Frameworks verwenden. Die Dokumentation wirkt nicht besonders gut, aber ausreichend. Die enthaltenen Fehlinformationen und mangelnden Anleitungen für den Betrieb mit Linux sind erst im Nachhinein aufgefallen. Insbesondere aufgrund seiner sehr hohen Flexibilität, haben wir uns am Ende für Oqtane entschieden. #### 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: 1. Auf welche Art Datenbank setzen wir? SQL, NoSQL, Graph, ... 2. Mit welcher speziellen Implementierung bekommen wir Support und bei welcher haben wir Vorwissen im Team? 3. Ist das auserkorene System kompatibel mit dem CMS, auf dem wir aufbauen? Es war von Anfang an klar, dass es ein SQL-basiertes System wird, da wir im Team nur mit SQL-basierten Systemen Erfahrungen haben. Außerdem unterstützt unser CMS (Oqtane) nur SQL-basierte Systeme. In der Linuxwelt kommen jetzt nur noch ein paar Datenbankmanagementsysteme in die Auswahl: PostgreSQL, MySQL / MariaDB, SQLite. Da ist die Wahl auf PostgreSQL gefallen. Grund dafür war meine Vorerfahrung mit diesem Datenbankmanagementsystem, welche ich in meinem Nebenjob erlangt habe. ### Beschreibung und Architektur von Oqtane Oqtane ist ein Framework und CMS zur Entwicklung von Webseiten mithilfe von ASP.NET und Blazor. [@oqtane_about] 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`. [@oqtane_docs_extensions] Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Webseite (die Shell) festlegen. [@oqtane_docs_extensions] #### Architektur eines Moduls \ Ein Modul in Oqtane besteht aus vier Projekten: - Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. Dazu gehören unter anderem alle Repositories, Controller, Manager, Migrationen und Server-Services und Server-Startuplogik. - Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services, Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul. - Im 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 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). ### Zusammenspiel der Infrastruktur In diesem Kapitel erkläre ich wie die ausgewählten Komponenten zusammenspielen. #### NginX as Reverse Proxy \ NginX fungiert in unserer Infrastruktur als `Reverse Proxy`. Ein Reverse Proxy nimmt Anfragen aus dem Internet entgegen und leitet sie an interne Server (wie Kestrel) weiter. Dies bietet mehrere Vorteile: - **Sicherheit**: Die interne Applikation ist nicht direkt dem Internet ausgesetzt. - **SSL-Terminierung**: NginX übernimmt die rechenintensive Verschlüsselung (HTTPS), während die Applikation dahinter über einfaches HTTP kommuniziert. - **Statische Inhalte**: NginX kann statische Dateien (Bilder, CSS) effizienter ausliefern als ein Applikationsserver. Wir verwenden NginX für die SSL Terminierung. Das Zertifikat wird von Let's Encrypt bereit gestellt und mittels HTTP-Challenges und dem Certbot auf dem Server aktualisiert. Hier ist ein Auszug der NginX-Konfiguration (`nginx.conf`) für den Alumnihub: ```nginx server { listen 443 ssl; server_name alumni.example.com; ssl_certificate /etc/letsencrypt/live/alumni.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/alumni.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } } ``` 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. ```mermaid sequenceDiagram participant browser as Client participant nginx as NginX participant oqtane as Oqtane participant db as PostgreSQL browser->>+nginx: HTTPS => 0.0.0.0:443 nginx->>nginx: SSL Terminierung nginx->>+oqtane: HTTP => 127.0.0.1:5000 oqtane->>+db: SQL => 127.0.0.1:5432 db-->>-oqtane: SQL oqtane-->>-nginx: HTTP nginx-->>-browser: HTTPS ``` Zusätzlich gab es einen Administrationszugang zu den Servern, welcher über SSH möglich war. Dieser wurde für die Installation und Konfiguration der einzelnen Komponenten verwendet. Der SSH Service ist in jeder Umgebung anders erreichbar gewesen. | Umgebung | Administrationszugang | | :--------------------------- | :----------------------------------------------------------- | | Hetzner | Wireguard | | Schule | Highport | | LiveDesign | IPSEC VPN | Table: SSH Zugänge in den unterschiedlichen Umgebungen Die VPN basierten Zugänge sind tendenziell schwieriger zu finden und auszunutzen, während die Lösung in der Schule mittels Highport den SSH Service öffentlich erreichbar macht. Durch den `Highport` ist der SSH Service schwieriger zu finden. Zur Authentifizierung mit SSH verwenden wir SSH-Keys, da diese durch ihre komplexität sicherer sind, als Passwörter. ### Entwicklung mit ASP.NET #### Blazor [@wikipedia_blazor] \ 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: | Hosting-Modell | Ausführungsort | Interaktivität | Kommunikation | | :-------------------------- | :----------------- | :----------------- | :--------------------------- | | **Static Server** | Server | Keine | HTTP (Initialer Load) | | **Interactive Server** | Server | Hoch (Echtzeit) | SignalR / WebSockets | | **Interactive WebAssembly** | Client (Browser) | Hoch (Lokal) | REST API / HTTP | | **Interactive Auto ** | Server & Client (ab zweitem Besuch) | Hoch (Echtzeit / Lokal) | SignalR / Websockets / RestAPI / HTTP | | **Hybrid** | Native App (WebView) | Hoch (Lokal) | n/a (Mutterprozess) | Table: Vergleich der Blazor Hosting-Modelle Im Rahmen dieser Diplomarbeit haben wir und für den RenderModus Interactive Server entschieden. Dieser Modus ist für Oqtane die Standardeinstellung und bietet eine gute Balance zwischen Leistung und Benutzerfreundlichkeit. Das ist für unseren Anwendungsfall auch die Empfehlung von Oqtane selbst. [@oqtane_docs_rendermodes] Razor-Komponenten (in dieser Arbeit, sowie umgangssprachlich, auch oft nur Komponenten genannt) sind der Grundbaustein für Blazor Web Apps. Sie bestehen aus HTML, welches mit der Verwendung von inline C# beeinflusst werden kann. Blazor stellt sicher, dass das gerenderte Markup aktualisiert wird, wenn sich der Status der Komponente ändert. Dieser Code kann entweder vollständig in einer .razor Datei liegen, oder in einer seperaten Code-Behind-Datei. Inline C# Code wird mithilfe von `@`- Zeichen markiert. Hier ist ein Beispiel für einen einfachen Counter: ```razor

Counter

Count: @count

@code { private int count = 0; private void Increment() { count++; } } ``` Mit`@count` in Zeile 3 wird der Wert der Variablen count in den `

` Tag mit eingebaut. Mit `@onclick="Increment"` in Zeile 5 wird die onclick Property vom `