Compare commits
No commits in common. "main" and "ccd53bc2a10469a2441ac2d96dc4fa883ba92727" have entirely different histories.
main
...
ccd53bc2a1
52 changed files with 2360 additions and 1009 deletions
|
@ -1,2 +1 @@
|
|||
venv
|
||||
src/database.db
|
||||
|
|
|
@ -4,9 +4,6 @@ WORKDIR /app
|
|||
|
||||
COPY requirements.txt .
|
||||
|
||||
RUN apt-get -y update
|
||||
RUN apt-get -y install sqlite3
|
||||
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
COPY /src .
|
||||
|
|
|
@ -6,8 +6,6 @@ RUN apt-get -y update && apt-get -y upgrade
|
|||
|
||||
COPY requirements.txt .
|
||||
|
||||
RUN apt-get -y install sqlite3
|
||||
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
COPY /src .
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
autopep8==1.5.7
|
||||
blinker==1.4
|
||||
click==7.1.2
|
||||
Deprecated==1.2.12
|
||||
|
@ -17,13 +16,11 @@ MarkupSafe==1.1.1
|
|||
passlib==1.7.4
|
||||
pendulum==2.1.2
|
||||
py-buzz==1.0.3
|
||||
pycodestyle==2.7.0
|
||||
PyJWT==2.1.0
|
||||
python-dateutil==2.8.1
|
||||
python-dotenv==0.17.1
|
||||
pytzdata==2020.1
|
||||
six==1.16.0
|
||||
SQLAlchemy==1.4.15
|
||||
toml==0.10.2
|
||||
Werkzeug==1.0.1
|
||||
wrapt==1.12.1
|
||||
|
|
|
@ -5,7 +5,6 @@ import flask_sqlalchemy
|
|||
import flask_praetorian
|
||||
import flask_cors
|
||||
import sys
|
||||
from password_util import get_random_password
|
||||
|
||||
db = flask_sqlalchemy.SQLAlchemy()
|
||||
guard = flask_praetorian.Praetorian()
|
||||
|
@ -76,12 +75,6 @@ db.init_app(app)
|
|||
# Initializes CORS so that the api_tool can talk to the example app
|
||||
cors.init_app(app)
|
||||
|
||||
# create database
|
||||
# Add users for the example
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@app.route('/api/login', methods=['POST'])
|
||||
def login():
|
||||
|
@ -113,20 +106,13 @@ def refresh():
|
|||
$ curl http://localhost:5000/api/refresh -X GET \
|
||||
-H "Authorization: Bearer <your_token>"
|
||||
"""
|
||||
old_token = flask.request.get_data()
|
||||
print("refresh request")
|
||||
old_token = request.get_data()
|
||||
new_token = guard.refresh_jwt_token(old_token)
|
||||
ret = {'access_token': new_token}
|
||||
return ret, 200
|
||||
|
||||
|
||||
@app.route('/api/username', methods=['GET'])
|
||||
@flask_praetorian.auth_required
|
||||
def get_username():
|
||||
username = flask_praetorian.current_user().username
|
||||
ret = {'username': username}
|
||||
return ret, 200
|
||||
|
||||
|
||||
@app.route('/api/protected')
|
||||
@flask_praetorian.auth_required
|
||||
def protected():
|
||||
|
@ -141,13 +127,6 @@ def protected():
|
|||
return {'message': f'protected endpoint (allowed user {flask_praetorian.current_user().username})'}
|
||||
|
||||
|
||||
@app.route('/api/rcv_pw', methods=['GET'])
|
||||
def get_password():
|
||||
pw = get_random_password()
|
||||
ret = {'random_password': pw}
|
||||
return ret, 200
|
||||
|
||||
|
||||
@app.route('/api/register', methods=['POST'])
|
||||
def register():
|
||||
req = flask.request.get_json(force=True)
|
||||
|
@ -173,17 +152,6 @@ def register():
|
|||
return ret, 409
|
||||
|
||||
|
||||
@app.route('/api/protected/behavior', methods=['POST'])
|
||||
@flask_praetorian.auth_required
|
||||
def check_password_username():
|
||||
req = flask.request.get_json(force=True)
|
||||
token = guard.read_token_from_header()
|
||||
extracted_token = guard.extract_jwt_token(token)
|
||||
id_req = extracted_token['id']
|
||||
ret = {'message': 'Top'}
|
||||
return ret, 200
|
||||
|
||||
|
||||
@app.route('/api/protected/umfrage', methods=['POST'])
|
||||
@flask_praetorian.auth_required
|
||||
def survey():
|
||||
|
@ -247,6 +215,7 @@ def survey():
|
|||
user_db.education = education
|
||||
user_db.skills = skills
|
||||
db.session.commit()
|
||||
print(req)
|
||||
ret = {'message': 'Vielen Dank für das Ausfüllen der Umfrage.'}
|
||||
return ret, 200
|
||||
else:
|
||||
|
@ -255,6 +224,14 @@ def survey():
|
|||
return ret, 400
|
||||
|
||||
|
||||
@app.route('/api/protected/behavior', methods=['POST'])
|
||||
@flask_praetorian.auth_required
|
||||
def check_password_username():
|
||||
print("hallooo POST", file=sys.stderr)
|
||||
ret = {'message': 'Top'}
|
||||
return ret, 200
|
||||
|
||||
|
||||
# Run the example
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=debug, host=host, port=port)
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
from random import seed
|
||||
from random import randint
|
||||
import time
|
||||
|
||||
seed(int(time.time()))
|
||||
|
||||
|
||||
def get_random_value(list_length):
|
||||
random_select = randint(0, list_length)
|
||||
return random_select
|
||||
|
||||
|
||||
def get_random_password():
|
||||
|
||||
first_part = [
|
||||
"Der Vogel",
|
||||
"Die Ameise",
|
||||
"Die Biene",
|
||||
"Ein Mensch",
|
||||
"Jemand",
|
||||
"Der Hund",
|
||||
"Der Kater",
|
||||
]
|
||||
|
||||
second_part = [
|
||||
"%",
|
||||
"(",
|
||||
")",
|
||||
"$",
|
||||
"+",
|
||||
"!",
|
||||
]
|
||||
|
||||
third_part = [
|
||||
"frisst",
|
||||
"küsst",
|
||||
"begrüsst",
|
||||
"besucht",
|
||||
"beeinflusst",
|
||||
"isst",
|
||||
"findet",
|
||||
"vergisst",
|
||||
]
|
||||
|
||||
forth_part = [
|
||||
"1 Vogel!",
|
||||
"2 Vögel!",
|
||||
"3 Vögel!",
|
||||
"4 Vögel!",
|
||||
"5 Vögel!",
|
||||
"6 Vögel!",
|
||||
"7 Vögel!",
|
||||
"8 Vögel!",
|
||||
"9 Vögel!",
|
||||
"1 Mücke",
|
||||
"2 Mücken!",
|
||||
"3 Mücken!",
|
||||
"4 Mücken!",
|
||||
"5 Mücken!",
|
||||
"6 Mücken!",
|
||||
"7 Mücken!",
|
||||
"8 Mücken!",
|
||||
"9 Mücken!",
|
||||
"1 Adler",
|
||||
"2 Adler!",
|
||||
"3 Adler!",
|
||||
"4 Adler!",
|
||||
"5 Adler!",
|
||||
"6 Adler!",
|
||||
"7 Adler!",
|
||||
"8 Adler!",
|
||||
"9 Adler!",
|
||||
"1 Apfel",
|
||||
"2 Äpfel!",
|
||||
"3 Äpfel!",
|
||||
"4 Äpfel!",
|
||||
"5 Äpfel!",
|
||||
"6 Äpfel!",
|
||||
"7 Äpfel!",
|
||||
"8 Äpfel!",
|
||||
"9 Äpfel!",
|
||||
"1 Birne",
|
||||
"2 Birnen!",
|
||||
"3 Birnen!",
|
||||
"4 Birnen!",
|
||||
"5 Birnen!",
|
||||
"6 Birnen!",
|
||||
"7 Birnen!",
|
||||
"8 Birnen!",
|
||||
"9 Birnen!",
|
||||
"1 Biene",
|
||||
"2 Bienen!",
|
||||
"3 Bienen!",
|
||||
"4 Bienen!",
|
||||
"5 Bienen!",
|
||||
"6 Bienen!",
|
||||
"7 Bienen!",
|
||||
"8 Bienen!",
|
||||
"9 Bienen!",
|
||||
"1 Gurke",
|
||||
"2 Gurken!",
|
||||
"3 Gurken!",
|
||||
"4 Gurken!",
|
||||
"5 Gurken!",
|
||||
"6 Gurken!",
|
||||
"7 Gurken!",
|
||||
"8 Gurken!",
|
||||
"9 Gurken!",
|
||||
]
|
||||
|
||||
password = ""
|
||||
password += str(first_part[get_random_value(len(first_part)-1)])
|
||||
password += " " + str(second_part[get_random_value(len(second_part)-1)])
|
||||
password += " " + str(third_part[get_random_value(len(third_part)-1)])
|
||||
password += " " + str(forth_part[get_random_value(len(forth_part)-1)])
|
||||
|
||||
return password
|
|
@ -1,27 +1,14 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
frontend-prod:
|
||||
frontend_bt:
|
||||
image: caminsha/bt-frontend
|
||||
container_name: frontend-prod
|
||||
container_name: frontend_bt_prod
|
||||
ports:
|
||||
- 3000:80
|
||||
- 3000:3000
|
||||
backend-prod:
|
||||
image: caminsha/bt-backend
|
||||
container_name: backend-prod
|
||||
volumes:
|
||||
- "./database.db:/app/database.db:z"
|
||||
container_name: backend_bt
|
||||
environment:
|
||||
DEBUG: "no"
|
||||
PORT: 5050
|
||||
PORT: 5000
|
||||
HOST: "0.0.0.0"
|
||||
behametrics-server:
|
||||
image: registry.gitlab.com/behametrics/server:latest
|
||||
container_name: "behametrics-server"
|
||||
ports:
|
||||
- 5000:5000
|
||||
environment:
|
||||
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
||||
mongodb:
|
||||
image: mongo:4.0.25
|
||||
container_name: "behametrics-mongo"
|
||||
command: mongod --smallfiles
|
||||
|
|
|
@ -2,7 +2,7 @@ version: '3.7'
|
|||
|
||||
services:
|
||||
frontend-dev:
|
||||
container_name: frontend-dev
|
||||
container_name: hello_world_client
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
|
@ -14,27 +14,16 @@ services:
|
|||
environment:
|
||||
- CHOKIDAR_USEPOLLING=true
|
||||
backend-dev:
|
||||
container_name: backend-dev
|
||||
container_name: backend_bt
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
tty: true
|
||||
volumes:
|
||||
- ./backend/src:/app/
|
||||
ports:
|
||||
- 5050:5050
|
||||
environment:
|
||||
DEBUG: "yes"
|
||||
PORT: 5050
|
||||
HOST: "0.0.0.0"
|
||||
behametrics-server:
|
||||
image: registry.gitlab.com/behametrics/server:latest
|
||||
container_name: "behametrics-server"
|
||||
ports:
|
||||
- 5000:5000
|
||||
environment:
|
||||
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
||||
mongodb:
|
||||
image: mongo:4.0.25
|
||||
container_name: "behametrics-mongo"
|
||||
command: mongod --smallfiles
|
||||
DEBUG: "yes"
|
||||
PORT: 5000
|
||||
HOST: "0.0.0.0"
|
||||
|
|
|
@ -10,7 +10,9 @@ server {
|
|||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://backend-prod:5050;
|
||||
# include uwsgi_params;
|
||||
# uwsgi_pass http://backend-prod:5000;
|
||||
proxy_pass http://backend-prod:5000;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
|
2068
frontend/package-lock.json
generated
2068
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -5,11 +5,18 @@
|
|||
"dependencies": {
|
||||
"@behametrics/logger-web": "^3.1.1",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"@react-hook/mouse-position": "^4.1.0",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"npm": "^7.19.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-form-with-constraints": "^0.18.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "4.0.3",
|
||||
"react-token-auth": "^1.1.8"
|
||||
"react-token-auth": "^1.1.8",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
@ -35,5 +42,5 @@
|
|||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://localhost:5050"
|
||||
"proxy": "http://localhost:5000"
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 3.8 KiB |
|
@ -28,13 +28,10 @@
|
|||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>BA - Marco Camenzind</title>
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript
|
||||
>Diese Anwendung funktioniert leider nur mit JavaScript. Bitte aktivieren
|
||||
JavaScript in den Einstellungen</noscript
|
||||
>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
|
|
|
@ -40,10 +40,6 @@
|
|||
color: var(--primary);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover:not(.navbar-logo) {
|
||||
border-bottom: 4px dotted var(--secondary);
|
||||
}
|
||||
|
@ -55,32 +51,21 @@ a:hover:not(.navbar-logo) {
|
|||
}
|
||||
|
||||
h1 {
|
||||
font-size: 4.5em;
|
||||
font-size: 5em;
|
||||
margin: 0.7em auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sitePage h2 {
|
||||
font-size: 3.7em;
|
||||
font-size: 3.75em;
|
||||
margin: 0.7em auto;
|
||||
}
|
||||
|
||||
.sitePage h3 {
|
||||
font-size: 2em;
|
||||
margin: 0.5em auto;
|
||||
}
|
||||
|
||||
.sitePage p {
|
||||
font-size: 1.5em;
|
||||
max-width: 60%;
|
||||
margin-bottom: 4vh;
|
||||
}
|
||||
|
||||
.sitePage ul li {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
|
||||
.errorMessage {
|
||||
color: var(--error);
|
||||
max-width: 60%;
|
||||
|
@ -92,18 +77,3 @@ h1 {
|
|||
.bildnachweise {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.generated-password {
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.study-finished {
|
||||
background-color: var(--primary);
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.study-finished > p {
|
||||
color: var(--error);
|
||||
font-size: 2em;
|
||||
}
|
||||
|
|
|
@ -4,17 +4,20 @@ import "./App.css";
|
|||
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
|
||||
import Home from "./components/pages/Home";
|
||||
import Ueber from "./components/pages/Ueber";
|
||||
import Lizenzen from "./components/pages/Lizenzen";
|
||||
import Lizenzen from "./components/pages/lizenzen";
|
||||
import Privacy from "./components/pages/Privacy";
|
||||
import Login from "./components/pages/Login";
|
||||
import Register from "./components/pages/Register";
|
||||
import Manual from "./components/pages/Manual";
|
||||
import Secret from "./components/pages/Secret";
|
||||
import Umfrage from "./components/pages/Umfrage";
|
||||
import PrivateRoute from "./auth/PrivateRoute";
|
||||
import Study from "./components/pages/Study";
|
||||
import Secret from "./components/pages/Secret";
|
||||
import { useAuth } from "./auth/AuthProvider";
|
||||
import BehaviorNormal from "./components/pages/BehaviorNormal";
|
||||
|
||||
function App() {
|
||||
const [isLoggedIn] = useAuth();
|
||||
isLoggedIn ? (document.title = isLoggedIn) : document.title = isLoggedIn;
|
||||
return (
|
||||
<>
|
||||
<Router>
|
||||
|
@ -28,7 +31,7 @@ function App() {
|
|||
<Route path="/register" component={Register} />
|
||||
<Route path="/manual" component={Manual} />
|
||||
<Route path="/ueber" component={Ueber} />
|
||||
<PrivateRoute path="/study" component={Study} />
|
||||
<PrivateRoute path="/behavior" component={BehaviorNormal} />
|
||||
<PrivateRoute path="/secret" component={Secret} />
|
||||
<PrivateRoute path="/umfrage" component={Umfrage} />
|
||||
</Switch>
|
|
@ -92,6 +92,45 @@
|
|||
color: #b1b1b1;
|
||||
}
|
||||
|
||||
/* Social Icons */
|
||||
.social-icon-link {
|
||||
color: var(--forth);
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.social-media {
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.social-media-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 99%;
|
||||
max-width: 1000px;
|
||||
margin: 40px auto 0 auto;
|
||||
}
|
||||
|
||||
.social-icons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.social-logo {
|
||||
color: var(--forth);
|
||||
justify-self: start;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
align-self: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 820px) {
|
||||
.footer-links {
|
||||
padding-top: 2rem;
|
||||
|
@ -109,4 +148,7 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.social-media-wrap {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import "./Footer.css";
|
||||
import "@fortawesome/fontawesome-free/css/all.css";
|
||||
|
||||
function Footer() {
|
||||
return (
|
7
frontend/src/components/Author.js
Normal file
7
frontend/src/components/Author.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
function AuthorDate() {
|
||||
return <div></div>;
|
||||
}
|
||||
|
||||
export default AuthorDate;
|
|
@ -1,16 +0,0 @@
|
|||
import React from "react";
|
||||
import "../App.css";
|
||||
import GeneratedPassword from "./GeneratedPassword";
|
||||
|
||||
export default function BehaviorNormal(props) {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Zu Beginn geht es darum, dass Sie ganz normal den Benutzernamen und das
|
||||
Passwort eingeben. Verhalten Sie sich einfach so, als ob Sie sich
|
||||
normalerweise anmelden.
|
||||
</p>
|
||||
<GeneratedPassword genPassword={props.genPassword} />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import React from "react";
|
||||
import "../App.css";
|
||||
import GeneratedPassword from "./GeneratedPassword";
|
||||
|
||||
export default function BehaviorPhone(props) {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Im nächsten Schritt geht es darum, dass Sie während der Passworteingabe
|
||||
telefonieren. Nehmen Sie hierzu Ihr Smartphone oder Telefon und stellen
|
||||
Sie sich vor, dass Sie gerade am Telefonieren sind. Verwenden Sie bitte
|
||||
kein Headset oder Ähnliches.
|
||||
</p>
|
||||
<GeneratedPassword genPassword={props.genPassword} />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import React from "react";
|
||||
import "../App.css";
|
||||
import GeneratedPassword from "./GeneratedPassword";
|
||||
|
||||
export default function BehaviorStanding(props) {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
In dieser Situation geht es darum, dass Sie das Passwort im Stehen
|
||||
eingeben. Stehen Sie also vor den Computer und geben Sie den
|
||||
Benutzernamen und das Passwort wie gewohnt ein.
|
||||
</p>
|
||||
<GeneratedPassword genPassword={props.genPassword} />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import React from "react";
|
||||
import "../App.css";
|
||||
|
||||
export default function BehaviorStudyEnd() {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Vielen Dank, dass Sie an der Studie teilgenommen haben. Sie helfen mir
|
||||
mit Ihrer Teilnahme enorm für die Bachelorthesis weiter.
|
||||
</p>
|
||||
<p>
|
||||
Damit ich möglichst aussagekräftige Ergebnisse erhalte, ist es für mich
|
||||
wichtig, dass Sie mehrmals an der Studie teilnehmen. Daher bitte ich
|
||||
Sie, dass Sie zu einem anderen Zeitpunkt die Studie wiederholen.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import React from "react";
|
||||
import "../App.css";
|
||||
|
||||
export default function BehaviorStudyInfo() {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Nachfolgend werden Sie einige Schritte durchlaufen, um ihre
|
||||
Nutzerinteraktion messen zu können. Verwenden Sie hierbei jeweils ihren
|
||||
Benutzernamen, welchen Sie bereits zuvor genutzt haben. Das Passwort
|
||||
wird jeweils generiert.
|
||||
</p>
|
||||
<p>
|
||||
Bitte klicken Sie auf weiter, um mit der Studie zu beginnen. Bitte lesen
|
||||
Sie die jeweilige Aufgabe jeweils genau.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -31,12 +31,6 @@
|
|||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.btn--full {
|
||||
padding: 12px 26px;
|
||||
margin: 0 auto;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.btn--large:hover,
|
||||
.btn--medium:hover {
|
||||
transition: all 0.3s ease-out;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Link } from "react-router-dom";
|
|||
|
||||
const STYLES = ["btn--primary", "btn--outline"];
|
||||
|
||||
const SIZES = ["btn--medium", "btn--large", "btn--full"];
|
||||
const SIZES = ["btn--medium", "btn--large"];
|
||||
export const Button = ({
|
||||
children,
|
||||
type,
|
|
@ -4,7 +4,7 @@ import "../App.css";
|
|||
export default function ErrorMessage(props) {
|
||||
return (
|
||||
<>
|
||||
<p className="errorMessage">{props.message}</p>
|
||||
<p className="errorMessage">{props.message}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import React from "react";
|
||||
import "../App.css";
|
||||
|
||||
export default function GeneratedPassword(props) {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
Das Passwort für diese Situation lautet:{" "}
|
||||
<span className="generated-password">{props.genPassword}</span>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -2,23 +2,22 @@ import React from "react";
|
|||
import "../App.css";
|
||||
import { Button } from "./Button";
|
||||
import "./HeroSection.css";
|
||||
import "@fortawesome/fontawesome-free/css/all.css";
|
||||
import { useAuth } from "../auth/AuthProvider";
|
||||
import StudyFinished from "./StudyFinished";
|
||||
|
||||
export default function HeroSection() {
|
||||
function HeroSection() {
|
||||
const [isLoggedIn] = useAuth();
|
||||
|
||||
return (
|
||||
<div className="hero-container">
|
||||
<h1>Herzlich Willkommen</h1>
|
||||
<StudyFinished />
|
||||
<div className="hero-btns">
|
||||
{isLoggedIn ? (
|
||||
<Button
|
||||
className="btns"
|
||||
buttonStyle="btn--primary"
|
||||
buttonSize="btn--large"
|
||||
newTo="study"
|
||||
newTo="behavior"
|
||||
>
|
||||
Zur Studie
|
||||
</Button>
|
||||
|
@ -54,3 +53,5 @@ export default function HeroSection() {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default HeroSection;
|
|
@ -6,8 +6,7 @@ import "@fortawesome/fontawesome-free/css/all.css";
|
|||
|
||||
function Navbar() {
|
||||
const [click, setClick] = useState(false);
|
||||
// eslint-disable-next-line
|
||||
const [button, setButton] = useState(true);
|
||||
const [button,setButton] = useState(true);
|
||||
|
||||
const handleClick = () => setClick(!click);
|
||||
const closeMobileMenu = () => setClick(false);
|
||||
|
@ -44,17 +43,6 @@ function Navbar() {
|
|||
Startseite
|
||||
</Link>
|
||||
</li>
|
||||
{isLoggedIn && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
to="/study"
|
||||
className="nav-links"
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
Studie
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
<li className="nav-item">
|
||||
<Link to="/Ueber" className="nav-links" onClick={closeMobileMenu}>
|
||||
Über
|
|
@ -1,11 +0,0 @@
|
|||
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>
|
||||
);
|
||||
}
|
120
frontend/src/components/pages/BehaviorNormal.js
Normal file
120
frontend/src/components/pages/BehaviorNormal.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
import React, { useEffect, useState} from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
import { Logger } from "@behametrics/logger-web";
|
||||
import { useAuth } from "../../auth/AuthProvider";
|
||||
import InputField from "../InputField";
|
||||
import SubmitField from "../SubmitField";
|
||||
|
||||
export default function BehaviorNormal() {
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const handleUsernameChange = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
const handlePasswordChange = (e) => {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
|
||||
const handleOnCopyEvent = (e) => {
|
||||
e.preventDefault();
|
||||
console.log("copy not allowed");
|
||||
return false;
|
||||
};
|
||||
|
||||
const handleOnPasteEvent = (e) => {
|
||||
e.preventDefault();
|
||||
console.log("paste not allowed");
|
||||
return false;
|
||||
};
|
||||
|
||||
const onSubmitClick = (e) => {
|
||||
e.preventDefault();
|
||||
let opts = {
|
||||
username: username,
|
||||
password: password,
|
||||
};
|
||||
fetch("/api/protected/behavior", {
|
||||
method: "post",
|
||||
body: JSON.stringify(opts),
|
||||
}).then((response) => {
|
||||
if (response.status === 401) {
|
||||
response.json().then((resp) => {
|
||||
console.log("nicht so wirklich gut");
|
||||
// setErrorMessage(resp.message);
|
||||
});
|
||||
} else {
|
||||
response.json().then((token) => {
|
||||
console.log("Alles gut :-)");
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let logger = new Logger({
|
||||
//inputs: ["cursor", "wheel", "keyboard", "touch"],
|
||||
inputs: ["keyboard"],
|
||||
// logToConsole: true,
|
||||
});
|
||||
logger.init();
|
||||
|
||||
let [isLoggedIn] = useAuth();
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `${isLoggedIn}`;
|
||||
if (isLoggedIn === false) {
|
||||
logger.stop();
|
||||
} else {
|
||||
logger.start();
|
||||
}
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<h1>Studie</h1>
|
||||
<p>
|
||||
Nachfolgend werden Sie einige Schritte durchlaufen, um ihre
|
||||
Nutzerinteraktion messen zu können. Verwenden Sie hierbei jeweils
|
||||
ihren Benutzernamen, welchen Sie bereits zuvor genutzt haben. Das
|
||||
Passwort wird jeweils generiert.
|
||||
</p>
|
||||
<p>
|
||||
Zu Beginn geht es darum, dass Sie ganz normal den Benutzernamen und
|
||||
das Passwort eingeben. Verhalten Sie sich einfach so, als ob Sie sich
|
||||
normalerweise anmelden.
|
||||
</p>
|
||||
<p onCopy={handleOnCopyEvent}>
|
||||
Das Passwort für diese Situation lautet: abcdefgeh
|
||||
</p>
|
||||
<form action="#">
|
||||
<InputField
|
||||
LabelName="Benutzername"
|
||||
onChange={handleUsernameChange}
|
||||
InputType="text"
|
||||
InputName="Benutzername"
|
||||
InputPlaceHolder="Benutzername"
|
||||
onCopy={handleOnCopyEvent}
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<InputField
|
||||
LabelName="Passwort"
|
||||
onChange={handlePasswordChange}
|
||||
InputType="password"
|
||||
InputName="Passwort"
|
||||
InputPlaceHolder="Benutzername"
|
||||
onCopy={handleOnCopyEvent}
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<SubmitField
|
||||
LabelName="Weiter zur nächsten Situation"
|
||||
InputValue="next-situation"
|
||||
InputName="Weiter"
|
||||
onClick={onSubmitClick}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
import React from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
|
||||
export default function Lizenzen() {
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage license">
|
||||
<h1>Lizenzen und Bildnachweise</h1>
|
||||
<p>
|
||||
Nachfolgend sollen die verwendeten Bibliotheken inklusive der Lizenz
|
||||
aufgeführt werden. Neben den Bibliotheken sollen vorallem auch
|
||||
Bildnachweise notiert werden.
|
||||
</p>
|
||||
<h2>Verwendete Bibliotheken</h2>
|
||||
<h3>Frontend</h3>
|
||||
<ul>
|
||||
<li>
|
||||
ReactJS (MIT-Lizenz):{" "}
|
||||
<a href="https://github.com/facebook/react">
|
||||
https://github.com/facebook/react
|
||||
</a>{" "}
|
||||
</li>
|
||||
<li>
|
||||
Behametrics Web-Logger (MIT-Lizenz):{" "}
|
||||
<a href="https://gitlab.com/behametrics/logger-web">
|
||||
https://gitlab.com/behametrics/logger-web
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
Fortawesome Icons (CC-BY-4.0):{" "}
|
||||
<a href="https://github.com/FortAwesome/Font-Awesome">
|
||||
https://github.com/FortAwesome/Font-Awesome
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
React-Token-Auth (ISC-Lizenz):{" "}
|
||||
<a href="https://github.com/obabichev/react-token-auth">
|
||||
https://github.com/obabichev/react-token-auth
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
react-router-dom (MIT-Lizenz)
|
||||
<a href="https://github.com/ReactTraining/react-router">
|
||||
https://github.com/ReactTraining/react-router
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Backend</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Flask (BSD-3-Lizenz):{" "}
|
||||
<a href="https://github.com/pallets/flask/">
|
||||
https://github.com/pallets/flask/
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
flask-sqlalchemy (BSD-3-Lizenz):{" "}
|
||||
<a href="https://github.com/pallets/flask-sqlalchemy">
|
||||
https://github.com/pallets/flask-sqlalchemy
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
flask-praetorian (MIT-Lizenz):{" "}
|
||||
<a href="https://github.com/dusktreader/flask-praetorian">
|
||||
https://github.com/dusktreader/flask-praetorian
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
Flask-CORS (MIT-Lizenz):{" "}
|
||||
<a href="https://github.com/corydolphin/flask-cors">
|
||||
https://github.com/corydolphin/flask-cors
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
Behametrics Serverimplementierung (MIT-Lizenz):{" "}
|
||||
<a href="https://gitlab.com/behametrics/server">
|
||||
https://gitlab.com/behametrics/server
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Bildnachweise</h2>
|
||||
<ul className="bildnachweise">
|
||||
<li>
|
||||
Originalbild für die Startseite:{" "}
|
||||
<a href="https://pixabay.com/illustrations/virtual-identity-digital-identity-69996/">
|
||||
https://pixabay.com/illustrations/virtual-identity-digital-identity-69996/
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import React, {useState} from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
import InputField from "../InputField";
|
||||
|
@ -70,7 +70,7 @@ export default function Login() {
|
|||
</form>
|
||||
) : (
|
||||
<>
|
||||
<Redirect to="/study" />
|
||||
<Redirect to="/behavior" />
|
||||
</>
|
||||
)}
|
||||
</div>
|
14
frontend/src/components/pages/Manual.js
Normal file
14
frontend/src/components/pages/Manual.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import React from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
|
||||
export default function Manual() {
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<h1> Anleitung / Bedienungshinweise</h1>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
|
||||
export default function Manual() {
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<h1> Anleitung / Bedienungshinweise</h1>
|
||||
<p>
|
||||
Vielen Dank für Ihr Interesse an meiner Bachelorthesis. Falls Sie noch
|
||||
grundlegende Informationen benötigen, können Sie diese{" "}
|
||||
<Link to="ueber">hier</Link> genauer anschauen. Hier geht es darum,
|
||||
dass ich Ihnen eine kurze Anleitung zur Verfügung stelle und erkäre
|
||||
wie das ganze funktioniert.
|
||||
</p>
|
||||
<h2>Neu hier</h2>
|
||||
<p>
|
||||
Bei Besuchern, die das erste Mal hier sind, geht es um zwei Dinge.
|
||||
Erstens müssen sich diese registrieren und zweitens sollte eine
|
||||
Umfrage durchgeführt werden. Diese Umfrage dient dazu, dass ich eine
|
||||
grobe Übersicht habe, welche Personengruppen teilgenommen haben. Für
|
||||
die Registrierung klicken Sie oben rechts einfach auf registieren. Sie
|
||||
müssen dann einen Nutzernamen und ein Passwort eingeben. Schauen Sie
|
||||
darauf, dass Sie sich den Benutzernamen und das Passwort merken
|
||||
können. Es gibt keine Möglichkeit, das Passwort oder den Benutzernamen
|
||||
zurückzusetzen. Nach der Registrierung landen Sie auf einer
|
||||
Umfrageseite. Füllen Sie die Fragen wahrheitsgemäss aus und klicken
|
||||
Sie danach auf "Umfrage abschicken". Nachdem die Umfrage durchgeführt
|
||||
wurde, können Sie an der Studie teilnehmen, indem Sie auf den Button
|
||||
"Studie starten" klicken. Folgen Sie danach den Anweisungen gemäss der
|
||||
Studie.
|
||||
</p>
|
||||
<h2>War schon einmal hier</h2>
|
||||
<p>Wenn Sie schon einmal hier waren, gibt es zwei mögliche Zustände:</p>
|
||||
<ul>
|
||||
<li>Sie sind noch eingeloggt</li>
|
||||
<li>Sie sind nicht mehr eingeloggt</li>
|
||||
</ul>
|
||||
<p>
|
||||
Sofern Sie noch nicht eingeloggt sind, können Sie sich anmelden mit
|
||||
ihrem gewählten Benutzernamen und dem Passwort. Sie landen dann direkt
|
||||
auf der Seite, welche ich für meine Studie benötige. Führen Sie dort
|
||||
die Studie die Studie wie gewohnt durch und beenden Sie diese am
|
||||
Schluss der Studie mit dem Button "Studie beenden".
|
||||
</p>
|
||||
<p>
|
||||
Wenn Sie bereits eingeloggt sind, dann landen Sie auf der Startseite.
|
||||
Sie finden in der Mitte einen Button mit der Überschrift "Zur Studie".
|
||||
Klicken Sie bitte auf diesen Button und führen Sie dann die Studie
|
||||
durch.
|
||||
</p>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
15
frontend/src/components/pages/Privacy.js
Normal file
15
frontend/src/components/pages/Privacy.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import React from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
|
||||
export default function Privacy() {
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<h1>Datenschutz</h1>
|
||||
</div>
|
||||
"
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
import React from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
|
||||
export default function Privacy() {
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<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>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import React, {useState} from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
import InputField from "../InputField";
|
|
@ -1,283 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
import InputField from "../InputField";
|
||||
import SubmitField from "../SubmitField";
|
||||
import ErrorMessage from "../ErrorMessage";
|
||||
import { Logger } from "@behametrics/logger-web";
|
||||
import { Button } from "../Button";
|
||||
import BehaviorStudyInfo from "../BehaviorStudyInfo";
|
||||
import BehaviorNormal from "../BehaviorNormal";
|
||||
import BehaviorPhone from "../BehaviorPhone";
|
||||
import BehaviorStanding from "../BehaviorStanding";
|
||||
import BehaviorStudyEnd from "../BehaviorStudyEnd";
|
||||
import { authFetch } from "../../auth/AuthProvider";
|
||||
import StudyFinished from "../StudyFinished";
|
||||
|
||||
export default function Study() {
|
||||
const _logger = useRef(0);
|
||||
const [serverUsername, setServerUsername] = useState("");
|
||||
const [genPassword, setGenPassword] = useState("");
|
||||
const STATES = {
|
||||
START: "start",
|
||||
NORMAL: "normal",
|
||||
PHONE: "phone",
|
||||
STANDING: "standing",
|
||||
END: "end",
|
||||
};
|
||||
const [state, setState] = useState(STATES.START);
|
||||
const [isInputCorrect, setIsInputCorrect] = useState(true);
|
||||
|
||||
const errorText =
|
||||
"Das Passwort und der Benutzername stimmen nicht überein. Bitte prüfen Sie, dass Sie das Passwort richtig abgetippt und den Benutzernamen richtig eingegeben haben.";
|
||||
|
||||
useEffect(() => {
|
||||
_logger.current = new Logger({
|
||||
inputs: ["keyboard", "wheel", "cursor", "custom"],
|
||||
});
|
||||
_logger.current.init();
|
||||
authFetch("/api/username", {
|
||||
method: "get",
|
||||
}).then((response) => {
|
||||
response.json().then((resp) => {
|
||||
setServerUsername(resp.username);
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
let username = "";
|
||||
const setUsername = (tmp_username) => {
|
||||
username = tmp_username;
|
||||
};
|
||||
|
||||
let password = "";
|
||||
const setPassword = (tmp_password) => {
|
||||
password = tmp_password;
|
||||
};
|
||||
|
||||
const handleLoggerOff = () => {
|
||||
_logger.current.stop();
|
||||
console.log("Logger ausgeschaltet");
|
||||
};
|
||||
|
||||
const handleLoggerOn = () => {
|
||||
_logger.current.start();
|
||||
console.log("start logging ");
|
||||
};
|
||||
|
||||
const handlePasswordChange = (e) => {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
|
||||
const handleUsernameChange = (e) => {
|
||||
setUsername(e.target.value);
|
||||
};
|
||||
|
||||
const handleOnPasteEvent = (e) => {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
};
|
||||
const handleOnCopyEvent = (e) => {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
const checkIfUsernameIsCorrect = () => {
|
||||
return serverUsername === username;
|
||||
};
|
||||
|
||||
const receiveRandomPassword = () => {
|
||||
fetch("/api/rcv_pw", {
|
||||
method: "get",
|
||||
}).then((response) => {
|
||||
response.json().then((resp) => {
|
||||
setGenPassword(resp.random_password);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const checkIfPasswordIsCorrect = () => {
|
||||
return genPassword === password;
|
||||
};
|
||||
|
||||
const checkIfValuesAreCorrect = () => {
|
||||
return checkIfPasswordIsCorrect() && checkIfUsernameIsCorrect();
|
||||
};
|
||||
|
||||
const handleClickAtStepStart = () => {
|
||||
receiveRandomPassword();
|
||||
setState(STATES.NORMAL);
|
||||
handleLoggerOn();
|
||||
// map username and session with the logs
|
||||
_logger.current.logCustomEvent({
|
||||
name: serverUsername,
|
||||
});
|
||||
};
|
||||
|
||||
const resetInputValues = () => {
|
||||
let inputElements = document.querySelectorAll(
|
||||
'div input:not([type="submit"])'
|
||||
);
|
||||
for (let i = 0; i < inputElements.length; i++) {
|
||||
inputElements[i].value = "";
|
||||
}
|
||||
};
|
||||
|
||||
const handleClickAtStepNormal = () => {
|
||||
if (checkIfValuesAreCorrect()) {
|
||||
receiveRandomPassword();
|
||||
setIsInputCorrect(true);
|
||||
setState(STATES.PHONE);
|
||||
} else {
|
||||
setIsInputCorrect(false);
|
||||
resetInputValues();
|
||||
}
|
||||
};
|
||||
|
||||
const handleClickAtStepPhone = () => {
|
||||
if (checkIfValuesAreCorrect()) {
|
||||
receiveRandomPassword();
|
||||
setIsInputCorrect(true);
|
||||
setState(STATES.STANDING);
|
||||
} else {
|
||||
setIsInputCorrect(false);
|
||||
resetInputValues();
|
||||
}
|
||||
};
|
||||
|
||||
const handleClickAtStepStanding = () => {
|
||||
if (checkIfValuesAreCorrect()) {
|
||||
setIsInputCorrect(true);
|
||||
setState(STATES.END);
|
||||
handleLoggerOff();
|
||||
} else {
|
||||
setIsInputCorrect(false);
|
||||
resetInputValues();
|
||||
}
|
||||
};
|
||||
|
||||
const study_start = (
|
||||
<>
|
||||
<BehaviorStudyInfo />
|
||||
<Button
|
||||
className="btns"
|
||||
buttonStyle="btn--primary"
|
||||
buttonSize="btn--full"
|
||||
onClick={handleClickAtStepStart}
|
||||
newTo="study"
|
||||
>
|
||||
Studie starten
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
const study_normal = (
|
||||
<>
|
||||
<BehaviorNormal onCopy={handleOnCopyEvent} genPassword={genPassword} />
|
||||
{!isInputCorrect && <ErrorMessage message={errorText} />}
|
||||
<div>
|
||||
<InputField
|
||||
LabelName="Benutzername"
|
||||
onChange={handleUsernameChange}
|
||||
InputType="text"
|
||||
InputName="Benutzername"
|
||||
InputPlaceHolder="Benutzername"
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<InputField
|
||||
LabelName="Passwort"
|
||||
onChange={handlePasswordChange}
|
||||
InputType="password"
|
||||
InputName="Passwort"
|
||||
InputPlaceHolder="Passwort"
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<SubmitField
|
||||
LabelName="Weiter zur nächsten Situation"
|
||||
InputValue="next-situation"
|
||||
InputName="Weiter"
|
||||
onClick={handleClickAtStepNormal}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const study_phone = (
|
||||
<>
|
||||
<BehaviorPhone genPassword={genPassword} />
|
||||
{!isInputCorrect && <ErrorMessage message={errorText} />}
|
||||
<div>
|
||||
<InputField
|
||||
LabelName="Benutzername"
|
||||
onChange={handleUsernameChange}
|
||||
InputType="text"
|
||||
InputName="Benutzername"
|
||||
InputPlaceHolder="Benutzername"
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<InputField
|
||||
LabelName="Passwort"
|
||||
onChange={handlePasswordChange}
|
||||
InputType="password"
|
||||
InputName="Passwort"
|
||||
InputPlaceHolder="Passwort"
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<SubmitField
|
||||
LabelName="Weiter zur nächsten Situation"
|
||||
InputValue="next-situation"
|
||||
InputName="Weiter"
|
||||
onClick={handleClickAtStepPhone}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const study_standing = (
|
||||
<>
|
||||
<BehaviorStanding genPassword={genPassword} />
|
||||
{!isInputCorrect && <ErrorMessage message={errorText} />}
|
||||
<div>
|
||||
<InputField
|
||||
LabelName="Benutzername"
|
||||
onChange={handleUsernameChange}
|
||||
InputType="text"
|
||||
InputName="Benutzername"
|
||||
InputPlaceHolder="Benutzername"
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<InputField
|
||||
LabelName="Passwort"
|
||||
onChange={handlePasswordChange}
|
||||
InputType="password"
|
||||
InputName="Passwort"
|
||||
InputPlaceHolder="Passwort"
|
||||
onPaste={handleOnPasteEvent}
|
||||
/>
|
||||
<SubmitField
|
||||
LabelName="Studie beenden"
|
||||
InputValue="stopStudy"
|
||||
InputName="quit"
|
||||
onClick={handleClickAtStepStanding}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const study_end = <BehaviorStudyEnd />;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<h1>Studie</h1>
|
||||
<StudyFinished />
|
||||
{state === STATES.START ? study_start : null}
|
||||
{state === STATES.NORMAL ? study_normal : null}
|
||||
{state === STATES.PHONE ? study_phone : null}
|
||||
{state === STATES.STANDING ? study_standing : null}
|
||||
{state === STATES.END ? study_end : null}
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -9,10 +9,10 @@ export default function Ueber() {
|
|||
<h1>Über das Projekt</h1>
|
||||
<p>
|
||||
Im Rahmen meiner Bachelorthesis an der Fernfachhochschule Schweiz
|
||||
möchte ich der Frage nachgehen, wie sich die Verhaltensmerkmale (also zum Beispiel Tastaturanschläge und Mausbewegungen) in
|
||||
möchte ich der Frage nachgehen, wie sich die Verhaltensmerkmale in
|
||||
unterschiedlichen Situationen unterscheiden. Hierfür habe ich eine
|
||||
Webanwendung entwickelt, welche die Nutzerinnen und Nutzer möglichst
|
||||
einfach durch die Studie führt. Damit ich ein paar Personen respektive deren Verhalten erfassen kann, ist es natürlich wichtig, dass mehrere Personen an der Studie teilnehmen. Ausserdem ist es wichtig, dass die teilnehmenden Personen mehrere Male teilnehmen, so dass ich mögliche Unterschiede während des Tagesverlauf bewerten kann.
|
||||
einfach durch die Studie führt.
|
||||
</p>
|
||||
<p>
|
||||
Falls Sie Fragen haben, können Sie diese jederzeit per Mail stellen.
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from "react";
|
||||
import React, {useState} from "react";
|
||||
import "../../App.css";
|
||||
import "../Input.css";
|
||||
import Footer from "../../Footer";
|
||||
|
@ -51,8 +51,8 @@ export default function Umfrage() {
|
|||
|
||||
if (!Number(age)) {
|
||||
setAgeErrorMessage("Das Alter muss als Zahl angegeben werden.");
|
||||
setIsSurveyValid(false);
|
||||
setIsAgeOk(false);
|
||||
//setIsSurveyValid(false);
|
||||
// setIsAgeOk(false);
|
||||
}
|
||||
if (gender === "DEFAULT" || gender === "") {
|
||||
setGenderErrorMessage(
|
||||
|
@ -219,7 +219,7 @@ export default function Umfrage() {
|
|||
{!isSurveyValidBackend ? (
|
||||
<ErrorMessage message={backendErrorMessage} />
|
||||
) : (
|
||||
<Redirect to="/study" />
|
||||
<Redirect to="/behavior" />
|
||||
)}
|
||||
</div>
|
||||
<Footer />
|
31
frontend/src/components/pages/lizenzen.js
Normal file
31
frontend/src/components/pages/lizenzen.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React from "react";
|
||||
import "../../App.css";
|
||||
import Footer from "../../Footer";
|
||||
|
||||
export default function Lizenzen() {
|
||||
return (
|
||||
<>
|
||||
<div className="sitePage">
|
||||
<h1>Lizenzen und Bildnachweise</h1>
|
||||
<p>
|
||||
Nachfolgend sollen die verwendeten Bibliotheken inklusive der Lizenz
|
||||
aufgeführt werden. Neben den Bibliotheken sollen vorallem auch
|
||||
Bildnachweise notiert werden.
|
||||
</p>
|
||||
<h2>Verwendete Bibliotheken</h2>
|
||||
<h3>Backend</h3>
|
||||
<h3>Frontend</h3>
|
||||
<h2>Bildnachweise</h2>
|
||||
<ul className="bildnachweise">
|
||||
<li>
|
||||
Originalbild für die Startseite:
|
||||
<a href="https://pixabay.com/illustrations/virtual-identity-digital-identity-69996/">
|
||||
https://pixabay.com/illustrations/virtual-identity-digital-identity-69996/
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
BIN
frontend/src/images/img-9.jpg
Normal file
BIN
frontend/src/images/img-9.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 466 KiB |
BIN
frontend/src/images/img-home.jpg
Normal file
BIN
frontend/src/images/img-home.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 612 KiB |
60
requests.sh
60
requests.sh
|
@ -1,60 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
ACTION=$1
|
||||
VALUE=$2
|
||||
ACTIONS=(login register rcvpw username data csv prod_data prod_csv)
|
||||
|
||||
print_help(){
|
||||
echo "Usage: $0 ACTION [TOKEN|INPUT_TYPE]"
|
||||
echo
|
||||
echo "available actions:"
|
||||
for el in "${ACTIONS[@]}"; do
|
||||
echo - "$el"
|
||||
done
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ -z $1 ]]; then
|
||||
print_help
|
||||
fi
|
||||
|
||||
|
||||
case $ACTION in
|
||||
"${ACTIONS[0]}") # login
|
||||
echo "login action"
|
||||
curl localhost:5050/api/login -X POST -d '{"username":"test","password":"test"}'
|
||||
;;
|
||||
"${ACTIONS[1]}") # register
|
||||
echo "register action"
|
||||
curl localhost:5050/api/register -X POST -d '{"username":"test","password":"test"}'
|
||||
;;
|
||||
"${ACTIONS[2]}") # reveice password
|
||||
echo "rcv_pw action"
|
||||
curl localhost:5050/api/protected/rcv_pw
|
||||
;;
|
||||
"${ACTIONS[3]}") # get current username
|
||||
echo "get username action"
|
||||
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
|
||||
print_help
|
||||
;;
|
||||
esac
|
4
stop.sh
4
stop.sh
|
@ -1,6 +1,2 @@
|
|||
podman stop frontend-dev frontend-prod frontend-testing backend-dev backend-prod backend-testing
|
||||
podman rm frontend-dev frontend-prod frontend-testing backend-dev backend-prod backend-testing
|
||||
podman rmi app_from_scratch_backend-dev app_from_scratch_frontend-dev
|
||||
podman rmi caminsha/bt-frontend caminsha/bt-backend
|
||||
podman-compose down
|
||||
podman-compose -f docker-compose.prod.yml down
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
frontend-prod:
|
||||
containername: frontend-testing
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile.prod
|
||||
ports:
|
||||
- 3000:80
|
||||
backend-prod:
|
||||
container_name: backend-testing
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile.prod
|
||||
environment:
|
||||
DEBUG: "no"
|
||||
PORT: 5050
|
||||
HOST: "0.0.0.0"
|
||||
behametrics-server:
|
||||
image: registry.gitlab.com/behametrics/server:latest
|
||||
container_name: "behametrics-server"
|
||||
ports:
|
||||
- 5000:5000
|
||||
environment:
|
||||
- MONGO_URI=mongodb://mongodb:27017/behametrics
|
||||
mongodb:
|
||||
image: mongo:4.0.1
|
||||
container_name: "behametrics-mongo"
|
||||
command: mongod --smallfiles
|
Loading…
Reference in a new issue