-
Notifications
You must be signed in to change notification settings - Fork 0
/
stackptr.py
executable file
·391 lines (323 loc) · 10.6 KB
/
stackptr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
#!/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()