API - reformat python files w/ black

This commit is contained in:
Sam 2019-08-28 13:25:39 +02:00
parent d2adeed805
commit d914951c61
30 changed files with 2924 additions and 3170 deletions

View File

@ -42,8 +42,9 @@ def create_app():
if app.debug: if app.debug:
logging.getLogger('sqlalchemy').setLevel(logging.WARNING) logging.getLogger('sqlalchemy').setLevel(logging.WARNING)
logging.getLogger('sqlalchemy' logging.getLogger('sqlalchemy').handlers = logging.getLogger(
).handlers = logging.getLogger('werkzeug').handlers 'werkzeug'
).handlers
logging.getLogger('sqlalchemy.orm').setLevel(logging.WARNING) logging.getLogger('sqlalchemy.orm').setLevel(logging.WARNING)
logging.getLogger('flake8').propagate = False logging.getLogger('flake8').propagate = False
appLog.setLevel(logging.DEBUG) appLog.setLevel(logging.DEBUG)
@ -58,7 +59,7 @@ def create_app():
) )
response.headers.add( response.headers.add(
'Access-Control-Allow-Methods', 'Access-Control-Allow-Methods',
'GET,PUT,POST,DELETE,PATCH,OPTIONS' 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
) )
return response return response

View File

@ -8,16 +8,25 @@ from flask import Blueprint, current_app, jsonify, request, send_file
from sqlalchemy import exc from sqlalchemy import exc
from ..users.utils import ( from ..users.utils import (
User, authenticate, can_view_activity, verify_extension User,
authenticate,
can_view_activity,
verify_extension,
) )
from .models import Activity from .models import Activity
from .utils import ( from .utils import (
ActivityException, create_activity, edit_activity, get_absolute_file_path, ActivityException,
get_datetime_with_tz, process_files create_activity,
edit_activity,
get_absolute_file_path,
get_datetime_with_tz,
process_files,
) )
from .utils_format import convert_in_duration from .utils_format import convert_in_duration
from .utils_gpx import ( from .utils_gpx import (
ActivityGPXException, extract_segment_from_gpx_file, get_chart_data ActivityGPXException,
extract_segment_from_gpx_file,
get_chart_data,
) )
activities_blueprint = Blueprint('activities', __name__) activities_blueprint = Blueprint('activities', __name__)
@ -177,8 +186,9 @@ def get_activities(auth_user_id):
_, date_from = get_datetime_with_tz(user.timezone, date_from) _, date_from = get_datetime_with_tz(user.timezone, date_from)
date_to = params.get('to') date_to = params.get('to')
if date_to: if date_to:
date_to = datetime.strptime(f'{date_to} 23:59:59', date_to = datetime.strptime(
'%Y-%m-%d %H:%M:%S') f'{date_to} 23:59:59', '%Y-%m-%d %H:%M:%S'
)
_, date_to = get_datetime_with_tz(user.timezone, date_to) _, date_to = get_datetime_with_tz(user.timezone, date_to)
distance_from = params.get('distance_from') distance_from = params.get('distance_from')
distance_to = params.get('distance_to') distance_to = params.get('distance_to')
@ -191,46 +201,59 @@ def get_activities(auth_user_id):
order = params.get('order') order = params.get('order')
sport_id = params.get('sport_id') sport_id = params.get('sport_id')
per_page = int(params.get('per_page')) if params.get('per_page') else 5 per_page = int(params.get('per_page')) if params.get('per_page') else 5
activities = Activity.query.filter( activities = (
Activity.user_id == auth_user_id, Activity.query.filter(
Activity.sport_id == sport_id if sport_id else True, Activity.user_id == auth_user_id,
Activity.activity_date >= date_from if date_from else True, Activity.sport_id == sport_id if sport_id else True,
Activity.activity_date < date_to + timedelta(seconds=1) Activity.activity_date >= date_from if date_from else True,
if date_to else True, Activity.activity_date < date_to + timedelta(seconds=1)
Activity.distance >= int(distance_from) if distance_from else True, if date_to
Activity.distance <= int(distance_to) if distance_to else True, else True,
Activity.moving >= convert_in_duration(duration_from) Activity.distance >= int(distance_from)
if duration_from else True, if distance_from
Activity.moving <= convert_in_duration(duration_to) else True,
if duration_to else True, Activity.distance <= int(distance_to) if distance_to else True,
Activity.ave_speed >= float(ave_speed_from) Activity.moving >= convert_in_duration(duration_from)
if ave_speed_from else True, if duration_from
Activity.ave_speed <= float(ave_speed_to) else True,
if ave_speed_to else True, Activity.moving <= convert_in_duration(duration_to)
Activity.max_speed >= float(max_speed_from) if duration_to
if max_speed_from else True, else True,
Activity.max_speed <= float(max_speed_to) Activity.ave_speed >= float(ave_speed_from)
if max_speed_to else True, if ave_speed_from
).order_by( else True,
Activity.activity_date.asc() Activity.ave_speed <= float(ave_speed_to)
if order == 'asc' if ave_speed_to
else Activity.activity_date.desc() else True,
).paginate( Activity.max_speed >= float(max_speed_from)
page, per_page, False if max_speed_from
).items else True,
Activity.max_speed <= float(max_speed_to)
if max_speed_to
else True,
)
.order_by(
Activity.activity_date.asc()
if order == 'asc'
else Activity.activity_date.desc()
)
.paginate(page, per_page, False)
.items
)
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {
'activities': [activity.serialize(params) 'activities': [
for activity in activities] activity.serialize(params) for activity in activities
} ]
},
} }
code = 200 code = 200
except Exception as e: except Exception as e:
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code
@ -327,7 +350,8 @@ def get_activity(auth_user_id, activity_id):
if activity: if activity:
response_object, code = can_view_activity( response_object, code = can_view_activity(
auth_user_id, activity.user_id) auth_user_id, activity.user_id
)
if response_object: if response_object:
return jsonify(response_object), code return jsonify(response_object), code
@ -340,9 +364,7 @@ def get_activity(auth_user_id, activity_id):
response_object = { response_object = {
'status': status, 'status': status,
'data': { 'data': {'activities': activities_list},
'activities': activities_list
}
} }
return jsonify(response_object), code return jsonify(response_object), code
@ -353,13 +375,14 @@ def get_activity_data(auth_user_id, activity_id, data_type, segment_id=None):
content = '' content = ''
if activity: if activity:
response_object, code = can_view_activity( response_object, code = can_view_activity(
auth_user_id, activity.user_id) auth_user_id, activity.user_id
)
if response_object: if response_object:
return jsonify(response_object), code return jsonify(response_object), code
if not activity.gpx or activity.gpx == '': if not activity.gpx or activity.gpx == '':
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': f'No gpx file for this activity (id: {activity_id})' 'message': f'No gpx file for this activity (id: {activity_id})',
} }
return jsonify(response_object), 400 return jsonify(response_object), 400
@ -372,19 +395,16 @@ def get_activity_data(auth_user_id, activity_id, data_type, segment_id=None):
content = f.read() content = f.read()
if segment_id is not None: if segment_id is not None:
content = extract_segment_from_gpx_file( content = extract_segment_from_gpx_file(
content, content, segment_id
segment_id
) )
except ActivityGPXException as e: except ActivityGPXException as e:
appLog.error(e.message) appLog.error(e.message)
response_object = {'status': e.status, response_object = {'status': e.status, 'message': e.message}
'message': e.message}
code = 404 if e.status == 'not found' else 500 code = 404 if e.status == 'not found' else 500
return jsonify(response_object), code return jsonify(response_object), code
except Exception as e: except Exception as e:
appLog.error(e) appLog.error(e)
response_object = {'status': 'error', response_object = {'status': 'error', 'message': 'internal error'}
'message': 'internal error'}
return jsonify(response_object), 500 return jsonify(response_object), 500
status = 'success' status = 'success'
@ -395,11 +415,15 @@ def get_activity_data(auth_user_id, activity_id, data_type, segment_id=None):
message = f'Activity not found (id: {activity_id})' message = f'Activity not found (id: {activity_id})'
code = 404 code = 404
response_object = {'status': status, response_object = {
'message': message, 'status': status,
'data': ({'chart_data': content} 'message': message,
if data_type == 'chart' 'data': (
else {'gpx': content})} {'chart_data': content}
if data_type == 'chart'
else {'gpx': content}
),
}
return jsonify(response_object), code return jsonify(response_object), code
@ -520,7 +544,7 @@ def get_activity_chart_data(auth_user_id, activity_id):
@activities_blueprint.route( @activities_blueprint.route(
'/activities/<int:activity_id>/gpx/segment/<int:segment_id>', '/activities/<int:activity_id>/gpx/segment/<int:segment_id>',
methods=['GET'] methods=['GET'],
) )
@authenticate @authenticate
def get_segment_gpx(auth_user_id, activity_id, segment_id): def get_segment_gpx(auth_user_id, activity_id, segment_id):
@ -570,7 +594,7 @@ def get_segment_gpx(auth_user_id, activity_id, segment_id):
@activities_blueprint.route( @activities_blueprint.route(
'/activities/<int:activity_id>/chart_data/segment/<int:segment_id>', '/activities/<int:activity_id>/chart_data/segment/<int:segment_id>',
methods=['GET'] methods=['GET'],
) )
@authenticate @authenticate
def get_segment_chart_data(auth_user_id, activity_id, segment_id): def get_segment_chart_data(auth_user_id, activity_id, segment_id):
@ -673,7 +697,7 @@ def get_map(map_id):
if not activity: if not activity:
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'Map does not exist' 'message': 'Map does not exist',
} }
return jsonify(response_object), 404 return jsonify(response_object), 404
else: else:
@ -681,10 +705,7 @@ def get_map(map_id):
return send_file(absolute_map_filepath) return send_file(absolute_map_filepath)
except Exception as e: except Exception as e:
appLog.error(e) appLog.error(e)
response_object = { response_object = {'status': 'error', 'message': 'internal error.'}
'status': 'error',
'message': 'internal error.'
}
return jsonify(response_object), 500 return jsonify(response_object), 500
@ -808,17 +829,13 @@ def post_activity(auth_user_id):
activity_data = json.loads(request.form["data"]) activity_data = json.loads(request.form["data"])
if not activity_data or activity_data.get('sport_id') is None: if not activity_data or activity_data.get('sport_id') is None:
response_object = { response_object = {'status': 'error', 'message': 'Invalid payload.'}
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400 return jsonify(response_object), 400
activity_file = request.files['file'] activity_file = request.files['file']
upload_dir = os.path.join( upload_dir = os.path.join(
current_app.config['UPLOAD_FOLDER'], current_app.config['UPLOAD_FOLDER'], 'activities', str(auth_user_id)
'activities', )
str(auth_user_id))
folders = { folders = {
'extract_dir': os.path.join(upload_dir, 'extract'), 'extract_dir': os.path.join(upload_dir, 'extract'),
'tmp_dir': os.path.join(upload_dir, 'tmp'), 'tmp_dir': os.path.join(upload_dir, 'tmp'),
@ -832,27 +849,21 @@ def post_activity(auth_user_id):
response_object = { response_object = {
'status': 'created', 'status': 'created',
'data': { 'data': {
'activities': [new_activity.serialize() 'activities': [
for new_activity in new_activities] new_activity.serialize()
} for new_activity in new_activities
]
},
} }
code = 201 code = 201
else: else:
response_object = { response_object = {'status': 'fail', 'data': {'activities': []}}
'status': 'fail',
'data': {
'activities': []
}
}
code = 400 code = 400
except ActivityException as e: except ActivityException as e:
db.session.rollback() db.session.rollback()
if e.e: if e.e:
appLog.error(e.e) appLog.error(e.e)
response_object = { response_object = {'status': e.status, 'message': e.message}
'status': e.status,
'message': e.message,
}
code = 500 if e.status == 'error' else 400 code = 500 if e.status == 'error' else 400
shutil.rmtree(folders['extract_dir'], ignore_errors=True) shutil.rmtree(folders['extract_dir'], ignore_errors=True)
@ -975,14 +986,14 @@ def post_activity_no_gpx(auth_user_id):
""" """
activity_data = request.get_json() activity_data = request.get_json()
if not activity_data or activity_data.get('sport_id') is None \ if (
or activity_data.get('duration') is None \ not activity_data
or activity_data.get('distance') is None \ or activity_data.get('sport_id') is None
or activity_data.get('activity_date') is None: or activity_data.get('duration') is None
response_object = { or activity_data.get('distance') is None
'status': 'error', or activity_data.get('activity_date') is None
'message': 'Invalid payload.' ):
} response_object = {'status': 'error', 'message': 'Invalid payload.'}
return jsonify(response_object), 400 return jsonify(response_object), 400
try: try:
@ -993,9 +1004,7 @@ def post_activity_no_gpx(auth_user_id):
response_object = { response_object = {
'status': 'created', 'status': 'created',
'data': { 'data': {'activities': [new_activity.serialize()]},
'activities': [new_activity.serialize()]
}
} }
return jsonify(response_object), 201 return jsonify(response_object), 201
@ -1004,7 +1013,7 @@ def post_activity_no_gpx(auth_user_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'Error during activity save.' 'message': 'Error during activity save.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
@ -1130,17 +1139,15 @@ def update_activity(auth_user_id, activity_id):
""" """
activity_data = request.get_json() activity_data = request.get_json()
if not activity_data: if not activity_data:
response_object = { response_object = {'status': 'error', 'message': 'Invalid payload.'}
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400 return jsonify(response_object), 400
try: try:
activity = Activity.query.filter_by(id=activity_id).first() activity = Activity.query.filter_by(id=activity_id).first()
if activity: if activity:
response_object, code = can_view_activity( response_object, code = can_view_activity(
auth_user_id, activity.user_id) auth_user_id, activity.user_id
)
if response_object: if response_object:
return jsonify(response_object), code return jsonify(response_object), code
@ -1148,17 +1155,13 @@ def update_activity(auth_user_id, activity_id):
db.session.commit() db.session.commit()
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'activities': [activity.serialize()]},
'activities': [activity.serialize()]
}
} }
code = 200 code = 200
else: else:
response_object = { response_object = {
'status': 'not found', 'status': 'not found',
'data': { 'data': {'activities': []},
'activities': []
}
} }
code = 404 code = 404
except (exc.IntegrityError, exc.OperationalError, ValueError) as e: except (exc.IntegrityError, exc.OperationalError, ValueError) as e:
@ -1166,7 +1169,7 @@ def update_activity(auth_user_id, activity_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code
@ -1213,31 +1216,32 @@ def delete_activity(auth_user_id, activity_id):
activity = Activity.query.filter_by(id=activity_id).first() activity = Activity.query.filter_by(id=activity_id).first()
if activity: if activity:
response_object, code = can_view_activity( response_object, code = can_view_activity(
auth_user_id, activity.user_id) auth_user_id, activity.user_id
)
if response_object: if response_object:
return jsonify(response_object), code return jsonify(response_object), code
db.session.delete(activity) db.session.delete(activity)
db.session.commit() db.session.commit()
response_object = { response_object = {'status': 'no content'}
'status': 'no content'
}
code = 204 code = 204
else: else:
response_object = { response_object = {
'status': 'not found', 'status': 'not found',
'data': { 'data': {'activities': []},
'activities': []
}
} }
code = 404 code = 404
except (exc.IntegrityError, exc.OperationalError, ValueError, OSError) \ except (
as e: exc.IntegrityError,
exc.OperationalError,
ValueError,
OSError,
) as e:
db.session.rollback() db.session.rollback()
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code

View File

@ -21,42 +21,38 @@ record_types = [
def update_records(user_id, sport_id, connection, session): def update_records(user_id, sport_id, connection, session):
record_table = Record.__table__ record_table = Record.__table__
new_records = Activity.get_user_activity_records( new_records = Activity.get_user_activity_records(user_id, sport_id)
user_id,
sport_id)
for record_type, record_data in new_records.items(): for record_type, record_data in new_records.items():
if record_data['record_value']: if record_data['record_value']:
record = Record.query.filter_by( record = Record.query.filter_by(
user_id=user_id, user_id=user_id, sport_id=sport_id, record_type=record_type
sport_id=sport_id,
record_type=record_type,
).first() ).first()
if record: if record:
value = convert_value_to_integer( value = convert_value_to_integer(
record_type, record_data['record_value'] record_type, record_data['record_value']
) )
connection.execute(record_table.update().where( connection.execute(
record_table.c.id == record.id, record_table.update()
).values( .where(record_table.c.id == record.id)
value=value, .values(
activity_id=record_data['activity'].id, value=value,
activity_date=record_data['activity'].activity_date, activity_id=record_data['activity'].id,
)) activity_date=record_data['activity'].activity_date,
)
)
else: else:
new_record = Record( new_record = Record(
activity=record_data['activity'], activity=record_data['activity'], record_type=record_type
record_type=record_type
) )
new_record.value = record_data['record_value'] new_record.value = record_data['record_value']
session.add(new_record) session.add(new_record)
else: else:
connection.execute(record_table.delete().where( connection.execute(
record_table.c.user_id == user_id, record_table.delete()
).where( .where(record_table.c.user_id == user_id)
record_table.c.sport_id == sport_id, .where(record_table.c.sport_id == sport_id)
).where( .where(record_table.c.record_type == record_type)
record_table.c.record_type == record_type, )
))
class Sport(db.Model): class Sport(db.Model):
@ -65,12 +61,12 @@ class Sport(db.Model):
label = db.Column(db.String(50), unique=True, nullable=False) label = db.Column(db.String(50), unique=True, nullable=False)
img = db.Column(db.String(255), unique=True, nullable=True) img = db.Column(db.String(255), unique=True, nullable=True)
is_default = db.Column(db.Boolean, default=False, nullable=False) is_default = db.Column(db.Boolean, default=False, nullable=False)
activities = db.relationship('Activity', activities = db.relationship(
lazy=True, 'Activity', lazy=True, backref=db.backref('sports', lazy='joined')
backref=db.backref('sports', lazy='joined')) )
records = db.relationship('Record', records = db.relationship(
lazy=True, 'Record', lazy=True, backref=db.backref('sports', lazy='joined')
backref=db.backref('sports', lazy='joined')) )
def __repr__(self): def __repr__(self):
return f'<Sport {self.label!r}>' return f'<Sport {self.label!r}>'
@ -83,62 +79,53 @@ class Sport(db.Model):
'id': self.id, 'id': self.id,
'label': self.label, 'label': self.label,
'img': self.img, 'img': self.img,
'_can_be_deleted': '_can_be_deleted': len(self.activities) == 0
len(self.activities) == 0 and not self.is_default and not self.is_default,
} }
class Activity(db.Model): class Activity(db.Model):
__tablename__ = "activities" __tablename__ = "activities"
id = db.Column( id = db.Column(db.Integer, primary_key=True, autoincrement=True)
db.Integer, user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
primary_key=True,
autoincrement=True)
user_id = db.Column(
db.Integer,
db.ForeignKey('users.id'),
nullable=False)
sport_id = db.Column( sport_id = db.Column(
db.Integer, db.Integer, db.ForeignKey('sports.id'), nullable=False
db.ForeignKey('sports.id'), )
nullable=False)
title = db.Column(db.String(255), nullable=True) title = db.Column(db.String(255), nullable=True)
gpx = db.Column(db.String(255), nullable=True) gpx = db.Column(db.String(255), nullable=True)
creation_date = db.Column( creation_date = db.Column(db.DateTime, default=datetime.datetime.utcnow)
db.DateTime, default=datetime.datetime.utcnow)
modification_date = db.Column( modification_date = db.Column(
db.DateTime, onupdate=datetime.datetime.utcnow) db.DateTime, onupdate=datetime.datetime.utcnow
)
activity_date = db.Column(db.DateTime, nullable=False) activity_date = db.Column(db.DateTime, nullable=False)
duration = db.Column(db.Interval, nullable=False) duration = db.Column(db.Interval, nullable=False)
pauses = db.Column(db.Interval, nullable=True) pauses = db.Column(db.Interval, nullable=True)
moving = db.Column(db.Interval, nullable=True) moving = db.Column(db.Interval, nullable=True)
distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers
min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
descent = db.Column(db.Numeric(7, 2), nullable=True) # meters descent = db.Column(db.Numeric(7, 2), nullable=True) # meters
ascent = db.Column(db.Numeric(7, 2), nullable=True) # meters ascent = db.Column(db.Numeric(7, 2), nullable=True) # meters
max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
bounds = db.Column(postgresql.ARRAY(db.Float), nullable=True) bounds = db.Column(postgresql.ARRAY(db.Float), nullable=True)
map = db.Column(db.String(255), nullable=True) map = db.Column(db.String(255), nullable=True)
map_id = db.Column(db.String(50), nullable=True) map_id = db.Column(db.String(50), nullable=True)
weather_start = db.Column(JSON, nullable=True) weather_start = db.Column(JSON, nullable=True)
weather_end = db.Column(JSON, nullable=True) weather_end = db.Column(JSON, nullable=True)
notes = db.Column(db.String(500), nullable=True) notes = db.Column(db.String(500), nullable=True)
segments = db.relationship('ActivitySegment', segments = db.relationship(
lazy=True, 'ActivitySegment',
cascade='all, delete', lazy=True,
backref=db.backref( cascade='all, delete',
'activities', backref=db.backref('activities', lazy='joined', single_parent=True),
lazy='joined', )
single_parent=True)) records = db.relationship(
records = db.relationship('Record', 'Record',
lazy=True, lazy=True,
cascade='all, delete', cascade='all, delete',
backref=db.backref( backref=db.backref('activities', lazy='joined', single_parent=True),
'activities', )
lazy='joined',
single_parent=True))
def __str__(self): def __str__(self):
return f'<Activity \'{self.sports.label}\' - {self.activity_date}>' return f'<Activity \'{self.sports.label}\' - {self.activity_date}>'
@ -162,58 +149,80 @@ class Activity(db.Model):
max_speed_from = params.get('max_speed_from') if params else None max_speed_from = params.get('max_speed_from') if params else None
max_speed_to = params.get('max_speed_to') if params else None max_speed_to = params.get('max_speed_to') if params else None
sport_id = params.get('sport_id') if params else None sport_id = params.get('sport_id') if params else None
previous_activity = Activity.query.filter( previous_activity = (
Activity.id != self.id, Activity.query.filter(
Activity.user_id == self.user_id, Activity.id != self.id,
Activity.sport_id == sport_id if sport_id else True, Activity.user_id == self.user_id,
Activity.activity_date <= self.activity_date, Activity.sport_id == sport_id if sport_id else True,
Activity.activity_date >= datetime.datetime.strptime( Activity.activity_date <= self.activity_date,
date_from, '%Y-%m-%d' Activity.activity_date
) if date_from else True, >= datetime.datetime.strptime(date_from, '%Y-%m-%d')
Activity.activity_date <= datetime.datetime.strptime( if date_from
date_to, '%Y-%m-%d' else True,
) if date_to else True, Activity.activity_date
Activity.distance >= int(distance_from) if distance_from else True, <= datetime.datetime.strptime(date_to, '%Y-%m-%d')
Activity.distance <= int(distance_to) if distance_to else True, if date_to
Activity.duration >= convert_in_duration(duration_from) else True,
if duration_from else True, Activity.distance >= int(distance_from)
Activity.duration <= convert_in_duration(duration_to) if distance_from
if duration_to else True, else True,
Activity.ave_speed >= float(ave_speed_from) Activity.distance <= int(distance_to) if distance_to else True,
if ave_speed_from else True, Activity.duration >= convert_in_duration(duration_from)
Activity.ave_speed <= float(ave_speed_to) if duration_from
if ave_speed_to else True, else True,
Activity.max_speed >= float(max_speed_from) Activity.duration <= convert_in_duration(duration_to)
if max_speed_from else True, if duration_to
Activity.max_speed <= float(max_speed_to) else True,
if max_speed_to else True, Activity.ave_speed >= float(ave_speed_from)
).order_by( if ave_speed_from
Activity.activity_date.desc() else True,
).first() Activity.ave_speed <= float(ave_speed_to)
next_activity = Activity.query.filter( if ave_speed_to
Activity.id != self.id, else True,
Activity.user_id == self.user_id, Activity.max_speed >= float(max_speed_from)
Activity.sport_id == sport_id if sport_id else True, if max_speed_from
Activity.activity_date >= self.activity_date, else True,
Activity.activity_date >= datetime.datetime.strptime( Activity.max_speed <= float(max_speed_to)
date_from, '%Y-%m-%d' if max_speed_to
) if date_from else True, else True,
Activity.activity_date <= datetime.datetime.strptime( )
date_to, '%Y-%m-%d' .order_by(Activity.activity_date.desc())
) if date_to else True, .first()
Activity.distance >= int(distance_from) if distance_from else True, )
Activity.distance <= int(distance_to) if distance_to else True, next_activity = (
Activity.duration >= convert_in_duration(duration_from) Activity.query.filter(
if duration_from else True, Activity.id != self.id,
Activity.duration <= convert_in_duration(duration_to) Activity.user_id == self.user_id,
if duration_to else True, Activity.sport_id == sport_id if sport_id else True,
Activity.ave_speed >= float(ave_speed_from) Activity.activity_date >= self.activity_date,
if ave_speed_from else True, Activity.activity_date
Activity.ave_speed <= float(ave_speed_to) >= datetime.datetime.strptime(date_from, '%Y-%m-%d')
if ave_speed_to else True, if date_from
).order_by( else True,
Activity.activity_date.asc() Activity.activity_date
).first() <= datetime.datetime.strptime(date_to, '%Y-%m-%d')
if date_to
else True,
Activity.distance >= int(distance_from)
if distance_from
else True,
Activity.distance <= int(distance_to) if distance_to else True,
Activity.duration >= convert_in_duration(duration_from)
if duration_from
else True,
Activity.duration <= convert_in_duration(duration_to)
if duration_to
else True,
Activity.ave_speed >= float(ave_speed_from)
if ave_speed_from
else True,
Activity.ave_speed <= float(ave_speed_to)
if ave_speed_to
else True,
)
.order_by(Activity.activity_date.asc())
.first()
)
return { return {
"id": self.id, "id": self.id,
"user_id": self.user_id, "user_id": self.user_id,
@ -233,59 +242,67 @@ class Activity(db.Model):
"max_speed": float(self.max_speed) if self.max_speed else None, "max_speed": float(self.max_speed) if self.max_speed else None,
"ave_speed": float(self.ave_speed) if self.ave_speed else None, "ave_speed": float(self.ave_speed) if self.ave_speed else None,
"with_gpx": self.gpx is not None, "with_gpx": self.gpx is not None,
"bounds": [float(bound) for bound in self.bounds] if self.bounds else [], # noqa "bounds": [float(bound) for bound in self.bounds]
"previous_activity": previous_activity.id if previous_activity else None, # noqa if self.bounds
else [], # noqa
"previous_activity": previous_activity.id
if previous_activity
else None, # noqa
"next_activity": next_activity.id if next_activity else None, "next_activity": next_activity.id if next_activity else None,
"segments": [segment.serialize() for segment in self.segments], "segments": [segment.serialize() for segment in self.segments],
"records": [record.serialize() for record in self.records], "records": [record.serialize() for record in self.records],
"map": self.map_id if self.map else None, "map": self.map_id if self.map else None,
"weather_start": self.weather_start, "weather_start": self.weather_start,
"weather_end": self.weather_end, "weather_end": self.weather_end,
"notes": self.notes "notes": self.notes,
} }
@classmethod @classmethod
def get_user_activity_records(cls, user_id, sport_id, as_integer=False): def get_user_activity_records(cls, user_id, sport_id, as_integer=False):
record_types_columns = { record_types_columns = {
'AS': 'ave_speed', # 'Average speed' 'AS': 'ave_speed', # 'Average speed'
'FD': 'distance', # 'Farthest Distance' 'FD': 'distance', # 'Farthest Distance'
'LD': 'moving', # 'Longest Duration' 'LD': 'moving', # 'Longest Duration'
'MS': 'max_speed', # 'Max speed' 'MS': 'max_speed', # 'Max speed'
} }
records = {} records = {}
for record_type, column in record_types_columns.items(): for record_type, column in record_types_columns.items():
column_sorted = getattr(getattr(Activity, column), 'desc')() column_sorted = getattr(getattr(Activity, column), 'desc')()
record_activity = Activity.query.filter_by( record_activity = (
user_id=user_id, Activity.query.filter_by(user_id=user_id, sport_id=sport_id)
sport_id=sport_id, .order_by(column_sorted, Activity.activity_date)
).order_by( .first()
column_sorted, )
Activity.activity_date,
).first()
records[record_type] = dict( records[record_type] = dict(
record_value=(getattr(record_activity, column) record_value=(
if record_activity else None), getattr(record_activity, column)
activity=record_activity) if record_activity
else None
),
activity=record_activity,
)
return records return records
@listens_for(Activity, 'after_insert') @listens_for(Activity, 'after_insert')
def on_activity_insert(mapper, connection, activity): def on_activity_insert(mapper, connection, activity):
@listens_for(db.Session, 'after_flush', once=True) @listens_for(db.Session, 'after_flush', once=True)
def receive_after_flush(session, context): def receive_after_flush(session, context):
update_records(activity.user_id, activity.sport_id, connection, session) # noqa update_records(
activity.user_id, activity.sport_id, connection, session
) # noqa
@listens_for(Activity, 'after_update') @listens_for(Activity, 'after_update')
def on_activity_update(mapper, connection, activity): def on_activity_update(mapper, connection, activity):
if object_session(activity).is_modified(activity, include_collections=True): # noqa if object_session(activity).is_modified(
activity, include_collections=True
): # noqa
@listens_for(db.Session, 'after_flush', once=True) @listens_for(db.Session, 'after_flush', once=True)
def receive_after_flush(session, context): def receive_after_flush(session, context):
sports_list = [activity.sport_id] sports_list = [activity.sport_id]
records = Record.query.filter_by( records = Record.query.filter_by(activity_id=activity.id).all()
activity_id=activity.id,
).all()
for rec in records: for rec in records:
if rec.sport_id not in sports_list: if rec.sport_id not in sports_list:
sports_list.append(rec.sport_id) sports_list.append(rec.sport_id)
@ -295,7 +312,6 @@ def on_activity_update(mapper, connection, activity):
@listens_for(Activity, 'after_delete') @listens_for(Activity, 'after_delete')
def on_activity_delete(mapper, connection, old_record): def on_activity_delete(mapper, connection, old_record):
@listens_for(db.Session, 'after_flush', once=True) @listens_for(db.Session, 'after_flush', once=True)
def receive_after_flush(session, context): def receive_after_flush(session, context):
if old_record.map: if old_record.map:
@ -307,26 +323,25 @@ def on_activity_delete(mapper, connection, old_record):
class ActivitySegment(db.Model): class ActivitySegment(db.Model):
__tablename__ = "activity_segments" __tablename__ = "activity_segments"
activity_id = db.Column( activity_id = db.Column(
db.Integer, db.Integer, db.ForeignKey('activities.id'), primary_key=True
db.ForeignKey('activities.id'), )
primary_key=True) segment_id = db.Column(db.Integer, primary_key=True)
segment_id = db.Column(
db.Integer,
primary_key=True)
duration = db.Column(db.Interval, nullable=False) duration = db.Column(db.Interval, nullable=False)
pauses = db.Column(db.Interval, nullable=True) pauses = db.Column(db.Interval, nullable=True)
moving = db.Column(db.Interval, nullable=True) moving = db.Column(db.Interval, nullable=True)
distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers
min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
descent = db.Column(db.Numeric(7, 2), nullable=True) # meters descent = db.Column(db.Numeric(7, 2), nullable=True) # meters
ascent = db.Column(db.Numeric(7, 2), nullable=True) # meters ascent = db.Column(db.Numeric(7, 2), nullable=True) # meters
max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
def __str__(self): def __str__(self):
return (f'<Segment \'{self.segment_id}\' ' return (
f'for activity \'{self.activity_id}\'>') f'<Segment \'{self.segment_id}\' '
f'for activity \'{self.activity_id}\'>'
)
def __init__(self, segment_id, activity_id): def __init__(self, segment_id, activity_id):
self.segment_id = segment_id self.segment_id = segment_id
@ -345,38 +360,35 @@ class ActivitySegment(db.Model):
"descent": float(self.descent) if self.descent else None, "descent": float(self.descent) if self.descent else None,
"ascent": float(self.ascent) if self.ascent else None, "ascent": float(self.ascent) if self.ascent else None,
"max_speed": float(self.max_speed) if self.max_speed else None, "max_speed": float(self.max_speed) if self.max_speed else None,
"ave_speed": float(self.ave_speed) if self.ave_speed else None "ave_speed": float(self.ave_speed) if self.ave_speed else None,
} }
class Record(db.Model): class Record(db.Model):
__tablename__ = "records" __tablename__ = "records"
__table_args__ = (db.UniqueConstraint( __table_args__ = (
'user_id', 'sport_id', 'record_type', name='user_sports_records'),) db.UniqueConstraint(
id = db.Column( 'user_id', 'sport_id', 'record_type', name='user_sports_records'
db.Integer, ),
primary_key=True, )
autoincrement=True) id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column( user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
db.Integer,
db.ForeignKey('users.id'),
nullable=False)
sport_id = db.Column( sport_id = db.Column(
db.Integer, db.Integer, db.ForeignKey('sports.id'), nullable=False
db.ForeignKey('sports.id'), )
nullable=False)
activity_id = db.Column( activity_id = db.Column(
db.Integer, db.Integer, db.ForeignKey('activities.id'), nullable=False
db.ForeignKey('activities.id'), )
nullable=False)
record_type = db.Column(Enum(*record_types, name="record_types")) record_type = db.Column(Enum(*record_types, name="record_types"))
activity_date = db.Column(db.DateTime, nullable=False) activity_date = db.Column(db.DateTime, nullable=False)
_value = db.Column("value", db.Integer, nullable=True) _value = db.Column("value", db.Integer, nullable=True)
def __str__(self): def __str__(self):
return (f'<Record {self.sports.label} - ' return (
f'{self.record_type} - ' f'<Record {self.sports.label} - '
f"{self.activity_date.strftime('%Y-%m-%d')}>") f'{self.record_type} - '
f"{self.activity_date.strftime('%Y-%m-%d')}>"
)
def __init__(self, activity, record_type): def __init__(self, activity, record_type):
self.user_id = activity.user_id self.user_id = activity.user_id
@ -421,19 +433,19 @@ class Record(db.Model):
@listens_for(Record, 'after_delete') @listens_for(Record, 'after_delete')
def on_record_delete(mapper, connection, old_record): def on_record_delete(mapper, connection, old_record):
@listens_for(db.Session, 'after_flush', once=True) @listens_for(db.Session, 'after_flush', once=True)
def receive_after_flush(session, context): def receive_after_flush(session, context):
activity = old_record.activities activity = old_record.activities
new_records = Activity.get_user_activity_records( new_records = Activity.get_user_activity_records(
activity.user_id, activity.user_id, activity.sport_id
activity.sport_id) )
for record_type, record_data in new_records.items(): for record_type, record_data in new_records.items():
if record_data['record_value'] \ if (
and record_type == old_record.record_type: record_data['record_value']
and record_type == old_record.record_type
):
new_record = Record( new_record = Record(
activity=record_data['activity'], activity=record_data['activity'], record_type=record_type
record_type=record_type
) )
new_record.value = record_data['record_value'] new_record.value = record_data['record_value']
session.add(new_record) session.add(new_record)

View File

@ -104,15 +104,13 @@ def get_records(auth_user_id):
""" """
records = Record.query.filter_by(user_id=auth_user_id)\ records = (
.order_by( Record.query.filter_by(user_id=auth_user_id)
Record.sport_id.asc(), .order_by(Record.sport_id.asc(), Record.record_type.asc())
Record.record_type.asc(), .all()
).all() )
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'records': [record.serialize() for record in records]},
'records': [record.serialize() for record in records]
}
} }
return jsonify(response_object), 200 return jsonify(response_object), 200

View File

@ -87,9 +87,7 @@ def get_sports(auth_user_id):
sports = Sport.query.order_by(Sport.id).all() sports = Sport.query.order_by(Sport.id).all()
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'sports': [sport.serialize() for sport in sports]},
'sports': [sport.serialize() for sport in sports]
}
} }
return jsonify(response_object), 200 return jsonify(response_object), 200
@ -161,34 +159,25 @@ def get_sport(auth_user_id, sport_id):
if sport: if sport:
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'sports': [sport.serialize()]},
'sports': [sport.serialize()]
}
} }
code = 200 code = 200
else: else:
response_object = { response_object = {'status': 'not found', 'data': {'sports': []}}
'status': 'not found',
'data': {
'sports': []
}
}
code = 404 code = 404
return jsonify(response_object), code return jsonify(response_object), code
# no administration - no documentation for now # no administration - no documentation for now
@sports_blueprint.route('/sports', methods=['POST']) @sports_blueprint.route('/sports', methods=['POST'])
@authenticate_as_admin @authenticate_as_admin
def post_sport(auth_user_id): def post_sport(auth_user_id):
"""Post a sport""" """Post a sport"""
sport_data = request.get_json() sport_data = request.get_json()
if not sport_data or sport_data.get('label') is None: if not sport_data or sport_data.get('label') is None:
response_object = { response_object = {'status': 'error', 'message': 'Invalid payload.'}
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400 return jsonify(response_object), 400
try: try:
@ -197,9 +186,7 @@ def post_sport(auth_user_id):
db.session.commit() db.session.commit()
response_object = { response_object = {
'status': 'created', 'status': 'created',
'data': { 'data': {'sports': [new_sport.serialize()]},
'sports': [new_sport.serialize()]
}
} }
code = 201 code = 201
except (exc.IntegrityError, exc.OperationalError, ValueError) as e: except (exc.IntegrityError, exc.OperationalError, ValueError) as e:
@ -207,7 +194,7 @@ def post_sport(auth_user_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code
@ -219,10 +206,7 @@ def update_sport(auth_user_id, sport_id):
"""Update a sport""" """Update a sport"""
sport_data = request.get_json() sport_data = request.get_json()
if not sport_data or sport_data.get('label') is None: if not sport_data or sport_data.get('label') is None:
response_object = { response_object = {'status': 'error', 'message': 'Invalid payload.'}
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400 return jsonify(response_object), 400
sports_list = [] sports_list = []
@ -231,23 +215,16 @@ def update_sport(auth_user_id, sport_id):
if sport: if sport:
sport.label = sport_data.get('label') sport.label = sport_data.get('label')
db.session.commit() db.session.commit()
sports_list.append({ sports_list.append({'id': sport.id, 'label': sport.label})
'id': sport.id,
'label': sport.label
})
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'sports': sports_list},
'sports': sports_list
}
} }
code = 200 code = 200
else: else:
response_object = { response_object = {
'status': 'not found', 'status': 'not found',
'data': { 'data': {'sports': sports_list},
'sports': sports_list
}
} }
code = 404 code = 404
except (exc.IntegrityError, exc.OperationalError, ValueError) as e: except (exc.IntegrityError, exc.OperationalError, ValueError) as e:
@ -255,7 +232,7 @@ def update_sport(auth_user_id, sport_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code
@ -270,24 +247,17 @@ def delete_sport(auth_user_id, sport_id):
if sport: if sport:
db.session.delete(sport) db.session.delete(sport)
db.session.commit() db.session.commit()
response_object = { response_object = {'status': 'no content'}
'status': 'no content'
}
code = 204 code = 204
else: else:
response_object = { response_object = {'status': 'not found', 'data': {'sports': []}}
'status': 'not found',
'data': {
'sports': []
}
}
code = 404 code = 404
except exc.IntegrityError as e: except exc.IntegrityError as e:
db.session.rollback() db.session.rollback()
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Associated activities exist.' 'message': 'Error. Associated activities exist.',
} }
code = 500 code = 500
except (exc.OperationalError, ValueError) as e: except (exc.OperationalError, ValueError) as e:
@ -295,7 +265,7 @@ def delete_sport(auth_user_id, sport_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code

View File

@ -18,7 +18,7 @@ def get_activities(user_id, filter_type):
if not user: if not user:
response_object = { response_object = {
'status': 'not found', 'status': 'not found',
'message': 'User does not exist.' 'message': 'User does not exist.',
} }
return jsonify(response_object), 404 return jsonify(response_object), 404
@ -29,8 +29,9 @@ def get_activities(user_id, filter_type):
_, date_from = get_datetime_with_tz(user.timezone, date_from) _, date_from = get_datetime_with_tz(user.timezone, date_from)
date_to = params.get('to') date_to = params.get('to')
if date_to: if date_to:
date_to = datetime.strptime(f'{date_to} 23:59:59', date_to = datetime.strptime(
'%Y-%m-%d %H:%M:%S') f'{date_to} 23:59:59', '%Y-%m-%d %H:%M:%S'
)
_, date_to = get_datetime_with_tz(user.timezone, date_to) _, date_to = get_datetime_with_tz(user.timezone, date_to)
sport_id = params.get('sport_id') sport_id = params.get('sport_id')
time = params.get('time') time = params.get('time')
@ -42,19 +43,22 @@ def get_activities(user_id, filter_type):
if not sport: if not sport:
response_object = { response_object = {
'status': 'not found', 'status': 'not found',
'message': 'Sport does not exist.' 'message': 'Sport does not exist.',
} }
return jsonify(response_object), 404 return jsonify(response_object), 404
activities = Activity.query.filter( activities = (
Activity.user_id == user_id, Activity.query.filter(
Activity.activity_date >= date_from if date_from else True, Activity.user_id == user_id,
Activity.activity_date < date_to + timedelta(seconds=1) Activity.activity_date >= date_from if date_from else True,
if date_to else True, Activity.activity_date < date_to + timedelta(seconds=1)
Activity.sport_id == sport_id if sport_id else True, if date_to
).order_by( else True,
Activity.activity_date.asc() Activity.sport_id == sport_id if sport_id else True,
).all() )
.order_by(Activity.activity_date.asc())
.all()
)
activities_list = {} activities_list = {}
for activity in activities: for activity in activities:
@ -63,21 +67,25 @@ def get_activities(user_id, filter_type):
if sport_id not in activities_list: if sport_id not in activities_list:
activities_list[sport_id] = { activities_list[sport_id] = {
'nb_activities': 0, 'nb_activities': 0,
'total_distance': 0., 'total_distance': 0.0,
'total_duration': 0, 'total_duration': 0,
} }
activities_list[sport_id]['nb_activities'] += 1 activities_list[sport_id]['nb_activities'] += 1
activities_list[sport_id]['total_distance'] += \ activities_list[sport_id]['total_distance'] += float(
float(activity.distance) activity.distance
activities_list[sport_id]['total_duration'] += \ )
convert_timedelta_to_integer(activity.moving) activities_list[sport_id][
'total_duration'
] += convert_timedelta_to_integer(activity.moving)
else: else:
if time == 'week': if time == 'week':
activity_date = activity.activity_date - timedelta( activity_date = activity.activity_date - timedelta(
days=(activity.activity_date.isoweekday() days=(
if activity.activity_date.isoweekday() < 7 activity.activity_date.isoweekday()
else 0) if activity.activity_date.isoweekday() < 7
else 0
)
) )
time_period = datetime.strftime(activity_date, "%Y-%m-%d") time_period = datetime.strftime(activity_date, "%Y-%m-%d")
elif time == 'weekm': # week start Monday elif time == 'weekm': # week start Monday
@ -86,13 +94,17 @@ def get_activities(user_id, filter_type):
) )
time_period = datetime.strftime(activity_date, "%Y-%m-%d") time_period = datetime.strftime(activity_date, "%Y-%m-%d")
elif time == 'month': elif time == 'month':
time_period = datetime.strftime(activity.activity_date, "%Y-%m") # noqa time_period = datetime.strftime(
activity.activity_date, "%Y-%m"
) # noqa
elif time == 'year' or not time: elif time == 'year' or not time:
time_period = datetime.strftime(activity.activity_date, "%Y") # noqa time_period = datetime.strftime(
activity.activity_date, "%Y"
) # noqa
else: else:
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'Invalid time period.' 'message': 'Invalid time period.',
} }
return jsonify(response_object), 400 return jsonify(response_object), 400
sport_id = activity.sport_id sport_id = activity.sport_id
@ -101,27 +113,27 @@ def get_activities(user_id, filter_type):
if sport_id not in activities_list[time_period]: if sport_id not in activities_list[time_period]:
activities_list[time_period][sport_id] = { activities_list[time_period][sport_id] = {
'nb_activities': 0, 'nb_activities': 0,
'total_distance': 0., 'total_distance': 0.0,
'total_duration': 0, 'total_duration': 0,
} }
activities_list[time_period][sport_id]['nb_activities'] += 1 activities_list[time_period][sport_id]['nb_activities'] += 1
activities_list[time_period][sport_id]['total_distance'] += \ activities_list[time_period][sport_id][
float(activity.distance) 'total_distance'
activities_list[time_period][sport_id]['total_duration'] += \ ] += float(activity.distance)
convert_timedelta_to_integer(activity.moving) activities_list[time_period][sport_id][
'total_duration'
] += convert_timedelta_to_integer(activity.moving)
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'statistics': activities_list},
'statistics': activities_list
}
} }
code = 200 code = 200
except Exception as e: except Exception as e:
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
code = 500 code = 500
return jsonify(response_object), code return jsonify(response_object), code

View File

@ -35,7 +35,8 @@ def get_datetime_with_tz(timezone, activity_date, gpx_data=None):
fmt = '%Y-%m-%d %H:%M:%S' fmt = '%Y-%m-%d %H:%M:%S'
activity_date_string = activity_date.strftime(fmt) activity_date_string = activity_date.strftime(fmt)
activity_date_tmp = utc_tz.localize( activity_date_tmp = utc_tz.localize(
datetime.strptime(activity_date_string, fmt)) datetime.strptime(activity_date_string, fmt)
)
activity_date_tz = activity_date_tmp.astimezone(user_tz) activity_date_tz = activity_date_tmp.astimezone(user_tz)
else: else:
activity_date_tz = user_tz.localize(activity_date) activity_date_tz = user_tz.localize(activity_date)
@ -59,27 +60,34 @@ def update_activity_data(activity, gpx_data):
return activity return activity
def create_activity( def create_activity(user, activity_data, gpx_data=None):
user, activity_data, gpx_data=None activity_date = (
): gpx_data['start']
activity_date = gpx_data['start'] if gpx_data else datetime.strptime( if gpx_data
activity_data.get('activity_date'), '%Y-%m-%d %H:%M') else datetime.strptime(
activity_data.get('activity_date'), '%Y-%m-%d %H:%M'
)
)
activity_date_tz, activity_date = get_datetime_with_tz( activity_date_tz, activity_date = get_datetime_with_tz(
user.timezone, activity_date, gpx_data) user.timezone, activity_date, gpx_data
)
duration = gpx_data['duration'] if gpx_data \ duration = (
gpx_data['duration']
if gpx_data
else timedelta(seconds=activity_data.get('duration')) else timedelta(seconds=activity_data.get('duration'))
distance = gpx_data['distance'] if gpx_data \ )
else activity_data.get('distance') distance = (
title = gpx_data['name'] if gpx_data \ gpx_data['distance'] if gpx_data else activity_data.get('distance')
else activity_data.get('title') )
title = gpx_data['name'] if gpx_data else activity_data.get('title')
new_activity = Activity( new_activity = Activity(
user_id=user.id, user_id=user.id,
sport_id=activity_data.get('sport_id'), sport_id=activity_data.get('sport_id'),
activity_date=activity_date, activity_date=activity_date,
distance=distance, distance=distance,
duration=duration duration=duration,
) )
new_activity.notes = activity_data.get('notes') new_activity.notes = activity_data.get('notes')
@ -91,7 +99,8 @@ def create_activity(
activity_datetime = ( activity_datetime = (
activity_date_tz.strftime(fmt) activity_date_tz.strftime(fmt)
if activity_date_tz if activity_date_tz
else new_activity.activity_date.strftime(fmt)) else new_activity.activity_date.strftime(fmt)
)
new_activity.title = f'{sport.label} - {activity_datetime}' new_activity.title = f'{sport.label} - {activity_datetime}'
if gpx_data: if gpx_data:
@ -100,18 +109,18 @@ def create_activity(
update_activity_data(new_activity, gpx_data) update_activity_data(new_activity, gpx_data)
else: else:
new_activity.moving = duration new_activity.moving = duration
new_activity.ave_speed = (None new_activity.ave_speed = (
if duration.seconds == 0 None
else float(new_activity.distance) / if duration.seconds == 0
(duration.seconds / 3600)) else float(new_activity.distance) / (duration.seconds / 3600)
)
new_activity.max_speed = new_activity.ave_speed new_activity.max_speed = new_activity.ave_speed
return new_activity return new_activity
def create_segment(activity_id, segment_data): def create_segment(activity_id, segment_data):
new_segment = ActivitySegment( new_segment = ActivitySegment(
activity_id=activity_id, activity_id=activity_id, segment_id=segment_data['idx']
segment_id=segment_data['idx']
) )
new_segment.duration = segment_data['duration'] new_segment.duration = segment_data['duration']
new_segment.distance = segment_data['distance'] new_segment.distance = segment_data['distance']
@ -127,7 +136,8 @@ def update_activity(activity):
(case of a modified gpx file, see issue #7) (case of a modified gpx file, see issue #7)
""" """
gpx_data, _, _ = get_gpx_info( gpx_data, _, _ = get_gpx_info(
get_absolute_file_path(activity.gpx), False, False) get_absolute_file_path(activity.gpx), False, False
)
updated_activity = update_activity_data(activity, gpx_data) updated_activity = update_activity_data(activity, gpx_data)
updated_activity.duration = gpx_data['duration'] updated_activity.duration = gpx_data['duration']
updated_activity.distance = gpx_data['distance'] updated_activity.distance = gpx_data['distance']
@ -156,21 +166,26 @@ def edit_activity(activity, activity_data, auth_user_id):
if not activity.gpx: if not activity.gpx:
if activity_data.get('activity_date'): if activity_data.get('activity_date'):
activity_date = datetime.strptime( activity_date = datetime.strptime(
activity_data.get('activity_date'), '%Y-%m-%d %H:%M') activity_data.get('activity_date'), '%Y-%m-%d %H:%M'
)
_, activity.activity_date = get_datetime_with_tz( _, activity.activity_date = get_datetime_with_tz(
user.timezone, activity_date) user.timezone, activity_date
)
if activity_data.get('duration'): if activity_data.get('duration'):
activity.duration = timedelta( activity.duration = timedelta(
seconds=activity_data.get('duration')) seconds=activity_data.get('duration')
)
activity.moving = activity.duration activity.moving = activity.duration
if activity_data.get('distance'): if activity_data.get('distance'):
activity.distance = activity_data.get('distance') activity.distance = activity_data.get('distance')
activity.ave_speed = (None if activity.duration.seconds == 0 activity.ave_speed = (
else float(activity.distance) / None
(activity.duration.seconds / 3600)) if activity.duration.seconds == 0
else float(activity.distance) / (activity.duration.seconds / 3600)
)
activity.max_speed = activity.ave_speed activity.max_speed = activity.ave_speed
return activity return activity
@ -183,19 +198,17 @@ def get_file_path(dir_path, filename):
def get_new_file_path( def get_new_file_path(
auth_user_id, activity_date, sport, old_filename=None, extension=None auth_user_id, activity_date, sport, old_filename=None, extension=None
): ):
if not extension: if not extension:
extension = f".{old_filename.rsplit('.', 1)[1].lower()}" extension = f".{old_filename.rsplit('.', 1)[1].lower()}"
_, new_filename = tempfile.mkstemp( _, new_filename = tempfile.mkstemp(
prefix=f'{activity_date}_{sport}_', prefix=f'{activity_date}_{sport}_', suffix=extension
suffix=extension
) )
dir_path = os.path.join('activities', str(auth_user_id)) dir_path = os.path.join('activities', str(auth_user_id))
if not os.path.exists(dir_path): if not os.path.exists(dir_path):
os.makedirs(dir_path) os.makedirs(dir_path)
file_path = os.path.join(dir_path, file_path = os.path.join(dir_path, new_filename.split('/')[-1])
new_filename.split('/')[-1])
return file_path return file_path
@ -228,7 +241,7 @@ def process_one_gpx_file(params, filename):
auth_user_id=auth_user_id, auth_user_id=auth_user_id,
activity_date=gpx_data['start'], activity_date=gpx_data['start'],
old_filename=filename, old_filename=filename,
sport=params['sport_label'] sport=params['sport_label'],
) )
absolute_gpx_filepath = get_absolute_file_path(new_filepath) absolute_gpx_filepath = get_absolute_file_path(new_filepath)
os.rename(params['file_path'], absolute_gpx_filepath) os.rename(params['file_path'], absolute_gpx_filepath)
@ -238,7 +251,7 @@ def process_one_gpx_file(params, filename):
auth_user_id=auth_user_id, auth_user_id=auth_user_id,
activity_date=gpx_data['start'], activity_date=gpx_data['start'],
extension='.png', extension='.png',
sport=params['sport_label'] sport=params['sport_label'],
) )
absolute_map_filepath = get_absolute_file_path(map_filepath) absolute_map_filepath = get_absolute_file_path(map_filepath)
generate_map(absolute_map_filepath, map_data) generate_map(absolute_map_filepath, map_data)
@ -249,7 +262,8 @@ def process_one_gpx_file(params, filename):
try: try:
new_activity = create_activity( new_activity = create_activity(
params['user'], params['activity_data'], gpx_data) params['user'], params['activity_data'], gpx_data
)
new_activity.map = map_filepath new_activity.map = map_filepath
new_activity.map_id = get_map_hash(map_filepath) new_activity.map_id = get_map_hash(map_filepath)
new_activity.weather_start = weather_data[0] new_activity.weather_start = weather_data[0]
@ -280,8 +294,9 @@ def process_zip_archive(common_params, extract_dir):
gpx_files_ok = 0 gpx_files_ok = 0
for gpx_file in os.listdir(extract_dir): for gpx_file in os.listdir(extract_dir):
if ('.' in gpx_file and gpx_file.rsplit('.', 1)[1].lower() if '.' in gpx_file and gpx_file.rsplit('.', 1)[
in current_app.config.get('ACTIVITY_ALLOWED_EXTENSIONS')): 1
].lower() in current_app.config.get('ACTIVITY_ALLOWED_EXTENSIONS'):
gpx_files_ok += 1 gpx_files_ok += 1
if gpx_files_ok > gpx_files_limit: if gpx_files_ok > gpx_files_limit:
break break
@ -303,7 +318,7 @@ def process_files(auth_user_id, activity_data, activity_file, folders):
raise ActivityException( raise ActivityException(
'error', 'error',
f"Sport id: {activity_data.get('sport_id')} does not exist", f"Sport id: {activity_data.get('sport_id')} does not exist",
None None,
) )
user = User.query.filter_by(id=auth_user_id).first() user = User.query.filter_by(id=auth_user_id).first()

View File

@ -4,7 +4,7 @@ from datetime import timedelta
def convert_in_duration(value): def convert_in_duration(value):
hours = int(value.split(':')[0]) hours = int(value.split(':')[0])
minutes = int(value.split(':')[1]) minutes = int(value.split(':')[1])
return timedelta(seconds=(hours*3600 + minutes*60)) return timedelta(seconds=(hours * 3600 + minutes * 60))
def convert_timedelta_to_integer(value): def convert_timedelta_to_integer(value):

View File

@ -36,8 +36,9 @@ def get_gpx_data(parsed_gpx, max_speed, start, stopped_time_btwn_seg):
mv = parsed_gpx.get_moving_data() mv = parsed_gpx.get_moving_data()
gpx_data['moving_time'] = timedelta(seconds=mv.moving_time) gpx_data['moving_time'] = timedelta(seconds=mv.moving_time)
gpx_data['stop_time'] = (timedelta(seconds=mv.stopped_time) gpx_data['stop_time'] = (
+ stopped_time_btwn_seg) timedelta(seconds=mv.stopped_time) + stopped_time_btwn_seg
)
distance = mv.moving_distance + mv.stopped_distance distance = mv.moving_distance + mv.stopped_distance
gpx_data['distance'] = distance / 1000 gpx_data['distance'] = distance / 1000
@ -52,10 +53,7 @@ def get_gpx_info(gpx_file, update_map_data=True, update_weather_data=True):
if gpx is None: if gpx is None:
return None return None
gpx_data = { gpx_data = {'name': gpx.tracks[0].name, 'segments': []}
'name': gpx.tracks[0].name,
'segments': []
}
max_speed = 0 max_speed = 0
start = 0 start = 0
map_data = [] map_data = []
@ -90,12 +88,12 @@ def get_gpx_info(gpx_file, update_map_data=True, update_weather_data=True):
weather_data.append(get_weather(point)) weather_data.append(get_weather(point))
if update_map_data: if update_map_data:
map_data.append([ map_data.append([point.longitude, point.latitude])
point.longitude, point.latitude segment_max_speed = (
]) segment.get_moving_data().max_speed
segment_max_speed = (segment.get_moving_data().max_speed if segment.get_moving_data().max_speed
if segment.get_moving_data().max_speed else 0
else 0) )
if segment_max_speed > max_speed: if segment_max_speed > max_speed:
max_speed = segment_max_speed max_speed = segment_max_speed
@ -115,7 +113,7 @@ def get_gpx_info(gpx_file, update_map_data=True, update_weather_data=True):
bounds.min_latitude, bounds.min_latitude,
bounds.min_longitude, bounds.min_longitude,
bounds.max_latitude, bounds.max_latitude,
bounds.max_longitude bounds.max_longitude,
] ]
return gpx_data, map_data, weather_data return gpx_data, map_data, weather_data
@ -126,16 +124,10 @@ def get_gpx_segments(track_segments, segment_id=None):
segment_index = segment_id - 1 segment_index = segment_id - 1
if segment_index > (len(track_segments) - 1): if segment_index > (len(track_segments) - 1):
raise ActivityGPXException( raise ActivityGPXException(
'not found', 'not found', f'No segment with id \'{segment_id}\'', None
f'No segment with id \'{segment_id}\'',
None
) )
if segment_index < 0: if segment_index < 0:
raise ActivityGPXException( raise ActivityGPXException('error', 'Incorrect segment id', None)
'error',
'Incorrect segment id',
None
)
segments = [track_segments[segment_index]] segments = [track_segments[segment_index]]
else: else:
segments = track_segments segments = track_segments
@ -160,28 +152,41 @@ def get_chart_data(gpx_file, segment_id=None):
for point_idx, point in enumerate(segment.points): for point_idx, point in enumerate(segment.points):
if segment_idx == 0 and point_idx == 0: if segment_idx == 0 and point_idx == 0:
first_point = point first_point = point
distance = (point.distance_3d(previous_point) distance = (
if (point.elevation point.distance_3d(previous_point)
and previous_point if (
and previous_point.elevation) point.elevation
else point.distance_2d(previous_point) and previous_point
) and previous_point.elevation
)
else point.distance_2d(previous_point)
)
distance = 0 if distance is None else distance distance = 0 if distance is None else distance
distance += previous_distance distance += previous_distance
speed = (round((segment.get_speed(point_idx) / 1000)*3600, 2) speed = (
if segment.get_speed(point_idx) is not None round((segment.get_speed(point_idx) / 1000) * 3600, 2)
else 0) if segment.get_speed(point_idx) is not None
chart_data.append({ else 0
'distance': (round(distance / 1000, 2) )
if distance is not None else 0), chart_data.append(
'duration': point.time_difference(first_point), {
'elevation': (round(point.elevation, 1) 'distance': (
if point.elevation is not None else 0), round(distance / 1000, 2)
'latitude': point.latitude, if distance is not None
'longitude': point.longitude, else 0
'speed': speed, ),
'time': point.time, 'duration': point.time_difference(first_point),
}) 'elevation': (
round(point.elevation, 1)
if point.elevation is not None
else 0
),
'latitude': point.latitude,
'longitude': point.longitude,
'speed': speed,
'time': point.time,
}
)
previous_point = point previous_point = point
previous_distance = distance previous_distance = distance
@ -194,8 +199,7 @@ def extract_segment_from_gpx_file(content, segment_id):
return None return None
track_segment = get_gpx_segments( track_segment = get_gpx_segments(
gpx_content.tracks[0].segments, gpx_content.tracks[0].segments, segment_id
segment_id
) )
gpx = gpxpy.gpx.GPX() gpx = gpxpy.gpx.GPX()
@ -207,8 +211,8 @@ def extract_segment_from_gpx_file(content, segment_id):
for point_idx, point in enumerate(track_segment[0].points): for point_idx, point in enumerate(track_segment[0].points):
gpx_segment.points.append( gpx_segment.points.append(
gpxpy.gpx.GPXTrackPoint( gpxpy.gpx.GPXTrackPoint(
point.latitude, point.latitude, point.longitude, elevation=point.elevation
point.longitude, )
elevation=point.elevation)) )
return gpx.to_xml() return gpx.to_xml()

View File

@ -17,7 +17,7 @@ def get_weather(point):
point.latitude, point.latitude,
point.longitude, point.longitude,
time=point_time, time=point_time,
units='si' units='si',
) )
weather = forecast.currently() weather = forecast.currently()
return { return {

View File

@ -5,15 +5,14 @@ from flask import current_app
class BaseConfig: class BaseConfig:
"""Base configuration""" """Base configuration"""
DEBUG = False DEBUG = False
TESTING = False TESTING = False
SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_TRACK_MODIFICATIONS = False
BCRYPT_LOG_ROUNDS = 13 BCRYPT_LOG_ROUNDS = 13
TOKEN_EXPIRATION_DAYS = 30 TOKEN_EXPIRATION_DAYS = 30
TOKEN_EXPIRATION_SECONDS = 0 TOKEN_EXPIRATION_SECONDS = 0
UPLOAD_FOLDER = os.path.join( UPLOAD_FOLDER = os.path.join(current_app.root_path, 'uploads')
current_app.root_path, 'uploads'
)
PICTURE_ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'} PICTURE_ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'}
ACTIVITY_ALLOWED_EXTENSIONS = {'gpx', 'zip'} ACTIVITY_ALLOWED_EXTENSIONS = {'gpx', 'zip'}
REGISTRATION_ALLOWED = ( REGISTRATION_ALLOWED = (
@ -23,6 +22,7 @@ class BaseConfig:
class DevelopmentConfig(BaseConfig): class DevelopmentConfig(BaseConfig):
"""Development configuration""" """Development configuration"""
DEBUG = True DEBUG = True
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
SECRET_KEY = 'development key' SECRET_KEY = 'development key'
@ -33,6 +33,7 @@ class DevelopmentConfig(BaseConfig):
class TestingConfig(BaseConfig): class TestingConfig(BaseConfig):
"""Testing configuration""" """Testing configuration"""
DEBUG = True DEBUG = True
TESTING = True TESTING = True
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_TEST_URL') SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_TEST_URL')

View File

@ -50,9 +50,7 @@ def user_1():
@pytest.fixture() @pytest.fixture()
def user_1_admin(): def user_1_admin():
admin = User( admin = User(
username='admin', username='admin', email='admin@example.com', password='12345678'
email='admin@example.com',
password='12345678'
) )
admin.admin = True admin.admin = True
db.session.add(admin) db.session.add(admin)
@ -114,7 +112,7 @@ def activity_cycling_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('01/01/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('01/01/2018', '%d/%m/%Y'),
distance=10, distance=10,
duration=datetime.timedelta(seconds=1024) duration=datetime.timedelta(seconds=1024),
) )
activity.max_speed = 10 activity.max_speed = 10
activity.ave_speed = 10 activity.ave_speed = 10
@ -126,10 +124,7 @@ def activity_cycling_user_1():
@pytest.fixture() @pytest.fixture()
def activity_cycling_user_1_segment(): def activity_cycling_user_1_segment():
activity_segment = ActivitySegment( activity_segment = ActivitySegment(activity_id=1, segment_id=0)
activity_id=1,
segment_id=0
)
activity_segment.duration = datetime.timedelta(seconds=6000) activity_segment.duration = datetime.timedelta(seconds=6000)
activity_segment.moving = activity_segment.duration activity_segment.moving = activity_segment.duration
activity_segment.distance = 5 activity_segment.distance = 5
@ -145,7 +140,7 @@ def activity_running_user_1():
sport_id=2, sport_id=2,
activity_date=datetime.datetime.strptime('01/04/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('01/04/2018', '%d/%m/%Y'),
distance=12, distance=12,
duration=datetime.timedelta(seconds=6000) duration=datetime.timedelta(seconds=6000),
) )
activity.moving = activity.duration activity.moving = activity.duration
db.session.add(activity) db.session.add(activity)
@ -160,7 +155,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('20/03/2017', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('20/03/2017', '%d/%m/%Y'),
distance=5, distance=5,
duration=datetime.timedelta(seconds=1024) duration=datetime.timedelta(seconds=1024),
) )
activity.ave_speed = float(activity.distance) / (1024 / 3600) activity.ave_speed = float(activity.distance) / (1024 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -171,7 +166,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('01/06/2017', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('01/06/2017', '%d/%m/%Y'),
distance=10, distance=10,
duration=datetime.timedelta(seconds=3456) duration=datetime.timedelta(seconds=3456),
) )
activity.ave_speed = float(activity.distance) / (3456 / 3600) activity.ave_speed = float(activity.distance) / (3456 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -182,7 +177,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('01/01/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('01/01/2018', '%d/%m/%Y'),
distance=10, distance=10,
duration=datetime.timedelta(seconds=1024) duration=datetime.timedelta(seconds=1024),
) )
activity.ave_speed = float(activity.distance) / (1024 / 3600) activity.ave_speed = float(activity.distance) / (1024 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -193,7 +188,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('23/02/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('23/02/2018', '%d/%m/%Y'),
distance=1, distance=1,
duration=datetime.timedelta(seconds=600) duration=datetime.timedelta(seconds=600),
) )
activity.ave_speed = float(activity.distance) / (600 / 3600) activity.ave_speed = float(activity.distance) / (600 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -204,7 +199,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('23/02/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('23/02/2018', '%d/%m/%Y'),
distance=10, distance=10,
duration=datetime.timedelta(seconds=1000) duration=datetime.timedelta(seconds=1000),
) )
activity.ave_speed = float(activity.distance) / (1000 / 3600) activity.ave_speed = float(activity.distance) / (1000 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -215,7 +210,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('01/04/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('01/04/2018', '%d/%m/%Y'),
distance=8, distance=8,
duration=datetime.timedelta(seconds=6000) duration=datetime.timedelta(seconds=6000),
) )
activity.ave_speed = float(activity.distance) / (6000 / 3600) activity.ave_speed = float(activity.distance) / (6000 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -226,7 +221,7 @@ def seven_activities_user_1():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('09/05/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('09/05/2018', '%d/%m/%Y'),
distance=10, distance=10,
duration=datetime.timedelta(seconds=3000) duration=datetime.timedelta(seconds=3000),
) )
activity.ave_speed = float(activity.distance) / (3000 / 3600) activity.ave_speed = float(activity.distance) / (3000 / 3600)
activity.moving = activity.duration activity.moving = activity.duration
@ -242,7 +237,7 @@ def activity_cycling_user_2():
sport_id=1, sport_id=1,
activity_date=datetime.datetime.strptime('23/01/2018', '%d/%m/%Y'), activity_date=datetime.datetime.strptime('23/01/2018', '%d/%m/%Y'),
distance=15, distance=15,
duration=datetime.timedelta(seconds=3600) duration=datetime.timedelta(seconds=3600),
) )
activity.moving = activity.duration activity.moving = activity.duration
db.session.add(activity) db.session.add(activity)

View File

@ -6,7 +6,10 @@ from fittrackee_api.activities.models import Activity
def assert_activity_data_with_gpx(data): def assert_activity_data_with_gpx(data):
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert 'Tue, 13 Mar 2018 12:44:45 GMT' == data['data']['activities'][0]['activity_date'] # noqa assert (
'Tue, 13 Mar 2018 12:44:45 GMT'
== data['data']['activities'][0]['activity_date']
) # noqa
assert 1 == data['data']['activities'][0]['user_id'] assert 1 == data['data']['activities'][0]['user_id']
assert '0:04:10' == data['data']['activities'][0]['duration'] assert '0:04:10' == data['data']['activities'][0]['duration']
assert data['data']['activities'][0]['ascent'] == 0.4 assert data['data']['activities'][0]['ascent'] == 0.4
@ -50,37 +53,29 @@ def test_edit_an_activity_with_gpx(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(sport_id=2, title="Activity test")),
sport_id=2,
title="Activity test",
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -94,14 +89,11 @@ def test_edit_an_activity_with_gpx(
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(notes="test notes")),
notes="test notes"
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -118,45 +110,34 @@ def test_edit_an_activity_with_gpx_different_user(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='toto@toto.com', password='87654321')),
email='toto@toto.com', content_type='application/json',
password='87654321'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(sport_id=2, title="Activity test")),
sport_id=2,
title="Activity test",
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -171,36 +152,29 @@ def test_edit_an_activity_with_gpx_partial(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(sport_id=2)),
sport_id=2,
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -213,39 +187,34 @@ def test_edit_an_activity_with_gpx_partial(
def test_edit_an_activity_with_gpx_invalid_payload( def test_edit_an_activity_with_gpx_invalid_payload(
app, user_1, sport_1_cycling, gpx_file app, user_1, sport_1_cycling, gpx_file
): ):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict()), data=json.dumps(dict()),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -261,43 +230,39 @@ def test_edit_an_activity_with_gpx_incorrect_data(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(sport_id=2)),
sport_id=2,
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 500 assert response.status_code == 500
assert 'error' in data['status'] assert 'error' in data['status']
assert 'Error. Please try again or contact the administrator.' in data['message'] # noqa assert (
'Error. Please try again or contact the administrator.'
in data['message']
) # noqa
def test_edit_an_activity_wo_gpx( def test_edit_an_activity_wo_gpx(
@ -306,28 +271,26 @@ def test_edit_an_activity_wo_gpx(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/activities/no_gpx', '/api/activities/no_gpx',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=1, dict(
duration=3600, sport_id=1,
activity_date='2018-05-14 14:05', duration=3600,
distance=7, activity_date='2018-05-14 14:05',
title='Activity test' distance=7,
)), title='Activity test',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -336,7 +299,10 @@ def test_edit_an_activity_wo_gpx(
assert 'created' in data['status'] assert 'created' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Mon, 14 May 2018 14:05:00 GMT' # noqa assert (
data['data']['activities'][0]['activity_date']
== 'Mon, 14 May 2018 14:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 1 assert data['data']['activities'][0]['sport_id'] == 1
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
@ -382,18 +348,19 @@ def test_edit_an_activity_wo_gpx(
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=2, dict(
duration=3600, sport_id=2,
activity_date='2018-05-15 15:05', duration=3600,
distance=8, activity_date='2018-05-15 15:05',
title='Activity test' distance=8,
)), title='Activity test',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -401,7 +368,10 @@ def test_edit_an_activity_wo_gpx(
assert 'success' in data['status'] assert 'success' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Tue, 15 May 2018 15:05:00 GMT' # noqa assert (
data['data']['activities'][0]['activity_date']
== 'Tue, 15 May 2018 15:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 2 assert data['data']['activities'][0]['sport_id'] == 2
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
@ -447,14 +417,11 @@ def test_edit_an_activity_wo_gpx(
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(notes='test notes')),
notes='test notes'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -462,7 +429,10 @@ def test_edit_an_activity_wo_gpx(
assert 'success' in data['status'] assert 'success' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Tue, 15 May 2018 15:05:00 GMT' # noqa assert (
data['data']['activities'][0]['activity_date']
== 'Tue, 15 May 2018 15:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 2 assert data['data']['activities'][0]['sport_id'] == 2
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
@ -512,52 +482,48 @@ def test_edit_an_activity_wo_gpx_different_user(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities/no_gpx', '/api/activities/no_gpx',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=1, dict(
duration=3600, sport_id=1,
activity_date='2018-05-14 14:05', duration=3600,
distance=7, activity_date='2018-05-14 14:05',
title='Activity test' distance=7,
)), title='Activity test',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='toto@toto.com', password='87654321')),
email='toto@toto.com', content_type='application/json',
password='87654321'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=2, dict(
duration=3600, sport_id=2,
activity_date='2018-05-15 15:05', duration=3600,
distance=8, activity_date='2018-05-15 15:05',
title='Activity test' distance=8,
)), title='Activity test',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -572,27 +538,25 @@ def test_edit_an_activity_wo_gpx_timezone(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/activities/no_gpx', '/api/activities/no_gpx',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=1, dict(
duration=3600, sport_id=1,
activity_date='2018-05-14 14:05', duration=3600,
distance=7 activity_date='2018-05-14 14:05',
)), distance=7,
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -601,11 +565,17 @@ def test_edit_an_activity_wo_gpx_timezone(
assert 'created' in data['status'] assert 'created' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Mon, 14 May 2018 12:05:00 GMT' # noqa assert (
data['data']['activities'][0]['activity_date']
== 'Mon, 14 May 2018 12:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 1 assert data['data']['activities'][0]['sport_id'] == 1
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
assert data['data']['activities'][0]['title'] == 'Cycling - 2018-05-14 14:05:00' # noqa assert (
data['data']['activities'][0]['title']
== 'Cycling - 2018-05-14 14:05:00'
) # noqa
assert data['data']['activities'][0]['ascent'] is None assert data['data']['activities'][0]['ascent'] is None
assert data['data']['activities'][0]['ave_speed'] == 7.0 assert data['data']['activities'][0]['ave_speed'] == 7.0
assert data['data']['activities'][0]['descent'] is None assert data['data']['activities'][0]['descent'] is None
@ -643,18 +613,19 @@ def test_edit_an_activity_wo_gpx_timezone(
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=2, dict(
duration=3600, sport_id=2,
activity_date='2018-05-15 15:05', duration=3600,
distance=8, activity_date='2018-05-15 15:05',
title='Activity test' distance=8,
)), title='Activity test',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -662,7 +633,10 @@ def test_edit_an_activity_wo_gpx_timezone(
assert 'success' in data['status'] assert 'success' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Tue, 15 May 2018 13:05:00 GMT' # noqa assert (
data['data']['activities'][0]['activity_date']
== 'Tue, 15 May 2018 13:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 2 assert data['data']['activities'][0]['sport_id'] == 2
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
@ -702,32 +676,28 @@ def test_edit_an_activity_wo_gpx_timezone(
assert records[3]['value'] == 8.0 assert records[3]['value'] == 8.0
def test_edit_an_activity_wo_gpx_partial( def test_edit_an_activity_wo_gpx_partial(app, user_1, sport_1_cycling):
app, user_1, sport_1_cycling
):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/activities/no_gpx', '/api/activities/no_gpx',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=1, dict(
duration=3600, sport_id=1,
activity_date='2018-05-14 14:05', duration=3600,
distance=7 activity_date='2018-05-14 14:05',
)), distance=7,
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -736,12 +706,17 @@ def test_edit_an_activity_wo_gpx_partial(
assert 'created' in data['status'] assert 'created' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0][ assert (
'activity_date'] == 'Mon, 14 May 2018 14:05:00 GMT' # noqa data['data']['activities'][0]['activity_date']
== 'Mon, 14 May 2018 14:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 1 assert data['data']['activities'][0]['sport_id'] == 1
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
assert data['data']['activities'][0]['title'] == 'Cycling - 2018-05-14 14:05:00' # noqa assert (
data['data']['activities'][0]['title']
== 'Cycling - 2018-05-14 14:05:00'
) # noqa
assert data['data']['activities'][0]['ascent'] is None assert data['data']['activities'][0]['ascent'] is None
assert data['data']['activities'][0]['ave_speed'] == 7.0 assert data['data']['activities'][0]['ave_speed'] == 7.0
assert data['data']['activities'][0]['descent'] is None assert data['data']['activities'][0]['descent'] is None
@ -779,15 +754,11 @@ def test_edit_an_activity_wo_gpx_partial(
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(sport_id=1, distance=10)),
sport_id=1,
distance=10
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -796,11 +767,17 @@ def test_edit_an_activity_wo_gpx_partial(
assert 'success' in data['status'] assert 'success' in data['status']
assert len(data['data']['activities']) == 1 assert len(data['data']['activities']) == 1
assert 'creation_date' in data['data']['activities'][0] assert 'creation_date' in data['data']['activities'][0]
assert data['data']['activities'][0]['activity_date'] == 'Mon, 14 May 2018 14:05:00 GMT' # noqa assert (
data['data']['activities'][0]['activity_date']
== 'Mon, 14 May 2018 14:05:00 GMT'
) # noqa
assert data['data']['activities'][0]['user_id'] == 1 assert data['data']['activities'][0]['user_id'] == 1
assert data['data']['activities'][0]['sport_id'] == 1 assert data['data']['activities'][0]['sport_id'] == 1
assert data['data']['activities'][0]['duration'] == '1:00:00' assert data['data']['activities'][0]['duration'] == '1:00:00'
assert data['data']['activities'][0]['title'] == 'Cycling - 2018-05-14 14:05:00' # noqa assert (
data['data']['activities'][0]['title']
== 'Cycling - 2018-05-14 14:05:00'
) # noqa
assert data['data']['activities'][0]['ascent'] is None assert data['data']['activities'][0]['ascent'] is None
assert data['data']['activities'][0]['ave_speed'] == 10.0 assert data['data']['activities'][0]['ave_speed'] == 10.0
assert data['data']['activities'][0]['descent'] is None assert data['data']['activities'][0]['descent'] is None
@ -842,21 +819,17 @@ def test_edit_an_activity_wo_gpx_invalid_payload(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict()), data=json.dumps(dict()),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -872,62 +845,55 @@ def test_edit_an_activity_wo_gpx_incorrect_data(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=1, dict(
duration=3600, sport_id=1, duration=3600, activity_date='15/2018', distance=10
activity_date='15/2018', )
distance=10 ),
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 500 assert response.status_code == 500
assert 'error' in data['status'] assert 'error' in data['status']
assert 'Error. Please try again or contact the administrator.' \ assert (
in data['message'] 'Error. Please try again or contact the administrator.'
in data['message']
)
def test_edit_an_activity_no_activity( def test_edit_an_activity_no_activity(app, user_1, sport_1_cycling):
app, user_1, sport_1_cycling
):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
sport_id=1, dict(
duration=3600, sport_id=1,
activity_date='2018-05-15 14:05', duration=3600,
distance=10 activity_date='2018-05-15 14:05',
)), distance=10,
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -943,24 +909,20 @@ def test_refresh_an_activity_with_gpx(
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
# Edit some activity data # Edit some activity data
@ -971,14 +933,11 @@ def test_refresh_an_activity_with_gpx(
response = client.patch( response = client.patch(
'/api/activities/1', '/api/activities/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(refresh=True)),
refresh=True,
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())

View File

@ -15,76 +15,64 @@ def test_delete_an_activity_with_gpx(app, user_1, sport_1_cycling, gpx_file):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
response = client.delete( response = client.delete(
'/api/activities/1', '/api/activities/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
assert response.status_code == 204 assert response.status_code == 204
def test_delete_an_activity_with_gpx_different_user( def test_delete_an_activity_with_gpx_different_user(
app, user_1, user_2, sport_1_cycling, gpx_file): app, user_1, user_2, sport_1_cycling, gpx_file
):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='toto@toto.com', password='87654321')),
email='toto@toto.com', content_type='application/json',
password='87654321'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/activities/1', '/api/activities/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -95,47 +83,39 @@ def test_delete_an_activity_with_gpx_different_user(
def test_delete_an_activity_wo_gpx( def test_delete_an_activity_wo_gpx(
app, user_1, sport_1_cycling, activity_cycling_user_1 app, user_1, sport_1_cycling, activity_cycling_user_1
): ):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/activities/1', '/api/activities/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
assert response.status_code == 204 assert response.status_code == 204
def test_delete_an_activity_wo_gpx_different_user( def test_delete_an_activity_wo_gpx_different_user(
app, user_1, user_2, sport_1_cycling, activity_cycling_user_1 app, user_1, user_2, sport_1_cycling, activity_cycling_user_1
): ):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='toto@toto.com', password='87654321')),
email='toto@toto.com', content_type='application/json',
password='87654321'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/activities/1', '/api/activities/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -149,19 +129,15 @@ def test_delete_an_activity_no_activity(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/activities/9999', '/api/activities/9999',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 404 assert response.status_code == 404
@ -169,28 +145,25 @@ def test_delete_an_activity_no_activity(app, user_1):
def test_delete_an_activity_with_gpx_invalid_file( def test_delete_an_activity_with_gpx_invalid_file(
app, user_1, sport_1_cycling, gpx_file): app, user_1, sport_1_cycling, gpx_file
):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
client.post( client.post(
'/api/activities', '/api/activities',
data=dict( data=dict(
file=(BytesIO(str.encode(gpx_file)), 'example.gpx'), file=(BytesIO(str.encode(gpx_file)), 'example.gpx'),
data='{"sport_id": 1}' data='{"sport_id": 1}',
), ),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token'],
)['auth_token'] ),
)
) )
gpx_filepath = get_gpx_filepath(1) gpx_filepath = get_gpx_filepath(1)
@ -200,15 +173,16 @@ def test_delete_an_activity_with_gpx_invalid_file(
response = client.delete( response = client.delete(
'/api/activities/1', '/api/activities/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 500 assert response.status_code == 500
assert 'error' in data['status'] assert 'error' in data['status']
assert 'Error. Please try again or contact the administrator.' \ assert (
in data['message'] 'Error. Please try again or contact the administrator.'
in data['message']
)

View File

@ -1,8 +1,4 @@
def test_add_activity(app, sport_1_cycling, user_1, activity_cycling_user_1):
def test_add_activity(
app, sport_1_cycling, user_1, activity_cycling_user_1
):
activity_cycling_user_1.title = 'Test' activity_cycling_user_1.title = 'Test'
assert 1 == activity_cycling_user_1.id assert 1 == activity_cycling_user_1.id
@ -12,7 +8,9 @@ def test_add_activity(
assert 10.0 == float(activity_cycling_user_1.distance) assert 10.0 == float(activity_cycling_user_1.distance)
assert '0:17:04' == str(activity_cycling_user_1.duration) assert '0:17:04' == str(activity_cycling_user_1.duration)
assert 'Test' == activity_cycling_user_1.title assert 'Test' == activity_cycling_user_1.title
assert '<Activity \'Cycling\' - 2018-01-01 00:00:00>' == str(activity_cycling_user_1) # noqa assert '<Activity \'Cycling\' - 2018-01-01 00:00:00>' == str(
activity_cycling_user_1
) # noqa
serialized_activity = activity_cycling_user_1.serialize() serialized_activity = activity_cycling_user_1.serialize()
assert 1 == serialized_activity['id'] assert 1 == serialized_activity['id']
@ -44,7 +42,12 @@ def test_add_activity(
def test_add_segment( def test_add_segment(
app, sport_1_cycling, user_1, activity_cycling_user_1, app,
activity_cycling_user_1_segment sport_1_cycling,
user_1,
activity_cycling_user_1,
activity_cycling_user_1_segment,
): ):
assert '<Segment \'0\' for activity \'1\'>' == str(activity_cycling_user_1_segment) # noqa assert '<Segment \'0\' for activity \'1\'>' == str(
activity_cycling_user_1_segment
) # noqa

View File

@ -7,13 +7,15 @@ def test_user_registration(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='justatest', dict(
email='test@test.com', username='justatest',
password='12345678', email='test@test.com',
password_conf='12345678' password='12345678',
)), password_conf='12345678',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -27,13 +29,15 @@ def test_user_registration_user_already_exists(app, user_1):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(
email='test@test.com', username='test',
password='12345678', email='test@test.com',
password_conf='12345678' password='12345678',
)), password_conf='12345678',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
@ -46,17 +50,21 @@ def test_user_registration_invalid_short_username(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='t', dict(
email='test@test.com', username='t',
password='12345678', email='test@test.com',
password_conf='12345678' password='12345678',
)), password_conf='12345678',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == "Errors: Username: 3 to 12 characters required.\n" # noqa assert (
data['message'] == "Errors: Username: 3 to 12 characters required.\n"
) # noqa
assert response.content_type == 'application/json' assert response.content_type == 'application/json'
assert response.status_code == 400 assert response.status_code == 400
@ -65,17 +73,21 @@ def test_user_registration_invalid_long_username(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='testestestestestest', dict(
email='test@test.com', username='testestestestestest',
password='12345678', email='test@test.com',
password_conf='12345678' password='12345678',
)), password_conf='12345678',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == "Errors: Username: 3 to 12 characters required.\n" # noqa assert (
data['message'] == "Errors: Username: 3 to 12 characters required.\n"
) # noqa
assert response.content_type == 'application/json' assert response.content_type == 'application/json'
assert response.status_code == 400 assert response.status_code == 400
@ -84,13 +96,15 @@ def test_user_registration_invalid_email(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(
email='test@test', username='test',
password='12345678', email='test@test',
password_conf='12345678' password='12345678',
)), password_conf='12345678',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
@ -103,17 +117,21 @@ def test_user_registration_invalid_short_password(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(
email='test@test.com', username='test',
password='1234567', email='test@test.com',
password_conf='1234567' password='1234567',
)), password_conf='1234567',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == "Errors: Password: 8 characters required.\n" # noqa assert (
data['message'] == "Errors: Password: 8 characters required.\n"
) # noqa
assert response.content_type == 'application/json' assert response.content_type == 'application/json'
assert response.status_code == 400 assert response.status_code == 400
@ -122,17 +140,22 @@ def test_user_registration_mismatched_password(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(
email='test@test.com', username='test',
password='12345678', email='test@test.com',
password_conf='87654321' password='12345678',
)), password_conf='87654321',
content_type='application/json' )
),
content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == "Errors: Password and password confirmation don\'t match.\n" # noqa assert (
data['message']
== "Errors: Password and password confirmation don\'t match.\n"
) # noqa
assert response.content_type == 'application/json' assert response.content_type == 'application/json'
assert response.status_code == 400 assert response.status_code == 400
@ -142,7 +165,7 @@ def test_user_registration_invalid_json(app):
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict()), data=json.dumps(dict()),
content_type='application/json' content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code, 400 assert response.status_code, 400
@ -154,10 +177,13 @@ def test_user_registration_invalid_json_keys_no_username(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
email='test@test.com', dict(
password='12345678', email='test@test.com',
password_conf='12345678')), password='12345678',
password_conf='12345678',
)
),
content_type='application/json', content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -170,10 +196,11 @@ def test_user_registration_invalid_json_keys_no_email(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(
password='12345678', username='test', password='12345678', password_conf='12345678'
password_conf='12345678')), )
),
content_type='application/json', content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -186,10 +213,13 @@ def test_user_registration_invalid_json_keys_no_password(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(
email='test@test.com', username='test',
password_conf='12345678')), email='test@test.com',
password_conf='12345678',
)
),
content_type='application/json', content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -202,10 +232,9 @@ def test_user_registration_invalid_json_keys_no_password_conf(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username='test', dict(username='test', email='test@test.com', password='12345678')
email='test@test.com', ),
password='12345678')),
content_type='application/json', content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -218,17 +247,22 @@ def test_user_registration_invalid_data(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/register', '/api/auth/register',
data=json.dumps(dict( data=json.dumps(
username=1, dict(
email='test@test.com', username=1,
password='12345678', email='test@test.com',
password_conf='12345678' password='12345678',
)), password_conf='12345678',
)
),
content_type='application/json', content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 500 assert response.status_code == 500
assert 'Error. Please try again or contact the administrator.' in data['message'] # noqa assert (
'Error. Please try again or contact the administrator.'
in data['message']
) # noqa
assert 'error' in data['status'] assert 'error' in data['status']
@ -258,11 +292,8 @@ def test_login_registered_user(app, user_1):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -276,11 +307,8 @@ def test_login_no_registered_user(app):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
@ -294,7 +322,7 @@ def test_login_invalid_payload(app):
response = client.post( response = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict()), data=json.dumps(dict()),
content_type='application/json' content_type='application/json',
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
@ -307,11 +335,8 @@ def test_login_registered_user_invalid_password(app, user_1):
client = app.test_client() client = app.test_client()
response = client.post( response = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='123456789')),
email='test@test.com', content_type='application/json',
password='123456789'
)),
content_type='application/json'
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
@ -325,20 +350,16 @@ def test_logout(app, user_1):
# user login # user login
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
# valid token logout # valid token logout
response = client.get( response = client.get(
'/api/auth/logout', '/api/auth/logout',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -350,21 +371,17 @@ def test_logout_expired_token(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
# invalid token logout # invalid token logout
time.sleep(4) time.sleep(4)
response = client.get( response = client.get(
'/api/auth/logout', '/api/auth/logout',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
@ -375,8 +392,8 @@ def test_logout_expired_token(app, user_1):
def test_logout_invalid(app): def test_logout_invalid(app):
client = app.test_client() client = app.test_client()
response = client.get( response = client.get(
'/api/auth/logout', '/api/auth/logout', headers=dict(Authorization='Bearer invalid')
headers=dict(Authorization='Bearer invalid')) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == 'Invalid token. Please log in again.' assert data['message'] == 'Invalid token. Please log in again.'
@ -385,9 +402,7 @@ def test_logout_invalid(app):
def test_logout_invalid_headers(app): def test_logout_invalid_headers(app):
client = app.test_client() client = app.test_client()
response = client.get( response = client.get('/api/auth/logout', headers=dict())
'/api/auth/logout',
headers=dict())
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == 'Provide a valid auth token.' assert data['message'] == 'Provide a valid auth token.'
@ -398,19 +413,15 @@ def test_user_profile_minimal(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/auth/profile', '/api/auth/profile',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -431,19 +442,15 @@ def test_user_profile_full(app, user_1_full):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/auth/profile', '/api/auth/profile',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -466,25 +473,25 @@ def test_user_profile_full(app, user_1_full):
def test_user_profile_with_activities( def test_user_profile_with_activities(
app, user_1, sport_1_cycling, sport_2_running, app,
activity_cycling_user_1, activity_running_user_1 user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_running_user_1,
): ):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/auth/profile', '/api/auth/profile',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -504,8 +511,8 @@ def test_user_profile_with_activities(
def test_invalid_profile(app): def test_invalid_profile(app):
client = app.test_client() client = app.test_client()
response = client.get( response = client.get(
'/api/auth/profile', '/api/auth/profile', headers=dict(Authorization='Bearer invalid')
headers=dict(Authorization='Bearer invalid')) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == 'Invalid token. Please log in again.' assert data['message'] == 'Invalid token. Please log in again.'
@ -516,30 +523,28 @@ def test_user_profile_valid_update(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/profile/edit', '/api/auth/profile/edit',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
first_name='John', dict(
last_name='Doe', first_name='John',
location='Somewhere', last_name='Doe',
bio='just a random guy', location='Somewhere',
birth_date='1980-01-01', bio='just a random guy',
password='87654321', birth_date='1980-01-01',
password_conf='87654321', password='87654321',
timezone='America/New_York' password_conf='87654321',
)), timezone='America/New_York',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -551,27 +556,25 @@ def test_user_profile_valid_update_without_password(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/profile/edit', '/api/auth/profile/edit',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
first_name='John', dict(
last_name='Doe', first_name='John',
location='Somewhere', last_name='Doe',
bio='just a random guy', location='Somewhere',
birth_date='1980-01-01' bio='just a random guy',
)), birth_date='1980-01-01',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -583,23 +586,17 @@ def test_user_profile_valid_update_with_one_field(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/profile/edit', '/api/auth/profile/edit',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(first_name='John')),
first_name='John'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -611,21 +608,17 @@ def test_user_profile_update_invalid_json(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/profile/edit', '/api/auth/profile/edit',
content_type='application/json', content_type='application/json',
data=json.dumps(dict()), data=json.dumps(dict()),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 400 assert response.status_code == 400
@ -637,34 +630,34 @@ def test_user_profile_invalid_password(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/profile/edit', '/api/auth/profile/edit',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
first_name='John', dict(
last_name='Doe', first_name='John',
location='Somewhere', last_name='Doe',
bio='just a random guy', location='Somewhere',
birth_date='1980-01-01', bio='just a random guy',
password='87654321', birth_date='1980-01-01',
password_conf='876543210', password='87654321',
timezone='America/New_York' password_conf='876543210',
)), timezone='America/New_York',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == 'Password and password confirmation don\'t match.\n' # noqa assert (
data['message'] == 'Password and password confirmation don\'t match.\n'
) # noqa
assert response.status_code == 400 assert response.status_code == 400
@ -672,33 +665,33 @@ def test_user_profile_missing_password_conf(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/profile/edit', '/api/auth/profile/edit',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(
first_name='John', dict(
last_name='Doe', first_name='John',
location='Somewhere', last_name='Doe',
bio='just a random guy', location='Somewhere',
birth_date='1980-01-01', bio='just a random guy',
password='87654321', birth_date='1980-01-01',
timezone='America/New_York' password='87654321',
)), timezone='America/New_York',
)
),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'error' assert data['status'] == 'error'
assert data['message'] == 'Password and password confirmation don\'t match.\n' # noqa assert (
data['message'] == 'Password and password confirmation don\'t match.\n'
) # noqa
assert response.status_code == 400 assert response.status_code == 400
@ -706,22 +699,17 @@ def test_update_user_picture(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/picture', '/api/auth/picture',
data=dict( data=dict(file=(BytesIO(b'avatar'), 'avatar.png')),
file=(BytesIO(b'avatar'), 'avatar.png')
),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
authorization='Bearer ' + authorization='Bearer '
json.loads(resp_login.data.decode())['auth_token'] + json.loads(resp_login.data.decode())['auth_token'],
) ),
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -731,14 +719,12 @@ def test_update_user_picture(app, user_1):
response = client.post( response = client.post(
'/api/auth/picture', '/api/auth/picture',
data=dict( data=dict(file=(BytesIO(b'avatar2'), 'avatar2.png')),
file=(BytesIO(b'avatar2'), 'avatar2.png')
),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
authorization='Bearer ' + authorization='Bearer '
json.loads(resp_login.data.decode())['auth_token'] + json.loads(resp_login.data.decode())['auth_token'],
) ),
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'success' assert data['status'] == 'success'
@ -752,19 +738,16 @@ def test_update_user_no_picture(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/picture', '/api/auth/picture',
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
authorization='Bearer ' + authorization='Bearer '
json.loads(resp_login.data.decode())['auth_token'] + json.loads(resp_login.data.decode())['auth_token'],
) ),
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'fail' assert data['status'] == 'fail'
@ -776,22 +759,17 @@ def test_update_user_invalid_picture(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/auth/picture', '/api/auth/picture',
data=dict( data=dict(file=(BytesIO(b'avatar'), 'avatar.bmp')),
file=(BytesIO(b'avatar'), 'avatar.bmp')
),
headers=dict( headers=dict(
content_type='multipart/form-data', content_type='multipart/form-data',
authorization='Bearer ' + authorization='Bearer '
json.loads(resp_login.data.decode())['auth_token'] + json.loads(resp_login.data.decode())['auth_token'],
) ),
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert data['status'] == 'fail' assert data['status'] == 'fail'

View File

@ -6,7 +6,8 @@ def test_development_config(app):
assert app.config['DEBUG'] assert app.config['DEBUG']
assert not app.config['TESTING'] assert not app.config['TESTING']
assert app.config['SQLALCHEMY_DATABASE_URI'] == os.environ.get( assert app.config['SQLALCHEMY_DATABASE_URI'] == os.environ.get(
'DATABASE_URL') 'DATABASE_URL'
)
def test_testing_config(app): def test_testing_config(app):
@ -15,4 +16,5 @@ def test_testing_config(app):
assert app.config['TESTING'] assert app.config['TESTING']
assert not app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] assert not app.config['PRESERVE_CONTEXT_ON_EXCEPTION']
assert app.config['SQLALCHEMY_DATABASE_URI'] == os.environ.get( assert app.config['SQLALCHEMY_DATABASE_URI'] == os.environ.get(
'DATABASE_TEST_URL') 'DATABASE_TEST_URL'
)

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,7 @@ import datetime
from fittrackee_api.activities.models import Record from fittrackee_api.activities.models import Record
def test_record_model( def test_record_model(app, user_1, sport_1_cycling, activity_cycling_user_1):
app, user_1, sport_1_cycling, activity_cycling_user_1
):
record_ld = Record.query.filter_by( record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id, sport_id=activity_cycling_user_1.sport_id,
@ -29,7 +27,7 @@ def test_record_model(
def test_record_model_none_value( def test_record_model_none_value(
app, user_1, sport_1_cycling, activity_cycling_user_1 app, user_1, sport_1_cycling, activity_cycling_user_1
): ):
record_ld = Record.query.filter_by( record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,
@ -49,9 +47,7 @@ def test_record_model_none_value(
assert record_serialize['value'] is None assert record_serialize['value'] is None
def test_add_as_records( def test_add_as_records(app, user_1, sport_1_cycling, activity_cycling_user_1):
app, user_1, sport_1_cycling, activity_cycling_user_1
):
record_as = Record.query.filter_by( record_as = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id, sport_id=activity_cycling_user_1.sport_id,
@ -67,9 +63,7 @@ def test_add_as_records(
assert isinstance(record_serialize.get('value'), float) assert isinstance(record_serialize.get('value'), float)
def test_add_fd_records( def test_add_fd_records(app, user_1, sport_1_cycling, activity_cycling_user_1):
app, user_1, sport_1_cycling, activity_cycling_user_1
):
record_fd = Record.query.filter_by( record_fd = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id, sport_id=activity_cycling_user_1.sport_id,
@ -85,9 +79,7 @@ def test_add_fd_records(
assert isinstance(record_serialize.get('value'), float) assert isinstance(record_serialize.get('value'), float)
def test_add_ld_records( def test_add_ld_records(app, user_1, sport_1_cycling, activity_cycling_user_1):
app, user_1, sport_1_cycling, activity_cycling_user_1
):
record_ld = Record.query.filter_by( record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,
sport_id=activity_cycling_user_1.sport_id, sport_id=activity_cycling_user_1.sport_id,
@ -104,7 +96,7 @@ def test_add_ld_records(
def test_add_ld_records_zero( def test_add_ld_records_zero(
app, user_1, sport_1_cycling, activity_cycling_user_1 app, user_1, sport_1_cycling, activity_cycling_user_1
): ):
record_ld = Record.query.filter_by( record_ld = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,
@ -123,7 +115,7 @@ def test_add_ld_records_zero(
def test_add_ms_records_no_value( def test_add_ms_records_no_value(
app, user_1, sport_1_cycling, activity_cycling_user_1 app, user_1, sport_1_cycling, activity_cycling_user_1
): ):
record_ms = Record.query.filter_by( record_ms = Record.query.filter_by(
user_id=activity_cycling_user_1.user_id, user_id=activity_cycling_user_1.user_id,

View File

@ -4,14 +4,14 @@ expected_sport_1_cycling_result = {
'id': 1, 'id': 1,
'label': 'Cycling', 'label': 'Cycling',
'img': None, 'img': None,
'_can_be_deleted': True '_can_be_deleted': True,
} }
expected_sport_2_running_result = { expected_sport_2_running_result = {
'id': 2, 'id': 2,
'label': 'Running', 'label': 'Running',
'img': None, 'img': None,
'_can_be_deleted': True '_can_be_deleted': True,
} }
@ -19,19 +19,15 @@ def test_get_all_sports(app, user_1, sport_1_cycling, sport_2_running):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/sports', '/api/sports',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -47,19 +43,15 @@ def test_get_a_sport(app, user_1, sport_1_cycling):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/sports/1', '/api/sports/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -74,19 +66,15 @@ def test_get_a_sport_invalid(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/sports/1', '/api/sports/1',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -99,23 +87,17 @@ def test_add_a_sport(app, user_1_admin):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/sports', '/api/sports',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(label='Cycling')),
label='Cycling'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -130,23 +112,17 @@ def test_add_a_sport_not_admin(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/sports', '/api/sports',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(label='surfing')),
label='surfing'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -160,21 +136,17 @@ def test_add_a_sport_invalid_payload(app, user_1_admin):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.post( response = client.post(
'/api/sports', '/api/sports',
content_type='application/json', content_type='application/json',
data=json.dumps(dict()), data=json.dumps(dict()),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -187,23 +159,17 @@ def test_update_a_sport(app, user_1_admin, sport_1_cycling):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(label='cycling updated')),
label='cycling updated'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -218,23 +184,17 @@ def test_update_a_sport_not_admin(app, user_1, sport_1_cycling):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(label='cycling updated')),
label='cycling updated'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -248,21 +208,17 @@ def test_update_a_sport_invalid_payload(app, user_1_admin):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict()), data=json.dumps(dict()),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -275,23 +231,17 @@ def test_update_a_sport_invalid_id(app, user_1_admin):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.patch( response = client.patch(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict( data=json.dumps(dict(label='cycling updated')),
label='cycling updated'
)),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -304,20 +254,16 @@ def test_delete_a_sport(app, user_1_admin, sport_1_cycling):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
assert response.status_code == 204 assert response.status_code == 204
@ -326,20 +272,16 @@ def test_delete_a_sport_not_admin(app, user_1, sport_1_cycling):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -352,21 +294,17 @@ def test_delete_a_sport_invalid_id(app, user_1_admin):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
data=json.dumps(dict()), data=json.dumps(dict()),
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -376,25 +314,21 @@ def test_delete_a_sport_invalid_id(app, user_1_admin):
def test_delete_a_sport_with_an_activity( def test_delete_a_sport_with_an_activity(
app, user_1_admin, sport_1_cycling, activity_cycling_user_1 app, user_1_admin, sport_1_cycling, activity_cycling_user_1
): ):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='admin@example.com', password='12345678')),
email='admin@example.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.delete( response = client.delete(
'/api/sports/1', '/api/sports/1',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())

View File

@ -10,7 +10,7 @@ def test_sport_model(app, sport_1_cycling):
def test_sport_model_with_activity( def test_sport_model_with_activity(
app, sport_1_cycling, user_1, activity_cycling_user_1 app, sport_1_cycling, user_1, activity_cycling_user_1
): ):
assert 1 == sport_1_cycling.id assert 1 == sport_1_cycling.id
assert 'Cycling' == sport_1_cycling.label assert 'Cycling' == sport_1_cycling.label

File diff suppressed because it is too large Load Diff

View File

@ -18,20 +18,16 @@ def test_single_user(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
f'/api/users/{user_1.id}', f'/api/users/{user_1.id}',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -55,27 +51,27 @@ def test_single_user(app, user_1):
def test_single_user_with_activities( def test_single_user_with_activities(
app, user_1, sport_1_cycling, sport_2_running, app,
activity_cycling_user_1, activity_running_user_1 user_1,
sport_1_cycling,
sport_2_running,
activity_cycling_user_1,
activity_running_user_1,
): ):
"""=> Get single user details""" """=> Get single user details"""
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
f'/api/users/{user_1.id}', f'/api/users/{user_1.id}',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -103,20 +99,16 @@ def test_single_user_no_id(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/users/blah', '/api/users/blah',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -130,20 +122,16 @@ def test_single_user_wrong_id(app, user_1):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/users/99999999999', '/api/users/99999999999',
content_type='application/json', content_type='application/json',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
@ -158,19 +146,15 @@ def test_users_list(app, user_1, user_2):
client = app.test_client() client = app.test_client()
resp_login = client.post( resp_login = client.post(
'/api/auth/login', '/api/auth/login',
data=json.dumps(dict( data=json.dumps(dict(email='test@test.com', password='12345678')),
email='test@test.com', content_type='application/json',
password='12345678'
)),
content_type='application/json'
) )
response = client.get( response = client.get(
'/api/users', '/api/users',
headers=dict( headers=dict(
Authorization='Bearer ' + json.loads( Authorization='Bearer '
resp_login.data.decode() + json.loads(resp_login.data.decode())['auth_token']
)['auth_token'] ),
)
) )
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())

View File

@ -80,14 +80,14 @@ def register_user():
return jsonify(response_object), 403 return jsonify(response_object), 403
# get post data # get post data
post_data = request.get_json() post_data = request.get_json()
if not post_data or post_data.get('username') is None \ if (
or post_data.get('email') is None \ not post_data
or post_data.get('password') is None \ or post_data.get('username') is None
or post_data.get('password_conf') is None: or post_data.get('email') is None
response_object = { or post_data.get('password') is None
'status': 'error', or post_data.get('password_conf') is None
'message': 'Invalid payload.' ):
} response_object = {'status': 'error', 'message': 'Invalid payload.'}
return jsonify(response_object), 400 return jsonify(response_object), 400
username = post_data.get('username') username = post_data.get('username')
email = post_data.get('email') email = post_data.get('email')
@ -102,27 +102,21 @@ def register_user():
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
if ret != '': if ret != '':
response_object = { response_object = {'status': 'error', 'message': 'Errors: ' + ret}
'status': 'error',
'message': 'Errors: ' + ret
}
return jsonify(response_object), 400 return jsonify(response_object), 400
try: try:
# check for existing user # check for existing user
user = User.query.filter( user = User.query.filter(
or_(User.username == username, User.email == email)).first() or_(User.username == username, User.email == email)
).first()
if not user: if not user:
# add new user to db # add new user to db
new_user = User( new_user = User(username=username, email=email, password=password)
username=username,
email=email,
password=password
)
new_user.timezone = 'Europe/Paris' new_user.timezone = 'Europe/Paris'
db.session.add(new_user) db.session.add(new_user)
db.session.commit() db.session.commit()
@ -131,13 +125,13 @@ def register_user():
response_object = { response_object = {
'status': 'success', 'status': 'success',
'message': 'Successfully registered.', 'message': 'Successfully registered.',
'auth_token': auth_token.decode() 'auth_token': auth_token.decode(),
} }
return jsonify(response_object), 201 return jsonify(response_object), 201
else: else:
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Sorry. That user already exists.' 'message': 'Sorry. That user already exists.',
} }
return jsonify(response_object), 400 return jsonify(response_object), 400
# handler errors # handler errors
@ -147,7 +141,7 @@ def register_user():
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
@ -202,10 +196,7 @@ def login_user():
# get post data # get post data
post_data = request.get_json() post_data = request.get_json()
if not post_data: if not post_data:
response_object = { response_object = {'status': 'error', 'message': 'Invalid payload.'}
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400 return jsonify(response_object), 400
email = post_data.get('email') email = post_data.get('email')
password = post_data.get('password') password = post_data.get('password')
@ -218,13 +209,13 @@ def login_user():
response_object = { response_object = {
'status': 'success', 'status': 'success',
'message': 'Successfully logged in.', 'message': 'Successfully logged in.',
'auth_token': auth_token.decode() 'auth_token': auth_token.decode(),
} }
return jsonify(response_object), 200 return jsonify(response_object), 200
else: else:
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Invalid credentials.' 'message': 'Invalid credentials.',
} }
return jsonify(response_object), 404 return jsonify(response_object), 404
# handler errors # handler errors
@ -233,7 +224,7 @@ def login_user():
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
@ -291,19 +282,16 @@ def logout_user(user_id):
if not isinstance(user_id, str): if not isinstance(user_id, str):
response_object = { response_object = {
'status': 'success', 'status': 'success',
'message': 'Successfully logged out.' 'message': 'Successfully logged out.',
} }
return jsonify(response_object), 200 return jsonify(response_object), 200
else: else:
response_object = { response_object = {'status': 'error', 'message': resp}
'status': 'error',
'message': resp
}
return jsonify(response_object), 401 return jsonify(response_object), 401
else: else:
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Provide a valid auth token.' 'message': 'Provide a valid auth token.',
} }
return jsonify(response_object), 401 return jsonify(response_object), 401
@ -360,10 +348,7 @@ def get_user_status(user_id):
""" """
user = User.query.filter_by(id=user_id).first() user = User.query.filter_by(id=user_id).first()
response_object = { response_object = {'status': 'success', 'data': user.serialize()}
'status': 'success',
'data': user.serialize()
}
return jsonify(response_object), 200 return jsonify(response_object), 200
@ -434,10 +419,7 @@ def edit_user(user_id):
# get post data # get post data
post_data = request.get_json() post_data = request.get_json()
if not post_data: if not post_data:
response_object = { response_object = {'status': 'error', 'message': 'Invalid payload.'}
'status': 'error',
'message': 'Invalid payload.'
}
return jsonify(response_object), 400 return jsonify(response_object), 400
first_name = post_data.get('first_name') first_name = post_data.get('first_name')
last_name = post_data.get('last_name') last_name = post_data.get('last_name')
@ -452,7 +434,7 @@ def edit_user(user_id):
if password_conf != password: if password_conf != password:
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Password and password confirmation don\'t match.\n' 'message': 'Password and password confirmation don\'t match.\n',
} }
return jsonify(response_object), 400 return jsonify(response_object), 400
else: else:
@ -478,7 +460,7 @@ def edit_user(user_id):
response_object = { response_object = {
'status': 'success', 'status': 'success',
'message': 'User profile updated.' 'message': 'User profile updated.',
} }
return jsonify(response_object), 200 return jsonify(response_object), 200
@ -488,7 +470,7 @@ def edit_user(user_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Error. Please try again or contact the administrator.' 'message': 'Error. Please try again or contact the administrator.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
@ -560,18 +542,12 @@ def edit_picture(user_id):
file = request.files['file'] file = request.files['file']
filename = secure_filename(file.filename) filename = secure_filename(file.filename)
dirpath = os.path.join( dirpath = os.path.join(
current_app.config['UPLOAD_FOLDER'], current_app.config['UPLOAD_FOLDER'], 'pictures', str(user_id)
'pictures',
str(user_id)
) )
if not os.path.exists(dirpath): if not os.path.exists(dirpath):
os.makedirs(dirpath) os.makedirs(dirpath)
absolute_picture_path = os.path.join(dirpath, filename) absolute_picture_path = os.path.join(dirpath, filename)
relative_picture_path = os.path.join( relative_picture_path = os.path.join('pictures', str(user_id), filename)
'pictures',
str(user_id),
filename
)
try: try:
user = User.query.filter_by(id=user_id).first() user = User.query.filter_by(id=user_id).first()
@ -585,7 +561,7 @@ def edit_picture(user_id):
response_object = { response_object = {
'status': 'success', 'status': 'success',
'message': 'User picture updated.' 'message': 'User picture updated.',
} }
return jsonify(response_object), 200 return jsonify(response_object), 200
@ -594,7 +570,7 @@ def edit_picture(user_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'Error during picture update.' 'message': 'Error during picture update.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500
@ -637,9 +613,7 @@ def del_picture(user_id):
user.picture = None user.picture = None
db.session.commit() db.session.commit()
response_object = { response_object = {'status': 'no content'}
'status': 'no content'
}
return jsonify(response_object), 204 return jsonify(response_object), 204
except (exc.IntegrityError, ValueError) as e: except (exc.IntegrityError, ValueError) as e:
@ -647,6 +621,6 @@ def del_picture(user_id):
appLog.error(e) appLog.error(e)
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'Error during picture deletion.' 'message': 'Error during picture deletion.',
} }
return jsonify(response_object), 500 return jsonify(response_object), 500

View File

@ -23,19 +23,19 @@ class User(db.Model):
bio = db.Column(db.String(200), nullable=True) bio = db.Column(db.String(200), nullable=True)
picture = db.Column(db.String(255), nullable=True) picture = db.Column(db.String(255), nullable=True)
timezone = db.Column(db.String(50), nullable=True) timezone = db.Column(db.String(50), nullable=True)
activities = db.relationship('Activity', activities = db.relationship(
lazy=True, 'Activity', lazy=True, backref=db.backref('users', lazy='joined')
backref=db.backref('users', lazy='joined')) )
records = db.relationship('Record', records = db.relationship(
lazy=True, 'Record', lazy=True, backref=db.backref('users', lazy='joined')
backref=db.backref('users', lazy='joined')) )
def __repr__(self): def __repr__(self):
return f'<User {self.username!r}>' return f'<User {self.username!r}>'
def __init__( def __init__(
self, username, email, password, self, username, email, password, created_at=datetime.datetime.utcnow()
created_at=datetime.datetime.utcnow()): ):
self.username = username self.username = username
self.email = email self.email = email
self.password = bcrypt.generate_password_hash( self.password = bcrypt.generate_password_hash(
@ -52,17 +52,18 @@ class User(db.Model):
""" """
try: try:
payload = { payload = {
'exp': datetime.datetime.utcnow() + datetime.timedelta( 'exp': datetime.datetime.utcnow()
+ datetime.timedelta(
days=current_app.config.get('TOKEN_EXPIRATION_DAYS'), days=current_app.config.get('TOKEN_EXPIRATION_DAYS'),
seconds=current_app.config.get('TOKEN_EXPIRATION_SECONDS') seconds=current_app.config.get('TOKEN_EXPIRATION_SECONDS'),
), ),
'iat': datetime.datetime.utcnow(), 'iat': datetime.datetime.utcnow(),
'sub': user_id 'sub': user_id,
} }
return jwt.encode( return jwt.encode(
payload, payload,
current_app.config.get('SECRET_KEY'), current_app.config.get('SECRET_KEY'),
algorithm='HS256' algorithm='HS256',
) )
except Exception as e: except Exception as e:
return e return e
@ -76,8 +77,8 @@ class User(db.Model):
""" """
try: try:
payload = jwt.decode( payload = jwt.decode(
auth_token, auth_token, current_app.config.get('SECRET_KEY')
current_app.config.get('SECRET_KEY')) )
return payload['sub'] return payload['sub']
except jwt.ExpiredSignatureError: except jwt.ExpiredSignatureError:
return 'Signature expired. Please log in again.' return 'Signature expired. Please log in again.'
@ -91,14 +92,13 @@ class User(db.Model):
sports = [] sports = []
total = (None, None) total = (None, None)
if nb_activity > 0: if nb_activity > 0:
sports = db.session.query( sports = (
func.count(Activity.sport_id) db.session.query(func.count(Activity.sport_id))
).group_by( .group_by(Activity.sport_id)
Activity.sport_id .all()
).all() )
total = db.session.query( total = db.session.query(
func.sum(Activity.distance), func.sum(Activity.distance), func.sum(Activity.duration)
func.sum(Activity.duration)
).first() ).first()
return { return {
'id': self.id, 'id': self.id,

View File

@ -85,9 +85,7 @@ def get_users(auth_user_id):
users = User.query.all() users = User.query.all()
response_object = { response_object = {
'status': 'success', 'status': 'success',
'data': { 'data': {'users': [user.serialize() for user in users]},
'users': [user.serialize() for user in users]
}
} }
return jsonify(response_object), 200 return jsonify(response_object), 200
@ -148,19 +146,13 @@ def get_single_user(auth_user_id, user_id):
- User does not exist - User does not exist
""" """
response_object = { response_object = {'status': 'fail', 'message': 'User does not exist.'}
'status': 'fail',
'message': 'User does not exist.'
}
try: try:
user = User.query.filter_by(id=int(user_id)).first() user = User.query.filter_by(id=int(user_id)).first()
if not user: if not user:
return jsonify(response_object), 404 return jsonify(response_object), 404
else: else:
response_object = { response_object = {'status': 'success', 'data': user.serialize()}
'status': 'success',
'data': user.serialize()
}
return jsonify(response_object), 200 return jsonify(response_object), 200
except ValueError: except ValueError:
return jsonify(response_object), 404 return jsonify(response_object), 404
@ -192,16 +184,13 @@ def get_picture(user_id):
- No picture. - No picture.
""" """
response_object = { response_object = {'status': 'not found', 'message': 'No picture.'}
'status': 'not found',
'message': 'No picture.'
}
try: try:
user = User.query.filter_by(id=int(user_id)).first() user = User.query.filter_by(id=int(user_id)).first()
if not user: if not user:
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'User does not exist.' 'message': 'User does not exist.',
} }
return jsonify(response_object), 404 return jsonify(response_object), 404
if user.picture is not None: if user.picture is not None:
@ -238,7 +227,4 @@ def ping_pong():
:statuscode 200: success :statuscode 200: success
""" """
return jsonify({ return jsonify({'status': 'success', 'message': 'pong!'})
'status': 'success',
'message': 'pong!'
})

View File

@ -47,12 +47,14 @@ def verify_extension(file_type, req):
else 'PICTURE_ALLOWED_EXTENSIONS' else 'PICTURE_ALLOWED_EXTENSIONS'
) )
if not ('.' in file.filename and if not (
file.filename.rsplit('.', 1)[1].lower() in '.' in file.filename
current_app.config.get(allowed_extensions)): and file.filename.rsplit('.', 1)[1].lower()
in current_app.config.get(allowed_extensions)
):
response_object = { response_object = {
'status': 'fail', 'status': 'fail',
'message': 'File extension not allowed.' 'message': 'File extension not allowed.',
} }
return response_object return response_object
@ -61,7 +63,7 @@ def verify_extension(file_type, req):
def verify_user(current_request, verify_admin): def verify_user(current_request, verify_admin):
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'Something went wrong. Please contact us.' 'message': 'Something went wrong. Please contact us.',
} }
code = 401 code = 401
auth_header = current_request.headers.get('Authorization') auth_header = current_request.headers.get('Authorization')
@ -110,7 +112,7 @@ def can_view_activity(auth_user_id, activity_user_id):
if auth_user_id != activity_user_id: if auth_user_id != activity_user_id:
response_object = { response_object = {
'status': 'error', 'status': 'error',
'message': 'You do not have permissions.' 'message': 'You do not have permissions.',
} }
return response_object, 403 return response_object, 403
return None, None return None, None

View File

@ -24,9 +24,8 @@ def drop_db():
def initdata(): def initdata():
"""Init the database.""" """Init the database."""
admin = User( admin = User(
username='admin', username='admin', email='admin@example.com', password='mpwoadmin'
email='admin@example.com', )
password='mpwoadmin')
admin.admin = True admin.admin = True
admin.timezone = 'Europe/Paris' admin.timezone = 'Europe/Paris'
db.session.add(admin) db.session.add(admin)
@ -61,9 +60,11 @@ def initdata():
@app.cli.command() @app.cli.command()
def recalculate(): def recalculate():
print("Starting activities data refresh") print("Starting activities data refresh")
activities = Activity.query.filter(Activity.gpx != None).order_by( # noqa activities = (
Activity.activity_date.asc() Activity.query.filter(Activity.gpx != None)
).all() .order_by(Activity.activity_date.asc()) # noqa
.all()
)
if len(activities) == 0: if len(activities) == 0:
print('➡️ no activities to upgrade.') print('➡️ no activities to upgrade.')
return None return None