def get(self, uuid): survey = database.survey.get(current_identity.survey_id) start = dateutil.parser.parse(request.values.get('startTime')) end = dateutil.parser.parse(request.values.get('endTime')) parameters = { 'break_interval_seconds': survey.trip_break_interval, 'cold_start_distance_meters': survey.trip_break_cold_start_distance, 'subway_buffer_meters': survey.trip_subway_buffer, 'accuracy_cutoff_meters': survey.gps_accuracy_threshold } gps_points = database.mobile_user.coordinates(survey, uuid, start, end) trips, summaries = tripbreaker.run(parameters, survey.subway_stops, gps_points) response = { 'trips': to_trips_geojson(trips, summaries) if trips else {}, 'searchStart': start.isoformat(), 'searchEnd': end.isoformat() } return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=response)
def get(self): survey = database.survey.get(current_identity.survey_id) start_time = database.survey.get_start_time(survey) if start_time: start_time = start_time.isoformat() contact_email = survey.contact_email if not contact_email: admin_user = database.survey.get_admin(survey) contact_email = admin_user.email response = { 'survey_id': survey.id, 'about_text': survey.about_text, 'terms_of_service': survey.terms_of_service, 'contact_email': contact_email, 'survey_start': start_time, 'survey_max_days': survey.max_survey_days, 'survey_max_prompts': survey.max_prompts, 'survey_record_acceleration': survey.record_acceleration, 'survey_record_mode': survey.record_mode, 'gps_accuracy_threshold_meters': survey.gps_accuracy_threshold, 'tripbreaker_interval_seconds': survey.trip_break_interval, 'tripbreaker_cold_start_distance_meters': survey.trip_break_cold_start_distance, 'tripbreaker_subway_buffer_meters': survey.trip_subway_buffer } return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(response))
def delete_inactive_survey(): survey_name = request.form.get('surveyName') error = database.survey_admin.delete(survey_name) if not error: # format the same as jinja2 renders the template response = { 'recent_signups': [], 'message': 'Survey "{}" deleted.'.format(survey_name) } for survey in database.survey_admin.get_recent_signups(10): response['recent_signups'].append({ 'name': survey.name, 'pretty_name': survey.pretty_name, 'created_at': str(survey.created_at.replace(microsecond=0)), 'active': 'True' if survey.mobile_coordinates.first() else 'False' }) return Success(status_code=200, headers={'Location': '/manage-surveys/delete'}, resource_type='NewSurveySchema', body=response) return Error(status_code=400, headers={'Location': '/manage-surveys/delete'}, resource_type='NewSurveySchema', errors=[error])
def post(self): validations = [{ 'admin_email': { 'key': 'email', 'validator': value_exists, 'response': Error, 'error': 'Email cannot be blank.', }, 'admin_password': { 'key': 'password', 'validator': value_exists, 'response': Error, 'error': 'Password cannot be blank.', }, 'survey_name': { 'key': 'surveyName', 'validator': value_exists, 'response': Error, 'error': 'Survey name cannot be blank.', }, 'signup_code': { 'key': 'signupCode', 'validator': database.survey.register.use_token, 'response': Error, 'error': 'Survey sign-up token is invalid.', } }] validated = validate_json(validations, self.headers, self.resource_type) errors = [] survey = database.survey.register.create( survey_name=validated['survey_name']) if survey: admin_role = database.web_user.create_admin( survey=survey, email=validated['admin_email'], password=validated['admin_password']) reseacher_token = database.web_user.create_invite_researcher_token( survey) else: errors.append('Survey already exists.') if not errors: if not admin_role: errors.append('Admin user could not be created.') if not reseacher_token: errors.append( 'Initial invite reseacher token could not be created.') if errors: return Error(status_code=400, headers=self.headers, resource_type=self.resource_type, errors=errors) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(validated))
def post(self): survey = database.survey.get(current_identity.survey_id) data = request.files.get('stops') dialect = csv.Sniffer().sniff(data.read(), delimiters=';,') data.seek(0) reader = csv.DictReader(data, dialect=dialect) reader.fieldnames = [name.lower() for name in reader.fieldnames] # determine the keys out of the options for the lat/lng columns location_columns = None location_columns_options = [('latitude', 'longitude'), ('lat', 'lng'), ('y', 'x')] for columns in location_columns_options: if set(columns).issubset(set(reader.fieldnames)): location_columns = columns # insert subway stations into database if location_columns: rename = ('latitude' and 'longitude') not in location_columns if rename: reader = self._rename_columns(location_columns, reader) subway_stops = database.survey.upsert_subway_stops(survey=survey, stops=reader) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body={'stations': to_prompts_geojson(subway_stops)}) return Error(status_code=400, headers=self.headers, resource_type=self.resource_type, errors=['Failed to parse subway stops .csv file'])
def post(self): results = {} # check if a survey with the same name exists survey_name = request.json.get('surveyName') if survey_name: if not database.survey.find_by_name(survey_name): results['survey_name'] = True else: results['survey_name'] = False # check if the email already exists in database email = request.json.get('email') if email: if not database.web_user.find_by_email(email): results['email'] = True else: results['email'] = False # check that entered signup code is valid signup_token = request.json.get('signupCode') if signup_token: if database.survey.register.validate_token(signup_token): results['signup_code'] = True else: results['signup_code'] = False return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(results))
def post(self): validations = [{ 'language': { 'key': 'language', 'validator': value_exists, 'response': Error, 'error': 'Language selection cannot be blank.', }, 'about_text': { 'key': 'aboutText', 'validator': value_exists, 'response': Error, 'error': 'Survey about text cannot be blank.', }, 'terms_of_service': { 'key': 'termsOfService', 'validator': value_exists, 'response': Error, 'error': 'Survey terms of service name cannot be blank.', } }] validated = validate_json(validations, self.headers, self.resource_type) survey = database.survey.get(current_identity.survey_id) database.survey.update(survey, settings=validated, questions=request.json['questions']) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body=request.json)
def post(self): survey = database.survey.get(current_identity.survey_id) img = request.files.get('avatar') # delete the previous avatar image file if survey.avatar_uri: filehandler.delete(survey.avatar_uri) # shrink avatar image size try: thumbnail = filehandler.make_thumbnail(img) except IOError as e: return Error(status_code=400, headers=self.headers, resource_type=self.resource_type, errors=[e.message]) filename = filehandler.save( thumbnail, extensions=set(['.jpg', '.jpeg', '.gif', '.png', '.bmp'])) # get image uri by finding static folder within avatar path. This # is to dynamically include subfolders within the static assets folder with current_app.app_context(): uri = '{base}/user/avatars/{file}'.format( base=current_app.config['ASSETS_ROUTE'], file=filename) survey.avatar_uri = uri database.survey.update(survey) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body={'avatarUri': uri})
def post(self): survey = database.survey.get(current_identity.survey_id) database.prompts.update(survey=survey, prompts=request.json['prompts']) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body=request.json)
def post(self): survey = database.survey.get(current_identity.survey_id) database.survey.reset(survey) survey = database.survey.get_survey_questions_json(survey) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body={'survey': survey})
def get(self): survey = database.survey.get(current_identity.survey_id) token = database.web_user.get_invite_researcher_token(survey) if not token: token = database.web_user.create_invite_researcher_token(survey) return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body={'token': token.token})
def post(self): survey = database.survey.get(current_identity.survey_id) response = { 'token': database.web_user.create_invite_researcher_token(survey).token } return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body=response)
def disable_account_recovery_token(): token_id = request.form['tokenId'] token = database.token.account_recovery.disable(token_id) response = { 'message': 'WebUserResetPasswordToken {id} disabled.'.format(id=token.id) } return Success(status_code=201, headers={'Location': '/account-recovery/deactivate'}, resource_type='DeactivateNewSurveyToken', body=response)
def delete(self): survey = database.survey.get(current_identity.survey_id) survey.subway_stops.delete() db.session.commit() return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body={'stations': { 'features': [] }})
def get(self): survey = database.survey.get(current_identity.survey_id) response = { 'stations': to_prompts_geojson(survey.subway_stops), 'bufferSize': survey.trip_subway_buffer } return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=response)
def post(self): json_data = json.loads(request.data.decode('utf-8')) data = rename_json_keys(json_data, camelcase_to_underscore) survey_name = data['survey_name'].lower().strip() survey = database.survey.find_by_name(survey_name) if not survey: return Error(status_code=410, headers=self.headers, resource_type=self.resource_type, errors=['Specified survey not found']) user = database.user.create(survey=survey, user_data=data['user']) if user: survey_json = database.survey.formatted_survey_questions(survey) prompts_json = database.survey.formatted_survey_prompts(survey) # supply a default max_prompts value of 0 if no prompts are set instead of None max_prompts = survey.max_prompts if len(prompts_json) > 0 else 0 response = { 'user': '******', 'uuid': data['user']['uuid'], 'contact_email': survey.contact_email, 'default_avatar': get_default_avatar_path(), 'avatar': survey.avatar_uri, 'survey': survey_json, 'prompt': { 'max_days': survey.max_survey_days, 'max_prompts': max_prompts, 'num_prompts': len(prompts_json), 'prompts': prompts_json }, 'lang': survey.language, 'about_text': survey.about_text, 'terms_of_service': survey.terms_of_service, 'survey_name': survey.pretty_name, 'record_acceleration': survey.record_acceleration, 'record_mode': survey.record_mode } # add in deprecation warning for v1 api return Success( status_code=201, headers=self.headers, resource_type=self.resource_type, status= 'Warning (deprecated): API v1 will soon be phased out. Please refer to documentation for v2 calls.', body=rename_json_keys(response, underscore_to_camelcase)) return Error(status_code=400, headers=self.headers, resource_type=self.resource_type, errors=['Could not register new user.'])
def delete(self, email): survey = database.survey.get(current_identity.survey_id) user = survey.web_users.filter_by(email=email).one_or_none() if user: database.web_user.delete(user) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body={}) return Error(status_code=401, headers=self.headers, resource_type=self.resource_type, errors=['Web user could not be deleted from survey.'])
def get(self): survey = database.survey.get(current_identity.survey_id) prompts = database.prompts.formatted_prompt_questions(survey) response = { 'survey_id': survey.id, 'prompts': prompts, 'started': True if database.survey.get_start_time(survey) else False } return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(response))
def get(self): survey = database.survey.get(current_identity.survey_id) uri = survey.avatar_uri # use default avatar if a custom one is not set if not uri: with current_app.app_context(): uri = '{base}/static/{avatar}'.format( base=current_app.config['ASSETS_ROUTE'], avatar=current_app.config['DEFAULT_AVATAR_FILENAME']) return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body={'avatarUri': uri})
def put(self): email = request.json.get('email') password = request.json.get('password') token = request.json.get('token') user = database.web_user.update_password(email, password, token) if user: return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body={}) return Error(status_code=401, headers=self.headers, resource_type=self.resource_type, errors=[])
def get(self): survey = database.survey.get(current_identity.survey_id) sort_fields = json.loads(request.values.get('sorting', '{}')) page_index = int(request.values.get('pageIndex')) items_per_page = int(request.values.get('itemsPerPage')) response = database.web_user.paginated_table( survey=survey, page_index=page_index, items_per_page=items_per_page, sort_fields=sort_fields) return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=response)
def post(self): data = json.loads(request.data) survey_name = data['survey_name'].lower() survey = database.survey.find_by_name(survey_name) if not survey: return Error(status_code=400, headers=self.headers, resource_type=self.resource_type, errors=['Specified survey not found']) user = database.user.create(survey=survey, user_data=data['user']) if user: survey_json = database.survey.formatted_survey_questions(survey) prompts_json = database.survey.formatted_survey_prompts(survey) # supply a default max_prompts value of 0 if no prompts are set instead of None max_prompts = survey.max_prompts if len(prompts_json) > 0 else 0 response = { 'survey_id': survey.id, 'user': '******', 'uuid': data['user']['uuid'], 'default_avatar': get_default_avatar_path(), 'avatar': survey.avatar_uri, 'survey': survey_json, 'prompt': { 'max_days': survey.max_survey_days, 'max_prompts': max_prompts, 'num_prompts': len(prompts_json), 'prompts': prompts_json }, 'lang': survey.language, 'about_text': survey.about_text, 'terms_of_service': survey.terms_of_service, 'survey_name': survey.pretty_name, 'record_acceleration': survey.record_acceleration, 'record_mode': survey.record_mode } return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(response)) return Error(status_code=400, headers=self.headers, resource_type=self.resource_type, errors=['Could not register new user.'])
def get(self): survey = database.survey.get(current_identity.survey_id) response = { 'language': survey.language, 'about_text': survey.about_text, 'terms_of_service': survey.terms_of_service, 'max_days': survey.max_survey_days, 'max_prompts': survey.max_prompts, 'survey': database.survey.get_survey_questions_json(survey), 'survey_id': survey.id, 'started': True if database.survey.get_start_time(survey) else False } return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(response))
def delete(self): survey = database.survey.get(current_identity.survey_id) if survey.avatar_uri: filehandler.delete(survey.avatar_uri) # reset to default avatar with current_app.app_context(): default_avatar_uri = '{base}/user/{avatar}'.format( base=current_app.config['ASSETS_ROUTE'], avatar=current_app.config['DEFAULT_AVATAR_FILENAME']) survey.avatar_uri = default_avatar_uri database.survey.update(survey) return Success(status_code=202, headers=self.headers, resource_type=self.resource_type, body={'avatarUri': default_avatar_uri})
def upload_survey_schema_json(): if not request.json.get('surveyName'): return Error(status_code=400, headers={'Location': '/manage-surveys/schema'}, resource_type='NewSurveySchema', errors=['A unique survey name must be provided.']) errors = None if request.json.get('schema'): survey_name = request.json['surveyName'] error = database.survey_admin.create_from_schema( survey_name=survey_name, admin_email=request.json['schema']['adminEmail'], admin_password=request.json['schema']['adminPassword'], language=request.json['schema']['language'], survey_questions=request.json['schema']['surveyQuestions'], survey_prompts=request.json['schema']['surveyPrompts']) if not error: # format the same as jinja2 renders the template response = { 'recent_signups': [], 'message': 'Survey "{}" created.'.format(survey_name) } for survey in database.survey_admin.get_recent_signups(10): response['recent_signups'].append({ 'name': survey.name, 'pretty_name': survey.pretty_name, 'created_at': str(survey.created_at.replace(microsecond=0)), 'active': 'True' if survey.mobile_coordinates.first() else 'False' }) return Success(status_code=201, headers={'Location': '/manage-surveys/schema'}, resource_type='NewSurveySchema', body=response) errors = [error] if not errors: errors = ['New survey schema could not be uploaded.'] return Error(status_code=400, headers={'Location': '/manage-surveys/schema'}, resource_type='NewSurveySchema', errors=errors)
def get(self): survey = database.survey.get(current_identity.survey_id) start = database.survey.get_start_time(survey) response = { 'message': 'Survey has not begun.', 'start_time': None, 'last_export': None } if start: response['message'] = 'Survey has started' response['start_time'] = start.isoformat() response['last_export'] = survey.last_export return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=make_keys_camelcase(response))
def get(self): survey = database.survey.get(current_identity.survey_id) start = request.values.get('start') end = request.values.get('end') period = request.values.get('period') get_counts_overview = request.values.get( 'countsTable').lower() == 'true' response = { 'installationsBarGraph': mobile_installations_bargraph(survey, start, end, period), 'activeUsersLineGraph': active_users_linegraph(survey) } if get_counts_overview is True: response['overview'] = survey_overview(survey) return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=response)
def generate_new_survey_token(): database.token.new_survey.create() response = { 'recent_tokens': [], 'message': 'New survey sign-up token successfully created.' } # format the same as jinja2 renders the template for token in database.token.new_survey.get_recent(10): response['recent_tokens'].append({ 'token': token.token, 'created_at': str(token.created_at.replace(microsecond=0)), 'active': str(token.active), 'usages': token.usages }) return Success(status_code=201, headers={'Location': '/signup-tokens/token'}, resource_type='NewSurveyToken', body=response)
def get(self): survey_id = current_identity.survey_id start = ciso8601.parse_datetime(request.values.get('start')) end = ciso8601.parse_datetime(request.values.get('end')) timezone = request.values.get('timezone') sse_channel = request.values.get('channel') # sse.publish({'msg': 'starting exports...', 'type': 'request-ack'}, # channel=sse_channel) mobile_data_dump.queue(survey_id, start, end, timezone, sse_channel) # mobile_data_dump(survey_id, start, end, timezone, sse_channel) response = { 'start': start.isoformat(), 'end': end.isoformat() } return Success(status_code=200, headers=self.headers, resource_type=self.resource_type, body=response)
def post(self): email = request.json.get('email') base_url = request.json.get('baseUrl') token = database.web_user.create_reset_password_token(email) if token: email_password_token.queue(current_app.config['MAILGUN_DOMAIN'], current_app.config['MAILGUN_API_KEY'], base_url, email, token.token) # email_password_token(current_app.config['MAILGUN_DOMAIN'], # current_app.config['MAILGUN_API_KEY'], # base_url, email, token.token) return Success(status_code=201, headers=self.headers, resource_type=self.resource_type, body={}) return Error(status_code=401, headers=self.headers, resource_type=self.resource_type, errors=['Email not found.'])