Files
BellScheduler/app/app.py

218 lines
7.2 KiB
Python

import os
from flask import Flask, render_template, redirect, url_for, request, flash
from flask_migrate import Migrate
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import (LoginManager, login_user, login_required, logout_user, current_user)
from misc import datetime, date, time, currDay, ZoneInfo, currVersion, currCommit
from db import (db, Period, Task, Event, User)
from forms import (TaskForm, EventForm, PeriodForm, SignupForm, LoginForm, SettingsForm)
from backgroundTasks import scheduleCreateEvents
from create_events import createEvents
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SECRET_KEY'] = 'HwG55rpe83jcaglifXm8NuF4WEeXyJV4'
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, os.environ['SQLITE_DB'])
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
# init migration
migrate = Migrate()
migrate.init_app(app, db)
# Schedule creation of events every hour
with app.app_context():
scheduleCreateEvents(app, db, currDay, Period, Event, createEvents)
# Authentication stuff
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.init_app(app)
if 'SIGNUP_ENABLED' in os.environ:
if os.environ['SIGNUP_ENABLED'] == "YES":
signup_enabled = True
else:
signup_enabled = False
else:
signup_enabled = False
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# Context processor injects current version and commit
@app.context_processor
def injectVerCommit():
return dict(currVersion=currVersion, currCommit=currCommit)
# Index route
@app.route('/')
def index():
return redirect('/events')
# Authentication routes
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
userName = form.userName.data
password = form.password.data
user = User.query.filter_by(userName=userName).first()
if not user or not check_password_hash(user.password, password):
flash('Credentials incorrect! Please try again')
return redirect(url_for('login'))
login_user(user)
return redirect(url_for('events'))
return render_template('login.html', form=form)
@app.route('/createaccount', methods=['GET', 'POST'])
def createAccount():
if signup_enabled == True:
form = SignupForm()
if form.validate_on_submit():
usernameExists = User.query.filter_by(userName=form.userName.data).first()
if usernameExists:
flash('Username already exists')
return redirect(url_for('createAccount'))
new_user = User(email=form.email.data, userName=form.userName.data, realName=form.realName.data,
password=generate_password_hash(form.password.data, method='sha256'))
db.session.add(new_user)
db.session.commit()
return redirect(url_for('login'))
return render_template('createAccount.html', form=form)
else:
return 'Account creation is currently disabled'
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
@app.route('/settings', methods=('GET', 'POST'))
@login_required
def settings():
user = User.query.get_or_404(current_user.id)
form = SettingsForm(obj=user)
if form.validate_on_submit():
user.realName = form.realName.data
user.timezone = form.timezone.data
if form.password.data != '':
user.password = generate_password_hash(form.password.data, method='sha256')
db.session.commit()
return render_template('settings.html', form=form)
# Periods routes
@app.route('/periods')
@login_required
def periods():
periods = Period.query.all()
return render_template('periods.html', periods=periods, datetime=datetime)
@app.route('/period/new', methods=('GET', 'POST'))
@login_required
def newPeriod():
form = PeriodForm()
if form.validate_on_submit():
period = Period(periodTime=form.periodTime.data,
weekendSchedule=form.weekendSchedule.data
)
db.session.add(period)
db.session.commit()
return redirect(f'/period/edit/{period.period}')
return render_template('newPeriod.html', form=form)
@app.route('/period/edit/<int:periodNum>', methods=('GET', 'POST'))
@login_required
def editPeriod(periodNum):
period = Period.query.get_or_404(periodNum)
form = PeriodForm(obj=period)
if form.validate_on_submit():
period.periodTime = form.periodTime.data
period.weekendSchedule = form.weekendSchedule.data
db.session.commit()
return redirect(f'/period/edit/{periodNum}')
return render_template('editPeriod.html', period=period, form=form, datetime=datetime)
@app.post('/period/delete/<int:periodNum>')
@login_required
def delete_period(periodNum):
period = Period.query.get_or_404(periodNum)
db.session.delete(period)
db.session.commit()
return redirect('/periods')
# Events routes
@app.route('/events')
@login_required
def events():
events = Event.query.all()
periods = Period.query.all()
return render_template('events.html', events=events, periods=periods, datetime=datetime, date=date, ZoneInfo=ZoneInfo)
@app.route('/event/edit/<int:event_id>/', methods=('GET', 'POST'))
@login_required
def editEvent(event_id):
event = Event.query.get_or_404(event_id)
form = EventForm(obj=event)
if form.validate_on_submit():
if hasattr(form.selectedTask.data, 'id'):
event.task_id = form.selectedTask.data.id
else:
event.task_id = None
db.session.commit()
return redirect('/events')
return render_template('editEvent.html', event=event, form=form, datetime=datetime)
# Tasks routes
@app.route('/tasks')
@login_required
def tasks():
tasks = Task.query.all()
return render_template('tasks.html', str=str, tasks=tasks, datetime=datetime, date=date)
@app.route('/task/<int:task_id>/')
@login_required
def task(task_id):
task = Task.query.get_or_404(task_id)
return render_template('task.html', str=str, task=task, datetime=datetime, date=date)
@app.route('/task/new', methods=('GET', 'POST'))
@login_required
def newTask():
form = TaskForm()
if form.validate_on_submit():
task = Task(title=form.title.data,
description=form.description.data,
created_timestamp=int(time.time()))
db.session.add(task)
db.session.commit()
return redirect(f'/task/{task.id}')
return render_template('newtask.html', form=form)
@app.route('/task/<int:task_id>/edit', methods=('GET', 'POST'))
@login_required
def editTask(task_id):
task = Task.query.get_or_404(task_id)
form = TaskForm(obj=task)
if form.validate_on_submit():
task.title=form.title.data
task.description=form.description.data
db.session.commit()
return redirect(f'/task/{task_id}')
return render_template('edittask.html', task=task, form=form)
@app.post('/task/<int:task_id>/delete')
@login_required
def delete_task(task_id):
task = Task.query.get_or_404(task_id)
db.session.delete(task)
db.session.commit()
return redirect('/tasks')