2024-01-12 10:57:58 +01:00
|
|
|
import datetime
|
2024-01-12 16:53:03 +01:00
|
|
|
import hashlib
|
2024-01-12 10:57:58 +01:00
|
|
|
|
|
|
|
|
from flask import Flask, render_template, redirect, url_for, request
|
2024-01-12 16:53:03 +01:00
|
|
|
from flask_login import login_required, LoginManager, login_user, logout_user, current_user
|
2024-01-12 10:57:58 +01:00
|
|
|
|
2024-01-19 10:44:00 +01:00
|
|
|
from models.Habit import Habit
|
2024-01-26 09:06:31 +01:00
|
|
|
from models.HabitTrackings import HabitTrackings
|
2024-01-12 10:57:58 +01:00
|
|
|
from models.User import User
|
2024-01-12 16:53:03 +01:00
|
|
|
from utils import anonymous_required
|
2024-01-12 10:57:58 +01:00
|
|
|
|
|
|
|
|
# Create a new Flask instance
|
|
|
|
|
app = Flask(__name__)
|
2024-01-12 16:53:03 +01:00
|
|
|
app.secret_key = 'PSSSSSHHHT!'
|
|
|
|
|
|
|
|
|
|
# Initialize the Flask-Login extension
|
|
|
|
|
login_manager = LoginManager()
|
|
|
|
|
login_manager.login_view = 'login'
|
|
|
|
|
login_manager.init_app(app)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_manager.user_loader
|
|
|
|
|
def load_user(user_id):
|
|
|
|
|
return User.get(user_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.context_processor
|
|
|
|
|
def inject_user():
|
|
|
|
|
return dict(user=current_user)
|
2024-01-12 10:57:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/login')
|
2024-01-12 16:53:03 +01:00
|
|
|
@anonymous_required
|
2024-01-12 10:57:58 +01:00
|
|
|
def login():
|
2024-01-12 16:53:03 +01:00
|
|
|
return render_template('auth/login.html', errors={})
|
2024-01-12 10:57:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/signup')
|
2024-01-12 16:53:03 +01:00
|
|
|
@anonymous_required
|
2024-01-12 10:57:58 +01:00
|
|
|
def signup():
|
|
|
|
|
return render_template('auth/signup.html', errors={})
|
|
|
|
|
|
2024-01-12 16:53:03 +01:00
|
|
|
|
2024-01-23 10:58:08 +01:00
|
|
|
@app.route('/login', methods=['POST'])
|
|
|
|
|
def login_post():
|
2024-01-12 10:57:58 +01:00
|
|
|
email = request.form.get('email')
|
|
|
|
|
password = request.form.get('password')
|
|
|
|
|
|
|
|
|
|
# Check for errors
|
|
|
|
|
errors = {}
|
|
|
|
|
if not email:
|
2024-01-19 10:44:00 +01:00
|
|
|
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
|
2024-01-12 10:57:58 +01:00
|
|
|
if not password:
|
2024-01-19 10:44:00 +01:00
|
|
|
errors['password'] = 'Das Passwort ist erforderlich.'
|
2024-01-12 10:57:58 +01:00
|
|
|
|
2024-01-23 10:58:08 +01:00
|
|
|
# Check if user exists
|
|
|
|
|
user = User.get_by_email(email)
|
|
|
|
|
|
|
|
|
|
if not user:
|
|
|
|
|
errors['email'] = 'E-Mail Adresse nicht gefunden.'
|
|
|
|
|
elif user.password is None or hashlib.sha256(password.encode()).hexdigest() != user.password:
|
|
|
|
|
errors['password'] = 'Das Passwort ist falsch.'
|
|
|
|
|
|
2024-01-12 16:53:03 +01:00
|
|
|
if errors:
|
|
|
|
|
return render_template(
|
2024-01-23 10:58:08 +01:00
|
|
|
'auth/login.html',
|
2024-01-12 16:53:03 +01:00
|
|
|
email=email,
|
|
|
|
|
password=password,
|
|
|
|
|
errors=errors
|
|
|
|
|
)
|
2024-01-12 10:57:58 +01:00
|
|
|
|
2024-01-12 16:53:03 +01:00
|
|
|
login_user(user)
|
|
|
|
|
|
|
|
|
|
# Redirect to login page
|
2024-01-16 11:16:21 +01:00
|
|
|
return redirect(url_for('index'))
|
2024-01-12 16:53:03 +01:00
|
|
|
|
|
|
|
|
|
2024-01-23 10:58:08 +01:00
|
|
|
@app.route('/signup', methods=['POST'])
|
|
|
|
|
def signup_post():
|
2024-01-12 16:53:03 +01:00
|
|
|
email = request.form.get('email')
|
2024-01-23 10:58:08 +01:00
|
|
|
name = request.form.get('name')
|
2024-01-12 16:53:03 +01:00
|
|
|
password = request.form.get('password')
|
|
|
|
|
|
|
|
|
|
# Check for errors
|
|
|
|
|
errors = {}
|
|
|
|
|
if not email:
|
2024-01-19 10:44:00 +01:00
|
|
|
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
|
2024-01-23 10:58:08 +01:00
|
|
|
if not name:
|
|
|
|
|
errors['name'] = 'Der Name ist erforderlich.'
|
2024-01-12 16:53:03 +01:00
|
|
|
if not password:
|
2024-01-19 10:44:00 +01:00
|
|
|
errors['password'] = 'Das Passwort ist erforderlich.'
|
2024-01-12 16:53:03 +01:00
|
|
|
|
|
|
|
|
if errors:
|
|
|
|
|
return render_template(
|
2024-01-23 10:58:08 +01:00
|
|
|
'auth/signup.html',
|
2024-01-12 16:53:03 +01:00
|
|
|
email=email,
|
2024-01-23 10:58:08 +01:00
|
|
|
name=name,
|
2024-01-12 16:53:03 +01:00
|
|
|
password=password,
|
|
|
|
|
errors=errors
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-23 10:58:08 +01:00
|
|
|
# Save user to database. Maybe log the user in directly.
|
|
|
|
|
user = User.create(name, email, password)
|
2024-01-12 16:53:03 +01:00
|
|
|
login_user(user)
|
2024-01-12 10:57:58 +01:00
|
|
|
|
|
|
|
|
# Redirect to login page
|
2024-01-16 11:16:21 +01:00
|
|
|
return redirect(url_for('index'))
|
2024-01-12 10:57:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/logout')
|
|
|
|
|
@login_required
|
|
|
|
|
def logout():
|
|
|
|
|
# Log out functionality
|
2024-01-12 16:53:03 +01:00
|
|
|
logout_user()
|
|
|
|
|
|
2024-01-12 10:57:58 +01:00
|
|
|
return redirect(url_for('index'))
|
|
|
|
|
|
|
|
|
|
|
2024-01-23 10:58:08 +01:00
|
|
|
# Create a new route
|
|
|
|
|
@app.route('/')
|
|
|
|
|
def index():
|
|
|
|
|
if current_user.is_authenticated:
|
|
|
|
|
habits = current_user.get_habits()
|
2024-01-23 11:00:37 +01:00
|
|
|
name = "Hallo " + current_user.name
|
2024-01-23 10:58:08 +01:00
|
|
|
else:
|
|
|
|
|
habits = []
|
2024-01-26 11:07:41 +01:00
|
|
|
name = "Bitte melde dich an."
|
2024-01-23 10:58:08 +01:00
|
|
|
|
2024-01-26 10:09:57 +01:00
|
|
|
# Sort habits by whether they have been checked today and then by slot
|
|
|
|
|
habits.sort(key=lambda habit: (habit.checked, habit.slot))
|
|
|
|
|
|
2024-01-23 10:58:08 +01:00
|
|
|
return render_template(
|
|
|
|
|
'index.html',
|
|
|
|
|
title=name,
|
|
|
|
|
utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M %A"),
|
|
|
|
|
habits=habits,
|
|
|
|
|
errors={},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2024-01-19 10:50:35 +01:00
|
|
|
@app.route('/habit')
|
|
|
|
|
@login_required
|
|
|
|
|
def habit_creation():
|
|
|
|
|
return render_template(
|
|
|
|
|
'habit.html',
|
|
|
|
|
title='Erstelle ein Habit',
|
2024-01-26 10:25:01 +01:00
|
|
|
unit="Woche",
|
2024-01-19 10:50:35 +01:00
|
|
|
errors={},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2024-01-19 10:44:00 +01:00
|
|
|
@app.route('/habit', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def habit_create():
|
|
|
|
|
name = request.form.get('name')
|
|
|
|
|
note = request.form.get('note')
|
|
|
|
|
times = request.form.get('times')
|
|
|
|
|
unit = request.form.get('unit')
|
|
|
|
|
|
|
|
|
|
# Check for errors
|
|
|
|
|
errors = {}
|
|
|
|
|
if not name:
|
|
|
|
|
errors['name'] = 'Der Name ist erforderlich.'
|
|
|
|
|
if not times:
|
|
|
|
|
errors['times'] = 'Die Anzahl ist erforderlich.'
|
|
|
|
|
if not note:
|
|
|
|
|
note = ''
|
|
|
|
|
if not unit:
|
|
|
|
|
errors['unit'] = 'Die Einheit ist erforderlich.'
|
|
|
|
|
|
|
|
|
|
# Check if times is an integer
|
|
|
|
|
try:
|
|
|
|
|
times = int(times)
|
2024-01-23 10:46:52 +01:00
|
|
|
|
|
|
|
|
# Check that times is greater than 0
|
|
|
|
|
if times <= 0:
|
|
|
|
|
errors['times'] = 'Die Anzahl muss größer als 0 sein.'
|
2024-01-19 10:44:00 +01:00
|
|
|
except ValueError:
|
|
|
|
|
errors['times'] = 'Die Anzahl muss eine Zahl sein.'
|
|
|
|
|
|
2024-01-19 11:05:27 +01:00
|
|
|
# Check that unit is valid
|
|
|
|
|
if unit not in ['Tag', 'Woche', 'Monat', 'Jahr']:
|
|
|
|
|
errors['unit'] = 'Die Einheit ist ungültig.'
|
|
|
|
|
|
2024-01-19 10:44:00 +01:00
|
|
|
if errors:
|
|
|
|
|
return render_template(
|
2024-01-19 10:50:35 +01:00
|
|
|
'habit.html',
|
|
|
|
|
title='Erstelle ein Habit',
|
2024-01-19 10:44:00 +01:00
|
|
|
name=name,
|
|
|
|
|
note=note,
|
|
|
|
|
times=times,
|
|
|
|
|
unit=unit,
|
2024-01-19 11:13:01 +01:00
|
|
|
errors=errors
|
2024-01-19 10:44:00 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Map unit to integer
|
|
|
|
|
if unit == 'Tag':
|
|
|
|
|
unit = 0
|
|
|
|
|
elif unit == 'Woche':
|
|
|
|
|
unit = 1
|
|
|
|
|
elif unit == 'Monat':
|
|
|
|
|
unit = 2
|
|
|
|
|
elif unit == 'Jahr':
|
|
|
|
|
unit = 3
|
|
|
|
|
else:
|
|
|
|
|
unit = 1
|
|
|
|
|
|
|
|
|
|
# Save habit to database
|
|
|
|
|
habit = Habit.create(current_user.id, name, times, note, unit)
|
|
|
|
|
|
|
|
|
|
# Back to index
|
2024-01-26 07:59:17 +01:00
|
|
|
return redirect(url_for('index'))
|
|
|
|
|
|
|
|
|
|
"""return render_template(
|
2024-01-19 10:50:35 +01:00
|
|
|
'habit.html',
|
|
|
|
|
title='Erstelle ein Habit',
|
2024-01-19 10:44:00 +01:00
|
|
|
name=name,
|
|
|
|
|
note=note,
|
|
|
|
|
times=times,
|
|
|
|
|
unit=unit,
|
|
|
|
|
errors=errors,
|
2024-01-26 07:59:17 +01:00
|
|
|
)"""
|
2024-01-19 10:44:00 +01:00
|
|
|
|
2024-01-26 08:30:06 +01:00
|
|
|
|
2024-01-26 10:25:01 +01:00
|
|
|
@app.route('/profile')
|
|
|
|
|
@login_required
|
|
|
|
|
def profile():
|
|
|
|
|
return render_template(
|
|
|
|
|
"profile.html",
|
|
|
|
|
name=current_user.name,
|
|
|
|
|
email=current_user.email,
|
|
|
|
|
errors={}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.route('/profile', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def profile_change():
|
|
|
|
|
newName = request.form.get('newName')
|
|
|
|
|
newEmail = request.form.get('newEmail')
|
|
|
|
|
newPassword = request.form.get('newPassword')
|
2024-01-26 10:45:58 +01:00
|
|
|
oldPassword = request.form.get('oldPassword')
|
2024-01-26 10:25:01 +01:00
|
|
|
|
|
|
|
|
# Check for errors
|
|
|
|
|
errors = {}
|
2024-01-26 10:40:12 +01:00
|
|
|
if not newName:
|
|
|
|
|
errors['newName'] = 'Der Name ist erforderlich.'
|
|
|
|
|
|
|
|
|
|
if not newEmail:
|
|
|
|
|
errors['newEmail'] = 'Die E-Mail Adresse ist erforderlich.'
|
|
|
|
|
|
2024-01-26 10:45:58 +01:00
|
|
|
if not oldPassword:
|
2024-01-26 10:25:01 +01:00
|
|
|
errors['oldPassword'] = 'Du musst dein aktuelles Passwort angeben.'
|
2024-01-26 10:40:12 +01:00
|
|
|
else:
|
|
|
|
|
if hashlib.sha256(oldPassword.encode()).hexdigest() != current_user.password:
|
|
|
|
|
errors['oldPassword'] = 'Das Passwort ist falsch.'
|
2024-01-26 10:25:01 +01:00
|
|
|
|
|
|
|
|
if errors:
|
|
|
|
|
return render_template(
|
|
|
|
|
"profile.html",
|
|
|
|
|
name=current_user.name,
|
|
|
|
|
email=current_user.email,
|
|
|
|
|
errors=errors
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-26 10:40:12 +01:00
|
|
|
# Update user
|
|
|
|
|
current_user.name = newName
|
|
|
|
|
current_user.email = newEmail
|
|
|
|
|
if newPassword:
|
|
|
|
|
current_user.password = hashlib.sha256(newPassword.encode()).hexdigest()
|
|
|
|
|
current_user.update()
|
2024-01-26 10:25:01 +01:00
|
|
|
|
2024-01-26 10:40:12 +01:00
|
|
|
# Back to profile
|
|
|
|
|
return render_template(
|
|
|
|
|
"profile.html",
|
|
|
|
|
name=current_user.name,
|
|
|
|
|
email=current_user.email,
|
|
|
|
|
errors={}
|
|
|
|
|
)
|
2024-01-26 10:25:01 +01:00
|
|
|
|
|
|
|
|
|
2024-01-26 08:27:44 +01:00
|
|
|
@app.route('/check', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def check_habit():
|
2024-01-26 09:06:31 +01:00
|
|
|
habit_id = request.get_json()["habitId"]
|
|
|
|
|
|
|
|
|
|
habit = Habit.get(habit_id)
|
|
|
|
|
|
|
|
|
|
if habit is None:
|
|
|
|
|
return {"error": "Habit not found"}
|
|
|
|
|
|
|
|
|
|
# Check if habit belongs to user
|
|
|
|
|
if habit.user_id != current_user.id:
|
|
|
|
|
return {"error": "Habit does not belong to user"}
|
|
|
|
|
|
|
|
|
|
trackings = habit.get_habitTrackings()
|
|
|
|
|
|
|
|
|
|
# Check if habit has been tracked today
|
2024-01-30 09:55:44 +01:00
|
|
|
delete_tracking = None
|
2024-01-26 09:06:31 +01:00
|
|
|
for tracking in trackings:
|
2024-01-26 10:01:02 +01:00
|
|
|
# day
|
|
|
|
|
if habit.unit == 0:
|
|
|
|
|
if tracking.created_at.date() == datetime.date.today():
|
|
|
|
|
delete_tracking = tracking
|
|
|
|
|
break
|
|
|
|
|
# week
|
|
|
|
|
elif habit.unit == 1:
|
|
|
|
|
if tracking.created_at.date().isocalendar()[1] == datetime.date.today().isocalendar()[1]:
|
|
|
|
|
delete_tracking = tracking
|
|
|
|
|
break
|
|
|
|
|
# month
|
|
|
|
|
elif habit.unit == 2:
|
|
|
|
|
if tracking.created_at.date().month == datetime.date.today().month:
|
|
|
|
|
delete_tracking = tracking
|
|
|
|
|
break
|
|
|
|
|
# year
|
|
|
|
|
elif habit.unit == 3:
|
|
|
|
|
if tracking.created_at.date().year == datetime.date.today().year:
|
|
|
|
|
delete_tracking = tracking
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
if not delete_tracking:
|
2024-01-26 09:06:31 +01:00
|
|
|
HabitTrackings.create(habit_id, 1)
|
2024-01-26 10:01:02 +01:00
|
|
|
else:
|
|
|
|
|
delete_tracking.delete()
|
2024-01-26 09:06:31 +01:00
|
|
|
|
2024-01-30 10:37:38 +01:00
|
|
|
# Update habit
|
|
|
|
|
habit.fill_statistics()
|
|
|
|
|
|
2024-01-26 09:06:31 +01:00
|
|
|
return {
|
|
|
|
|
"habitId": habit_id,
|
2024-01-30 10:41:05 +01:00
|
|
|
"unchecked": not delete_tracking,
|
|
|
|
|
"percentage": habit.percentage,
|
2024-01-26 09:06:31 +01:00
|
|
|
}
|
2024-01-19 10:44:00 +01:00
|
|
|
|
2024-01-26 11:07:41 +01:00
|
|
|
@app.route('/delete', methods=['POST'])
|
|
|
|
|
@login_required
|
|
|
|
|
def delete_habit():
|
|
|
|
|
habit_id = request.get_json()["habitId"]
|
|
|
|
|
|
|
|
|
|
habit = Habit.get(habit_id)
|
|
|
|
|
|
|
|
|
|
if habit is None:
|
|
|
|
|
return {"error": "Habit not found"}
|
|
|
|
|
|
|
|
|
|
# Check if habit belongs to user
|
|
|
|
|
if habit.user_id != current_user.id:
|
|
|
|
|
return {"error": "Habit does not belong to user"}
|
|
|
|
|
|
|
|
|
|
habit.delete()
|
|
|
|
|
|
|
|
|
|
return {}
|
|
|
|
|
|
2024-01-26 08:30:06 +01:00
|
|
|
|
2024-01-12 10:57:58 +01:00
|
|
|
# Run the application
|
|
|
|
|
if __name__ == '__main__':
|
2024-01-19 10:44:00 +01:00
|
|
|
app.run(port=5000, debug=True)
|