summaryrefslogtreecommitdiff
path: root/10-entwurfsheft/sections/apidoc.tex
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/apidoc.tex
Initial commitHEADmain
Diffstat (limited to '10-entwurfsheft/sections/apidoc.tex')
-rw-r--r--10-entwurfsheft/sections/apidoc.tex558
1 files changed, 558 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}
+