def cancel_participation(): """Cancel the current user's participation to the study.""" user_id = session.get('rr_user_id') if user_id == None: response = make_response(json.dumps('Current user not connected.'), 401) response.headers['Content-Type'] = 'application/json' return response client_log_table_insert(get_max_devices_table_id_from_users_table_id(user_id), user_id, "CANCEL-PARTICIPATION", "") # Send email to the maintainers about the cancellation try: import yagmail yag = yagmail.SMTP(app.config['GMAIL_FROM'], app.config['GMAIL_PWD']) msgBody = ['User id: ' + str(user_id)] print('Sending participation cancellation email with message body: ' + msgBody[0]) yag.send(app.config['EMAIL_TO'], 'CANCEL request from user', msgBody) response = make_response(json.dumps('TrafficSense project informed of participation cancellation.'), 200) response.headers['Content-Type'] = 'application/json' return response except Exception as e: print('Exception' + e.message) response = make_response(json.dumps('Error in informing the TrafficSense project: ' + e.message), 500) response.headers['Content-Type'] = 'application/json' return response
def authenticate_post(): json = request.json user_id = json['userId'] device_id = json['deviceId'] installation_id = json['installationId'] # Get optionally - old clients do not send this client_version = json.get('clientVersion') messaging_token = json.get('messagingToken', '') # 1. check that user exists or abort users_table_id = verify_user_id(user_id) devices_table_id = get_device_table_id( users_table_id, device_id, installation_id) session_token = get_session_token_for_device(devices_table_id) if session_token is None: print('User is not registered. userId=' + user_id) abort(403) # 2. Update messaging token, if included if len(messaging_token) > 1: update_messaging_token(devices_table_id, messaging_token) update_last_activity(devices_table_id, client_version) # 3. Update log client_log_table_insert( devices_table_id, get_user_id_from_device_id(devices_table_id), "MOBILE-AUTHENTICATE", "ClientVersion:" + (client_version or "")) return jsonify({ 'sessionToken': session_token })
def authenticate_post(): json = request.json user_id = json['userId'] device_id = json['deviceId'] installation_id = json['installationId'] # Get optionally - old clients do not send this client_version = json.get('clientVersion') messaging_token = json.get('messagingToken', '') # 1. check that user exists or abort users_table_id = verify_user_id(user_id) devices_table_id = get_device_table_id( users_table_id, device_id, installation_id) session_token = get_session_token_for_device(devices_table_id) if session_token is None: print 'User is not registered. userId=' + user_id abort(403) # 2. Update messaging token, if included if len(messaging_token) > 1: update_messaging_token(devices_table_id, messaging_token) update_last_activity(devices_table_id, client_version) # 3. Update log client_log_table_insert( devices_table_id, get_user_id_from_device_id(devices_table_id), "MOBILE-AUTHENTICATE", "ClientVersion:" + (client_version or "")) return jsonify({ 'sessionToken': session_token })
def path(session_token): devices_table_id = get_device_table_id_for_session(session_token) client_log_table_insert( devices_table_id, get_user_id_from_device_id(devices_table_id), "MOBILE-PATH", request.args.get("date")) devices = db.metadata.tables["devices"] where = devices.c.token == session_token return common_path(request, db, where)
def energymap(): """Draw the energy consumption map of the user.""" user_id = session.get('rr_user_id') if user_id == None: # Not authenticated -> throw back to front page return index() client_log_table_insert(get_max_devices_table_id_from_users_table_id(user_id), user_id, "WEB-PATH", "") return render_template('energymap.html', APPLICATION_NAME=APPLICATION_NAME, RR_URL_PREFIX=app.config['RR_URL_PREFIX'], api_key=app.config['MAPS_API_KEY'])
def download_dump(): user_id = session.get('rr_user_id') if user_id == None: response = make_response(json.dumps( 'No user data in current session.'), 401) response.headers['Content-Type'] = 'application/json' return response client_log_table_insert( get_max_devices_table_id_from_users_table_id(user_id), user_id, "WEB-DOWNLOAD-DATA", "") return common_download_zip(user_id)
def logtest(): user_id = 1 device_id = 1 # Dummy entries for setting up the tables # from pyfiles.database_interface import ( # users_table_insert, devices_table_insert) # users_table_insert("user", "foobar", "barfoo") # devices_table_insert(1, "foobar", "a5b8ef8f-73b1-4197-ade9-29141c0ed6e9", "model", "a5b8ef8f-73b1-4197-ade9-29141c0ed6e9") print('get_user_id_from_device_id: ' + str(get_user_id_from_device_id(device_id))) print('get_max_devices_table_id_from_users_table_id: ' + str(get_max_devices_table_id_from_users_table_id(user_id))) client_log_table_insert(device_id, get_user_id_from_device_id(device_id), "WEB-PATH", "Kukkuluuruu") response = make_response(json.dumps('Logtest successfully executed.'), 200) response.headers['Content-Type'] = 'application/json' return response
def fbrefresh(session_token): device_id = get_device_table_id_for_session(session_token) if device_id < 0: return "" # get the token messaging_token = request.args.get("messaging_token") if len(messaging_token) > 1: update_messaging_token(device_id, messaging_token) user_id = get_user_id_from_device_id(device_id) if user_id < 0: return "" client_log_table_insert(device_id, user_id, "MOBILE-FCM-TOKEN", "") return make_response(json.dumps('Ack'), 200)
def trips_json(): user_id = session.get('rr_user_id') if user_id == None: response = make_response(json.dumps( 'No user data in current session.'), 401) response.headers['Content-Type'] = 'application/json' return response client_log_table_insert( get_max_devices_table_id_from_users_table_id(user_id), user_id, "WEB-TRIPS-LIST", "/".join([ request.args.get("firstday", ""), request.args.get("lastday", "")])) return common_trips_json(request, db, user_id)
def logtest(): user_id = 1 device_id = 1 # Dummy entries for setting up the tables # from pyfiles.database_interface import ( # users_table_insert, devices_table_insert) # users_table_insert("user", "foobar", "barfoo") # devices_table_insert(1, "foobar", "a5b8ef8f-73b1-4197-ade9-29141c0ed6e9", "model", "a5b8ef8f-73b1-4197-ade9-29141c0ed6e9") print 'get_user_id_from_device_id: ' + str( get_user_id_from_device_id(device_id)) print 'get_max_devices_table_id_from_users_table_id: ' + str( get_max_devices_table_id_from_users_table_id(user_id)) client_log_table_insert(device_id, get_user_id_from_device_id(device_id), "WEB-PATH", "Kukkuluuruu") response = make_response(json.dumps('Logtest successfully executed.'), 200) response.headers['Content-Type'] = 'application/json' return response
def setlegmode_post(): """Allow user to correct detected transit modes and line names.""" user_id = session.get('rr_user_id') if user_id == None: # Not authenticated -> throw back to front page return index() device, legid, legact, legline = common_setlegmode(request, db, user_id) client_log_table_insert( device, user_id, "WEB-PATH-EDIT", "%s %s %s" % (legid, legact, legline)) return jsonify({})
def setlegmode_post(): """Allow user to correct detected transit modes and line names.""" devices = db.metadata.tables["devices"] user = select( [devices.c.user_id], devices.c.token == request.json["sessionToken"] ).scalar() device, legid, legact, legline = common_setlegmode(request, db, user) client_log_table_insert( device, user, "MOBILE-PATH-EDIT", "%s %s %s" % (legid, legact, legline)) return jsonify({})
def energycertificate_svg(): user_id = session.get('rr_user_id') if user_id == None: # Not authenticated -> throw back to front page return index() firstlastday = [ d in request.args and datetime.datetime.strptime( request.args[d], '%Y-%m-%d') or None for d in ["firstday", "lastday"]] client_log_table_insert( get_max_devices_table_id_from_users_table_id(user_id), user_id, "WEB-CERTIFICATE", "/".join(str(x)[:10] for x in firstlastday)) return Response(get_svg(user_id, *firstlastday), mimetype="image/svg+xml")
def svg(session_token): device_id = get_device_table_id_for_session(session_token) if device_id < 0: return "" user_id = get_user_id_from_device_id(device_id) if user_id < 0: return "" firstlastday = [ d in request.args and datetime.datetime.strptime( request.args[d], '%Y-%m-%d') or None for d in ["firstday", "lastday"]] client_log_table_insert( device_id, user_id, "MOBILE-CERTIFICATE", "/".join(str(x)[:10] for x in firstlastday)) return get_svg(user_id, *firstlastday)
def connect(): """Exchange the one-time authorization code for a token and store the token in the session.""" # Ensure that the request is not a forgery and that the user sending # this connect request is the expected user. # print 'Session state returns: ' + session.get('state') if request.args.get('state', '') != session.get('state'): response = make_response(json.dumps('Invalid state parameter.'), 401) response.headers['Content-Type'] = 'application/json' print('401 due to invalid state parameter.') return response # Delete the one-time token - page refresh required to re-connect del session['state'] # If this request does not have `X-Requested-With` header, this could be a CSRF if not request.headers.get('X-Requested-With'): response = make_response(json.dumps('Invalid header.'), 403) response.headers['Content-Type'] = 'application/json' print('403 due to missing X-Requested-With header.') return response code = request.data try: # Upgrade the authorization code into a credentials object oauth_flow = flow_from_clientsecrets(CLIENT_SECRET_FILE, scope='profile', redirect_uri='postmessage') credentials = oauth_flow.step2_exchange(code) except FlowExchangeError as err: # invalid token print('Invalid token: ' + code + ". error: " + err.message) response = make_response( json.dumps('Failed to upgrade the authorization code.'), 401) response.headers['Content-Type'] = 'application/json' return response # An ID Token is a cryptographically-signed JSON object encoded in base 64. # Normally, it is critical that you validate an ID Token before you use it, # but since you are communicating directly with Google over an # intermediary-free HTTPS channel and using your Client Secret to # authenticate yourself to Google, you can be confident that the token you # receive really comes from Google and is valid. If your server passes the # ID Token to other components of your app, it is extremely important that # the other components validate the token before using it. google_id = verify_and_get_account_id(CLIENT_ID, credentials)['google_id'] stored_credentials = session.get('credentials') stored_google_id = session.get('google_id') if stored_credentials is not None and google_id == stored_google_id: response = make_response(json.dumps('Current user is already connected.'), 200) response.headers['Content-Type'] = 'application/json' return response # Store the access token in the session for later use. session['credentials'] = credentials session['google_id'] = google_id # Find and store the RegularRoutes user id user_hash_id = user_hash(google_id) user_id = get_users_table_id(user_hash_id) if user_id < 0: # No data for the user -> show the nodata -page print('No data found for the current user.') response = make_response(json.dumps('Nodata.'), 200) response.headers['Content-Type'] = 'application/json' return response client_log_table_insert(get_max_devices_table_id_from_users_table_id(user_id), user_id, "WEB-CONNECT", "") session['rr_user_id'] = user_id response = make_response(json.dumps('Successfully connected user.'), 200) response.headers['Content-Type'] = 'application/json' return response
def destinations(session_token): dd = db.metadata.tables["device_data"] devices = db.metadata.tables["devices"] users = db.metadata.tables["users"] legs = db.metadata.tables["legs"] # Limit number of destinations on output, all if blank given limit = request.args.get("limit", DESTINATIONS_LIMIT) limit = None if limit == "" else int(limit) # Exclude nearby and faraway destinations from point if given, or last # device location is not given. All included if blank given in either. lat = request.args.get("lat") lng = request.args.get("lng") exclude = True if "" not in (lat, lng): if None not in (lat, lng): excoord = "POINT(%s %s)" % (lng, lat) else: excoord = db.engine.execute(select( [func.ST_AsText(dd.c.coordinate)], devices.c.token == session_token, order_by=dd.c.time.desc(), limit=1)).scalar() if excoord is not None: rmin, rmax = INCLUDE_DESTINATIONS_BETWEEN exclude = and_( not_(func.st_dwithin(legs.c.coordinate_start, excoord, rmin)), func.st_dwithin(legs.c.coordinate_start, excoord, rmax)) start = datetime.datetime.now() - datetime.timedelta(days=30) query = select( [ func.ST_AsGeoJSON(legs.c.coordinate_start).label("geojson"), legs.c.time_start, legs.c.time_end], and_( devices.c.token == session_token, legs.c.time_end >= start, legs.c.activity == "STILL", exclude), devices.join(users).join(legs)) stops = list(dict(x) for x in db.engine.execute(query)) for x in stops: x["coordinates"] = json.loads(x["geojson"])["coordinates"] dests = sorted( stop_clusters(stops, DEST_RADIUS_MAX * 2), key=lambda x: x["visits_rank"]) geojson = { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": d["coordinates"]}, "properties": d} for d in dests[:limit]]} for f in geojson["features"]: del f["properties"]["coordinates"] # included in geometry f["properties"]["visits"] = len(f["properties"]["visits"]) devices_table_id = get_device_table_id_for_session(session_token) client_log_table_insert(devices_table_id, get_user_id_from_device_id(devices_table_id), "MOBILE-DESTINATIONS", "") return jsonify(geojson)
def register_post(): """ Server should receive valid one-time token that can be used to authenticate user via Google+ API See: https://developers.google.com/+/web/signin/server-side-flow#step_6_send_the_authorization_code_to_the_server """ data = request.json google_one_time_token = data['oneTimeToken'] device_id = data['deviceId'] installation_id = data['installationId'] device_model = data['deviceModel'] # print 'deviceModel=' + str(device_model) # Get optionally - old clients do not send this client_version = data.get('clientVersion') # 1. authenticate with Google validation_data = authenticate_with_google_oauth(app.config['AUTH_REDIRECT_URI'], CLIENT_SECRET_FILE, CLIENT_ID, google_one_time_token) if validation_data is None: abort(403) # auth failed account_google_id = validation_data['google_id'] # The following hash value is also generated in client and used in authentication user_id = user_hash(account_google_id) users_table_id = None # 2. Check if user has registered previously ext_users_table_id = get_users_table_id(user_id) if ext_users_table_id >= 0: users_table_id = ext_users_table_id # 3. Check if same device has registered with same user devices_table_id = get_device_table_id( users_table_id, device_id, installation_id) # 4. create/update user to db if users_table_id is None: users_table_id = users_table_insert(str(user_id), str(validation_data['refresh_token']), str(validation_data['access_token'])) else: print 're-registration for same user detected -> using existing user account' users_table_update(str(users_table_id), str(validation_data['refresh_token']), str(validation_data['access_token'])) # 5. Create/update device to db if devices_table_id is None: session_token = uuid4().hex devices_table_id = devices_table_insert( users_table_id, device_id, installation_id, device_model, session_token, client_version) else: print 'device re-registration detected -> using same device' update_last_activity(devices_table_id, client_version) session_token = get_session_token_for_device(devices_table_id) # 6. Log the registration client_log_table_insert( devices_table_id, users_table_id, "MOBILE-REGISTER", "ClientVersion:" + (client_version or "")) resp = jsonify({'sessionToken': session_token}) return resp
def register_post(): """ Server should receive valid one-time token that can be used to authenticate user via Google+ API """ data = request.json google_one_time_token = data['oneTimeToken'] device_id = data['deviceId'] installation_id = data['installationId'] device_model = data['deviceModel'] # print 'deviceModel=' + str(device_model) # Get optionally - old clients do not send this client_version = data.get('clientVersion') # 1. authenticate with Google validation_data, response = authenticate_with_google_oauth(app.config['AUTH_REDIRECT_URI'], CLIENT_SECRET_FILE, CLIENT_ID, google_one_time_token) if response: return response account_google_id = validation_data['google_id'] # The following hash value is also generated in client and used in authentication user_id = user_hash(account_google_id) users_table_id = None # 2. Check if user has registered previously ext_users_table_id = get_users_table_id(user_id) if ext_users_table_id >= 0: users_table_id = ext_users_table_id # 3. Check if same device has registered with same user devices_table_id = get_device_table_id( users_table_id, device_id, installation_id) # 4. create/update user to db if users_table_id is None: users_table_id = users_table_insert(str(user_id), str(validation_data['refresh_token']), str(validation_data['access_token'])) else: print('re-registration for same user detected -> using existing user account') users_table_update(str(users_table_id), str(validation_data['refresh_token']), str(validation_data['access_token'])) # 5. Create/update device to db if devices_table_id is None: session_token = uuid4().hex devices_table_id = devices_table_insert( users_table_id, device_id, installation_id, device_model, session_token, client_version) else: print('device re-registration detected -> using same device') update_last_activity(devices_table_id, client_version) session_token = get_session_token_for_device(devices_table_id) # 6. Log the registration client_log_table_insert( devices_table_id, users_table_id, "MOBILE-REGISTER", "ClientVersion:" + (client_version or "")) resp = jsonify({'sessionToken': session_token}) return resp