summaryrefslogtreecommitdiff
path: root/10-entwurfsheft/sections
diff options
context:
space:
mode:
authorOrangerot <purple@orangerot.dev>2024-05-24 17:42:08 +0200
committerOrangerot <purple@orangerot.dev>2024-05-24 17:47:22 +0200
commit7fcdc1c788725f866de71fc9dfd8c4d1cb132b57 (patch)
tree89931c85ae3f149884ba02c69862558e93f01531 /10-entwurfsheft/sections
Initial commitHEADmain
Diffstat (limited to '10-entwurfsheft/sections')
-rw-r--r--10-entwurfsheft/sections/apidoc.tex558
-rw-r--r--10-entwurfsheft/sections/aufbau.tex89
-rw-r--r--10-entwurfsheft/sections/backend.tex28
-rw-r--r--10-entwurfsheft/sections/changes.tex41
-rw-r--r--10-entwurfsheft/sections/einleitung.tex22
-rw-r--r--10-entwurfsheft/sections/frontend.tex150
-rw-r--r--10-entwurfsheft/sections/glossar.tex371
-rw-r--r--10-entwurfsheft/sections/structure.tex104
8 files changed, 1363 insertions, 0 deletions
diff --git a/10-entwurfsheft/sections/apidoc.tex b/10-entwurfsheft/sections/apidoc.tex
new file mode 100644
index 0000000..1eb181c
--- /dev/null
+++ b/10-entwurfsheft/sections/apidoc.tex
@@ -0,0 +1,558 @@
+\newenvironment{urlParameter}
+{
+ \newcommand{\urlParamItem}[2]
+ {
+ \rowcolor{\methodLightColor} ##1 & ##2 \\
+ }
+ \newcommand{\noUrlParameter}[1]
+ {
+ \small{\textit{##1}}
+ }
+ %\vspace{-0.61em}
+
+ \arrayrulecolor{\methodColor}
+
+ \begin{tabularx}{\textwidth}{X}
+ \rowcolor{\methodLightColor!20}
+ \textbf{URL-Parameter} \\ \hline
+ \end{tabularx}
+
+ \tabularx{\textwidth}{l X}
+}
+
+\newenvironment{pathParameter}
+{
+ \newcommand{\pathParamItem}[2]
+ {
+ \rowcolor{\methodLightColor} ##1 & ##2 \\
+ }
+ \newcommand{\noPathParameter}[1]
+ {
+ \small{\textit{##1}}
+ }
+ %\vspace{-0.61em}
+
+ \arrayrulecolor{\methodColor}
+
+ \begin{tabularx}{\textwidth}{X}
+ \rowcolor{\methodLightColor!20}
+ \textbf{Pfad-Parameter} \\ \hline
+ \end{tabularx}
+
+ \tabularx{\textwidth}{l X}
+}
+
+\newenvironment{jsonKeys}
+{
+ \newcommand{\jsonKeyItem}[2]
+ {
+ \rowcolor{\methodLightColor} ##1 & ##2 \\
+ }
+ \newcommand{\nojsonKeys}[1]
+ {
+ \small{\textit{##1}}
+ }
+ %\vspace{-0.61em}
+
+ \arrayrulecolor{\methodColor}
+
+ \begin{tabularx}{\textwidth}{X}
+ \rowcolor{\methodLightColor!20}
+ \textbf{Json-Keys} \\ \hline
+ \end{tabularx}
+
+ \tabularx{\textwidth}{l X}
+}
+
+\section{\Gls{api}}
+
+\subsection{Hypertext Transfer Protocol}
+% könnte auch unter in die Sektion API
+
+Das Hypertext Transfer Protocol (http) ist ein Protokoll zum übertragen von
+medialen Daten. Ein Webserver hört über den Port 80 auf Anfragen und antwortet.
+Eine Anfrage besteht aus einer Methode, einem Pfad, Kopfzeilen (\texttt{Header})
+und Inhalt (\texttt{Body}). Die Methode ist eine Konvention, um zu verdeutlichen
+was mit der Anfrage geschehen soll. Es können Daten abgefragt (\texttt{GET}),
+erstellt (\texttt{POST}), aktualisiert (\texttt{PUT}) oder gelöscht werden
+(\texttt{DELETE}). Der Pfad gibt an, für welche Daten die Methode gelten soll.
+Die Kopfzeilen beinhalten dabei Metadaten, wie Authentifikationen, \Glspl{cookie},
+Datentypen (MIME-Types), Sprache und das Anwenderprogramm.
+
+Der Server antwortet mit einem Statuscode, Kopfzeilen und Inhalt. Der Statuscode
+teilt mit, ob die Anfrage erhalten wurde ($\geq$ 100), erfolgreich bearbeitet
+werden konnte ($\geq$ 200), eine Weiterleitung nötig ist ($\geq$ 300),
+die Anfrage einen Fehler enthält ($\geq$ 400) oder
+ein interner Serverfehler aufgetreten ist ($\geq$ 500). In den Kopfzeilen können
+Berechtigungen gesetzt werden, welche festlegen, wie mit den Daten
+umzugehen ist.
+
+\newpage
+\subsection{Geräte} \label{Geräte}
+Die \Gls{gpodder}, welche wir für unser Produkt verwenden und erweitern, bietet eine gerätespezifische
+Synchronisation an. Diese bieten wir jedoch nicht an, denn wir synchronisieren Änderungen aller
+Geräte gleichwertig mit dem Nutzeraccount.
+Deshalb werden Geräte innerhalb der API ignoriert.
+
+\subsection{Authentication API}\label{a:auth}
+
+\subsubsection{Registrierung}\label{a:register}
+
+\begin{apiRoute}{post}{/api/2/auth/register.json}
+ {Registriert einen Nutzer mit einer E-Mail-Adresse und Passwort.
+ Versendet E-Mail mit Bestätigungslink an die angegebene E-Mail-Adresse.}
+ \begin{routeRequest}{application/json}
+ \begin{routeRequestBody}
+{
+ email: "jeff@example.com",
+ password: "MyNameIsJeff"
+}
+ \end{routeRequestBody}
+ \end{routeRequest}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: Nutzer wurde erfolgreich angelegt.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Fehler beim Parsen der Anfrage}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+
+\subsubsection{Anmelden}\label{a:login}
+
+\begin{apiRoute}{post}{/api/2/auth/\{username\}/login.json}
+ {Gegebenen Nutzer des gegebenen Geräts mithilfe HTTP Basic Auth einloggen.}
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des einzuloggenden Nutzers}
+ \end{pathParameter}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: Die Responseheader haben ein gesetztes Session-ID \Gls{cookie}.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Der Client stellt einen \Gls{cookie} für einen falschen Nutzer bereit.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{401}
+ {Unauthorized: Zugriff ohne Anmeldedaten}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\subsubsection{Abmelden}\label{a:logout}
+
+\begin{apiRoute}{post}{/api/2/auth/\{username\}/logout.json}
+ {Löscht den \Gls{cookie} beim Client.}
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \end{pathParameter}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: Falls der Client keinen \Gls{cookie} gesendet hat oder der Nutzer
+ erfolgreich ausgeloggt wurde.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Der Client stellt einen \Gls{cookie} für den falschen Nutzer bereit.}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+
+\subsubsection{Passwort ändern}\label{a:changepassword}
+
+\begin{apiRoute}{put}{/api/2/auth/\{username\}/changepassword.json}
+ {Passwort des gegebenen Nutzer ändern, indem altes und neues Passwort
+ übergeben werden. }
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \end{pathParameter}
+ \begin{routeRequest}{application/json}
+ \begin{routeRequestBody}
+{
+ password: "MyPasswordWasLeaked",
+ new_password: "SoIMadeANewOne"
+}
+ \end{routeRequestBody}
+ \end{routeRequest}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: Die Responseheader haben ein gesetztes Session-ID \Gls{cookie}.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Der Client stellt einen \Gls{cookie} für einen falschen Nutzer bereit.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{401}
+ {Unauthorized: Zugriff ohne Anmeldedaten}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\subsubsection{Passwort vergessen}\label{a:forgot}
+
+\begin{apiRoute}{post}{/api/2/auth/forgot.json}
+ {Sende eine E-Mail zum Zurücksetzen des Passworts. }
+ \begin{routeRequest}{application/json}
+ \begin{routeRequestBody}
+{
+ email: "jeff@example.com"
+}
+ \end{routeRequestBody}
+ \end{routeRequest}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: E-Mail wurde erfolgreich versendet.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Fehler beim Parsen der Anfrage}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+\subsubsection{Passwort zurücksetzen}\label{a:resetpassword}
+
+\begin{apiRoute}{put}{/api/2/auth/\{username\}/resetpassword.json}
+ {Passwort des gegebenen Nutzers ändern nachdem dieser sein Passwort
+ vergessen hat. }
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \end{pathParameter}
+ \begin{urlParameter}
+ \urlParamItem{token}{JSON-Web-Token}
+ \end{urlParameter}
+ \begin{routeRequest}{application/json}
+ \begin{routeRequestBody}
+{
+ password: "APasswordIWontForgetAgain"
+}
+ \end{routeRequestBody}
+ \end{routeRequest}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: Das Passwort wurde erfolgreich geändert.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Fehler beim Parsen der Anfragen. }
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{401}
+ {Unauthorized: JWT ist ungültig. }
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+\subsubsection{Account löschen}\label{a:delete}
+
+\begin{apiRoute}{delete}{/api/2/auth/\{username\}/delete.json}
+ {Der Account des gegebenen Nutzers wird gelöscht.}
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des zu löschenden Nutzers.}
+ \end{pathParameter}
+ \begin{routeRequest}{application/json}
+ \begin{routeRequestBody}
+{
+ password: "APasswordIWontHaveToRememberAnymore"
+}
+ \end{routeRequestBody}
+ \end{routeRequest}
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: Der Account des gegebenen Nutzers wurde erfolgreich gelöscht.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}
+ {Bad Request: Der Client stellt einen \Gls{cookie} für einen falschen Nutzer bereit.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{401}
+ {Unauthorized: Zugriff ohne Anmeldedaten}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+\subsection{Subscriptions API}\label{a:subs}
+\subsubsection{Abrufen aller \Glspl{abo}}\label{a:getSubs}
+
+\begin{apiRoute}{get}{/subscriptions/\{username\}.json}{/subscriptions/\{username\}/\{deviceid\}.json}
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \pathParamItem{deviceid}{siehe~\nameref{Geräte}}
+ \end{pathParameter}
+
+ \begin{urlParameter}
+ \urlParamItem{jsonp}{\Gls{JSONP} wird nicht unterstützt und der Parameter entsprechend ignoriert.}
+ \end{urlParameter}
+
+ \begin{routeResponse}{application/json}
+
+ \begin{routeResponseItem}{200}
+ {OK: \Glspl{abo} werden im \Gls{json}-Format zurückgegeben.}
+ \begin{routeResponseItemBody}
+[
+ "http://example.org/feed.rss",
+ "http://example.org/podcast.php",
+ "http://example.org/foo"
+]
+ \end{routeResponseItemBody}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}{Bad Request: falsches Format}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{401}
+ {Unauthorized: falscher Nutzer oder nicht eingeloggt}
+ \end{routeResponseItem}
+
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+\subsubsection{Abrufen der Informationen aller \Glspl{abo}}\label{a:getTitles}
+
+\begin{apiRoute}{get}{/subscriptions/titles/\{username\}.json}{/subscriptions/\{username\}/\{deviceid\}.json}
+
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \end{pathParameter}
+ \begin{routeResponse}{application/json}
+
+ \begin{routeResponseItem}{200}
+ {OK: \Glspl{abo} werden im angefragten Format zurückgegeben. Dabei werden für ein \Gls{abo} nur die aktuellsten 20 \Glspl{episode} zurückgegeben.}
+ \begin{routeResponseItemBody}
+[
+ {
+ "url": "http://example.com/podcast.php",
+ "title": "This is a cool podcast"
+ "timestamp": "2009-12-12T09:00:00",
+ "episodes": [
+ {
+ "podcast": "http://example.org/podcast.php",
+ "episode": "http://ftp.example.org/foo.ogg",
+ "title": "Episode 1: My journy",
+ "timestamp": "2009-12-12T09:00:00",
+ "guid": "AU-20190814-1342-5100-A",
+ "action": "play",
+ "started": 15,
+ "position": 120,
+ "total": 500
+ }
+ ]
+ }
+]
+ \end{routeResponseItemBody}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}{Bad Request: falsches Format}
+ \end{routeResponseItem}
+
+ \end{routeResponse}
+
+\end{apiRoute}
+\newpage
+
+\subsubsection{\Glspl{abo} hochladen}\label{a:uploadSubs}
+
+\begin{apiRoute}{put}{/subscriptions/\{username\}/\{deviceid\}.json}
+ {Falls bereits \Glspl{abo} im Nutzeraccount vorhanden, werden diese
+ zusammengeführt.}
+
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \pathParamItem{deviceid}{siehe~\nameref{Geräte}}
+ \end{pathParameter}
+
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}
+ {OK: \Glspl{abo} wurden aktualisiert und leerer String wird zurückgegeben.}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{400}{Bad Request: falsches Format}
+ \end{routeResponseItem}
+
+ \begin{routeResponseItem}{401}{Unauthorized: falscher Nutzer}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\subsubsection{Abrufen von \Gls{abo}-Änderungen}\label{a:getSubDelta}
+
+\begin{apiRoute}{get}{/api/2/subscriptions/\{username\}/\{deviceid\}.json}
+ {}
+
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \pathParamItem{deviceid}{siehe~\nameref{Geräte}}
+ \end{pathParameter}
+
+ \begin{urlParameter}
+ \urlParamItem{since}{Timestamp-Wert der letzten Antwort}
+ \end{urlParameter}
+
+ \begin{routeResponse}{application/json}
+
+ \begin{routeResponseItemBody}
+{
+ "add": [
+ "http://example.com/feed.rss",
+ "http://example.org/podcast.php"
+ ],
+ "remove": ["http://example.net/foo.xml"],
+ "timestamp": 12347
+}
+ \end{routeResponseItemBody}
+ \end{routeResponse}
+
+\end{apiRoute}
+
+\newpage
+\subsubsection{Änderungen der \Glspl{abo} hochladen}\label{a:applySubDelta}
+
+\begin{apiRoute}{post}{/api/2/subscriptions/\{username\}/\{deviceid\}.json}
+ {}
+
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \pathParamItem{deviceid}{siehe~\nameref{Geräte}}
+ \end{pathParameter}
+
+ \begin{routeRequest}{application/json}
+ \begin{routeRequestBody}
+{
+ "add": [
+ "http://example.com/feed.rss",
+ "http://example.org/podcast.php"
+ ],
+ "remove": ["http://example.net/foo.xml"]
+}
+ \end{routeRequestBody}
+ \end{routeRequest}
+
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}{OK: \Glspl{abo} wurden aktualisiert.}
+ \begin{routeResponseItemBody}
+{
+ "timestamp": 1337,
+ "update_urls": []
+}
+ \end{routeResponseItemBody}
+ ``update\textunderscore urls'' wird nicht bereitgestellt, deshalb
+ wird eine leere Liste zurückgegeben.
+ \end{routeResponseItem}
+ \begin{routeResponseItem}{400}{Bad Request: falsches Format}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\newpage
+\subsection{Episode Action API}\label{a:episodeActions}
+
+\subsubsection{Episode Actions hochladen}\label{a:uploadEpisodeActions}
+
+\begin{apiRoute}{post}{/api/2/episodes/\{username\}.json}
+ {}
+
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \end{pathParameter}
+
+ \begin{routeRequest}
+
+ \begin{routeRequestBody}
+POST /api/2/episodes/some-user.json
+[
+ {
+ "podcast": "http://example.org/podcast.php",
+ "episode": "http://ftp.example.org/foo.ogg",
+ "title": "Episode 1: My journey",
+ "timestamp": "2009-12-12T09:00:00"
+ "guid": "AU-20190814-1342-5100-A",
+ "action": "play",
+ "started": 15,
+ "position": 120,
+ "total": 500
+ }
+]
+
+ \end{routeRequestBody}
+
+ \end{routeRequest}
+
+ \begin{jsonKeys}
+ \jsonKeyItem{podcast}{Feed-URL des \Glspl{podcast} zu welchem die \Gls{episode} gehört (erforderlich)}
+ \jsonKeyItem{episode}{Medien-URL der \Gls{episode} (erforderlich)}
+ \jsonKeyItem{device}{Geräte-ID auf welcher die Aktion stattfand.}
+ \jsonKeyItem{action}{Eins von: download, play, delete, new (erforderlich)}
+ \jsonKeyItem{timestamp}{UTC-Timestamp im ISO 8601 Format, wann die Aktion stattfand}
+ \jsonKeyItem{started}{Position in Sekunden, an welcher das Anhören der \Gls{episode} gestartet wurde (nur bei Aktion: play)}
+ \jsonKeyItem{position}{Position in Sekunden, an welcher das Anhören der \Gls{episode} gestoppt wurde (nur bei Aktion: play)}
+ \jsonKeyItem{total}{Länge der \Gls{episode} (nur bei Aktion: play)}
+
+ \end{jsonKeys}
+
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}{OK}
+ \begin{routeResponseItemBody}
+{
+ "timestamp": 1337,
+ "update_urls": []
+}
+ \end{routeResponseItemBody}
+ ``update\textunderscore urls'' wird nicht bereitgestellt, deshalb
+ wird eine leere Liste zurückgegeben.
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
+\subsubsection{Abrufen von Episode Actions}\label{a:getEpisodeActions}
+
+\begin{apiRoute}{get}{/api/2/episodes/\{username\}.json}
+ {}
+
+ \begin{pathParameter}
+ \pathParamItem{username}{Nutzername des betreffenden Nutzers}
+ \end{pathParameter}
+
+ \begin{urlParameter}
+ \urlParamItem{podcast (string)}{URL des \Glspl{podcast}; falls gesetzt, werden nur Aktionen der \Glspl{episode} des gegebenen \Glspl{podcast} zurückgegeben.}
+ \urlParamItem{device (string)}{Device-ID; siehe~\nameref{Geräte}}
+ \urlParamItem{since (int)}{Nur \Glspl{episode}-Aktionen ab dem gegebenen Timestamp werden zurückgegeben.}
+ \urlParamItem{aggregated (bool)}{Wird ignoriert. }
+ \end{urlParameter}
+
+ \begin{routeResponse}{application/json}
+ \begin{routeResponseItem}{200}{OK}
+ \begin{routeResponseItemBody}
+{
+ "actions": [
+ {
+ "podcast": "http://example.org/podcast.php",
+ "episode": "http://ftp.example.org/foo.ogg",
+ "title": "Episode 1: My journey",
+ "timestamp": "2009-12-12T09:00:00"
+ "guid": "AU-20190814-1342-5100-A",
+ "action": "play",
+ "started": 15,
+ "position": 120,
+ "total": 500
+ }
+ ],
+ "timestamp": 12345
+}
+ \end{routeResponseItemBody}
+ \end{routeResponseItem}
+ \end{routeResponse}
+\end{apiRoute}
+
diff --git a/10-entwurfsheft/sections/aufbau.tex b/10-entwurfsheft/sections/aufbau.tex
new file mode 100644
index 0000000..c0747a9
--- /dev/null
+++ b/10-entwurfsheft/sections/aufbau.tex
@@ -0,0 +1,89 @@
+\section{Aufbau}
+
+\subsection{Architektur}
+
+\subsubsection{Aufteilung in Pakete}
+
+Das Backend wird in Pakete aufgeteilt, die den einzelnen implementierten
+\Glspl{api} der gpodder.net \Gls{api} entsprechen.
+Dies entspricht hier den \Glspl{api}: Subscriptions, Episode Actions und Authentication.
+Außerdem gibt es ein Model-Paket, welches die in den Logikschichten verwendeten Objekte modelliert.
+
+Für den Webserver selbst werden die \Glspl{api} um zusätzliche Funktionen erweitert. Denn die vorhandenen \Glspl{api} bieten nicht alle Funktionalitäten, die der Webserver benötigt, um die im Pflichtenheft beschriebenen Kriterien zu erfüllen.
+% (TODO: WebAPI bestimmen)
+
+\subsubsection{Die Architektur in den Paketen}
+
+In den Paketen selber herrscht eine 3-schichtige Architektur aus den Schichten: Controller, Service und Data-Access (siehe \ref{DAO_Pattern}).
+
+Die Controller-Schicht nimmt die Anfragen des Clients entgegen, lässt diese in den untergeordneten Schichten verarbeiten und gibt den Status der abgeschlossenen Handlung an den Client zurück.
+
+Die Service-Schicht ist die \Gls{business} des Programmes und überprüft bspw. Eingaben oder verschickt E-Mails. Sollte ein \Gls{db}aufruf nötig sein, so ruft der Service die Data-Access-Schicht auf und übergibt ihr die nötigen Informationen, was gespeichert, gelöscht, aktualisiert oder gelesen werden soll.
+
+Die Data-Access-Schicht ist für den Datenzugriff auf \Glspl{db} verantwortlich. Alle verantwortlichen Klassen für einen solchen Zugriff folgen dem \Gls{crud}-Prinzip.
+\Gls{crud} steht für die Funktionen Create (erschaffen), Read (lesen), Update (aktualisieren) und Delete (löschen). Entsprechend können Einträge in einer \Gls{db} auch nur erschaffen, gelesen, aktualisiert und gelöscht werden.
+
+\subsubsection{Das Model-Paket}\label{p:model}
+
+In einem globalen Model-Paket befinden sich alle Klassen, die für die Modellierungen von Objekten zuständig sind.
+Diese Objekte werden später in \Gls{db}abfragen gelesen und mittels objektrelationaler Abbildung (siehe \ref{t:orm}) gespeichert.
+In einer Antwort an den Client werden die Objekte, falls benötigt, als Antwort-Klassen gewrappt im \Gls{json}-Format zurückgeschickt.
+Auch kann der Client in einer Anfrage ein Objekt im \Gls{json}-Format übergeben, welches dann mithilfe von Spring als \Gls{java}-Objekt der korrespondierenden Anfrage-Klasse interpretiert wird.
+Aus diesem wird dann in Controller- und Service-Schicht das Objekt der entsprechenden Model-Klasse extrahiert.
+
+\subsubsection{Die Datenhaltungsschicht}
+
+Mit den Paketen ist bereits eine 3-schichtige Architektur aufgebaut.
+Damit Daten aber auch gelesen und gespeichert werden können ist eine vierte globale Schicht nötig - die Datenhaltungsschicht.
+
+Die Datenhaltungsschicht ist für die persistente Speicherung aller Daten zuständig.
+Diese werden meist (wie in diesem Fall) in einer \Gls{db} gespeichert.
+Der Zugriff auf die Datenhaltungsschicht erfolgt gemäß der intransparenten Schichtenarchitektur nur über die Data-Access-Schicht der Pakete.
+
+Der Vorteil dieser mehrschichtigen Architektur ist die klare Strukturierung des Programmes, womit der Code leserlicher und einfacher zu warten ist.
+
+\begin{landscape}
+
+\subsection{Klassendiagramm Backend}
+Das Klassendiagramm zeigt alle für den Entwurf relevanten Klassen des Backends mit ihren öffentlichen Methoden.
+Weiter zeigt das Diagramm die Aufteilung der Klassen in Pakete sowie schemenhaft dargestellte Verbindungen zu \Gls{db} und Webserver.
+
+% \input{assets/diagrams/classdiagram.latex}
+\includegraphics[width=\linewidth]{assets/diagrams/classdiagram}
+\end{landscape}
+
+\subsection{Sequenzdiagramme}
+
+\subsubsection{Authentication \Gls{api}}
+\subsubsection*{Registrierung \scriptsize{(\ref{a:register})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-register}
+\subsubsection*{Passwort vergessen und zurücksetzen \scriptsize{(\ref{a:forgot}, \ref{a:resetpassword})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-forgotAndResetPW}
+
+\subsubsection{Subscriptions \Gls{api}}
+\subsubsection*{Abonnements hochladen \scriptsize{(\ref{a:uploadSubs})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-uploadSubscriptions}
+
+\subsubsection*{Abrufen aller Abonnements \scriptsize{(\ref{a:getSubs})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-getSubscriptions}
+
+\subsubsection{Episode Actions \Gls{api}}
+\subsubsection*{Episode Actions hochladen \scriptsize{(\ref{a:uploadEpisodeActions})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-uploadEpisodeActions}
+
+\subsubsection*{Abrufen aller Episode Actions seit einem Zeitpunkt \scriptsize{(\ref{a:getEpisodeActions})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-getEpisodeActionsOfPodcastSince}
+
+\subsubsection*{Abrufen aller Episode Actions \scriptsize{(\ref{a:getEpisodeActions})}}
+\includegraphics[width=\textwidth]{assets/diagrams/sequencediagram-getEpisodeActions}
+
+\subsection{Komponentendiagramm Backend}
+\includegraphics[width=\textwidth]{assets/diagrams/backendComponentDiagram}
+
+\subsection{Verteilungsdiagram}
+\includegraphics[width=\textwidth]{assets/diagrams/deployment}
+
+\subsection{\Gls{db}-Modell}
+
+\includegraphics[width=\textwidth]{assets/diagrams/db}
+
diff --git a/10-entwurfsheft/sections/backend.tex b/10-entwurfsheft/sections/backend.tex
new file mode 100644
index 0000000..19efd65
--- /dev/null
+++ b/10-entwurfsheft/sections/backend.tex
@@ -0,0 +1,28 @@
+\section{Backend}
+
+Für das Backend wird das \Gls{java}-Framework \Gls{spring} verwendet. Neben seiner Modularität,
+bietet es viele Funktionen, die unter
+anderem die Entwicklung von Backend-Anwendungen vereinfachen.
+Darunter fällt zum Beispiel die Unterstützung von Dependency Injection, dessen
+Vorteile bereits beschrieben wurden.
+Außerdem unterstützt \Gls{java} \Gls{spring} intern eine Verwaltung von \Glspl{db}, sodass
+sich nicht mit dem \Gls{SQL}-Code an sich befasst werden muss.
+Auch bezüglich Authentifizierung und Sicherheit bietet \Gls{spring} eigene Funktionalitäten.
+
+Zusätzlich dazu wird als Build-System für das \Gls{java}-\Gls{spring}-Backend Maven verwendet.
+Maven hilft dabei alle Abhängigkeiten des Projekts zu verwalten und automatisiert
+den Build Prozess.
+Durch die zusätzliche Unterstützung von Versionskontrollsystemen und der Kompatibilität
+zu vielen Continuous Integration-Tools wird außerdem die Entwicklung in einem Team erleichtert
+und optimiert. Denn dadurch können Build- und Deployment-Prozesse automatisiert werden.
+Außerdem bietet Maven Bibliotheken zum Testen sowie zur Generierung von Dokumentationen an.
+
+Vom Backend benötigte Abhängigkeiten:
+\begin{itemize}
+ \item \Gls{spring} Web
+ \item \Gls{spring} Security
+ \item \Gls{spring} Mail Sender
+ \item \Gls{spring} Data JPA
+ \item Lombok
+ \item Rome (\Gls{rss} parsing/fetching)
+\end{itemize} \ No newline at end of file
diff --git a/10-entwurfsheft/sections/changes.tex b/10-entwurfsheft/sections/changes.tex
new file mode 100644
index 0000000..d8ac2ec
--- /dev/null
+++ b/10-entwurfsheft/sections/changes.tex
@@ -0,0 +1,41 @@
+
+\section{Änderungen zum Pflichtenheft}
+
+Im Folgenden werden die Änderungen zum Pflichtenheft aufgelistet.
+Hierbei handelt es sich um neue Kriterien, Kriterien die wegfallen und Kriterien die modifiziert wurden.
+
+\subsection{Neue Kriterien}
+
+\subsubsection{Cooldown Fetch-Vorgang}
+\begin{description}
+ \item[\textcolor{Green}{\textlangle RS11\textrangle}] \textcolor{Green}{Wenn ein Nuter ein \Gls{abo} oder eine \Gls{episode} eines \Gls{abo} hinzugefügt hat, welche noch nicht
+ in der \Gls{db} vorhanden ist, werden die Daten vom entsprechenden Server gefetched. Bis eine weitere fetch-Anfrage
+ zum selben \Gls{abo} gestartet wird, wird ein Cooldown von einer Stunde abgewartet.
+ Das hilft dabei DoS Angriffe zu vermeiden, da der Server damit nicht durch zu viele Fetch-Anfragen überlastet
+ werden kann.}
+\end{description}
+
+\subsubsection{Sprache von Browserinformationen übernehmen}
+\begin{description}
+ \item[\textcolor{Green}{\textlangle RC13\textrangle}] \textcolor{Green}{Betritt ein Nutzer zum ersten Mal die Webseite, ruft ein Skript die Browserdaten zur eingestellten Sprache ab.
+ Die Sprache wird im localStorage gespeichert und ruft entsprechend die Webseite in der jeweiligen Sprache auf.
+ Ändert der Nutzer die Sprache, so wird dies durch eine Änderung der Sprachvariable im localStorage festgehalten. }
+\end{description}
+
+\subsection{Abgeänderte Kriterien}
+
+ \subsubsection{Sessionspeicherung mit JWT}
+
+ \begin{description}
+ \item[\textlangle RS10\textrangle] Im Webfrontend angemeldete Benutzer bleiben dort angemeldet.
+ Hierfür wird ein \Gls{session-token} in einem \Gls{cookie} gespeichert.
+ \textcolor{blue}{Als \Gls{session-token} wird ein \Gls{json} Web Token verwendet.
+ Dieser Token wird für die Authentifikation genutzt.}
+ \end{description}
+
+\subsection{Entfernte Kriterien}
+
+ \begin{description}
+ \item[\textlangle RC5\textrangle]
+ \textcolor{red}{\sout{Die Weboberfläche ist kompatibel mit beliebigen \Glspl{gpodder}.}}
+ \end{description}
diff --git a/10-entwurfsheft/sections/einleitung.tex b/10-entwurfsheft/sections/einleitung.tex
new file mode 100644
index 0000000..0fd6114
--- /dev/null
+++ b/10-entwurfsheft/sections/einleitung.tex
@@ -0,0 +1,22 @@
+\section{Einleitung}
+
+Im vorangegangenen Pflichtenheft wurde ein Synchronisationsserver für \Glspl{podcast} beschrieben.
+In diesem Entwurfsheft wird die Implementierung dieses Synchronisationsservers
+mithilfe eines Entwurfes geplant.
+Wie im Pflichtenheft beschrieben, wird das finale Produkt
+aus einem Backend und einem Frontend bestehen.
+
+Das Webfrontend dient dazu, dem Nutzer eine Oberfläche zur Accountverwaltung
+und Einsicht seiner Synchronisationsstände und Daten zu ermöglichen.
+Dieses wird mithilfe des Javascript Frameworks Vue.js erstellt.
+
+Das Backend dient dazu, HTTP-Anfragen des Frontends und der \Gls{podcatcher} entgegenzunehmen,
+zu verarbeiten sowie zu beantworten.
+Damit Daten persistent gespeichert werden können, wird eine \Gls{db} eingebunden.
+Zur Erstellung des Backends wird \Gls{java} \Gls{spring} verwendet und für die \Gls{db} MariaDB.
+
+%Neben den Schichten gibt es drei große Zuordnungsbereiche in unserem Produkt.
+%Nämlich die Abonnements die ein Nutzer haben kann, deren Episoden
+%und die Accountverwaltung.
+%Deshalb unterteilen wir die einzelnen Projektklassen
+%schichtenübergreifend gemäß dieser Kategorien nochmals in einzelne Pakete.
diff --git a/10-entwurfsheft/sections/frontend.tex b/10-entwurfsheft/sections/frontend.tex
new file mode 100644
index 0000000..69a3c61
--- /dev/null
+++ b/10-entwurfsheft/sections/frontend.tex
@@ -0,0 +1,150 @@
+\section{Weboberfläche}
+
+Die Weboberfläche wird mit dem Frontend-Web-Framework Vue.js erstellt. Mit Vue
+werden wiederverwendbare, auf Datenänderungen reagierende Komponenten erstellt.
+Die Komponenten nutzen ein fertiges Aussehen von dem Frontend-CSS-Framework
+Bootstrap. Außerdem werden Icons der freien Schriftart fontawesome
+verwendet.
+
+Das Projekt wird durch den \Gls{bundler} vite aufgesetzt, gebaut und stellt einen
+Entwicklungswebserver mit Echtzeitvorschau bereit. Durch den vue-router wird bei
+der \Gls{spa} ein Seitenwechsel durch Manipulation der
+Browser-Chronik (History Manipulation) simuliert. Dadurch hat der Nutzer eine
+bessere Erfahrung, weil die Seite nicht neu geladen werden muss, wenn zu einem
+anderen Menüpunkt gewechselt wird.
+
+Wenn der Nutzer sich anmeldet wird die E-Mail-Adresse, der \Gls{session-token} und
+Spracheinstellungen in dem globallen Zustandsspeicher gespeichert, welcher durch
+die Pinia-Abhängigkeit bereitgestellt wird. Dadurch haben alle
+\Glspl{uiComponent} einfachen Zugriff auf die Daten und diese müssen nicht über
+Props in tiefliegende \Glspl{uiComponent} durchgereicht werden.
+
+Die Seiten werden als einzelne Kompontenten erstellt. Andere HTML-Strukturen
+werden als eigene Komponenten ausgelagert, wenn sie in mehreren Seiten verwendet
+werden und zur Reduzierung von Komplexität und Duplikation beitragen und selbst
+Logik beinhalten.
+
+Vom Frontend benötigte Abhängigkeiten:
+\begin{itemize}
+\item vite
+\item vue
+\item vue-router
+\item Pinia (globaler Zustandsspeicher)
+\item bootstrap
+\item fontawesome
+\item vue-i18n (Support für mehrere Sprachen)
+\end{itemize}
+
+\subsection{Komponentendiagramm Web-Frontend}
+\includegraphics[width=\textwidth]{assets/diagrams/componentdiagram}
+
+\subsection{Komponentenbeschreibung}
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{SubscriptionComponent}
+
+\begin{description}
+\item[Tag] \texttt{<Subscription subscription>}
+\item[Props] \mbox{} \\
+ \emph{subscription} \mbox{} Subscription-Objekt, welches Attribute zu einem \Gls{podcast} und
+ dessen \Glspl{episode} enthält.
+\item[Beschreibung] Nimmt ein Subscription-Objekt, zeigt Titel und LastUpdate und
+\Glspl{episode} der Subscription an.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/subscription.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+\begin{minipage}{.7\linewidth}
+\subsubsection*{EpisodeComponent}
+
+\begin{description}
+\item[Tag] \texttt{<Episode episode>}
+\item[Props] \mbox{} \\
+ \emph{episode} \mbox{} EpisodeAction-Objekt, welches Titel, \Gls{podcast},
+ Timestamp, Dauer und Hörfortschritt der \Gls{episode} enthält.
+\item[Beschreibung] Nimmt ein EpisodeAction-Object, zeigt Titel, \Gls{podcast}, Dauer,
+ Hörfortschritt und LastUpdate an.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/episode.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+\begin{minipage}{.7\linewidth}
+\subsubsection*{LastUpdateComponent}
+
+\begin{description}
+\item[Tag] \texttt{<LastUpdate timestamp>}
+\item[Props] \mbox{} \\
+ \emph{timestamp} \mbox{} Date-Objekt, welches die Zeit der letzten Änderung enthält
+\item[Beschreibung] Nimmt ein Timestamp und gibt die Zeit seit dem Timestamp in
+ einem menschenlesbaren Format aus.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/lastupdate.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+\begin{minipage}{.7\linewidth}
+\subsubsection*{HelpComponent}
+
+\begin{description}
+\item[Tag] \texttt{<Help>}
+\item[Beschreibung] Zeigt Hilfestellungen in einem Fenster an. Dieses kann über
+ die Navigationsleiste aufgerufen werden.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/help.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+\begin{minipage}{.7\linewidth}
+\subsubsection*{NavbarComponent}
+
+\begin{description}
+\item[Tag] \texttt{<Navbar>}
+\item[Beschreibung] Enthält route-links zu im vue-router definierten Pfaden.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \fbox{\includegraphics[width=\textwidth]{assets/navbar.png}}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+\begin{minipage}{.7\linewidth}
+\subsubsection*{PasswordValidatorComponent}
+
+\begin{description}
+\item[Tag] \texttt{<Password>}
+\item[Beschreibung] Überprüft ob der eingegebene Text die Bedingungen für ein
+ sicheres Passwort erfüllt.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/password-margin.png}
+ \end{figure}
+\end{minipage}
+
diff --git a/10-entwurfsheft/sections/glossar.tex b/10-entwurfsheft/sections/glossar.tex
new file mode 100644
index 0000000..9caad87
--- /dev/null
+++ b/10-entwurfsheft/sections/glossar.tex
@@ -0,0 +1,371 @@
+\makeglossaries
+
+\newglossaryentry{spa}
+{
+ name=Single-Page-Application,
+ description={
+ ist ein Webseiten-Modell, bei welchem dem Nutzer nur ein Webdokument
+ bereitgestellt wird. Mit einem Skript wird der Inhalt der Seite
+ dynamisch mit Daten einer API befüllt. Außerdem verwaltet die Seite
+ (nicht der Server), welcher Inhalt bei welchem Pfad angezeigt wird. Dies
+ erzeugt geringere Serverlast und eine bessere Nutzererfahrung, da die
+ Seitenstruktur beim Laden von neuen Inhalten erhalten bleibt}
+}
+
+\newglossaryentry{packagemanager}
+{
+ name=Paketmanager,
+ description={
+ ist ein Programm, welches Pakete und dessen Abhängigkeiten verwaltet,
+ installiert, entfernt und aktualisiert. Pakete können andere Programme,
+ Plugins oder Software-Bibliotheken sein}
+}
+
+\newglossaryentry{bundler}
+{
+ name=Bundler,
+ description={
+ ist ein Programm, welches genutzte Teile von Abhängigkeiten eines
+ Software-Projekts in passender Reihenfolge zusammensucht und daraus
+ Dateien erstellt, die für den Nutzer bereitgestellt werden können. Dabei
+ kann der Bundler mit zusätzlichen Modulen Dateien erzeugen, die
+ rückwärtskompatibel oder für den Nutzer schwerer einsehbar sind}
+}
+
+\newglossaryentry{java}
+{
+ name=Java,
+ description={
+ ist eine objekt-orientierte interpretierte kompilierte
+ Programmiersprache, welche plattformunabhängig auf einer virtuellen
+ Maschine ausgeführt wird}
+}
+
+\newglossaryentry{db}
+{
+ name=Datenbank,
+ plural=Datenbanken,
+ description={
+ ist ein System um Daten persistent zu speichern und effizient zu
+ verwalten. Am meisten verbreitet sind relationale Datenbanken, welche
+ Daten in Tabellen mit Referenzen zu Einträgen anderer Tabellen
+ speichern. Programme können dann über eine Anfragesprache (Structured
+ Query Language - \Gls{SQL}) komplexe Operationen auf den Daten ausführen}
+}
+
+\newglossaryentry{docker}
+{
+ name=Docker,
+ description={
+ ist ein Programm, das virtualisierte Container ausführt. Ein Programm in
+ so einem Container läuft in seiner eigenen virtuellen Umgebung, wodurch
+ das Host-System sicher bleibt. Zudem lassen sich die Container leicht
+ auf andere Systeme verteilen}
+}
+
+% RESTfull-API, JSON, RSS-Feed, Salting and Hasing, OAuth, Cookie, Garbage
+% Collection, DSGVO, Podcast, Podcatcher, Episode, Gpodder,
+
+\newglossaryentry{podcatcher}
+{
+ name=Podcatcher,
+ plural=Podcatchern,
+ description={
+ ist ein Programm, über welches man Podcasts entdecken, abonnieren und
+ Episoden von Podcasts hören kann. Mit einem Account auf einer Plattform,
+ welche eine Gpodder-API zur Verfügung stellt, können Ereignisse, die von
+ einem Nutzer ausgehen, auf anderen Podcatchern des Nutzers
+ synchronisiert werden}
+}
+
+\newglossaryentry{podcast}
+{
+ name=Podcast,
+ description={
+ ist ein RSS-Feed, dessen Einträge die Episoden darstellen}
+}
+
+\newglossaryentry{episode}
+{
+ name=Episode,
+ plural=Episoden,
+ description={
+ ist ein Eintrag in einem Podcast. Eine URL in dem Eintrag zeigt auf eine
+ Medien-Datei, welche vom Podcatcher abgespielt werden kann}
+}
+
+\newglossaryentry{rest-api}
+{
+ name=RESTful-API,
+ description={
+ ist ein Schnittstellenentwurf über das Hypertext Transfer Protocol
+ (HTTP), bei dem die Schnittstellen strukturiert als Pfad an einem
+ Endpunkt erreichbar sind. Mittels verschiedener HTTP-Methoden können an
+ der Schnittstelle Daten abgefragt (GET), gesendet (PUT), gelöscht
+ (DELETE) oder geändert (POST) werden. Die Daten, die über die
+ Schnittstelle gesendet werden liegen meist im JSON-Format vor}
+}
+
+
+\newglossaryentry{gpodder}
+{
+ name=Gpodder-API,
+ description={
+ wird von gpodder.net benutzt und entwickelt. Die API wird als
+ Schnittstelle zwischen Podcatchern und Podcast Synchronisationsservern
+ verwendet. Weitere Details sind unter
+ "https://gpoddernet.readthedocs.io/en/latest/api/" zu finden}
+}
+
+\newglossaryentry{json}
+{
+ name=JSON,
+ description={
+ (JavaScript Object Notation) ist ein Datenformat und wird zur
+ Übertragung von Strukturen und Daten eingesetzt. JSON besteht dabei aus
+ grundlegenden Datentypen sowie Objekten mit Schlüssel-Wert Paaren und
+ Listen}
+}
+
+\newglossaryentry{oauth}
+{
+ name=OAuth,
+ description={
+ (Open Authorization) ist ein offenes Protokoll, welches es Nutzern
+ ermöglicht, sich mit bereits bestehenden Accounts bei anderen Diensten
+ zu registrieren. Dabei werden benötigte Daten für die Registrierung über
+ die bereitgestellte Schnittstelle zur Verfügung gestellt}
+}
+
+\newglossaryentry{garbage-collection}
+{
+ name=Garbage Collection,
+ description={
+ ist eine automatische Speicherbereinigung, welche nicht mehr benötigten
+ Speicherplatz wieder freigibt. Die Bereinigung kann dabei in determinierten
+ Zeitintervallen erfolgen oder durch bestimmte Ereignisse ausgelöst
+ werden}
+}
+
+\newglossaryentry{salt-hash}
+{
+ name=Salting und Hashing,
+ description={
+ ist eine Methode um Passwörter so zu kodieren, dass sie nicht als
+ Klartext gespeichert werden und auch sicher vor Hash-Wörterbüchern sind.
+ Dafür wird dem Passwort ein bekanntes Wort, der Salt, angefügt, bevor
+ aus dem kompletten Wort eine Prüfsumme, ein Hash, generiert wird. Beim
+ Anmelden wird die Prüfsumme der Anmeldung mit der bekannten
+ Prüfsumme des Passworts verglichen}
+}
+
+\newglossaryentry{rss}
+{
+ name=RSS,
+ description={
+ (Really Simple Syndication) zeigt strukturiert Listen von Nachrichten
+ an. Die Änderungen werden im XML-Format in sogenannte RSS-Dateien
+ geschrieben, welche über einen Link abgerufen werden können}
+}
+
+\newglossaryentry{dsgvo}
+{
+ name=Datenschutz-Grundverordnung,
+ description={
+ (DSGVO) ist eine im europäischen Wirtschaftsraum
+ geltende Verordnung. Sie sorgt für eine Reglementierung bei der
+ Verarbeitung personenbezogener Daten. Unter anderem muss einsehbar sein,
+ welche Daten von Nutzern erhoben werden. Außerdem muss für einen Nutzer
+ die Möglichkeit bestehen, seine erhobenen Daten abrufen zu können}
+}
+
+\newglossaryentry{push-pull}
+{
+ name=Push und Pull,
+ description={
+ sind Methoden, um Daten auszutauschen. Bei der Pull-Methode
+ stellt Akteur A einem Akteur B eine Anfrage auf Daten und erhält diese
+ als Antwort. Damit Akteur A und B immer auf dem selben Stand sind, muss
+ Akteur A chronisch Anfragen an Akteur B stellen. Im Gegensatz dazu steht
+ die Push-Methode, bei der Akteur B den Akteuren mitteilt, dass er neue
+ Änderungen hat. Dafür muss Akteur B allerdings wissen mit welchen
+ anderen Akteuren er in Verbindung steht und diese Verbindung aufrecht
+ erhalten}
+}
+
+\newglossaryentry{ui-lib}
+{
+ name=UI-Bibliothek,
+ plural=UI-Bibliotheken,
+ description={
+ kümmert sich um das Layout einer Webseite. Dabei unterscheidet man
+ zwischen Design-Bibliotheken (wie Bootstrap), welche fertige
+ UI-Komponenten bereitstellen, und Layout-Bibliotheken (wie Vue oder
+ React.js), welche die Komponenten basierend auf Daten dynamisch
+ anzeigen}
+}
+
+\newglossaryentry{responsive}
+{
+ name=Responsive,
+ description={
+ Design ist ein Design-Prinzip für Webseiten, bei dem die selbe Webseite ihre
+ Komponenten dynamisch der Bildschirmbreite anpasst}
+}
+
+\newglossaryentry{pseudoprotocol}
+{
+ name=Pseudoprotokoll,
+ description={
+ ist ein URL-Schema, auf das Webseiten hören können, wenn sie sich das
+ URL-Schema im Browser anmelden. Bekannt Pseudoprotokolle sind:
+ ,,mailto:'', ,,tel:'' oder ,,irc:''}
+}
+
+\newglossaryentry{dashboard}
+{
+ name=Dashboard,
+ description={
+ ist die erste Seite auf der man landet, wenn man angemeldet ist}
+}
+
+\newglossaryentry{abo}
+{
+ name=Abonnement,
+ description={
+ ist ein abonnierter Podcast}
+}
+
+\newglossaryentry{discovery}
+{
+ name=Discovery,
+ description={
+ ist ein Feature der Gpodder-API, welches dem Nutzer eine Reihe von
+ Podcasts zum abonnieren anbietet}
+}
+
+\newglossaryentry{session-token}
+{
+ name=Session-Token,
+ description={
+ ist ein Wort, dass vom Client gespeichert wird solange der Nutzer
+ eingeloggt ist und bei jeder Anfrage an den Server mitgeschickt wird.
+ Der Server kann den Session-Token einem Nutzer zuordnen und so mit
+ nutzerspezifischen Daten antworten}
+}
+
+\newglossaryentry{cookie}
+{
+ name=Cookie,
+ description={
+ ist ein kleiner webseitenspezifischer Speicher im Browser, welcher vom
+ Server und von der Webseite gesetzt werden kann und bei jeder weiteren
+ Anfrage an den Server mitgesendet wird. Cookies bleiben entweder
+ temporär im Browserspeicher, bis der Browser geschlossen wird oder
+ permanent, bis ein optionales Verfallsdatum erreicht ist}
+}
+
+\newglossaryentry{uiComponent}
+{
+ name=UI-Komponente,
+ plural=UI-Komponenten,
+ description={
+ In Vue.js werden die grafischen Elemente einer Webseite in einzelne
+ Komponenten zerteilt.
+ Diese reagieren automatisch auf Änderungen und können ohne Neuladen
+ der Seite ihr Aussehen verändern und somit Änderungen direkt anzeigen}
+}
+
+\newglossaryentry{spring}
+{
+ name=Spring,
+ description={
+ Ein Java-Framework, welches die Entwicklung von Web-Applikationen erleichtert.
+ Dazu wird eine Reihe von Werkzeugsets zur Verfügung gestellt.
+ Unter anderem sind das Spring Web für das Erstellen von Webanwendungen,
+ Spring Security für die Verwaltung von Benutzerauthentifizierungen und
+ Spring Data JPA für die Arbeit mit relationalen Datenbanken
+ }
+}
+
+\newglossaryentry{api}
+{
+ name=API,
+ plural=APIs,
+ description={
+ Eine Schnittstelle, welche es ermöglicht auf Funktionalitäten einer Anwendung
+ zuzugreifen. APIs für Webanwendungen heißen WebAPIs.
+ Ein Beispiel für eine WebAPI ist die REST-API
+ }
+}
+
+\newglossaryentry{business}
+{
+ name=Geschäftslogik,
+ description={
+ Eine Schicht in der Anwendungsentwicklung, in der die Art und Weise, wie das
+ Programm auf Eingaben reagiert, wie Daten verarbeitet und wie sie gespeichert
+ werden sollen, festgelegt ist
+ }
+}
+
+\newglossaryentry{solid}
+{
+ name=SOLID,
+ description={
+ Eine Sammlung an Prinzipien, welche zu gutem objektorientierten Design führen soll.
+ Jedes Prinzip steht für einen Buchstaben in SOLID:
+ \textbf{S}ingle-Responsibility Prinzip,
+ \textbf{O}pen-Closed Prinzip,
+ \textbf{L}iskovsches Substitutionsprinzip,
+ \textbf{I}nterface Segregation Prinzip und
+ \textbf{D}ependency Inversion Prinzip
+ }
+}
+
+\newglossaryentry{crud}
+{
+ name=CRUD,
+ description={
+ CRUD steht für \textbf{C}reate, \textbf{R}ead, \textbf{U}pdate und \textbf{D}elete.
+ Hierbei handelt es sich um die grundlegenden Funktionen einer Anwendung,
+ die mit einer Datenbank arbeitet.
+ Hierbei können Daten angelegt, abgerufen, aktualisiert und gelöscht werden.
+ Auch in Web-Applikationen ist CRUD mit HTTP über die Anfragen POST, GET, PUT und DELETE
+ vertreten
+ }
+}
+
+\newglossaryentry{SQL}
+{
+ name=SQL,
+ description={
+ SQL (Structured Query Language) ist eine Sprache, die einen strukturierten Zugriff auf Datenbanken ermöglicht.
+ Daten können hierbei hinzugefügt, abgefragt, geändert und gelöscht werden.
+ Das besondere hierbei ist der strukturierte Zugriff auf Daten, indem explizit Daten mit bestimmten Kriterien und
+ Relationen ausgewählt und bearbeitet werden können.
+ SQL wird fast von allen verbreiteten Datenbanksystemen unterstützt
+ }
+}
+
+\newglossaryentry{Base64}
+{
+ name=Base64,
+ description={
+ Mithilfe von Base64 können 8-Bit-Binärdaten in eine ASCII-Zeichenkette
+ kodiert werden. So werden zum Beispiel E-Mail-Anhänge versendet
+ }
+}
+
+\newglossaryentry{JSONP}
+{
+ name=JSONP,
+ description={
+ JSONP ermöglicht die Übertragung von JSON-Daten zwischen verschiedenen Domains.
+ Dies wäre durch die Same-Origin-Policy nicht möglich.
+ JSONP nutzt allerdings die Tatsache aus,
+ dass sich Skripte domainübergreifend übertragen lassen.
+ Dazu werden die JSON-Daten als Argument einer übergebenen Funktion über
+ ein Skript-Element eingebunden
+ }
+}
diff --git a/10-entwurfsheft/sections/structure.tex b/10-entwurfsheft/sections/structure.tex
new file mode 100644
index 0000000..2a6ecb3
--- /dev/null
+++ b/10-entwurfsheft/sections/structure.tex
@@ -0,0 +1,104 @@
+\section{Entwurfsmuster und Techniken}
+
+\subsection{Entwurfsmuster}
+
+\subsubsection{Dependency Injection}
+
+Die Dependency Injection (dt. Abhängigkeitsinjektion) ist ein Entwurfsmuster, welches die Abhängigkeiten von Objekten bestimmt und an einem zentralen Ort speichert sowie verwaltet.
+Sollte ein Objekt also von einem anderen Objekt abhängig sein, so wird an diesem zentralen Ort nach der Abhängigkeit gesucht.
+Ist die Abhängigkeit vorhanden, so wird dieses Objekt dann an dem benötigten Ort eingesetzt (injiziert).
+Dies geschieht während der Laufzeit.
+Der zentrale Ort, an dem die Abhängigkeiten gespeichert werden, wird meist von einem Framework verwaltet.
+
+Im Falle dieses Projekts ist \Gls{spring} das Framework und der \Gls{spring} Container der zentrale Ort, an dem die Abhängigkeiten gespeichert werden.
+Der Vorteil dieses Entwurfsmusters ist, dass Objekte von anderen Objekten abgekoppelt werden, sprich: Das Objekt mit der Abhängigkeit muss nicht mehr von der expliziten Klasse Kenntnis haben und es kann nur mit Interfaces gearbeitet werden, was in den \Gls{solid}-Kriterien das D für Dependency Inversion erfüllt.
+Ein weiterer Vorteil ist, dass die Abhängigkeiten innerhalb einer Konfigurationsdatei definiert werden können.
+Sprich: Man kann mehrere Implementierungen besitzen, die alle das gleiche Interface implementieren und kann in der Konfigurationsdatei angeben, welche Implementierung gewählt werden soll.
+
+\subsubsection{Data Access Object (DAO)}
+\label{DAO_Pattern}
+
+Das Data Access Object (kurz: DAO, dt: Datenzugriffsobjekt) ist ein Entwurfsmuster, das eingesetzt wird um den Zugriff auf \Gls{db}en zu vereinfachen und die \Gls{business} von der Datenzugriffslogik zu trennen.
+Dazu gibt es zwei Komponenten: das DAO-Interface und die DAO-Implementierung.
+
+Das DAO-Interface wird von allen DAO-Implementierungen implementiert und bietet alle Datenzugriffsfunktionen an, auf die die \Gls{business} zugreift.
+Die DAO-Implementierung ist eine Klasse, die das DAO-Interface implementiert und den tatsächlichen Zugriff auf die \Gls{db} ausführt.
+
+Der Vorteil dieses Entwurfsmusters ist es mehrere Implementierungen desselben DAO-Interfaces zu besitzen.
+In Kombination mit der Dependency Injection ist es einfach zwischen den Implementierungen für verschiedene \Gls{db}en (bspw. MariaDB und My\Gls{SQL}) zu wechseln.
+Damit wird der Datenzugriff flexibler.
+Im Falle dieses Projekts wird eine DAO-Implementierung für MariaDB verwendet.
+
+Ein weiterer Vorteil ist die zuvor angesprochene Trennung der Geschäfts- und Datenzugriffslogik.
+Da sich die \Gls{business} und Datenzugriffslogik mithilfe dieses Musters in verschiedenen Komponenten befinden, sind diese voneinander getrennt und es wird einfacher die jeweiligen Implementierungen zu testen.
+Gleichzeitig verbessert sich damit die Wiederverwendbarkeit des Codes, da die DAO-Implementierungen in anderen Programmen, die mit demselben DAO-Interface arbeiten, eingesetzt werden können.
+
+Damit erfüllt das DAO-Muster die Kriterien S und O der \Gls{solid}-Kriterien.
+Das Single-Responsibility Prinzip wird erfüllt, da der Zugriff auf die \Gls{db} von der \Gls{business} getrennt wird und damit die DAO-Implementierung alleine für den Zugriff auf die \Gls{db} verantwortlich ist.
+Das Open/Closed Prinzip wird erfüllt, da die DAO-Implementierung erweitert werden kann, ohne dass der Rest vom Projekt betroffen wird und außerhalb der Klasse nur mit dem DAO-Interface gearbeitet werden kann.
+
+\subsection{Techniken}
+
+\subsubsection{JSON Web Token}
+
+\Gls{json} Web Token (JWT) ist ein offener Standard der in RFC 7519 definiert wird.
+Mit einem JWT ist es möglich Informationen sicher in einem kodierten \Gls{json} Objekt zu übertragen.
+Die Sicherheit der Daten wird dabei durch eine digitale Signatur gewährleistet.
+
+Ein JWT besteht aus drei durch Punkte ('.') voneinander getrennten Teilen:
+\texttt{Header}, \texttt{Payload} und \texttt{Signatur}.
+Der \texttt{Header} besteht dabei typischerweise aus der Information um welchen Typ von Token es sich handelt, also einen JWT,
+und der Information welcher Signierungs-Algorithmus verwendet wird.
+Diese Informationen werden \Gls{Base64} kodiert und bilden den ersten Teil des JWT.
+
+Im \texttt{Payload} Teil werden die eigentlichen Informationen \Gls{Base64} kodiert.
+
+Die \texttt{Signatur} ergibt sich durch die mit einem Punkt voneinander getrennten Kodierungen des \texttt{Headers} und
+des \texttt{Payload}-Teils. Diese Zeichenkette wird dann mit einem geheimen Schlüssel
+durch den im \texttt{Header} angegebenen Signierungs-Algorithmus signiert.
+JWT werden einmalig vom Server erzeugt und beim Client gehalten. Daher ist es
+nicht notwendig wie z.B. bei \gls{cookie} basierten Sessions, eine Liste mit gültigen Sessions auf dem Server zu verwalten, was bei mehreren Servern schwierig ist.
+
+In diesem Projekt werden JWT zur Verifikation der E-Mail-Adresse eines Benutzers und zur Überprüfung der Autorisation bei Anfragen an den Server verwendet.
+
+Zur Bestätigung der E-Mail-Adresse speichert der Server die zur Verifikation des
+Benutzers benötigten Daten in einem JWT. Dieser wird in der URL des Verifikations-Links kodiert. Wenn der Benutzer den Verifikations-Link anklickt,
+wird der JWT an den Server weitergeleitet. Dieser überprüft die Signatur des JWT ihn mit seinem geheimen Schlüssel
+und kann so die Verifikation der E-Mail-Adresse abschließen.
+
+Bei dem Login-Vorgang sendet der Client zuerst seine Anmeldedaten (Benutername und Passwort), um sich zu authentifizieren.
+Der Server überprüft die Angaben, generiert einen JWT und gibt diesen zurück, falls die Daten korrekt sind.
+Bei späteren Anfragen an den Server übermittelt der Client diesen JWT. Der Server überprüft die Validität des JWT und trifft
+basierend darauf die Entscheidung, ob die Anfrage bearbeitet oder abgelehnt wird.
+
+\subsubsection{Objektrelationale Abbildung (Object-relational mapping)}\label{t:orm}
+
+Objektrelationale Abbildung - kurz ORM von der englischen Bezeichnung \enquote{Object-relational mapping} - ist eine Technik der Softwareentwicklung.
+Sie widmet sich dem, mit der persistenten Speicherung von Laufzeit-Objekten zusammenhängenden \enquote{Impedance mismatch} Problem.
+Dieses beschreibt die Diskrepanz zwischen den in der Pogrammier- beziehungsweise \Gls{db}welt vorherrschenden Konzepten - nämlich der objektorientierten Programmierung und relationalen \Gls{db}en.
+So speichern objektorientierte Programmiersprachen Daten und Verhalten in Objekten mit eindeutiger Identität, wobei Zustand und Verhalten hinter einer Schnittstelle verborgen werden.
+Relationale \Gls{db}en hingegen speichern Daten in Tabellen und basieren auf dem mathematischen Konzept der Relationenalgebra.
+
+Objektrelationale Abbildung bietet eine Möglichkeit diese Diskrepanz zu vermindern, indem sie ein Mapping zwischen Objekten und Datenstrukturen relationaler \Gls{db}en herstellt.
+Einem, in einer objektorientierten Programmiersprache geschriebenen, Anwendungsprogramm erscheint dann die verbundene relationale \Gls{db} als objektorientierte \Gls{db}.
+Durch ORM wird also sowohl das Ablegen von Objekten mit Attributen und Methoden in relationale \Gls{db}en, als auch das Erzeugen von solchen Objekten aus entsprechenden Datensätzen ermöglicht.
+Vorteilhaft ist daran außerdem, dass die objektorientierte Programmiersprache nicht erweitert werden muss.
+Des Weiteren existiert für jede Umgebung ausgereifte Software für die Verwendung relationaler \Gls{db}en.
+Allerdings ist der Schritt in Richtung objektorientiertem Ansatz immanent ein Schritt weg von den eigentlichen Stärken relationaler \Gls{db}en.
+
+Der grundlegende Ansatz ist die Abbildung von Klassen auf Tabellen, wobei die Spalten den Attributen und die Zeilen den Objekten der Klasse zugeordnet sind.
+Dabei entspricht der Primärschlüssel der Tabelle der Objektidentität und Objektreferenzen werden mithilfe von zusätzlichen Fremdschlüsseln repräsentiert.
+%Um Vererbung abzubilden gibt es drei grundlegende Möglichkeiten.
+%Erst einmal kann für eine Vererbungshierarchie auch genau eine gemeinsame Tabelle mit allen Attributen verwendet werden, in der ein Diskriminator bestimmt, zu welcher Klasse ein Objekt gehört.
+%Als zweite Option kann pro Unterklasse eine zusätzliche verknüpfte Tabelle eingeführt werden.
+%Letztlich kann auch pro konkreter Klasse eine Tabelle verwendet werden, wobei die Tabelle für die abstrakte Basisklasse entfällt.
+
+Die von diesem Mapping betroffenen Klassen aus dem Model-Paket (\ref{p:model}) des Backends sind User, SubscriptionAction, Subscription, EpisodeAction und \Gls{episode}.
+
+Konkret für dieses Projekt findet ORM als Technik durch die Implementierung der Jakarta Persistence \Gls{api} (JPA) Anwendung.
+Dafür wird das von \Gls{spring} zur Implementierung von JPA-basierten Datenzugriffsschichten bereitgestellte Modul \Gls{spring} Data JPA genutzt.
+Als JPA-Implementation wiederum wird das Open-Source-Persistenz- und ORM-Framework Hibernate für \Gls{java} verwendet.
+Dabei erfolgen Abfragen der persistierten Objekte über die Abfragesprache Jakarta Persistence Query Language (JPQL), welche dann mittels JDBC in den entsprechen \Gls{SQL}-Dialekt für MariaDB übersetzt.
+%Hier sei angemerkt, dass JPQL eine Untermenge der Hibernate Query Language (HQL) ist.
+
+\newpage