raphael
752c7c5577
- the icalHandler in the backend is used in two instances. First, when the user adds a new ical calendar into the database, routes.py passes the information (name and url) to the ical Handler. The calendars are saved in the database as type 'ical'. Then, when a connected device pulls current events, all the calendars which are of type 'ical' are pulled and parsed for current events. See the backend commit for details on what happens there. - All google Calendar related functions now have an additional check, to make sure that the calendar they are working on is of type 'Google'.
291 lines
9.1 KiB
Python
291 lines
9.1 KiB
Python
# Python standard libraries
|
|
import json
|
|
import os
|
|
import time
|
|
|
|
# Third-party libraries
|
|
import flask
|
|
from flask import render_template, flash
|
|
from flask import Flask, redirect, request, url_for, jsonify
|
|
from flask_login import (
|
|
LoginManager,
|
|
current_user,
|
|
login_required,
|
|
login_user,
|
|
logout_user,
|
|
)
|
|
from random_words import RandomWords
|
|
import requests
|
|
|
|
import backend.icalHandler as ical
|
|
import server.googleHandler as google
|
|
|
|
from server import login_manager, app, db
|
|
from server.forms import LoginForm, RegistrationForm, DeviceForm, CalendarForm
|
|
import backend
|
|
from database.models import User, Calendar, Device, GoogleToken
|
|
|
|
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
|
|
|
@app.route("/")
|
|
def startpage():
|
|
return flask.render_template('startpage.html')
|
|
|
|
|
|
|
|
@app.route("/privacy")
|
|
def privacy():
|
|
return flask.render_template('privacy.html')
|
|
|
|
@app.route("/login")
|
|
def login():
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for('account'))
|
|
return flask.render_template('login.html')
|
|
|
|
|
|
@app.route("/account")
|
|
def account():
|
|
if current_user.is_authenticated:
|
|
calendars = []
|
|
gCalendars, colors, token = google.fetchCalendars()
|
|
if token != None:
|
|
current_user.google_token.token = token
|
|
db.session.commit()
|
|
calendars.extend(gCalendars)
|
|
backend.updateCalendars(current_user, calendars, colors)
|
|
|
|
return (flask.render_template('account.html',
|
|
username = current_user.username, email = current_user.email, profile_img=current_user.profile_pic
|
|
)
|
|
)
|
|
else:
|
|
return redirect(url_for("login"))
|
|
|
|
@app.route("/view")
|
|
def view():
|
|
if not current_user.is_authenticated:
|
|
return flask.render_template('login.html')
|
|
else:
|
|
return (flask.render_template('view.html'))
|
|
|
|
@app.route("/devices", methods=['GET', 'POST'])
|
|
def devices():
|
|
if not current_user.is_authenticated:
|
|
return flask.render_template('login.html')
|
|
|
|
# if this is a post request from the 'unlink' submittion form
|
|
# delete this device from the list
|
|
form = DeviceForm()
|
|
if request.method == 'POST':
|
|
|
|
if request.form.get("submit") == "Unlink":
|
|
device = db.session.query(Device).filter(Device.deviceName==request.form.get("device")).first()
|
|
db.session.delete(device)
|
|
db.session.commit()
|
|
|
|
# if this is part of the device form
|
|
elif form.validate_on_submit():
|
|
device = db.session.query(Device).filter(Device.deviceName==form.deviceName.data).first()
|
|
current_user.devices.append(device)
|
|
db.session.commit()
|
|
|
|
return flask.render_template('devices.html',
|
|
devices=current_user.devices,
|
|
form=form)
|
|
|
|
|
|
@app.route("/calendar", methods=['GET', 'POST', 'DELETE'])
|
|
@login_required
|
|
def calendar():
|
|
calendars = backend.calendarsFromDb(current_user)
|
|
|
|
form = CalendarForm()
|
|
if request.method == 'POST':
|
|
|
|
if form.validate_on_submit():
|
|
# try to add the submitted ical as a calendar
|
|
print(form.iCalURL.data, flush=True)
|
|
|
|
|
|
ical.icalToCalendarDb(form.iCalURL.data, form.calName.data, current_user)
|
|
|
|
# otherwise it is a javascript POST
|
|
else:
|
|
calId = request.json.get('calendar_id')
|
|
color = request.json.get('color', None)
|
|
toggle = request.json.get('toggle', None)
|
|
|
|
if color != None:
|
|
current_user.updateCalendar(calId, color=color)
|
|
if toggle != None:
|
|
current_user.updateCalendar(calId, toggle=toggle)
|
|
# toggle specific calendar of user
|
|
calId = request.json.get('calendar_id')
|
|
color = request.json.get('color', None)
|
|
toggle = request.json.get('toggle', None)
|
|
|
|
if color != None:
|
|
current_user.updateCalendar(calId, color=color)
|
|
if toggle != None:
|
|
current_user.updateCalendar(calId, toggle=toggle)
|
|
# toggle specific calendar of user
|
|
|
|
return 'OK'
|
|
|
|
elif request.method == 'DELETE':
|
|
# do nothing
|
|
return 'NONE'
|
|
else:
|
|
# POST Error 405
|
|
print("405")
|
|
|
|
return flask.render_template('calendar.html', calendars=calendars, form=form)
|
|
|
|
# POST
|
|
|
|
@app.route('/login/email', methods=['GET', 'POST'])
|
|
def emaillogin():
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for('account') )
|
|
form = LoginForm()
|
|
|
|
if form.validate_on_submit():
|
|
user = User.query.filter_by(username=form.username.data).first()
|
|
if user is None or not user.checkPassword(form.password.data):
|
|
flash('invalid username or password')
|
|
return redirect(url_for('emaillogin'))
|
|
login_user(user, remember=form.remember_me.data)
|
|
return redirect(url_for('account'))
|
|
return render_template('emaillogin.html', title='Sign In', form=form)
|
|
|
|
|
|
@app.route('/register', methods=['GET', 'POST'])
|
|
def register():
|
|
if current_user.is_authenticated:
|
|
return redirect(url_for('account'))
|
|
|
|
|
|
|
|
form = RegistrationForm()
|
|
if form.validate_on_submit():
|
|
user = User(userid=form.username.data,
|
|
username=form.username.data,
|
|
email=form.email.data)
|
|
user.setPassword(form.password.data)
|
|
db.session.add(user)
|
|
db.session.commit()
|
|
flash('Congratulations, you are now a registered user!')
|
|
return redirect(url_for('emaillogin'))
|
|
return flask.render_template('register.html', title='Register', form=form)
|
|
|
|
@app.route("/delete_account")
|
|
def deleteAccount():
|
|
if not current_user.is_authenticated:
|
|
return redirect(url_for('account'))
|
|
if current_user.google_token != None:
|
|
google.deleteAccount(current_user)
|
|
|
|
db.session.delete(current_user)
|
|
db.session.commit()
|
|
logout_user()
|
|
|
|
return redirect(url_for('account'))
|
|
|
|
@app.route("/login/google")
|
|
def googlelogin():
|
|
if current_user.is_authenticated and current_user.google_token != None:
|
|
return redirect(url_for('account'))
|
|
|
|
authorization_url = google.login()
|
|
|
|
return flask.redirect(authorization_url)
|
|
|
|
@app.route("/login/google/callback")
|
|
def callback():
|
|
session, credentials = google.verifyResponse()
|
|
userinfo = session.get('https://www.googleapis.com/userinfo/v2/me').json()
|
|
|
|
# Create a user in your db with the information provided
|
|
# by Google
|
|
|
|
# Doesn't exist? Add it to the database.
|
|
if not db.session.query(User).filter(User.userid==userinfo['id']).first():
|
|
gc = GoogleToken(token=credentials.get("token"),
|
|
refresh_token=credentials.get("refresh_token"))
|
|
db.session.add(gc)
|
|
newser = User(
|
|
|
|
userid=userinfo['id'],
|
|
username=userinfo['name'],
|
|
email=userinfo['email'],
|
|
profile_pic=userinfo['picture'],
|
|
password_hash="",
|
|
google_token = gc
|
|
)
|
|
db.session.add(newser)
|
|
db.session.commit()
|
|
|
|
user = db.session.query(User).filter(User.userid==userinfo['id']).first()
|
|
|
|
# Begin user session by logging the user in
|
|
login_user(user)
|
|
|
|
return flask.redirect(flask.url_for('account'))
|
|
|
|
@app.route("/logout")
|
|
@login_required
|
|
def logout():
|
|
logout_user()
|
|
return redirect(url_for("startpage"))
|
|
|
|
|
|
@app.route("/device/<path:device>/calendarevents.json")
|
|
def downloader(device):
|
|
path = "/home/calendarwatch/device/" + device + "/"
|
|
request_device = db.session.query(Device).filter(Device.deviceName==device).first()
|
|
if request_device == None:
|
|
return jsonify(kind="not found")
|
|
if request_device.user_id == None:
|
|
return jsonify(kind="unregistered")
|
|
|
|
request_device.lastConnection=int(round(time.time()))
|
|
request_device.connection=True
|
|
db.session.commit()
|
|
request_user = db.session.query(User).filter(User.id==request_device.user_id).first()
|
|
|
|
# TODO add test if googke token exists
|
|
# if request_user.google_token != Null:
|
|
# TODO only pass along google calendars form user
|
|
startDate, endDate = backend.getTimeStamps()
|
|
events, colors = google.fetchCalendarEvents(request_user, request_user.calendars, startDate, endDate)
|
|
events.extend(ical.fetchCalendarEvents(request_user.calendars, startDate, endDate))
|
|
calendarjson = backend.generateJsonFromCalendarEntries(events, colors)
|
|
return jsonify(calendarjson)
|
|
|
|
@app.route("/devicefingerprint.json")
|
|
def generateDeviceFingerprint():
|
|
# Create Three Random Words
|
|
r = RandomWords()
|
|
while True:
|
|
fingerprint = ""
|
|
length = 3
|
|
randos = r.random_words(count=length)
|
|
for i in range(len(randos)):
|
|
fingerprint += randos[i]
|
|
if i < length-1:
|
|
fingerprint += "-"
|
|
|
|
# check not in Device Database
|
|
if not db.session.query(Device).filter(Device.deviceName==fingerprint).first():
|
|
# Save as new Device
|
|
device = Device(deviceName=fingerprint, connection=False)
|
|
device.lastConnection = int(round(time.time()))
|
|
db.session.add(device)
|
|
db.session.commit()
|
|
break;
|
|
|
|
# Send to Device
|
|
return jsonify(deviceName=fingerprint)
|
|
|