From ad8de7141f75b0af9dc64c8768c84f734733bbfb Mon Sep 17 00:00:00 2001 From: KoCoder Date: Mon, 23 Mar 2026 08:30:25 +0100 Subject: [PATCH 1/2] Fix --- ...uch-individueller-teil-Florian-Edlmayer.md | 2 +- debug.tex | 6007 ----------------- test.md | 1 - 3 files changed, 1 insertion(+), 6009 deletions(-) delete mode 100644 debug.tex delete mode 100644 test.md diff --git a/04-Diplomarbeitsbuch-individueller-teil-Florian-Edlmayer.md b/04-Diplomarbeitsbuch-individueller-teil-Florian-Edlmayer.md index d3c1831..a66db7a 100644 --- a/04-Diplomarbeitsbuch-individueller-teil-Florian-Edlmayer.md +++ b/04-Diplomarbeitsbuch-individueller-teil-Florian-Edlmayer.md @@ -556,7 +556,7 @@ Daraufhin wird der Benutzer zur LinkedIn-Authentifizierungsseite weitergeleitet. Nach erfolgreicher Authentifizierung sendet LinkedIn eine Antwort an die zuvor definierte Redirect-URL der Webanwendung. Diese Antwort enthält einen Autorisierungscode, der anschließend vom Server der Webanwendung gegen ein Zugriffstoken ausgetauscht wird. -Wie in Abschnitt 4.3.1 beschrieben, werden die abgerufenen Profildaten zur Identifikation oder Neuanlage des Benutzerkontos in der lokalen Datenbank verwendet. +Wie in Abschnitt 4.4.3.1 beschrieben, werden die abgerufenen Profildaten zur Identifikation oder Neuanlage des Benutzerkontos in der lokalen Datenbank verwendet. ### Implementierung des Premium-Bereichs diff --git a/debug.tex b/debug.tex deleted file mode 100644 index c5d6fc4..0000000 --- a/debug.tex +++ /dev/null @@ -1,6007 +0,0 @@ -% Options for packages loaded elsewhere -\PassOptionsToPackage{unicode}{hyperref} -\PassOptionsToPackage{hyphens}{url} -\documentclass[ - 12pt, - twoside]{article} -\usepackage{xcolor} -\usepackage[top=2.5cm, bottom=2cm, left=3cm, right=2cm, a4paper]{geometry} -\usepackage{amsmath,amssymb} -\setcounter{secnumdepth}{5} -\usepackage{iftex} -\ifPDFTeX - \usepackage[T1]{fontenc} - \usepackage[utf8]{inputenc} - \usepackage{textcomp} % provide euro and other symbols -\else % if luatex or xetex - \usepackage{unicode-math} % this also loads fontspec - \defaultfontfeatures{Scale=MatchLowercase} - \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} -\fi -\usepackage{lmodern} -\ifPDFTeX\else - % xetex/luatex font selection -\fi -% Use upquote if available, for straight quotes in verbatim environments -\IfFileExists{upquote.sty}{\usepackage{upquote}}{} -\IfFileExists{microtype.sty}{% use microtype if available - \usepackage[]{microtype} - \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts -}{} -\usepackage{setspace} -\makeatletter -\@ifundefined{KOMAClassName}{% if non-KOMA class - \IfFileExists{parskip.sty}{% - \usepackage{parskip} - }{% else - \setlength{\parindent}{0pt} - \setlength{\parskip}{6pt plus 2pt minus 1pt}} -}{% if KOMA class - \KOMAoptions{parskip=half}} -\makeatother -\usepackage{color} -\usepackage{fancyvrb} -\newcommand{\VerbBar}{|} -\newcommand{\VERB}{\Verb[commandchars=\\\{\}]} -\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} -% Add ',fontsize=\small' for more characters per line -\newenvironment{Shaded}{}{} -\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} -\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} -\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} -\newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{#1}} -\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} -\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} -\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} -\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} -\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} -\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} -\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} -\newcommand{\ExtensionTok}[1]{#1} -\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} -\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} -\newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{\textbf{#1}}} -\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} -\newcommand{\NormalTok}[1]{#1} -\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} -\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} -\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} -\newcommand{\RegionMarkerTok}[1]{#1} -\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} -\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} -\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\usepackage{longtable,booktabs,array} -\usepackage{calc} % for calculating minipage widths -% Correct order of tables after \paragraph or \subparagraph -\usepackage{etoolbox} -\makeatletter -\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} -\makeatother -% Allow footnotes in longtable head/foot -\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} -\makesavenoteenv{longtable} -\usepackage{graphicx} -\makeatletter -\newsavebox\pandoc@box -\newcommand*\pandocbounded[1]{% scales image to fit in text height/width - \sbox\pandoc@box{#1}% - \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}% - \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}% - \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both - \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}% - \else\usebox{\pandoc@box}% - \fi% -} -% Set default figure placement to htbp -\def\fps@figure{htbp} -\makeatother -% definitions for citeproc citations -\NewDocumentCommand\citeproctext{}{} -\NewDocumentCommand\citeproc{mm}{% - \begingroup\def\citeproctext{#2}\cite{#1}\endgroup} -\makeatletter - % allow citations to break across lines - \let\@cite@ofmt\@firstofone - % avoid brackets around text for \cite: - \def\@biblabel#1{} - \def\@cite#1#2{{#1\if@tempswa , #2\fi}} -\makeatother -\newlength{\cslhangindent} -\setlength{\cslhangindent}{1.5em} -\newlength{\csllabelwidth} -\setlength{\csllabelwidth}{3em} -\newenvironment{CSLReferences}[2] % #1 hanging-indent, #2 entry-spacing - {\begin{list}{}{% - \setlength{\itemindent}{0pt} - \setlength{\leftmargin}{0pt} - \setlength{\parsep}{0pt} - % turn on hanging indent if param 1 is 1 - \ifodd #1 - \setlength{\leftmargin}{\cslhangindent} - \setlength{\itemindent}{-1\cslhangindent} - \fi - % set entry spacing - \setlength{\itemsep}{#2\baselineskip}}} - {\end{list}} -\usepackage{calc} -\newcommand{\CSLBlock}[1]{\hfill\break\parbox[t]{\linewidth}{\strut\ignorespaces#1\strut}} -\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{\strut#1\strut}} -\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{\strut#1\strut}} -\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1} -\setlength{\emergencystretch}{3em} % prevent overfull lines -\providecommand{\tightlist}{% - \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} -\usepackage{float} -\floatplacement{figure}{H} -\raggedbottom -\usepackage{etoolbox} -\makeatletter -\patchcmd{\LT@array}{\tabskip\z@}{\tabskip\fill}{}{} -\makeatother - -% Rename Table prefix to Tab. -\AtBeginDocument{% - \renewcommand{\tablename}{Tab.} - \renewcommand{\figurename}{Abb.} - \renewcommand{\listtablename}{Tabellenverzeichnis} -} - -\usepackage[hyphens]{url} -\usepackage[hidelinks]{hyperref} -\usepackage[htt]{hyphenat} -\usepackage{microtype} -\setlength{\emergencystretch}{5em} % Increased to solve overfull lines - -\usepackage{tocloft} - -% Dotted lines for all levels in TOC -\renewcommand{\cftsecleader}{\cftdotfill{\cftdotsep}} -\renewcommand{\cftsubsecleader}{\cftdotfill{\cftdotsep}} -\renewcommand{\cftsubsubsecleader}{\cftdotfill{\cftdotsep}} - -% Bold section numbers and names -\renewcommand{\cftsecfont}{\bfseries} -\renewcommand{\cftsecpagefont}{\bfseries} - -% Adjust vertical spacing before sections -\setlength{\cftbeforesecskip}{0.5em} - -\usepackage{fvextra} -\fvset{breaklines=true} - -\usepackage{needspace} -\let\oldShaded\Shaded -\let\oldendShaded\endShaded -\renewenvironment{Shaded}{\needspace{8\baselineskip}\oldShaded}{\oldendShaded} - -\usepackage{fancyhdr} - -% Define the fancy style but don't activate yet -\fancypagestyle{fancy}{ - \fancyhf{} % clear all header and footer fields - \fancyhead[RO,LE]{\includegraphics[height=2cm]{images/preamble/logo.png}} - \fancyhead[LO,RE]{\nouppercase{\leftmark}} - \fancyfoot[RO,LE]{\thepage} - \renewcommand{\headrulewidth}{0.4pt} - \renewcommand{\footrulewidth}{0.4pt} - \newgeometry{top=2.5cm, bottom=4cm, left=3cm, right=2cm, includehead, includefoot, a4paper} - \setlength{\headheight}{2cm} - \setlength{\footskip}{1.5cm} -} - -\renewcommand{\sectionmark}[1]{\markboth{#1}{}} % Set section title to \leftmark - -% Default style for preamble/TOC -\pagestyle{plain} -\fancyhf{} -\fancyfoot[C]{\thepage} -\renewcommand{\headrulewidth}{0pt} -\renewcommand{\footrulewidth}{0pt} -\usepackage{bookmark} -\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available -\urlstyle{same} -\hypersetup{ - hidelinks, - pdfcreator={LaTeX via pandoc}} - -\author{} -\date{} - -\begin{document} - -\begin{titlepage} -\begin{minipage}[c]{0.25\textwidth} - \includegraphics[width=\textwidth]{images/preamble/szu.png} -\end{minipage} -\hfill -\begin{minipage}[c]{0.7\textwidth} - \raggedleft - \textbf{Schulzentrum HTL HAK Ungargasse} \\ - Höhere Lehranstalt für Informationstechnologie \\ - Ausbildungsschwerpunkt Netzwerktechnik -\end{minipage} -\rule{\textwidth}{0.4pt} - - \vspace{1cm} - - \begin{center} - \includegraphics[width=0.6\textwidth]{images/preamble/logo.png} \\ - \vspace{1.5cm} - - \textbf{\Huge DIPLOMARBEIT} \\ - \vspace{1cm} - \textbf{\huge AlumniHub} \\ - \vspace{0.5cm} - \textit{\Large Plattform für den Absolventenverein des SZ HTL HAK Ungargasse} - \end{center} - - \vspace{1.75cm} - - \begin{minipage}[t]{0.5\textwidth} - \textbf{Verfasser:} \\ - Adam Gaiswinkler \\ - Florian Edlmayer \\ - Konstantin Hintermayer - \end{minipage} - \begin{minipage}[t]{0.4\textwidth} - \textbf{Betreuer:} \\ - Prof. Thomas Gürth - \end{minipage} - - \vspace{0.5cm} - - \begin{minipage}[t]{0.5\textwidth} - \textbf{Klasse:} \\ - 5BHITN - \end{minipage} - \begin{minipage}[t]{0.4\textwidth} - \textbf{Schuljahr:} \\ - 2025/26 - \end{minipage} - - \vspace{0.75cm} - - \begin{minipage}[t]{0.5\textwidth} - \textbf{Abgabevermerk:} \\ - Wien, am 26.03.2026 - \end{minipage} - \begin{minipage}[t]{0.4\textwidth} - \textbf{Projektnummer:} \\ - 3U\_HI\_2026\_04 \\ - \hrulefill - \end{minipage} - - \vspace{0.25cm} - - \textbf{übernommen von:} \\ - \hrulefill -\end{titlepage} - -\newpage -\pagenumbering{Roman} -\cleardoublepage -\section*{Eidesstattliche Erklärung} -Ich erkläre, dass ich die vorliegende Diplomarbeit selbstständig und ohne fremde Hilfe verfasst, andere als die angegebenen Quellen und Hilfsmittel nicht benutzt, sowie die aus anderen Werken übernommene Inhalte durch Quellenangaben erkenntlich gemacht habe. - -\vspace{1.5cm} - -\begin{tabular}{@{}p{5cm}p{1cm}p{7cm}@{}} -Wien, am 26.03.2026 & & \hrulefill \\ -& & Adam Gaiswinkler -\end{tabular} - -\vspace{1.2cm} - -\begin{tabular}{@{}p{5cm}p{1cm}p{7cm}@{}} -Wien, am 26.03.2026 & & \hrulefill \\ -& & Florian Edlmayer -\end{tabular} - -\vspace{1.2cm} - -\begin{tabular}{@{}p{5cm}p{1cm}p{7cm}@{}} -Wien, am 26.03.2026 & & \hrulefill \\ -& & Konstantin Hintermayer -\end{tabular} - -\makeatletter -\renewcommand{\tableofcontents}{% - \@starttoc{toc}% -} -\renewcommand{\listoffigures}{% - \@starttoc{lof}% -} -\renewcommand{\listoftables}{% - \@starttoc{lot}% -} - -\setstretch{1.5} -\newpage - -\section*{Kurzfassung}\label{kurzfassung} - -In dieser Diplomarbeit geht es um die Entwicklung von „AlumniHub`` -- -einer Webanwendung für den Absolventenverein der HTL Ungargasse. Wir -haben die alte, händische Verwaltung durch ein modernes, automatisiertes -System ersetzt, das auf ASP.NET Core, Blazor und dem Oqtane CMS basiert. -Ziel war es, eine Plattform zu schaffen, die Kommunikation, -Event-Planung und Networking an einem zentralen Ort bündelt. - -Die technische Arbeit haben wir uns im Team aufgeteilt: Konstantin -Hintermayer hat als Product Owner die Linux-Serverinfrastruktur, die -PostgreSQL-Datenbank und die CI/CD-Pipelines aufgesetzt sowie das -digitale „Schwarze Brett`` programmiert. Adam Gaiswinkler hat das -responsive Design im Stil der Schule entworfen und das Event-Anmeldetool -sowie die „Hall of Fame`` inklusive PDF-Export umgesetzt. Florian -Edlmayer war für den Premiumbereich mit seinem Freigabe-Workflow -verantwortlich, hat die DSGVO-Vorgaben umgesetzt und den sicheren Login -über LinkedIn (OAuth 2.0) eingebaut. Das Ergebnis ist eine -leistungsstarke Plattform, die dem Verein die tägliche Verwaltungsarbeit -deutlich erleichtert. \cleardoublepage - -\section*{Abstract}\label{abstract} - -This diploma thesis covers the development of ``AlumniHub,'' a web -platform designed for the alumni association of the HTL Ungargasse. Our -goal was to replace their old, manual administration with an automated -system using ASP.NET Core, Blazor, and the Oqtane CMS. The platform now -handles communication, event planning, and networking in one central -place. - -The technical work was split between the team: Konstantin Hintermayer -(Product Owner) was responsible for the Linux server infrastructure, the -PostgreSQL database, and CI/CD pipelines, while also building the -digital ``Blackboard.'' Adam Gaiswinkler created the responsive UI in -the school's style and implemented the event registration tool and the -``Hall of Fame'' with automated PDF exports. Florian Edlmayer developed -the premium area and its approval workflow, ensured GDPR compliance, and -integrated the LinkedIn Login (OAuth 2.0). Overall, we built a -high-performance system that significantly simplifies the association's -daily administrative work. - -\newpage - -\section*{Danksagung}\label{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. - -\newpage - -\section*{Vorwort}\label{vorwort} - -Diese Diplomarbeit ist im Schuljahr 2025/2026 an der HTL SZU Ungargasse -im Rahmen des Projekts Alumnihub entstanden. Unser Ziel war es, zusammen -mit dem Absolventenverein die veraltete Mitgliederverwaltung zu -modernisieren und eine neue digitale Plattform für ehemalige -Schülerinnen und Schüler zu entwickeln. Was am Anfang nur eine -Pflichtaufgabe für die Schule war, wurde für uns schnell zu einem -Projekt, mit dem wir uns voll identifiziert haben. Besonders -herausfordernd war, dass unser Team im Laufe der Zeit kleiner wurde und -wir am Ende nur noch zu dritt waren. Konstantin Hintermayer, Florian -Edlmayer und Adam Gaiswinkler mussten deshalb viel mehr Verantwortung -übernehmen und technisches Wissen schneller aufbauen als eigentlich -geplant. Die Arbeit am AlumniHub war für uns die ideale Chance, das -Wissen aus der Theorie endlich mal in einem echten und anspruchsvollen -Softwareprojekt einzusetzen. Es war eine stressige, aber sehr lehrreiche -Zeit, und wir sind stolz auf das, was wir am Ende als Team abgeliefert -haben. - -\newpage - -\section*{Einsatz Künstlicher Intelligenz -(KI-Disclaimer)}\label{einsatz-kuxfcnstlicher-intelligenz-ki-disclaimer} - -Diese Diplomarbeit und die Software Alumnihub wurden von uns -eigenständig entwickelt. KI-Tools haben wir lediglich als Unterstützung -für Aufgaben wie Korrekturlesen, Übersetzungen oder zur gezielten -Recherche genutzt. Auch beim Debugging im Code war die KI eine Hilfe. -Der eigentliche Quellcode, die inhaltliche Ausarbeitung und alle -technischen Entscheidungen stammen jedoch direkt von uns. Sämtliche -KI-Vorschläge wurden von uns kritisch hinterfragt und nur nach eigener -Prüfung übernommen. - -\cleardoublepage -\pagestyle{empty} -\pagenumbering{arabic} -\setcounter{page}{1} - -\cleardoublepage - -\section*{Inhaltsverzeichnis}\label{inhaltsverzeichnis} - -\tableofcontents - -\cleardoublepage -\pagestyle{fancy} -\pagenumbering{arabic} - -\section{Einleitung Allgemeiner Teil}\label{einleitung-allgemeiner-teil} - -\subsection{Diplomarbeitsantrag}\label{diplomarbeitsantrag} - -\subsubsection{Ausgangslage}\label{ausgangslage} - -Der Absolventenverein verwaltet derzeit rund 300 Alumni, deren Daten in -einer CSV-Datei gepflegt werden. Die Event-Anmeldungen der letzten Jahre -erfolgten über ``Perspective Funnels'', dessen Lizenz mittlerweile -abgelaufen ist. Für die kommenden Veranstaltungen wird daher ein Ersatz -für die Event-Registrierung benötigt. Die aktuellen Abläufe sind -dezentral und teilweise manuell, was zu einem erhöhten -Verwaltungsaufwand und fehlender Übersicht führt. Eine integrierte -Plattform für Mitgliederverwaltung, Kommunikation und Event-Organisation -existiert bislang nicht. - -\subsubsection{Zielsetzung}\label{zielsetzung} - -Ziel der Diplomarbeit ist es, ein Content-Management-System als Basis -für eine innovative, barrierefreie und sichere Webseite des -Absolventenvereins zu nutzen, dabei vorhandene Funktionen des CMS -anzupassen und eigene Module wie eine Eventanmeldung, eine Hall of Fame, -ein Schwarzes Brett als Kommunikationsplattform sowie einen -Premiumbereich zu entwickeln. Die Anwendung soll modular, erweiterbar -und leicht wartbar sein und auf einem Schulserver betrieben werden, um -eine kontrollierte und geschützte Umgebung für die Verwaltung der -Mitglieder- und Veranstaltungsdaten zu gewährleisten. - -\subsubsection{Tatsächliches Ergebnis}\label{tatsuxe4chliches-ergebnis} - -Im Rahmen des Projekts konnten alle priorisierten Tickets aus dem -Product Backlog erfolgreich umgesetzt werden. - -Konstantin Hintermayer übernahm als Product Owner die Kommunikation mit -dem Auftraggeber und stellte einen funktionsfähigen Linux-Server als -technische Grundlage bereit. Zusätzlich erarbeitete er Skripte sowie -Dokumentationen zur Serverlandschaft und führte die Grundkonfiguration -des CMS durch. Weiters wurden die Module „Auswertung`` und „Schwarzes -Brett`` erfolgreich an den Kunden übergeben. - -Adam Gaiswinkler war für die Dokumentation der Benutzeroberfläche und -des Backends sowie für die Entwicklung eines CMS-Moduls zur Anmeldung -und für die „Hall of Fame`` verantwortlich. Auch die grundlegende -Konfiguration des CMS wurde erfolgreich umgesetzt. - -Florian Edlmayer entwickelte ein funktionierendes CMS-Modul für den -Premiumbereich der Absolventen. Zusätzlich erstellte er eine -vollständige und gesetzeskonforme Datenschutzerklärung. Ein weiterer -wichtiger Bestandteil war die erfolgreiche Implementierung einer -OAuth-Authentifizierung über LinkedIn. - -\subsection{Das Team}\label{das-team} - -Konstantin Hintermayer - -Geboren am: 25.05.2007 - -E-Mail: {[}konstantin.hintermayer@edu.szu.at{]} - -Individuelle Themenstellung: Projektleitung (Product Owner), (Server-) -Infrastruktur, Aufsetzen und Installieren der Server / Linux / -Datenbank, Adminzugriff, Skripten, Entwicklung der Auswertungen und des -schwarzen Bretts. - -Florian Edlmayer - -Geboren am: 20.08.2006 - -E-Mail: {[}florian.edlmayer@edu.szu.at{]} - -Individuelle Themenstellung: Entwicklung eines CMS-Moduls für den -Premiumbereich des Absolventenvereins,Verfassung der -Datenschutzerklärung und zuständig für Informationssicherheit, -Implementierung von OAuth, Datenbankmanagement. - -Adam Gaiswinkler - -Geboren am: 11.10.2006 - -E-Mail: {[}adam.gaiswinkler@edu.szu.at{]} - -Individuelle Themenstellung:Entwicklung zweier CMS-Module: (Anmeldetool -für Treffen und Hall of Fame), Grundkonfiguration des CMS, Starker Fokus -auf nutzerfreundliches und responsives Design, Web-Entwicklung mit C\# -und ASP.NET. - -\subsection{Fachliches -Umfeld(Technologien)}\label{fachliches-umfeldtechnologien} - -Im fachlichen Umfeld dieser Diplomarbeit kommt das -Content-Management-System Oqtane zum Einsatz. Oqtane basiert auf -modernen Webtechnologien wie ASP.NET Core und der Plattform .NET und -ermöglicht die Entwicklung modularer und skalierbarer Webanwendungen. -Durch seine komponentenbasierte Architektur können Funktionen in Form -von Modulen flexibel entwickelt und in die Anwendung integriert werden. -Dies erleichtert sowohl die Erweiterbarkeit als auch die Wartung der -Plattform. Besonders im Kontext dieser Arbeit bietet Oqtane eine -geeignete Grundlage, um eine dynamische und benutzerorientierte -Alumni-Plattform umzusetzen, da sowohl Inhalte als auch -Benutzerverwaltung effizient verwaltet werden können. - -Siehe Details unter: Konstantin Hintermayer individueller Teil - -\section{Projektplanung}\label{projektplanung} - -\subsection{Projektziele}\label{projektziele} - -\subsubsection{Hauptziele}\label{hauptziele} - -\begin{itemize} -\item - \textbf{HZ01 -- Verwaltung von Absolventenprofilen} Das System - ermöglicht die zentrale Erstellung und Pflege individueller Profile - für Absolventen. -\item - \textbf{HZ02 -- Organisation von Veranstaltungen} Die Applikation - stellt Funktionen zur Planung und Durchführung von Vereinstreffen und - Events bereit. -\item - \textbf{HZ03 -- Darstellung der Hall of Fame} Besondere Leistungen und - Erfolge von Absolventen werden in einer digitalen Ehrengalerie - präsentiert. -\item - \textbf{HZ04 -- Firmen- und Jobstellenmarkt} Integration einer - Plattform für Stellenangebote, Praktika und die Vernetzung mit - Partnerunternehmen. -\item - \textbf{HZ05 -- Zugriffsverwaltung und Sicherheit} Implementierung - einer rollenbasierten Zugriffskontrolle und Gewährleistung der - Datensicherheit nach DSGVO-Standard. -\item - \textbf{HZ06 -- Schülerzugang und CMS} Einbindung eines - Redaktionssystems für Beiträge und eines speziellen Zugangs für - aktuelle Schüler. -\end{itemize} - -\subsubsection{Hardwareanforderungen und -Infrastruktur}\label{hardwareanforderungen-und-infrastruktur} - -\begin{itemize} -\item - \textbf{HW01 -- Benutzerkapazität (300 Nutzer)} Das System unterstützt - mindestens 300 gleichzeitig registrierte Benutzer für Administration - und Nutzung. -\item - \textbf{HW02 -- Aktive Zugriffsrate (50 Zugriffe/Tag)} Die - Infrastruktur ist auf ca. 50 tägliche aktive Nutzer ohne - Performanceverluste ausgelegt. -\item - \textbf{HW03 -- Einfache Skalierbarkeit} Die Architektur erlaubt eine - flexible Erweiterung der Ressourcen ohne strukturelle Änderungen. -\item - \textbf{HW04/05 -- Hochverfügbarkeit (99,5 \%)} Der Betrieb erfolgt - auf skalierbaren Cloud-Servern mit einer angestrebten Verfügbarkeit - von 99,5 \% pro Jahr. -\item - \textbf{HW07 -- Disaster Recovery (24h)} Im Falle eines Totalausfalls - muss das System innerhalb von 24 Stunden wieder benutzbar sein. -\end{itemize} - -• \textbf{HW12/13 -- Automatisierte Sicherung} Implementierung einer -automatisierten Datensicherung für Datenbanken und Binaries auf -unabhängigen Speichern. - -• \textbf{RED-1 -- Redundanz der Datenbank} Die Datenbank wird zur -Ausfallsicherheit redundant geführt und nutzt automatische -Master-Promotion im Fehlerfall. - -\subsubsection{Schnittstellenanforderungen}\label{schnittstellenanforderungen} - -\begin{itemize} -\item - \textbf{SnT-1 -- REST-API (Frontend/Backend)} Bereitstellung einer API - zur Kommunikation zwischen dem Oqtane-CMS und dem Blazor-Frontend für - dynamische CRUD-Operationen. -\item - \textbf{SnT-2 -- SMTP-E-Mail-Versand (Brevo)} Einbindung des Brevo - SMTP-Dienstes für den Versand von bis zu 300 transaktionalen E-Mails - pro Tag. -\item - \textbf{SnT-3 -- LinkedIn OAuth (Phase 2)} Schnittstelle zur - Authentifizierung und zum automatisierten Abruf von Profildaten über - LinkedIn. -\end{itemize} - -\subsubsection{Software und -Zugriffsverwaltung}\label{software-und-zugriffsverwaltung} - -\begin{itemize} -\item - \textbf{SW-1/2 -- Barrierefreiheit und Browser-Support} Unterstützung - gängiger Browser und Einhaltung des WCAG 2.1 AA Standards für - Barrierefreiheit. -\item - \textbf{SW-4 -- Sicherer Administrationszugriff} Administrativer - Zugriff erfolgt ausschließlich über eine verschlüsselte VPN-Verbindung - (Wireguard) und SSH. -\item - \textbf{ZUG-1--4 -- Authentifizierung und Rollen} Implementierung - klassischer Login-Verfahren, Passwort-Reset-Funktionen und einer - detaillierten Benutzerverwaltung für Administratoren. -\item - \textbf{ZUG-6/7 -- Magic Link und 2FA (Phase 2)} Erweiterung der - Sicherheit durch passwortlose Anmeldung via E-Mail-Link und - Zwei-Faktor-Authentifizierung. -\end{itemize} - -\subsubsection{Funktionsmodule (Phase 2)}\label{funktionsmodule-phase-2} - -\begin{itemize} -\item - \textbf{HoF-1/2 -- Hall of Fame Funktionen} Nutzer können ihre Erfolge - online präsentieren und als ansprechendes PDF für Treffen exportieren. -\item - \textbf{JOB-1/2 -- Job- und Praktikumsbörse} Plattform für - Stellenanzeigen und Bewerbungen inklusive Dashboard für Arbeitgeber - und statistischen Auswertungen. -\item - \textbf{PRE-1--3 -- Premiumbereich} Exklusiver Zugang für - Premiummitglieder inklusive Einsicht in Ingenieuranträge und - erweiterter Event-Organisation. -\item - \textbf{ScB-1--4 -- Schwarzes Brett} Ein interaktiver Feed für - Nachrichten, Event-Ankündigungen und Werbung mit integriertem - Meldesystem für Inhalte. -\item - \textbf{AfT-1--5 -- Anmeldetool für Treffen} Umfassendes Tool zur - Eventerstellung, zum Versand von Einladungen (E-Mail/SMS) und zur - Zielgruppenfilterung. -\item - \textbf{Pro-1--4 -- Erweiterte Profilverwaltung} Nutzer können ihre - Daten manuell pflegen oder automatisiert mit ihrem LinkedIn-Profil - abgleichen lassen. -\end{itemize} - -\subsubsection{Daten und Dokumentation}\label{daten-und-dokumentation} - -\begin{itemize} -\item - \textbf{DB-1 -- PostgreSQL Datenbank} Entwicklung eines relationalen - Datenbankdesigns inklusive Indizierung und Verschlüsselung zur - Gewährleistung der Datenintegrität. -\item - \textbf{DOK-1--6 -- Projektdokumentation} Erstellung aller notwendigen - Handbücher (Benutzer, Admin, Git) und des Disaster-Recovery-Handbuchs. -\end{itemize} - -\subsubsection{Nicht-Ziele}\label{nicht-ziele} - -\begin{itemize} -\item - \textbf{NZ01 -- Zahlungsprozesse} Die technische Abwicklung von - Zahlungen im Premiumbereich liegt außerhalb des Projektscopes. -\item - \textbf{NZ02 -- Externe Kalenderlösungen} Die Integration externer - Dienste wie V-Calendar oder V-Event ist nicht vorgesehen. -\end{itemize} - -\subsection{Aufgabenverteilung}\label{aufgabenverteilung} - -\subsubsection{Konstantin Hintermayer}\label{konstantin-hintermayer} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.2051}} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.7949}}@{}} -\caption{Aufgabenverteilung Konstantin Hintermayer}\tabularnewline -\toprule\noalign{} -\endfirsthead -\endhead -\bottomrule\noalign{} -\endlastfoot -Themenstellung: & Die individuelle Themenstellung umfasst die Konzeption -und Umsetzung der Infrastruktur sowie die Entwicklung von Modulen für -Auswertungen und ein Schwarzes Brett innerhalb der Plattform. \\ -Ziele und Anforderungen & HW01, HW02, HW03, HW04/05, HW07, RED-1, SW-4, -ScB-1--4 \\ -\end{longtable} - -\subsubsection{Florian Edlmayer}\label{florian-edlmayer} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.1943}} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.8057}}@{}} -\caption{Aufgabenverteilung Florian Edlmayer}\tabularnewline -\toprule\noalign{} -\endfirsthead -\endhead -\bottomrule\noalign{} -\endlastfoot -Themenstellung: & Die individuelle Themenstellung umfasst die -Entwicklung eines Premiumbereichs sowie die Umsetzung von Datenschutz- -und Informationssicherheitsmaßnahmen, einschließlich Zugriffs- und -Profilverwaltung. \\ -Ziele und Anforderungen & HZ01, HZ05, HW12/13, SnT-3, ZUG-1--4, ZUG-6/7, -PRE-1--3, Pro-1--4, DB-1 \\ -\end{longtable} - -\subsubsection{Adam Gaiswinkler}\label{adam-gaiswinkler} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.2087}} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.7913}}@{}} -\caption{Aufgabenverteilung Adam Gaiswinkler}\tabularnewline -\toprule\noalign{} -\endfirsthead -\endhead -\bottomrule\noalign{} -\endlastfoot -Themenstellung: & Die individuelle Themenstellung umfasst die -Entwicklung einer Hall of Fame, die Implementierung eines Anmeldetools -für Treffen sowie die Konfiguration des Content-Management-Systems. \\ -Ziele und Anforderungen & HZ02, HZ03, HZ06, SnT-2, SW-1/2, HoF-1/2, -AfT-1--5 \\ -\end{longtable} - -\subsection{Geplante Projektablauf}\label{geplante-projektablauf} - -\subsubsection{Meilensteine}\label{meilensteine} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.0087}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.0405}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.9509}}@{}} -\caption{Meilensteine}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -\# -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Datum -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -\# -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Datum -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -\emph{1} & \emph{19.09.2025} & Fertigstellung und Abgabe des -Diplomarbeitsantrags. \\ -\emph{2} & \emph{30.10.2025} & {[}cite\_start{]}Server-Setup mit -SSH-Zugriff {[}cite: 83{]}{[}cite\_start{]}, CMS-Grundkonfiguration -(Oqtane) im SZU-Design {[}cite: 69, 83{]}{[}cite\_start{]}, -Implementierung der Eingabemaske und API für das Anmeldetool {[}cite: -137{]} {[}cite\_start{]}sowie Erstellung der DSGVO-Richtlinien {[}cite: -38{]} {[}cite\_start{]}und Backupstrategie{[}cite: 55, 62{]}. \\ -\emph{3} & \emph{27.11.2025} & {[}cite\_start{]}Entwicklung grafischer -Auswertungen für Anmeldedaten {[}cite: 120{]} {[}cite\_start{]}und -Integration der OAuth-Authentifizierung zum automatisierten Abruf von -Profildaten{[}cite: 78, 148{]}. \\ -\emph{4} & \emph{18.12.2025} & Realisierung des Schwarzen Bretts inkl. -{[}cite\_start{]}Sperrfunktion für Administratoren {[}cite: -133{]}{[}cite\_start{]}, Entwicklung des Hall of Fame Moduls mit -PDF-Generierung {[}cite: 105{]} {[}cite\_start{]}sowie Aufbau der -Premiumkunden-Verwaltung{[}cite: 113{]}. \\ -\emph{5} & \emph{21.01.2026} & {[}cite\_start{]}Erstellung der -technischen Systemdokumentation {[}cite: 155{]}{[}cite\_start{]}, -Durchführung von Modultests und Implementierung der -Premium-Serviceverwaltung{[}cite: 113{]}. \\ -\emph{6} & \emph{08.02.2026} & {[}cite\_start{]}Projektabschluss der -Infrastruktur-Tasks, Übergabe der Disaster-Recovery-Skripte {[}cite: -58{]} {[}cite\_start{]}und Finalisierung der gesamten -Projektdokumentation{[}cite: 155{]}. \\ -\emph{7} & \emph{12.03.2026} & Finale Abgabe des Diplomarbeitsbuchs. \\ -\emph{8} & \emph{22.04.2026} & Defensio (Projektabschluss). \\ -\end{longtable} - -\subsubsection{Sprints}\label{sprints} - -\begin{longtable}[]{@{}lllll@{}} -\caption{Sprints und deren Schwerpunkte}\tabularnewline -\toprule\noalign{} -\# & Beginn & Ende & Hinweis & Meilensteine \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\# & Beginn & Ende & Hinweis & Meilensteine \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -1 & 02.10.2025 & 16.10.2025 & & \\ -2 & 16.10.2025 & 30.10.2025 & & 1. Meilenstein \\ -3 & 30.10.2025 & 13.11.2025 & Herbstferien & \\ -4 & 13.11.2025 & 27.11.2025 & & 2. Meilenstein \\ -5 & 27.11.2025 & 11.12.2025 & & \\ -6 & 11.12.2025 & 25.12.2025 & Weihnachtsferien & 3. Meilenstein \\ -7 & 25.12.2025 & 08.01.2026 & Weihnachtsferien & \\ -8 & 08.01.2026 & 22.01.2026 & & 4. Meilenstein \\ -9 & 22.01.2026 & 05.02.2026 & Semesterferien & \\ -10 & 05.02.2026 & 19.02.2026 & & 5. Meilenstein \\ -11 & 19.02.2026 & 05.03.2026 & & \\ -12 & 05.03.2026 & 19.03.2026 & & 6. Meilenstein \\ -\end{longtable} - -\subsection{Projektumfeld Analyse}\label{projektumfeld-analyse} - -\subsubsection{Grafische Darstellung}\label{grafische-darstellung} - -\pandocbounded{\includegraphics[keepaspectratio]{39eb1359e85e22bd63fd1e8e89e8c71f3b107392.pdf}} - -\subsubsection{Beschreibung der wichtigsten -Umfelder}\label{beschreibung-der-wichtigsten-umfelder} - -\begin{longtable}[]{@{}llll@{}} -\caption{Projektumfelder und deren Bewertung}\tabularnewline -\toprule\noalign{} -ID & Name & Beschreibung & Bewertung \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -ID & Name & Beschreibung & Bewertung \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -8 & Konkurrenz & Potenziell vorhandene Konkurrenz & - \\ -\end{longtable} - -\subsection{Risikoanalyse}\label{risikoanalyse} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 10\tabcolsep) * \real{0.0153}} - >{\raggedright\arraybackslash}p{(\linewidth - 10\tabcolsep) * \real{0.0918}} - >{\raggedright\arraybackslash}p{(\linewidth - 10\tabcolsep) * \real{0.6582}} - >{\centering\arraybackslash}p{(\linewidth - 10\tabcolsep) * \real{0.1122}} - >{\centering\arraybackslash}p{(\linewidth - 10\tabcolsep) * \real{0.0714}} - >{\centering\arraybackslash}p{(\linewidth - 10\tabcolsep) * \real{0.0510}}@{}} -\caption{Risikoanalyse und Bewertung}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -\# -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Bezeichnung -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} & \begin{minipage}[b]{\linewidth}\centering -Wahrscheinlichkeit (\%) -\end{minipage} & \begin{minipage}[b]{\linewidth}\centering -Auswirkung (\%) -\end{minipage} & \begin{minipage}[b]{\linewidth}\centering -Risikowert -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -\# -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Bezeichnung -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} & \begin{minipage}[b]{\linewidth}\centering -Wahrscheinlichkeit (\%) -\end{minipage} & \begin{minipage}[b]{\linewidth}\centering -Auswirkung (\%) -\end{minipage} & \begin{minipage}[b]{\linewidth}\centering -Risikowert -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -1 & Infrastruktur & {[}cite\_start{]}Instabilität oder Fehlkonfiguration -der Cloud-Server (Hetzner CX22), die den Live-Betrieb -unterbrechen{[}cite: 45, 51{]}. & 60 & 90 & 5400 \\ -2 & Datenverlust & {[}cite\_start{]}Kritischer Ausfall der Datenbank -ohne erfolgreiche Wiederherstellung durch automatisierte Backups{[}cite: -51, 62{]}. & 15 & 95 & 1425 \\ -3 & DSGVO-Verstoß & {[}cite\_start{]}Fehlende Konformität bei der -Speicherung personenbezogener Daten oder beim Opt-In-Verfahren{[}cite: -38, 39, 128{]}. & 10 & 100 & 1000 \\ -4 & Sicherheitslücke & {[}cite\_start{]}Unbefugter Zugriff auf das -System durch Schwachstellen in der VPN- oder SSH-Verbindung{[}cite: -83{]}. & 15 & 85 & 1275 \\ -5 & API-Schnittstellen & {[}cite\_start{]}Ausfall oder Inkompatibilität -externer Dienste wie LinkedIn OAuth oder Brevo Mailservice{[}cite: 74, -78{]}. & 30 & 50 & 1500 \\ -6 & Performance & {[}cite\_start{]}Beeinträchtigung der Systemleistung -bei steigenden Zugriffszahlen in Phase 2{[}cite: 44, 46{]}. & 40 & 40 & -1600 \\ -7 & Wiederherstellung & {[}cite\_start{]}Überschreitung des geplanten -Disaster-Recovery-Zeitraums von 24 Stunden{[}cite: 51, 66{]}. & 25 & 70 -& 1750 \\ -8 & Oqtane-Integration & {[}cite\_start{]}Komplexität bei der -Entwicklung und Einbindung benutzerdefinierter CMS-Module{[}cite: 69, -72{]}. & 30 & 45 & 1350 \\ -9 & Dokumentation & {[}cite\_start{]}Lückenhafte technische -Dokumentation erschwert die Wartung durch den Absolventenverein{[}cite: -155{]}. & 20 & 30 & 600 \\ -\end{longtable} - -\subsubsection{Grafische Darstellung}\label{grafische-darstellung-1} - -\pandocbounded{\includegraphics[keepaspectratio]{663e9454cc5dacd0b2a92b630e8be28bbcb7a29d.pdf}} - -\subsection{Projektressourcen}\label{projektressourcen} - -\subsubsection{2.6.3 Personelle Ressourcen -(geplant)}\label{personelle-ressourcen-geplant} - -\begin{longtable}[]{@{}lc@{}} -\caption{Personelle Ressourcen}\tabularnewline -\toprule\noalign{} -Teammitglied & Personenstunden \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -Teammitglied & Personenstunden \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -\textbf{Konstantin Hintermayer} & 180 \\ -\textbf{Florian Edlmayer} & 180 \\ -\textbf{Adam Gaiswinkler} & 180 \\ -\textbf{SUMME} & \textbf{540} \\ -\end{longtable} - -\subsubsection{Persönliche -Ressourcen(real)}\label{persuxf6nliche-ressourcenreal} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1692}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2462}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2462}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3385}}@{}} -\caption{Persönliche Ressourcen(real)}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Monat/Datum -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Florian Edlmayer -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Adam Gaiswinkler -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Konstantin Hintermayer -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Monat/Datum -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Florian Edlmayer -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Adam Gaiswinkler -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Konstantin Hintermayer -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -30.05. & 1.0h & 1.0h & 0.2h \\ -13.06. & 0.5h & 0.8h & 13.8h \\ -27.06. & 1.2h & 2.1h & 1.5h \\ -11.07. & 0.8h & 0.5h & 5.0h \\ -25.07. & 1.5h & 1.2h & 2.5h \\ -08.08. & 0.5h & 1.5h & 1.0h \\ -22.08. & 1.0h & 2.0h & 1.8h \\ -05.09. & 2.3h & 1.4h & 3.2h \\ -19.09. & 1.8h & 2.8h & 4.5h \\ -03.10. & 10.8h & 18.1h & 22.8h \\ -17.10. & 1.0h & 5.5h & 10.8h \\ -31.10. & 8.0h & 3.5h & 2.2h \\ -14.11. & 3.8h & 10.0h & 5.0h \\ -28.11. & 6.0h & 14.3h & 22.5h \\ -12.12. & 25.0h & 20.0h & 30.0h \\ -26.12. & 15.0h & 14.7h & 25.0h \\ -09.01. & 3.0h & 20.0h & 25.0h \\ -23.01. & 30.0h & 12.5h & 24.0h \\ -06.02. & 17.5h & 47.9h & 16.0h \\ -20.02. & 31.0h & 9.5h & 24.0h \\ -06.03. & 42.9h & 24.0h & 8.7h \\ -\textbf{Gesamt} & \textbf{204.6h} & \textbf{213.3h} & \textbf{249.5h} \\ -\end{longtable} - -\subsection{Projektmanagement mit -Scrum}\label{projektmanagement-mit-scrum} - -\subsubsection{Grundlagen der -Scrum-Methode}\label{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. - -\pandocbounded{\includegraphics[keepaspectratio]{./images/02-Allgemein/scrum-framework.png}} -\emph{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. - -\subsubsection{Rollenverteilung im -Projektteam}\label{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. - -\subsubsection{Sprintplanung und -Umsetzung}\label{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. - -\subsubsection{Vorteile von Scrum für die -Webentwicklung}\label{vorteile-von-scrum-fuxfcr-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. - -\cleardoublepage - -\section{Adam Gaiswinkler}\label{adam-gaiswinkler-1} - -\subsection{1. Einleitung des individuellen -Teils}\label{einleitung-des-individuellen-teils} - -\subsubsection{1.1 Motivation}\label{motivation} - -Zu Beginn des Projekts war meine persönliche Motivation überschaubar. -Wie viele Schulprojekte startete auch AlumniHub zunächst als eine -Pflichtaufgabe -- ich war zwar von Anfang an dabei, jedoch ohne -besonders großes Interesse am Thema. Das Projekt war zu Beginn eine von -vielen schulischen Anforderungen, und ich sah es zunächst nicht als -etwas, mit dem ich mich wirklich identifizieren würde. Die -Aufgabenstellung klang zwar interessant, aber der persönliche Bezug -fehlte noch. - -Das änderte sich im Laufe des Projekts grundlegend -- und zwar durch -einen Umstand, den ich anfangs nicht als Chance gesehen hätte: die -Teamverkleinerung. Als das Team von ursprünglich sechs auf drei Personen -verkleinert wurde, änderte sich meine Rolle schlagartig. Plötzlich trug -ich deutlich mehr Verantwortung -- nicht nur für meinen eigenen Bereich, -sondern auch für das Gesamtprojekt. Aufgaben, die ursprünglich andere -übernehmen sollten, lagen nun in meinen Händen. Diese Situation zwang -mich, proaktiver zu handeln, eigenständiger zu entscheiden und tiefer in -die Materie einzutauchen als ursprünglich geplant. - -Genau in diesem Moment begann mein Interesse zu wachsen. Je mehr -Verantwortung ich übernahm, desto mehr identifizierte ich mich mit dem -Projekt und seinen Zielen. Ich merkte, dass die Entscheidungen, die ich -traf, direkte Auswirkungen auf das Endergebnis hatten -- und das -motivierte mich, die Arbeit wirklich gut zu machen und nicht nur -fertigzustellen. - -Die technische Herausforderung, eine moderne Webanwendung mit Blazor und -ASP.NET umzusetzen, sowie die Möglichkeit, ein echtes System für eine -reale Organisation zu entwickeln, wurden zur echten Motivation. Die -Aufgabenstellung bot mir die Chance, theoretisches Wissen aus dem -Unterricht in einem praxisnahen Umfeld anzuwenden und gleichzeitig einen -konkreten Mehrwert für den Absolventenverein zu schaffen. Rückblickend -war die Teamverkleinerung -- obwohl sie damals als Problem wahrgenommen -wurde -- einer der wichtigsten Faktoren für meine persönliche -Entwicklung im Rahmen dieses Projekts. - -\subsubsection{1.2 Individuelle -Themenstellung}\label{individuelle-themenstellung} - -Entwicklung des Anmeldetools und Hall-of-Fame-Moduls für Oqtane, -Integration in das bestehende CMS-System, Responsive UI-Entwicklung mit -Blazor und ASP.NET Core - -\subsubsection{1.3 Teamrolle}\label{teamrolle} - -Developer, Tester der eigenen Module - -\subsubsection{1.4 Untersuchungsanliegen}\label{untersuchungsanliegen} - -Modulentwicklung mit Blazor und ASP.NET Core, Integration eigenständiger -Module in die Oqtane-Architektur, Entwicklung reaktiver -Benutzeroberflächen mit Blazor-Komponenten, Responsive UI-Design mit -Bootstrap und eigenem CSS, PDF-Generierung mit QuestPDF, Fehlerbehebung -und Optimierung der mobilen Darstellung - -\subsubsection{1.5 Persönlicher -Aufgabenbereich}\label{persuxf6nlicher-aufgabenbereich} - -Der persönliche Aufgabenbereich umfasste die Entwicklung der beiden -zentralen CMS-Module der Plattform: das Anmeldetool für Veranstaltungen -sowie das Hall-of-Fame-Modul. Beide Module wurden als eigenständige, -wiederverwendbare Oqtane-Module konzipiert und vollständig in C\# und -Blazor implementiert. Neben der technischen Umsetzung lag ein besonderer -Fokus auf der Benutzerfreundlichkeit, der responsiven Darstellung und -der nahtlosen Integration in das bestehende CMS-System. - -\subsubsection{1.6 Abgrenzung der Arbeit}\label{abgrenzung-der-arbeit} - -Das Datenbankdesign sowie die Infrastruktur und das Server-Setup waren -nicht Teil meines persönlichen Aufgabenbereichs und wurden von anderen -Teammitgliedern verantwortet. Mein persönlicher Anteil beschränkt sich -auf die Entwicklung der Anwendungsschicht, konkret auf die -Implementierung der beiden CMS-Module -- das Anmeldetool und das -Hall-of-Fame-Modul -- sowie deren Integration in das bestehende System. - -\subsection{2. Technologien}\label{technologien} - -In diesem Kapitel werden die Technologien und Werkzeuge vorgestellt, die -für die Entwicklung des Anmeldetools, des Hall-of-Fame-Moduls und des -Oqtane-Themes eingesetzt wurden. Die Beschreibungen sind dabei so -gestaltet, dass sie auch für Leserinnen und Leser ohne technischen -Hintergrund verständlich sind. - -\subsubsection{2.1 C\# und ASP.NET Core}\label{c-und-asp.net-core} - -C\# ist eine moderne Programmiersprache von Microsoft, die besonders für -die Entwicklung von Webanwendungen und Softwaresystemen geeignet ist. -Sie ist klar strukturiert, gut lesbar und weit verbreitet in der -professionellen Softwareentwicklung. ASP.NET Core ist ein Framework -- -also eine Art Werkzeugkasten -- das auf C\# aufbaut und die Entwicklung -von Webseiten und Webanwendungen vereinfacht.\footnote{Microsoft (2026a) - (siehe Internet-/Intranetverzeichnis).} Es stellt vorgefertigte -Bausteine bereit, sodass man nicht alles von Grund auf neu programmieren -muss. Für AlumniHub bildete ASP.NET Core die technische Grundlage aller -entwickelten Module. - -\subsubsection{2.2 Blazor}\label{blazor} - -Blazor ist ein Framework, das es ermöglicht, interaktive Weboberflächen -direkt in C\# zu entwickeln.\footnote{Microsoft (2026b) (siehe - Internet-/Intranetverzeichnis).} Normalerweise werden solche -Oberflächen -- also alles, was der Benutzer auf dem Bildschirm sieht und -mit dem er interagiert -- mit einer anderen Programmiersprache namens -JavaScript umgesetzt. Blazor erlaubt es, dasselbe in C\# zu schreiben, -was die Entwicklung vereinheitlicht und übersichtlicher macht. Konkret -bedeutet das: Wenn ein Benutzer beispielsweise auf den „Zusagen''-Button -klickt, reagiert die Seite sofort und aktualisiert sich automatisch -- -ohne dass die gesamte Seite neu geladen werden muss. - -\subsubsection{2.3 Oqtane}\label{oqtane} - -Oqtane ist ein Content-Management-System (CMS) -- also eine Software, -mit der Webseiten und deren Inhalte verwaltet werden können, ähnlich wie -WordPress oder Typo3.\footnote{Oqtane Foundation (2026a) (siehe - Internet-/Intranetverzeichnis).} Das Besondere an Oqtane ist, dass es -vollständig auf Blazor und C\# aufbaut und eine modulare Architektur -besitzt: Man kann eigene Erweiterungen -- sogenannte Module -- -entwickeln und in das System einbinden, ohne den Kern der Software -verändern zu müssen.\footnote{Oqtane Foundation (2026b) (siehe - Internet-/Intranetverzeichnis).} Für AlumniHub wurde Oqtane als -Grundlage gewählt, weil es Benutzerverwaltung, Seitenstruktur und viele -weitere Standardfunktionen bereits mitbringt und somit viel -Entwicklungsaufwand spart. - -\subsubsection{2.4 Bootstrap und CSS}\label{bootstrap-und-css} - -CSS (Cascading Style Sheets) ist die Sprache, mit der das Aussehen einer -Webseite festgelegt wird -- also Farben, Schriftarten, Abstände und das -Layout. Bootstrap ist eine fertige Sammlung von CSS-Regeln und -Hilfsmitteln, die von Twitter entwickelt wurde und kostenlos verfügbar -ist.\footnote{Bootstrap (2026) (siehe Internet-/Intranetverzeichnis).} -Der große Vorteil von Bootstrap ist, dass es sogenanntes Responsive -Design einfach umsetzbar macht: Die Webseite passt sich automatisch an -verschiedene Bildschirmgrößen an -- egal ob Desktop, Tablet oder -Smartphone. Für AlumniHub wurde Bootstrap als Basis verwendet, ergänzt -durch eigenes CSS für das individuelle Erscheinungsbild der Plattform. - -\subsubsection{2.5 QuestPDF}\label{questpdf} - -QuestPDF ist eine kostenlose Open-Source-Bibliothek -- also eine fertige -Programmsammlung -- die es ermöglicht, PDF-Dokumente direkt aus C\#-Code -heraus zu erstellen.\footnote{QuestPDF (2026) (siehe - Internet-/Intranetverzeichnis).} Anstatt ein PDF manuell zu gestalten, -beschreibt man im Code wie das Dokument aussehen soll, und QuestPDF -generiert daraus automatisch eine fertige PDF-Datei. Im -Hall-of-Fame-Modul wurde QuestPDF eingesetzt, um jedem Absolventen zu -ermöglichen, sein eigenes Profil als visuell ansprechendes PDF -herunterzuladen. - -\subsubsection{2.6 Gitea}\label{gitea} - -Wenn mehrere Personen gemeinsam an einem Softwareprojekt arbeiten, -braucht man ein System, das alle Änderungen am Code nachverfolgt und -verhindert, dass sich Änderungen verschiedener Personen gegenseitig -überschreiben. Dieses Konzept nennt sich Versionskontrolle. Gitea ist -eine selbst gehostete Plattform für genau diesen Zweck -- ähnlich wie -GitHub, aber auf einem eigenen Server betrieben.\footnote{Gitea (2026) - (siehe Internet-/Intranetverzeichnis).} Jede Änderung am Code wird als -sogenannter „Commit'' gespeichert, sodass man jederzeit nachvollziehen -kann, wer wann was geändert hat, und bei Bedarf auf eine ältere Version -zurückwechseln kann. - -\subsubsection{2.7 Entwicklungsumgebung}\label{entwicklungsumgebung} - -Eine Entwicklungsumgebung -- auch IDE (Integrated Development -Environment) genannt -- ist ein Programm, das Entwicklerinnen und -Entwickler beim Schreiben von Code unterstützt. Sie bietet unter anderem -Funktionen wie automatische Vervollständigung, Fehlererkennung und -integrierte Debugging-Werkzeuge, die das Auffinden und Beheben von -Fehlern im Code erleichtern. - -Zu Beginn des Projekts wurde Visual Studio 2022 auf Windows verwendet. -Visual Studio 2022 ist die führende Entwicklungsumgebung von Microsoft -für .NET-Projekte und bietet eine umfangreiche Unterstützung für ASP.NET -Core und Blazor. Im Laufe des Projekts erfolgte jedoch ein Wechsel von -Windows auf macOS. Da Visual Studio 2022 auf Mac nicht mehr verfügbar -ist -- Microsoft hat die Mac-Version eingestellt -- wurde als Ersatz -JetBrains Rider eingesetzt.\footnote{JetBrains (2026) (siehe - Internet-/Intranetverzeichnis).} JetBrains Rider ist eine -next-generation IDE von JetBrains, die plattformübergreifend -funktioniert und eine moderne Entwicklungsumgebung für .NET-Projekte auf -macOS bietet. Der Umstieg auf JetBrains Rider ermöglichte es, die -Entwicklung auf dem neuen System ohne größere Unterbrechungen -fortzusetzen. - -\subsubsection{2.8 Plattformwechsel: Windows zu -macOS}\label{plattformwechsel-windows-zu-macos} - -Ein besonderer Aspekt der Entwicklung war der Wechsel von Windows auf -macOS während des Projektverlaufs. Unter Plattform versteht man in der -Softwareentwicklung das Betriebssystem, auf dem eine Anwendung läuft -- -also etwa Windows, macOS oder Linux. Dieser Wechsel brachte spezifische -Herausforderungen mit sich, da Oqtane primär für Windows entwickelt -wurde. Obwohl Oqtane grundsätzlich auch auf macOS und Linux lauffähig -ist, ist die Unterstützung für diese Plattformen veraltet und nicht -vollständig angepasst. In der Praxis bedeutete das: Der Code ließ sich -teilweise nicht fehlerfrei kompilieren -- also in ein lauffähiges -Programm umwandeln -- und Oqtane startete zunächst nur mit -Fehlermeldungen. Durch den Einsatz von JetBrains Rider als IDE konnten -diese Probleme weitgehend gelöst werden, da JetBrains Rider eine bessere -plattformübergreifende Integration bietet als die ursprünglich -verwendete Entwicklungsumgebung. - -\subsection{3. Module}\label{module} - -\subsubsection{3.1 Entwicklung des Oqtane -Themes}\label{entwicklung-des-oqtane-themes} - -\paragraph{3.1.1 Ziel des Themes}\label{ziel-des-themes} - -Im Rahmen des Projekts AlumniHub wurde ein eigenes Theme für das -Content-Management-System Oqtane entwickelt. Ziel dieser Entwicklung war -es, das Standarddesign von Oqtane vollständig durch eine -projektspezifische Benutzeroberfläche zu ersetzen, die den Anforderungen -des Absolventenvereins der HTL Ungargasse entspricht. Das Standardtheme -von Oqtane ist funktional, jedoch generisch gehalten und bietet keinen -Bezug zur Schule oder zum Projekt. Aus diesem Grund wurde frühzeitig die -Entscheidung getroffen, ein vollständig eigenes Theme zu entwickeln, das -sowohl optisch als auch technisch auf die Bedürfnisse der Plattform -zugeschnitten ist. - -Das visuelle Design orientiert sich dabei am bestehenden -Erscheinungsbild der offiziellen Schulwebseite szu.at. Es wurde bewusst -ein schlichtes Grau-Weiß-Farbschema gewählt, das eine klare, -professionelle und zeitlose Optik erzeugt. Auf auffällige Farben oder -komplexe Animationen wurde verzichtet, um die Inhalte in den Vordergrund -zu stellen und eine ruhige Benutzeroberfläche zu schaffen, die für ein -breites Publikum -- von Schülerinnen und Schülern über Lehrkräfte bis -hin zu ehemaligen Absolventinnen und Absolventen -- zugänglich ist. - -Neben der visuellen Gestaltung standen auch technische Anforderungen im -Mittelpunkt. Das Theme sollte auf unterschiedlichen Endgeräten -- sowohl -auf Desktop-Computern als auch auf Smartphones und Tablets -- -zuverlässig und benutzerfreundlich funktionieren. Responsive Design war -daher von Anfang an eine zentrale Anforderung. Darüber hinaus sollte das -Theme vollständig in die Oqtane-Architektur integriert sein, sodass alle -Standardfunktionen des CMS wie Benutzerverwaltung, Seitenverwaltung und -Modulintegration weiterhin ohne Einschränkungen genutzt werden können. - -\paragraph{3.1.2 Technische Umsetzung}\label{technische-umsetzung} - -Als technische Grundlage diente die Theme-Architektur von Oqtane. Das -Layout wurde in einer zentralen Razor-Datei (\texttt{Theme.razor}) -definiert, welche von der Basisklasse \texttt{ThemeBase} erbt. Durch -diese Vererbung stehen im Theme automatisch zentrale Funktionen des -Frameworks zur Verfügung, darunter der Seitenzustand -(\texttt{PageState}), Navigationsdaten, Systemeinstellungen sowie -Informationen über den aktuell angemeldeten Benutzer. Dies ermöglicht -eine tiefe Integration des Themes in das CMS, ohne dass zusätzliche -Schnittstellen oder externe Datenzugriffe notwendig sind. - -\subparagraph{3.1.2.1 Navigationsleiste}\label{navigationsleiste} - -Ein zentrales Element des Themes ist die fixierte Navigationsleiste am -oberen Rand der Seite. Sie ist in drei klar voneinander getrennte -Bereiche gegliedert: Auf der linken Seite befindet sich das Logo der HTL -Ungargasse, das als visuelles Erkennungsmerkmal der Schule dient und -beim Klick zur Startseite führt. In der Mitte werden die -Navigationspunkte der Plattform angezeigt, die dynamisch aus der -Seitenstruktur des CMS generiert werden. Auf der rechten Seite befinden -sich die Benutzerfunktionen, also Login, Registrierung und bei -angemeldeten Benutzern ein Link zum eigenen Profil. - -Die dynamische Generierung der Navigationspunkte stellte dabei eine -besondere Herausforderung dar. Das Oqtane-Framework stellt standardmäßig -eine \texttt{\textless{}Menu\textgreater{}}-Komponente bereit, die -automatisch alle im System registrierten Seiten in der Navigation -anzeigt. Diese Komponente gibt jedoch nicht nur öffentlich sichtbare -Inhaltsseiten aus, sondern auch interne Systemseiten wie Login, -Register, Reset, Profile, Search, Privacy, Terms, Not Found oder Admin. -Diese Seiten sind für den normalen Benutzer nicht relevant und sollten -daher nicht in der Hauptnavigation erscheinen. - -Da die Standardkomponente das Burger-Menü automatisch generierte und -keine Möglichkeit bot, dieses individuell anzupassen, wurde auf sie -verzichtet. Da ein eigenes, maßgeschneidertes Burger-Menü benötigt -wurde, wurde stattdessen eine vollständig eigene Navigation -implementiert. Dabei wurde auf die Basisklassen \texttt{MenuBase} und -\texttt{MenuItemsBase} zurückgegriffen, die von Oqtane bereitgestellt -werden und den Zugriff auf die Seitenliste ermöglichen. Die -Navigationspunkte werden direkt über \texttt{PageState.Pages} abgerufen -und anschließend mittels LINQ gefiltert. Dabei werden nur Root-Seiten -berücksichtigt, also Seiten ohne übergeordnete Seite -(\texttt{ParentId\ ==\ null}), die als Navigationsseite markiert sind -und nicht in einer manuell definierten Ausschlussliste -(\texttt{hiddenNames}) stehen. - -\begin{Shaded} -\begin{Highlighting}[] -\DataTypeTok{var}\NormalTok{ hiddenNames }\OperatorTok{=} \KeywordTok{new}\OperatorTok{[]} -\OperatorTok{\{} - \StringTok{"Login"}\OperatorTok{,} \StringTok{"Register"}\OperatorTok{,} \StringTok{"Reset"}\OperatorTok{,} \StringTok{"Profile"}\OperatorTok{,} - \StringTok{"Search"}\OperatorTok{,} \StringTok{"Privacy"}\OperatorTok{,} \StringTok{"Terms"}\OperatorTok{,} \StringTok{"Not Found"}\OperatorTok{,} \StringTok{"Admin"} -\OperatorTok{\};} - -\KeywordTok{foreach} \OperatorTok{(}\DataTypeTok{var}\NormalTok{ item }\KeywordTok{in}\NormalTok{ PageState}\OperatorTok{.}\FunctionTok{Pages} - \OperatorTok{.}\FunctionTok{Where}\OperatorTok{(}\NormalTok{p }\OperatorTok{=\textgreater{}}\NormalTok{ p}\OperatorTok{.}\FunctionTok{ParentId} \OperatorTok{==} \KeywordTok{null} - \OperatorTok{\&\&} \OperatorTok{!}\NormalTok{hiddenNames}\OperatorTok{.}\FunctionTok{Contains}\OperatorTok{(}\NormalTok{p}\OperatorTok{.}\FunctionTok{Name}\OperatorTok{)))} -\OperatorTok{\{} -\NormalTok{ @item}\OperatorTok{.}\FunctionTok{Name} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -Durch diesen Ansatz werden ausschließlich die für Benutzer relevanten -Inhaltsseiten in der Navigation angezeigt. Gleichzeitig bleibt die -Navigation vollständig dynamisch: Werden im CMS neue Seiten angelegt und -als Navigationsseiten markiert, erscheinen diese automatisch im Menü, -ohne dass eine Anpassung am Theme-Code notwendig ist. - -!{[}Abbildung 4.2: Filterlogik der Oqtane-Navigation{]} -(./images/06-Adam/navigationsfilter\_v2.svg) \emph{Abbildung 4.2: -Filterlogik zur Bereinigung der Oqtane-Navigation (Theme.razor)} Dies -reduziert den Wartungsaufwand erheblich und stellt sicher, dass die -Navigation stets dem aktuellen Stand der Plattform entspricht. - -\subparagraph{3.1.2.2 Responsive Design und -Burger-Menü}\label{responsive-design-und-burger-menuxfc} - -Da die Plattform auch auf mobilen Endgeräten genutzt werden soll, war -die Umsetzung eines responsiven Layouts eine wichtige Anforderung. Auf -Desktop-Geräten werden alle Navigationspunkte direkt in der -Navigationsleiste angezeigt. Auf kleineren Bildschirmen wie Smartphones -oder Tablets würde dies jedoch zu Platzproblemen führen, da die Anzahl -der Navigationspunkte die verfügbare Breite überschreiten kann. - -Aus diesem Grund wurde für mobile Endgeräte ein sogenanntes Burger-Menü -implementiert. Dabei handelt es sich um ein Icon mit drei horizontalen -Linien, das auf kleinen Bildschirmen anstelle der ausgeschriebenen -Navigationspunkte angezeigt wird. Beim Anklicken öffnet sich eine -seitliche Sidebar, in der alle Navigationspunkte vertikal untereinander -dargestellt werden. Die Sidebar ist so aufgebaut, dass der obere Bereich -die Navigationspunkte enthält und bei einer großen Anzahl von Einträgen -gescrollt werden kann. Am unteren Rand der Sidebar sind die Login- und -Registrierungsfunktionen fixiert, sodass diese unabhängig von der Anzahl -der Navigationspunkte immer sichtbar und erreichbar sind. - -Die technische Umsetzung des Burger-Menüs basiert auf einer -CSS-Checkbox-Lösung. Das Öffnen und Schließen der Sidebar wird über den -Zustand einer versteckten Checkbox gesteuert, der mittels CSS-Selektoren -ausgewertet wird. Dieser Ansatz ermöglicht eine funktionsfähige mobile -Navigation ohne den Einsatz zusätzlicher JavaScript-Frameworks oder -komplexer Logik. Die gesamte Darstellungslogik -- also welche Elemente -auf welcher Bildschirmgröße sichtbar sind -- wird über CSS Media Queries -gesteuert, die zwischen der Desktop- und der mobilen Ansicht -unterscheiden. - -\subparagraph{3.1.2.3 Pane-Struktur}\label{pane-struktur} - -Für den Inhaltsbereich der Plattform wurden mehrere sogenannte Panes -definiert. Panes sind in Oqtane Platzhalter-Bereiche innerhalb eines -Themes, in die später Module oder Inhalte eingefügt werden können. Durch -die Definition mehrerer Panes mit unterschiedlichen Breiten und -Positionen können Seiten sehr flexibel und ohne Änderungen am Theme-Code -strukturiert werden. - -Im entwickelten Theme stehen unter anderem folgende Panes zur Verfügung: -ein vollbreiter Bereich oben (\texttt{Top\ 100\%}), ein linker Bereich -(\texttt{Left\ 50\%}), eine rechte Seitenleiste -(\texttt{Right\ Sidebar\ 33\%}) sowie ein vollbreiter Bereich am unteren -Rand (\texttt{Bottom\ 100\%}). Diese Struktur ermöglicht es, Seiten -sowohl ein- als auch mehrspaltig aufzubauen, je nach den Anforderungen -des jeweiligen Inhalts. - -\subparagraph{3.1.2.4 Weitere -Integrationen}\label{weitere-integrationen} - -Neben Navigation und Layout wurden weitere Funktionen in das Theme -integriert. Die Cookie-Consent-Komponente von Oqtane wurde eingebunden, -sodass beim ersten Besuch der Plattform ein Hinweis zur Verwendung von -Cookies angezeigt wird. Diese Funktion ist über die Site-Einstellungen -von Oqtane steuerbar, das Theme rendert lediglich die entsprechende -Komponente. - -Darüber hinaus wurde das ControlPanel von Oqtane integriert, das -Administratorinnen und Administratoren direkten Zugriff auf -Verwaltungsfunktionen bietet. Login- und Registrierungsoptionen werden -über den \texttt{SettingService} aus den Site-Einstellungen geladen, -sodass diese Funktionen ohne Anpassungen am Code aktiviert oder -deaktiviert werden können. - -\paragraph{3.1.3 Herausforderungen}\label{herausforderungen} - -Die eigene Implementierung der Navigation über \texttt{PageState.Pages} -und eine LINQ-basierte Filterlogik erwies sich als die richtige -Entscheidung. Sie löste nicht nur das Problem der fehlenden -Anpassbarkeit der Standardkomponente, sondern brachte gleichzeitig einen -wesentlichen Mehrwert: Die Navigation ist vollständig wartungsfrei. -Werden im CMS neue Seiten angelegt, erscheinen diese automatisch im Menü --- ohne dass eine einzige Zeile Code angepasst werden muss. Zudem -ermöglichte dieser Ansatz die vollständige Kontrolle über das -Erscheinungsbild des Burger-Menüs, was mit der Standardkomponente nicht -möglich gewesen wäre. - -\subsubsection{3.2 Anmeldetool}\label{anmeldetool} - -\paragraph{3.2.1 Ziel des Moduls}\label{ziel-des-moduls} - -Das Anmeldetool wurde entwickelt, um Mitgliedern des Absolventenvereins -eine einfache und strukturierte Möglichkeit zu bieten, sich zu -Veranstaltungen und Treffen an- oder abzumelden. Ziel des Moduls ist es, -den organisatorischen Aufwand bei der Planung und Verwaltung von Treffen -deutlich zu reduzieren und gleichzeitig eine benutzerfreundliche -Oberfläche für alle Beteiligten bereitzustellen. - -Das Modul wurde als zusätzliche Funktionserweiterung in das bestehende -Content-Management-System integriert. Es ermöglicht sowohl die -Verwaltung der Veranstaltungen auf Seiten der Organisatoren als auch -eine intuitive Interaktion für die Teilnehmerinnen und Teilnehmer. Durch -den Einsatz moderner Webtechnologien konnte dabei eine reaktionsschnelle -und geräteübergreifend nutzbare Lösung geschaffen werden. - -\paragraph{3.2.2 Frontend (Eingabemaske)}\label{frontend-eingabemaske} - -Die Benutzeroberfläche des Anmeldetools wurde mithilfe von Blazor -realisiert, einem Framework der ASP.NET-Technologieplattform, das die -Entwicklung interaktiver Weboberflächen in C\# ermöglicht. Die -Eingabemaske wurde als eigenständige Blazor-Komponente implementiert, -die flexibel in verschiedene Seiten der Anwendung eingebettet werden -kann. - -Beim Aufruf der Seite wird dem Benutzer zunächst eine kurze Beschreibung -der jeweiligen Veranstaltung angezeigt. Im Anschluss stehen zwei klar -gekennzeichnete Schaltflächen zur Verfügung: Zusagen zur Bestätigung der -Teilnahme sowie Absagen zur Ablehnung. Die Schaltflächen wurden farblich -differenziert gestaltet -- eine grüne Hervorhebung signalisiert die -Zusage, eine rote Darstellung steht für die Absage. Diese Gestaltung -orientiert sich an etablierten Designkonventionen moderner -Webanwendungen und verbessert die intuitive Bedienbarkeit erheblich. -Darüber hinaus wurde besonderer Wert auf eine responsive Darstellung -gelegt, damit das Tool sowohl auf Desktop-Geräten als auch auf -Smartphones und Tablets problemlos genutzt werden kann. - -\paragraph{3.2.3 API-Schnittstelle}\label{api-schnittstelle} - -Die Anbindung des Anmeldetools an das bestehende CMS erfolgt über klar -definierte Schnittstellen innerhalb der ASP.NET-Architektur. Die -Komponente kommuniziert mit dem Backend, um Veranstaltungsdaten -abzurufen sowie Anmelde- und Absagestatus der Teilnehmenden zu -übermitteln und zu persistieren. - -Die Datenübertragung erfolgt nach dem Prinzip der sauberen -Komponentenarchitektur: Die Blazor-Komponente ist als eigenständige -Einheit konzipiert, die über Parameter und Rückruffunktionen mit -übergeordneten Seitenkomponenten kommuniziert. Diese Struktur -gewährleistet eine klare Trennung zwischen Darstellungslogik und -Datenzugriff und erleichtert zukünftige Erweiterungen der Schnittstelle -erheblich. - -\paragraph{3.2.4 Datenauswertung}\label{datenauswertung} - -Die im Anmeldetool erfassten Daten bilden die Grundlage für die -Verwaltung und Auswertung von Veranstaltungsteilnahmen. Organisatoren -können auf Basis der gespeicherten An- und Abmeldungen die -Teilnehmerzahlen einsehen und die Planung entsprechend anpassen. - -Die Architektur des Moduls ist bereits auf zukünftige Erweiterungen -ausgelegt. Geplante Erweiterungen umfassen eine übersichtliche -Teilnehmerliste mit Namen und Anmeldestatus, die Möglichkeit, eine -maximale Teilnehmeranzahl je Veranstaltung festzulegen sowie eine -direkte Speicherung und Auswertung der Anmeldedaten in einer Datenbank. -Durch diese Erweiterungen soll das Anmeldetool künftig nicht nur als -Interaktionselement für Teilnehmer, sondern auch als vollwertiges -Verwaltungswerkzeug für Veranstaltungsorganisatoren dienen. - -\paragraph{3.2.5 UX-Überlegungen (User -Experience)}\label{ux-uxfcberlegungen-user-experience} - -Ein zentraler Aspekt bei der Entwicklung des Anmeldetools war die -Benutzerfreundlichkeit der Oberfläche. UX (User Experience) bezeichnet -dabei die Gesamtheit aller Erfahrungen, die ein Benutzer bei der -Interaktion mit einer Anwendung macht -- von der visuellen Gestaltung -über die Bedienbarkeit bis hin zur allgemeinen Zufriedenheit mit dem -System. Die Module wurden so gestaltet, dass Benutzerinnen und Benutzer -die Funktionen ohne zusätzliche Schulung verwenden können. Eine klare -Struktur, eine intuitive Bedienung sowie ein konsistentes -Erscheinungsbild innerhalb des bestehenden Systems standen dabei im -Vordergrund. - -Während der Testphase wurden mehrere visuelle Darstellungsprobleme -identifiziert und behoben. Dazu zählten Fehler bei der -Overlay-Darstellung -- insbesondere in Bezug auf Hintergrundfarben, -Transparenzen und z-Index-Ebenen -- sowie sogenannte Clipping-Fehler auf -mobilen Endgeräten, bei denen Inhalte teilweise abgeschnitten oder -außerhalb des sichtbaren Bereichs angezeigt wurden. Die Layoutstruktur -und Elementgrößen wurden angepasst, ausreichende Abstände zu -Seitenrändern sichergestellt und Tests auf verschiedenen Browser- und -Gerätevarianten durchgeführt. - -Diese Maßnahmen stellen einen ersten Schritt in der kontinuierlichen -Verbesserung der mobilen Benutzeroberfläche dar. Weitere -Feinabstimmungen sind geplant, um das Anmeldetool langfristig als -stabile, benutzerfreundliche und geräteübergreifend konsistente Lösung -zu etablieren. - -\subsubsection{3.3 Hall of Fame}\label{hall-of-fame} - -Das Hall-of-Fame-Modul ist ein zentrales Modul der AlumniHub-Plattform. -Es dient dazu, ehemalige Absolventinnen und Absolventen der HTL -Ungargasse sichtbar zu machen und ihre beruflichen Werdegänge zu -präsentieren. Das Modul wurde als eigenständiges, wiederverwendbares -Oqtane-Modul entwickelt und ermöglicht es registrierten Benutzerinnen -und Benutzern, sich selbst mit einem persönlichen Profil einzutragen. - -\paragraph{3.3.1 Benutzeroberfläche}\label{benutzeroberfluxe4che} - -Die Benutzeroberfläche des Moduls besteht aus mehreren Komponenten, die -zusammen eine vollständige und benutzerfreundliche Verwaltung der -Hall-of-Fame-Einträge ermöglichen. - -\subparagraph{3.3.1.1 Übersichtsseite -(Index.razor)}\label{uxfcbersichtsseite-index.razor} - -Die Hauptseite der Hall of Fame ist die erste Seite, die Besucherinnen -und Besucher zu sehen bekommen. Sie zeigt alle veröffentlichten Einträge -in einem responsiven Kartenlayout. Auf Desktop-Geräten werden die Karten -in drei Spalten nebeneinander dargestellt, auf kleineren Bildschirmen -passt sich das Layout automatisch an und zeigt die Karten einspaltig -untereinander an. - -Jede Karte enthält das Foto der jeweiligen Person als großes -Vorschaubild im oberen Bereich. Darunter werden Name und -Abschlussjahrgang als Überschrift angezeigt. Im unteren Bereich der -Karte befindet sich ein Teaser der Beschreibung, also ein kurzer -Ausschnitt aus dem Werdegang der Person. Da Beschreibungen -unterschiedlich lang sein können, wurde die Kartenhöhe durch eine -Kombination aus CSS-Flexbox und einer Maximalhöhe mit -\texttt{overflow:\ hidden} vereinheitlicht. Dadurch weisen alle Karten -in einer Zeile dieselbe Höhe auf, was ein sauberes und gleichmäßiges -Erscheinungsbild der Übersichtsseite gewährleistet. Am unteren Rand -jeder Karte befindet sich ein „Details ansehen''-Button, der die -Besucherin oder den Besucher zur vollständigen Detailseite des Eintrags -weiterleitet. - -Über der Kartenliste befindet sich eine Filterleiste mit einer -Suchfunktion und einer Sortieroption. Die Suchleiste ermöglicht eine -Echtzeit-Suche über Name und Beschreibung aller Einträge -- die -Ergebnisse aktualisieren sich direkt beim Tippen, ohne dass die Seite -neu geladen werden muss. Neben der Suchleiste befindet sich ein -Sortier-Dropdown, über das zwischen verschiedenen Sortierkriterien -gewählt werden kann, darunter Datum, Name und Jahrgang. Ein -Toggle-Button mit dynamischem Pfeil-Icon ermöglicht das Umschalten -zwischen aufsteigender und absteigender Sortierrichtung. - -Für angemeldete Benutzerinnen und Benutzer wird im oberen rechten -Bereich der Seite ein zusätzlicher Button angezeigt. Hat die Person noch -keinen eigenen Eintrag erstellt, erscheint ein „Eintragen''-Button. -Existiert bereits ein Eintrag, ändert sich der Button automatisch zu -„Mein Eintrag'', über den der bestehende Eintrag bearbeitet werden kann. -Administratorinnen und Administratoren sehen zusätzlich Warnhinweise bei -gemeldeten Einträgen sowie einen Lösch-Button bei jedem Eintrag. - -\subparagraph{3.3.1.2 Detailseite -(Details.razor)}\label{detailseite-details.razor} - -Die Detailseite zeigt einen einzelnen Hall-of-Fame-Eintrag in seiner -vollständigen Form. Das Layout ist zweispaltig aufgebaut: Auf der linken -Seite befindet sich das Foto der Person, eingebettet in einen unscharfen -Bildhintergrund, der dasselbe Foto in einer größeren, weichgezeichneten -Version als Hintergrund verwendet. Dieser Effekt verleiht der Seite eine -moderne und ansprechende Optik. Das eigentliche Foto ist dabei als klar -umrandetes Porträtbild in der Mitte des linken Bereichs positioniert. - -Auf der rechten Seite werden zunächst eine Breadcrumb-Navigation („Hall -of Fame / Details'') sowie Name und Jahrgang der Person angezeigt. Der -Jahrgang wird in blauer Schrift als „Absolvent des Jahrgangs -{[}Jahr{]}'' dargestellt, was einen visuellen Akzent setzt und den -Jahrgang klar hervorhebt. Darunter folgt die vollständige Beschreibung -unter der Überschrift „Werdegang \& Erfolge''. - -Am unteren Rand der Seite befinden sich je nach Konfiguration des -Eintrags bis zu vier Buttons. Der „PDF Vorschau''-Button öffnet einen -modalen Dialog mit einer vollständigen Vorschau des generierten PDFs -sowie einem „Herunterladen''-Button. Der „Zurück''-Button führt zurück -zur Übersichtsseite. Falls die Person einen optionalen Link hinterlegt -hat, wird zusätzlich ein „Webseite besuchen''-Button angezeigt, der die -Besucherin oder den Besucher direkt zur externen Webseite der Person -führt. Für eingeloggte Benutzer gibt es außerdem einen „Melden''-Button, -über den ein Eintrag gemeldet werden kann. - -\subparagraph{3.3.1.3 Edit-Seite -(Edit.razor)}\label{edit-seite-edit.razor} - -Die Edit-Komponente dient sowohl zum Erstellen eines neuen Eintrags als -auch zum Bearbeiten eines bestehenden. Das Formular ist klar -strukturiert und enthält alle notwendigen Felder für einen vollständigen -Hall-of-Fame-Eintrag. - -Das Formular enthält zunächst ein Textfeld für den Namen der Person -sowie ein Zahlenfeld für den Abschlussjahrgang. Für die Beschreibung -wird ein Rich-Text-Editor eingesetzt, der Formatierungsmöglichkeiten wie -Fett, Kursiv, Listen und weitere Optionen bietet. Unterhalb des Editors -wird ein Live-Zeichenzähler angezeigt, der die aktuelle Zeichenanzahl in -Echtzeit aktualisiert und die maximal erlaubte Zeichenanzahl von 504 -Zeichen anzeigt. Dadurch sehen Benutzerinnen und Benutzer jederzeit, wie -viel Platz noch zur Verfügung steht. - -Für das Foto gibt es ein Upload-Feld mit einer Vorschaufunktion. Wird -ein Bild ausgewählt, wird es sofort als Vorschau angezeigt, bevor der -Eintrag gespeichert wird. Erlaubt sind nur JPG- und PNG-Dateien mit -einer maximalen Größe von 5 MB. Zusätzlich gibt es ein optionales -Link-Feld, in das eine externe Webseite der Person eingetragen werden -kann. - -Am unteren Rand des Formulars befinden sich zwei Speicheroptionen: „Als -Entwurf speichern'' und „Veröffentlichen''. Einträge im Entwurfsmodus -sind nur für die eigene Person sichtbar und erscheinen nicht in der -öffentlichen Übersicht. Erst durch das Veröffentlichen wird der Eintrag -für alle Besucherinnen und Besucher sichtbar. Eine Eigentümerprüfung -verhindert, dass Benutzerinnen und Benutzer fremde Einträge bearbeiten, -und eine Duplikatprüfung stellt sicher, dass pro Person nur ein Eintrag -erstellt werden kann. Dabei greifen die beiden Prüfungen zu -unterschiedlichen Zeitpunkten: Die Duplikatprüfung wird beim Erstellen -eines neuen Eintrags ausgeführt und verhindert, dass eine Person mehrere -Einträge anlegt. Die Eigentümerprüfung hingegen greift beim Bearbeiten -eines bestehenden Eintrags und stellt sicher, dass nur die Person, die -den Eintrag erstellt hat, diesen auch ändern kann. - -Der folgende Lebenszyklus zeigt die möglichen Zustände eines Eintrags -und die Übergänge zwischen ihnen: - -!{[}Abbildung 4.1: Lebenszyklus eines Hall-of-Fame-Eintrags{]} -(./images/06-Adam/hall\_of\_fame\_lebenszyklus\_v4.svg) \emph{Abbildung -4.1: Lebenszyklus eines Hall-of-Fame-Eintrags} - -\subparagraph{3.3.1.4 Meldefunktion}\label{meldefunktion} - -Die Meldefunktion ermöglicht es angemeldeten Benutzerinnen und -Benutzern, einen Hall-of-Fame-Eintrag zu melden, wenn dieser -unangemessene oder falsche Inhalte enthält. Durch Klicken auf den -„Melden''-Button auf der Detailseite öffnet sich ein kleines -Popup-Fenster, in das der Meldegrund eingetragen werden kann. Nach dem -Absenden wird die Meldung in der Datenbank gespeichert und im -Admin-Modul angezeigt. Administratorinnen und Administratoren können -dort alle eingegangenen Meldungen einsehen und bei Bedarf den -betreffenden Eintrag löschen oder freigeben. - -Die Meldefunktion ist dabei nicht direkt im Hall-of-Fame-Modul -implementiert, sondern wird über eine zentrale Schnittstelle aus einem -gemeinsamen Interfaces-Paket eingebunden. Dieses Konzept ermöglicht es, -dieselbe Melde-Oberfläche in beliebig vielen weiteren Modulen -wiederzuverwenden, ohne die Logik mehrfach implementieren zu müssen. - -!{[}Abbildung 6.1: Ablauf des globalen Reporting-Systems{]} -(./images/06-Adam/reporting\_sequence\_diagram.svg) \emph{Abbildung 6.1: -Ablauf des globalen Reporting-Systems (Sequenzdiagramm)} - -\subparagraph{3.3.1.5 PDF-Export}\label{pdf-export} - -Der PDF-Export ist eine besondere Funktion des Hall-of-Fame-Moduls. Er -ermöglicht es Benutzerinnen und Benutzern, ihren Eintrag als visuell -ansprechendes PDF-Dokument herunterzuladen. Die PDF-Generierung wird -über die Open-Source-Bibliothek QuestPDF in der Community-Edition -realisiert. - -Das generierte PDF folgt einem Glasmorphismus-Design und ist im Format -DIN A4 gehalten. Das Foto der Person wird als vollflächiges -Hintergrundbild verwendet, das die gesamte Seite ausfüllt. Im oberen -Bereich der Seite befindet sich ein halbtransparenter dunkler Bereich, -in dem der Name der Person in großen Großbuchstaben mit weitem -Zeichenabstand dargestellt wird. Darunter wird der Jahrgang mit erhöhtem -Zeichenabstand angezeigt. Im unteren Bereich der Seite befindet sich ein -weiterer halbtransparenter Bereich mit der vollständigen Beschreibung. -Der charakteristische Glaseffekt wird durch mehrschichtige -halbtransparente Hintergründe mit abgerundeten Ecken erzeugt, die dem -Dokument ein modernes und professionelles Erscheinungsbild verleihen. - -Die PDF-Vorschau kann direkt auf der Detailseite über den „PDF -Vorschau''-Button geöffnet werden. Es öffnet sich ein modaler Dialog, -der das generierte PDF in einer Vorschau anzeigt. Über einen -„Herunterladen''-Button kann das PDF direkt auf das Gerät gespeichert -werden. - -\paragraph{3.3.2 Datenmodell}\label{datenmodell} - -Das Modul verwendet zwei Entitäten, die in der Datenbank als Tabellen -abgebildet werden. - -\textbf{Entität HallOfFame} - -Die zentrale Entität repräsentiert einen einzelnen Absolventeneintrag -und wird in der Datenbanktabelle \texttt{SZUAbsolventenvereinHallOfFame} -gespeichert. - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.1875}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.1875}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.6250}}@{}} -\caption{Entität HallOfFame}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Spalte -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Datentyp -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Spalte -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Datentyp -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -\texttt{HallOfFameId} & \texttt{int} (PK, Auto-Inkrement) & -Primärschlüssel \\ -\texttt{ModuleId} & \texttt{int} (FK → \texttt{Module}) & Fremdschlüssel -zur Oqtane-Modulinstanz \\ -\texttt{Name} & \texttt{string} & Name der Person \\ -\texttt{Year} & \texttt{int} & Abschlussjahrgang \\ -\texttt{Description} & \texttt{string} & Beschreibung bzw. Werdegang \\ -\texttt{Image} & \texttt{string} & Relativer Pfad zum hochgeladenen -Foto \\ -\texttt{Link} & \texttt{string} & Optionaler externer Link \\ -\texttt{Status} & \texttt{string} (max. 50) & Veröffentlichungsstatus: -„Draft'' oder „Published'' \\ -\texttt{UserId} & \texttt{int} & ID der Benutzerin bzw. des Benutzers, -der den Eintrag erstellt hat \\ -\texttt{IsReported} & \texttt{bool} & Kennzeichnung, ob der Eintrag -gemeldet wurde \\ -\texttt{ReportReason} & \texttt{string} & (Legacy) Ursprüngliches Feld -für Meldegrund, abgelöst durch die Report-Tabelle \\ -\texttt{CreatedBy} & \texttt{string} & Erstellt von (Audit) \\ -\texttt{CreatedOn} & \texttt{DateTime} & Erstellzeitpunkt (Audit) \\ -\texttt{ModifiedBy} & \texttt{string} & Zuletzt geändert von (Audit) \\ -\texttt{ModifiedOn} & \texttt{DateTime} & Zeitpunkt der letzten Änderung -(Audit) \\ -\end{longtable} - -Die Entität implementiert das Oqtane-Interface \texttt{IAuditable}, -wodurch die Audit-Felder automatisch vom Framework befüllt werden. Der -Fremdschlüssel \texttt{ModuleId} verknüpft jeden Eintrag mit einer -bestimmten Modulinstanz und ermöglicht so den Multi-Tenant-Betrieb. - -\textbf{Entität HallOfFameReport} - -Die zweite Entität bildet einzelne Meldungen zu einem Eintrag ab und -wird in der Tabelle \texttt{SZUAbsolventenvereinHallOfFameReport} -gespeichert. - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.2277}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.1782}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.5941}}@{}} -\caption{Entität HallOfFameReport}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Spalte -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Datentyp -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Spalte -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Datentyp -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -\texttt{HallOfFameReportId} & \texttt{int} (PK, Auto-Inkrement) & -Primärschlüssel \\ -\texttt{HallOfFameId} & \texttt{int} (FK → -\texttt{SZUAbsolventenvereinHallOfFame}) & Zugehöriger Eintrag \\ -\texttt{Reason} & \texttt{string} & Meldegrund \\ -\texttt{CreatedBy} & \texttt{string} & Erstellt von (Audit) \\ -\texttt{CreatedOn} & \texttt{DateTime} & Erstellzeitpunkt (Audit) \\ -\texttt{ModifiedBy} & \texttt{string} & Zuletzt geändert von (Audit) \\ -\texttt{ModifiedOn} & \texttt{DateTime} & Zeitpunkt der letzten Änderung -(Audit) \\ -\end{longtable} - -Der Fremdschlüssel zu \texttt{SZUAbsolventenvereinHallOfFame} ist mit -kaskadierendem Löschen konfiguriert, sodass beim Löschen eines Eintrags -automatisch alle zugehörigen Meldungen entfernt werden. Zwischen den -beiden Entitäten besteht eine 1:n-Beziehung: Ein Eintrag kann beliebig -viele Meldungen besitzen. - -\paragraph{3.3.3 Datenbankmigrationen}\label{datenbankmigrationen} - -Die Datenbankstruktur wird über Entity Framework Core Migrationen -versioniert verwaltet.\footnote{Microsoft (2026c) (siehe - Internet-/Intranetverzeichnis).} - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.4545}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3636}} - >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.1818}}@{}} -\caption{Datenbankmigrationen im Hall-of-Fame-Modul}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Migration -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Versionsnummer -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Inhalt -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Migration -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Versionsnummer -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Inhalt -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -\texttt{InitializeModule} & \texttt{01.00.00.00} & Erstellt die -Haupttabelle mit allen Grundspalten sowie den Audit-Spalten \\ -\texttt{AddReportingColumns} & \texttt{01.00.00.02} & Erweitert die -Haupttabelle um die Spalten \texttt{IsReported} und -\texttt{ReportReason} \\ -\texttt{AddReportTable} & \texttt{01.00.00.03} & Erstellt die -eigenständige Report-Tabelle mit Fremdschlüssel zur Haupttabelle \\ -\end{longtable} - -\begin{quote} -\textbf{Hinweis:} Version \texttt{01.00.00.01} wurde im -Entwicklungsprozess übersprungen, da eine fehlerhafte Migration erstellt -und anschließend wieder gelöscht werden musste. -\end{quote} - -\paragraph{3.3.4 Implementierungsdetails und -Problemlösungen}\label{implementierungsdetails-und-problemluxf6sungen} - -Während der Entwicklung traten mehrere technische Herausforderungen auf, -die im Folgenden zusammen mit ihren Lösungen beschrieben werden. - -\textbf{Bild-Upload-System} - -In der ursprünglichen Version des Moduls mussten Benutzerinnen und -Benutzer eine Bild-URL manuell in ein Textfeld eingeben. Dies war wenig -benutzerfreundlich und erforderte, dass Bilder zunächst anderweitig -hochgeladen und verlinkt werden mussten. Das implementierte -Bild-Upload-System ersetzt dies durch eine -Blazor-\texttt{InputFile}-Komponente mit Live-Vorschau, -Fortschrittsanzeige und Lösch-Button. Die Upload-Methode prüft die -Dateigröße (maximal 5 MB), öffnet die Datei als Stream und übermittelt -sie als \texttt{MultipartFormDataContent} an den Server, der den -Dateityp serverseitig validiert, einen UUID-Dateinamen (Universally -Unique Identifier -- eine zufällig generierte, global eindeutige -Zeichenkette) generiert und die Datei speichert. Das System unterstützt -beide Blazor-Rendering-Modi. - -\textbf{Concurrency Exception beim Löschen} - -Beim Löschen von Einträgen mit vorhandenen Meldungen trat eine -\texttt{DbUpdateConcurrencyException} auf, verursacht durch Konflikte im -Entity Framework Change Tracker. Die Lösung bestand in der Aufteilung -der Löschoperation in zwei separate Transaktionen mit jeweils eigenem -DbContext: zuerst werden alle zugehörigen Meldungen gelöscht, danach der -Haupteintrag. - -\textbf{Kartendesign-Optimierung} - -Karten hatten ursprünglich unterschiedliche Höhen durch variierende -Beschreibungslängen. Die Lösung kombiniert CSS-Flexbox auf dem -Kartenelement mit einer Maximalhöhe von 150 Pixeln und -\texttt{overflow:\ hidden} auf dem Beschreibungscontainer, sodass alle -Karten einer Zeile dieselbe Höhe aufweisen. - -\textbf{Sortier-Toggle} - -Die ursprünglich fest codierten Sortierrichtungen wurden durch einen -Toggle-Button neben dem Sortier-Dropdown ersetzt, der mit einem -dynamischen Pfeil-Icon zwischen aufsteigender und absteigender -Sortierung umschaltet. Die Sortierlogik ist in einer berechneten -Eigenschaft gekapselt, die Suche und Sortierung kombiniert. - -\subsection{4. Übergangslösung \& -Probleme}\label{uxfcbergangsluxf6sung-probleme} - -\subsubsection{4.1 Übergangslösung (Sommer -2025)}\label{uxfcbergangsluxf6sung-sommer-2025} - -\paragraph{4.1.1 Gründe \& Technische -Umsetzung}\label{gruxfcnde-technische-umsetzung} - -Da AlumniHub zum Zeitpunkt des ersten Absolvententreffens im Sommer 2025 -noch nicht vollständig fertiggestellt war und das Hosting von Oqtane auf -dem Hetzner-Server zu unerwarteten technischen Problemen geführt hatte, -wurde im Team die Entscheidung getroffen, eine eigenständige -Übergangslösung zu entwickeln. Diese sollte pünktlich zur Veranstaltung -einsatzbereit sein und die wichtigsten Funktionen abdecken: die -Möglichkeit für Absolventinnen und Absolventen, ihre Teilnahme am -Treffen zu bestätigen oder abzusagen, sowie die Möglichkeit, direktes -Feedback zum Diplomprojekt AlumniHub abzugeben. - -Da für die Entwicklung nur wenig Zeit zur Verfügung stand und eine -vollständige Integration in die noch nicht fertige AlumniHub-Plattform -nicht realistisch war, wurde bewusst auf einen schlanken, eigenständigen -Technologie-Stack gesetzt. Dieser sollte schnell entwickelt, einfach -deploybar und zuverlässig betreibbar sein -- ohne die Komplexität eines -vollständigen CMS-Systems. - -Das Frontend der Übergangslösung wurde mit den grundlegenden -Webtechnologien HTML, CSS und JavaScript umgesetzt. Die Hauptseite -(\texttt{index.html}) präsentiert den Besucherinnen und Besuchern eine -übersichtliche und schlichte Oberfläche, die sich am Erscheinungsbild -der HTL Ungargasse orientiert -- mit dem Schullogo im Header und einem -Grau-Weiß-Farbschema. Im Mittelpunkt der Seite befindet sich ein -zentraler Button, über den ein modales Overlay-Formular geöffnet werden -kann. Über dieses Formular konnten Nutzerinnen und Nutzer ihre -E-Mail-Adresse eingeben und ihr Feedback zum Projekt abgeben. Die -Steuerung des Overlays erfolgt über JavaScript: Das Formular öffnet sich -beim Klick auf den Button und schließt sich automatisch, wenn außerhalb -des Formularfensters geklickt wird. Dadurch ist eine intuitive Bedienung -ohne zusätzliche Schaltflächen möglich. - -Für die Verarbeitung von Zu- und Absagen zum Absolvententreffen wurden -zusätzlich zwei separate Bestätigungsseiten erstellt: -\texttt{zusage.html} und \texttt{absage.html}. Diese Seiten werden dem -Nutzer nach dem erfolgreichen Absenden des jeweiligen Formulars -angezeigt und bestätigen den Eingang der Rückmeldung. Das Design aller -drei Seiten ist einheitlich gehalten und folgt dem gleichen -Layout-Prinzip mit Header, Logo und zentriertem Hauptinhalt. - -Das Backend der Lösung, das für die Verarbeitung der Formulardaten und -den Versand von Bestätigungs-E-Mails zuständig war, wurde von einem -Teammitglied entwickelt und war nicht Teil des eigenen Aufgabenbereichs. -Es wurde mit Node.js und dem Framework Express umgesetzt und auf einem -virtuellen Server bei Hetzner Cloud gehostet. - -\paragraph{4.1.2 Differenzen zur finalen -Lösung}\label{differenzen-zur-finalen-luxf6sung} - -Im direkten Vergleich zur finalen AlumniHub-Plattform unterscheidet sich -die Übergangslösung in mehreren wesentlichen Punkten. Während AlumniHub -auf dem vollständigen CMS Oqtane basiert und eine umfangreiche -Funktionspalette bietet -- darunter Benutzerverwaltung, Hall of Fame, -Anmeldetool, Datenauswertung und ein individuelles Theme -- beschränkte -sich die Übergangslösung bewusst auf das absolut Notwendige. - -Es gab keine Benutzerkonten und keine Authentifizierung. Jede Person, -die die Seite aufrief, konnte das Formular ausfüllen und absenden, ohne -sich vorher registrieren oder anmelden zu müssen. Es gab keine Datenbank -im klassischen Sinne -- die eingegangenen Formulardaten wurden -serverseitig als einfache JSON-Dateien gespeichert. Es gab keine -administrativen Funktionen, keine Übersichten und keine Möglichkeit, die -Daten direkt über eine Benutzeroberfläche auszuwerten. - -Diese bewusste Reduktion auf das Wesentliche war jedoch kein Nachteil, -sondern eine pragmatische Entscheidung: Die Lösung musste schnell -funktionieren und zuverlässig sein -- und das war sie. Nach dem -Absolvententreffen wurde die Seite nicht einfach abgeschaltet, sondern -zu einer reinen Feedback-Seite für das Diplomprojekt umfunktioniert. -Über diese Seite konnten Interessierte -- darunter Lehrkräfte, -Mitschülerinnen und Mitschüler sowie externe Besucher der Präsentation --- weiterhin direktes Feedback zum Projekt abgeben. Die Seite blieb so -lange in Betrieb, bis die vollständig entwickelte AlumniHub-Plattform -diese Funktion nativ übernahm. - -\subsubsection{4.2 Probleme}\label{probleme} - -\paragraph{4.2.1 Technische Probleme}\label{technische-probleme} - -Eine der größten technischen Herausforderungen im gesamten -Projektverlauf war der Zeitdruck, der insbesondere im Vorfeld des ersten -Absolvententreffens spürbar war. Da AlumniHub zu diesem Zeitpunkt noch -nicht einsatzbereit war, musste die Übergangslösung in sehr kurzer Zeit -konzipiert, entwickelt und in Betrieb genommen werden. Dieser Zeitdruck -führte dazu, dass keine ausreichende Zeit für gründliches Testen oder -für die Umsetzung zusätzlicher Funktionen blieb. - -Ein weiteres technisches Problem ergab sich durch den Wechsel von -Windows auf macOS während der Entwicklung. Da Oqtane primär für Windows -entwickelt ist und die macOS-Unterstützung veraltet bzw. nicht -vollständig angepasst ist, traten nach dem Plattformwechsel Build-Fehler -auf und Oqtane startete zunächst nur mit Fehlern. Diese Probleme -erschwerten die Weiterentwicklung erheblich, da zunächst die -Entwicklungsumgebung stabilisiert werden musste, bevor die eigentliche -Arbeit an den Modulen fortgesetzt werden konnte. Durch den Wechsel auf -JetBrains Rider als Entwicklungsumgebung konnten die Build-Probleme -schließlich behoben und die Arbeit an den Modulen erfolgreich -fortgesetzt werden. - -Ein weiteres technisches Problem betraf das Hosting von Oqtane auf dem -Hetzner-Server. Die Einrichtung und der Betrieb von Oqtane auf dem -Server bereiteten unerwartete Schwierigkeiten, die den regulären -Entwicklungsfortschritt verlangsamten. Da dieser Bereich nicht zum -eigenen Aufgabengebiet gehörte, konnten die genauen Ursachen nicht -vollständig nachvollzogen werden. Die Probleme wirkten sich jedoch auf -den gesamten Zeitplan des Projekts aus und waren mitverantwortlich -dafür, dass AlumniHub zum Zeitpunkt des ersten Treffens noch nicht -fertig war. - -In den letzten Monaten des Projekts wurde daher ein Wechsel des -Hosting-Anbieters vorgenommen. Statt Hetzner wird die Plattform nun bei -LiveDesign gehostet, einem österreichischen Unternehmen, das sich auf -Hosting, Webdesign und individuelle Webservices spezialisiert -hat.\footnote{LiveDesign (2026) (siehe Internet-/Intranetverzeichnis).} -LiveDesign betreibt seine Datacenter ausschließlich in Österreich und -bietet eine zuverlässige Infrastruktur für CMS-Systeme wie Oqtane. Durch -diesen Wechsel konnten die bestehenden Stabilitätsprobleme behoben und -der Betrieb der Plattform deutlich verbessert werden. - -\paragraph{4.2.2 Kontakt mit Oqtane- und -Hetzner-Support}\label{kontakt-mit-oqtane--und-hetzner-support} - -Im Verlauf des Projekts wurde sowohl der Support von Oqtane als auch der -Support von Hetzner kontaktiert, um Hilfe bei den aufgetretenen -technischen Problemen zu erhalten. - -Der Kontakt mit dem Oqtane-Support erfolgte über GitHub Issues sowie per -E-Mail. Die gemeldeten Probleme betrafen spezifische Verhaltensweisen -des Frameworks beim Hosting auf dem Hetzner-Server. Trotz der -Kontaktaufnahme konnte keine hilfreiche Antwort erhalten werden, die zur -Lösung der Probleme beigetragen hätte. Die offizielle Dokumentation -sowie vorhandene Community-Beiträge lieferten ebenfalls keine -ausreichenden Antworten auf die spezifischen Konfigurationsprobleme. - -Auch der Hetzner-Support wurde bezüglich der Serverprobleme kontaktiert. -Die Anfragen bezogen sich auf die Serverkonfiguration und mögliche -Ursachen für die Instabilität beim Betrieb von Oqtane. Auch hier führten -die Rückmeldungen nicht zu einer vollständigen Lösung des Problems. Die -Erfahrung zeigte, dass bei der Nutzung spezialisierter Frameworks auf -externen Hosting-Plattformen mit eingeschränktem Support gerechnet -werden muss und eine intensive Eigenrecherche oft unumgänglich ist. - -\paragraph{4.2.3 Organisatorische -Probleme}\label{organisatorische-probleme} - -Neben den technischen Herausforderungen gab es auch auf -organisatorischer Ebene ein zentrales Problem, das den Projektverlauf im -Sommer 2025 erheblich beeinflusste. Während der Sommermonate war die -aktive Mitarbeit innerhalb des Teams sehr ungleich verteilt. Ein -Großteil der Teammitglieder war urlaubsbedingt nicht oder nur -eingeschränkt erreichbar und beteiligte sich in dieser Zeit kaum am -Projekt. Nur ein kleiner Teil des Teams arbeitete in dieser Phase aktiv -weiter und trieb den Fortschritt voran. - -Diese Situation führte zu einer deutlichen Ungleichverteilung der -Arbeitsbelastung. Wenige Personen mussten in dieser Zeit deutlich mehr -Verantwortung übernehmen als ursprünglich geplant, was zu Frustration -und Verzögerungen führte. Im Nachhinein zeigt sich, dass klarere -Absprachen und verbindlichere Vereinbarungen zu Beginn des Sommers dazu -beigetragen hätten, diese Situation zu vermeiden oder zumindest -abzumildern. - -\subsection{5. Learnings}\label{learnings} - -\subsubsection{5.1 Technisch}\label{technisch} - -Das Projekt hat auf technischer Ebene wertvolle praktische Kenntnisse -vermittelt, die über den schulischen Rahmen hinausgehen. Der konsequente -Einsatz von Git zur Versionskontrolle war dabei eine der wichtigsten -Erfahrungen. Durch die tägliche Arbeit mit Branches, Commits und Merges -wurde ein tiefes Verständnis für kollaborative Softwareentwicklung -aufgebaut. Es wurde deutlich, wie wichtig aussagekräftige -Commit-Nachrichten, regelmäßige Commits und eine saubere Branch-Struktur -für die Zusammenarbeit im Team sind. - -Im Bereich Responsive Design wurden durch die praktische Umsetzung des -Themes und der Übergangslösung wichtige Kenntnisse vertieft. Dabei wurde -gelernt, wie man mit CSS Media Queries und Flexbox Layouts baut, die -sich zuverlässig an unterschiedliche Bildschirmgrößen anpassen. -Besonders die Umsetzung des Burger-Menüs für mobile Geräte war eine -lehrreiche Erfahrung, die zeigte, wie man komplexe UI-Funktionen mit -minimalem JavaScript-Einsatz realisieren kann. - -Auch der Umgang mit JavaScript zur Steuerung von UI-Elementen wurde -durch die Arbeit am Projekt verbessert. Die Implementierung der -Overlay-Steuerung in der Übergangslösung sowie die Menü-Logik im Theme -haben gezeigt, wie JavaScript gezielt und effizient eingesetzt werden -kann, um eine bessere Benutzererfahrung zu schaffen. - -\subsubsection{5.2 Methodisch}\label{methodisch} - -Auf methodischer Ebene hat das Projekt gezeigt, wie wichtig eine klare -und verbindliche Aufgabenverteilung von Beginn an ist. In Phasen, in -denen nicht klar war, wer welche Aufgaben übernimmt, entstanden Lücken -und Verzögerungen. Eine strukturiertere Planung mit klar definierten -Zuständigkeiten hätte in solchen Situationen geholfen, den Überblick zu -behalten und die Arbeit effizienter aufzuteilen. - -Darüber hinaus hat sich gezeigt, dass regelmäßige Team-Meetings ein -wichtiges Werkzeug für den Projekterfolg sind. In Phasen, in denen der -Austausch im Team spärlicher war, dauerte es länger, bis Probleme -erkannt und gelöst wurden. Kurze, regelmäßige Abstimmungen hätten dazu -beigetragen, den aktuellen Stand besser zu kommunizieren und gemeinsam -schneller auf Hindernisse zu reagieren. - -\subsubsection{5.3 Persönlich}\label{persuxf6nlich} - -Auf persönlicher Ebene war die wichtigste Erkenntnis aus diesem Projekt -die Bedeutung von Eigeninitiative. In einem größeren Teamprojekt kann -man sich nicht immer darauf verlassen, dass andere Aufgaben erledigen -oder Entscheidungen treffen. Gerade in den Phasen, in denen nicht alle -Teammitglieder aktiv waren, hat sich gezeigt, dass proaktives Handeln -entscheidend ist, um das Projekt voranzubringen. Diese Erfahrung hat das -Bewusstsein dafür gestärkt, Verantwortung nicht nur für den eigenen -Bereich, sondern auch für das Gesamtprojekt zu übernehmen und bei Bedarf -auch Aufgaben außerhalb des ursprünglich geplanten Bereichs zu -übernehmen. - -\subsection{6. Testen \& -Qualitätssicherung}\label{testen-qualituxe4tssicherung} - -\subsubsection{6.1 Funktionstests der -Module}\label{funktionstests-der-module} - -Alle entwickelten Module -- das Anmeldetool und das Hall-of-Fame-Modul --- wurden manuell auf ihre korrekte Funktionsweise getestet. Dabei -wurden sämtliche Benutzeraktionen systematisch durchgegangen, darunter -das An- und Abmelden zu Veranstaltungen, das Erstellen, Bearbeiten und -Veröffentlichen von Hall-of-Fame-Einträgen, das Hochladen von Bildern -sowie die Melde- und Löschfunktionen. Fehler und unerwartetes Verhalten -wurden dokumentiert und im Anschluss behoben. - -Beim Anmeldetool wurde insbesondere geprüft, ob die Zusage- und -Absage-Buttons korrekt reagieren und der Status unmittelbar in der -Oberfläche angezeigt wird. Beim Hall-of-Fame-Modul lag ein besonderer -Fokus auf dem Bild-Upload: Es wurde getestet, ob die Größenbeschränkung -von 5 MB korrekt greift, ob die Vorschau sofort erscheint und ob -ungültige Dateiformate abgelehnt werden. Auch die Duplikatprüfung -- -also die Sicherstellung, dass pro Person nur ein Eintrag erstellt werden -kann -- sowie die Eigentümerprüfung wurden gezielt getestet. - -\subsubsection{6.2 Theme-Tests}\label{theme-tests} - -Das entwickelte Oqtane-Theme wurde auf verschiedenen Browsern und -Geräten getestet, um eine konsistente Darstellung sicherzustellen. -Getestet wurde unter anderem auf aktuellen Versionen von Chrome, Firefox -und Safari sowie auf mobilen Geräten mit unterschiedlichen -Bildschirmgrößen. Ein besonderer Fokus lag dabei auf der korrekten -Darstellung des Burger-Menüs auf mobilen Endgeräten sowie auf der -Funktionsfähigkeit der dynamischen Navigation. - -\subsubsection{6.3 Usability-Tests}\label{usability-tests} - -Neben den technischen Tests wurde die Plattform auch von weiteren -Personen -- darunter Mitschülerinnen und Mitschüler sowie Lehrkräfte -- -auf ihre Benutzerfreundlichkeit geprüft. Das Feedback aus diesen Tests -floss in die weitere Entwicklung ein und führte unter anderem zu -Anpassungen in der Darstellung und Bedienung einzelner Elemente. - -Ein häufiges Feedback war, dass die Unterscheidung zwischen Zusage und -Absage auf den ersten Blick nicht immer sofort klar war. Daraufhin -wurden die Schaltflächen farblich deutlicher gestaltet -- Grün für die -Zusage, Rot für die Absage -- und die Beschriftungen präzisiert. Solche -Rückmeldungen aus echten Nutzertests sind wertvoll, weil Entwicklerinnen -und Entwickler ihre eigene Anwendung oft anders wahrnehmen als Personen, -die das System zum ersten Mal sehen. - -\subsection{7. Fazit und Ausblick}\label{fazit-und-ausblick} - -\subsubsection{7.1 Zielerreichung}\label{zielerreichung} - -Rückblickend auf das Projekt AlumniHub lässt sich festhalten, dass die -zentralen Ziele meines individuellen Aufgabenbereichs erfolgreich -umgesetzt wurden. - -Das \textbf{Hall-of-Fame-Modul} wurde vollständig fertiggestellt. Es -umfasst die Übersichtsseite mit responsivem Kartenlayout, die -Detailseite mit Glasmorphismus-Design, die Edit-Seite mit -Rich-Text-Editor und Bild-Upload, die Meldefunktion sowie den PDF-Export -mit QuestPDF. Das Modul ist in das Oqtane-CMS integriert und produktiv -einsetzbar. - -Das \textbf{Anmeldetool} wurde ebenfalls implementiert und ist -funktionsfähig. Grundfunktionen wie Zusage und Absage zu Veranstaltungen -sowie die responsive Darstellung sind vollständig umgesetzt. -Weiterführende Funktionen wie eine vollständige Teilnehmerliste mit -Datenbankanbindung und die Möglichkeit, maximale Teilnehmerzahlen -festzulegen, sind architektonisch bereits vorbereitet, jedoch noch nicht -vollständig implementiert. - -Das \textbf{Theme} wurde von einem anderen Teammitglied entwickelt und -ist ebenfalls fertiggestellt. Der Wechsel des Hostings von Hetzner zu -LiveDesign hat die Stabilität der Plattform deutlich verbessert. - -Insgesamt bin ich mit dem erreichten Stand zufrieden -- insbesondere -angesichts der Herausforderungen durch die Teamverkleinerung, den -Plattformwechsel von Windows auf macOS und die technischen Probleme mit -dem ursprünglichen Hosting. - -\subsubsection{7.2 Ausblick}\label{ausblick} - -Für die Weiterentwicklung der Plattform gibt es mehrere sinnvolle -nächste Schritte. Im Bereich des Anmeldetools wäre die Implementierung -einer vollständigen Teilnehmerliste mit direkter Datenbankanbindung der -wichtigste nächste Schritt. Ergänzend dazu sollte die Möglichkeit -geschaffen werden, maximale Teilnehmerzahlen pro Veranstaltung -festzulegen, sodass Organisatoren die Kapazität von Treffen besser -steuern können. - -Langfristig könnte die Plattform um eine automatische -E-Mail-Benachrichtigung erweitert werden, die Mitglieder an -bevorstehende Veranstaltungen erinnert. Auch eine Exportfunktion für die -Anmeldedaten -- beispielsweise als CSV oder PDF -- wäre für die -Vereinsverwaltung hilfreich. - -AlumniHub bietet als Plattform eine solide Grundlage, die in den -kommenden Jahren kontinuierlich erweitert werden kann, um den -Absolventenverein der HTL Ungargasse langfristig digital zu -unterstützen. - -\cleardoublepage - -\section{Florian Edlmayer}\label{florian-edlmayer-1} - -\subsection{Einleitung des individuellen -Teils}\label{einleitung-des-individuellen-teils-1} - -\subsubsection{Ausgangssituation}\label{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. - -\subsubsection{Zielsetzung}\label{zielsetzung-1} - -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. - -\subsubsection{Nutzen für den -Absolventenverein}\label{nutzen-fuxfcr-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. - -\subsubsection{Themenstellung}\label{themenstellung} - -\paragraph{Entwicklung eines -CMS-Moduls}\label{entwicklung-eines-cms-moduls} - -• \textbf{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. - -\subparagraph{Erstellung einer -Datenschutzerklärung}\label{erstellung-einer-datenschutzerkluxe4rung} - -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. - -\paragraph{LinkedIn-Anmeldung}\label{linkedin-anmeldung} - -Zur Verbesserung der Benutzerfreundlichkeit und zur vereinfachten -Anmeldung wird eine Anmeldung über LinkedIn mithilfe des -OAuth-2.0-Protokolls implementiert. Diese ermöglicht es Benutzerinnen -und Benutzern, sich mit einem bestehenden LinkedIn-Konto zu registrieren -oder anzumelden. - -\paragraph{Datenbank-Backup und -Restore}\label{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. - -\subsubsection{Detail-Zielsetzungen}\label{detail-zielsetzungen} - -\paragraph{Zielsetzung}\label{zielsetzung-2} - -\subparagraph{Technische Zielsetzung}\label{technische-zielsetzung} - -Die technische Zielsetzung dieses Diplomarbeitsprojekts bestand darin, -eine stabile und sichere Webplattform für Alumni zu entwickeln. Als -technische Grundlage wurde das Content-Management-System Oqtane -verwendet, welches auf modernen Webtechnologien basiert und eine -modulare Erweiterung von Funktionen ermöglicht. Die Implementierung -erfolgte innerhalb der von Oqtane bereitgestellten Architektur, wodurch -verschiedene Funktionen effizient integriert werden konnten. - -Ein zentraler Bestandteil der technischen Umsetzung war die Integration -einer externen Authentifizierung über LinkedIn mithilfe des Protokolls -OAuth 2.0. Dadurch können sich Benutzer direkt mit ihrem LinkedIn-Konto -auf der Plattform anmelden, ohne ein separates Benutzerkonto erstellen -zu müssen. Dies vereinfacht den Registrierungsprozess und erhöht -gleichzeitig die Sicherheit, da sensible Zugangsdaten ausschließlich -beim externen Anbieter verbleiben. - -Zusätzlich wurde eine Datenbank auf Basis von PostgreSQL eingesetzt, um -Benutzerinformationen, Inhalte sowie weitere Systemdaten zuverlässig zu -speichern. Um die langfristige Verfügbarkeit dieser Daten -sicherzustellen, wurde ein automatisiertes Backup-System implementiert. -Dieses System erstellt regelmäßig Sicherungskopien der Datenbank sowie -der wichtigsten Systemdateien. Ergänzend dazu wurde ein Restore-Skript -entwickelt, mit dem gespeicherte Daten im Falle eines Systemfehlers oder -Datenverlustes wiederhergestellt werden können. - -Ein weiterer wichtiger Aspekt der technischen Zielsetzung war die -Einhaltung rechtlicher Anforderungen im Bereich Datenschutz. Daher wurde -eine Datenschutzerklärung erstellt und die Plattform so konzipiert, dass -personenbezogene Daten der Benutzer entsprechend den Vorgaben der -Datenschutz-Grundverordnung verarbeitet werden. - -\subparagraph{Funktionale Zielsetzung}\label{funktionale-zielsetzung} - -Die funktionale Zielsetzung des Projekts bestand darin, eine -Onlineplattform zu entwickeln, die ehemaligen Schülerinnen und Schülern -die Möglichkeit bietet, miteinander in Kontakt zu bleiben und sich über -aktuelle Veranstaltungen zu informieren. Die Plattform dient somit als -digitales Netzwerk für Alumni und soll den Austausch zwischen ehemaligen -Mitgliedern der Bildungseinrichtung fördern. - -Eine zentrale Funktion der Anwendung ist die Anmeldung über LinkedIn, -wodurch Benutzer schnell und unkompliziert Zugriff auf die Plattform -erhalten können. Nach der erfolgreichen Anmeldung wird automatisch ein -Benutzerkonto erstellt oder ein bestehendes Konto zugeordnet. - -Darüber hinaus bietet die Plattform Funktionen zur Darstellung und -Verwaltung von Veranstaltungen. Alumni können sich über kommende Events -informieren und sich für diese anmelden. Dadurch wird die Organisation -von Treffen oder Veranstaltungen erleichtert und die Vernetzung -innerhalb der Alumni-Community gefördert. - -Zusätzlich wurde ein Premiumbereich entwickelt, der bestimmte Inhalte -oder Funktionen exklusiv für berechtigte Benutzer bereitstellt. Dieser -Bereich erweitert die Möglichkeiten der Plattform und ermöglicht es, -spezielle Inhalte nur bestimmten Benutzergruppen zugänglich zu machen. - -Durch diese Funktionen entsteht eine Plattform, die nicht nur als -Informationsquelle dient, sondern auch aktiv zur Vernetzung der Alumni -beiträgt. - -\subparagraph{Gestalterische -Zielsetzung}\label{gestalterische-zielsetzung} - -Neben den technischen und funktionalen Anforderungen spielte auch die -Gestaltung der Plattform eine wichtige Rolle. Ziel war es, eine -übersichtliche und benutzerfreundliche Oberfläche zu entwickeln, die -eine einfache Navigation und intuitive Bedienung ermöglicht. - -Die Struktur der Webseite wurde so aufgebaut, dass wichtige Funktionen -wie Login, Benutzerprofil oder Eventübersicht schnell erreichbar sind. -Ein klares Layout und eine strukturierte Seitenaufteilung tragen dazu -bei, dass sich Benutzer auf der Plattform leicht orientieren können. - -Darüber hinaus wurde darauf geachtet, dass die Plattform ein modernes -Erscheinungsbild besitzt und den Erwartungen einer zeitgemäßen -Webanwendung entspricht. Durch eine klare Gestaltung und eine reduzierte -Benutzeroberfläche wird sichergestellt, dass Inhalte übersichtlich -dargestellt werden und die Nutzung der Plattform möglichst komfortabel -ist. - -Insgesamt verfolgt die gestalterische Zielsetzung das Ziel, eine -Plattform zu schaffen, die sowohl funktional als auch optisch -ansprechend ist und den Benutzern eine positive Nutzungserfahrung -bietet. - -\subsection{Anforderungen an das entwickelte Modul bzw. die -Funktionalität}\label{anforderungen-an-das-entwickelte-modul-bzw.-die-funktionalituxe4t} - -funktionale / nicht‑funktionale Anforderungen - -Use Cases - -\subsection{Technologien}\label{technologien-1} - -\subsubsection{ASP.NET und .NET}\label{asp.net-und-.net} - -Für die Entwicklung der Webanwendung wurde das Framework ASP.NET in -Kombination mit der Plattform .NET verwendet. .NET ist eine von -Microsoft entwickelte Entwicklungsplattform zur Erstellung moderner -Anwendungen für Web, Desktop, Cloud und mobile Systeme. - -ASP.NET stellt innerhalb der .NET-Plattform ein Framework dar, das -speziell für die Entwicklung von Webanwendungen und Webservices -konzipiert wurde. Es bietet eine Vielzahl an Funktionen zur Verarbeitung -von HTTP-Anfragen, zur Verwaltung von Benutzersitzungen sowie zur -Integration von Datenbanken und externen Diensten. - -Die Anwendung basiert auf .NET 8, einer aktuellen Version der Plattform, -welche insbesondere Verbesserungen in den Bereichen Performance, -Sicherheit und Skalierbarkeit bietet. Durch die Nutzung dieser Plattform -ist es möglich, stabile und performante Webanwendungen zu entwickeln, -die auch bei steigender Benutzeranzahl zuverlässig funktionieren. - -Ein wesentliches Konzept von ASP.NET ist die serverseitige Verarbeitung -von Webanfragen. Wenn ein Benutzer eine Seite im Browser aufruft, wird -zunächst eine Anfrage an den Webserver gesendet. Der Server verarbeitet -diese Anfrage innerhalb der ASP.NET-Anwendung und sendet anschließend -eine generierte Antwort zurück an den Browser. - -Durch diese Architektur wird sichergestellt, dass die eigentliche Logik -der Anwendung auf dem Server ausgeführt wird, während der Browser -lediglich für die Darstellung der Benutzeroberfläche zuständig ist. - -Ein weiterer Vorteil von ASP.NET besteht in der klar strukturierten -Architektur moderner Webanwendungen. Typischerweise wird eine Anwendung -in mehrere Schichten unterteilt, beispielsweise: - -• Präsentationsschicht (Benutzeroberfläche) • Geschäftslogik • -Datenzugriffsschicht - -Diese Struktur erleichtert die Wartung und Erweiterung der Anwendung -erheblich, da Änderungen gezielt innerhalb einzelner Komponenten -vorgenommen werden können. - -\subsubsection{PostgreSQL-Datenbank}\label{postgresql-datenbank} - -Zur Speicherung der Daten der Plattform wurde das relationale -Datenbanksystem PostgreSQL eingesetzt. PostgreSQL gehört zu den -leistungsfähigsten Open-Source-Datenbanken und wird weltweit in vielen -professionellen Anwendungen verwendet. - -Eine relationale Datenbank speichert Informationen in Tabellen, die aus -Zeilen und Spalten bestehen. Jede Tabelle repräsentiert eine bestimmte -Art von Daten, beispielsweise Benutzer, Veranstaltungen oder -Systeminformationen. Beziehungen zwischen Tabellen werden durch -sogenannte Schlüssel definiert. - -Durch diese Struktur kann beispielsweise gespeichert werden: - -• welcher Benutzer existiert • welche Veranstaltungen geplant sind • -welcher Benutzer sich für welches Event angemeldet hat - -PostgreSQL bietet darüber hinaus zahlreiche Funktionen, die für moderne -Webanwendungen wichtig sind. Dazu gehören unter anderem: - -• hohe Stabilität und Zuverlässigkeit • Unterstützung komplexer -Datenabfragen mittels SQL • Transaktionssicherheit zur Vermeidung von -Datenverlust • Erweiterbarkeit durch zusätzliche Module - -Ein weiterer wichtiger Vorteil besteht darin, dass PostgreSQL sehr gut -mit modernen Webframeworks wie ASP.NET zusammenarbeitet. Dadurch kann -die Anwendung effizient auf gespeicherte Daten zugreifen und diese -verarbeiten. - -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. - -\subsubsection{OAuth 2.0}\label{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. - -\subsection{Module}\label{module-1} - -\subsubsection{Datenschutz und rechtliche -Grundlagen}\label{datenschutz-und-rechtliche-grundlagen} - -\paragraph[Bedeutung der Datenschutz-Grundverordnung -(DSGVO)]{\texorpdfstring{Bedeutung der Datenschutz-Grundverordnung -(DSGVO)\footnote{Europäische Union (2016) (siehe - Internet-/Intranetverzeichnis).}}{Bedeutung der Datenschutz-Grundverordnung (DSGVO)}}\label{bedeutung-der-datenschutz-grundverordnung-dsgvo-dsgvo} - -Die Datenschutz-Grundverordnung (DSGVO) ist eine rechtsverbindliche -Verordnung der Europäischen Union, die seit dem 25. Mai 2018 unmittelbar -in allen EU-Mitgliedstaaten gilt und den Schutz personenbezogener Daten -regelt. Sie wurde erlassen, um die Rechte natürlicher Personen bei der -Verarbeitung ihrer Daten zu stärken und ein einheitliches -Datenschutzniveau innerhalb der EU zu gewährleisten. - -Der Anwendungsbereich der DSGVO umfasst alle Verarbeitungen -personenbezogener Daten, unabhängig davon, ob diese automatisiert oder -in nicht-automatisierten Akten erfolgt. Personenbezogene Daten sind -dabei definiert als alle Informationen, die sich auf eine identifizierte -oder identifizierbare natürliche Person beziehen. - -Die DSGVO verfolgt mehrere grundsätzliche Ziele: - -• Schutz der Grundrechte natürlicher Personen bei der Verarbeitung ihrer -personenbezogenen Daten sowie die Gewährleistung ihrer Grundfreiheiten. -• Einheitlicher Datenschutz in der EU, sodass sowohl Unternehmen -innerhalb als auch außerhalb der EU, die Daten von EU-Bürgern -verarbeiten, denselben Regeln unterliegen. • Schaffung klarer Pflichten -für Datenverantwortliche und -verarbeiter zur rechtskonformen -Datenverarbeitung. - -Die DSGVO enthält dabei zentral die Grundsätze der Datenverarbeitung -(Art. 5 DSGVO), die sicherstellen, dass personenbezogene Daten nur -rechtmäßig, zweckgebunden und in transparentem Umfang verarbeitet -werden. Dazu gehören unter anderem: - -• Rechtmäßigkeit, Fairness und Transparenz der Verarbeitung • -Zweckbindung der Datenerhebung • Datenminimierung und Speicherbegrenzung -• Integrität und Vertraulichkeit der Datenverarbeitung - -Die Einhaltung dieser Prinzipien ist für jede Organisation -verpflichtend, die personenbezogene Daten verarbeitet -- unabhängig von -ihrer Größe oder Branche. Dies umfasst sowohl technische Aspekte der -Datenverarbeitung als auch die Informationspflichten gegenüber -Betroffenen, wie sie etwa in Datenschutzerklärungen umgesetzt werden -müssen. - -\paragraph[Umsetzung der Datenschutzanforderungen auf der -Webseite]{\texorpdfstring{Umsetzung der Datenschutzanforderungen auf der -Webseite\footnote{Bundeskanzleramt Österreich (2024) (siehe - Internet-/Intranetverzeichnis).}}{Umsetzung der Datenschutzanforderungen auf der Webseite}}\label{umsetzung-der-datenschutzanforderungen-auf-der-webseite-ris} - -Im Rahmen der Diplomarbeit wurde eine umfassende Analyse der -Datenschutzanforderungen durchgeführt und entsprechende Maßnahmen zur -Umsetzung auf der Webseite implementiert. Dabei wurden insbesondere die -Vorgaben der DSGVO berücksichtigt, um sicherzustellen, dass die Webseite -den geltenden Datenschutzbestimmungen entspricht. - -Ein zentrales Element der Umsetzung war die Erstellung einer -gesetzeskonformen Datenschutzerklärung. Diese informiert die Nutzerinnen -und Nutzer über: - -• die Art der verarbeiteten personenbezogenen Daten, • den Zweck der -Datenverarbeitung, • die Rechtsgrundlagen der Verarbeitung, • die -Speicherdauer der Daten, • die Weitergabe von Daten an Dritte • sowie -über die Rechte der Betroffenen gemäß Art. 15--22 DSGVO. - -Die Datenschutzerklärung wird auf der Webseite gut sichtbar eingebunden -und ist für alle Nutzerinnen und Nutzer jederzeit zugänglich. - -Neben der Informationspflicht wurden auch technische und -organisatorische Maßnahmen umgesetzt, um die Sicherheit der -verarbeiteten Daten zu gewährleisten. Dazu gehören unter anderem: - -• Verschlüsselte Übertragung von Daten mittels HTTPS • -Passwortgeschützter Zugriff auf sensible Daten • Regelmäßige -Sicherheitsupdates der eingesetzten Software • Minimierung der -Datenerhebung auf das Notwendige: Es werden nur die Daten erhoben, die -für die Funktion der Webseite unbedingt erforderlich sind. (Grundprinzip -der Datenminimierung nach Art. 5 Abs. 1 lit. c DSGVO) - -\paragraph[Schutz personenbezogener Daten der -Benutzer]{\texorpdfstring{Schutz personenbezogener Daten der -Benutzer\footnote{Datenschutzbehörde (2024) (siehe - Internet-/Intranetverzeichnis).}}{Schutz personenbezogener Daten der Benutzer}}\label{schutz-personenbezogener-daten-der-benutzer-dsb} - -Der Schutz personenbezogener Daten der Benutzer stellt einen zentralen -Bestandteil der Webseite des Absolventenvereins dar. Sämtliche -Datenverarbeitungen erfolgen unter Berücksichtigung der Vorgaben der -Datenschutz-Grundverordnung (DSGVO) sowie des österreichischen -Datenschutzgesetzes (DSG). - -Gemäß Art. 5 Abs. 1 lit. c DSGVO gilt der Grundsatz der -Datenminimierung, wonach nur jene personenbezogenen Daten erhoben werden -dürfen, die für den jeweiligen Zweck erforderlich sind. Auf der Webseite -werden daher ausschließlich solche Daten verarbeitet, die für die -Verwaltung der Mitgliedschaft, die Organisation von Veranstaltungen -sowie die Kommunikation mit Absolventinnen und Absolventen notwendig -sind. - -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ü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 Webseite -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. - -Zusätzlich werden die Betroffenenrechte gemäß Art. 15--22 DSGVO -ausdrücklich gewährleistet. Benutzerinnen und Benutzer haben das Recht -auf Auskunft, Berichtigung, Löschung, Einschränkung der Verarbeitung, -Datenübertragbarkeit sowie Widerspruch gegen die Verarbeitung. - -Darüber hinaus besteht das Recht, sich bei der österreichischen -Datenschutzbehörde zu beschweren, sofern eine rechtswidrige Verarbeitung -vermutet wird. - -Durch die Kombination aus klar definierten Rechtsgrundlagen, -transparenten Informationspflichten und technischen Schutzmaßnahmen wird -ein hohes Datenschutzniveau gewährleistet und der verantwortungsvolle -Umgang mit personenbezogenen Daten sichergestellt. - -\subsubsection{Backup \& Restore}\label{backup-restore} - -\paragraph[Notwendigkeit von Datensicherung -{[}{]}]{\texorpdfstring{Notwendigkeit von Datensicherung {[}Bundesamt -für Sicherheit in der Informationstechnik -(BSI)\footnote{(2024) (siehe Internet-/Intranetverzeichnis).}{]}\footnote{BSI - (2023) (siehe Internet-/Intranetverzeichnis).}}{Notwendigkeit von Datensicherung {[}Bundesamt für Sicherheit in der Informationstechnik (BSI){]}}}\label{notwendigkeit-von-datensicherung-bsi_datensicherungbsi_grundschutz} - -Die Datensicherung ist ein wesentlicher Bestandteil der Webseite des -Absolventenvereins. Sie dient dazu, die auf der Webseite gespeicherten -Daten vor Verlust oder Beschädigung zu schützen. Digitale Daten bilden -die Grundlage für die Funktion der Webseite und müssen daher regelmäßig -gesichert werden. Ein Verlust oder eine Beschädigung der Daten kann zu -erheblichen Problemen führen. - -Mögliche Ursachen für einen Datenverlust sind unter anderem -Hardwaredefekte, Softwarefehler, menschliches Versagen oder -Cyberangriffe. Ohne geeignete Sicherheitsmaßnahmen besteht das Risiko, -dass Daten unwiederbringlich verloren gehen oder nur mit erheblichen -Kosten wiederhergestellt werden können. - -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. - -\paragraph{Konzeption des -Backup-Systems}\label{konzeption-des-backup-systems} - -Ziel des Backup-Systems war es im Falle eines Datenverlustes oder eines -Systemausfalls die Daten wiederherstellen zu können. Es wurde eine -Strategie entwickelt die es ermöglicht sowohl die Datenbank als auch die -Dateien auf dem Server zu sichern. Der Umfang des Backups besteht aus -zwei zentralen Komponenten: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - Die PostgreSQL-Datenbank -\item - Der Ordner ``oqtane.server'' auf dem Server - - Damit wird eine vollständige Sicherung der Webseite ermöglicht, da bei - einer reinen Datenbanksicherung wichtige Anwendungsdateien fehlen - würden. -\end{enumerate} - -\begin{figure} -\centering -\includegraphics[width=0.8\linewidth,height=0.7\textheight]{flowchart-backup-system.pdf} -\caption{Ablaufdiagramm des Backup-Systems} -\end{figure} - -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. - -\begin{Shaded} -\begin{Highlighting}[] -\VariableTok{TS}\OperatorTok{=}\StringTok{"}\VariableTok{$(}\FunctionTok{date} \AttributeTok{{-}u}\NormalTok{ +}\StringTok{\textquotesingle{}\%Y\%m\%dT\%H\%M\%SZ\textquotesingle{}}\VariableTok{)}\StringTok{"} -\VariableTok{DEST\_DIR}\OperatorTok{=}\StringTok{"}\VariableTok{$\{BACKUP\_ROOT\}}\StringTok{/}\VariableTok{$\{TS\}}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -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: - -\begin{Shaded} -\begin{Highlighting}[] -\ExtensionTok{pg\_dump} \AttributeTok{{-}h} \StringTok{"}\VariableTok{$PGHOST}\StringTok{"} \AttributeTok{{-}p} \StringTok{"}\VariableTok{$PGPORT}\StringTok{"} \AttributeTok{{-}U} \StringTok{"}\VariableTok{$PGUSER}\StringTok{"} \AttributeTok{{-}d} \StringTok{"}\VariableTok{$PGDATABASE}\StringTok{"} \AttributeTok{{-}Fc} \DataTypeTok{\textbackslash{}} - \AttributeTok{{-}f} \StringTok{"}\VariableTok{$\{DEST\_DIR\}}\StringTok{/db\_}\VariableTok{$\{PGDATABASE\}}\StringTok{.dump"} -\end{Highlighting} -\end{Shaded} - -Hierbei werden Host, Port, Benutzer und Datenbankname über Variablen -definiert, wodurch das Skript flexibel einsetzbar bleibt. Der Parameter --Fc erstellt das Backup im sogenannten Custom-Format. Dieses Format -bietet den Vorteil, dass beim Wiederherstellen einzelne Tabellen oder -Datenbankobjekte selektiv importiert werden können. Zudem ist es -komprimiert und effizienter als ein reines SQL-Textdump. Die Ausgabe -wird direkt in eine Datei im zuvor erstellten Backup-Ordner geschrieben. -Die Authentifizierung erfolgt über eine .pgpass-Datei, wodurch das -Backup automatisiert und ohne manuelle Passworteingabe ausgeführt werden -kann. - -Neben der Datenbank wird auch der gesamte Anwendungsordner gesichert. -Dies geschieht mithilfe des tar-Programms, das Dateien zu einem -komprimierten Archiv zusammenfasst: - -\begin{Shaded} -\begin{Highlighting}[] -\FunctionTok{tar} \AttributeTok{{-}cvpzf} \StringTok{"}\VariableTok{$\{DEST\_DIR\}}\StringTok{/oqtane\_files.tar.gz"} \DataTypeTok{\textbackslash{}} - \AttributeTok{{-}{-}absolute{-}names} \StringTok{"}\VariableTok{$OQTANE\_DIR}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -Das Programm tar steht für Tape Archive und wurde ursprünglich -entwickelt, um mehrere Dateien auf Magnetbändern zu sichern. Heute wird -es unter Linux und Unix-Systemen verwendet, um mehrere Dateien und -Verzeichnisse zu einem einzigen Archiv zusammenzufassen. Dabei kann das -Archiv optional komprimiert werden. - -Der Parameter -c erstellt ein neues Archiv, -v gibt die verarbeiteten -Dateien aus, -p erhält die ursprünglichen Dateiberechtigungen und -z -aktiviert die gzip-Komprimierung. Die Komprimierung reduziert den -Speicherbedarf der Sicherung erheblich. Besonders relevant ist die -Option --absolute-names, da dadurch die vollständigen Pfadangaben im -Archiv gespeichert werden. Dies erleichtert eine spätere exakte -Wiederherstellung der ursprünglichen Verzeichnisstruktur. Durch die -Kombination aus Datenbank-Dump und komprimiertem Dateisystem-Archiv -entsteht ein vollständiges Vollbackup des Systems. - -Ein Cronjob ist eine zeitgesteuerte Aufgabe unter Linux-Systemen, die -automatisch zu einem festgelegten Zeitpunkt ausgeführt wird. Er basiert -auf dem Hintergrunddienst cron, der regelmäßig überprüft, ob geplante -Befehle gestartet werden müssen. - -Im vorliegenden Projekt wird ein Cronjob verwendet, um das Backup-Skript -täglich automatisiert auszuführen. Der entsprechende Eintrag lautet: - -\begin{Shaded} -\begin{Highlighting}[] -\ExtensionTok{30}\NormalTok{ 2 }\PreprocessorTok{*} \PreprocessorTok{*} \PreprocessorTok{*}\NormalTok{ /home/florian/backup{-}script.sh }\OperatorTok{\textgreater{}\textgreater{}}\NormalTok{ /home/florian/backup.log }\DecValTok{2}\OperatorTok{\textgreater{}\&}\DecValTok{1} -\end{Highlighting} -\end{Shaded} - -Die ersten fünf Felder definieren den Ausführungszeitpunkt. In diesem -Fall bedeutet die Konfiguration, dass das Skript täglich um 02:30 Uhr -gestartet wird. Die nächtliche Ausführung reduziert die Systembelastung -während der regulären Nutzung. - -Der hintere Teil des Befehls (\textgreater\textgreater{} -/home/florian/backup.log 2\textgreater\&1) sorgt dafür, dass sowohl -normale Ausgaben als auch Fehlermeldungen in einer Logdatei gespeichert -werden. Dadurch kann überprüft werden, ob das Backup erfolgreich -durchgeführt wurde. - -Durch den Einsatz eines Cronjobs wird eine regelmäßige und zuverlässige -Datensicherung ohne manuelles Eingreifen gewährleistet. - -Ein weiterer Bestandteil des Backup-Systems ist ein automatischer -Mechanismus zur Verwaltung alter Sicherungen. Da Backups langfristig -Speicherplatz beanspruchen können, wurde eine Funktion implementiert, -die nur eine definierte Anzahl an Sicherungen beibehält. In der -Konfiguration des Skripts wird festgelegt, dass maximal 30 Backups -gespeichert werden. - -\begin{Shaded} -\begin{Highlighting}[] -\VariableTok{RETAIN}\OperatorTok{=}\NormalTok{30} -\end{Highlighting} -\end{Shaded} - -Während der Ausführung überprüft das Skript, wie viele Backup-Ordner im -Backup-Verzeichnis vorhanden sind. Die Ordner werden anhand ihres -Zeitstempels sortiert, wodurch die chronologische Reihenfolge der -Sicherungen eindeutig bestimmt werden kann. Sollte die Anzahl der -vorhandenen Backups den definierten Wert überschreiten, werden -automatisch die ältesten Sicherungen gelöscht. - -\begin{Shaded} -\begin{Highlighting}[] -\ControlFlowTok{if} \KeywordTok{((} \VariableTok{$\{}\OperatorTok{\#}\VariableTok{backups}\OperatorTok{[@]}\VariableTok{\}} \OperatorTok{\textgreater{}} \VariableTok{RETAIN} \KeywordTok{));} \ControlFlowTok{then} - \ControlFlowTok{for}\NormalTok{ old }\KeywordTok{in} \StringTok{"}\VariableTok{$\{backups}\OperatorTok{[@]:}\NormalTok{RETAIN}\VariableTok{\}}\StringTok{"}\KeywordTok{;} \ControlFlowTok{do} - \FunctionTok{rm} \AttributeTok{{-}rf} \AttributeTok{{-}{-}} \StringTok{"}\VariableTok{$old}\StringTok{"} - \ControlFlowTok{done} -\ControlFlowTok{fi} -\end{Highlighting} -\end{Shaded} - -Durch diesen Rotationsmechanismus wird verhindert, dass sich im Laufe -der Zeit eine unbegrenzte Anzahl von Backups ansammelt und dadurch der -verfügbare Speicherplatz auf dem Server erschöpft wird. Gleichzeitig -bleibt eine ausreichende Anzahl an Sicherungsständen erhalten, um im -Fehlerfall auf frühere Systemzustände zurückgreifen zu können. - -Die gewählte Anzahl von 30 Sicherungen ermöglicht es, bei täglicher -Ausführung des Backup-Skripts ungefähr einen Monat an -Wiederherstellungspunkten vorzuhalten. Dadurch wird ein sinnvoller -Kompromiss zwischen Datensicherheit und effizienter Speicherverwaltung -erreicht. - -\paragraph{Implementierung der -Backup-Skripte}\label{implementierung-der-backup-skripte} - -Die Implementierung des Backup-Systems erfolgte mittels eines -Bash-Skripts, das auf dem Linux-Server ausgeführt wird. Bash eignet sich -besonders für administrative Aufgaben, da sie direkten Zugriff auf -Systembefehle, Dateien und Prozesse bietet. Das Skript wurde so -aufgebaut, dass es robust, automatisierbar und nachvollziehbar arbeitet. - -Zu Beginn des Skripts wird folgende Konfiguration gesetzt: - -\begin{Shaded} -\begin{Highlighting}[] -\CommentTok{\#\#!/usr/bin/env bash} -\BuiltInTok{set} \AttributeTok{{-}euo}\NormalTok{ pipefail} -\end{Highlighting} -\end{Shaded} - -Die erste Zeile definiert den Interpreter, mit dem das Skript ausgeführt -wird. Dadurch wird sichergestellt, dass unabhängig von der -Systemkonfiguration die korrekte Bash-Version verwendet wird. - -Die Anweisung set -euo pipefail erhöht die Sicherheit und Stabilität des -Skripts: - -• \texttt{-e} beendet das Skript sofort, wenn ein Befehl fehlschlägt • -\texttt{-u} verhindert die Verwendung nicht definierter Variablen • -\texttt{-o\ pipefail} sorgt dafür, dass auch Fehler innerhalb von -Befehls-Pipelines erkannt werden - -Diese Einstellungen verhindern, dass das Backup bei Fehlern unbemerkt -unvollständig ausgeführt wird. - -Im nächsten Schritt werden zentrale Konfigurationsvariablen definiert: - -\begin{Shaded} -\begin{Highlighting}[] -\VariableTok{BACKUP\_ROOT}\OperatorTok{=}\StringTok{"/var/backups/fullserver"} -\VariableTok{RETAIN}\OperatorTok{=}\NormalTok{30} - -\VariableTok{PGHOST}\OperatorTok{=}\StringTok{"localhost"} -\VariableTok{PGPORT}\OperatorTok{=}\StringTok{"5432"} -\VariableTok{PGUSER}\OperatorTok{=}\StringTok{"florian"} -\VariableTok{PGDATABASE}\OperatorTok{=}\StringTok{"oqtane"} -\end{Highlighting} -\end{Shaded} - -Durch die Verwendung von Variablen bleibt das Skript flexibel und -wartbar. Änderungen, beispielsweise am Speicherort oder an der -Datenbank, können an einer zentralen Stelle vorgenommen werden, ohne den -restlichen Code anzupassen. - -Die Sicherung der PostgreSQL-Datenbank erfolgt mittels pg\_dump im -Custom-Format. Dieses Format ist besonders geeignet, da es eine flexible -Wiederherstellung ermöglicht. Die Ausgabe wird direkt in den jeweiligen -Backup-Ordner geschrieben. Die Authentifizierung erfolgt über eine -.pgpass-Datei, wodurch das Backup ohne interaktive Passworteingabe -automatisiert durchgeführt werden kann. - -Anschließend wird der gesamte Anwendungsordner mit tar archiviert und -komprimiert. Dabei werden Dateirechte und Verzeichnisstrukturen -vollständig erhalten. Dies ist insbesondere bei Webanwendungen wichtig, -da falsche Berechtigungen nach einer Wiederherstellung zu -Funktionsstörungen führen könnten. - -Ein weiterer wichtiger Bestandteil der Implementierung ist das -integrierte Rotationsprinzip. Das Skript überprüft automatisch, wie -viele Backup-Ordner vorhanden sind. Falls die definierte Grenze von 30 -Sicherungen überschritten wird, werden die ältesten Backups gelöscht. -Dadurch wird verhindert, dass der verfügbare Speicherplatz durch alte -Sicherungen dauerhaft belegt wird. Die Sortierung erfolgt anhand der -Zeitstempel im Ordnernamen, wodurch die chronologische Reihenfolge -eindeutig bestimmbar ist. - -Zusätzlich gibt das Skript Statusmeldungen mit Zeitangaben aus: - -\begin{Shaded} -\begin{Highlighting}[] -\BuiltInTok{echo} \StringTok{"[}\VariableTok{$(}\FunctionTok{date} \AttributeTok{{-}Iseconds}\VariableTok{)}\StringTok{] Backup{-}Job abgeschlossen."} -\end{Highlighting} -\end{Shaded} - -Diese Meldungen werden bei automatischer Ausführung über den Cronjob in -eine Logdatei geschrieben. Dadurch kann jederzeit überprüft werden, ob -das Backup erfolgreich abgeschlossen wurde oder ob Fehler aufgetreten -sind. - -Die Implementierung zeichnet sich durch folgende Eigenschaften aus: - -• vollständige Sicherung von Datenbank und Anwendungsdateien • -automatische tägliche Ausführung • integrierte Fehlerbehandlung • -strukturierte Archivierung mit Zeitstempel • automatische -Speicherverwaltung durch Rotationsmechanismus - -Durch diese Umsetzung wurde ein zuverlässiges und wartbares -Backup-System geschaffen, das den kontinuierlichen Betrieb der -Webanwendung unterstützt und im Fehlerfall eine schnelle -Wiederherstellung ermöglicht. - -\paragraph{Wiederherstellung von Daten mittels -Restore-Skripten}\label{wiederherstellung-von-daten-mittels-restore-skripten} - -Neben der Datensicherung stellt die strukturierte Wiederherstellung der -Daten einen zentralen Bestandteil des Backup-Systems dar. Zu diesem -Zweck wurde ein eigenes Bash-Skript implementiert, das sowohl die -PostgreSQL-Datenbank als auch die Anwendungsdateien aus einem gewählten -Backup-Ordner wiederherstellt (Restore-Skript). Ziel war es, einen klar -definierten und kontrollierten Prozess zu schaffen, der im Fehlerfall -eine vollständige Rücksetzung des Systems ermöglicht. - -Das Skript beginnt -- analog zum Backup-Skript -- mit einer sicheren -Ausführungskonfiguration: - -\begin{Shaded} -\begin{Highlighting}[] -\CommentTok{\#\#!/usr/bin/env bash} -\BuiltInTok{set} \AttributeTok{{-}euo}\NormalTok{ pipefail} -\end{Highlighting} -\end{Shaded} - -Auch hier sorgt set -euo pipefail dafür, dass das Skript bei Fehlern -sofort abbricht, keine undefinierten Variablen verwendet werden und -Fehler innerhalb von Befehls-Pipelines korrekt erkannt werden. Dadurch -wird verhindert, dass ein unvollständiger oder fehlerhafter Restore -durchgeführt wird. - -Zu Beginn wird festgelegt, welcher Backup-Ordner verwendet werden soll. -Wird beim Start ein Argument übergeben, wird dieses als -Backup-Verzeichnis interpretiert. Andernfalls wird automatisch das -neueste Backup ausgewählt: - -\begin{Shaded} -\begin{Highlighting}[] -\ControlFlowTok{if} \KeywordTok{[[} \VariableTok{$\#} \OtherTok{{-}ge}\NormalTok{ 1 }\KeywordTok{]];} \ControlFlowTok{then} - \VariableTok{BACKUP\_SUBDIR}\OperatorTok{=}\StringTok{"}\VariableTok{$1}\StringTok{"} -\ControlFlowTok{else} - \VariableTok{BACKUP\_SUBDIR}\OperatorTok{=}\StringTok{"}\VariableTok{$(}\FunctionTok{ls} \AttributeTok{{-}1} \StringTok{"}\VariableTok{$\{BACKUP\_ROOT\}}\StringTok{"} \KeywordTok{|} \FunctionTok{sort} \KeywordTok{|} \FunctionTok{tail} \AttributeTok{{-}n}\NormalTok{ 1}\VariableTok{)}\StringTok{"} -\ControlFlowTok{fi} -\end{Highlighting} -\end{Shaded} - -Diese Logik ermöglicht eine flexible Nutzung des Skripts. -Administratoren können gezielt einen bestimmten Sicherungsstand -auswählen oder standardmäßig den aktuellsten verwenden. - -Vor Beginn der Wiederherstellung erfolgt eine deutliche -Sicherheitswarnung: - -\begin{Shaded} -\begin{Highlighting}[] -\BuiltInTok{read} \AttributeTok{{-}rp} \StringTok{"Fortfahren? (ja/nein): "} \VariableTok{answer} -\ControlFlowTok{if} \KeywordTok{[[} \StringTok{"}\VariableTok{$answer}\StringTok{"} \OtherTok{!=} \StringTok{"ja"} \KeywordTok{]];} \ControlFlowTok{then} - \BuiltInTok{exit}\NormalTok{ 0} -\ControlFlowTok{fi} -\end{Highlighting} -\end{Shaded} - -Diese Abfrage dient als Schutzmechanismus, da der Restore-Prozess -bestehende Daten überschreibt. Erst nach expliziter Bestätigung wird die -Wiederherstellung gestartet. - -Die Wiederherstellung der PostgreSQL-Datenbank erfolgt in mehreren -Schritten. Zunächst wird -- falls vorhanden -- die bestehende Datenbank -gelöscht: - -\begin{Shaded} -\begin{Highlighting}[] -\ExtensionTok{dropdb} \AttributeTok{{-}h} \StringTok{"}\VariableTok{$PGHOST}\StringTok{"} \AttributeTok{{-}p} \StringTok{"}\VariableTok{$PGPORT}\StringTok{"} \AttributeTok{{-}U} \StringTok{"}\VariableTok{$PGUSER}\StringTok{"} \StringTok{"}\VariableTok{$PGDATABASE}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -Anschließend wird eine neue, leere Datenbank erstellt: - -\begin{Shaded} -\begin{Highlighting}[] -\ExtensionTok{createdb} \AttributeTok{{-}h} \StringTok{"}\VariableTok{$PGHOST}\StringTok{"} \AttributeTok{{-}p} \StringTok{"}\VariableTok{$PGPORT}\StringTok{"} \AttributeTok{{-}U} \StringTok{"}\VariableTok{$PGUSER}\StringTok{"} \StringTok{"}\VariableTok{$PGDATABASE}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -Danach wird der zuvor gesicherte Dump eingespielt: - -\begin{Shaded} -\begin{Highlighting}[] -\ExtensionTok{pg\_restore} \AttributeTok{{-}h} \StringTok{"}\VariableTok{$PGHOST}\StringTok{"} \AttributeTok{{-}p} \StringTok{"}\VariableTok{$PGPORT}\StringTok{"} \AttributeTok{{-}U} \StringTok{"}\VariableTok{$PGUSER}\StringTok{"} \DataTypeTok{\textbackslash{}} - \AttributeTok{{-}d} \StringTok{"}\VariableTok{$PGDATABASE}\StringTok{"} \AttributeTok{{-}c} \StringTok{"}\VariableTok{$DUMP\_FILE}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -Das Programm pg\_restore liest das im Custom-Format gespeicherte Backup -ein und stellt sämtliche Tabellen, Indizes und Datenbankobjekte wieder -her. Die Option -c sorgt dafür, dass bestehende Objekte vor dem Import -entfernt werden, wodurch Konflikte vermieden werden. - -Neben der Datenbank wird auch der Anwendungsordner wiederhergestellt. -Bevor die neuen Dateien entpackt werden, wird der aktuell vorhandene -Ordner zur Sicherheit umbenannt: - -\begin{Shaded} -\begin{Highlighting}[] -\FunctionTok{mv} \StringTok{"}\VariableTok{$OQTANE\_DIR}\StringTok{"} \StringTok{"}\VariableTok{$\{OQTANE\_DIR\}}\StringTok{.old.}\VariableTok{$(}\FunctionTok{date}\NormalTok{ +\%s}\VariableTok{)}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -Diese Maßnahme verhindert einen vollständigen Datenverlust, falls beim -Restore ein Problem auftreten sollte. Anschließend wird das Archiv -entpackt: - -\begin{Shaded} -\begin{Highlighting}[] -\FunctionTok{tar} \AttributeTok{{-}xvpzf} \StringTok{"}\VariableTok{$FILES\_ARCHIVE}\StringTok{"} -\end{Highlighting} -\end{Shaded} - -Der Parameter -x extrahiert das Archiv, -p stellt die ursprünglichen -Dateiberechtigungen wieder her und -z dekomprimiert das gzip-Archiv. -Dadurch wird die komplette Ordnerstruktur in ihrem ursprünglichen -Zustand wiederhergestellt. - -Zusammenfassend ermöglicht das Restore-Skript eine vollständige -Rücksetzung der Webanwendung auf einen definierten Sicherungsstand. -Durch die Kombination aus Sicherheitsabfrage, kontrollierter -Datenbank-Neuerstellung und strukturiertem Dateirestore wird ein -zuverlässiger und nachvollziehbarer Wiederherstellungsprozess -gewährleistet. Das System ergänzt somit das Backup-Konzept um eine -praxisnahe und technisch saubere Lösung für den Ernstfall. - -\paragraph{Fazit zur Datensicherung}\label{fazit-zur-datensicherung} - -Durch die Implementierung eines automatisierten Backup- und -Restore-Systems wurde eine zuverlässige Grundlage für die -Datensicherheit der Webanwendung geschaffen. Das entwickelte System -ermöglicht eine regelmäßige Sicherung sowohl der PostgreSQL-Datenbank -als auch der vollständigen Anwendungsdateien. Durch die automatisierte -Ausführung mittels Cronjob wird sichergestellt, dass die Backups ohne -manuelles Eingreifen täglich erstellt werden. - -Zusätzlich sorgt das integrierte Rotationsprinzip dafür, dass ältere -Sicherungen automatisch entfernt werden und der verfügbare Speicherplatz -effizient genutzt wird. Die strukturierte Ablage der Backups mit -Zeitstempeln erleichtert die Auswahl eines bestimmten Sicherungsstandes. - -Neben der Datensicherung wurde auch ein Restore-Skript implementiert, -das eine vollständige Wiederherstellung des Systems ermöglicht. Dabei -werden sowohl die Datenbank als auch die Anwendungsdateien aus einem -ausgewählten Backup wiederhergestellt. Sicherheitsmechanismen wie -Bestätigungsabfragen und das temporäre Umbenennen bestehender Daten -reduzieren das Risiko von Datenverlust während des -Wiederherstellungsprozesses. - -Insgesamt stellt das entwickelte Backup-System eine robuste und -praxisnahe Lösung dar, die den sicheren Betrieb der Webanwendung -unterstützt und im Fehlerfall eine schnelle Wiederherstellung der Daten -ermöglicht. - -\subsubsection{Benutzerverwaltung und Authentifizierung per -LinkedIn}\label{benutzerverwaltung-und-authentifizierung-per-linkedin} - -\paragraph{Authentifizierung mittels OAuth -2.0}\label{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.\footnote{IETF (2012) (siehe Internet-/Intranetverzeichnis).} -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. - -Der grundlegende Ablauf einer OAuth-Authentifizierung ist in Abbildung X -dargestellt. Dabei wird der Benutzer zunächst zur Login-Seite des -externen Anbieters weitergeleitet. Nach erfolgreicher Anmeldung -bestätigt der Benutzer, dass die Anwendung Zugriff auf bestimmte -Profildaten erhalten darf. - -\begin{figure} -\centering -\pandocbounded{\includegraphics[keepaspectratio]{./images/04-Florian/oauth-flow.png}} -\caption{Ablauf der OAuth-Authentifizierung (Erstellt mit ChatGPT)} -\end{figure} - -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 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. - -\paragraph{Technische Umsetzung der LinkedIn-Anmeldung in -Oqtane}\label{technische-umsetzung-der-linkedin-anmeldung-in-oqtane} - -Die technische Umsetzung der LinkedIn-Authentifizierung erfolgte über -das integrierte External Login System\footnote{Oqtane Foundation (2024a) - (siehe Internet-/Intranetverzeichnis).} 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\footnote{Microsoft (2026d) (siehe - Internet-/Intranetverzeichnis).} erstellt. Dabei werden zwei zentrale -Zugangsdaten generiert: - -• Client ID • Client Secret - -Diese dienen zur Identifikation der Webanwendung gegenüber den -LinkedIn-Servern. - -Innerhalb der Oqtane-Konfiguration wurde anschließend ein neuer -OAuth-Provider eingerichtet. Dabei mussten mehrere Parameter definiert -werden, darunter die Autorisierungs- und Token-Endpunkte von LinkedIn. - -Beispielsweise wird für die Benutzerautorisierung folgende Adresse -verwendet: - -https://www.linkedin.com/oauth/v2/authorization - -Nach erfolgreicher Anmeldung stellt LinkedIn über folgenden Endpunkt ein -Zugriffstoken bereit: - -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. - -In der Konfiguration wurde außerdem festgelegt, welche Benutzerdaten von -LinkedIn übernommen werden sollen. Dazu gehören unter anderem: - -• Benutzername • E-Mail-Adresse • eindeutige Benutzer-ID - -Diese Daten werden von Oqtane als sogenannte Claims verarbeitet und -anschließend dem Benutzerkonto der Plattform zugeordnet. - -Darüber hinaus wurde in den Einstellungen aktiviert, dass bei der ersten -Anmeldung automatisch ein neues Benutzerkonto erstellt werden kann. -Dadurch können sich neue Nutzer direkt über ihr LinkedIn-Konto -registrieren. - -\paragraph{Ablauf des -Anmeldeprozesses}\label{ablauf-des-anmeldeprozesses} - -Der eigentliche Anmeldevorgang erfolgt in mehreren aufeinanderfolgenden -Schritten. Zunächst wählt der Benutzer auf der Login-Seite der -Webplattform die Option zur Anmeldung über LinkedIn aus. - -Daraufhin wird der Benutzer zur LinkedIn-Authentifizierungsseite -weitergeleitet. Dort meldet sich der Benutzer mit seinem LinkedIn-Konto -an und bestätigt die Autorisierung der Anwendung. - -Nach erfolgreicher Authentifizierung sendet LinkedIn eine Antwort an die -zuvor definierte Redirect-URL der Webanwendung. Diese Antwort enthält -einen Autorisierungscode, der anschließend vom Server der Webanwendung -gegen ein Zugriffstoken ausgetauscht wird. - -Wie in Abschnitt 4.3.1 beschrieben, werden die abgerufenen Profildaten -zur Identifikation oder Neuanlage des Benutzerkontos in der lokalen -Datenbank verwendet. - -\subsubsection{Implementierung des -Premium-Bereichs}\label{implementierung-des-premium-bereichs} - -\paragraph{Ziel und Zweck des -Premium-Bereichs}\label{ziel-und-zweck-des-premium-bereichs} - -Der Premium-Bereich wurde mit dem Ziel entwickelt, den Mitgliedern des -SZU Absolventenvereins einen klar abgegrenzten, exklusiven Bereich -innerhalb der VereinsWebseite bereitzustellen. Das Premium-Bereich-Modul -ist eine Erweiterung für das Content-Management-System Oqtane und bildet -das Kernstück des digitalen Mitgliederbereichs. Es ermöglicht -Mitgliedern, sich über das Hochladen eines Ingenieur-Antrags als -PDF-Dokument für eine zeitlich begrenzte Premium-Mitgliedschaft zu -qualifizieren. Premium-Mitglieder erhalten Zugang zu exklusiven -Funktionen wie dem Einsehen genehmigter Anträge anderer Mitglieder sowie -einer Mitgliedersuche mit integrierter Kontaktfunktion. - -Der zentrale Zweck besteht darin, einen Anreiz für aktives Engagement im -Verein zu schaffen. Dadurch entsteht ein Kreislauf, in dem qualitativ -hochwertige Anträge die Wissensbasis der Gemeinschaft bereichern und -gleichzeitig den einreichenden Mitgliedern einen konkreten Gegenwert in -Form von Premium-Funktionen bieten. Der Premium-Bereich dient darüber -hinaus als digitales Netzwerk-Instrument. Durch die Kombination aus -Antrags-Einsicht, Mitgliedersuche und Kontaktfunktion wird eine -Plattform geschaffen, die den fachlichen Austausch zwischen Absolventen -fördert und die Vernetzung innerhalb der Gemeinschaft stärkt. Die -zeitliche Begrenzung der Premium-Mitgliedschaft auf 12 Monate sorgt -dafür, dass Mitglieder regelmäßig aktiv bleiben und neue Inhalte -beitragen, um ihren Premium-Status aufrechtzuerhalten. - -Die Entwicklung erfolgte als eigenständiges Oqtane-Modul, wodurch eine -nahtlose Integration in die bestehende VereinsWebseite gewährleistet -wird. Das Modul nutzt dabei die vom Framework bereitgestellten -Mechanismen für Authentifizierung, Autorisierung, Datenbankzugriff und -Dateiverwaltung. Die Architektur folgt etablierten Entwurfsmustern wie -dem Repository-Pattern, Dependency Injection und dem -Service-Layer-Muster. Das kumulative Premium-System mit vollständigem -Audit-Trail stellt sicher, dass alle Statusänderungen transparent und -nachvollziehbar sind. Die modulare Struktur erlaubt eine einfache -Erweiterung um zusätzliche Funktionen, ohne die bestehende Codebasis -grundlegend verändern zu müssen. - -\begin{figure} -\centering -\includegraphics[width=0.8\linewidth,height=0.7\textheight]{architecture-premium-module.pdf} -\caption{Architektur des Premium-Bereich-Moduls} -\end{figure} - -\paragraph{Funktionalität und Features des -Premium-Bereichs}\label{funktionalituxe4t-und-features-des-premium-bereichs} - -Der Premium-Bereich umfasst mehrere miteinander verknüpfte Funktionen, -die gemeinsam ein geschlossenes System bilden. - -\textbf{Ingenieur-Antrags-Workflow} - -Das Kernfeature ist der Ingenieur-Antrags-Workflow. Mitglieder können -über eine dedizierte Seite einen Antrag mit Titel, Kurzbeschreibung und -PDF-Dokument einreichen. Die zentrale Datenstruktur dafür ist die Klasse -\texttt{EngineerApplication}, die in der Tabelle -\texttt{SZUAbsolventenvereinEngineerApplications} gespeichert wird: - -\begin{Shaded} -\begin{Highlighting}[] -\OperatorTok{[}\FunctionTok{Table}\OperatorTok{(}\StringTok{"SZUAbsolventenvereinEngineerApplications"}\OperatorTok{)]} -\KeywordTok{public} \KeywordTok{class}\NormalTok{ EngineerApplication }\OperatorTok{:}\NormalTok{ ModelBase} -\OperatorTok{\{} - \OperatorTok{[}\NormalTok{Key}\OperatorTok{]} \KeywordTok{public} \DataTypeTok{int}\NormalTok{ ApplicationId }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \DataTypeTok{int}\NormalTok{ UserId }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \DataTypeTok{int}\NormalTok{ ModuleId }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \DataTypeTok{int}\NormalTok{ FileId }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \OperatorTok{[}\FunctionTok{StringLength}\OperatorTok{(}\DecValTok{256}\OperatorTok{)]} \KeywordTok{public} \DataTypeTok{string}\NormalTok{ Title }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \DataTypeTok{string}\NormalTok{ ShortDescription }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \OperatorTok{[}\FunctionTok{StringLength}\OperatorTok{(}\DecValTok{50}\OperatorTok{)]} \KeywordTok{public} \DataTypeTok{string}\NormalTok{ Status }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public}\NormalTok{ DateTime}\OperatorTok{?}\NormalTok{ SubmittedOn }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public}\NormalTok{ DateTime}\OperatorTok{?}\NormalTok{ ApprovedOn }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -Die Klasse erbt von \texttt{ModelBase}, wodurch automatisch die -Audit-Felder \texttt{CreatedBy}, \texttt{CreatedOn}, \texttt{ModifiedBy} -und \texttt{ModifiedOn} zur Verfügung stehen. Das Feld \texttt{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 -\texttt{FileId} im Oqtane-Dateisystem referenziert. Das nachfolgende -Klassendiagramm veranschaulicht diese Struktur und zeigt, wie -Basis-Metadaten durch die Vorfahrenklasse abgedeckt werden, während -antragsbezogene Daten in der Hauptklasse gekapselt bleiben. - -\begin{figure} -\centering -\pandocbounded{\includegraphics[keepaspectratio]{classdiagram-engineer-application.pdf}} -\caption{Klassendiagramm der EngineerApplication-Entität} -\end{figure} - -Der Lebenszyklus eines Antrags durchläuft mehrere Phasen. Der Benutzer -beginnt auf der Antragsseite \texttt{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 -\texttt{SubmitApplication} ein neues \texttt{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 -\texttt{ApplicationId}, ob ein neuer Antrag über den Service -\texttt{AddApplicationAsync} erstellt oder ein bestehender über -\texttt{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 \texttt{ApplicationService}, der als HTTP-Client die -Anfragen an den REST-Controller weiterleitet. Wie die nachfolgende -Abbildung zeigt, führt die klare Gestaltung der Benutzeroberfläche den -Benutzer im Browser intuitiv durch den Einreichungsprozess und stellt -auch den Bearbeitungsstatus des Antrags übersichtlich dar. - -\begin{figure} -\centering -\pandocbounded{\includegraphics[keepaspectratio]{./images/04-Florian/ingenieur-antrag-status.png}} -\caption{Formular zum Einreichen eines Ingenieur-Antrags} -\end{figure} - -Serverseitig nimmt die Methode \texttt{AddApplicationAsync} im -\texttt{ServerEngineerApplicationService} den Antrag entgegen. Dort wird -zunächst geprüft, ob der Benutzer authentifiziert ist und die -View-Berechtigung für das Modul besitzt. Die User-ID wird aus dem -HTTP-Kontext extrahiert und dem Antrag zugewiesen, um sicherzustellen, -dass kein Benutzer Anträge im Namen anderer erstellen kann. Anschließend -wird der Antrag über das Repository in der Datenbank persistiert. - -Ein Administrator kann den Antrag entweder genehmigen oder ablehnen. Bei -einer Genehmigung wird der Status auf „Approved'' gesetzt und -automatisch über den \texttt{PremiumService} eine 12-monatige -Premium-Mitgliedschaft vergeben. Bei einer Ablehnung wechselt der Status -auf „Rejected'' und der Benutzer hat die Möglichkeit, einen -überarbeiteten Antrag erneut einzureichen. - -\textbf{Anzeige genehmigter Anträge} - -Die Antrags-Listenansicht bildet das zweite zentrale Feature. Wie in der -nachfolgenden Abbildung zu sehen ist, sehen Premium-Mitglieder alle -genehmigten und veröffentlichten Anträge in einer benutzerfreundlichen -Kartenansicht und können Titel, Autor sowie Kurzbeschreibung auf einen -Blick erfassen. Jede Karte enthält das Veröffentlichungsdatum und -integrierte Schaltflächen, über welche das zugehörige PDF-Dokument bei -Bedarf direkt im Browser via eingebettetem iFrame betrachtet oder -heruntergeladen werden kann. - -\begin{figure} -\centering -\pandocbounded{\includegraphics[keepaspectratio]{./images/04-Florian/ingenieur-antraege-liste.png}} -\caption{Ansicht der genehmigten Ingenieur-Anträge} -\end{figure} - -Die serverseitige Methode \texttt{GetApplicationsAsync} steuert dabei -die rollenbasierte Zugriffslogik und entscheidet, welche Anträge ein -Benutzer sehen darf: - -\begin{Shaded} -\begin{Highlighting}[] -\KeywordTok{public}\NormalTok{ Task}\OperatorTok{\textless{}}\NormalTok{List}\OperatorTok{\textless{}}\NormalTok{EngineerApplication}\OperatorTok{\textgreater{}\textgreater{}} \FunctionTok{GetApplicationsAsync}\OperatorTok{(}\DataTypeTok{int}\NormalTok{ ModuleId}\OperatorTok{)} -\OperatorTok{\{} - \DataTypeTok{var}\NormalTok{ user }\OperatorTok{=}\NormalTok{ \_accessor}\OperatorTok{.}\FunctionTok{HttpContext}\OperatorTok{.}\FunctionTok{User}\OperatorTok{;} - \KeywordTok{if} \OperatorTok{(}\NormalTok{\_userPermissions}\OperatorTok{.}\FunctionTok{IsAuthorized}\OperatorTok{(}\NormalTok{user}\OperatorTok{,}\NormalTok{ \_alias}\OperatorTok{.}\FunctionTok{SiteId}\OperatorTok{,}\NormalTok{ EntityNames}\OperatorTok{.}\FunctionTok{Module}\OperatorTok{,}\NormalTok{ ModuleId}\OperatorTok{,}\NormalTok{ PermissionNames}\OperatorTok{.}\FunctionTok{Edit}\OperatorTok{))} - \OperatorTok{\{} - \KeywordTok{return}\NormalTok{ Task}\OperatorTok{.}\FunctionTok{FromResult}\OperatorTok{(}\NormalTok{\_repository}\OperatorTok{.}\FunctionTok{GetEngineerApplications}\OperatorTok{(}\NormalTok{ModuleId}\OperatorTok{).}\FunctionTok{ToList}\OperatorTok{());} - \OperatorTok{\}} - - \DataTypeTok{var}\NormalTok{ userId }\OperatorTok{=}\NormalTok{ \_accessor}\OperatorTok{.}\FunctionTok{HttpContext}\OperatorTok{.}\FunctionTok{GetUserId}\OperatorTok{();} - \DataTypeTok{var}\NormalTok{ results }\OperatorTok{=} \KeywordTok{new}\NormalTok{ List}\OperatorTok{\textless{}}\NormalTok{EngineerApplication}\OperatorTok{\textgreater{}();} - - \KeywordTok{if} \OperatorTok{(}\NormalTok{userId }\OperatorTok{!=} \OperatorTok{{-}}\DecValTok{1}\OperatorTok{)} - \OperatorTok{\{} - \DataTypeTok{var}\NormalTok{ ownApps }\OperatorTok{=}\NormalTok{ \_repository}\OperatorTok{.}\FunctionTok{GetEngineerApplications}\OperatorTok{(}\NormalTok{ModuleId}\OperatorTok{)} - \OperatorTok{.}\FunctionTok{Where}\OperatorTok{(}\NormalTok{a }\OperatorTok{=\textgreater{}}\NormalTok{ a}\OperatorTok{.}\FunctionTok{UserId} \OperatorTok{==}\NormalTok{ userId}\OperatorTok{).}\FunctionTok{ToList}\OperatorTok{();} -\NormalTok{ results}\OperatorTok{.}\FunctionTok{AddRange}\OperatorTok{(}\NormalTok{ownApps}\OperatorTok{);} - \OperatorTok{\}} - - \KeywordTok{if} \OperatorTok{(}\FunctionTok{IsUserPremium}\OperatorTok{(}\NormalTok{user}\OperatorTok{))} - \OperatorTok{\{} - \DataTypeTok{var}\NormalTok{ approved }\OperatorTok{=}\NormalTok{ \_repository}\OperatorTok{.}\FunctionTok{GetEngineerApplications}\OperatorTok{(}\NormalTok{ModuleId}\OperatorTok{,} \StringTok{"Approved"}\OperatorTok{);} - \DataTypeTok{var}\NormalTok{ published }\OperatorTok{=}\NormalTok{ \_repository}\OperatorTok{.}\FunctionTok{GetEngineerApplications}\OperatorTok{(}\NormalTok{ModuleId}\OperatorTok{,} \StringTok{"Published"}\OperatorTok{);} -\NormalTok{ results}\OperatorTok{.}\FunctionTok{AddRange}\OperatorTok{(}\NormalTok{approved}\OperatorTok{.}\FunctionTok{Union}\OperatorTok{(}\NormalTok{published}\OperatorTok{));} -\NormalTok{ results }\OperatorTok{=}\NormalTok{ results}\OperatorTok{.}\FunctionTok{GroupBy}\OperatorTok{(}\NormalTok{a }\OperatorTok{=\textgreater{}}\NormalTok{ a}\OperatorTok{.}\FunctionTok{ApplicationId}\OperatorTok{).}\FunctionTok{Select}\OperatorTok{(}\NormalTok{g }\OperatorTok{=\textgreater{}}\NormalTok{ g}\OperatorTok{.}\FunctionTok{First}\OperatorTok{()).}\FunctionTok{ToList}\OperatorTok{();} - \OperatorTok{\}} - - \KeywordTok{return}\NormalTok{ Task}\OperatorTok{.}\FunctionTok{FromResult}\OperatorTok{(}\NormalTok{results}\OperatorTok{);} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -Administratoren erhalten alle Anträge zurück. Für andere Benutzer werden -zunächst die eigenen Anträge geladen. Wenn der Benutzer Premium-Status -hat, werden zusätzlich alle genehmigten und veröffentlichten Anträge -anderer Benutzer ergänzt. Durch \texttt{GroupBy} werden Duplikate -entfernt, die entstehen können, wenn ein eigener Antrag gleichzeitig den -Status „Approved'' trägt. - -\textbf{Mitgliedersuche und Kontaktfunktion} - -Die in der nachfolgenden Abbildung gezeigte Mitgliedersuche ermöglicht -Premium-Mitgliedern das gezielte Auffinden anderer registrierter -Benutzer. Die clientseitige Blazor-Komponente \texttt{UserSearch.razor} -stellt ein Eingabefeld bereit, über das der Benutzer seinen Suchbegriff -eingibt. Aus der dann resultierenden Listenansicht heraus ermöglicht -eine Kontaktfunktion, Nachrichten sicher an die gefundenen Personen zu -senden, ohne deren direkte E-Mail-Adresse offenzulegen. Bei jeder Suche -wird der eingegebene Text an den \texttt{ServerUserContactService} auf -dem Server übermittelt, der die eigentliche Suchlogik implementiert. - -\begin{figure} -\centering -\pandocbounded{\includegraphics[keepaspectratio]{./images/04-Florian/premium-mitglieder-suche.png}} -\caption{Mitgliedersuche und Kontaktfunktion für Premium-Mitglieder} -\end{figure} - -Die serverseitige Methode \texttt{SearchUsersAsync} prüft zunächst, ob -der Suchbegriff mindestens drei Zeichen umfasst, um übermäßig breite -Abfragen zu vermeiden, und ob der anfragende Benutzer authentifiziert -ist. Anschließend durchsucht sie die Benutzerdatenbank sowohl nach -Anzeigenamen als auch nach Benutzernamen, wobei die Suche -groß-/kleinschreibungsunabhängig erfolgt. Die Ergebnisse werden auf -maximal 20 Treffer begrenzt. - -Besonders wichtig ist die Datenschutzfilterung: Anstatt die -vollständigen \texttt{User}-Objekte aus der Datenbank zurückzugeben, -erstellt die Methode neue, reduzierte Objekte, die nur die Felder -\texttt{UserId}, \texttt{Username}, \texttt{DisplayName} und -\texttt{PhotoFileId} enthalten. E-Mail-Adressen, Passwort-Hashes und -andere sensible Daten werden dadurch serverseitig herausgefiltert, bevor -die Ergebnisse an den Client gesendet werden. Dieser Ansatz folgt dem -Prinzip der Datenminimierung --- es werden nur die Informationen -übertragen, die für die Anzeige der Suchergebnisse tatsächlich benötigt -werden. - -Die Kontaktfunktion ermöglicht es Premium-Mitgliedern, aus den -Suchergebnissen heraus direkt eine Nachricht an den gefundenen Benutzer -zu senden. Der Nachrichtenversand erfolgt über das -Oqtane-Benachrichtigungssystem. Dabei werden pro Nachricht zwei separate -Benachrichtigungen erstellt: Die erste Benachrichtigung hat ein leeres -\texttt{ToEmail}-Feld und wird daher ausschließlich als In-App-Nachricht -zugestellt, die der Empfänger beim nächsten Login in seinem -Benachrichtigungsbereich sieht. Die zweite Benachrichtigung enthält die -E-Mail-Adresse des Empfängers und löst zusätzlich eine E-Mail-Zustellung -aus. Durch diesen dualen Mechanismus wird sichergestellt, dass der -Empfänger sowohl innerhalb als auch außerhalb der Plattform erreicht -wird, ohne dass der Absender die E-Mail-Adresse des Empfängers jemals zu -sehen bekommt. - -Ergänzend steht eine Meldefunktion zur Verfügung, über die -Premium-Mitglieder Anträge mit unangemessenen oder fehlerhaften Inhalten -melden können. Diese Community-Moderationsfunktion unterstützt die -Administratoren bei der Qualitätssicherung der veröffentlichten Inhalte. - -\textbf{Datenbank und Persistenz} - -Alle Entitäten werden über einen Entity-Framework-Core-Datenbankkontext -verwaltet, der die Multi-Tenant-Datenbankverbindung automatisch -handhabt: - -\begin{Shaded} -\begin{Highlighting}[] -\KeywordTok{public} \KeywordTok{class}\NormalTok{ PremiumAreaContext }\OperatorTok{:}\NormalTok{ DBContextBase}\OperatorTok{,}\NormalTok{ ITransientService}\OperatorTok{,}\NormalTok{ IMultiDatabase} -\OperatorTok{\{} - \KeywordTok{public} \KeywordTok{virtual}\NormalTok{ DbSet}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{PremiumArea}\OperatorTok{\textgreater{}}\NormalTok{ PremiumArea }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \KeywordTok{virtual}\NormalTok{ DbSet}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{EngineerApplication}\OperatorTok{\textgreater{}}\NormalTok{ EngineerApplication }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \KeywordTok{virtual}\NormalTok{ DbSet}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{UserPremium}\OperatorTok{\textgreater{}}\NormalTok{ UserPremium }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - \KeywordTok{public} \KeywordTok{virtual}\NormalTok{ DbSet}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{PremiumEvent}\OperatorTok{\textgreater{}}\NormalTok{ PremiumEvent }\OperatorTok{\{} \KeywordTok{get}\OperatorTok{;} \KeywordTok{set}\OperatorTok{;} \OperatorTok{\}} - - \KeywordTok{public} \FunctionTok{PremiumAreaContext}\OperatorTok{(}\NormalTok{IDBContextDependencies DBContextDependencies}\OperatorTok{)} \OperatorTok{:} \KeywordTok{base}\OperatorTok{(}\NormalTok{DBContextDependencies}\OperatorTok{)} - \OperatorTok{\{} - \OperatorTok{\}} - - \KeywordTok{protected} \KeywordTok{override} \DataTypeTok{void} \FunctionTok{OnModelCreating}\OperatorTok{(}\NormalTok{ModelBuilder builder}\OperatorTok{)} - \OperatorTok{\{} - \KeywordTok{base}\OperatorTok{.}\FunctionTok{OnModelCreating}\OperatorTok{(}\NormalTok{builder}\OperatorTok{);} -\NormalTok{ builder}\OperatorTok{.}\FunctionTok{Entity}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{PremiumArea}\OperatorTok{\textgreater{}().}\FunctionTok{ToTable}\OperatorTok{(}\NormalTok{ActiveDatabase}\OperatorTok{.}\FunctionTok{RewriteName}\OperatorTok{(}\StringTok{"SZUAbsolventenvereinPremiumArea"}\OperatorTok{));} -\NormalTok{ builder}\OperatorTok{.}\FunctionTok{Entity}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{EngineerApplication}\OperatorTok{\textgreater{}().}\FunctionTok{ToTable}\OperatorTok{(}\NormalTok{ActiveDatabase}\OperatorTok{.}\FunctionTok{RewriteName}\OperatorTok{(}\StringTok{"SZUAbsolventenvereinEngineerApplications"}\OperatorTok{));} -\NormalTok{ builder}\OperatorTok{.}\FunctionTok{Entity}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{UserPremium}\OperatorTok{\textgreater{}().}\FunctionTok{ToTable}\OperatorTok{(}\NormalTok{ActiveDatabase}\OperatorTok{.}\FunctionTok{RewriteName}\OperatorTok{(}\StringTok{"SZUAbsolventenvereinUserPremium"}\OperatorTok{));} -\NormalTok{ builder}\OperatorTok{.}\FunctionTok{Entity}\OperatorTok{\textless{}}\NormalTok{Models}\OperatorTok{.}\FunctionTok{PremiumEvent}\OperatorTok{\textgreater{}().}\FunctionTok{ToTable}\OperatorTok{(}\NormalTok{ActiveDatabase}\OperatorTok{.}\FunctionTok{RewriteName}\OperatorTok{(}\StringTok{"SZUAbsolventenvereinPremiumEvents"}\OperatorTok{));} - \OperatorTok{\}} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -Die Tabellennamen werden über \texttt{ActiveDatabase.RewriteName()} -datenbankunabhängig gehalten, sodass das Modul mit verschiedenen -Datenbanksystemen betrieben werden kann. Neben der Antragstabelle -speichert das Modul den Premium-Status der Benutzer in der Tabelle -\texttt{UserPremium} mit einem Ablaufdatum und einer Quellenangabe. -Ergänzend protokolliert die Tabelle \texttt{PremiumEvent} jede Änderung -am Premium-Status als Audit-Trail, wodurch die vollständige Historie -aller Premium-Vergaben nachvollziehbar bleibt. - -Die Datenbankstruktur wird über Oqtane's Migrationssystem aufgebaut. Die -folgende Migration zeigt exemplarisch die Erstellung der drei -Kerntabellen: - -\begin{Shaded} -\begin{Highlighting}[] -\OperatorTok{[}\FunctionTok{DbContext}\OperatorTok{(}\KeywordTok{typeof}\OperatorTok{(}\NormalTok{PremiumAreaContext}\OperatorTok{))]} -\OperatorTok{[}\FunctionTok{Migration}\OperatorTok{(}\StringTok{"SZUAbsolventenverein.Module.PremiumArea.01.00.00.01"}\OperatorTok{)]} -\KeywordTok{public} \KeywordTok{class}\NormalTok{ AddPremiumTables }\OperatorTok{:}\NormalTok{ MultiDatabaseMigration} -\OperatorTok{\{} - \KeywordTok{public} \FunctionTok{AddPremiumTables}\OperatorTok{(}\NormalTok{IDatabase database}\OperatorTok{)} \OperatorTok{:} \KeywordTok{base}\OperatorTok{(}\NormalTok{database}\OperatorTok{)} \OperatorTok{\{} \OperatorTok{\}} - - \KeywordTok{protected} \KeywordTok{override} \DataTypeTok{void} \FunctionTok{Up}\OperatorTok{(}\NormalTok{MigrationBuilder migrationBuilder}\OperatorTok{)} - \OperatorTok{\{} - \DataTypeTok{var}\NormalTok{ engAppBuilder }\OperatorTok{=} \KeywordTok{new} \FunctionTok{EngineerApplicationEntityBuilder}\OperatorTok{(}\NormalTok{migrationBuilder}\OperatorTok{,}\NormalTok{ ActiveDatabase}\OperatorTok{);} -\NormalTok{ engAppBuilder}\OperatorTok{.}\FunctionTok{Create}\OperatorTok{();} - - \DataTypeTok{var}\NormalTok{ userPremBuilder }\OperatorTok{=} \KeywordTok{new} \FunctionTok{UserPremiumEntityBuilder}\OperatorTok{(}\NormalTok{migrationBuilder}\OperatorTok{,}\NormalTok{ ActiveDatabase}\OperatorTok{);} -\NormalTok{ userPremBuilder}\OperatorTok{.}\FunctionTok{Create}\OperatorTok{();} - - \DataTypeTok{var}\NormalTok{ premEventBuilder }\OperatorTok{=} \KeywordTok{new} \FunctionTok{PremiumEventEntityBuilder}\OperatorTok{(}\NormalTok{migrationBuilder}\OperatorTok{,}\NormalTok{ ActiveDatabase}\OperatorTok{);} -\NormalTok{ premEventBuilder}\OperatorTok{.}\FunctionTok{Create}\OperatorTok{();} - \OperatorTok{\}} - - \KeywordTok{protected} \KeywordTok{override} \DataTypeTok{void} \FunctionTok{Down}\OperatorTok{(}\NormalTok{MigrationBuilder migrationBuilder}\OperatorTok{)} - \OperatorTok{\{} - \DataTypeTok{var}\NormalTok{ engAppBuilder }\OperatorTok{=} \KeywordTok{new} \FunctionTok{EngineerApplicationEntityBuilder}\OperatorTok{(}\NormalTok{migrationBuilder}\OperatorTok{,}\NormalTok{ ActiveDatabase}\OperatorTok{);} -\NormalTok{ engAppBuilder}\OperatorTok{.}\FunctionTok{Drop}\OperatorTok{();} - - \DataTypeTok{var}\NormalTok{ userPremBuilder }\OperatorTok{=} \KeywordTok{new} \FunctionTok{UserPremiumEntityBuilder}\OperatorTok{(}\NormalTok{migrationBuilder}\OperatorTok{,}\NormalTok{ ActiveDatabase}\OperatorTok{);} -\NormalTok{ us} -\NormalTok{ erPremBuilder}\OperatorTok{.}\FunctionTok{Drop}\OperatorTok{();} - - \DataTypeTok{var}\NormalTok{ premEventBuilder }\OperatorTok{=} \KeywordTok{new} \FunctionTok{PremiumEventEntityBuilder}\OperatorTok{(}\NormalTok{migrationBuilder}\OperatorTok{,}\NormalTok{ ActiveDatabase}\OperatorTok{);} -\NormalTok{ premEventBuilder}\OperatorTok{.}\FunctionTok{Drop}\OperatorTok{();} - \OperatorTok{\}} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -Insgesamt definieren vier Migrationen die Datenbankstruktur: Die erste -erstellt die Basistabelle des Moduls, die zweite fügt die drei Tabellen -für Ingenieur-Anträge, Premium-Status und Premium-Events hinzu, die -dritte entfernt nicht mehr benötigte Spalten nach der Umstellung auf den -Oqtane FileManager, und die vierte ergänzt die Felder für Titel und -Kurzbeschreibung. Alle Migrationen werden bei der Modulinstallation -automatisch ausgeführt. - -\paragraph{Zugriffsbeschränkung und -Benutzerrechte}\label{zugriffsbeschruxe4nkung-und-benutzerrechte} - -Der Zugriff auf den Premium-Bereich wird durch ein mehrstufiges -Berechtigungssystem gesteuert, das sowohl auf Server- als auch auf -Client-Seite durchgesetzt wird. Die verfügbaren Berechtigungen werden in -der \texttt{ModuleInfo}-Klasse registriert: - -\begin{Shaded} -\begin{Highlighting}[] -\KeywordTok{public} \KeywordTok{class}\NormalTok{ ModuleInfo }\OperatorTok{:}\NormalTok{ IModule} -\OperatorTok{\{} - \KeywordTok{public}\NormalTok{ ModuleDefinition ModuleDefinition }\OperatorTok{=\textgreater{}} \KeywordTok{new}\NormalTok{ ModuleDefinition} - \OperatorTok{\{} -\NormalTok{ Name }\OperatorTok{=} \StringTok{"PremiumArea"}\OperatorTok{,} -\NormalTok{ Description }\OperatorTok{=} \StringTok{"This module adds a premium member system to Octane."}\OperatorTok{,} -\NormalTok{ Version }\OperatorTok{=} \StringTok{"1.0.3"}\OperatorTok{,} -\NormalTok{ ServerManagerType }\OperatorTok{=} \StringTok{"SZUAbsolventenverein.Module.PremiumArea.Manager.PremiumAreaManager, SZUAbsolventenverein.Module.PremiumArea.Server.Oqtane"}\OperatorTok{,} -\NormalTok{ ReleaseVersions }\OperatorTok{=} \StringTok{"1.0.0,1.0.1,1.0.2,1.0.3"}\OperatorTok{,} -\NormalTok{ Dependencies }\OperatorTok{=} \StringTok{"SZUAbsolventenverein.Module.PremiumArea.Shared.Oqtane"}\OperatorTok{,} -\NormalTok{ PermissionNames }\OperatorTok{=}\NormalTok{ $}\StringTok{"\{PermissionNames.View\},\{PermissionNames.Edit\},\{PermissionNames.Browse\}"} - \OperatorTok{\};} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -Die Eigenschaft \texttt{PermissionNames} legt fest, welche -Berechtigungen für das Modul verfügbar sind. Die View-Berechtigung -erlaubt grundlegende Funktionen wie das Einreichen eigener Anträge. Die -Edit-Berechtigung gewährt administrative Funktionen wie das Genehmigen -und Ablehnen von Anträgen. Über \texttt{ReleaseVersions} wird die -Migrationshistorie definiert, sodass Oqtane bei Updates die korrekten -Migrationsschritte ausführt. - -Grundsätzlich wird zwischen drei Zugriffsebenen unterschieden: -Standardbenutzer können ausschließlich eigene Ingenieur-Anträge -einreichen und verwalten. Sie haben keinen Einblick in die Anträge -anderer Mitglieder und können weder die Mitgliedersuche noch die -Kontaktfunktion nutzen. Premium-Mitglieder erhalten Zugang zu allen -Funktionen des Premium-Bereichs. Administratoren besitzen -uneingeschränkten Zugriff und können sämtliche Anträge unabhängig vom -Status einsehen, genehmigen oder ablehnen. - -Der Premium-Status kann auf zwei Wegen erlangt werden: durch die -Genehmigung eines Ingenieur-Antrags mit automatischer 12-monatiger -Mitgliedschaft oder durch manuelle Zuweisung der Oqtane-Rolle „Premium -Member'' durch einen Administrator. Die serverseitige Methode -\texttt{IsUserPremium} berücksichtigt beide Wege: - -\begin{Shaded} -\begin{Highlighting}[] -\KeywordTok{private} \DataTypeTok{bool} \FunctionTok{IsUserPremium}\OperatorTok{(}\NormalTok{System}\OperatorTok{.}\FunctionTok{Security}\OperatorTok{.}\FunctionTok{Claims}\OperatorTok{.}\FunctionTok{ClaimsPrincipal}\NormalTok{ user}\OperatorTok{)} -\OperatorTok{\{} - \KeywordTok{if} \OperatorTok{(!}\NormalTok{user}\OperatorTok{.}\FunctionTok{Identity}\OperatorTok{.}\FunctionTok{IsAuthenticated}\OperatorTok{)} - \KeywordTok{return} \KeywordTok{false}\OperatorTok{;} - - \KeywordTok{if} \OperatorTok{(}\NormalTok{user}\OperatorTok{.}\FunctionTok{IsInRole}\OperatorTok{(}\StringTok{"Premium Member"}\OperatorTok{))} - \KeywordTok{return} \KeywordTok{true}\OperatorTok{;} - - \DataTypeTok{int}\NormalTok{ userId }\OperatorTok{=} \OperatorTok{{-}}\DecValTok{1}\OperatorTok{;} - \DataTypeTok{var}\NormalTok{ claim }\OperatorTok{=}\NormalTok{ user}\OperatorTok{.}\FunctionTok{Claims}\OperatorTok{.}\FunctionTok{FirstOrDefault}\OperatorTok{(}\NormalTok{item }\OperatorTok{=\textgreater{}} -\NormalTok{ item}\OperatorTok{.}\FunctionTok{Type} \OperatorTok{==}\NormalTok{ System}\OperatorTok{.}\FunctionTok{Security}\OperatorTok{.}\FunctionTok{Claims}\OperatorTok{.}\FunctionTok{ClaimTypes}\OperatorTok{.}\FunctionTok{NameIdentifier}\OperatorTok{);} - \KeywordTok{if} \OperatorTok{(}\NormalTok{claim }\OperatorTok{!=} \KeywordTok{null}\OperatorTok{)} - \DataTypeTok{int}\OperatorTok{.}\FunctionTok{TryParse}\OperatorTok{(}\NormalTok{claim}\OperatorTok{.}\FunctionTok{Value}\OperatorTok{,} \KeywordTok{out}\NormalTok{ userId}\OperatorTok{);} - - \KeywordTok{if} \OperatorTok{(}\NormalTok{userId }\OperatorTok{!=} \OperatorTok{{-}}\DecValTok{1}\OperatorTok{)} - \KeywordTok{return}\NormalTok{ \_premiumService}\OperatorTok{.}\FunctionTok{IsPremium}\OperatorTok{(}\NormalTok{userId}\OperatorTok{);} - - \KeywordTok{return} \KeywordTok{false}\OperatorTok{;} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -\begin{figure} -\centering -\includegraphics[width=0.8\linewidth,height=0.7\textheight]{flowchart-premium-access.pdf} -\caption{Zugriffsprüfung für Premium-Inhalte} -\end{figure} - -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 -\texttt{{[}Authorize{]}}-Attribut mit Policies wie -\texttt{PolicyNames.ViewModule} und \texttt{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. - -\paragraph{Mehrwert für registrierte -Mitglieder}\label{mehrwert-fuxfcr-registrierte-mitglieder} - -Der Premium-Bereich schafft einen konkreten Mehrwert für registrierte -Mitglieder auf mehreren Ebenen. Auf fachlicher Ebene entsteht durch die -gesammelten Ingenieur-Anträge eine wachsende Wissensbasis, die allen -Premium-Mitgliedern zugänglich ist. Absolventen können von den Arbeiten -anderer Mitglieder lernen, sich inspirieren lassen und fachliche Ansätze -vergleichen. Durch die Möglichkeit, Titel und Kurzbeschreibungen zu -hinterlegen, können Mitglieder gezielt nach relevanten Themen suchen, -ohne jedes PDF-Dokument einzeln öffnen zu müssen. - -Auf sozialer Ebene fördert der Premium-Bereich die Vernetzung innerhalb -der Absolventengemeinschaft. Die Mitgliedersuche mit integrierter -Kontaktfunktion ermöglicht es, gezielt nach ehemaligen Kommilitonen oder -Fachkollegen zu suchen und direkt Kontakt aufzunehmen. Der duale -Benachrichtigungsmechanismus --- bestehend aus In-App-Nachricht und -E-Mail --- stellt sicher, dass Kontaktanfragen zuverlässig zugestellt -werden und kein Mitglied eine Nachricht verpasst. - -Auf motivationaler Ebene bietet das zeitlich begrenzte Premium-System -einen Anreiz zur aktiven Teilnahme. Die Aussicht auf exklusive -Funktionen motiviert Mitglieder, eigene Ingenieur-Anträge einzureichen -und damit sowohl den eigenen Premium-Status zu erlangen als auch zur -Wissensbasis der Gemeinschaft beizutragen. Die Meldefunktion gibt -Mitgliedern zusätzlich die Möglichkeit, aktiv zur Qualitätssicherung -beizutragen und unangemessene Inhalte zu kennzeichnen. - -Der Datenschutz wird dabei konsequent gewahrt. Die Mitgliedersuche gibt -nur ausgewählte, nicht-sensible Informationen wie Anzeigenamen und -Benutzernamen zurück. E-Mail-Adressen und andere persönliche Daten -werden serverseitig herausgefiltert und sind für andere Mitglieder nicht -einsehbar. Die Kontaktaufnahme erfolgt ausschließlich über das -plattformeigene Benachrichtigungssystem, sodass kein Mitglied seine -persönlichen Kontaktdaten preisgeben muss. - -\subsection{Learnings}\label{learnings-1} - -\subsubsection{Technische und fachliche -Erkenntnisse}\label{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. - -Ein wesentlicher Lernaspekt war die praktische Anwendung des -Webframeworks ASP.NET auf Basis der Plattform .NET 8. Dabei konnte ich -ein tieferes Verständnis für die Architektur moderner Webanwendungen -entwickeln. Besonders wichtig war das Zusammenspiel zwischen -Backend-Logik, Datenbankzugriff und Benutzeroberfläche. Durch die -Entwicklung verschiedener Funktionen, wie beispielsweise -Eventverwaltung, Benutzerprofile und Premiumbereiche, wurde deutlich, -wie wichtig eine klare Strukturierung der Anwendung ist. - -Ein weiterer technischer Schwerpunkt war die Arbeit mit der relationalen -Datenbank PostgreSQL. Hier lernte ich, Datenmodelle zu entwerfen, -Tabellenbeziehungen zu definieren und effiziente Datenbankabfragen zu -erstellen. Da die Plattform personenbezogene Daten verwaltet, musste -auch auf Aspekte wie Datensicherheit und Datenintegrität geachtet -werden. In diesem Zusammenhang wurde zusätzlich ein Backup- und -Restore-System implementiert, das eine Wiederherstellung der Datenbank -im Falle eines Fehlers ermöglicht. Dadurch konnte ich praktische -Erfahrungen im Bereich Datensicherung und Systemstabilität sammeln. - -Ein weiterer wichtiger Bestandteil der Arbeit war die Integration eines -externen Authentifizierungssystems über LinkedIn. Dabei wurde das -Autorisierungsprotokoll OAuth 2.0 eingesetzt. Durch diese -Implementierung konnte ich ein besseres Verständnis für moderne -Authentifizierungsverfahren entwickeln. Besonders interessant war dabei -der Ablauf des OAuth-Authentifizierungsprozesses, bei dem Benutzer über -einen externen Anbieter authentifiziert werden, ohne dass ihre -Zugangsdaten direkt an die eigene Anwendung übermittelt werden. - -Zusätzlich wurden Funktionen im Bereich Datenschutz umgesetzt, die den -Anforderungen der DSGVO entsprechen. Dazu zählen unter anderem -Möglichkeiten zur Verwaltung personenbezogener Daten sowie -automatisierte Löschmechanismen. Diese Aspekte haben mir gezeigt, wie -wichtig Datenschutz und rechtliche Anforderungen bei der Entwicklung -moderner Webanwendungen sind. - -Insgesamt konnte ich durch die praktische Umsetzung der Plattform ein -deutlich tieferes Verständnis für Webtechnologien, Systemarchitekturen -und Backend-Entwicklung gewinnen. - -\subsubsection{Agile Projektarbeit und Teamarbeit -(Zeitmanagement)}\label{agile-projektarbeit-und-teamarbeit-zeitmanagement} - -Neben den technischen Aspekten konnte ich auch wichtige Erfahrungen im -Bereich der agilen Projektarbeit sammeln. Für die Organisation des -Projekts wurde das agile Framework Scrum eingesetzt. - -Die Arbeit wurde in Sprints von jeweils zwei Wochen unterteilt. -Innerhalb eines Sprints wurden konkrete Aufgaben definiert, die bis zum -Ende des Zeitraums umgesetzt werden sollten. Diese Struktur ermöglichte -eine klare Planung der Arbeitsschritte und half dabei, größere -Entwicklungsaufgaben in kleinere, überschaubare Teilaufgaben zu -unterteilen. - -Ein wichtiger Bestandteil der Scrum-Arbeitsweise war die regelmäßige -Reflexion der Arbeit. Nach jedem Sprint konnte überprüft werden, welche -Funktionen erfolgreich umgesetzt wurden und welche Aufgaben -möglicherweise angepasst werden mussten. Dadurch entstand ein iterativer -Entwicklungsprozess, bei dem das System kontinuierlich verbessert wurde. - -Auch das Zeitmanagement spielte eine zentrale Rolle. Da die Entwicklung -der Plattform mehrere unterschiedliche Komponenten umfasste -- -beispielsweise Datenbankstruktur, Benutzerverwaltung, -Authentifizierungssystem und Eventverwaltung -- war eine gute Planung -notwendig. Durch die Aufteilung in Sprints konnte ich meine Arbeitszeit -besser strukturieren und Prioritäten setzen. - -Darüber hinaus zeigte sich, dass agile Methoden besonders gut für -Softwareprojekte geeignet sind, da sie flexible Anpassungen während der -Entwicklung ermöglichen. Neue Anforderungen oder Verbesserungen konnten -relativ einfach in zukünftige Sprints integriert werden. - -Diese Erfahrungen haben mir ein besseres Verständnis für moderne -Softwareentwicklungsprozesse vermittelt und gezeigt, wie wichtig -strukturierte Planung und kontinuierliche Verbesserung in technischen -Projekten sind. - -\subsubsection{Persönliche -Weiterentwicklung}\label{persuxf6nliche-weiterentwicklung} - -Neben den technischen und organisatorischen Erkenntnissen stellte die -Diplomarbeit auch eine wichtige persönliche Weiterentwicklung dar. Die -eigenständige Planung und Umsetzung eines komplexen Softwareprojekts -erforderte ein hohes Maß an Selbstorganisation und Durchhaltevermögen. - -Während der Entwicklung der Alumni-Plattform musste ich regelmäßig neue -Technologien und Konzepte erlernen. Dazu gehörten unter anderem -Webframeworks, Datenbanksysteme, Authentifizierungsprotokolle sowie -Aspekte der IT-Sicherheit und des Datenschutzes. Der Umgang mit diesen -Technologien hat meine Fähigkeiten im Bereich der Softwareentwicklung -deutlich erweitert. - -Darüber hinaus lernte ich, technische Probleme systematisch zu -analysieren und eigenständig Lösungen zu entwickeln. Besonders bei der -Integration verschiedener Systeme -- beispielsweise der -LinkedIn-Authentifizierung oder der Datenbankfunktionen -- traten immer -wieder Herausforderungen auf, die eine intensive Recherche und -Fehlersuche erforderten. - -Ein weiterer wichtiger Lernaspekt war die Verbesserung meiner -Fähigkeiten im Bereich der Dokumentation. Die Erstellung eines -Diplomarbeitsbuchs erfordert eine strukturierte und verständliche -Beschreibung technischer Inhalte. Dadurch konnte ich lernen, komplexe -technische Zusammenhänge klar und nachvollziehbar darzustellen. - -Zusammenfassend hat mir die Diplomarbeit nicht nur tiefere technische -Kenntnisse vermittelt, sondern auch meine Fähigkeiten im Bereich -Problemlösung, Selbstorganisation und Projektplanung gestärkt. Diese -Kompetenzen stellen eine wichtige Grundlage für zukünftige berufliche -Tätigkeiten im Bereich der Softwareentwicklung dar. - -\subsection{Fazit und Ausblick}\label{fazit-und-ausblick-1} - -\subsubsection{Zusammenfassung der -Arbeit}\label{zusammenfassung-der-arbeit} - -Ziel dieser Diplomarbeit war die Konzeption und Entwicklung einer -webbasierten Alumni-Plattform für den Absolventenverein. Die Plattform -soll ehemaligen Studierenden ermöglichen, miteinander in Kontakt zu -bleiben, Informationen auszutauschen und an Veranstaltungen des Vereins -teilzunehmen. Dadurch wird die Kommunikation zwischen Absolventinnen und -Absolventen sowie der Bildungseinrichtung langfristig gestärkt. - -Im Rahmen der Arbeit wurde eine moderne Webanwendung entwickelt, die auf -dem Framework ASP.NET und der Plattform .NET 8 basiert. Die Speicherung -der Daten erfolgt in der relationalen Datenbank PostgreSQL, welche eine -strukturierte Verwaltung der Benutzerdaten, Eventinformationen und -Systemdaten ermöglicht. - -Ein wichtiger Bestandteil der Plattform ist die Benutzerverwaltung. Um -den Registrierungs- und Loginprozess zu vereinfachen, wurde eine -Authentifizierung über LinkedIn implementiert. Dabei wird das -Autorisierungsprotokoll OAuth 2.0 verwendet, wodurch sich Benutzer mit -ihrem bestehenden LinkedIn-Konto anmelden können. Dies erhöht die -Benutzerfreundlichkeit und reduziert gleichzeitig den Verwaltungsaufwand -für eigene Login-Daten. - -Neben der Benutzerverwaltung wurden auch weitere Funktionen umgesetzt. -Dazu zählen unter anderem die Verwaltung von Veranstaltungen, für die -sich Alumni anmelden können, sowie ein Premiumbereich mit erweiterten -Funktionen für Mitglieder. Zusätzlich wurden Maßnahmen im Bereich -Datenschutz umgesetzt, um den Anforderungen der DSGVO gerecht zu werden. -Dazu gehört beispielsweise die Möglichkeit zur Verwaltung und Löschung -personenbezogener Daten sowie ein System zur Sicherung der Datenbank -mittels Backup- und Restore-Funktionen. - -Die Entwicklung der Plattform erfolgte nach agilen Prinzipien mithilfe -des Scrum-Frameworks. Die Arbeit wurde in mehrere zweiwöchige Sprints -unterteilt, wodurch eine strukturierte und iterative Entwicklung der -einzelnen Funktionen möglich war. - -Zusammenfassend konnte mit der Diplomarbeit eine funktionale und -erweiterbare Plattform entwickelt werden, die eine moderne Grundlage für -die digitale Vernetzung von Alumni darstellt. - -\subsubsection{Mögliche Erweiterungen der -Webseite}\label{muxf6gliche-erweiterungen-der-webseite} - -Obwohl bereits viele grundlegende Funktionen implementiert wurden, -bietet die Plattform weiteres Potenzial für zukünftige Erweiterungen und -Verbesserungen. - -Eine mögliche Erweiterung wäre beispielsweise die Integration eines -internen Nachrichtensystems. Dadurch könnten Alumni direkt über die -Plattform miteinander kommunizieren und Kontakte einfacher pflegen. -Ebenso wäre die Implementierung eines Forums oder einer -Diskussionsplattform denkbar, in der Mitglieder Erfahrungen austauschen -oder berufliche Themen diskutieren können. - -Auch im Bereich der Eventverwaltung könnten zusätzliche Funktionen -integriert werden. Beispielsweise wäre es möglich, automatische -Erinnerungen für Veranstaltungen zu versenden oder Teilnehmerlisten -übersichtlich darzustellen. Darüber hinaus könnten Eventberichte oder -Fotogalerien vergangener Veranstaltungen integriert werden. - -Ein weiterer möglicher Ausbau betrifft den Premiumbereich der Plattform. -Hier könnten zusätzliche Inhalte oder exklusive Funktionen für -Mitglieder bereitgestellt werden, etwa spezielle Networking-Angebote -oder Zugriff auf besondere Veranstaltungen. - -Auch technische Erweiterungen sind denkbar. Dazu zählen beispielsweise: - -eine mobile Optimierung der Plattform - -eine eigene mobile App - -Integration weiterer Social-Media-Plattformen - -erweiterte Such- und Filterfunktionen für Alumni-Profile - -Durch diese Erweiterungen könnte die Plattform langfristig noch -attraktiver und vielseitiger gestaltet werden. - -\subsubsection{Zukunftspotenzial für den -Absolventenverein}\label{zukunftspotenzial-fuxfcr-den-absolventenverein} - -Die entwickelte Alumni-Plattform bietet dem Absolventenverein eine -moderne digitale Infrastruktur zur Verwaltung und Vernetzung seiner -Mitglieder. Durch die zentrale Plattform können Informationen, -Veranstaltungen und Kontakte effizient organisiert werden. - -Ein wesentlicher Vorteil besteht darin, dass der Verein seine Mitglieder -dauerhaft an die Institution binden kann. Ehemalige Studierende haben -die Möglichkeit, weiterhin mit ihrer Ausbildungsstätte und anderen -Absolventinnen und Absolventen in Verbindung zu bleiben. Dies stärkt das -Netzwerk des Vereins und kann langfristig auch neue Kooperationen oder -berufliche Kontakte ermöglichen. - -Darüber hinaus kann die Plattform auch zur Organisation von -Veranstaltungen genutzt werden. Alumni können sich direkt online für -Events anmelden und erhalten Informationen zu kommenden Aktivitäten. -Dadurch wird die Planung von Veranstaltungen für den Verein deutlich -erleichtert. - -Langfristig kann die Plattform zu einem zentralen digitalen Treffpunkt -für Absolventinnen und Absolventen werden. Besonders im beruflichen -Umfeld kann ein starkes Alumni-Netzwerk einen großen Mehrwert bieten, -beispielsweise durch den Austausch von Erfahrungen oder beruflichen -Möglichkeiten. - -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. - -\cleardoublepage - -\section{Konstantin Hintermayer}\label{konstantin-hintermayer-1} - -\subsection{Einleitung}\label{einleitung} - -\subsubsection{Motivation}\label{motivation-1} - -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)? - -\subsubsection{Auftrag und persönliche -Aufgabenstellungen}\label{auftrag-und-persuxf6nliche-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: - -\paragraph{Projektleitung und Organisation (Product -Owner)}\label{projektleitung-und-organisation-product-owner} - -~ - -Als Product Owner war ich für die Definition der Produktvision und die -Priorisierung des Backlogs verantwortlich. Dies beinhaltete: - -\textbf{Anforderungsmanagement}: Erhebung und Strukturierung der -Anforderungen in Zusammenarbeit mit den Betreuern und dem Team. - -\textbf{Sprint-Planung}: Organisation der 14-tägigen Sprints in -YouTrack, um einen kontinuierlichen Entwicklungsfluss sicherzustellen. - -\textbf{Qualitätssicherung}: Definition der \emph{Definition of Done} -(DoD) und Durchführung von Code-Reviews zur Einhaltung von -Architekturstandards. - -\paragraph{Infrastruktur und -Systemarchitektur}\label{infrastruktur-und-systemarchitektur} - -~ - -Ein wesentlicher Teil meiner Arbeit lag in der Bereitstellung der -technischen Basis für das gesamte Team: - \textbf{Deployment-Strategie}: -Konzeption und Umsetzung der Server-Infrastruktur auf Basis von Debian -Linux und NginX als Reverse-Proxy. - \textbf{Datenbankdesign}: Entwurf -des relationalen Datenmodells in PostgreSQL, inklusive der Absicherung -durch SSL/TLS. - \textbf{CI/CD-Pipeline}: Automatisierung der Build- und -Deployment-Prozesse mittels Gitea Actions für eine effiziente -Integration der Teambeiträge. - -\paragraph{Modulentwicklung}\label{modulentwicklung} - -~ - -Zusätzlich zur Infrastruktur habe ich drei zentrale Module für den -Alumnihub entworfen und implementiert: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - \textbf{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. -\item - \textbf{Reporting System}: Ein generisches System zur Meldung von - Inhalten, das nach dem \emph{Open-Closed-Prinzip} entworfen wurde, um - eine einfache Erweiterbarkeit für alle anderen Module zu bieten. -\item - \textbf{Schwarzes Brett (BlackBoard)}: Ein Community-Modul für den - Austausch von Informationen, inklusive eines automatisierten - E-Mail-Digest-Systems zur Nutzerbenachrichtigung. -\end{enumerate} - -\subsection{Anforderungen an das entwickelte Modul bzw. die -Funktionalität}\label{anforderungen-an-das-entwickelte-modul-bzw.-die-funktionalituxe4t-1} - -\subsubsection{Modulanforderungen / funktionale -Anforderungen}\label{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: - -\paragraph{Anmeldetool -(EventRegistration)}\label{anmeldetool-eventregistration} - -~ - -Das Ziel des Anmeldetools ist die effiziente Organisation von -Vereinsveranstaltungen. - -\begin{itemize} -\tightlist -\item - \textbf{Veranstaltungsmanagement}: Administratoren müssen in der Lage - sein, neue Veranstaltungen anzulegen. Dabei müssen Name, Beschreibung, - Datum, Zeit und Ort festlegbar sein. -\item - \textbf{Anmeldeprozess}: Registrierte Benutzer müssen sich für eine - Veranstaltung an- oder abmelden können. -\item - \textbf{Teilnehmerliste}: Für jede Veranstaltung muss eine Übersicht - der Rückmeldungen (Anmeldungen/Absagen) für Administratoren einsehbar - sein. -\item - \textbf{Statistische Auswertung}: Die Rückmeldungen sollen grafisch - (z. B. als Tortendiagramm) aufbereitet werden, um die Planung zu - erleichtern. -\end{itemize} - -\paragraph{Globales Reporting System}\label{globales-reporting-system} - -~ - -Das Reporting System dient der Qualitätssicherung von Benutzerinhalten -über alle Module hinweg. - -\begin{itemize} -\tightlist -\item - \textbf{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. -\item - \textbf{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. -\item - \textbf{Administrations-Dashboard}: Gemeldete Inhalte müssen in einer - zentralen Übersicht für Administratoren aufgelistet werden. -\item - \textbf{Moderationsaktionen}: Administratoren müssen gemeldete Inhalte - löschen, die Meldung ignorieren oder den Ersteller verwarnen/sperren - können. -\end{itemize} - -\paragraph{Schwarzes Brett -(BlackBoard)}\label{schwarzes-brett-blackboard} - -~ - -Das Schwarze Brett fungiert als digitale Kommunikationsplattform für den -Verein. - -\begin{itemize} -\tightlist -\item - \textbf{Beiträge erstellen}: Benutzer müssen Textbeiträge erstellen - können. Die Formatierung der Texte soll über einen Rich-Text-Editor - möglich sein. -\item - \textbf{Bilder-Upload}: Zu jedem Beitrag soll optional ein Bild - hochgeladen werden können, welches automatisch für die Vorschau - skaliert wird. -\item - \textbf{Benachrichtigungs-System}: Das System soll regelmäßig - (täglich/wöchentlich) eine Zusammenfassung neuer Beiträge per E-Mail - an alle interessierten Mitglieder versenden. -\end{itemize} - -\paragraph{Mass Mailing (Admin)}\label{mass-mailing-admin} - -~ - -Dieses Modul ermöglicht die direkte Kommunikation des Vorstandes mit -allen Mitgliedern. - -\begin{itemize} -\tightlist -\item - \textbf{Rundmails verfassen}: Administratoren müssen E-Mails mit - Betreff und Inhalt an alle registrierten Benutzer verfassen können. -\item - \textbf{Personalisierung}: Die E-Mails sollen automatisch mit dem - Namen des Empfängers personalisiert werden können. -\item - \textbf{Verspätetes Senden}: Aufgrund von Versandlimits des Providers - (Brevo) müssen die E-Mails in eine Warteschlange eingereiht und - zeitversetzt in Batches versendet werden. -\end{itemize} - -\paragraph{Token Lifetime Management -(Admin)}\label{token-lifetime-management-admin} - -~ - -Dies dient der Konfiguration sicherheitsrelevanter Parameter. - -\begin{itemize} -\tightlist -\item - \textbf{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. -\item - \textbf{Einstellungs-Persistenz}: Die geänderten Werte müssen - dauerhaft gespeichert werden und sofort für neue Token-Generierungen - wirksam sein. -\end{itemize} - -\subsubsection{Use Cases}\label{use-cases} - -Um die Interaktion der Benutzer mit den Modulen zu verdeutlichen, wurden -folgende Use Cases definiert: - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.0660}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2170}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1698}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.5472}}@{}} -\caption{Wesentliche Use Cases der entwickelten Module}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -ID -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Name -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Akteur -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -ID -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Name -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Akteur -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Beschreibung -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -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. \\ -\end{longtable} - -Es ist zu beachten, dass es sich hierbei um eine Auswahl handelt und -nicht alle Use Cases der Module abgebildet werden. - -\subsection{Technisches Umfeld}\label{technisches-umfeld} - -Mein Aufgabenbereich umfasst einerseits die Entwicklung eigener Module, -sowie das Bereitstellen des Services. - -\subsubsection{Auswahlverfahren}\label{auswahlverfahren} - -\paragraph{Entscheidungsfindung CMS}\label{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: - -\begin{itemize} -\tightlist -\item - Piranha CMS \textgreater{} Piranha erscheint auf den ersten Blick - nicht so flexibel wie Oqtane, es basiert auf .NET 8.0 und wird nicht - so aktiv gewartet. -\item - Umbraco \textgreater{} 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! -\item - DNN / Dot Net Nuke \textgreater{} 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. -\item - Oqtane \textgreater{} 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. -\end{itemize} - -Insbesondere aufgrund seiner sehr hohen Flexibilität, haben wir uns am -Ende für Oqtane entschieden. - -\paragraph{Entscheidungsfindung restliche -Infrastruktur}\label{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: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - Auf welche Art Datenbank setzen wir? SQL, NoSQL, Graph, \ldots{} -\item - Mit welcher speziellen Implementierung bekommen wir Support und bei - welcher haben wir Vorwissen im Team? -\item - Ist das auserkorene System kompatibel mit dem CMS, auf dem wir - aufbauen? -\end{enumerate} - -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. - -\subsubsection{Beschreibung und Architektur von -Oqtane}\label{beschreibung-und-architektur-von-oqtane} - -Oqtane ist ein Framework und CMS zur Entwicklung von Webseiten mithilfe -von ASP.NET und Blazor.\footnote{Oqtane Foundation (2024a) (siehe - Internet-/Intranetverzeichnis).} Ein Oqtane-System besteht aus -mehreren Komponenten. - -In dieser Diplomarbeit fokussieren wir uns hauptsächlich auf -\texttt{Themes} und \texttt{Modules}, aber es gibt auch -\texttt{Language\ Packs} und \texttt{Pure\ Extensions}.\footnote{Oqtane - Foundation (2024b) (siehe Internet-/Intranetverzeichnis).} - -Ein \texttt{Module} (Modul) soll neue Funktionalitäten in das CMS -hinzufügen und ein \texttt{Theme} soll die ganze Gestaltung der Webseite -(die Shell) festlegen.\footnote{Ebenda.} - -\paragraph{Architektur eines Moduls}\label{architektur-eines-moduls} - -~ - -Ein Modul in Oqtane besteht aus vier Projekten: - -\begin{itemize} -\item - 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. -\item - 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. -\item - 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. -\item - Im Package Projekt findet man Skripte zum Debuggen und Releasen eines - Moduls und die NuGet-Spezifikation. - - \begin{itemize} - \tightlist - \item - Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte - und Stylesheets der drei anderen Projekte in den bereits gebauten - Oqtane.Server - \texttt{oqtane.framework/oqtane.server/bin/debug/net10.0/...} - kopiert. - \item - 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). - \end{itemize} -\end{itemize} - -\subsubsection{Zusammenspiel der -Infrastruktur}\label{zusammenspiel-der-infrastruktur} - -In diesem Kapitel erkläre ich wie die ausgewählten Komponenten -zusammenspielen. - -\paragraph{NginX as Reverse Proxy}\label{nginx-as-reverse-proxy} - -~ - -NginX fungiert in unserer Infrastruktur als \texttt{Reverse\ Proxy}. Ein -Reverse Proxy nimmt Anfragen aus dem Internet entgegen und leitet sie an -interne Server (wie Kestrel) weiter. Dies bietet mehrere Vorteile: - -\begin{itemize} -\tightlist -\item - \textbf{Sicherheit}: Die interne Applikation ist nicht direkt dem - Internet ausgesetzt. -\item - \textbf{SSL-Terminierung}: NginX übernimmt die rechenintensive - Verschlüsselung (HTTPS), während die Applikation dahinter über - einfaches HTTP kommuniziert. -\item - \textbf{Statische Inhalte}: NginX kann statische Dateien (Bilder, CSS) - effizienter ausliefern als ein Applikationsserver. -\end{itemize} - -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 (\texttt{nginx.conf}) für -den Alumnihub: - -\begin{Shaded} -\begin{Highlighting}[] -\DataTypeTok{server} \OperatorTok{\{} - \DataTypeTok{listen} \DecValTok{443} \KeywordTok{ssl}\OperatorTok{;} - \DataTypeTok{server\_name}\NormalTok{ alumni.example.com}\OperatorTok{;} - - \DataTypeTok{ssl\_certificate}\NormalTok{ /etc/letsencrypt/live/alumni.example.com/fullchain.pem}\OperatorTok{;} - \DataTypeTok{ssl\_certificate\_key}\NormalTok{ /etc/letsencrypt/live/alumni.example.com/privkey.pem}\OperatorTok{;} - - \DataTypeTok{location}\NormalTok{ / }\OperatorTok{\{} - \DataTypeTok{proxy\_pass}\NormalTok{ http://}\DecValTok{127}\NormalTok{.}\DecValTok{0}\NormalTok{.}\DecValTok{0}\NormalTok{.}\DecValTok{1}\NormalTok{:}\DecValTok{5000}\OperatorTok{;} - \DataTypeTok{proxy\_http\_version} \DecValTok{1}\NormalTok{.}\DecValTok{1}\OperatorTok{;} - \DataTypeTok{proxy\_set\_header}\NormalTok{ Upgrade }\VariableTok{$http\_upgrade}\OperatorTok{;} - \DataTypeTok{proxy\_set\_header}\NormalTok{ Connection keep{-}alive}\OperatorTok{;} - \DataTypeTok{proxy\_set\_header}\NormalTok{ Host }\VariableTok{$host}\OperatorTok{;} - \DataTypeTok{proxy\_cache\_bypass} \VariableTok{$http\_upgrade}\OperatorTok{;} - \OperatorTok{\}} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -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. - -\pandocbounded{\includegraphics[keepaspectratio]{783200d10c9c35d1be650f901b7a01885746de85.pdf}} - -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. - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.3182}} - >{\raggedright\arraybackslash}p{(\linewidth - 2\tabcolsep) * \real{0.6818}}@{}} -\caption{SSH Zugänge in den unterschiedlichen Umgebungen}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Umgebung -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Administrationszugang -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Umgebung -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Administrationszugang -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -Hetzner & Wireguard \\ -Schule & Highport \\ -LiveDesign & IPSEC VPN \\ -\end{longtable} - -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 \texttt{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. - -\subsubsection{Entwicklung mit ASP.NET}\label{entwicklung-mit-asp.net} - -\paragraph[Blazor]{\texorpdfstring{Blazor\footnote{Wikipedia (2024) - (siehe Internet-/Intranetverzeichnis).}}{Blazor}}\label{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: - -\begin{longtable}[]{@{} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2967}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1978}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.1978}} - >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.3077}}@{}} -\caption{Vergleich der Blazor Hosting-Modelle}\tabularnewline -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Hosting-Modell -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Ausführungsort -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Interaktivität -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Kommunikation -\end{minipage} \\ -\midrule\noalign{} -\endfirsthead -\toprule\noalign{} -\begin{minipage}[b]{\linewidth}\raggedright -Hosting-Modell -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Ausführungsort -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Interaktivität -\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright -Kommunikation -\end{minipage} \\ -\midrule\noalign{} -\endhead -\bottomrule\noalign{} -\endlastfoot -\textbf{Static Server} & Server & Keine & HTTP (Initialer Load) \\ -\textbf{Interactive Server} & Server & Hoch (Echtzeit) & SignalR / -WebSockets \\ -\textbf{Interactive WebAssembly} & Client (Browser) & Hoch (Lokal) & -REST API / HTTP \\ -\textbf{Interactive Auto } & Server \& Client (ab zweitem Besuch) & Hoch -(Echtzeit / Lokal) & SignalR / Websockets / RestAPI / HTTP \\ -\textbf{Hybrid} & Native App (WebView) & Hoch (Lokal) & n/a -(Mutterprozess) \\ -\end{longtable} - -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.\footnote{Oqtane Foundation (2024c) (siehe - Internet-/Intranetverzeichnis).} - -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 -\texttt{@}- Zeichen markiert. Hier ist ein Beispiel für einen einfachen -Counter: - -\begin{Shaded} -\begin{Highlighting}[] -\DataTypeTok{\textless{}}\KeywordTok{h1}\DataTypeTok{\textgreater{}}\NormalTok{Counter}\DataTypeTok{\textless{}/}\KeywordTok{h1}\DataTypeTok{\textgreater{}} - -\DataTypeTok{\textless{}}\KeywordTok{p}\DataTypeTok{\textgreater{}}\NormalTok{Count: }\ControlFlowTok{@count}\DataTypeTok{\textless{}/}\KeywordTok{p}\DataTypeTok{\textgreater{}} - -\DataTypeTok{\textless{}}\KeywordTok{button}\OtherTok{ }\ErrorTok{@}\OtherTok{onclick}\OperatorTok{=}\StringTok{"Increment"}\DataTypeTok{\textgreater{}}\NormalTok{Increment}\DataTypeTok{\textless{}/}\KeywordTok{button}\DataTypeTok{\textgreater{}} - -\ControlFlowTok{@code} -\NormalTok{\{} -\NormalTok{ private int count = 0;} - -\NormalTok{ private void Increment()} -\NormalTok{ \{} -\NormalTok{ count++;} -\NormalTok{ \}} -\NormalTok{\}} -\end{Highlighting} -\end{Shaded} - -Mit\texttt{@count} in Zeile 3 wird der Wert der Variablen count in den -\texttt{\textless{}p\textgreater{}} Tag mit eingebaut. Mit -\texttt{@onclick="Increment"} in Zeile 5 wird die onclick Property vom -\texttt{\textless{}button\textgreater{}}Tag auf die Increment Methode im -C\# Code gesetzt. Der \texttt{@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): - -\begin{itemize} -\tightlist -\item - namespace: Gibt den aktuellen Namespace in der Razor Datei an. -\item - inherits: Gibt die Superklasse der generierten C\# Klasse an. -\item - using: Gibt die im C\# Code benutzen/verfügbaren Namespaces an -\item - foreach: Für Wiederholungen im Markup -\item - if: Für Verzweigungen im Markup -\end{itemize} - -\paragraph{Kommunikation zwischen Front- und -Backend}\label{kommunikation-zwischen-front--und-backend} - -~ - -Die Interaktion zwischen Client und Server folgt in Oqtane einem klaren -Architekturmuster, das je nach Render-Modus unterschiedliche -Technologien nutzt. - -\begin{itemize} -\tightlist -\item - \textbf{SignalR (Interactive Server)}: Für Echtzeit-Interaktionen - nutzt Oqtane SignalR. Dabei wird eine persistente WebSocket-Verbindung - (oder Fallbacks wie Long-Polling) aufgebaut. Zustandsänderungen im UI - lösen C\#-Events auf dem Server aus, und das resultierende ``Diff'' - des DOMs wird zurück an den Client gestreamt. -\item - \textbf{REST API (WebAssembly/Shared)}: Bei Modulen, die Daten - asynchron laden (im WebAssembly-Modus), kommuniziert der Client über - einen \texttt{HttpClient} mit dem Controller. -\end{itemize} - -Der folgende Ablauf zeigt die Kommunikation bei einer typischen -Datenabfrage in einem Oqtane-Modul: - -\pandocbounded{\includegraphics[keepaspectratio]{fdabef25f189cc75c2e232304f32645db4899631.pdf}} - -Durch diese Abstraktion bleibt die Geschäftslogik im Backend -(Repository/Controller) gekapselt, während das Frontend lediglich die -Daten präsentiert und Benutzereingaben entgegennimmt. Dies unterstützt -die Testbarkeit, da Repositories unabhängig vom UI getestet werden -können. - -\subsubsection{Dependency Injection}\label{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.\footnote{Fowler, Martin (2004) - (siehe Internet-/Intranetverzeichnis).} 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. - -\paragraph[Dependency Inversion Principle ]{\texorpdfstring{Dependency -Inversion Principle\footnote{Microsoft (2024a) (siehe - Internet-/Intranetverzeichnis).} -\footnote{LogRocket (2024) (siehe Internet-/Intranetverzeichnis).}}{Dependency Inversion Principle }}\label{dependency-inversion-principle-ms_dependency_inversion-logrocket_dependency_inversion} - -~ - -Das Dependency-Inversion-Principle (DIP / auf Deutsch: -Abhängigkeits-Umkehr-Prinzip) ist eines von den fünf \texttt{SOLID} -Prinzipien in der Softwareentwicklung. - -Das DIP unterscheidet zwischen high-level und low-level Modulen. - -\begin{itemize} -\tightlist -\item - Die High-Level-Module beschreiben die Applikations- / Businesslogik, - ohne direkt mit den Low-Level-Modulen zu interagieren, sondern - lediglich auf Abstraktionen.\footnote{OO Design (2024) (siehe - Internet-/Intranetverzeichnis).} -\item - Die Abstraktionen sollen nicht von Implementierungsdetails abhängig - sein, sondern die Low-Level-Implementierung sollen gemäß der - Abstraktionsschicht implementiert werden.\footnote{Ebenda.} -\end{itemize} - -Ausgangslage ist eine Softwarearchitektur im -Direct-Dependency-Graph-Modell. - -\pandocbounded{\includegraphics[keepaspectratio]{e08c4f02a7a60ce024375d5f7f40dd2b284b916f.pdf}} - -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. - -\pandocbounded{\includegraphics[keepaspectratio]{e3614678caacf98b36a36fa9f5451a214d4f21c6.pdf}} - -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. - -\paragraph{Microsoft Dependency Injection -Framework}\label{microsoft-dependency-injection-framework} - -~ - -Dependency Injection ist in .NET genau so wie Konfiguration, -Protokollierung und das Optionsmuster ins Framework -integriert.\footnote{Microsoft (2024b) (siehe - Internet-/Intranetverzeichnis).} - -Alle Dependencies werden in einem \texttt{Service-Container} zur -Verwaltung registriert. .NET hat einen eingebauten -\texttt{Service-Container} (eine Implementierung des -\texttt{IServiceProvider}).\footnote{Ebenda.} - -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.\footnote{Ebenda.} - -Hier ein Beispiel aus der Dokumentation von Microsoft:\footnote{Ebenda.} - -\begin{Shaded} -\begin{Highlighting}[] -\NormalTok{HostApplicationBuilder builder }\OperatorTok{=}\NormalTok{ Host}\OperatorTok{.}\FunctionTok{CreateApplicationBuilder}\OperatorTok{(}\NormalTok{args}\OperatorTok{);} - -\NormalTok{builder}\OperatorTok{.}\FunctionTok{Services}\OperatorTok{.}\FunctionTok{AddHostedService}\OperatorTok{\textless{}}\NormalTok{Worker}\OperatorTok{\textgreater{}();} -\NormalTok{builder}\OperatorTok{.}\FunctionTok{Services}\OperatorTok{.}\FunctionTok{AddSingleton}\OperatorTok{\textless{}}\NormalTok{IMessageWriter}\OperatorTok{,}\NormalTok{ MessageWriter}\OperatorTok{\textgreater{}();} - -\KeywordTok{using}\NormalTok{ IHost host }\OperatorTok{=}\NormalTok{ builder}\OperatorTok{.}\FunctionTok{Build}\OperatorTok{();} - -\NormalTok{host}\OperatorTok{.}\FunctionTok{Run}\OperatorTok{();} - -\KeywordTok{public} \KeywordTok{class}\NormalTok{ MessageWriter }\OperatorTok{:}\NormalTok{ IMessageWriter} -\OperatorTok{\{} - \KeywordTok{public} \DataTypeTok{void} \FunctionTok{Write}\OperatorTok{(}\DataTypeTok{string}\NormalTok{ message}\OperatorTok{)} - \OperatorTok{\{} -\NormalTok{ Console}\OperatorTok{.}\FunctionTok{WriteLine}\OperatorTok{(}\NormalTok{$}\StringTok{"MessageWriter.Write(message: }\SpecialCharTok{\textbackslash{}"}\StringTok{\{message\}}\SpecialCharTok{\textbackslash{}"}\StringTok{)"}\OperatorTok{);} - \OperatorTok{\}} -\OperatorTok{\}} - -\KeywordTok{public} \KeywordTok{interface}\NormalTok{ IMessageWriter} -\OperatorTok{\{} - \DataTypeTok{void} \FunctionTok{Write}\OperatorTok{(}\DataTypeTok{string}\NormalTok{ message}\OperatorTok{);} -\OperatorTok{\}} - -\KeywordTok{public} \KeywordTok{sealed} \KeywordTok{class} \FunctionTok{Worker}\OperatorTok{(}\NormalTok{IMessageWriter messageWriter}\OperatorTok{)} \OperatorTok{:}\NormalTok{ BackgroundService} -\OperatorTok{\{} - \KeywordTok{protected} \KeywordTok{override}\NormalTok{ async Task }\FunctionTok{ExecuteAsync}\OperatorTok{(}\NormalTok{CancellationToken stoppingToken}\OperatorTok{)} - \OperatorTok{\{} - \KeywordTok{while} \OperatorTok{(!}\NormalTok{stoppingToken}\OperatorTok{.}\FunctionTok{IsCancellationRequested}\OperatorTok{)} - \OperatorTok{\{} -\NormalTok{ messageWriter}\OperatorTok{.}\FunctionTok{Write}\OperatorTok{(}\NormalTok{$}\StringTok{"Worker running at: \{DateTimeOffset.Now\}"}\OperatorTok{);} -\NormalTok{ await Task}\OperatorTok{.}\FunctionTok{Delay}\OperatorTok{(}\DecValTok{1}\NormalTok{\_000}\OperatorTok{,}\NormalTok{ stoppingToken}\OperatorTok{);} - \OperatorTok{\}} - \OperatorTok{\}} -\OperatorTok{\}} -\end{Highlighting} -\end{Shaded} - -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 \texttt{Service-Container} -erstellt, danach alle Module registriert (entweder als HostedService, -oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, -Singleton)). - -Mit dem Aufruf von \texttt{builder.Build()} wird intern ein Dependency -Graph erstellt und mit \texttt{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. - -So sieht der Abhängigkeitsgraph bei diesem Beispiel aus. - -\pandocbounded{\includegraphics[keepaspectratio]{f39b4f0675636b8f1bfe34f890466e3db009627c.pdf}} - -\subsubsection{Continuous Integration}\label{sec:continuous-integration} - -Gitea, das Versionskontrollsystem dieser Diplomarbeit, hat einen -Continuous-Integration-System eingebaut. Im Kern ist es baugleich zu den -GitHub-Pipelines. Man kann im \texttt{.gitea/workflow} Ordner -\texttt{.yml} Dateien ablegen, welche dann das Verhalten der Workflows -definieren. - -Man kann definieren auf welcher Änderung im Git Repository die Pipeline -losgetreten wird (Keyword: \texttt{on}) und entweder eigene Kommandos -aufreihen, oder auf bestehende \texttt{actions} zurückgreifen, welche -dann der Reihe nach ausgeführt werden (Keyword: \texttt{jobs}). - -Die meisten Pipelines sind folgendermaßen Aufgebaut: Clone --\textgreater{} Checkout -\textgreater{} Submodule Checkout (optional) --\textgreater{} Dependencies einrichten (zum Beispiel das dotnet SDK) --\textgreater{} Build ausführen. -\textgreater{} Release erstellen und -Artefakte veröffentlichen (z.B. in Registries). Aber man kann auch -andere Dinge tun, z.B. mithilfe von Künstlicher Intelligenz Code und -Dokumentation überprüfen. - -Anwendungen von Gitea Actions bei dieser Diplomarbeit: - -\begin{itemize} -\tightlist -\item - \textbf{APT-Package Repository}: Zum Bauen von Oqtane und allen - Modulen, verpacken in ein .deb Paket und in die Registry pushen. -\item - \textbf{Interfaces Projekt}: Zum Bauen vom Interfaces-Projekt, - verpacken in ein NuGet Paket und in die Registry pushen. Die - Versionierung des NuGet-Pakets erfolgt dabei automatisiert über - Git-Tags, was eine konsistente Verknüpfung zwischen Quellcode-Stand - und Paketversion sicherstellt. -\item - \textbf{ursprünglich: oqtane.framework}: Zum bauen und Verpacken in - einen Docker Container und in die Registry pushen. -\item - \textbf{PM Repository}: Zum automatischen Überprüfen der Dokumente, - unter anderem, mithilfe von KI, wie zum Beispiel Gemini. -\end{itemize} - -Ein Beispiel für eine Konfiguration einer Gitea Action: - -\begin{Shaded} -\begin{Highlighting}[] -\FunctionTok{name}\KeywordTok{:}\AttributeTok{ build{-}debian{-}package} -\FunctionTok{on}\KeywordTok{:} -\AttributeTok{ }\FunctionTok{push}\KeywordTok{:} -\AttributeTok{ }\FunctionTok{tags}\KeywordTok{:} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\StringTok{"*"} - -\FunctionTok{jobs}\KeywordTok{:} -\AttributeTok{ }\FunctionTok{build}\KeywordTok{:} -\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ Build the debian package} -\AttributeTok{ }\FunctionTok{runs{-}on}\KeywordTok{:}\AttributeTok{ ubuntu{-}latest} -\AttributeTok{ }\FunctionTok{steps}\KeywordTok{:} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Git clone"} -\AttributeTok{ }\FunctionTok{run}\KeywordTok{:}\AttributeTok{ git clone $\{\{ gitea.server\_url \}\}/$\{\{ gitea.repository \}\}.git .} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Git checkout"} -\AttributeTok{ }\FunctionTok{run}\KeywordTok{:}\AttributeTok{ git checkout "$\{\{ gitea.sha \}\}"} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Submodules auschecken"} -\AttributeTok{ }\FunctionTok{run}\KeywordTok{:}\AttributeTok{ git submodule update {-}{-}init} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Dotnet SDK einrichten"} -\AttributeTok{ }\FunctionTok{uses}\KeywordTok{:}\AttributeTok{ actions/setup{-}dotnet@v4} -\AttributeTok{ }\FunctionTok{with}\KeywordTok{:} -\AttributeTok{ }\FunctionTok{dotnet{-}version}\KeywordTok{:}\AttributeTok{ }\StringTok{"10.0.x"} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Configure nuget source"} -\AttributeTok{ }\FunctionTok{run}\KeywordTok{:}\AttributeTok{ dotnet nuget add source {-}{-}name DAV {-}{-}username kocoder {-}{-}password $\{\{ secrets.REGISTRY\_TOKEN\_KOCODER \}\} https://git.kocoder.xyz/api/packages/Diplomarbeit{-}Absolventenverein/nuget/index.json {-}{-}store{-}password{-}in{-}clear{-}text} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Build .deb"} -\AttributeTok{ }\FunctionTok{run}\KeywordTok{:}\AttributeTok{ ./run{-}build.sh "$\{\{ gitea.ref\_name \}\}" "./alumnihub" "Release"} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Upload .deb"} -\AttributeTok{ }\FunctionTok{run}\KeywordTok{:}\AttributeTok{ curl {-}{-}user kocoder:$\{\{ secrets.REGISTRY\_TOKEN\_KOCODER \}\} {-}{-}upload{-}file ./alumnihub.deb https://git.kocoder.xyz/api/packages/Diplomarbeit{-}Absolventenverein/debian/pool/trixie/main/upload} -\AttributeTok{ }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{name}\KeywordTok{:}\AttributeTok{ }\StringTok{"Create release"} -\AttributeTok{ }\FunctionTok{uses}\KeywordTok{:}\AttributeTok{ akkuman/gitea{-}release{-}action@v1} -\AttributeTok{ }\FunctionTok{with}\KeywordTok{:} -\FunctionTok{ files}\KeywordTok{: }\CharTok{|{-}} -\NormalTok{ ./alumnihub.deb} -\NormalTok{ ./alumnihub/opt/alumnihub/Packages/*.nupkg} -\end{Highlighting} -\end{Shaded} - -Die Konfiguration führt teilweise vorgefertigte Actions aus, wie zum -Beispiel das Einrichten des .NET SDKs oder das Erstellen eines Releases. -Aber es werden auch eigene Skripte ausgeführt, wie zum Beispiel das -Bauen des .deb Pakets. Dieses ist im Repository unter -\texttt{./run-build.sh} zu finden. Dieses Skript ist für die -Automatisierung des Build-Prozesses zuständig und kümmert sich um das -Kompilieren der Anwendung, das Erstellen des Debian-Pakets und das -Hochladen in die Registry. Abgelegt ist es im APT-Package Repository -unter \texttt{./gitea/workflows}. - -\subsubsection{Debian Paket}\label{debian-paket} - -Um die Anwendung und ihre Abhängigkeiten konsistent auf dem Zielserver -(Linux/Hetzner) zu installieren, wurde ein eigenes Debian-Paket -(\texttt{.deb}) erstellt. Das Debian-Paketformat bietet den Vorteil, -dass es Metadaten über Versionen, Abhängigkeiten und -Installationsskripte (Maintainer Scripts) enthält. - -\paragraph{Struktur eines -Debian-Pakets}\label{struktur-eines-debian-pakets} - -~ - -Ein \texttt{.deb}-Paket ist im Grunde ein \texttt{ar}-Archiv, das drei -wesentliche Bestandteile enthält: - -\begin{itemize} -\tightlist -\item - \textbf{debian-binary}: Eine Textdatei mit der Versionsnummer des - Paketformats. -\item - \textbf{control.tar.gz}: Enthält die Metadaten - (\texttt{control}-Datei) und Skripte, die vor oder nach der - Installation ausgeführt werden (z. B. \texttt{postinst} zum Starten - des Systemd-Services). -\item - \textbf{data.tar.gz}: Enthält die eigentlichen Anwendungsdateien (die - kompilierten Oqtane-DLLs und statischen Assets), die in das - Zielverzeichnis (z. B. \texttt{/opt/alumnihub}) entpackt werden. -\end{itemize} - -\paragraph{Automatisierung im -Build-Prozess}\label{automatisierung-im-build-prozess} - -~ - -Der Bau des Pakets erfolgt vollautomatisch in der Gitea-CI-Pipeline. -Dabei werden die folgenden Schritte durchlaufen: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - \textbf{Dotnet Publish}: Kompilieren der Anwendung für Linux-x64. -\item - \textbf{Paketierung}: Erstellen der Verzeichnisstruktur gemäß dem FHS - (Filesystem Hierarchy Standard). -\item - \textbf{dpkg-deb}: Aufruf des Standard-Werkzeugs - \texttt{dpkg-deb\ -\/-build}, um das fertige Paket zu schnüren. Dabei - wird auch hier ein Git-Tag als Grundlage für die Paketversion - verwendet. -\item - \textbf{Publish}: Das Paket wird in die Gitea Package Registry - hochgeladen und steht dort für das Deployment via \texttt{apt} zur - Verfügung. -\end{enumerate} - -Durch diesen Prozess wird sichergestellt, dass jede Version der Software -eindeutig identifizierbar und einfach rückrollbar (Rollback) ist. - -\subsection{Projektmanagement \& Tools}\label{projektmanagement-tools} - -\subsubsection{Scrum}\label{scrum} - -Zum verwalten des Projektes haben wir uns an den Grundprinzipien von -Scrum orientiert, um flexibel auf Änderungen reagieren zu können. Die -Arbeit wurde in 14-tägige Sprints unterteilt. - -\begin{itemize} -\tightlist -\item - \textbf{Sprint Planning}: Zu Beginn jedes Sprints wurden die Aufgaben - aus dem Product Backlog in das Sprint Backlog übernommen. -\item - \textbf{Dailies/Weekly}: Wir hielten wöchentliche Treffen ab, um den - Fortschritt zu synchronisieren und Blocker zu identifizieren. -\item - \textbf{Sprint Review}: Am Ende eines Sprints wurden die funktionalen - Module präsentiert und der Stand der Diplomarbeit mit dem Betreuer - besprochen. -\item - \textbf{Sprint Retrospective}: Am Ende eines Sprints wurde der Sprint - reflektiert und es wurden Maßnahmen zur Verbesserung des Prozesses - abgeleitet. -\item - \textbf{Definition of Done}: Zu Beginn der Diplomarbeit haben wir uns - auf eine Definition of Done geeinigt, welche im Laufe der Diplomarbeit - immer wieder angepasst wurde. -\end{itemize} - -Mehr zum Projektmanagementprozess steht im allgemeinen Teil -\hyperref[projektmanagement-mit-scrum]{Projektmanagement mit Scrum}. - -\subsubsection{Projektmanagement-Tools (YouTrack \& -Gitea)}\label{projektmanagement-tools-youtrack-gitea} - -Für die initiale Planung und die ersten Sprints wurde YouTrack von -JetBrains eingesetzt. Im Vergleich zu einfachen To-Do-Listen bietet -YouTrack mächtige Features für Softwareteams wie agile Boards, Time -Tracking und Gantt-Diagramme. - -Im weiteren Verlauf der Diplomarbeit sind wir jedoch auf die -integrierten Projektmanagement-Funktionen von Gitea umgestiegen. -\hyperref[issues]{Siehe Issues}. Dieser Wechsel erfolgte, um den -gesamten Entwicklungsprozess --- von der Aufgabenverwaltung -(Issues/Boards) über die Versionskontrolle bis hin zur CI/CD-Pipeline -(Gitea Actions) --- an einem zentralen Ort zu bündeln. Dies verbesserte -die Übersichtlichkeit und reduzierte den administrativen Aufwand für die -Pflege unterschiedlicher Systeme. - -\subsubsection{Git}\label{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: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - Working Directory: Der aktuelle Zustand der Dateien auf der - Festplatte. -\item - Staging Area (Index): Eine Zwischenebene, in der Änderungen für den - nächsten Snapshot vorgemerkt werden. -\item - Repository (HEAD): Der dauerhafte Speicher der versionierten Stände - (Commits). -\end{enumerate} - -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 \texttt{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. - -\subsubsection{Gitea}\label{gitea-1} - -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.\footnote{Gitea - (2024a) (siehe Internet-/Intranetverzeichnis).} - -\paragraph{Repositories}\label{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.\footnote{Ebenda.} - -\paragraph{Issues}\label{issues} - -~ - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/GiteaIssues-TaskBoard.png} -\caption{Gitea Issues Board} -\end{figure} - -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.\footnote{Ebenda.} \footnote{Gitea (2024b) - (siehe Internet-/Intranetverzeichnis).} - -\paragraph{Pull Requests}\label{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.\footnote{Gitea (2024a) (siehe Internet-/Intranetverzeichnis).} -\footnote{Gitea (2024c) (siehe Internet-/Intranetverzeichnis).} - -\paragraph{Actions}\label{actions} - -~ - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/GiteaActions-Overview.png} -\caption{Gitea Actions} -\end{figure} - -Gitea Actions wurden eingesetzt, um CI/CD-Pipelines (Continuous -Integration / Continuous Deployment) zu realisieren. Bei jedem Push oder -Pull Request wurden automatisierte Skripte ausgeführt, die das Projekt -bauten. Dies reduzierte manuelle Fehlerquellen erheblich. Außerdem -konnten wir mithilfe von CI/CD den Release Prozess einmalig festlegen -und automatisieren, ohne bei jedem Update manuell den selben Prozess -wiederholt durchgehen zu müssen. Das APT-Package Projekt enthält die -CI/CD Konfiguration für das bauen von Oqtane, der Module und Themes, -sowie das verpacken in ein APT Paket und dem veröffentlichen aller -Pakete als eingenes Gitea Release. {[}Siehe Abschnitt -\ref{sec:continuous-integration}{]}\footnote{Gitea (2024a) (siehe - Internet-/Intranetverzeichnis).} \footnote{Gitea (2024d) (siehe - Internet-/Intranetverzeichnis).} - -\paragraph{Releases}\label{releases} - -~ - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/GiteaActions-Releases.png} -\caption{Gitea Releases} -\end{figure} - -Ü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.\footnote{Gitea (2024a) - (siehe Internet-/Intranetverzeichnis).} - -\paragraph{Package Repositories}\label{package-repositories} - -~ - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/GiteaPackageRepository.png} -\caption{Gitea Packages} -\end{figure} - -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.\footnote{Ebenda.} \footnote{Gitea (2024e) (siehe - Internet-/Intranetverzeichnis).} - -\subsubsection{Kommunikation}\label{kommunikation} - -\subsection{Module}\label{module-2} - -\subsubsection{Admin Modules}\label{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. - -\paragraph{Mass Mailing}\label{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. - -\subparagraph{Integration von Brevo}\label{integration-von-brevo} - -\hfill\break - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/Brevo.png} -\caption{Brevo Integration} -\end{figure} - -Für den tatsächlichen Versand der E-Mails nutzen wir den Cloud-Dienst -Brevo. Dieser bietet eine zuverlässige Zustellung (hohe Reputation der -Mailserver), sowie die Möglichkeit die Zustell-, Öffnungs- und -Klickraten zu beobachten. Das Limit von 300 E-Mails pro Tag stellt uns -jedoch in der kostenlosen Variante vor eine Herausforderung. - -\texttt{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 \texttt{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. - -\paragraph{Token Lifetime}\label{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 -\texttt{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 -\texttt{DataProtectionTokenProviderOptions} explizit konfiguriert werden -müssen.\footnote{Lock, Andrew (2024) (siehe - Internet-/Intranetverzeichnis).} Der ASP.NET Core -\texttt{UserManager}, welcher das generieren der Tokens übernimmt, -verwendet einen \texttt{DataProtectorTokenProvider} und dieser wiederum -kann mithilfe der \texttt{DataProtectionTokenProviderOptions} -konfiguriert werden. - -Es gibt 2 Möglichkeiten, wie man dieses Problem Lösen kann: - -\begin{itemize} -\tightlist -\item - \texttt{der\ Workaround}: Ein eigenes Modul, welches in seiner - \texttt{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 - \texttt{race-condition} auftreten.\footnote{Maryland, University of - (2024) (siehe Internet-/Intranetverzeichnis).} Darüber hinaus - besteht kein gleichzeitiger Zugriff auf die appsettings.json und den - IServiceProvider, in dem die Konfiguration gesetzt werden muss. - =\textgreater{} 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. -\item - \texttt{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 - \texttt{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 \texttt{race-condition} verhindert werden kann.\footnote{Ebenda.} - 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. -\end{itemize} - -\texttt{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 -\texttt{die\ saubere\ Lösung} implementieren. - -\paragraph{Reporting System}\label{reporting-system} - -~ - -Eine weitere Anforderung der Diplomarbeit war es Einträge in Modulen wie -der \texttt{Hall\ of\ Fame}, dem \texttt{Schwarzen\ Brett} und dem -Premium Bereich (\texttt{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: - -\pandocbounded{\includegraphics[keepaspectratio]{896637356e9d54db4c95ce116530ff0191d7fcce.pdf}} - -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: -\texttt{Single\ responsibility}. Die Module sind jetzt nicht mehr für -das Reporting selber verantwortlich, sondern müssen nur das Reportings -System einbinden. - -Darüber hinaus erfüllt dieses Design das \textbf{Open/Closed Principle}: -Das Reporting-System ist offen für Erweiterungen (neue Module können -einfach andocken), aber geschlossen für Modifikationen (der Kern des -Reporting-Systems muss nicht für jedes neue Modul geändert werden). - -Damit DI funktioniert muss für den DI Consumer -(\texttt{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 -\texttt{Interfaces}, wird per Gitea Actions automatisch in ein -NuGet-Paket gebaut und in der \texttt{Gitea\ Actions\ NuGet\ Registry} -veröffentlicht. Die Versionierung folgt dabei strikt den Git-Tags im -Repository, was eine saubere Release-History ermöglicht. Dieses -NuGet-Paket wird dann in jedem notwendigen Modul als Dependency -hinzugefügt und damit kann man Modulübergreifend auf die Services und -das \texttt{IReportingComponent} zugreifen. - -Die Implementierung des \texttt{IReportingComponents} stellt nur eine -Property (\texttt{ReportType}, welche den TypeName der Razor Komponente -zurückliefert, damit \texttt{DynamicComponent} sie laden kann) und eine -Methode (\texttt{ConstructParameterList}, welche das Parameter -Dictionary erstellt. Nur zwecks Typensicherheit eingefügt) bereit. Mit -dem \texttt{DynamicComponent} von Razor ist es möglich, per C\# Code -unterschiedliche Komponenten zu rendern und damit auch die per DI -injizierte Klasse. - -\begin{Shaded} -\begin{Highlighting}[] -\ControlFlowTok{@inject}\NormalTok{ IReportUI ReportUI} - -\DataTypeTok{\textless{}}\KeywordTok{DynamicComponent} -\OtherTok{ Type}\OperatorTok{=}\StringTok{"@ReportUI.ReportType"} -\OtherTok{ Parameters}\OperatorTok{=}\StringTok{"@ReportUI.ConstructParameterList(\_item, RenderModeBoundary)"} -\DataTypeTok{/\textgreater{}} - -\ControlFlowTok{@code}\NormalTok{ \{} -\NormalTok{ private IReportable \_item;} -\NormalTok{\}} -\end{Highlighting} -\end{Shaded} - -Die Bereitstellung des Moduls geschieht im \texttt{AdminModules} Modul. - -\subsubsection{Event Registration}\label{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. - -\paragraph{Backend und Datenhaltung}\label{backend-und-datenhaltung} - -~ - -Die serverseitige Implementierung basiert auf dem Repository-Pattern des -Oqtane-Frameworks. Hierbei kommen zwei zentrale Repositories zum -Einsatz: - -Das \texttt{EventRepository} verwaltet die Metadaten der Veranstaltungen -wie Name, Beschreibung, Datum und Ort. Das \texttt{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 \texttt{EventRegistrationController}, der -sicherstellt, dass nur autorisierte Benutzer Änderungen vornehmen oder -detaillierte Statistiken einsehen können. - -\subparagraph{Entity Relationship -Diagram}\label{entity-relationship-diagram} - -\hfill\break - -\begin{figure} -\centering -\includegraphics[width=0.5\linewidth,height=\textheight,keepaspectratio]{erd-event-registration.pdf} -\caption{ER Diagramm des Event Registration Moduls} -\end{figure} - -\paragraph{Statistik und -Visualisierung}\label{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 JS-Interop-Layer ist zwar -standardmäßig in Oqtane-Modulen vorgesehen, wurde jedoch in diesem Modul -zum ersten Mal angepasst und produktiv eingesetzt. Der Ablauf der -grafischen Darstellung gestaltet sich wie folgt: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - Datenaufbereitung: In der Edit-Komponente werden alle Rückmeldungen zu - einem Event geladen und nach ihrem Typ, oder beliebigen anderen - Merkmalen aggregiert. -\item - JS-Interop: Über die \texttt{CreateChart}-Methode der Interop-Klasse - wird die JavaScript-Funktion \texttt{createChart} in der - \texttt{Module.js} aufgerufen. Dabei werden die aggregierten Daten, - Beschriftungen und Konfigurationsoptionen übergeben. -\item - 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. -\end{enumerate} - -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. - -\begin{figure} -\centering -\includegraphics[width=0.4\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/EventRegistration-PieChart.png} -\caption{EventRegistration Pie Chart} -\end{figure} - -\subsubsection{Schwarzes Brett}\label{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. - -\paragraph{Struktur und Anzeige}\label{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. - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/BlackBoard-Overview.png} -\caption{Übersicht der Einträge auf dem Schwarzen Brett} -\end{figure} - -Bilderunterstützung: Das Modul nutzt die Oqtane-interne Dateiverwaltung. -Wenn ein Bild für einen Eintrag hochgeladen wurde, wird dieses über -einen Image-Proxy skaliert und als Vorschaubild angezeigt. Fehlt ein -Bild, wird ein konsistenter Platzhalter verwendet, um das visuelle -Gleichgewicht der Grid-Ansicht zu wahren. - -Detailansicht: Die Details-Komponente bietet eine fokussierte Ansicht -des Eintrags mit vollständiger HTML-Beschreibung. Für die Eingabe und -Formatierung der Texte wird auf die von Oqtane standardmäßig -bereitgestellten Rich-Text-Editoren zurückgegriffen, was eine -konsistente Nutzerführung im gesamten CMS gewährleistet. Ergänzt wird -dies durch Metadaten wie Erstellungsdatum und Autor. - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/BlackBoard-Details.png} -\caption{Detailansicht eines Eintrags auf dem Schwarzen Brett} -\end{figure} - -\paragraph{Automatisierter -E-Mail-Digest}\label{automatisierter-e-mail-digest} - -~ - -Um die Mitglieder regelmäßig über neue Inhalte zu informieren, wurde ein -automatisierter \texttt{Cronjob} implementiert. Dieser Job läuft im -Hintergrund des Oqtane-Frameworks und führt folgende Schritte aus: - -\begin{itemize} -\tightlist -\item - Filterung: Der Job identifiziert alle Einträge, die seit dem letzten - Versand erstellt wurden. -\item - Zielgruppenselektion: Es werden alle Benutzer identifiziert, die der - Rolle ``Absolventen'' angehören. -\item - Zusammenstellung: Für jeden dieser Benutzer wird eine personalisierte - Email-Notification generiert, welche eine Zusammenfassung der neuen - Einträge enthält. -\item - Versand: Die generierten Notifications werden in die Warteschlange der - Notification-Infrastruktur eingereiht und sukzessive versendet. - Integration des Reporting-Systems -\end{itemize} - -\paragraph{Reporting System}\label{reporting-system-1} - -~ - -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. - -\begin{figure} -\centering -\includegraphics[width=0.7\linewidth,height=\textheight,keepaspectratio]{./images/05-Konstantin/ReportSystem-HandleReport.png} -\caption{Reporting System} -\end{figure} - -\paragraph{Technischer Hintergrund}\label{technischer-hintergrund} - -~ - -Auf der Serverseite folgt das Modul dem etablierten Muster mit einem -\texttt{BlackBoardRepository} für den effizienten Datenbankzugriff und -einem \texttt{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. - -\subsection{Learnings}\label{learnings-2} - -\subsubsection{Produktion != Staging}\label{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 -\hyperref[arbeitszeiteinschuxe4tzung-zeitverzug]{Zeitverzug} gekommen. -Hätte ich mich vor dem Start der Diplomarbeit mit dem Deployment von -Oqtane auseinander gesetzt, dann wäre das in -\hyperref[fehlende-dokumentation]{Fehlende Dokumentation} beschriebene -Problem früher aufgekommen und der Zeitverzug wäre nicht so groß, oder -noch ganz vermeidbar gewesen. - -\subsubsection{Teamleitung (Motivation / -Downsizing)}\label{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. - -\subsubsection{Arbeitszeiteinschätzung -(Zeitverzug)}\label{arbeitszeiteinschuxe4tzung-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: - -\paragraph{Fehlende Dokumentation}\label{fehlende-dokumentation} - -~ - -\begin{itemize} -\tightlist -\item - \texttt{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. -\item - \texttt{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. -\item - \texttt{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?'' =\textgreater{} - 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. -\end{itemize} - -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. - -\begin{quote} -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. -\end{quote} - -\texttt{90\%\ fertig,\ oder\ fertig?}: Es gibt einige ``Regeln'', wie: -das \texttt{Paretoprinzip}, \texttt{Hofstadter’s\ Law} und die -\texttt{90-90\ Regel}. Letztere wurde im Jahr 1985 von Jon Bentley in -einer Kolumne ``Programming pearls'' veröffentlicht. Ausgeschrieben -lautet sie: - -\begin{quote} -{[}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.\footnote{Bentley, Jon (1985).} Diese Diplomarbeit liefert weitere -Evidenz, dass diese Faustregel stimmt. -\end{quote} - -\subsubsection{Sprints und Meetings (in Zukunft ja -asynchron)}\label{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: - -\begin{itemize} -\tightlist -\item - 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. -\item - 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. -\item - Ineffizienz: Lange Präsenz-Meetings blockierten wertvolle - Entwicklungszeit, ohne die technische Qualität zu steigern. -\end{itemize} - -Lösungsansatz: Meetings und Besprechungen asynchron zueinander setzen. - -\begin{itemize} -\tightlist -\item - 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) -\item - 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 - \texttt{Definition\ of\ Done} festgelegt worden. -\item - 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 \hyperref[continuous-integration]{Gitea Actions} Pipeline) am - Tag der Besprechung zu vermeiden. -\end{itemize} - -\pagebreak - -\cleardoublepage - -\section{Tabellenverzeichnis}\label{tabellenverzeichnis} - -\listoftables - -\cleardoublepage - -\section{Abbildungsverzeichnis}\label{abbildungsverzeichnis} - -\listoffigures - -\cleardoublepage - -\section{Quellenverzeichnis}\label{quellenverzeichnis} - -\phantomsection\label{refs} -\begin{CSLReferences}{1}{1} -\bibitem[\citeproctext]{ref-bentley1985programming} -\textbf{Bentley, Jon (\textbf{1985}):} Programming pearls\emph{ In: -Communications of the ACM}, Band 28, Ausgabe 9, 1985896--901, DOI: -\href{https://doi.org/10.1145/4284.315122}{10.1145/4284.315122}. - -\bibitem[\citeproctext]{ref-bootstrap} -\textbf{Bootstrap (\textbf{2026}):} Bootstrap Framework, 2026, abgerufen -am 17.03.2026, \url{https://getbootstrap.com/}. - -\bibitem[\citeproctext]{ref-bsi_grundschutz} -\textbf{BSI (\textbf{2023}):} IT-Grundschutz-Kompendium -- CON.3: -Datensicherungskonzept, 2023, abgerufen am 19.03.2026, -\url{https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Grundschutz/Kompendium/IT_Grundschutz_Kompendium_Edition2023.pdf}. - -\bibitem[\citeproctext]{ref-bsi_datensicherung} -\textbf{Bundesamt für Sicherheit in der Informationstechnik (BSI) -(\textbf{2024}):} Datensicherung und Datenverlust, 2024, abgerufen am -19.03.2026, -\url{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}. - -\bibitem[\citeproctext]{ref-ris} -\textbf{Bundeskanzleramt Österreich (\textbf{2024}):} -Rechtsinformationssystem des Bundes (RIS), 2024, abgerufen am -19.03.2026, \url{https://www.ris.bka.gv.at/}. - -\bibitem[\citeproctext]{ref-dsb} -\textbf{Datenschutzbehörde (\textbf{2024}):} Österreichische -Datenschutzbehörde (DSB), 2024, abgerufen am 19.03.2026, -\url{https://dsb.gv.at/}. - -\bibitem[\citeproctext]{ref-dsgvo} -\textbf{Europäische Union (\textbf{2016}):} Datenschutz-Grundverordnung -(DSGVO), 2016, abgerufen am 19.03.2026, -\url{https://eur-lex.europa.eu/eli/reg/2016/679/}. - -\bibitem[\citeproctext]{ref-fowler_dependency_injection} -\textbf{Fowler, Martin (\textbf{2004}):} Inversion of Control Containers -and the Dependency Injection pattern, 2004, abgerufen am 19.03.2026, -\url{https://martinfowler.com/articles/injection.html}. - -\bibitem[\citeproctext]{ref-gitea_docs} -\textbf{Gitea (\textbf{2024a}):} Gitea Documentation, 2024, abgerufen am -19.03.2026, \url{https://docs.gitea.com/}. - -\bibitem[\citeproctext]{ref-gitea_issue_tracker} -\textbf{Gitea (\textbf{2024b}):} Gitea Issue Tracker Comparison, 2024, -abgerufen am 19.03.2026, -\url{https://docs.gitea.com/installation/comparison\#issue-tracker}. - -\bibitem[\citeproctext]{ref-gitea_pull_requests} -\textbf{Gitea (\textbf{2024c}):} Gitea Pull Requests, 2024, abgerufen am -19.03.2026, \url{https://docs.gitea.com/usage/pull-request}. - -\bibitem[\citeproctext]{ref-gitea_actions} -\textbf{Gitea (\textbf{2024d}):} Gitea Actions Overview, 2024, abgerufen -am 19.03.2026, \url{https://docs.gitea.com/usage/actions/overview}. - -\bibitem[\citeproctext]{ref-gitea_packages} -\textbf{Gitea (\textbf{2024e}):} Gitea Packages Overview, 2024, -abgerufen am 19.03.2026, -\url{https://docs.gitea.com/usage/packages/overview}. - -\bibitem[\citeproctext]{ref-gitea_about} -\textbf{Gitea (\textbf{2026}):} Gitea -- Open Source Git Service, 2026, -abgerufen am 17.03.2026, \url{https://about.gitea.com/}. - -\bibitem[\citeproctext]{ref-rfc6749} -\textbf{IETF (\textbf{2012}):} IETF RFC 6749 -- The OAuth 2.0 -Authorization Framework, 2012, abgerufen am 19.03.2026, -\url{https://datatracker.ietf.org/doc/html/rfc6749}. - -\bibitem[\citeproctext]{ref-jetbrains_rider} -\textbf{JetBrains (\textbf{2026}):} JetBrains Rider, 2026, abgerufen am -17.03.2026, \url{https://www.jetbrains.com/rider/}. - -\bibitem[\citeproctext]{ref-livedesign} -\textbf{LiveDesign (\textbf{2026}):} LiveDesign -- Hosting, Design \& -Branding, 2026, abgerufen am 17.03.2026, \url{https://livedesign.at/}. - -\bibitem[\citeproctext]{ref-andrewlock_token_lifetime} -\textbf{Lock, Andrew (\textbf{2024}):} Implementing custom token -providers for passwordless authentication in ASP.NET Core Identity, -2024, abgerufen am 19.03.2026, -\url{https://andrewlock.net/implementing-custom-token-providers-for-passwordless-authentication-in-asp-net-core-identity/\#changing-the-default-token-lifetime}. - -\bibitem[\citeproctext]{ref-logrocket_dependency_inversion} -\textbf{LogRocket (\textbf{2024}):} Dependency Inversion Principle, -2024, abgerufen am 19.03.2026, -\url{https://blog.logrocket.com/dependency-inversion-principle/}. - -\bibitem[\citeproctext]{ref-race_conditions_pdf} -\textbf{Maryland, University of (\textbf{2024}):} Race Conditions, 2024, -abgerufen am 19.03.2026, -\url{https://www.cs.umd.edu/projects/syschat/raceConditions.pdf}. - -\bibitem[\citeproctext]{ref-ms_dependency_inversion} -\textbf{Microsoft (\textbf{2024a}):} Dependency Inversion, 2024, -abgerufen am 19.03.2026, -\url{https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/architectural-principles\#dependency-inversion}. - -\bibitem[\citeproctext]{ref-ms_di_overview} -\textbf{Microsoft (\textbf{2024b}):} Dependency Injection Overview, -2024, abgerufen am 19.03.2026, -\url{https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection/overview}. - -\bibitem[\citeproctext]{ref-aspnet_core_docs} -\textbf{Microsoft (\textbf{2026a}):} ASP.NET Core Documentation, 2026, -abgerufen am 17.03.2026, -\url{https://learn.microsoft.com/en-us/aspnet/core/}. - -\bibitem[\citeproctext]{ref-blazor_docs} -\textbf{Microsoft (\textbf{2026b}):} Blazor Documentation, 2026, -abgerufen am 17.03.2026, -\url{https://learn.microsoft.com/en-us/aspnet/core/blazor/}. - -\bibitem[\citeproctext]{ref-ef_core_migrations} -\textbf{Microsoft (\textbf{2026c}):} Entity Framework Core -- -Migrations, 2026, abgerufen am 17.03.2026, -\url{https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/}. - -\bibitem[\citeproctext]{ref-linkedin_auth_flow} -\textbf{Microsoft (\textbf{2026d}):} LinkedIn Developer Documentation -- -Authorization Code Flow, 2026, abgerufen am 19.03.2026, -\url{https://learn.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow}. - -\bibitem[\citeproctext]{ref-oodesign_dependency_inversion} -\textbf{OO Design (\textbf{2024}):} Dependency Inversion Principle, -2024, abgerufen am 19.03.2026, -\url{https://www.oodesign.com/dependency-inversion-principle}. - -\bibitem[\citeproctext]{ref-oqtane_about} -\textbf{Oqtane Foundation (\textbf{2024a}):} About Oqtane, 2024, -abgerufen am 19.03.2026, \url{https://www.oqtane.org/\#about}. - -\bibitem[\citeproctext]{ref-oqtane_docs_extensions} -\textbf{Oqtane Foundation (\textbf{2024b}):} Oqtane Extensions, 2024, -abgerufen am 19.03.2026, -\url{https://docs.oqtane.org/dev/extensions/index.html}. - -\bibitem[\citeproctext]{ref-oqtane_docs_rendermodes} -\textbf{Oqtane Foundation (\textbf{2024c}):} Oqtane Render Modes, 2024, -abgerufen am 19.03.2026, -\url{https://docs.oqtane.org/guides/concepts/render-modes/index.html}. - -\bibitem[\citeproctext]{ref-oqtane_framework_site} -\textbf{Oqtane Foundation (\textbf{2026a}):} Oqtane Framework, 2026, -abgerufen am 17.03.2026, \url{https://www.oqtane.org/}. - -\bibitem[\citeproctext]{ref-oqtane_docs_dev} -\textbf{Oqtane Foundation (\textbf{2026b}):} Oqtane Developer -Documentation, 2026, abgerufen am 17.03.2026, -\url{https://docs.oqtane.org/}. - -\bibitem[\citeproctext]{ref-questpdf} -\textbf{QuestPDF (\textbf{2026}):} QuestPDF Open Source Library, 2026, -abgerufen am 17.03.2026, \url{https://www.questpdf.com/}. - -\bibitem[\citeproctext]{ref-wikipedia_blazor} -\textbf{Wikipedia (\textbf{2024}):} Blazor, 2024, abgerufen am -19.03.2026, \url{https://en.wikipedia.org/wiki/Blazor}. - -\end{CSLReferences} - -\end{document} diff --git a/test.md b/test.md deleted file mode 100644 index fe9a6bf..0000000 --- a/test.md +++ /dev/null @@ -1 +0,0 @@ -![Test Image](./images/05-Konstantin/EventRegistration-PieChart.png){ width=40% fig-pos=H } From cda4491ac0725cafce91da5d7a3a9e4781236a57 Mon Sep 17 00:00:00 2001 From: KoCoder Date: Mon, 23 Mar 2026 08:53:17 +0100 Subject: [PATCH 2/2] Adam: Move to mermaid --- ...uch-individueller-teil-Adam-Gaiswinkler.md | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/03-Diplomarbeitsbuch-individueller-teil-Adam-Gaiswinkler.md b/03-Diplomarbeitsbuch-individueller-teil-Adam-Gaiswinkler.md index 1f47baa..47a1d5a 100644 --- a/03-Diplomarbeitsbuch-individueller-teil-Adam-Gaiswinkler.md +++ b/03-Diplomarbeitsbuch-individueller-teil-Adam-Gaiswinkler.md @@ -119,7 +119,28 @@ foreach (var item in PageState.Pages Durch diesen Ansatz werden ausschließlich die für Benutzer relevanten Inhaltsseiten in der Navigation angezeigt. Gleichzeitig bleibt die Navigation vollständig dynamisch: Werden im CMS neue Seiten angelegt und als Navigationsseiten markiert, erscheinen diese automatisch im Menü, ohne dass eine Anpassung am Theme-Code notwendig ist. -![Filterlogik der Oqtane-Navigation] (./images/06-Adam/navigationsfilter_v2.svg) + + +``` {.mermaid width=75%} +graph TD + %%| filename: navigationsfilter_v2 + %%| fig-cap: Filterlogik der Oqtane-Navigation (Theme.razor) + + Start[PageState.Pages
Alle CMS-Seiten ~12 Seiten] --> Filter1[Filter 1: ParentId == null
Nur Root-Seiten] + Filter1 -- Unterseiten --> Rejected1[Aussortiert] + Filter1 --> Filter2[Filter 2: hiddenNames
Systemseiten ausblenden] + Filter2 -- "Login, Register, Admin, Privacy, ..." --> Rejected2[Aussortiert] + Filter2 --> Result[Sichtbare Navigation
~3 Inhaltsseiten im Menü] + Result -.-> Note[Neue Seiten im CMS erscheinen automatisch im Menü – kein Code nötig] + + style Start fill:#444441,stroke:#B4B2A9,color:#D3D1C7 + style Filter1 fill:#3C3489,stroke:#AFA9EC,color:#CECBE6 + style Filter2 fill:#3C3489,stroke:#AFA9EC,color:#CECBE6 + style Rejected1 fill:#791F1F,stroke:#F09595,color:#F7C1C1 + style Rejected2 fill:#791F1F,stroke:#F09595,color:#F7C1C1 + style Result fill:#085041,stroke:#5DCAA5,color:#9FE1CF + style Note fill:none,stroke:#B4B2A9,stroke-dasharray: 5 5,color:#B4B2A9 +``` Dies reduziert den Wartungsaufwand erheblich und stellt sicher, dass die Navigation stets dem aktuellen Stand der Plattform entspricht. @@ -245,7 +266,33 @@ Am unteren Rand des Formulars befinden sich zwei Speicheroptionen: „Als Entwur Der folgende Lebenszyklus zeigt die möglichen Zustände eines Eintrags und die Übergänge zwischen ihnen: -![Lebenszyklus eines Hall-of-Fame-Eintrags] (./images/06-Adam/hall_of_fame_lebenszyklus_v4.svg) + + +``` {.mermaid width=75%} +graph TD + %%| filename: hall_of_fame_lebenszyklus_v4 + %%| fig-cap: Lebenszyklus eines Hall-of-Fame-Eintrags + + Start([Benutzer eingeloggt]) --> Create[Eintrag erstellen
Duplikat- & Eigentümerprüfung] + Create -- Fehler --> Rejected[Abgelehnt] + Create --> Draft[Draft
Nur für Eigentümer sichtbar] + Draft -- Veröffentlichen --> Published[Published
Öffentlich sichtbar] + Published -- Meldung --> Reported[Gemeldet
IsReported = true] + Reported --> Admin[Admin-Entscheidung] + Admin -- OK --> Approved[Freigegeben] + Admin -- Verstoß --> Deleted[Gelöscht
→ neuer Eintrag möglich] + + %% Styling to match original SVG + style Start fill:#444441,stroke:#B4B2A9,color:#D3D1C7 + style Create fill:#3C3489,stroke:#AFA9EC,color:#CECBE6 + style Rejected fill:#791F1F,stroke:#F09595,color:#F7C1C1 + style Draft fill:#085041,stroke:#5DCAA5,color:#9FE1CF + style Published fill:#085041,stroke:#5DCAA5,color:#9FE1CF + style Reported fill:#633806,stroke:#EF9F27,color:#FAC775 + style Admin fill:#444441,stroke:#B4B2A9,color:#D3D1C7 + style Approved fill:#27500A,stroke:#97C459,color:#C0DD97 + style Deleted fill:#791F1F,stroke:#F09595,color:#F7C1C1 +``` ##### Meldefunktion @@ -255,7 +302,26 @@ Die Meldefunktion ermöglicht es angemeldeten Benutzerinnen und Benutzern, einen Die Meldefunktion ist dabei nicht direkt im Hall-of-Fame-Modul implementiert, sondern wird über eine zentrale Schnittstelle aus einem gemeinsamen Interfaces-Paket eingebunden. Dieses Konzept ermöglicht es, dieselbe Melde-Oberfläche in beliebig vielen weiteren Modulen wiederzuverwenden, ohne die Logik mehrfach implementieren zu müssen. -![Ablauf des globalen Reporting-Systems] (./images/06-Adam/reporting_sequence_diagram.svg) + +```mermaid +sequenceDiagram + %%| filename: reporting_sequence_diagram + %%| fig-cap: Ablauf des globalen Reporting-Systems + participant User + participant Module + participant ReportingComponent + participant ReportingHandler + + User-->>+Module: View entity + Module-->>+ReportingComponent: Report current entity + ReportingComponent-->>User: Ask for reason + User-->>ReportingComponent: Enters reason + ReportingComponent-->>+ReportingHandler: New report (entity + reason) + ReportingHandler-->>-ReportingComponent: Done + ReportingComponent-->>-Module: Report saved + Module-->>-User: Report saved +``` + ##### PDF-Export