2020-04-22 22:15:21 +02:00
|
|
|
# Python standard libraries
|
|
|
|
import json
|
|
|
|
import os
|
2020-07-17 10:39:16 +02:00
|
|
|
import time
|
2020-04-22 22:15:21 +02:00
|
|
|
|
|
|
|
# Third-party libraries
|
|
|
|
import flask
|
2020-04-23 19:11:23 +02:00
|
|
|
from flask import render_template, flash
|
2020-05-24 13:26:41 +02:00
|
|
|
from flask import Flask, redirect, request, url_for, jsonify
|
2020-04-22 22:15:21 +02:00
|
|
|
from flask_login import (
|
|
|
|
LoginManager,
|
|
|
|
current_user,
|
|
|
|
login_required,
|
|
|
|
login_user,
|
|
|
|
logout_user,
|
|
|
|
)
|
2020-07-10 10:11:31 +02:00
|
|
|
from random_words import RandomWords
|
2020-04-22 22:15:21 +02:00
|
|
|
import requests
|
|
|
|
|
|
|
|
import server.googleHandler as google
|
|
|
|
|
|
|
|
from server import login_manager, app, db
|
2020-05-21 18:33:58 +02:00
|
|
|
from server.forms import LoginForm, RegistrationForm, DeviceForm
|
2020-05-30 23:05:46 +02:00
|
|
|
import backend
|
2020-05-27 20:06:43 +02:00
|
|
|
from database.models import User, Calendar, Device, GoogleToken
|
2020-04-22 22:15:21 +02:00
|
|
|
|
2020-05-10 20:31:42 +02:00
|
|
|
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
@app.route("/")
|
2020-06-06 20:02:18 +02:00
|
|
|
def startpage():
|
|
|
|
return flask.render_template('startpage.html')
|
|
|
|
|
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
|
2020-05-29 20:30:37 +02:00
|
|
|
@app.route("/privacy")
|
|
|
|
def privacy():
|
|
|
|
return flask.render_template('privacy.html')
|
|
|
|
|
2020-06-06 20:02:18 +02:00
|
|
|
@app.route("/login")
|
|
|
|
def login():
|
|
|
|
if current_user.is_authenticated:
|
|
|
|
return redirect(url_for('account'))
|
|
|
|
return flask.render_template('login.html')
|
|
|
|
|
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
@app.route("/account")
|
2020-06-06 20:02:18 +02:00
|
|
|
def account():
|
2020-04-22 22:15:21 +02:00
|
|
|
if current_user.is_authenticated:
|
2020-06-06 20:02:18 +02:00
|
|
|
calendars = []
|
2020-05-30 23:05:46 +02:00
|
|
|
gCalendars, colors, token = google.fetchCalendars()
|
2020-06-06 20:02:18 +02:00
|
|
|
if token != None:
|
|
|
|
current_user.google_token.token = token
|
|
|
|
db.session.commit()
|
|
|
|
calendars.extend(gCalendars)
|
|
|
|
backend.updateCalendars(current_user, calendars, colors)
|
2020-05-30 23:05:46 +02:00
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
return (flask.render_template('account.html',
|
|
|
|
username = current_user.username, email = current_user.email, profile_img=current_user.profile_pic
|
|
|
|
)
|
|
|
|
)
|
|
|
|
else:
|
2020-06-06 20:02:18 +02:00
|
|
|
return redirect(url_for("login"))
|
2020-04-22 22:15:21 +02:00
|
|
|
|
2020-05-21 15:38:22 +02:00
|
|
|
@app.route("/view")
|
|
|
|
def view():
|
|
|
|
if not current_user.is_authenticated:
|
|
|
|
return flask.render_template('login.html')
|
|
|
|
else:
|
|
|
|
return (flask.render_template('view.html'))
|
2020-05-21 18:33:58 +02:00
|
|
|
|
|
|
|
@app.route("/devices", methods=['GET', 'POST'])
|
|
|
|
def devices():
|
|
|
|
if not current_user.is_authenticated:
|
|
|
|
return flask.render_template('login.html')
|
2020-05-28 12:00:05 +02:00
|
|
|
|
|
|
|
# if this is a post request from the 'unlink' submittion form
|
|
|
|
# delete this device from the list
|
2020-07-10 10:11:31 +02:00
|
|
|
form = DeviceForm()
|
2020-05-28 12:00:05 +02:00
|
|
|
if request.method == 'POST':
|
2020-07-10 10:11:31 +02:00
|
|
|
|
2020-05-28 12:00:05 +02:00
|
|
|
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
|
2020-07-10 10:11:31 +02:00
|
|
|
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()
|
2020-05-28 15:43:51 +02:00
|
|
|
|
2020-05-28 12:00:05 +02:00
|
|
|
return flask.render_template('devices.html',
|
|
|
|
devices=current_user.devices,
|
|
|
|
form=form)
|
2020-05-21 18:33:58 +02:00
|
|
|
|
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
@app.route("/calendar")
|
|
|
|
@login_required
|
|
|
|
def calendar():
|
2020-05-30 23:05:46 +02:00
|
|
|
calendars = backend.calendarsFromDb(current_user)
|
2020-04-22 22:15:21 +02:00
|
|
|
return flask.render_template('calendar.html', calendars=calendars)
|
|
|
|
|
2020-04-23 19:11:23 +02:00
|
|
|
@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)
|
|
|
|
|
2020-05-21 18:33:58 +02:00
|
|
|
|
2020-04-23 19:11:23 +02:00
|
|
|
@app.route('/register', methods=['GET', 'POST'])
|
|
|
|
def register():
|
|
|
|
if current_user.is_authenticated:
|
|
|
|
return redirect(url_for('account'))
|
2020-05-28 12:00:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-23 19:11:23 +02:00
|
|
|
form = RegistrationForm()
|
|
|
|
if form.validate_on_submit():
|
2020-05-28 00:05:53 +02:00
|
|
|
user = User(userid=form.username.data,
|
2020-04-23 19:11:23 +02:00
|
|
|
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'))
|
2020-05-21 18:33:58 +02:00
|
|
|
return flask.render_template('register.html', title='Register', form=form)
|
2020-04-23 19:11:23 +02:00
|
|
|
|
2020-05-22 10:47:28 +02:00
|
|
|
@app.route("/delete_account")
|
|
|
|
def deleteAccount():
|
|
|
|
if not current_user.is_authenticated:
|
|
|
|
return redirect(url_for('account'))
|
2020-05-28 00:05:53 +02:00
|
|
|
if current_user.google_token != None:
|
|
|
|
google.deleteAccount(current_user)
|
2020-05-28 12:00:05 +02:00
|
|
|
|
2020-05-27 20:06:43 +02:00
|
|
|
db.session.delete(current_user)
|
2020-05-22 10:47:28 +02:00
|
|
|
db.session.commit()
|
2020-05-27 20:06:43 +02:00
|
|
|
logout_user()
|
2020-05-15 16:00:54 +02:00
|
|
|
|
2020-05-22 10:47:28 +02:00
|
|
|
return redirect(url_for('account'))
|
2020-05-15 16:00:54 +02:00
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
@app.route("/login/google")
|
2020-04-23 19:11:23 +02:00
|
|
|
def googlelogin():
|
2020-05-29 20:30:37 +02:00
|
|
|
if current_user.is_authenticated and current_user.google_token != None:
|
2020-05-24 13:26:41 +02:00
|
|
|
return redirect(url_for('account'))
|
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
authorization_url = google.login()
|
|
|
|
|
|
|
|
return flask.redirect(authorization_url)
|
|
|
|
|
|
|
|
@app.route("/login/google/callback")
|
|
|
|
def callback():
|
2020-04-24 19:54:56 +02:00
|
|
|
session, credentials = google.verifyResponse()
|
2020-04-22 22:15:21 +02:00
|
|
|
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.
|
2020-05-27 20:06:43 +02:00
|
|
|
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)
|
2020-04-22 22:15:21 +02:00
|
|
|
newser = User(
|
2020-05-27 20:06:43 +02:00
|
|
|
|
|
|
|
userid=userinfo['id'],
|
2020-04-22 22:15:21 +02:00
|
|
|
username=userinfo['name'],
|
|
|
|
email=userinfo['email'],
|
|
|
|
profile_pic=userinfo['picture'],
|
2020-05-27 20:06:43 +02:00
|
|
|
password_hash="",
|
|
|
|
google_token = gc
|
2020-04-22 22:15:21 +02:00
|
|
|
)
|
|
|
|
db.session.add(newser)
|
|
|
|
db.session.commit()
|
|
|
|
|
2020-05-27 20:06:43 +02:00
|
|
|
user = db.session.query(User).filter(User.userid==userinfo['id']).first()
|
2020-04-22 22:15:21 +02:00
|
|
|
|
|
|
|
# Begin user session by logging the user in
|
|
|
|
login_user(user)
|
2020-05-27 20:06:43 +02:00
|
|
|
|
2020-06-06 23:49:39 +02:00
|
|
|
return flask.redirect(flask.url_for('account'))
|
2020-04-22 22:15:21 +02:00
|
|
|
|
|
|
|
@app.route("/logout")
|
|
|
|
@login_required
|
|
|
|
def logout():
|
|
|
|
logout_user()
|
2020-06-06 23:49:39 +02:00
|
|
|
return redirect(url_for("startpage"))
|
2020-04-22 22:15:21 +02:00
|
|
|
|
|
|
|
|
2020-05-28 15:43:51 +02:00
|
|
|
@app.route("/device/<path:device>/calendarevents.json")
|
2020-05-24 13:26:41 +02:00
|
|
|
def downloader(device):
|
2020-05-28 15:43:51 +02:00
|
|
|
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:
|
2020-05-24 13:26:41 +02:00
|
|
|
return jsonify(kind="unregistered")
|
|
|
|
|
2020-07-17 10:39:16 +02:00
|
|
|
request_device.lastConnection=int(round(time.time()))
|
2020-05-28 15:43:51 +02:00
|
|
|
request_device.connection=True
|
|
|
|
db.session.commit()
|
|
|
|
request_user = db.session.query(User).filter(User.id==request_device.user_id).first()
|
|
|
|
|
2020-05-29 20:30:37 +02:00
|
|
|
# TODO add test if googke token exists
|
|
|
|
# if request_user.google_token != Null:
|
2020-05-30 23:05:46 +02:00
|
|
|
# TODO only pass along google calendars form user
|
|
|
|
startDate, endDate = backend.getTimeStamps()
|
|
|
|
events, colors = google.fetchCalendarEvents(request_user, request_user.calendars, startDate, endDate)
|
|
|
|
calendarjson = backend.generateJsonFromCalendarEntries(events, colors)
|
2020-05-27 20:36:05 +02:00
|
|
|
return jsonify(calendarjson)
|
2020-05-24 13:26:41 +02:00
|
|
|
|
|
|
|
@app.route("/devicefingerprint.json")
|
|
|
|
def generateDeviceFingerprint():
|
|
|
|
# Create Three Random Words
|
2020-05-28 15:43:51 +02:00
|
|
|
r = RandomWords()
|
|
|
|
while True:
|
|
|
|
fingerprint = ""
|
|
|
|
length = 3
|
2020-07-10 10:11:31 +02:00
|
|
|
randos = r.random_words(count=length)
|
2020-05-28 15:43:51 +02:00
|
|
|
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)
|
|
|
|
db.session.add(device)
|
|
|
|
db.session.commit()
|
|
|
|
break;
|
|
|
|
|
|
|
|
# Send to Device
|
|
|
|
return jsonify(deviceName=fingerprint)
|
2020-04-22 22:15:21 +02:00
|
|
|
|
|
|
|
# POST
|
|
|
|
|
|
|
|
@app.route('/calendar', methods = ['POST', 'DELETE'])
|
|
|
|
@login_required
|
|
|
|
def user():
|
|
|
|
if request.method == 'POST':
|
2020-05-18 23:52:18 +02:00
|
|
|
calId = request.json.get('calendar_id')
|
|
|
|
color = request.json.get('color', None)
|
|
|
|
toggle = request.json.get('toggle', None)
|
2020-04-22 22:15:21 +02:00
|
|
|
|
|
|
|
if color != None:
|
2020-05-27 20:36:05 +02:00
|
|
|
current_user.updateCalendar(calId, color=color)
|
2020-04-22 22:15:21 +02:00
|
|
|
if toggle != None:
|
2020-05-27 20:36:05 +02:00
|
|
|
current_user.updateCalendar(calId, toggle=toggle)
|
2020-04-22 22:15:21 +02:00
|
|
|
# toggle specific calendar of user
|
2020-05-18 23:52:18 +02:00
|
|
|
|
2020-04-22 22:15:21 +02:00
|
|
|
elif request.method == 'DELETE':
|
|
|
|
# do nothing
|
|
|
|
return 'NONE'
|
|
|
|
else:
|
|
|
|
# POST Error 405
|
|
|
|
print("405")
|
|
|
|
|
|
|
|
return 'OK'
|