\chapter{Backend} Das Backend ist das Herzstück einer jeden Anwendung. Es muss hochverfügbar und enorm fehlertolerant sein. Aus diesem Grund haben wir uns für Technologien entschieden, die Open-Source-Software sind und eine entsprechend große Verbreitung haben. Weiter war es von Anfang an wichtig trotz der großen Abhängigkeit zum Backend die Entwicklung der anderen Teile nicht zu blockieren. Es wurden daher frühzeitig Modelle und Protokolle erstellt, die bereits vor der Fertigstellung gemockt werden konnten. \section{Technologiebeschreibung} \subsection{Spring Boot} Für die Implementierung des REST-Backends haben wir auf das Spring Framework gesetzt. Genauer gesagt, das Spring \emph{Boot} Framework. Das Wort "Boot" steht hierbei sinngemäß für "bootstrap", was uns viel Konfigurationsarbeit abgenommen hat. Alle Standard Beans und Factories waren bereits initialisiert und konnten ohne weitere Konfiguration genutzt werden. Es wurden im Projektverlauf auch noch diverse Erweiterungen des Frameworks genutzt. \begin{itemize} \item \textbf{org.springframework.boot:spring-boot-starter-web}, bringt einen integrierten Tomcat Application Server mit und ermöglicht das Verarbeiten von Webanfragen. \item \textbf{org.springframework.boot:spring-boot-starter-actuator}, wird genutzt um Diagnose-Endpoints freizuschalten. \item \textbf{org.springframework.boot:spring-boot-starter-data-jpa}, bringt alle nötigen Abhängigkeiten um mit der Java Persistence API Daten in einer Datenbank abzulegen. \item \textbf{org.springframework.boot:spring-boot-starter-data-rest}, bietet Möglichkeiten sehr leicht Datenbank Entitäten als HTTP REST Ressourcen bereitzustellen. \item \textbf{org.springframework.boot:spring-boot-starter-security}, wird später zusammen mit der Authentifizierung über JWT genutzt. \item \textbf{org.springframework.boot:spring-boot-starter-test}, bringt Möglichkeiten leichtgewichtig Unit Tests für Webanwendungen zu schreiben. \end{itemize} Zur weiteren Reduktion des "Boilerplate Codes" wurde zusätzlich noch das Lombok Framework\footnote{\url{https://projectlombok.org/}} genutzt. Es bietet die Möglichkeit Getter und Setter sowie diverse Konstruktoren für Datenklassen zu generieren. Dadurch konnten die Datenklassen um etwa 80\% in der große reduziert werden, dies fördert die Lesbarkeit und vermeidet auch Leichtsinnsfehler. \subsection{MariaDB} Als Datenbank wurde MariaDB eingesetzt. MariaDB ist die Quelloffene Entwicklung der MySQL Datenbank und nimmt deshalb alle Befehle an die auch MySQL annimmt. Als Alternative stand noch Postgres zur Auswahl, da wir aber keine der erweiterten Funktionen von Postgres brauchten fiel die Auswahl auf MariaDB. MariaDB musste auf keinem Entwicklungsrechner installiert werden, da immer das offizielle Dockerimage\footnote{\url{https://hub.docker.com/_/mariadb}} genutzt wurde. \subsection{Weitere Open Source Software} Eine weitere Bibliothek die für die Authentifizierung benutzt wird ist die Java-JWT Implementation von Auth0. Sowie die H2 In-Memory Datenbank. Diese zweite Datenbank wird während der Entwicklung genutzt, um schnell homogene Beispieldaten zu laden und Tests auf diesen durchzuführen. \subsection{Spezielles Setup} Um produktiv zu Arbeiten mussten noch weitere Tools genutzt werden. Dazu zählt primär die IntelliJ IDEA Ultimate Entwicklungsumgebung\footnote{\url{https://www.jetbrains.com/de-de/idea/}}. Diese IDE hat sehr viele Integrationen für das Spring Framework, als auch mit unseren Docker-Setup. Es wird dadurch möglich ausschließlich in der IDE zu arbeiten, ohne weitere Kommandozeilenfenster. Das Zweite wichtige Programm war der REST-Client Insomnia REST\footnote{\url{https://insomnia.rest/}}, welcher alle Möglichkeiten bietet, um REST APIs zu testen und Testabfragen auszuführen. \section{Umsetzung} \subsection{Spring Entities} \begin{figure}[H] \centering \includegraphics[width=\linewidth]{img/backend/er-modell.png} \caption{ER-Modell} \label{fig:er-modell} \end{figure} Das ER-Modell in Abbildung \ref{fig:er-modell} zeigt die komplette Hierarchie wie sie unserem Konzept entspricht. Wir legen diese Definition aber nicht selbst in SQL an, sondern lassen Java Hibernate dies für uns tun. Die Grundstruktur der gespeicherten Daten ist wie folgt zu verstehen: \begin{itemize} \item Der \textbf{TimetrackUser} ist die Grundstruktur, die alle anderen Daten des Users zusammenhält. Sie speichert allgemeine Nutzerdaten und hält Referenzen auf die \textbf{Role} des Nutzers, seine \textbf{Location} und alle im gehörenden \textbf{TimetrackAccounts}. \item Die \textbf{Role} sollte ursprünglich erlauben zwischen eines Admins und eines normalen Nutzers zu unterscheiden, aus Zeitgründen wurde dies aber weggelassen. Die Grundstruktur ist dennoch implementiert, allerdings so, dass jeder Nutzer automatisch Administrator ist. \item Die \textbf{Location} Entität speichert den Geofence des Nutzers. Diese Daten werden ausschließlich von der Android App genutzt um beim Einloggen den Geofence zu setzen. \item Der \textbf{TimetrackAccount} ist die zweite große Struktur, die alle \textbf{TimeRecords} des Nutzers verwaltet, jeder Nutzer kann mehrere \textbf{TimetrackAccounts} besitzen, aber jeder Account kann nur einem Nutzer gehören. \item Jede getrackte Zeitspanne wird in einem \textbf{TimeRecord} abgespeichert. Dieser Record speichert einen Typ sowie das Start- und Enddatum. Der Typ kann entweder "PAID" oder "BREAK" sein. Jeder Record gehört zu genau einem TimetrackAccount. \end{itemize} Die Umsetzung in Java wird nun am Beispiel des TimetrackUsers und des TimetrackAccounts gezeigt. \lstinputlisting[language=Java,caption=TimetrackUser,firstline=12]{../backend/src/main/java/de/hft/geotime/entities/TimetrackUser.java} Die komplette Klasse ist durch die Lombok Integration sehr klein gehalten. Alles weitere wird durch Annotationen geregelt, einige Beispiele sind hier: \begin{itemize} \item[] \textbf{@Entity} markiert die Klasse als Speicherbar in der Datenbank. \item[] \textbf{@ManyToOne} markiert das Attribut als Fremdschlüssenrelation aus einer anderen Tabelle. \item[] \textbf{@Id} zeichnet des Primärschlüssel der Tabelle aus. \item[] \textbf{@Column} setzt spezielle Attribute für die Spalte in der Datenbank. \end{itemize} Die TimetrackAccounts haben zusätzlich noch die Eigenschaft, dass sie sich selbst rekursiv löschen wenn der zugehörige User gelöscht wird. Selbiges gilt auch für die Records, wenn der zugehörige Account gelöscht wird. \lstinputlisting[language=Java,caption=TimetrackAccount,firstline=12]{../backend/src/main/java/de/hft/geotime/entities/TimetrackAccount.java} \subsection{Sicherheit durch JWT} Da wird die Web App im laufe des Projekts auch öffentlich in Internet stellen mussten, war eine Art Authentifizierung so gut wie unumgänglich. Damit wird keine Probleme mit Session-Affinity haben, entschieden wir uns für eine Token-Based Authentifizierung. Bei der genauen Implementation handelt es sich hier um das Json Web Token, kurz JWT. \begin{figure}[H] \centering \includegraphics[width=\linewidth]{img/backend/jwt.io.png} \caption{Aufbau eines JWT} \label{fig:aufbau-jwt} \end{figure} In Abbildung \ref{fig:aufbau-jwt} ist ein exemplarischer Aufbau eines JWT dargestellt. Das JWT besteht grundsätzlich aus drei Teilbereichen: \begin{enumerate} \item \textbf{Rot hinterlegt:} Bei diesem Teil handelt es sich um den Header, dieser beinhaltet den Typ des Tokens, als auch den Algorithmus mit dem es verschlüsselt wurde. \item \textbf{Lila hinterlegt:} In diesem Teil werden die eigentlichen Nutzdaten des Tokens abgelegt, dort können z.B. Nutzernamen oder Nutzer-Id sowie eine Rolle hinterlegt werden. \item \textbf{Blau hinterlegt:} Der letzte Part ist dann noch die Signatur des Tokens. \end{enumerate} Jeder dieser Teile ist durch einen Punkt im Token abgetrennt. Es ist daher nicht wunderlich, dass alle Token das selbe Präfix haben werden und nur der Mittelteil, sowie die Signatur sich ändern. Die Implementation in Spring Boot gelang in drei, vergleichsweise einfachen, Schritten. Zunächst mussten einige Konstanten definiert werden, zur einfacheren Handhabung wurde auch das Secret in den Code platziert. Dieses könnte aber sehr leicht über eine Umgebungsvariable überschrieben werden. \lstinputlisting[language=Java,caption=JWT Security Constants]{../backend/src/main/java/de/hft/geotime/security/SecurityConstants.java} Die Lebensdauer eines Tokens wurde mit 10 Tagen ebenfalls sehr hoch gewählt, um die Entwicklung zu vereinfachen. Auch muss dem Token zur erfolgreichen Nutzung in anderen Systemen das Prefix "Bearer " vorangestellt werden. Um nun die Tokens in Java zu erzeugen und Abzugleichen, musste die Filterkette von Spring Boot, welche bei jeden Request durchlaufen wird, bearbeitet werden. Jeder Endpunkt außer "/login" und "/sign-up" benötigten ab diesen Zeitpunkt eine autorisierte Anfrage. \lstinputlisting[language=Java,linerange={30-48},caption=JWT Authentication Filter,label=code:jwt-authentication-parse]{../backend/src/main/java/de/hft/geotime/security/JWTAuthenticationFilter.java} In Listing \ref{code:jwt-authentication-parse} ist der Schritt zu sehen, der die ankommende Anfrage versucht in eine Loginanfrage zu parsen. Diese Anfrage wird dann in der Filterkette weitergereicht. Bis Sie zum UserDetailsService kommt, welcher den User in der Datenbank abfragt und auch das Password abgleicht. Sollte die interne Autorisation erfolgreich sein, wird dieses Objekt mit den Nutzerdaten wieder an die Filterkette zurückgegeben und landet schließlich bei Listing \ref{code:jwt-authentication-create}. \lstinputlisting[language=Java,linerange={50-62},caption=JWT Authentication Filter,label=code:jwt-authentication-create]{../backend/src/main/java/de/hft/geotime/security/JWTAuthenticationFilter.java} Der letzte Schritt ist dann nur noch das Token mit den erhaltenen Daten zu befüllen und dann den "Authorization" Header der Antwort auf das soeben erstelle Token zu setzen. Ab jetzt kann sich der Client der das Token angefragt hat für die nächsten 10 Tage damit authentifizieren. Dies läuft sehr ähnlich ab, deshalb hier nur sehr kurz dargestellt. \lstinputlisting[language=Java,linerange={40-55},caption=JWT Authorization Filter,label=code:jwt-authorization]{../backend/src/main/java/de/hft/geotime/security/JWTAuthorizationFilter.java} Der eingehende Request geht wieder durch die Filterkette und wenn er an dem Filter in Listing \ref{code:jwt-authorization} ankommt, wird der User extrahiert und später im Security Manager als Autorisation für diesen Request gesetzt. Wichtig ist hier, dass keine weitere Prüfung auf die Existenz des Users durchgeführt wird, auch das Password wird nicht nochmal abgefragt. Der Grund hierfür ist, wenn es den User nicht geben würde, wie käme er dann an das Token? \subsection{Repositories} \subsection{Projections} \section{Endpoints} \subsection{HAL und Paging} \section{Probleme und Lösungen} \section{Deployment}