# 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//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)