Compare commits
24 commits
d168b0c87e
...
main
Author | SHA1 | Date | |
---|---|---|---|
3b83ebf3fb | |||
a626e32cbe | |||
4c01e68264 | |||
7026909c61 | |||
d01a70f925 | |||
41143c361b | |||
3f6b622088 | |||
d5c6aad834 | |||
fe5b563139 | |||
ae82024e94 | |||
c5b595ad40 | |||
8bb37bbc21 | |||
74ca8d8973 | |||
deecf9ccad | |||
94070d8f75 | |||
c52308e623 | |||
d220f86cb8 | |||
a97c95f762 | |||
5816d4f914 | |||
617741218c | |||
a373ad4dce | |||
9f4e097e27 | |||
8e6a74d30c | |||
a1a719088d |
15 changed files with 152 additions and 25 deletions
|
@ -4,6 +4,9 @@ WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
RUN apt-get -y update
|
||||||
|
RUN apt-get -y install sqlite3
|
||||||
|
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
COPY /src .
|
COPY /src .
|
||||||
|
|
|
@ -6,6 +6,8 @@ RUN apt-get -y update && apt-get -y upgrade
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
RUN apt-get -y install sqlite3
|
||||||
|
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
COPY /src .
|
COPY /src .
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
autopep8==1.5.7
|
||||||
blinker==1.4
|
blinker==1.4
|
||||||
click==7.1.2
|
click==7.1.2
|
||||||
Deprecated==1.2.12
|
Deprecated==1.2.12
|
||||||
|
@ -16,11 +17,13 @@ MarkupSafe==1.1.1
|
||||||
passlib==1.7.4
|
passlib==1.7.4
|
||||||
pendulum==2.1.2
|
pendulum==2.1.2
|
||||||
py-buzz==1.0.3
|
py-buzz==1.0.3
|
||||||
|
pycodestyle==2.7.0
|
||||||
PyJWT==2.1.0
|
PyJWT==2.1.0
|
||||||
python-dateutil==2.8.1
|
python-dateutil==2.8.1
|
||||||
python-dotenv==0.17.1
|
python-dotenv==0.17.1
|
||||||
pytzdata==2020.1
|
pytzdata==2020.1
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
SQLAlchemy==1.4.15
|
SQLAlchemy==1.4.15
|
||||||
|
toml==0.10.2
|
||||||
Werkzeug==1.0.1
|
Werkzeug==1.0.1
|
||||||
wrapt==1.12.1
|
wrapt==1.12.1
|
||||||
|
|
|
@ -113,7 +113,7 @@ def refresh():
|
||||||
$ curl http://localhost:5000/api/refresh -X GET \
|
$ curl http://localhost:5000/api/refresh -X GET \
|
||||||
-H "Authorization: Bearer <your_token>"
|
-H "Authorization: Bearer <your_token>"
|
||||||
"""
|
"""
|
||||||
old_token = request.get_data()
|
old_token = flask.request.get_data()
|
||||||
new_token = guard.refresh_jwt_token(old_token)
|
new_token = guard.refresh_jwt_token(old_token)
|
||||||
ret = {'access_token': new_token}
|
ret = {'access_token': new_token}
|
||||||
return ret, 200
|
return ret, 200
|
||||||
|
|
|
@ -8,6 +8,8 @@ services:
|
||||||
backend-prod:
|
backend-prod:
|
||||||
image: caminsha/bt-backend
|
image: caminsha/bt-backend
|
||||||
container_name: backend-prod
|
container_name: backend-prod
|
||||||
|
volumes:
|
||||||
|
- "./database.db:/app/database.db:z"
|
||||||
environment:
|
environment:
|
||||||
DEBUG: "no"
|
DEBUG: "no"
|
||||||
PORT: 5050
|
PORT: 5050
|
||||||
|
@ -20,6 +22,6 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
||||||
mongodb:
|
mongodb:
|
||||||
image: mongo:4.0.1
|
image: mongo:4.0.25
|
||||||
container_name: "behametrics-mongo"
|
container_name: "behametrics-mongo"
|
||||||
command: mongod --smallfiles
|
command: mongod --smallfiles
|
||||||
|
|
|
@ -35,6 +35,6 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
||||||
mongodb:
|
mongodb:
|
||||||
image: mongo:4.0.1
|
image: mongo:4.0.25
|
||||||
container_name: "behametrics-mongo"
|
container_name: "behametrics-mongo"
|
||||||
command: mongod --smallfiles
|
command: mongod --smallfiles
|
||||||
|
|
|
@ -97,3 +97,13 @@ h1 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.study-finished {
|
||||||
|
background-color: var(--primary);
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.study-finished > p {
|
||||||
|
color: var(--error);
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import "./Footer.css";
|
import "./Footer.css";
|
||||||
import "@fortawesome/fontawesome-free/css/all.css";
|
|
||||||
|
|
||||||
function Footer() {
|
function Footer() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,11 +2,6 @@ import React from "react";
|
||||||
import "../App.css";
|
import "../App.css";
|
||||||
|
|
||||||
export default function GeneratedPassword(props) {
|
export default function GeneratedPassword(props) {
|
||||||
const handleOnCopyEvent = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -2,8 +2,8 @@ import React from "react";
|
||||||
import "../App.css";
|
import "../App.css";
|
||||||
import { Button } from "./Button";
|
import { Button } from "./Button";
|
||||||
import "./HeroSection.css";
|
import "./HeroSection.css";
|
||||||
import "@fortawesome/fontawesome-free/css/all.css";
|
|
||||||
import { useAuth } from "../auth/AuthProvider";
|
import { useAuth } from "../auth/AuthProvider";
|
||||||
|
import StudyFinished from "./StudyFinished";
|
||||||
|
|
||||||
export default function HeroSection() {
|
export default function HeroSection() {
|
||||||
const [isLoggedIn] = useAuth();
|
const [isLoggedIn] = useAuth();
|
||||||
|
@ -11,6 +11,7 @@ export default function HeroSection() {
|
||||||
return (
|
return (
|
||||||
<div className="hero-container">
|
<div className="hero-container">
|
||||||
<h1>Herzlich Willkommen</h1>
|
<h1>Herzlich Willkommen</h1>
|
||||||
|
<StudyFinished />
|
||||||
<div className="hero-btns">
|
<div className="hero-btns">
|
||||||
{isLoggedIn ? (
|
{isLoggedIn ? (
|
||||||
<Button
|
<Button
|
||||||
|
|
11
frontend/src/components/StudyFinished.jsx
Normal file
11
frontend/src/components/StudyFinished.jsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import React from "react";
|
||||||
|
import "../App.css"
|
||||||
|
|
||||||
|
export default function StudyFinished() {
|
||||||
|
return (
|
||||||
|
<div className="study-finished">
|
||||||
|
<p>Die Studie wurde beendet.</p>
|
||||||
|
<p>Vielen Dank für die Teilnahme an der Studie</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -73,7 +73,7 @@ export default function Lizenzen() {
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Behametrics Serverimplementierung (MIT-Lizenz)
|
Behametrics Serverimplementierung (MIT-Lizenz):{" "}
|
||||||
<a href="https://gitlab.com/behametrics/server">
|
<a href="https://gitlab.com/behametrics/server">
|
||||||
https://gitlab.com/behametrics/server
|
https://gitlab.com/behametrics/server
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -7,6 +7,89 @@ export default function Privacy() {
|
||||||
<>
|
<>
|
||||||
<div className="sitePage">
|
<div className="sitePage">
|
||||||
<h1>Datenschutz</h1>
|
<h1>Datenschutz</h1>
|
||||||
|
<p>
|
||||||
|
Nachfolgend werden Sie informiert, welche Daten ich von Ihnen erfasse
|
||||||
|
und erhebe. Grundsätzlich gilt, dass ich sämtliche Daten nach der
|
||||||
|
Bachelorthesis wieder lösche. Ausserdem gebe ich keine
|
||||||
|
personenbezogenen Daten an Dritte weiter. Nachfolgend werden die Daten
|
||||||
|
in folgende drei Kategorien eingeteilt:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Daten des Webservers</li>
|
||||||
|
<li>Anmelde- und Umfragedaten</li>
|
||||||
|
<li>Daten zu biometrischen Verhaltensmerkmalen</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Daten des Webservers</h2>
|
||||||
|
<p>
|
||||||
|
Diese Webanwendung wird auf einem virtuellen Server bei{" "}
|
||||||
|
<a href="https://netcup.de">netcup</a> betrieben. Um diese
|
||||||
|
Webanwendung grundsätzlich bereitzustellen, werden die folgenden Daten
|
||||||
|
erhoben:{" "}
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>IP-Adresse der Anfrage</li>
|
||||||
|
<li>URL der Anfrage</li>
|
||||||
|
<li>
|
||||||
|
User-Agent der Anfrage (also z.B. der verwendete Browser usw.)
|
||||||
|
</li>
|
||||||
|
<li>Status der Antwort</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Diese Informationen werden verwendet, um den reibungslosen Betrieb der
|
||||||
|
Webseit zu gewährleisten.{" "}
|
||||||
|
</p>
|
||||||
|
<h2>Anmelde- und Umfragedaten</h2>
|
||||||
|
<p>
|
||||||
|
Im Rahmen der Bachelorthesis erfasse ich einige Merkmale über Sie.
|
||||||
|
Hierzu zählen einerseits die Logindaten, welche erfasst werden müssen,
|
||||||
|
damit Sie sich einloggen können. Ausserdem erfasse ich die folgenden
|
||||||
|
Daten mit einer Umfrage:{" "}
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Alter </li>
|
||||||
|
<li>Geschlecht </li>
|
||||||
|
<li>Höchster Bildungsstand </li>
|
||||||
|
<li>Geschätzte Anwenderkenntnisse im Informatikbereich</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Die Anmeldedaten werden verwendet, damit Sie sich auf der Webseite
|
||||||
|
einloggen können. Damit Sie sich nicht jedes Mal anmelden müssen,
|
||||||
|
verwende ich die Methode von LocalStorage. Im Localstorage wird der
|
||||||
|
Wert REACT_TOKEN_AUTH_KEY gespeichert, welcher einen Zugangscode
|
||||||
|
enthält. Die Umfragedaten werden ausgewertet, damit ich die
|
||||||
|
Teilnehmenden einordnen kann. Die Daten werst sonst nicht
|
||||||
|
weiterverwertet.
|
||||||
|
</p>
|
||||||
|
<h2>Daten zu biometrischen Verhaltensmerkmalen</h2>
|
||||||
|
<p>
|
||||||
|
Während der Studie werden biometirsche Daten gesammelt. Zu den
|
||||||
|
biometrischen Daten gehören Mausbewegungen und Tastaturanschläge.
|
||||||
|
Diese Daten werden lediglich im Rahmen der Bachelorthesis verwendet
|
||||||
|
und ausgewertet. Nachdem die Bachelorthesis beendet ist, werden
|
||||||
|
sämtliche Daten gelöscht. Es erfolgt keine Auswertung der
|
||||||
|
biometrischen Daten im Zusammenhang mit den Daten der Umfrage.
|
||||||
|
Allerdings kann der Benutzername, welchen Sie bei der Anmeldung
|
||||||
|
angegeben haben, verwendet werden.
|
||||||
|
</p>
|
||||||
|
<h2>Weitergabe der Daten</h2>
|
||||||
|
<p>
|
||||||
|
Grundsätzlich werden die Daten nicht an Dritte weitergegeben. Folgende
|
||||||
|
Ausnahmen gibt es:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Der Fernfachhochschule Schweiz werden die Daten falls notwendig
|
||||||
|
weitergegeben.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Sofern es eine gesetzliche Grundlage gibt, werden die Daten auch
|
||||||
|
weitergegeben.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Wie bereits oben erwähnt, läuft die Webanwendung auf einem
|
||||||
|
virtuellen Server bei <a href="https://netcup.de">netcup</a>. Hierbei gelten die Datenschutzbestimmungen von netcup, welche <a href="https://www.netcup.de/kontakt/datenschutzerklaerung.php">hier</a> eingesehen werden können.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -12,6 +12,7 @@ import BehaviorPhone from "../BehaviorPhone";
|
||||||
import BehaviorStanding from "../BehaviorStanding";
|
import BehaviorStanding from "../BehaviorStanding";
|
||||||
import BehaviorStudyEnd from "../BehaviorStudyEnd";
|
import BehaviorStudyEnd from "../BehaviorStudyEnd";
|
||||||
import { authFetch } from "../../auth/AuthProvider";
|
import { authFetch } from "../../auth/AuthProvider";
|
||||||
|
import StudyFinished from "../StudyFinished";
|
||||||
|
|
||||||
export default function Study() {
|
export default function Study() {
|
||||||
const _logger = useRef(0);
|
const _logger = useRef(0);
|
||||||
|
@ -32,11 +33,7 @@ export default function Study() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
_logger.current = new Logger({
|
_logger.current = new Logger({
|
||||||
//inputs: ["cursor", "wheel", "keyboard", "touch"],
|
inputs: ["keyboard", "wheel", "cursor", "custom"],
|
||||||
inputs: ["keyboard"],
|
|
||||||
// apiUrl: "https://behavior.marcocamenzind.ch",
|
|
||||||
apiUrl: "http://localhost:5000",
|
|
||||||
logToConsole: true,
|
|
||||||
});
|
});
|
||||||
_logger.current.init();
|
_logger.current.init();
|
||||||
authFetch("/api/username", {
|
authFetch("/api/username", {
|
||||||
|
@ -94,7 +91,6 @@ export default function Study() {
|
||||||
method: "get",
|
method: "get",
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
response.json().then((resp) => {
|
response.json().then((resp) => {
|
||||||
console.log(resp.random_password);
|
|
||||||
setGenPassword(resp.random_password);
|
setGenPassword(resp.random_password);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -112,13 +108,18 @@ export default function Study() {
|
||||||
receiveRandomPassword();
|
receiveRandomPassword();
|
||||||
setState(STATES.NORMAL);
|
setState(STATES.NORMAL);
|
||||||
handleLoggerOn();
|
handleLoggerOn();
|
||||||
|
// map username and session with the logs
|
||||||
|
_logger.current.logCustomEvent({
|
||||||
|
name: serverUsername,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetInputValues = () => {
|
const resetInputValues = () => {
|
||||||
let inputElements = document.querySelectorAll('div input:not([type="submit"])');
|
let inputElements = document.querySelectorAll(
|
||||||
|
'div input:not([type="submit"])'
|
||||||
|
);
|
||||||
for (let i = 0; i < inputElements.length; i++) {
|
for (let i = 0; i < inputElements.length; i++) {
|
||||||
inputElements[i].value = ""
|
inputElements[i].value = "";
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -269,6 +270,7 @@ export default function Study() {
|
||||||
<>
|
<>
|
||||||
<div className="sitePage">
|
<div className="sitePage">
|
||||||
<h1>Studie</h1>
|
<h1>Studie</h1>
|
||||||
|
<StudyFinished />
|
||||||
{state === STATES.START ? study_start : null}
|
{state === STATES.START ? study_start : null}
|
||||||
{state === STATES.NORMAL ? study_normal : null}
|
{state === STATES.NORMAL ? study_normal : null}
|
||||||
{state === STATES.PHONE ? study_phone : null}
|
{state === STATES.PHONE ? study_phone : null}
|
||||||
|
|
24
requests.sh
24
requests.sh
|
@ -1,11 +1,11 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
ACTION=$1
|
ACTION=$1
|
||||||
TOKEN=$2
|
VALUE=$2
|
||||||
ACTIONS=(login register rcvpw username)
|
ACTIONS=(login register rcvpw username data csv prod_data prod_csv)
|
||||||
|
|
||||||
print_help(){
|
print_help(){
|
||||||
echo "Usage: $0 ACTION [TOKEN]"
|
echo "Usage: $0 ACTION [TOKEN|INPUT_TYPE]"
|
||||||
echo
|
echo
|
||||||
echo "available actions:"
|
echo "available actions:"
|
||||||
for el in "${ACTIONS[@]}"; do
|
for el in "${ACTIONS[@]}"; do
|
||||||
|
@ -34,7 +34,23 @@ case $ACTION in
|
||||||
;;
|
;;
|
||||||
"${ACTIONS[3]}") # get current username
|
"${ACTIONS[3]}") # get current username
|
||||||
echo "get username action"
|
echo "get username action"
|
||||||
curl localhost:5050/api/username -X GET -H "Authorization: Bearer $TOKEN"
|
curl localhost:5050/api/username -X GET -H "Authorization: Bearer $VALUE"
|
||||||
|
;;
|
||||||
|
"${ACTIONS[4]}") # get all data from behametricsserver
|
||||||
|
echo "get data action"
|
||||||
|
curl localhost:5000/data
|
||||||
|
;;
|
||||||
|
"${ACTIONS[5]}") # get all data from behametricsserver
|
||||||
|
echo "get csv from input action"
|
||||||
|
curl localhost:5000/data/csv/"${VALUE}"
|
||||||
|
;;
|
||||||
|
"${ACTIONS[6]}") # get all data from behametricsserver
|
||||||
|
echo "get prod data action"
|
||||||
|
curl behavior.marcocamenzind.ch:5000/data
|
||||||
|
;;
|
||||||
|
"${ACTIONS[7]}") # get all data from behametricsserver
|
||||||
|
echo "get prod csv from input action"
|
||||||
|
curl behavior.marcocamenzind.ch:5000/data/csv/"${VALUE}"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Action not available"
|
echo "Error: Action not available"
|
||||||
|
|
Loading…
Reference in a new issue