#!/usr/bin/env python #################### # Imports #################### from flask import * from flask_wtf import * from flask_cors import * app = application = Flask(__name__) app.config['WTF_CSRF_CHECK_DEFAULT'] = False csrf = CSRFProtect() csrf.init_app(app) import os import json import md5 import datetime import random import string import calendar import pytz import ConfigParser config = ConfigParser.ConfigParser() config.read(os.path.join(app.root_path, "stackptr.conf")) app.secret_key = config.get("app","secret_key") app.invite_code = config.get("app","invite_code", None) import logging, sys logging.basicConfig(stream=sys.stderr) import crossbarconnect from werkzeug.security import * from flask_login import login_user, logout_user, login_required, current_user, LoginManager from flask_sqlalchemy import SQLAlchemy from flask_script import Manager from flask_migrate import Migrate, MigrateCommand import stackptr_core #################### # Config #################### app.config['SQLALCHEMY_DATABASE_URI'] = config.get("database","uri") app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False from models import * db = SQLAlchemy(app) migrate = Migrate(app, Base) manager = Manager(app) manager.add_command('db', MigrateCommand) #################### # Login #################### login_manager = LoginManager(app) login_manager.login_view = 'login' @login_manager.user_loader def load_user(id): csrf.protect() return db.session.query(Users).get(int(id)) @login_manager.request_loader def load_user_from_request(request): apikey = None if request.method == "POST": apikey = request.form.get('apikey') else: apikey = request.args.get('apikey') if apikey: key = db.session.query(ApiKey).filter_by(key=apikey).first() if key == None: return None return db.session.query(Users).filter_by(id=key.userid).first() return None @login_manager.unauthorized_handler def unauthorized(): if request.form.get('apikey') or request.args.get('apikey'): return abort(401) else: return redirect(login_manager.login_view) @app.before_request def before_request(): g.user = current_user #################### # Index #################### @app.route('/') @login_required def index(): return send_from_directory("templates","map.html") # registration @app.route('/registration', methods=['GET','POST']) def registration(): if app.invite_code is None: return "invites disabled" if request.method == "GET": return render_template("registration.html") else: username = request.form['username'] email = request.form['email'] password = request.form['password'] invite_code = request.form['invite'] #todo check these are valid email and password values if invite_code != app.invite_code: return "invalid invite code" registered_email = db.session.query(Users).filter_by(email=email).first() #check if email already in DB if registered_email: return "email address already registered %s" % email registered_user = db.session.query(Users).filter_by(username=username).first() # check user name is registered in DB if registered_user: return "username already registered %s" % username else: user = Users(username, email) user.password = generate_password_hash(password) db.session.add(user) db.session.commit() tp = TrackPerson(user.id,username) db.session.add(tp) db.session.commit() login_user(user,remember=True) return redirect("/") ## login @app.route('/csrf') def csrftoken(): return render_template("csrf.html") @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == "GET": return render_template("login.html") else: email = request.form['email'] password = request.form['password'] registered_user = db.session.query(Users).filter_by(email=email).first() if not registered_user: return "no such user or incorrect password", 403 if check_password_hash(registered_user.password, password): login_user(registered_user, remember=True) return redirect("/") return "no such user or incorrect password", 403 @app.route('/logout') @login_required def logout(): logout_user() return redirect("/") ## API keys @app.route('/api/') @login_required def api_info(): keys = db.session.query(ApiKey).filter_by(userid = g.user.id).order_by(ApiKey.created).all() return render_template("api.html", keys=keys) @app.route('/api/new', methods=['POST']) @login_required def api_create(): key = ApiKey() key.key = "".join([random.choice(string.ascii_letters + string.digits) for n in xrange(32)]) key.userid = g.user.id key.created = datetime.datetime.now() key.name = request.form['description'] db.session.add(key) db.session.commit() if 'return' in request.form: return key.key return redirect(url_for('api_info')) @app.route('/api/remove', methods=['POST']) @login_required def api_remove(): key = db.session.query(ApiKey).filter_by(key = request.form['key_id'], userid=g.user.id).first() db.session.delete(key) db.session.commit() return redirect(url_for('api_info')) #################### # WebSocket functions #################### @app.route('/ws_uid', methods=['POST']) @cross_origin() @login_required def ws_uid(): return str(g.user.id) @app.route('/ws_token', methods=['POST']) @cross_origin() @login_required def ws_token(): at = AuthTicket() at.key = "".join([random.choice(string.ascii_letters + string.digits) for n in xrange(30)]) at.userid = g.user.id at.created = datetime.datetime.now() db.session.add(at) db.session.commit() # fixme: remove old tokens return str(at.key) #################### # Data #################### @app.route('/uid', methods=['POST']) @cross_origin() @login_required def sp_uid(): return json.dumps({'id': g.user.id, 'username': g.user.username, 'icon': stackptr_core.gravatar(g.user.email, size=256)}) @app.route('/users') @cross_origin() @login_required def userjson(): data = stackptr_core.userList(g.user, db=db) return Response(json.dumps(data), mimetype="text/json") def publish_message(dest, topic, msg=None, eligible=[]): if eligible != []: client = crossbarconnect.Client("http://127.0.0.1:9000/") client.publish(dest, topic, msg=msg, options={'eligible': eligible}) @app.route('/update', methods=['POST']) @cross_origin() @login_required def update(): lat = request.form.get('lat', None) lon = request.form.get('lon', None) alt = request.form.get('alt', None) hdg = request.form.get('hdg', None) spd = request.form.get('spd', None) ext = request.form.get('ext', None) return json.dumps(stackptr_core.update(lat,lon,alt,hdg,spd,ext,pm=publish_message,guser=g.user,db=db)) @app.route('/lochist', methods=['POST', 'GET']) @cross_origin() @login_required def lochist(): target = request.args.get('uid', g.user.id) return json.dumps(stackptr_core.locHist(target=target, guser=g.user, db=db)) @app.route('/acceptuser', methods=['POST']) @cross_origin() @login_required def acceptuser(): user = request.form['uid'] return json.dumps(stackptr_core.acceptUser(uid=user, pm=publish_message, guser=g.user, db=db)) @app.route('/adduser', methods=['POST']) @cross_origin() @login_required def adduser(): user = request.form['user'] return json.dumps(stackptr_core.addUser(user=user, pm=publish_message, guser=g.user, db=db)) @app.route('/deluser', methods=['POST']) @cross_origin() @login_required def deluser(): user = request.form['uid'] return json.dumps(stackptr_core.delUser(uid=user, pm=publish_message, guser=g.user, db=db)) ########### @app.route('/grouplist') @cross_origin() @login_required def grouplist(): return json.dumps(stackptr_core.groupList(guser=g.user, db=db)) @app.route('/groupdiscover') @cross_origin() @login_required def groupdiscover(): return json.dumps(stackptr_core.groupDiscover(guser=g.user, db=db)) @app.route('/creategroup', methods=['POST']) @cross_origin() @login_required def creategroup(): name = request.form.get('name') description = request.form.get('description') status = int(request.form.get('status')) return json.dumps(stackptr_core.createGroup(db=db, guser=g.user, name=name, description=description, status=status)) @app.route('/joingroup', methods=['POST']) @cross_origin() @login_required def joingroup(): gid = request.form.get('gid') return json.dumps(stackptr_core.joinGroup(db=db, pm=publish_message, guser=g.user, gid=gid)) @app.route('/groupusermod', methods=['POST']) @cross_origin() @login_required def groupusermod(): gid = request.form.get('gid') uid = request.form.get('uid') user = request.form.get('user') role = request.form.get('role') return json.dumps(stackptr_core.groupUserMod(gid=gid, uid=uid, user=user, role=role, pm=publish_message, guser=g.user, db=db)) @app.route('/leavegroup', methods=['POST']) @cross_origin() @login_required def leavegroup(): name = request.form.get('gid') return json.dumps(stackptr_core.leaveGroup(db=db, pm=publish_message, guser=g.user, gid=gid)) @app.route('/deletegroup', methods=['POST']) @cross_origin() @login_required def deletegroup(): name = request.form.get('gid') return json.dumps(stackptr_core.deleteGroup(db=db, pm=publish_message, guser=g.user, gid=gid)) @app.route('/updategroup', methods=['POST']) @cross_origin() @login_required def updategroup(): name = request.form.get('name') description = request.form.get('description') status = int(request.form.get('status')) gid = int(request.form.get('gid')) return json.dumps(stackptr_core.updateGroup(db=db, pm=publish_message, guser=g.user, gid=gid, name=name, description=description, status=status)) ########### @app.route('/groupdata', methods=['POST']) @cross_origin() @login_required def groupdata(): return json.dumps(stackptr_core.groupData(db=db, guser=g.user, gid=request.form.get('gid'))) @app.route('/addfeature', methods=['POST']) @cross_origin() @login_required def addfeature(): name = request.form.get('name',"Untitled") group = int(request.form['group']) ownerid = g.user.id gjson = request.form['gjson'] return json.dumps(stackptr_core.addFeature(db=db, pm=publish_message, name=name, group=group, guser=ownerid, gjson=gjson)) @app.route('/delfeature', methods=['POST']) @cross_origin() @login_required def delfeature(): fid = int(request.form['fid']) return json.dumps(stackptr_core.deleteFeature(db=db, pm=publish_message, fid=fid, guser=g.user)) @app.route('/editfeature', methods=['POST']) @cross_origin() @login_required def editfeature(): gjson = request.form.get('gjson', None) name = request.form.get('name', None) description = request.form.get('description', None) fid = int(request.form['fid']) return json.dumps(stackptr_core.editFeature(db=db, pm=publish_message, fid=fid, gjson=gjson, name=name, description=description, guser=g.user)) if __name__ == '__main__': manager.run()