diff options
Diffstat (limited to '00-pflichtenheft/sections')
-rw-r--r-- | 00-pflichtenheft/sections/2-produkteinsatz.tex | 73 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/TikzPictures/ActivityLogin.tex | 56 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/TikzPictures/ActivityRegister.tex | 60 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/TikzPictures/ActivityResetPass.tex | 70 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/TikzPictures/SequenceSynchroniseSubscription.tex | 79 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/TikzPictures/UseCaseUML.tex | 46 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/anforderungsanalyse.tex | 219 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/benutzeroberflaeche.tex | 183 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/einleitung.tex | 34 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/glossar.tex | 272 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/produktdaten.tex | 83 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/produktfunktionen.tex | 215 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/produktuebersicht.tex | 184 | ||||
-rw-r--r-- | 00-pflichtenheft/sections/tests.tex | 605 |
14 files changed, 2179 insertions, 0 deletions
diff --git a/00-pflichtenheft/sections/2-produkteinsatz.tex b/00-pflichtenheft/sections/2-produkteinsatz.tex new file mode 100644 index 0000000..2d98e82 --- /dev/null +++ b/00-pflichtenheft/sections/2-produkteinsatz.tex @@ -0,0 +1,73 @@ +\section{Produkteinsatz} + +Im Folgenden werden Anwendungsbereiche, Zielgruppen und Betriebsbedingungen des +Produkts geschildert. + +\subsection{Anwendungsbereiche} + +Der \Gls{podcast}-Synchronisationsserver dient dazu, +Betreibern von \Glspl{podcatcher} einen performanteren und schlankeren +Synchronisationsdienst zur Verfügung zu stellen, als aktuell erhältliche Synchronisationsserver. +Die Nutzer erhalten außerdem eine einfach zu bedienende und übersichtliche Möglichkeit, +ihre abonnierten \Glspl{podcast} über mehrere Geräte hinweg synchronisieren zu können. + +Damit das Produkt seinen Ansprüchen in Sachen Performanz und Nutzerfreundlichkeit +gerecht werden kann, wird ausdrücklich auf Features, die nicht zur Kernaufgabe gehören, +was die Synchronisation von \Glspl{podcast} ist, verzichtet. +Dazu gehören zum Beispiel Funktionalitäten, wie das Suchen von \Glspl{podcast} oder das +Anhören von \Glspl{episode}, welche nicht bereitgestellt werden. +Außerdem werden keine extra Konfigurationsmöglichkeiten für die Synchronisation angeboten. + +Es wird eine Schnittstelle in Form einer graphischen Weboberfläche +bereitgestellt, mithilfe welcher der Nutzer seinen Account verwalten und +synchronisierte \Glspl{podcast} einsehen kann. +Für die Synchronisation wird der Account mit einer oder mehreren \Gls{podcatcher}-Applikationen +verknüpft. +Dadurch werden lokal gespeicherte \Glspl{abo} und Abhörfortschritte auf den +Account und somit auf alle verknüpften \Gls{podcatcher} übertragen. + + +\subsection{Zielgruppen} +Zur Zielgruppe gehören Betreiber von \Gls{podcatcher}-Applikationen und deren Nutzer. +Durch den Synchronisationsserver können die Betreiber ihren Nutzern eine +schlanke und einfach bedienbare Möglichkeit zum Synchronisieren ihrer abonnierten +\Glspl{podcast} bieten. + +\subsection{Betriebsbedingungen} +Es müssen folgende Voraussetzungen auf Server- und Nutzerseite erfüllt sein. + +%\newcommand{\tabitem}{\vspace{.1cm}~~\llap{\textbullet}~~} +%\begin{tabular}{l l} +% Server: & Nutzer: \\ +% % \hline +% \tabitem Internetanbindung & +% \tabitem Internetanbindung \\ +% \tabitem Speicherplatz: mind. 12GB & +% \tabitem Aktueller Webbrowser \\ +% \tabitem Arbeitsspeicher: mind. 2GB & +% \tabitem \Gls{podcatcher} mit \Gls{gpodder} Unterstützung \\ +% \tabitem CPU: mind. 2 Kerne & \\ +% \tabitem JVM-Fähig (\Gls{java} 17) & \\ +% \tabitem MariaDB-Fähig (MariaDB Server 10.6) & \\ +%\end{tabular} + +\begin{multicols}{2} +Server: +\begin{itemize} + \item Speicherplatz: mind. 12GB + \item Arbeitsspeicher: mind. 2GB + \item CPU: mind. 2 Kerne + \item JVM-Fähig (\Gls{java} 17) + \item MariaDB-Fähig \\ (MariaDB Server 10.6) +\end{itemize} +\columnbreak +Nutzer: +\begin{itemize} + \item Internetanbindung + \item Aktueller Webbrowser + \item \Gls{podcatcher} mit \Gls{gpodder} Unterstützung + \item[] + \item[] +\end{itemize} +\end{multicols} + diff --git a/00-pflichtenheft/sections/TikzPictures/ActivityLogin.tex b/00-pflichtenheft/sections/TikzPictures/ActivityLogin.tex new file mode 100644 index 0000000..701eeef --- /dev/null +++ b/00-pflichtenheft/sections/TikzPictures/ActivityLogin.tex @@ -0,0 +1,56 @@ +\begin{tikzpicture} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Nodeklassen für Aktivitätsdiagramm festlegen: % + %-------------------------------------------------------------------------------% + % start - Schwarzer ausgefüllter Kreis % + % activity - Abgerundetes Rechteck für Aktivitäten des Users % + % actBox - Rechteck für Reaktionen des Systems % + % decision - Karokästchen für Entscheidungen / Abzweigungen % + % end - Zielscheibe für das Ende der Aktivität % + %-------------------------------------------------------------------------------% + % Siehe: https://www-kseta.ttp.kit.edu/fellows/Tanja.Harbaum/tikz_tutorial.pdf % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \tikzset{start/.style={circle,minimum width=0.3cm,minimum height=0.3cm,draw,fill}} + \tikzset{activity/.style={rectangle,minimum width=1cm,minimum height=0.5cm,rounded corners=5pt,draw,align=center}} + \tikzset{actBox/.style={rectangle,minimum width=1cm,minimum height=0.5cm,draw,align=center}} + \tikzset{decision/.style={diamond,minimum width=1cm,minimum height=1cm,draw,align=center}} + \tikzset{end/.style={draw,double=white,circle,inner sep=1pt,minimum width=0.3cm,minimum height=0.3cm,draw,fill}} + + % Nodes und deren Position (voneinander abhängig) angeben + \node[start] (Start) {}; + \node[activity, right = of Start] (Aufruf) {Website aufrufen}; + \node[actBox, right = of Aufruf] (Login) {Login page}; + \node[decision, right = of Login] (Remembered) {Gemerkt?}; + \node[decision, below left = of Remembered] (RemEnd1) {}; + \node[activity, below = of RemEnd1] (Input) {E-Mail und\\ Passwort eingeben}; + \node[activity, below = of Input] (RememberOpt) {Option \string"Passwort merken\string"\\ aus-/abwählen}; + \node[activity, below = of RememberOpt] (LoginPress) {\string"Anmelden\string"-Button\\ drücken}; + \node[actBox, left = of LoginPress] (ErrorBox) {Fehlermeldung}; + \node[decision, below = of LoginPress] (CorrectEntry) {Korrekte\\ Eingabe?}; + \node[actBox, right = of CorrectEntry] (DashboardShow) {Dashboard\\ der Website}; + \path[name path=P1] (Remembered.south east) -| (DashboardShow); + \path[name path=P2] (RemEnd1.north east) -| (DashboardShow); + \node[end, below = of DashboardShow] (End) {}; + \coordinate (jump1) at (DashboardShow |- RemEnd1){}; + \draw($(Start.north west)+(-1,2)$) rectangle ($(End.south east)+(2,-1)$); + \path ($(Start.north west)+(-1,1.3)$) -- ($(Start -| End)+(2,1.3)$) node[midway]{\Large \textbf{Anmeldung}}; + + % Verbindungen zwischen den Nodes + + \draw[-stealth, thick](Start) -- (Aufruf); + \draw[-stealth, thick](Aufruf) -- (Login); + \draw[-stealth, thick](Login) -- (Remembered); + \draw[-stealth, thick](Remembered) -- node[left = 2mm, very near start]{nein} (RemEnd1); + \draw[-stealth, thick](Remembered.south east) -- (jump1) node[right = 2mm, near start]{ja} -- (DashboardShow); + \draw[-stealth, thick](RemEnd1) -- (Input); + \draw[-stealth, thick](Input) -- (RememberOpt); + \draw[-stealth, thick](RememberOpt) -- (LoginPress); + \draw[-stealth, thick](LoginPress) -- (CorrectEntry); + \draw[-stealth, thick](CorrectEntry) -| node[above, very near start]{falsch} (ErrorBox); + \draw[-stealth, thick](ErrorBox) |- (RemEnd1); + \draw[-stealth, thick](CorrectEntry) -- node[above, midway]{wahr} (DashboardShow); + \draw[-stealth, thick](DashboardShow) -- (End); + +\end{tikzpicture}
\ No newline at end of file diff --git a/00-pflichtenheft/sections/TikzPictures/ActivityRegister.tex b/00-pflichtenheft/sections/TikzPictures/ActivityRegister.tex new file mode 100644 index 0000000..b50bafe --- /dev/null +++ b/00-pflichtenheft/sections/TikzPictures/ActivityRegister.tex @@ -0,0 +1,60 @@ +\begin{tikzpicture} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Nodeklassen für Aktivitätsdiagramm festlegen: % + %-------------------------------------------------------------------------------% + % start - Schwarzer ausgefüllter Kreis % + % activity - Abgerundetes Rechteck für Aktivitäten des Users % + % actBox - Rechteck für Reaktionen des Systems % + % decision - Karokästchen für Entscheidungen / Abzweigungen % + % end - Zielscheibe für das Ende der Aktivität % + %-------------------------------------------------------------------------------% + % Siehe: https://www-kseta.ttp.kit.edu/fellows/Tanja.Harbaum/tikz_tutorial.pdf % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \tikzset{start/.style={circle,minimum width=0.3cm,minimum height=0.3cm,draw,fill}} + \tikzset{activity/.style={rectangle,minimum width=1cm,minimum height=0.5cm,rounded corners=5pt,draw,align=center}} + \tikzset{actBox/.style={rectangle,minimum width=1cm,minimum height=0.5cm,draw,align=center}} + \tikzset{decision/.style={diamond,minimum width=1cm,minimum height=1cm,draw,align=center}} + \tikzset{end/.style={draw,double=white,circle,inner sep=1pt,minimum width=0.3cm,minimum height=0.3cm,draw,fill}} + + % Nodes und deren Position (voneinander abhängig) angeben + \node[start] (Start) {}; + \node[activity, right = of Start] (Aufruf) {Website aufrufen}; + \node[actBox, right = of Aufruf] (Login1) {Login page}; + \node[activity, below = of Login1] (RegOpt) {\string"Registrieren\string"-Option\\ auswählen}; + \node[actBox, below = of RegOpt] (Registrieren) {Registrierungsfenster}; + \node[decision, below = of Registrieren] (EmailTakenEnd) {}; + \node[activity, below = of EmailTakenEnd] (Input) {E-Mail-Adresse und\\ zweimal neues\\ Passwort eingeben}; + \node[activity, below = of Input] (RegPress) {\string"Registrieren\string"-Button\\ drücken}; + \node[decision, left = of RegPress] (EmailTaken) {E-Mail\\ vergeben?}; + \node[actBox] (Error1) at (EmailTaken |- EmailTakenEnd) {Fehlermeldung}; + \node[actBox, below = of EmailTaken] (Confirm) {E-Mail mit Link\\ zur Verifizierung}; + \node[activity, below = of Confirm] (LinkClick) {Link\\ anklicken}; + \node[decision, right = of LinkClick] (LinkTime) {Link älter\\ als 24h?}; + \node[actBox, right = 2cm of LinkTime] (Error2) {Fehler}; + \node[actBox, below = 1.5cm of LinkTime] (Login2) {Login Page}; + \node[end] (End) at (Error2 |- Login2) {}; + \draw ($(Start.north west)+(-2,2)$) rectangle ($(End.south east)+(2,-1)$); + \path ($(Start.north west)+(-2,1.4)$) -- ($(Start -| Error2)+(2,1.4)$) node[midway]{\Large \textbf{Registrieren}}; + + % Verbindungen zwischen den Nodes + \draw[-stealth, thick](Start) -- (Aufruf); + \draw[-stealth, thick](Aufruf) -- (Login1); + \draw[-stealth, thick](Login1) -- (RegOpt); + \draw[-stealth, thick](RegOpt) -- (Registrieren); + \draw[-stealth, thick](Registrieren) -- (EmailTakenEnd); + \draw[-stealth, thick](EmailTakenEnd) -- (Input); + \draw[-stealth, thick](Input) -- (RegPress); + \draw[-stealth, thick](RegPress) -- (EmailTaken); + \draw[-stealth, thick](EmailTaken) -- node[left, near start]{ja} (Error1); + \draw[-stealth, thick](Error1) -- (EmailTakenEnd); + \draw[-stealth, thick](EmailTaken) -- node[left, near start]{nein} (Confirm); + \draw[-stealth, thick](Confirm) -- (LinkClick); + \draw[-stealth, thick](LinkClick) -- (LinkTime); + \draw[-stealth, thick](LinkTime) -- node[above, near start]{ja} (Error2); + \draw[-stealth, thick](LinkTime) -- node[left, near start]{nein} (Login2); + \draw[-stealth, thick](Error2) -- (End); + \draw[-stealth, thick](Login2) -- (End); + +\end{tikzpicture}
\ No newline at end of file diff --git a/00-pflichtenheft/sections/TikzPictures/ActivityResetPass.tex b/00-pflichtenheft/sections/TikzPictures/ActivityResetPass.tex new file mode 100644 index 0000000..28a065c --- /dev/null +++ b/00-pflichtenheft/sections/TikzPictures/ActivityResetPass.tex @@ -0,0 +1,70 @@ +\begin{tikzpicture} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Nodeklassen für Aktivitätsdiagramm festlegen: % + %-------------------------------------------------------------------------------% + % start - Schwarzer ausgefüllter Kreis % + % activity - Abgerundetes Rechteck für Aktivitäten des Users % + % actBox - Rechteck für Reaktionen des Systems % + % decision - Karokästchen für Entscheidungen / Abzweigungen % + % end - Zielscheibe für das Ende der Aktivität % + %-------------------------------------------------------------------------------% + % Siehe: https://www-kseta.ttp.kit.edu/fellows/Tanja.Harbaum/tikz_tutorial.pdf % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \tikzset{start/.style={circle,minimum width=0.3cm,minimum height=0.3cm,draw,fill}} + \tikzset{activity/.style={rectangle,minimum width=1cm,minimum height=0.5cm,rounded corners=5pt,draw,align=center}} + \tikzset{actBox/.style={rectangle,minimum width=1cm,minimum height=0.5cm,draw,align=center}} + \tikzset{decision/.style={diamond,minimum width=1cm,minimum height=1cm,draw,align=center}} + \tikzset{end/.style={draw,double=white,circle,inner sep=1pt,minimum width=0.3cm,minimum height=0.3cm,draw,fill}} + + % Nodes und deren Position (voneinander abhängig) angeben + \node[start] (Start) {}; + \node[activity, right = of Start] (Aufruf) {Website aufrufen}; + \node[actBox, right = of Aufruf] (Login1) {Login page}; + \node[activity, below = of Login1] (ForgetOpt) {\string"Passwort vergessen\string"\\ Option auswählen}; + \node[actBox, below = of ForgetOpt] (Forget) {\string"Passwort vergessen\string"\\ Fenster}; + \node[decision, below = of Forget] (EmailDecEnd) {}; + \node[activity, below = of EmailDecEnd] (Input1) {E-Mail-Adresse\\ eingeben}; + \node[decision, left = of Input1] (EmailDec) {E-Mail\\ registriert?}; + \path (EmailDec) |- (EmailDecEnd) node[actBox, near end](Error2){Fehler}; + \node[actBox, below = of EmailDec] (SendMail) {E-Mail mit Link\\ zum Zurücksetzen\\ des Passworts}; + \node[activity, below = of SendMail] (LinkClick) {Empfangenen Link\\ öffnen}; + \node[decision, right = of LinkClick] (LinkTime) {Link älter\\ als 24h?}; + \node[actBox, above = of LinkTime] (Error) {Fehler}; + \node[end, right = of Error] (End1) {}; + \node[actBox, below = of LinkTime] (ResetWin) {\string"Passwort zurücksetzen\string"\\ Fenster}; + \node[decision, left = of ResetWin] (PswCorEnd) {}; + \node[activity, left = of PswCorEnd] (Input2) {neues Passwort\\ zweimal eingeben}; + \node[activity, below = 2cm of Input2] (ResetPress) {\string"Passwort zurücksetzen\string"-\\ Button drücken}; + \node[decision, right = of ResetPress] (PswCorrect) {Passwort\\ legal?}; + \node[actBox, right = of PswCorrect] (Login2) {Login page}; + \node[end, right = of Login2] (End2) {}; + \draw ($(Start.north west)+(-3,2)$) rectangle ($(End2.south east)+(1,-2)$); + \path ($(Start.north west)+(-3,1.4)$) -- ($(Start -| End2)+(1,1.4)$) node[midway]{\Large \textbf{Passwort vergessen}}; + + % Verbindungen zwischen den Nodes + \draw[-stealth, thick](Start) -- (Aufruf); + \draw[-stealth, thick](Aufruf) -- (Login1); + \draw[-stealth, thick](Login1) -- (ForgetOpt); + \draw[-stealth, thick](ForgetOpt) -- (Forget); + \draw[-stealth, thick](Forget) -- (EmailDecEnd); + \draw[-stealth, thick](EmailDecEnd) -- (Input1); + \draw[-stealth, thick](Input1) -- (EmailDec); + \draw[-stealth, thick](EmailDec) |- node[left, near start]{nein} (Error2); + \draw[-stealth, thick](Error2) -- (EmailDecEnd); + \draw[-stealth, thick](EmailDec) -- node[left, near start]{ja} (SendMail); + \draw[-stealth, thick](SendMail) -- (LinkClick); + \draw[-stealth, thick](LinkClick) -- (LinkTime); + \draw[-stealth, thick](LinkTime) -- node[left, near start]{ja} (Error); + \draw[-stealth, thick](Error) -- (End1); + \draw[-stealth, thick](LinkTime) -- node[left, near start]{nein} (ResetWin); + \draw[-stealth, thick](ResetWin) -- (PswCorEnd); + \draw[-stealth, thick](PswCorEnd) -- (Input2); + \draw[-stealth, thick](Input2) -- (ResetPress); + \draw[-stealth, thick](ResetPress) -- (PswCorrect); + \draw[-stealth, thick](PswCorrect.north west) -| (PswCorEnd) node[above, near start]{nein}; + \draw[-stealth, thick](PswCorrect) -- (Login2) node[above, near start]{ja}; + \draw[-stealth, thick](Login2) -- (End2); + +\end{tikzpicture}
\ No newline at end of file diff --git a/00-pflichtenheft/sections/TikzPictures/SequenceSynchroniseSubscription.tex b/00-pflichtenheft/sections/TikzPictures/SequenceSynchroniseSubscription.tex new file mode 100644 index 0000000..3e68555 --- /dev/null +++ b/00-pflichtenheft/sections/TikzPictures/SequenceSynchroniseSubscription.tex @@ -0,0 +1,79 @@ +%\begin{tikzpicture} +% +% \begin{umlseqdiag} +% +% \umlactor[no ddots]{Benutzer} +% \umlobject[no ddots]{Podcatcher1} +% \umlobject[no ddots]{Podcatcher2} +% \umlobject[no ddots]{Webfrontend} +% \umlobject[no ddots]{Server} +% +% \begin{umlcall}[dt=5, op=abonniere Podcast]{Benutzer}{Podcatcher1} +% \begin{umlcallself}[dt=8, op=füge Podcast zu Abos hinzu, type=synchron]{Podcatcher1} +% \end{umlcallself} +% \begin{umlcall}[op=lade Änderungen hoch]{Podcatcher1}{Server} +% \begin{umlcallself}[dt=8, op=speichere Änderungen]{Server} +% \end{umlcallself} +% \end{umlcall} +% \end{umlcall} +% +% \begin{umlcall}[dt=10, op=Abos anzeigen]{Benutzer}{Webfrontend} +% \begin{umlcall}[dt=5, op=hole Aboliste, return=Aboliste]{Webfrontend}{Server} +% \end{umlcall} +% \end{umlcall} +% +% \begin{umlcall}[dt=10, op=Abos anzeigen]{Benutzer}{Podcatcher2} +% \begin{umlcall}[dt=5, op=hole Aboliste, return=Aboliste]{Podcatcher2}{Server} +% \end{umlcall} +% \end{umlcall} +% +% \end{umlseqdiag} +% +%\end{tikzpicture} + +\begin{sequencediagram} + + \newthread{b}{Benutzer} + \newinst[2]{p1}{Podcatcher1} + \newinst{p2}{Podcatcher2} + \newinst[1]{w}{Webfrontend} + \newinst[1]{s}{Server} + + \begin{call}{b}{abonniere Podcast}{p1}{} + \begin{callself}{p1}{füge Podcasts zu Abos hinzu}{} + \begin{call}{p1}{lade Änderungen hoch}{s}{} + \begin{callself}{s}{\shortstack{speichere\\Änderungen\\persistent}}{} + \end{callself} + \end{call} + \end{callself} + \end{call} + + \begin{call}{b}{Abos anzeigen}{w}{} + \begin{call}{w}{hole Aboliste}{s}{Aboliste} + \end{call} + \end{call} + + \begin{call}{b}{Abos anzeigen}{p2}{} + \begin{call}{p2}{hole Aboliste}{s}{Aboliste} + \end{call} + \end{call} + +\end{sequencediagram} + + + + + + + + + + + + + + + + + + diff --git a/00-pflichtenheft/sections/TikzPictures/UseCaseUML.tex b/00-pflichtenheft/sections/TikzPictures/UseCaseUML.tex new file mode 100644 index 0000000..1bb2e2c --- /dev/null +++ b/00-pflichtenheft/sections/TikzPictures/UseCaseUML.tex @@ -0,0 +1,46 @@ +\begin{tikzpicture}%[trim left = 1cm] + + \begin{umlsystem}[x=5] {<<Website>> Podcast Sync Web} + \umlusecase[name=a,width=2.5cm] {Registrieren} + \umlusecase[name=c,y=-4,width=2.5cm] {Aktion ausführen} + \umlusecase[name=d,y=-6,width=2.5cm] {Anmelden} + \umlusecase[name=f,y=-2,width=2.5cm] {Sprache ändern (*)} + \umlusecase[name=g,x=6,y=-1,width=2.5cm] {Anleitung einsehen} + \umlusecase[name=h,x=6,y=-3,width=2.5cm] {Abonnierte Podcasts einsehen} + \umlusecase[name=i,x=6,y=-5,width=2.5cm] {Profil verwalten} + \umlusecase[name=r,x=6,y=-7.25,width=2.5cm] {Zuletzt angehörte\\ Episoden einsehen} + \umlusecase[name=j,x=6,y=-10.5,width=2.5cm] {Mit Google / anderen Anbietern anmelden (*)} + \umlusecase[name=k,x=4,y=-13,width=2.5cm] {Passwort vergessen} + \umlusecase[name=l,y=-15,width=2.5cm] {Admin Aktion ausführen (*)} + \umlusecase[name=m,x=8,y=-15,width=2.5cm] {Statistiken einsehen (*)} + \umlusecase[name=n,x=12,y=-4,width=2.5cm] {Passwort ändern} + \umlusecase[name=o,x=12,y=-2,width=2.5cm] {Gpodder verknüpfen (*)} + \umlusecase[name=p,x=12,y=-6,width=2.5cm] {Personenbezogene Daten abrufen (*)} + \umlusecase[name=q,x=12,y=-8,width=2.5cm] {Account löschen} + \end{umlsystem} + + \umlactor[y=-3] {User} + \umlactor[y=-15] {Admin} + + \umlinherit{Admin}{User} + + \umlassoc{User}{a} + \umlassoc{User}{c} + \umlassoc{User}{d} + \umlassoc{User}{f} + \umlassoc{Admin}{l} + + \umlextend{g}{c} + \umlextend{h}{c} + \umlextend{i}{c} + \umlextend{r}{c} + \umlextend{j}{d} + \umlextend{k}{d} + \umlextend{m}{l} + \umlinclude{c}{d} + \umlinclude{l}{d} + \umlextend{n}{i} + \umlextend{o}{i} + \umlextend{p}{i} + \umlextend{q}{i} +\end{tikzpicture}
\ No newline at end of file diff --git a/00-pflichtenheft/sections/anforderungsanalyse.tex b/00-pflichtenheft/sections/anforderungsanalyse.tex new file mode 100644 index 0000000..51be6c3 --- /dev/null +++ b/00-pflichtenheft/sections/anforderungsanalyse.tex @@ -0,0 +1,219 @@ +\newcommand{\newrequirementlist}[1]{ + % https://www.overleaf.com/learn/latex/Lists#Creating_a_new_list_with_enumitem + \newlist{#1list}{enumerate}{1} + \setlist[#1list, 1] + { + before=\leavevmode, + label=\upshape\textlangle #1\arabic*\textrangle, + ref=\upshape\textlangle #1\arabic*\textrangle, + resume=#1list + } + } + +\newrequirementlist{RM} +\newrequirementlist{RS} +\newrequirementlist{RC} +\newrequirementlist{RW} + +\section{Anforderungsanalyse} + +\subsection{ Musskriterien } + +Musskriterien: unabdingbare Leistungen der Software. + +\subsubsection*{ Funktionale Anforderungen } + +\begin{RMlist} + \item\label{r:login} Der Benutzer kann sich im Webfrontend mit einer + E-Mail-Adresse und einem Pass\-wort erstmalig registrieren und bei + abgeschlossener Registrierung fortan mit denselben Informationen + anmelden. + Für eine erfolgreiche Registrierung muss die angegebene + E-Mail-Adresse zuerst verifiziert werden.\\ + \emph{Tests: \ref{t:register}, \ref{t:login}} + \item\label{r:store} Die Liste der \Glspl{abo} eines Benutzers sowie + der zeitliche Fortschritt beim Anhören(/Ansehen) von jeder begonnen + \Gls{episode} werden für jeden Benutzer gespeichert. + \item\label{r:sync} Die Liste der \Glspl{abo} eines Benutzers + sowie der zeitliche Fortschritt beim Anhören(/Ansehen) von jeder + begonnenen \Gls{episode} wird automatisch über alle von einem Benutzer + verknüpften \Gls{podcatcher}n aktualisiert. + Dabei sind der zu synchronisierende Stand der \Glspl{abo} und der + zeitliche Fortschritt jeweils definiert als derjenige Stand, der + zeitlich am kürzesten zurückliegt.\\ + \emph{Tests: \ref{t:sync-sub}, \ref{t:sync-unsub}, \ref{t:sync-episode}} + \item\label{r:ui} Das Webfrontend bietet dem Benutzer eine graphische + Benutzeroberfläche zur Navigation und zur Ansteuerung einzelner + Funktionalitäten.\\ + \emph{Implizit durch alle Testfälle geprüft.} + \item\label{r:reset-pw} Der Benutzer kann sein Passwort ändern und es + gibt eine ,,Passwort vergessen''-Funktion. + So kann ein angemeldeter Benutzer sein Passwort direkt im Webfrontend + ändern. + Im nicht angemeldeten Zustand kann der Benutzer sein Passwort über + die registrierte E-Mail-Adresse zurücksetzen.\\ + \emph{Tests: \ref{t:change-pw}, \ref{t:forgot-pw}} + \item\label{r:show-podcasts} Das Webfrontend bietet dem Benutzer die + Möglichkeit, sich die Liste seiner \Glspl{abo} anzeigen zu + lassen. + Die dabei dargestellten Informationen beinhalten den Namen des + \Glspl{abo} und eine gerundete Angabe darüber, wie lange es her ist, + dass der Benutzer das letzte Mal eine \Gls{episode} dieses \Glspl{abo} + konsumiert hat.\\ + \emph{Tests: \ref{t:sync-sub}, \ref{t:sync-unsub}} +\end{RMlist} + +\subsubsection*{ Nicht-funktionale Anforderungen } + +\begin{RMlist} + \item\label{r:requests} Der Synchronisations-Server kann mindestens + 50 Anfragen pro Sekunde verarbeiten.\\ + \emph{Test: \ref{t:lasttest}} + \item\label{r:desktop-first} Das Webfrontend ist primär für + Desktop-Benutzer ausgelegt. + \item\label{r:gpodder} Der Datenaustausch erfolgt über die Gpodder + \Gls{rest-api} unter Verwendung des Datenformats \Gls{json}. + \item\label{r:persistent-storage} Die Speicherung der Daten eines + Benutzers \ref{r:store} über den Synchronisations-Server erfolgt + persistent in einer \Gls{db}. Diese Daten des Benutzers sind die + Liste seiner \Glspl{abo} und der zeitliche Fortschritt beim Anhören + (/Ansehen) aller begonnenen \Glspl{episode}. + \item\label{r:api-extension} Die \Gls{gpodder} wird um Funktionalitäten + zur verbesserten Kommunikation zwischen Front- und Backend erweitert + (siehe \ref{r:login}).\\ +\end{RMlist} + + +\subsection{ Sollkriterien } + +Sollkriterien: erstrebenswerte Leistungen. + +\subsubsection*{ Funktionale Anforderungen } + +\begin{RSlist} + \item\label{r:man} Das Webfrontend bietet die Möglichkeit eine nicht + ausgefüllte Benutzeranleitung für das Synchronisieren von \Glspl{podcast} + anzuzeigen (Abbildung \ref{fig:help-desktop}).\\ + \emph{Test: \ref{t:man}} + \item\label{r:delete-acc} Der Benutzer kann seinen Account löschen. + Daraufhin werden alle auf diesen Benutzer bezogenen Daten gelöscht.\\ + \emph{Test: \ref{t:delete-acc}} +\end{RSlist} + +\subsubsection*{ Nicht-funktionale Anforderungen } + +\begin{RSlist} +\item\label{r:backend-libs} Das Backend wird in \Gls{java} unter Verwendung des + quelloffenen Frameworks Spring implementiert. Weiter wird für die + \Gls{db} das relationale Open-Source Datenbankverwaltungssystem MariaDB + eingesetzt. + \item\label{r:ui-libs} Die Weboberfläche wird mithilfe der + \Gls{ui-lib} React oder des Webframeworks Vue in JavaScript und + mit dem Frontend-CSS-Framework Bootstrap entwickelt. + \item\label{r:ui-source} + Verwendete \Glspl{ui-lib} werden von einem \Gls{packagemanager}, wie dem Node + Package Manager (npm) bezogen. Ein \Gls{bundler}, wie vite oder Webpack, + stellt ein minimiertes Skript von den Teilen der Bibliotheken zusammen, + die vom Code verwendet werden. Das minimierte Skript wird dann auf einem + eigenen Server für die Weboberfläche bereitgestellt. + \item\label{r:spa} Die Weboberfläche wird als \Gls{spa} + entworfen und aktualisiert dynamisch ihren Inhalt, sobald es eine + Antwort auf eine Anfrage an die \Gls{gpodder} \ref{r:api-compat} erhält. + \item\label{r:parse-metadata} Das Backend kann die Metadaten von + \Gls{podcast} aus + deren \Gls{rss}-Feeds (XML-Dateien) für die Anzeige im Webfrontend + \ref{r:show-podcasts} parsen. + \item\label{r:pw-requirements} Verwendete Passwörter müssen mindestens 8 Zeichen, + ein Sonderzeichen, eine Zahl sowie einen Klein- und einen Großbuchstaben + enthalten. + Diese Anforderungen gelten also insbesondere für über die Funktionen + \ref{r:login} und \ref{r:reset-pw} neu gewählte Passwörter.\\ + \emph{Test: \ref{t:pw-req}} + \item\label{r:save-pw} Passwörter werden sicher mittels \Gls{salt-hash} + gespeichert. + \item\label{r:session} Im Webfrontend angemeldete Benutzer bleiben dort + angemeldet. Hierfür wird ein \Gls{session-token} in einem \Gls{cookie} gespeichert.\\ +\end{RSlist} + +\subsection{ Kannkriterien } + +Kannkriterien: Leistungen, die enthalten sein können. + +\subsubsection*{ Funktionale Anforderungen } + +\begin{RClist} + \item\label{r:subscribe} Ein Benutzer kann über die Weboberfläche einen + abonnierten \Gls{podcast} über einen generierten Link teilen. + Öffnet nun ein anderer Nutzer den Link wird dieser zur Weboberfläche + weitergeleitet und mit einem Pop-up gefragt, ob dieser den + \Gls{podcast} abonnieren + möchte, falls noch nicht geschehen. + Akzeptiert der Nutzer, so wird der \Gls{podcast} zur Liste der + \Glspl{abo} des + Nutzers hinzugefügt. + Gegebenenfalls muss sich der Benutzer dafür zuerst anmelden. + Der Link setzt sich dabei unter anderem aus der URL des Webfrontends oder + einem \Gls{pseudoprotocol} und dem \Gls{podcast}-Link des Providers zusammen. + \item\label{r:unsubscribe} Das Webfrontend bietet dem Benutzer die Möglichkeit, + \Glspl{abo} zu entfernen beziehungsweise \Glspl{podcast} zu deabonnieren. + \item\label{r:import} Das Importieren und Exportieren aller benutzerbezogenen + Daten wird unterstützt (siehe \ref{r:dsgvo}). + \item\label{r:import-other} Das Umsiedeln von anderen Gpodder-Plattformen und + damit insbesondere der damit verbundene Datenimport wird unterstützt. + \item\label{r:api-compat} Die Weboberfläche ist kompatibel mit beliebigen + \Glspl{gpodder}. + \item\label{r:responsive} Die Weboberfläche ist \gls{responsive}. + \item\label{r:admin} Es gibt Administrator Benutzerkonten. Eine angestrebte + Funktionalität dieser privilegierten Konten ist das Einsehen von Statistiken, + wie der Anzahl von Benutzern, und dem Abruf der Metadaten eines + \Glspl{abo}. +\end{RClist} + +\subsubsection*{ Nicht-funktionale Anforderungen } + +\begin{RClist} + \item\label{r:login-provider} Die Anmeldung im Webfrontend kann mit dem + offenen Protokoll \Gls{oauth} 2.0 über Google, Apple oder Facebook erfolgen. + Die bei der Verknüpfung eines \Gls{podcatcher}s mit dem Synchronisationsserver + geforderten Anmeldedaten werden dann automatisch für den betreffenden + Benutzer generiert. + Diese kann er im Webfrontend einsehen. + \item\label{r:live-update} Im Webfrontend angemeldete Benutzer bleiben dort + angemeldet, wenn das Backend ein Update bekommt. + \item\label{r:language} Die Benutzeroberfläche kann in mehreren Sprachen + angezeigt werden, wobei neben der standardmäßig deutschen + Benutzeroberfläche die zusätzliche Bereitstellung einer englischen + Version gegenüber anderen Fremdsprachen priorisiert angestrebt wird. + \item\label{r:dsgvo} Der Umgang mit personenbezogenen Daten ist konform mit + der \\\Gls{dsgvo} der Europäischen Union. + \item\label{r:docker} Die Benutzung von \Gls{docker} vereinfacht das Deployment auf + einen Server, da Abhängigkeiten bereits im \Gls{docker}-Image enthalten sind. + Außerdem bleibt bei einer Kompromittierung der Software das Host-System + durch Virtualisierung der Container sicher.\\ +\end{RClist} + +\subsection{ Abgrenzungskriterien } + +Abgrenzungskriterien: Leistungen, die explizit nicht umgesetzt werden. + +\begin{RWlist} + \item\label{r:playback} Das Webfrontend stellt explizit keine Funktionalität + zum Anhören von \Glspl{podcast} bereit und grenzt sich unter anderem dadurch + von \Gls{podcatcher}-Software ab. + \item\label{r:no-logs} Es werden explizit keine Logdateien für Benutzer-Aktionen + gespeichert. Stattdessen wird nur genau die Liste der \Glspl{abo} eines + Benutzers und der zeitliche Fortschritt jeder \Gls{episode} aktuell gehalten. + \item\label{r:no-devices} Die benutzerdefinierte Synchronisation über + verschiedene, für die Synchronisation differenzierte Geräte wird nicht + unterstützt. + Das heißt, die gespeicherten Daten eines Benutzers werden über alle + mit seinem Account verbundenen \Gls{podcatcher} unabhängig vom Gerät auf den + gleichen, letzten Stand synchronisiert. + \item\label{r:discovery} Das Webfrontend bietet keine Funktionalität zum + Suchen von \Glspl{podcast} (\Gls{discovery}) an. + \item\label{r:no-man} Im Webfrontend wird lediglich die Möglichkeit geboten, + eine zunächst leere Benutzeranleitung \ref{r:man} anzuzeigen. Eine + inhaltlich vollständig ausgeschriebene Benutzeranleitung wird + ausdrücklich nicht bereitgestellt. +\end{RWlist} + diff --git a/00-pflichtenheft/sections/benutzeroberflaeche.tex b/00-pflichtenheft/sections/benutzeroberflaeche.tex new file mode 100644 index 0000000..536ed04 --- /dev/null +++ b/00-pflichtenheft/sections/benutzeroberflaeche.tex @@ -0,0 +1,183 @@ +\section{Benutzeroberfläche} + +Die Synchronisation der \Glspl{podcast} soll über eine Weboberfläche verwalten werden. +Dazu wird eine \Gls{spa} erstellt. Diese kann durch ein +\Gls{responsive}-Design für Desktop- und Mobilgeräte nutzerfreundlich angezeigt +werden. + +Die Navigation erfolgt über eine Navigationsleiste, welche auf jeder +nutzerbezogenen Seite zu sehen ist. Über die Navigationsleiste können über +Knöpfe alle anderen nutzerbezogenen Seiten aufgerufen werden. Über ein +Dropdown-Menu werden Accounteinstellungen und ein Logout-Knopf sichtbar (siehe +Abbildung \ref{fig:listening-progress-account-dropdown}). Ein weiters +Dropdown-Menu erlaubt das Wechseln der Sprache (siehe Abbildung +\ref{fig:podcast-desktop-change-language}). Der ,,Hilfe''-Eintrag öffnet ein +Fenster mit Hilfestellungen (siehe Abbildung \ref{fig:help-desktop}). Durch das +\Gls{responsive}-Design kann die Navigations-Leiste auf Mobilgeräten sich zu +einem Burger-Menu zusammenklappen. + +Die Komponenten der Weboberfläche werden von einem Still-Framework, wie Bootstrap, +benutzt. + +% Übersichtlichkeit wichtig? + +% Webanwendung +% Single-Page-Application +% Responsive +% Navigationsleiste +% Bootstrap + +\subsection{Login} + +Bei der erstmaligen Nutzung des Services wird der Nutzer aufgefordert, sich neu +für die \Gls{podcast}-Synchronisation zu registrieren. Dabei gibt der Nutzer seine +E-Mail und ein Passwort ein. Daraufhin wird dem Nutzer eine E-Mail mit einem +Bestätigungslink an seine E-Mail-Adresse versandt. Erst wenn der Link angeklickt +wird, ist der Account freigeschaltet und der Nutzer wird zur Anmeldeseite +weitergeleitet (siehe Abbildung \ref{fig:login-mobile}). + +Alternativ kann der Nutzer sich auch mit einem Identifikationsbereitsteller, wie +Google oder Facebook registrieren und anmelden. + +Zusätzlich kann der Nutzer beim Anmelden über eine Checkbox einstellen, dass +dieser angemeldet bleiben möchte, sodass sich dieser beim nächsten Aufruf der +Weboberfläche nicht erneut anmelden muss. + +Nach dem Anmelden wird der Nutzer zur \Gls{podcast}-Liste weitergeleitet. + +% Registrieren +% E-Mail und Passwort, E-Mail bestätigung + +% anmelden mit E-Mail und Passwort oder es kann sich auch mit einem +% Identifikations-Bereitsteller (wie Google, Facebook, GitHub) angemeldet +% werden. + +% Angemeldet bleiben + +% Anschließlich auf der Startseite + +\subsection{Podcast-Liste} + +Die Seite der \Gls{podcast}-Liste zeigt eine Liste aller vom Nutzer abonnierten +\Glspl{podcast}. Diese sind danach sortiert, welcher \Gls{podcast} zuletzt +gehört wurde (siehe Abbildung \ref{fig:podcast-desktop-change-language}). + +\Glspl{podcast} können aufgeklappt werden, um \Glspl{episode} inklusive deren Hörfortschritt +anzuzeigen. Die \Glspl{episode} werden nach Veröffentlichungszeitpunkt sortiert. + +% Navigatinsleiste +% Zeigt eine Liste aller vom Nutzer abonnierten Podcasts sortiert nach welcher +% Podcast zuletzt gehört wurde. +% Podcasts können aufgeklappt werden, um Episoden inklusive deren Hörfortschritt +% anzuzueigen. Die Episoden werden nach Veröffentlichungszeitpunkt sortiert. + +\subsection{Zuletzt gehört} + +Die Seite ,,Zuletzt gehört'' zeigt eine Liste der vom Nutzer gehörten +\Glspl{episode} inklusive Hörfortschritt (siehe Abbildung +\ref{fig:listening-progress-account-dropdown}). Die \Glspl{episode} sind danach +sortiert wann sie zuletzt gehört wurden. + +Zusätzlich können die beendeten und angefangenen \Glspl{episode} über ein +Dropdown-Menu auch auf- und absteigend lexikografisch oder nach Hörfortschritt +sortiert werden. + +% \newpage + +\subsection{Einstellungen} + +Auf der Einstellungsseite darf der Nutzer sein Passwort ändern und seinen +Account löschen (siehe Abbildung \ref{fig:settings-mobile-1}). + +Der Nutzer kann seine personenbezogenen Daten, wie abonnierte \Glspl{podcast} und +Hörfortschritte, in eine Datei exportieren, welche der Nutzer herunterladen +kann. Außerdem kann der Nutzer zuvor heruntergeladene Exports wieder +importieren, um zum Beispiel alte abonnierte \Glspl{podcast} wiederherzustellen. + +Zusätzlich kann der Nutzer seine Daten von einer anderen \Gls{gpodder} importieren, +indem er sich in den Einstellungen auf der anderen \Gls{gpodder} anmeldet. + +% Passwort ändern +% Account löschen +% Daten importieren/exportieren +% Daten anderer Gpodder-API importieren + +% \vspace{1cm} + +%===================================================================================% +% https://tex.stackexchange.com/questions/55337/how-to-use-figure-inside-a-minipage % +%===================================================================================% +\hspace{-.5cm} +\begin{minipage}[H]{\linewidth} + %\centering + \begin{minipage}{0.32\linewidth} + \begin{figure}[H] + \fbox{\includegraphics[width=.9\linewidth]{assets/ui/login-mobile.png}} + \setcapindent*{1em} + \caption{Anmeldeseite mit Identitätsbereitsteller\\} + \label{fig:login-mobile} + \end{figure} + \end{minipage} +% \hspace{0.05\linewidth} + \begin{minipage}{0.32\linewidth} + \begin{figure}[H] + \fbox{\includegraphics[width=.9\linewidth]{assets/ui/podcasts-mobile.png}} + \setcapindent*{1em} + \caption{Mobile \Glspl{podcast}-Seite mit Burger-Menu\\} + \label{fig:podcasts-mobile} + \end{figure} + \end{minipage} +% \hspace{0.05\linewidth} + \begin{minipage}{0.32\linewidth} + \begin{figure}[H] + \fbox{\includegraphics[width=.9\linewidth]{assets/ui/listening-progress-mobile.png}} + \setcapindent*{1em} + \caption{Mobile ,,Zuletzt gehört''-Seite mit offenem Burger-Menu} + \label{fig:listening-progress-mobile} + \end{figure} + \end{minipage} +\end{minipage} + +\begin{figure}[H] + \centering + \fbox{\includegraphics[width=.9\linewidth]{assets/ui/podcasts-desktop-change-language.png}} + \caption{\Glspl{podcast}-Seite mit \Glspl{episode} und Sprachauswahl} + \label{fig:podcast-desktop-change-language} +\end{figure} + +\begin{figure}[H] + \centering + \fbox{\includegraphics[width=.9\linewidth]{assets/ui/listening-progess-account-dropdown.png}} + \caption{,,Zuletzt gehört''-Seite mit Fortschrittsbalken und Account-Dropdown} + \label{fig:listening-progress-account-dropdown} +\end{figure} + +\begin{figure}[H] + \centering + \includegraphics[width=.87\linewidth]{assets/ui/help-desktop.png} + \caption{Hilfe-Fenster, welches mit dem Menu-Eintrag ,,Hilfe'' geöffnet wird} + \label{fig:help-desktop} +\end{figure} + +\begin{minipage}[H]{.9\linewidth} + \centering + \begin{minipage}{.4\linewidth} + \begin{figure}[H] + \centering + \fbox{\includegraphics[width=.8\linewidth]{assets/ui/settings-mobile-1.png}} + \setcapindent*{1em} + \caption{Einstellungen mit Ändern des Passworts und Gpodder-Verknüpfung} + \label{fig:settings-mobile-1} + \end{figure}% + \end{minipage} + \hspace{.5cm} + \begin{minipage}{.4\linewidth} + \begin{figure}[H] + \fbox{\includegraphics[width=.8\linewidth]{assets/ui/settings-mobile-2.png}} + \setcapindent*{1em} + \caption{Einstellungen mit Datenexport und Accountlöschung\\} + \label{fig:settings-mobile-2} + \end{figure} + \end{minipage} +\end{minipage} + diff --git a/00-pflichtenheft/sections/einleitung.tex b/00-pflichtenheft/sections/einleitung.tex new file mode 100644 index 0000000..67b6208 --- /dev/null +++ b/00-pflichtenheft/sections/einleitung.tex @@ -0,0 +1,34 @@ +\section{Einleitung} + +Dieses Softwareprojekt setzt sich zum Ziel, einen im Vergleich zu anderen Synchronisationsservern +möglichst schlanken und performanten Synchronisationsserver für \Glspl{podcast} +bereitzustellen, welcher von sogenannten \Glspl{podcatcher} verwendet werden soll. + +Ein \Gls{podcatcher} ist eine Anwendung, mit der \Glspl{podcast} abonniert, +heruntergeladen und angehört werden können. +Durch diesen Synchronisationsserver ermöglichen Betreiber von \Glspl{podcatcher} den Nutzern +eine einfache Möglichkeit zum Synchronisieren von \Glspl{podcast} über verschiedene +Geräte hinweg. +Im Gegensatz zu anderen Synchronisationsservern für \Glspl{podcast} versucht dieses Produkt +möglichst einfach und unkompliziert in der Handhabung zu sein. Deshalb wird nur eine +grundlegende Synchronisationsfunktion ohne weitere +Anpassungsmöglichkeit bereitgestellt. +Außerden werden Funktionalitäten die bereits von einem \Gls{podcatcher} ermöglicht werden, wie +zum Beispiel das Anhören und Verwalten von \Glspl{podcast}, nicht bereitgestellt. +Dies sorgt zusätzlich für ein schlankes Backend. + +Es werden hierbei sowohl die \Glspl{podcast} an sich, als auch die aktuellen +Hörfortschritte synchronisiert. +Das bedeutet, dass alle vorgenommenen Änderungen auf den Server gespiegelt +werden. +Die Änderungen werden danach von jedem mit dem Account verbundenen +\Gls{podcatcher} heruntergeladen. +Dazu werden die \Glspl{podcast} und die Hörfortschritte eines jeden Nutzers in einer +\Gls{db} gespeichert. +Auf die \Gls{db} können die \Gls{podcatcher} mit einer API in Verbindung eines +Nutzeraccounts lesend und schreibend zugreifen. +Um eine Kompatibilität mit bestehenden Podcatchern +sicherzustellen, wird die weitverbreitete \Gls{gpodder} verwendet. +Zusätzlich soll es Nutzern durch ein Webinterface ermöglicht werden, ihre +synchronisierten \Glspl{podcast} einsehen zu können und ihren Nutzeraccount verwalten zu können. + diff --git a/00-pflichtenheft/sections/glossar.tex b/00-pflichtenheft/sections/glossar.tex new file mode 100644 index 0000000..8dce712 --- /dev/null +++ b/00-pflichtenheft/sections/glossar.tex @@ -0,0 +1,272 @@ +\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, + 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 - 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} +} + +% UI-Framework (React.js/Vue/Bootstrap) +% Responsive Design +% Abonnement +% Pseudoprotokoll +% Dashboard + diff --git a/00-pflichtenheft/sections/produktdaten.tex b/00-pflichtenheft/sections/produktdaten.tex new file mode 100644 index 0000000..c74e3fb --- /dev/null +++ b/00-pflichtenheft/sections/produktdaten.tex @@ -0,0 +1,83 @@ +\section{Produktdaten} + +Das Projekt erhebt an unterschiedlichen Stellen Daten des Benutzers oder anderen +Plattformen. Diese Daten können temporär gespeichert werden. Dabei bleiben die +Daten nur für eine kurze Zeit gespeichert, zum Beispiel so lange wie der Nutzer +eingeloggt ist. Andere Daten können auch persistent gespeichert werden. Dabei +bleiben die Daten solange gespeichert, bis sie manuell oder durch +\Gls{garbage-collection} gelöscht werden. + +\subsection{Weboberfläche} + +Die Weboberfläche bezieht direkt Daten vom Benutzer. Die Weboberfläche erhält +E-Mail-Adresse und Passwort vom Benutzer, speichert diese aber nur solange, bis +diese an das Backend zur Validierung geschickt werden. Daraufhin erhält die +Weboberfläche einen \Gls{session-token} welcher entweder persistent oder temporär als +\Gls{cookie} gespeichert bleibt, je nachdem, ob der Nutzer angemeldet bleiben möchte. + +Zusätzlich erhält die Weboberfläche die abonnierten \Glspl{podcast} und gehörten +\Glspl{episode} inklusive Metadaten vom Backend. Diese Daten werden nur temporär, +solange die Webseite offen ist, gespeichert. + +\subsubsection*{Persistent} + +\begin{itemize} + \item \Gls{session-token} (falls der Nutzer angemeldet bleiben möchte) +\end{itemize} + +\subsubsection*{Temporär} + +\begin{itemize} + \item Abonnierte \Glspl{podcast} + \item Gehörte \Glspl{episode} + \item \Gls{session-token} +\end{itemize} + +\subsection{Backend} + +Das Backend interagiert nicht direkt mit dem Benutzer, sondern bekommt Daten von +der Weboberfläche und \Glspl{podcatcher}. Wenn sich ein Nutzer über die Weboberfläche +oder im \Gls{podcatcher} anmeldet oder registriert speichert der Server temporär die E-Mail-Adresse und +das Passwort des Nutzers im Klartext, bevor es die Daten gegen die gehashten und +gesalzenen persistenten Daten der \Gls{db} abgleicht beziehungsweise speichert. + +Außerdem speichert das Backend abonnierte \Glspl{podcast} und gehörte +\Glspl{episode}, welche +es vom \Gls{podcatcher} bekommt, im persistenten Speicher. Diese Daten bleiben +gespeichert bis sie durch neue Daten obsolet werden (\Gls{garbage-collection}), +vom Nutzer manuell gelöscht werden oder der Account gelöscht wird. + +Wenn die Weboberfläche \Glspl{episode} über \Glspl{podcast} abfragt, welche noch nicht vom +Nutzer gehört wurden, holt der Server Metadaten über den \Glspl{podcast} und speichert +Informationen und Bilder des \Glspl{podcast} temporär, solange der Nutzer die +Weboberfläche geöffnet hat. + +\subsubsection*{Persistent} +\begin{itemize} +% Email (gehasht und gesalzen) / Betreuer fragen weil evtl Mails gesendet werden +% müssen, falls Datenschutzbedinungen geändert werden +\item E-Mail-Adresse gehasht und gesalzen +\item Passwort gehasht und gesalzen +\item Abonnierte \Glspl{podcast} +\item Gehörte \Glspl{episode} (Hörfortschritte) +\end{itemize} + +\subsubsection*{Temporär} +\begin{itemize} + \item Metadaten von Feeds (\Glspl{episode}, Bilder) +\end{itemize} + +\subsection{Podcatcher} + +Der \Gls{podcatcher} speichert die E-Mail-Adresse, das Passwort und die URL der +Gpodder-Instanz im persistenten Speicher. Zusätzlich speichert der +\Gls{podcatcher} +abonnierte \Glspl{podcast} und gehörte \Glspl{episode} im persistenten Speicher. + +\subsubsection*{Persistent} +\begin{itemize} +\item E-Mail-Adresse, Passwort und URL der Gpodder-Instanz +\item Abonnierte \Glspl{podcast} +\item Gehörte \Glspl{episode} +\end{itemize} + diff --git a/00-pflichtenheft/sections/produktfunktionen.tex b/00-pflichtenheft/sections/produktfunktionen.tex new file mode 100644 index 0000000..12c5b56 --- /dev/null +++ b/00-pflichtenheft/sections/produktfunktionen.tex @@ -0,0 +1,215 @@ +\section{ Produktfunktionen } + +\subsection{ Registrierung } +\label{f:registrierung} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer möchte sich registrieren. + \item[Anforderungen:] \ref{r:login} + \item[Test:] \ref{t:register}, \ref{t:pw-req} + \item[Ziel:] Der Nutzer hat einen funktionierenden Account. + \item[Vorbedingung:] - + \item[Nachbedingung Erfolg:] Erfolgreiche Registrierung. + \item[Nachbedingung Fehlschlag:] Registrierung/Verbindungsaufbau zum Server schlägt + fehl. + \item[Akteure:] Nutzer, Server + \item[Auslösendes Ereignis:] Drücken des \enquote{Registrieren}-Buttons. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Öffnen der Webseite. + \item Drücken auf \enquote{Registrieren}-Option. + \item E-Mail-Adresse und zwei Mal neues Passwort eingeben. + \item \enquote{Registrieren}-Button drücken. + \item Bestätigungs-E-Mail wird an angegebene E-Mail-Adresse gesendet. + \item Nutzer öffnet Bestätigungs-Link. + \item Nutzer wird auf Login-Seite weitergeleitet. Der Bestätigungs-Link verfällt. + \end{enumerate} + \item[Erweiterung:] Wenn der Link nach 24 Stunden noch nicht angeklickt wurde, verfällt \\ + dieser. +\end{description} + +\newpage + +\subsection{ Anmelden } +\label{f:anmelden} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer möchte sich anmelden + \item[Anforderungen:] \ref{r:login}, \ref{r:login-provider} + \item[Test:] \ref{t:login} + \item[Ziel:] Der Nutzer ist eingeloggt. + \item[Vorbedingung:] Der Nutzer hat einen funktionierenden Account. + \item[Nachbedingung Erfolg:] Erfolgreiche Anmeldung + \item[Nachbedingung Fehlschlag:] Anmeldung/Verbindungsaufbau zum Server schlägt + fehl. + \item[Akteure:] Nutzer, Server + \item[Auslösendes Ereignis:] Drücken des \enquote{Anmelden}-Buttons. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Öffnen der Webseite. + \item E-Mail-Adresse und Passwort eingeben. + \item Option \enquote{Passwort merken} aus-/abwählen. + \item \enquote{Anmelden}-Button drücken. + \item Nutzer wird zu seinem \Gls{dashboard} weitergeleitet. + \end{enumerate} + \item[Erweiterung:] Wenn die Option \enquote{Passwort merken} aktiviert ist, bleibt der Nutzer \\ + sitzungsübergreifend in seinem Account eingeloggt. + \item[Alternativen:] \mbox{} + \begin{enumerate} + \item Falls sich der Browser einen vorherigen Login gemerkt hat, + wird der Nutzer beim Aufruf der Seite direkt zu seinem + \Gls{dashboard} weitergeleitet. + \item Der Nutzer meldet sich mit einem \Gls{oauth} Dienst an. + \end{enumerate} +\end{description} + +\newpage + +\subsection{ Passwort vergessen } +\label{f:pwreset} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer hat sein Passwort vergessen und möchte es zurücksetzen. + \item[Anforderungen:] \ref{r:reset-pw} + \item[Test:] \ref{t:pw-req}, \ref{t:forgot-pw} + \item[Ziel:] Der Nutzer hat ein neues Passwort. + \item[Vorbedingung:] Der Nutzer hat einen bestehenden Account und Zugriff auf seine E-Mail-Adresse + \item[Nachbedingung Erfolg:] Erfolgreiche Passwort Zurücksetzung. + \item[Nachbedingung Fehlschlag:] Zurücksetzung des Passworts / Verbindungsaufbau zum Server + schlägt fehl. + \item[Akteure:] Nutzer, Server + \item[Auslösendes Ereignis:] Drücken der \enquote{Passwort-Vergessen} Option auf der Login-Seite. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Öffnen der Webseite. + \item \enquote{Passwort-Vergessen} Option auswählen. + \item Weiterleitung auf \enquote{Passwort zurücksetzen} Seite. + \item E-Mail-Adresse des Accounts eingeben. Falls kein Account mit dieser + Adresse existiert, wird dieser Schritt wiederholt. + \item Bestätigungs-E-Mail mit Zurücksetzungs-Link wird an die angegebene + E-Mail-Adresse gesendet. + \item Der Nutzer öffnet den Zurücksetzungs-Link. + \item Ein Neues Passwort zweimal eingeben. + \item Auf den \enquote{Passwort-Zurücksetzen}-Button klicken. + \item Weiterleitung auf Login-Seite. + \end{enumerate} +\end{description} + +\newpage + +\subsection{ Passwort ändern } +\label{f:pwchange} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer möchte sein Passwort ändern. + \item[Anforderungen:] \ref{r:reset-pw} + \item[Test:] \ref{t:pw-req}, \ref{t:change-pw} + \item[Ziel:] Der Nutzer hat ein neues Passwort. + \item[Vorbedingung:] Der Nutzer ist in seinem Account angemeldet. + \item[Nachbedingung Erfolg:] Erfolgreiche Passwort Änderung. + \item[Nachbedingung Fehlschlag:] Änderung des Passworts / Verbindungsaufbau zum Server + schlägt fehl. + \item[Akteure:] Nutzer, Server + \item[Auslösendes Ereignis:] Betätigen des \enquote{Passwort-Ändern}-Buttons. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Öffnen der Webseite. + \item Anmelden + \item Auf Account-Einstellungen gehen. + \item Bisheriges Passwort und zweimal neues Passwort in dafür vorgesehene Felder + eintippen. + \item \enquote{Passwort-Ändern}-Button betätigen. + \end{enumerate} +\end{description} + +\newpage + +\subsection{ Hörfortschritt synchronisieren } +\label{f:hörfortschrittSync} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer hört mit einem verknüpften + \Gls{podcatcher} eine \Gls{episode} bis zu + einem gewissen Zeitpunkt. + Der Hörfortschritt soll mit dem Server und allen anderen Geräten synchronisiert werden. + \item[Anforderungen:] \ref{r:sync}, \ref{r:store}, \ref{r:persistent-storage}, \ref{r:gpodder} + \item[Test:] \ref{t:sync-episode} + \item[Ziel:] Der Hörfortschritt wird auf den Server und alle verknüpften Geräte übertragen. + \item[Vorbedingung:] Der Nutzer hat seinen Account mit einem \Gls{podcatcher} verknüpft und verwendet + diesen im Folgenden. + \item[Nachbedingung Erfolg:] Erfolgreiche Synchronisation des Hörfortschritts. + \item[Nachbedingung Fehlschlag:] Verbindungsaufbau zum Server schlägt + fehl. +\item[Akteure:] Nutzer, \Gls{podcatcher}, Server +\item[Auslösendes Ereignis:] Anhören einer \Gls{episode} bis zu einem gewissen Zeitpunkt. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Der Nutzer hört innerhalb eines \Gls{podcatcher}s eine + \Gls{episode}. + \item Der Hörfortschritt wird dem Server über die \Gls{gpodder} mitgeteilt. + \item Der Server aktualisiert den Hörfortschritt im entsprechenden Datensatz + des Nutzeraccounts zur \Gls{episode}. + \end{enumerate} + \item[Erweiterung:] Wenn sich ein weiterer \Gls{podcatcher} aktualisiert, ruft dieser + die neuen Hörfortschritte des Nutzers vom Server über die \Gls{gpodder} ab und wendet diese an. +\end{description} + +\newpage + +\subsection{ Abonnements synchronisieren} +\label{f:abonnentsSync} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer fügt auf einem verknüpften + \Gls{podcatcher} ein \Gls{abo} hinzu bzw. löscht ein \Gls{abo}. + Dieses soll mit dem Server und allen anderen Geräten synchronisiert werden. + \item[Anforderungen:] \ref{r:sync}, \ref{r:store}, \ref{r:persistent-storage}, \ref{r:gpodder} + \item[Test:] \ref{t:sync-sub}, \ref{t:sync-unsub} + \item[Ziel:] Das (De-)\Gls{abo} wird auf den Server und alle verknüpften Geräte übertragen. + \item[Vorbedingung:] Der Nutzer hat seinen Account mit einem \Gls{podcatcher} verknüpft und verwendet + diesen im Folgenden. +\item[Nachbedingung Erfolg:] Erfolgreiche Synchronisation des \Glspl{abo}. + \item[Nachbedingung Fehlschlag:] Verbindungsaufbau zum Server schlägt + fehl. +\item[Akteure:] Nutzer, \Gls{podcatcher}, Server +\item[Auslösendes Ereignis:] (De-)Abonnieren eines \Glspl{podcast} innerhalb + eines \Gls{podcatcher}. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Der Nutzer (de-)abonniert innerhalb eines \Gls{podcatcher}s einen + \Gls{podcast}. + \item Die Änderung wird dem Server über die \Gls{gpodder} mitgeteilt. + \item Der Server fügt das neue \Gls{abo} persistent zum Datensatz des Nutzers + auf dem Server hinzu / löscht das \Gls{abo} vom Datensatz auf + dem Server. + \end{enumerate} + \item[Erweiterung:] Wenn sich ein weiterer \Gls{podcatcher} aktualisiert, holt dieser + die aktuelle Liste der \Glspl{abo} des Nutzers vom Server über die + \Gls{gpodder} (Client Pull). +\end{description} + +\newpage + +\subsection{ Account löschen} +\label{f:deleteAccount} + +\begin{description} + \item[Anwendungsfall:] Der Nutzer möchte seinen Account löschen. + \item[Anforderungen:] \ref{r:delete-acc} + \item[Test:] \ref{t:delete-acc} + \item[Ziel:] Der Account und alle Nutzerdaten werden vom Server gelöscht. + \item[Vorbedingung:] Der Nutzer ist angemeldet und befindet sich auf der Einstellungsseite. + \item[Nachbedingung Erfolg:] Der Account wurde gelöscht. + \item[Nachbedingung Fehlschlag:] Verbindungsaufbau zum Server schlägt + fehl. + \item[Akteure:] Nutzer, Server + \item[Auslösendes Ereignis:] Der Nutzer drückt auf den \enquote{Account löschen} Knopf. + \item[Beschreibung:] \mbox{} + \begin{enumerate} + \item Der Nutzer drückt auf den \enquote{Account löschen}-Knopf. + \item Der Nutzer wird dazu aufgefordert sein Passwort als Bestätigung der Löschung + einzugeben. + \item Der Server löscht den Account und alle dazugehörigen Daten. + \item Der Nutzer wird auf die Login-Seite weitergeleitet. + \end{enumerate} +\end{description} diff --git a/00-pflichtenheft/sections/produktuebersicht.tex b/00-pflichtenheft/sections/produktuebersicht.tex new file mode 100644 index 0000000..37e0789 --- /dev/null +++ b/00-pflichtenheft/sections/produktuebersicht.tex @@ -0,0 +1,184 @@ +\section{Produktübersicht} + +In diesem Kapitel wird der Aufbau der Synchronisationsserver-Webseite in einem Use-Case-Diagramm, welches sich in Abbildung +\ref{fig:UseCase} befindet, visualisiert. + +Hierbei wird in Aktivitätsdiagrammen näher auf die Aktionen \enquote{Anmelden} (Abbildung \ref{fig:ActLogin}), +\enquote{Registrieren} (Abbildung \ref{fig:ActRegister}) und \enquote{Passwort vergessen} (Abbildung \ref{fig:ActResetPass}) +eingegangen. + +Weiter beschreibt ein abstrahiertes Sequenzdiagramm (Abbildung +\ref{fig:SeqSynchSubs}) den Nachrichtenaustausch bei der Synchronisation der +gespeicherten Daten eines Benutzers. Dies erfolgt am Beispiel der Tätigung eines +neuen \Glspl{abo} über einen \Gls{podcatcher}. + +\subsection{Der Aufbau der Webseite} + +In dem Use-Case-Diagramm in Abbildung \ref{fig:UseCase} erkennt man den Aufbau der Webseite des Synchronisationsservers. +Besucht man die Seite ohne eingeloggt zu sein, so hat man die Möglichkeit die Sprache zu ändern, sich anzumelden, sich zu registrieren oder sein Passwort über die \enquote{Passwort vergessen}-Funktion \ref{f:pwreset} zurückzusetzen. +Dabei gibt es die Möglichkeit sich mit seinem Google-Konto oder dem Konto eines anderen Anbieters zu registrieren / anzumelden. + +Ist man angemeldet, wird man auf ein \Gls{dashboard} weitergeleitet. +Dort hat man die Möglichkeit eine Anleitung einzusehen und die bisher +abonnierten \Glspl{podcast} einzusehen. +Dabei erhält man zu jedem \Gls{podcast} einen Überblick über dessen +\Glspl{episode} und Details darüber, bis zu welchem Zeitpunkt man die +\Gls{episode} angehört hat. +Auch gibt es die Möglichkeit einen Verlauf und den korrespondierenden +Fortschritt aller zuletzt gehörten \Glspl{episode} einzusehen. + +Des Weiteren kann man das eigene Profil verwalten. +Dies beinhaltet das Ändern des eigenen Passworts, das Importieren der Daten einer Gpodder-Instanz über eine Anmeldung oder +dem Importieren als Datei. +Auch können in der Profilverwaltung personenbezogene Daten als Datei importiert und exportiert werden. +Schließlich hat man in der Profilverwaltung die Möglichkeit den eigenen Account permanent zu löschen. + +Ist man ein Administrator, so hat man zusätzlich die Möglichkeit Statistiken einzusehen. + +\newpage + +% UML Use-Case Diagramm +\begin{figure}[H] + \centering + \hspace*{-2.5cm} + \input{sections/TikzPictures/UseCaseUML} + \caption{Use-Case-Diagramm der Webseite\\(*) - Optionale Funktionen, deren Implementierung nicht feststeht} + \label{fig:UseCase} +\end{figure} +\newpage + +\subsection{Das Einloggen} + +Im Aktivitätsdiagramm \enquote{Anmeldung} in Abbildung \ref{fig:ActLogin} möchte der Nutzer sich auf der Webseite anmelden. +Hierzu ruft der Nutzer zunächst die Webseite auf und landet auf der Login Seite. + +Hat der Nutzer sich bereits zuvor auf dem Computer auf der Seite angemeldet und dabei ausgewählt eingeloggt zu bleiben, +so wird der Nutzer über Session-\Glspl{cookie} automatisch auf das \Gls{dashboard} weitergeleitet. +Ist das nicht der Fall, so muss der Nutzer seine Anmeldedaten eingeben. + +Nach dem Eintragen der Daten hat der Nutzer die Möglichkeit für das nächste Mal, wenn der Nutzer die Webseite +am selben Computer betritt, angemeldet zu bleiben. +Daraufhin drückt der Nutzer den \enquote{Anmelden}-Button. + +Wurde die E-Mail oder das Passwort falsch eingegeben, so zeigt die Seite eine Fehlermeldung an und der Nutzer wird aufgefordert seine Eingabe zu korrigieren. +Wurden die E-Mail und das Passwort korrekt eingegeben, so landet der Nutzer +angemeldet auf dem \Gls{dashboard}, von wo aus er dann alle Aktionen ausführen kann, für die man angemeldet sein muss. + +\newpage + +% UML Activity Diagramm - Login +\begin{figure}[H] + \centering + \input{sections/TikzPictures/ActivityLogin} + \caption{Aktivitätsdiagramm - Anmelden} + \label{fig:ActLogin} +\end{figure} +\newpage + +\subsection{Das Registrieren} + +Möchte sich der Nutzer einen neuen Account erstellen, so läuft dieser Vorgang +entsprechend dem Aktivitätsdiagramm \enquote{Registrieren} in Abbildung \ref{fig:ActRegister} ab. +Der Nutzer ruft zunächst die Webseite auf und landet auf der Login Seite. +Dort wählt der Nutzer die \enquote{Registrieren}-Option aus und wird zur Registrierungsseite weitergeleitet. + +Auf der Registrierungsseite gibt der Nutzer in den jeweils dafür zugeordneten Eingabefeldern seine E-Mail-Adresse und zur Kontrolle +zwei Mal das gleiche Passwort ein, welches dem Account zugeordnet werden soll. +Daraufhin drückt der Nutzer zum Abschluss den \enquote{Registrieren}-Button. +Der Server überprüft, ob die E-Mail-Adresse bereits vergeben ist und ob das Passwort die Passwortmindestanforderungen \ref{r:pw-requirements} erfüllt. + +Ist die E-Mail schon vergeben, so wird dem Nutzer eine entsprechende Meldung angezeigt und der Nutzer muss die eingegebene E-Mail-Adresse korrigieren. +Erfüllt das Passwort nicht die Mindestvoraussetzungen, so wird dem Nutzer auch hier eine entsprechende Meldung angezeigt und der Nutzer muss die Eingabe korrigieren. + +Erfüllen die Eingaben die Voraussetzungen, so wird an die angegebene E-Mail-Adresse eine E-Mail mit einem Link zur Verifizierung +der E-Mail-Adresse geschickt. +Der Nutzer muss diesen Link innerhalb der nächsten 24 Stunden zur Aktivierung seines Kontos öffnen, da ansonsten der Link +abläuft und der Nutzer den Prozess erneut beginnen muss. + +Wurde der Link innerhalb von 24 Stunden geöffnet, so wird der Account aktiviert und der Nutzer wird über den Link zur Login Seite +weitergeleitet, von wo aus er sich mit seinem neu erstellten Account nun einloggen kann. + +\newpage + +% UML Activity Diagram - Register +\begin{figure}[H] + \centering + \input{sections/TikzPictures/ActivityRegister} + \caption{Aktivitätsdiagramm - Registrieren} + \label{fig:ActRegister} +\end{figure} +\newpage + +\subsection{Das Vergessen des Passwortes} + +Hat der Nutzer einmal sein Passwort vergessen, so gibt es die Möglichkeit das Passwort zurückzusetzen. +Wie dieser Vorgang aussieht, wird im Aktivitätsdiagramm \enquote{Passwort zurücksetzen} in Abbildung \ref{fig:ActResetPass} +dargestellt. +Zunächst ruft der Nutzer die Webseite auf und landet auf der Login Seite. +Über die Option \enquote{Passwort vergessen} wird der Nutzer auf die \enquote{Passwort vergessen}-Seite weitergeleitet. + +Hier gibt der Nutzer in einem Eingabefeld die E-Mail-Adresse des Accounts an, dessen Passwort der Nutzer vergessen hat. +Nach der Bestätigung der Eingabe überprüft der Server, ob unter der angegebenen E-Mail-Adresse ein Account angelegt ist. +Ist dies nicht der Fall, so wird der Nutzer erneut darum gebeten die E-Mail-Adresse anzugeben. +Existiert ein Account unter der angegeben E-Mail-Adresse, so wird eine E-Mail an die angegebene Adresse geschickt, die einen +automatisch generierten Link enthält, der es dem Nutzer erlaubt das Passwort für den jeweiligen Account zurückzusetzen. + +Der Nutzer muss den Link innerhalb der nächsten 24 Stunden öffnen, da dieser ansonsten abläuft und zu einer entsprechenden +Fehlermeldung führt. +Öffnet der Nutzer den Link innerhalb von 24 Stunden, so wird der Nutzer auf eine Seite weitergeleitet auf der der Nutzer +zwei Mal das neue Passwort eingeben muss. +Das Passwort muss dabei die Passwortmindestanforderungen \ref{r:pw-requirements} erfüllen. + +Ist das neue Passwort eingegeben, so muss der Nutzer den \enquote{Passwort zurücksetzen}-Button drücken und das eingegebene Passwort wird überprüft. +Erfüllt das Passwort die Mindestanforderungen nicht, so wird dem Nutzer eine entsprechende Fehlermeldung angezeigt und der Nutzer muss sich ein neues Passwort ausdenken und zwei Mal eingeben. +Erfüllt das Passwort die Mindestanforderungen, so wird das neue Passwort für den Account gespeichert und der Nutzer wird auf die Login Seite weitergeleitet, von wo aus er sich mit dem neuen Passwort anmelden kann. + +\newpage + +% UML Activity Diagram - Reset Password +\begin{figure}[H] + \centering + \input{sections/TikzPictures/ActivityResetPass} + \caption{Aktivitätsdiagramm - Passwort vergessen} + \label{fig:ActResetPass} +\end{figure} +\newpage + +\subsection{Das Synchronisieren am Beispiel eines Abonnements} + +Der Benutzer in Abbildung \ref{fig:SeqSynchSubs} hört \Glspl{podcast} über die +verschiedenen \Gls{podcatcher}-Applika\-tionen \enquote{Podcatcher1} und \enquote{Podcatcher2}. +Dabei spielt es im Folgenden keine Rolle ob er beide Applikationen auf demselben Gerät, beide auf jeweils unterschiedlichen Geräten oder die gleiche Applikation auf unterschiedlichen Geräten verwendet. + +Der Benutzer tätigt ein neues \Gls{abo} über die \Gls{podcatcher}-Applikation \enquote{Podcatcher1}. +Dies bewirkt zunächst eine lokale Änderung der Liste der \Glspl{abo}. +Im Zuge dessen wird auch der Server über die vorgenommene Änderung benachrichtigt. +Dieser speichert dann die kommunizierte Änderung persistent in der \Gls{db}. + +Im Folgenden lässt sich der Benutzer die Liste seiner \Glspl{abo} im Webfrontend anzeigen. +Dafür benachrichtigt das Webfrontend den Server darüber, dass es die Liste der +\Glspl{abo} des entsprechenden Nutzers benötigt (\enquote{Client Pull}). +Das Webfrontend erhält die aktuelle Liste, welche insbesondere das zuvor +getätigte \Gls{abo} enthält, und zeigt diese dem Nutzer an. + +Der Benutzer lässt sich nun auch in der \Gls{podcatcher}-Applikation +\enquote{Podcatcher2} die Liste seiner \Glspl{abo} anzeigen. +Die Anwendung \enquote{Podcatcher2} benachrichtigt hierfür nach kurzer Zeit oder +nach manueller Anforderung den Server darüber, dass sie die Liste der +\Glspl{abo} des entsprechenden Nutzers benötigt. + +Die Anwendung erhält die aktuelle Liste, übernimmt diese lokal und zeigt sie dem Nutzer an. +So wird der aktuelle Stand der Liste der \Glspl{abo} (analog der Fortschritt +beim Anhören/Ansehen von \Glspl{episode}) über alle verbundenen \Gls{podcatcher} (und entsprechend alle verbundenen Geräte) synchronisiert. + +\newpage + +% UML Sequence Diagram - Synchronise Subscription +\begin{figure}[H] + \centering + \raisebox{3cm}{ + \input{sections/TikzPictures/SequenceSynchroniseSubscription}} + \caption{Sequenzdiagramm - Synchronisation am Beispiel Abonnieren} + \label{fig:SeqSynchSubs} +\end{figure} +\newpage diff --git a/00-pflichtenheft/sections/tests.tex b/00-pflichtenheft/sections/tests.tex new file mode 100644 index 0000000..9d29aa1 --- /dev/null +++ b/00-pflichtenheft/sections/tests.tex @@ -0,0 +1,605 @@ + +\section{Tests} + +\subsection{Registrierung}\label{t:register} +\vspace{0.3cm} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Ein Fenster ist im Browser geöffnet. + \item [Aktion] Der Benutzer gibt die URL der Weboberfläche in die Kopfzeile ein und drückt Enter. + \item [Reaktion] Der Browser wechselt zur Anmeldeseite der Weboberfläche. +\end{description} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Der Browser wechselt zur Registrierungsseite. +\end{description} + +\item +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Die Registrierungsseite mit Registrierungsmöglichkeit in der Mitte des Fensters ist geladen. + \item [Aktion] Der Benutzer gibt \enquote{pseIstToll@test.com} als E-Mail und \enquote{Test123!?} als Passwort ein. Weiter gibt er \enquote{test123!?} in das \enquote{Wiederholen} Feld ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Die Registrierungsseite bleibt geladen. Im E-Mail-Feld steht \enquote{pseIstToll@test.com}, im Feld \enquote{Passwort} steht \enquote{Test123!?} und im Feld \enquote{Wiederholen} steht \enquote{test123!?}. Der Benutzer wird aufgefordert in die Felder \enquote{Passwort} und \enquote{Wiederholen} das gleiche Passwort einzugeben. +\end{description} + +\item +\begin{description} + \item [Stand] Die Registrierungsseite ist geladen. Als E-Mail ist \enquote{pseIstToll@test\-.com}, als Passwort \enquote{Test123!?} und \enquote{test123!?} in das Feld \enquote{Wiederholen} eingetragen. + \item [Aktion] Der Benutzer gibt \enquote{Test123!?} in das Feld \enquote{Wiederholen} ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Dem Benutzer wird angezeigt, dass an die angegebene E-Mail-Adres\-se eine E-Mail mit einem Bestätigungslink versendet wurde. Der Benutzer wird aufgefordert diesen zu Bestätigen um die Registrierung abzuschließen. +\end{description} + +\end{enumerate} + +\item +\begin{description} + \item [Stand] Der Benutzer hat die Registrierung begonnen und die E-Mail mit dem Bestä\-tigungs-Link erhalten. Der Benutzer hat noch nicht auf den Bestätigungs-Link geklickt. + \item [Aktion] Der Benutzer klickt innerhalb von 24 Stunden nach Versendung auf den Bestätigungs-Link. + \item [Reaktion] Der Account wird erstellt und der Benutzer wird auf die Anmeldeseite weitergeleitet. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat die Registrierung bereits abgeschlossen. + \item [Aktion] Der Benutzer klickt auf den Bestätigungs-Link. + \item [Reaktion] Der Benutzer erhält eine Fehlermeldung, dass der Link abgelaufen ist. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat die Registrierung begonnen und die E-Mail mit dem Bestä\-tigungs-Link erhalten. Die E-Mail wurde vor mehr als 24 Stunden versendet. Der Benutzer hat den Bestätigungs-Link noch nicht angeklickt. + \item [Aktion] Der Benutzer klickt auf den Bestätigungs-Link. + \item [Reaktion] Der Benutzer erhält eine Fehlermeldung, dass der Link abgelaufen ist. Der Account wird nicht erstellt. Der Benutzer wird auf die Anmeldeseite weitergeleitet. +\end{description} + +\item +\begin{description} + \item [Stand] Die Registrierungsseite ist geladen. Es ist bereits ein Account mit der E-Mail-Adresse \enquote{pseIstToll@test.com} registriert. + \item [Aktion] Der Benutzer gibt \enquote{pseIstToll@test.com} als E-Mail-Adresse und \enquote{Test123!?} als Passwort ein. Weiter gibt er das gleiche Passwort in das Feld \enquote{Wiederholen} ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Die Registrierungsseite bleibt geladen. Es wird eine Fehlermeldung ausgegeben, dass diese E-Mail-Adresse bereits vergeben ist.\\ +\end{description} + +\end{enumerate} + +\newpage + + +\subsection{Passwort Anforderungen}\label{t:pw-req} +\vspace{0.3cm} + +\begin{description} + \item [Anmerkung] Die Testfälle sind beispielhaft für den Vorgang der Registrierung entworfen worden. Es wird analoges Verhalten bei den Vorgängen \enquote{Passwort ändern} \ref{t:change-pw} und \enquote{Passwort vergessen} \ref{t:forgot-pw} erwartet. +\end{description} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Die Registrierungsseite ist geladen. Als E-Mail-Adresse ist \enquote{pseIstToll@test\-.com} eingetragen. + \item [Aktion] Der Benutzer gibt \enquote{test} in die Felder \enquote{Passwort} und \enquote{Wiederholen} ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Die Registrierungsseite bleibt geladen. Dem Benutzer wird angezeigt das sein Passwort nicht die Passwort-Mindestanforderungen erfüllt. Weiter wird farblich angezeigt, dass sein Passwort nicht: + \color{red} + \begin{itemize} + \item mindestens 8 Zeichen lang ist. + \item mindestens einen Großbuchstaben enthält. + \item mindestens eine Zahl enthält. + \item mindestens ein Sonderzeichen enthält. + \end{itemize} + \color{black} + Dem Benutzer wird farblich angezeigt dass sein Passwort: + \color{ForestGreen} + \begin{itemize} + \item mindestens einen Kleinbuchstaben enthält. + \end{itemize} + \color{black} +\end{description} + +\item +\begin{description} + \item [Stand] Die Registrierungsseite ist geladen. Als E-Mail ist \enquote{pseIstToll@test.com} eingetragen. + \item [Aktion] Der Benutzer gibt \enquote{Test123} in die Felder \enquote{Passwort} und \enquote{Wiederholen} ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Die Registrierungsseite bleibt geladen. Dem Benutzer wird angezeigt das sein Passwort nicht die Passwort-Mindestanforderungen erfüllt. Weiter wird farblich angezeigt, dass sein Passwort nicht: + \color{red} + \begin{itemize} + \item mindestens 8 Zeichen lang ist. + \item mindestens ein Sonderzeichen enthält. + \end{itemize} + \color{black} + Dem Benutzer wird farblich angezeigt dass sein Passwort: + \color{ForestGreen} + \begin{itemize} + \item mindestens einen Kleinbuchstaben enthält. + \item mindestens einen Großbuchstaben enthält. + \item mindestens eine Zahl enthält. + \end{itemize} + \color{black} +\end{description} + +\newpage + +\item +\begin{description} + \item [Stand] Die Registrierungsseite ist geladen. Als E-Mail-Adresse ist \enquote{pseIstToll@test\-.com} eingetragen. + \item [Aktion] Der Benutzer gibt \enquote{TEST123?} in die Felder \enquote{Passwort} und \enquote{Wiederholen} ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Die Registrierungsseite bleibt geladen. Dem Benutzer wird angezeigt das sein Passwort nicht die Passwort-Mindestanforderungen erfüllt. Weiter wird farblich angezeigt, dass sein Passwort nicht: + \color{red} + \begin{itemize} + \item mindestens einen Kleinbuchstaben enthält. + \end{itemize} + \color{black} + Dem Benutzer wird farblich angezeigt dass sein Passwort: + \color{ForestGreen} + \begin{itemize} + \item mindestens 8 Zeichen lang ist. + \item mindestens einen Großbuchstaben enthält. + \item mindestens eine Zahl enthält. + \item mindestens ein Sonderzeichen enthält. + \end{itemize} + \color{black} +\end{description} + +\item +\begin{description} + \item [Stand] Die Registrierungsseite ist geladen. Als E-Mail ist \enquote{pseIstToll@test.com} eingetragen. + \item [Aktion] Der Benutzer gibt \enquote{Test123!?} in die Felder \enquote{Passwort} und \enquote{Wiederholen} ein. Dann klickt der Benutzer auf den Knopf \enquote{Registrieren}. + \item [Reaktion] Dem Benutzer wird angezeigt, dass an die angegebene E-Mail-Adresse eine E-Mail mit einem Bestätigungslink versendet wurde. Der Benutzer wird aufgefordert diesen zu bestätigen um die Registrierung abzuschließen.\\ +\end{description} + +\end{enumerate} + +\newpage + + +\subsection{Anmeldung}\label{t:login} +\vspace{0.3cm} + +\begin{description} + \item [Vorbedingung] Es ist nur ein Benutzer registriert. Dieser hat die E-Mail \enquote{pseIstToll@test\-.com} und das Passwort \enquote{Test123!?}. Die Option \enquote{Angemeldet bleiben} wurde nicht verwendet. +\end{description} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Ein Fenster ist im Browser geöffnet. + \item [Aktion] Der Benutzer gibt die URL der Weboberfläche in die Kopfzeile ein und drückt Enter. + \item [Reaktion] Der Browser wechselt zur Anmeldeseite der Weboberfläche. +\end{description} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite mit Anmeldemöglichkeit in der Mitte des Fensters ist im Browser geladen. + \item [Aktion] Der Benutzer macht keine Eingaben und klickt auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Die Anmeldeseite bleibt geladen. Der Benutzer wird aufgefordert die Felder \enquote{E-Mail-Adresse} und \enquote{Passwort} auszufüllen. +\end{description} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt als E-Mail-Adresse \enquote{pseIstToll@test.com} ein aber gibt kein Passwort ein. Dann klickt der Benutzer auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Die Anmeldeseite bleibt geladen. Im E-Mail-Feld ist \enquote{pseIstToll@test\-.com} eingetragen. Der Benutzer wird aufgefordert das Passwort-Feld auszufüllen. +\end{description} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{E-Mail}-Feld \enquote{pseIstSuperToll@test.com} ein und gibt \enquote{Test123!?} als Passwort ein. Dann klickt der Benutzer auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Die Anmeldeseite bleibt geladen. Als E-Mail ist \enquote{pseIstSuperToll@test\-.com} und als Passwort \enquote{Test123!?} eingetragen. Dem Benutzer wird eine Fehlermeldung ausgegeben: \enquote{E-Mail-Adresse oder Passwort ist ungültig!} +\end{description} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{E-Mail}-Feld \enquote{pseIstToll@test.com} ein und gibt \enquote{test} als Passwort ein. Der Benutzer wählt die Option \enquote{Angemeldet bleiben} aus. Dann klickt der Benutzer auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Die Anmeldeseite bleibt geladen. Als E-Mail ist \enquote{pseIstToll@test.com} und als Passwort \enquote{test} eingetragen. Die Option \enquote{Angemeldet bleiben} ist ausgewählt. Dem Benutzer wird eine Fehlermeldung ausgegeben: \enquote{E-Mail-Adresse oder Passwort ist ungültig!} +\end{description} + +\newpage + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. Als E-Mail ist \enquote{pseIstToll@test\-.com} und als Passwort \enquote{test} eingetragen. Die Option \enquote{Angemeldet bleiben} ist ausgewählt. + \item [Aktion] Der Benutzer gibt \enquote{Test123!?} als Passwort ein. Dann klickt der Benutzer auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Der Browser wechselt zum \Gls{dashboard}. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat sich erfolgreich angemeldet. Bei der Anmeldung wurde die Option \enquote{Angemeldet bleiben} ausgewählt. + \item [Aktion] Der Benutzer startet seinen Browser neu. Dann gibt er die URL der Weboberfläche in der Kopfzeile ein und drückt Enter. + \item [Reaktion] Der Benutzer wird automatisch angemeldet und das + \Gls{dashboard} geladen. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat sich erfolgreich angemeldet. Bei der Anmeldung wurde die nicht Option \enquote{Angemeldet bleiben} ausgewählt. + \item [Aktion] Der Benutzer startet seinen Browser neu. Dann gibt er die URL der Weboberfläche in der Kopfzeile ein und drückt Enter. + \item [Reaktion] Der Browser wechselt zur Anmeldeseite. Der Benutzer wird nicht automatisch angemeldet.\\ +\end{description} + +\end{enumerate} + +\newpage + + +\subsection{Passwort ändern}\label{t:change-pw} +\vspace{0.3cm} + +\begin{description} + \item [Vorbedingung] Es gibt einen Benutzer mit der E-Mail \enquote{pseIstToll@test.com} und dem Passwort \enquote{Test123!?}. +\end{description} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Das \Gls{dashboard} ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den Profil-Knopf oben rechts (Pfeil nach unten neben dem Männchen). Dann klickt er in dem geöffneten Menu oben rechts auf den Knopf \enquote{Einstellungen}. + \item [Reaktion] Der Browser wechselt zur \enquote{Einstellungs}-Oberfläche. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Die \enquote{Einstellungs}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer macht keine Eingaben und klickt auf den Knopf \enquote{Passwort ändern}. + \item [Reaktion] Die \enquote{Einstellungs}-Oberfläche bleibt geladen. Der Benutzer wird aufgefordert die Felder \enquote{Altes Passwort}, \enquote{Neues Passwort} und \enquote{Wiederholen} auszufüllen. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Die \enquote{Einstellungs}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer gibt \enquote{test} als altes Passwort ein. Weiter gibt er in die Felder \enquote{Neues Passwort} und \enquote{Wiederholen} \enquote{NeuerTest123!?} ein. Dann klickt er auf den Knopf \enquote{Passwort ändern}. + \item [Reaktion] Die \enquote{Einstellungs}-Oberfläche bleibt geladen. Der Benutzer bekommt eine Fehlermeldung, dass das alte Passwort falsch ist. In den Feldern \enquote{Neues Passwort} und \enquote{Wiederholen} steht weiter \enquote{NeuerTest123!?}. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Die \enquote{Einstellungs}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer gibt \enquote{Test123!?} als altes Passwort ein. Weiter gibt er in die Felder \enquote{Neues Passwort} und \enquote{Wiederholen} \enquote{neuerTest} ein. Dann klickt er auf den Knopf \enquote{Passwort ändern}. + \item [Reaktion] Die \enquote{Einstellungs}-Oberfläche bleibt geladen. Dem Benutzer wird angezeigt das sein neues Passwort nicht die Passwort-Mindestanforderungen erfüllt. Weiter wird farblich angezeigt, dass sein Passwort nicht: + \color{red} + \begin{itemize} + \item mindestens eine Zahl enthält. + \item mindestens ein Sonderzeichen enthält. + \end{itemize} + \color{black} + Dem Benutzer wird farblich angezeigt, dass sein Passwort: + \color{ForestGreen} + \begin{itemize} + \item mindestens 8 Zeichen lang ist. + \item mindestens einen Kleinbuchstaben enthält. + \item mindestens einen Großbuchstaben enthält. + \end{itemize} + \color{black} +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Die \enquote{Einstellungs}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{Altes Passwort}-Feld \enquote{Test123!?} ein. Er gibt in das \enquote{Neues Passwort}-Feld und in das \enquote{Wiederholen}-Feld \enquote{NeuerTest123!?} ein. Dann klickt er auf den Knopf \enquote{Passwort ändern}. + \item [Reaktion] Die \enquote{Einstellungs}-Oberfläche bleibt geladen. Die Felder \enquote{Altes Passwort}, \enquote{Neues Passwort} und \enquote{Wiederholen} werden geleert. Dem Benutzer wird angezeigt, dass das Passwort erfolgreich geändert wurde. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Die \enquote{Einstellungs}-Oberfläche ist im Browser geladen. Sein Passwort wurde zu \enquote{NeuerTest123!?} geändert. + \item [Aktion] Der Benutzer meldet sich ab. + \item [Reaktion] Der Browser wechselt zur Anmeldeseite. Der Benutzer ist abgemeldet. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist abgemeldet. Die Anmeldeseite ist geladen. + \item [Aktion] Der Benutzer gibt als E-Mail \enquote{pseIstToll@test.com} und \enquote{Test123!?} als Passwort ein. Dann klickt der Benutzer auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Die Anmeldeseite bleibt geladen. Als E-Mail ist \enquote{pseIstToll@test.com} eingetragen und als Passwort ist \enquote{Test123!?} eingetragen. Dem Benutzer wird per Fehlermeldung ausgegeben, dass E-Mail-Adresse oder Passwort ungültig sind. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer ist abgemeldet. Die Anmeldeseite ist geladen. + \item [Aktion] Der Benutzer gibt als E-Mail \enquote{pseIstToll@test.com} und \enquote{NeuerTest123!?} als Passwort ein. Dann klickt der Benutzer auf den Knopf \enquote{Anmelden}. + \item [Reaktion] Der Browser wechselt zum \Gls{dashboard}.\\ +\end{description} + +\end{enumerate} + +\newpage + + +\subsection{Passwort vergessen}\label{t:forgot-pw} +\vspace{0.3cm} + +\begin{description} + \item [Vorbedingung] Es gibt nur einen registrierten Benutzer. Dieser hat die E-Mail \enquote{pseIstToll@test.com} und \enquote{Test123!?} als Passwort. +\end{description} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den Knopf \enquote{Passwort vergessen?}. + \item [Reaktion] Der Browser wechselt zur \enquote{Passwort vergessen}-Seite. +\end{description} + +\item +\begin{description} + \item [Stand] Die Passwort-Vergessen-Seite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{E-Mail}-Feld \enquote{pseIstSuperToll@test.com} ein. Dann klickt der Benutzer auf den Knopf \enquote{Bestätigen}. + \item [Reaktion] Die \enquote{Passwort zurücksetzen}-Seite bleibt geladen. Dem Benutzer wird eine Fehlermeldung angezeigt, dass diese E-Mail-Adresse nicht vergeben ist. +\end{description} + +\item +\begin{description} + \item [Stand] Die Passwort-Vergessen-Seite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{E-Mail}-Feld \enquote{pseIstToll@test.com} ein. Der Benutzer klickt auf den Knopf \enquote{Bestätigen}. + \item [Reaktion] Der Benutzer wird darüber benachrichtigt, dass an die angegebene E-Mail-Adresse eine E-Mail mit einem Link zum Zurücksetzen des Passworts versendet wurde. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat die E-Mail mit dem Link zum Zurücksetzen des Passworts erhalten und sein Passwort noch nicht zurückgesetzt. + \item [Aktion] Der Benutzer klickt innerhalb von 24 Stunden nach Versendung auf den Link zum Passwort Zurücksetzen. + \item [Reaktion] Der Browser wechselt zur \enquote{Passwort zurücksetzen}-Seite. +\end{description} + +\item +\begin{description} + \item [Stand] Im Browser ist die \enquote{Passwort zurücksetzen}-Seite geladen. + \item [Aktion] Der Benutzer gibt in die Felder \enquote{Neues Passwort} und \enquote{Wiederholen} \enquote{neuerTest} ein. Dann klickt er auf den Knopf \enquote{Passwort zurücksetzen}. + \item [Reaktion] Die \enquote{Passwort zurücksetzen}-Seite bleibt geladen. Dem Benutzer wird angezeigt das sein neues Passwort nicht die Passwort-Mindestanforderungen erfüllt. Weiter wird farblich angezeigt, dass sein Passwort nicht: + \color{red} + \begin{itemize} + \item mindestens eine Zahl enthält. + \item mindestens ein Sonderzeichen enthält. + \end{itemize} + \color{black} + Dem Benutzer wird farblich angezeigt, dass sein Passwort: + \color{ForestGreen} + \begin{itemize} + \item mindestens 8 Zeichen lang ist. + \item mindestens einen Kleinbuchstaben enthält. + \item mindestens einen Großbuchstaben enthält. + \end{itemize} + \color{black} +\end{description} + +\newpage + +\item +\begin{description} + \item [Stand] Im Browser ist die \enquote{Passwort zurücksetzen}-Seite geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{Neues Passwort}-Feld und in das \enquote{Wiederholen}-Feld \enquote{NeuerTest123!?} ein. Dann klickt der Benutzer auf den Knopf \enquote{Passwort zurücksetzen}. + \item [Reaktion] Der Browser wechselt zur Anmeldeseite. Der verwendete Link zum zurücksetzen des Passworts wird ungültig. +\end{description} + +\item +\begin{description} + \item [Stand] Im Browser ist die Anmeldeseite geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{E-Mail}-Feld \enquote{pseIstToll@test.com} und \enquote{Test\-123!?} als Passwort ein. + \item [Reaktion] Die Anmeldeseite bleibt geladen. Der Benutzer bekommt eine Fehlermeldung, dass die E-Mail oder das Passwort ungültig ist. +\end{description} + +\item +\begin{description} + \item [Stand] Im Browser ist die Anmeldeseite geladen. + \item [Aktion] Der Benutzer gibt in das \enquote{E-Mail}-Feld \enquote{pseIstToll@test.com} und \enquote{NeuerTest123!?} als Passwort ein. + \item [Reaktion] Der Browser wechselt zum \Gls{dashboard}. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat die E-Mail mit dem Link zum Zurücksetzen des Passworts erhalten und sein Passwort noch nicht zurückgesetzt. Die E-Mail wurde vor mehr als 24 Stunden versendet. + \item [Aktion] Der Benutzer klickt auf den Link zum Passwort Zurücksetzen. + \item [Reaktion] Der Benutzer bekommt eine Fehlermeldung, dass der Link abgelaufen ist. Das Passwort wird nicht zurückgesetzt. Der Benutzer wird auf die Anmeldeseite weitergeleitet. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer hat die E-Mail mit dem Link zum Zurücksetzen des Passworts erhalten und sein Passwort bereits über diesen Link zurückgesetzt. + \item [Aktion] Der Benutzer klickt erneut auf den Link zum Passwort Zurücksetzen. + \item [Reaktion] Der Benutzer bekommt eine Fehlermeldung, dass der Link abgelaufen ist. Das Passwort wird nicht zurückgesetzt. Der Benutzer wird auf die Anmeldeseite weitergeleitet.\\ +\end{description} + +\end{enumerate} + +\newpage + + +\subsection{Account Löschen}\label{t:delete-acc} +\vspace{0.3cm} + +\begin{description} + \item [Vorbedingung] Es gibt den registrierten Benutzer mit der E-Mail \enquote{pseIstToll@test.com} und \enquote{Test123!?} als Passwort. +\end{description} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Der Benutzer ist angemeldet. Im Browser ist die Einstellungsseite geladen. Möglichkeit zum Löschen des Accounts unten links. + \item [Aktion] Der Benutzer klickt auf den Knopf \enquote{Account löschen}. + \item [Reaktion] Der Browser wechselt zur Account-Löschen-Seite. Auf dieser wird der Benutzer aufgefordert sein Passwort einzugeben um den Vorgang des Löschens zu Bestätigen. +\end{description} + +\item +\begin{description} + \item [Stand] Die Account-Löschen-Seite ist im Browser geladen. + \item [Aktion] Der Benutzer macht keine Eingaben und klickt auf den Knopf \enquote{Account löschen bestätigen}. + \item [Reaktion] Die Account-Löschen-Seite bleibt geladen. Dem Benutzer wird eine Fehlermeldung angezeigt, dass er um die Account Löschung zu bestätigen sein Passwort eingeben muss. +\end{description} + +\item +\begin{description} + \item [Stand] Die Account-Löschen-Seite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt \enquote{test123!?} als Passwort ein und klickt auf den Knopf \enquote{Account löschen bestätigen}. + \item [Reaktion] Es bleibt die Account-Löschen-Seite geladen. Dem Benutzer wird eine Fehlermeldung angezeigt, dass das Passwort falsch ist. +\end{description} + +\item +\begin{description} + \item [Stand] Die Account-Löschen-Seite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt \enquote{Test123!?} als Passwort ein und klickt auf den Knopf \enquote{Account löschen bestätigen}. + \item [Reaktion] Der Account des Benutzers wird zusammen mit allen dazugehörigen gespeicherten Daten gelöscht. Der Browser wechselt zur Anmeldeseite. +\end{description} + +\item +\begin{description} + \item [Stand] Die Anmeldeseite ist im Browser geladen. + \item [Aktion] Der Benutzer gibt als E-Mail \enquote{pseIstToll@test.com} und \enquote{Test123!?} als Passwort ein. Dann klickt er auf den \enquote{Anmelden} Knopf. + \item [Reaktion] Die Anmeldeseite bleibt geladen und dem Benutzer wird eine Fehlermeldung angezeigt: \enquote{E-Mail-Adresse oder Passwort ist ungültig!} +\end{description} + +\item +\begin{description} + \item [Stand] Die Account-Löschen-Seite ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den \enquote{Abbrechen} Knopf. + \item [Reaktion] Der Account wird nicht gelöscht. Der Browser wechselt zur Einstellungsseite. +\end{description} + +\end{enumerate} + +\newpage + + +\subsection{Synchronisation: Podcast abonnieren}\label{t:sync-sub} +\vspace{0.3cm} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Der Benutzer ist in einem synchronisierten \Gls{podcatcher} angemeldet. + \item [Aktion] Der Benutzer fügt den \Gls{podcast} \enquote{Der tagesschau + Zukunfts-Podcast: mal angenommen} zu seinen \Glspl{abo} hinzu. + \item [Reaktion] Der \Gls{podcatcher} synchronisiert das neue \Gls{abo}. +\end{description} + +\item +\begin{description} + \item [Stand] Dem Benutzer wird die \enquote{Zuletzt gehört}-Oberfläche angezeigt. + \item [Aktion] Der Benutzer klickt auf den Reiter \enquote{Podcasts}. + \item [Reaktion] Der Browser wechselt zur \enquote{Podcasts}-Oberfläche. + Diese zeigt eine Liste aller abonnierten \Glspl{podcast}. Der oberste + Eintrag ist der \Gls{podcast} \enquote{Der tagesschau Zukunfts-Podcast: + mal angenommen}. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer meldet sich über ein anderes Gerät in einem + synchronisierten \Gls{podcatcher} an. + \item [Aktion] Der Benutzer lässt sich im \Gls{podcatcher} die Liste seiner + \Glspl{abo} anzeigen. + \item [Reaktion] Nach kurzer Zeit oder durch manuelles Synchronisieren wird + dem Benutzer dort ebenfalls die aktualisierte Liste der \Glspl{abo} + angezeigt. Diese enthält insbesondere den Eintrag mit dem \Gls{podcast} \enquote{Der tagesschau Zukunfts-Podcast: mal angenommen}.\\ +\end{description} + +\end{enumerate} + + +\subsection{Synchronisation: Podcast deabonnieren}\label{t:sync-unsub} +\vspace{0.3cm} + +\begin{description} + \item [Vorbedingung] Der Benutzer hat den \Gls{podcast} \enquote{Der tagesschau Zukunfts-Podcast: mal angenommen} abonniert. +\end{description} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Der Benutzer ist in einem synchronisierten \Gls{podcatcher} angemeldet. + \item [Aktion] Der Benutzer deabonniert den \Gls{podcast} \enquote{Der tagesschau Zukunfts-Podcast: mal angenommen}. + \item [Reaktion] Der \Gls{podcatcher} synchronisiert die reduzierte Liste + der \Glspl{abo}. +\end{description} + +\item +\begin{description} + \item [Stand] Die \enquote{Zuletzt gehört}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den Reiter \enquote{Podcasts}. + \item [Reaktion] Der Browser wechselt zur \enquote{Podcasts}-Oberfläche. + Diese zeigt die aktuelle Liste aller abonnierten \Glspl{podcast}. Der Eintrag \enquote{Der tagesschau Zukunfts-Podcast: mal angenommen} ist nicht mehr in der Liste enthalten.\\ +\end{description} + +\end{enumerate} + +\newpage + +\subsection{Synchronisation: \Gls{episode} anhören}\label{t:sync-episode} +\vspace{0.3cm} + +\begin{enumerate} + +\item +\begin{description} + \item [Stand] Der Benutzer ist in einem synchronisierten \Gls{podcatcher} angemeldet. + \item [Aktion] Der Benutzer hört sich die \Gls{episode} \enquote{Kein Handel mit + China? Was dann?} des \Glspl{podcast} \enquote{Der tagesschau Zukunfts-Podcast: mal angenommen} bis zum Zeitpunkt 7 Minuten 19 Sekunden an. Dann beendet er die Wiedergabe. + \item [Reaktion] Der \Gls{podcatcher} synchronisiert den Fortschritt beim + Anhören der \Gls{episode}. +\end{description} + +\item +\begin{description} + \item [Stand] Die \enquote{Podcasts}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den Reiter \enquote{Zuletzt gehört}. + \item [Reaktion] Der Browser wechselt zur \enquote{Zuletzt + gehört}-Oberfläche. Diese zeigt eine Liste aller angefangenen, aber + nicht beendeten \Glspl{episode} mit korrespondierendem Hörfortschritt + an. Die Liste ist nach der Aktualität des Anhörens oder Ansehens einer + \Gls{episode} sortiert. Der oberste Eintrag ist die \Gls{episode} \enquote{Kein Handel mit China? Was dann?} mit dem Fortschritt 7 Minuten 19 Sekunden. +\end{description} + +\item +\begin{description} + \item [Stand] Der Benutzer meldet sich über ein anderes Gerät in einem + synchronisierten \Gls{podcatcher} an. + \item [Aktion] Der Benutzer hört sich die \Gls{episode} \enquote{Kein Handel mit + China? Was dann?} des \Glspl{podcast} \enquote{Der tagesschau Zukunfts-Podcast: mal angenommen} bis zum Zeitpunkt 4 Minuten 30 Sekunden an. Dann beendet er die Wiedergabe. + \item [Reaktion] Der \Gls{podcatcher} synchronisiert den Fortschritt beim + Anhören der \Gls{episode}. +\end{description} + +\item +\begin{description} + \item [Stand] Die \enquote{Podcasts}-Oberfläche ist im Browser geladen. + \item [Aktion] Der Benutzer klickt auf den Reiter \enquote{Zuletzt gehört}. + \item [Reaktion] Der Browser wechselt zur \enquote{Zuletzt + gehört}-Oberfläche. Der oberste Eintrag der \enquote{Zuletzt + gehört}-Liste ist die \Gls{episode} \enquote{Kein Handel mit China? Was dann?} mit dem Fortschritt 4 Minuten 30 Sekunden.\\ +\end{description} + +\end{enumerate} + + +\subsection{Benutzeranleitung anzeigen}\label{t:man} +\vspace{0.3cm} + +\begin{description} + \item [Stand] Der Benutzer ist im Webfrontend angemeldet. + \item [Aktion] Der Benutzer klickt auf den \enquote{Hilfe}-Button oben rechts (Abbildung \ref{fig:help-desktop}). + \item [Reaktion] Dem Benutzer wird ein leeres \enquote{Hilfe}-Fenster + angezeigt. (Dieses kann nachträglich um Hilfestellungen zum + Synchronisieren von \Glspl{podcast} ergänzt werden. \ref{r:no-man})\\ +\end{description} + + +\subsection{Lasttest}\label{t:lasttest} +\vspace{0.3cm} +Es werden Lasttests zur Überprüfung der Leitungsfähigkeit des Synchronisa\-tions-Server Systems durchgeführt. +Dabei müssen über einen längeren Zeitraum mindestens 50 Anfragen pro Sekunde verarbeitet werden. +Die Antwortzeit pro Anfrage darf dabei nicht mehr als 500 Millisekunden betragen. +Der Test gilt als bestanden, wenn diese Anforderungen erfüllt sind. + |