API - add endpoint to reset sport preferences - #123

This commit is contained in:
Sam 2021-12-19 11:51:28 +01:00
parent c0f9dc8fdf
commit 91e7127a09
2 changed files with 117 additions and 3 deletions

View File

@ -7,7 +7,7 @@ import pytest
from flask import Flask from flask import Flask
from freezegun import freeze_time from freezegun import freeze_time
from fittrackee.users.models import User from fittrackee.users.models import User, UserSportPreference
from fittrackee.users.utils_token import get_user_token from fittrackee.users.utils_token import get_user_token
from fittrackee.workouts.models import Sport, Workout from fittrackee.workouts.models import Sport, Workout
@ -887,6 +887,7 @@ class TestUserSportPreferencesUpdate(ApiTestCaseMixin):
data = json.loads(response.data.decode()) data = json.loads(response.data.decode())
assert response.status_code == 404 assert response.status_code == 404
assert 'not found' in data['status'] assert 'not found' in data['status']
assert 'sport does not exist' in data['message']
def test_it_returns_error_if_payload_contains_only_sport_id( def test_it_returns_error_if_payload_contains_only_sport_id(
self, app: Flask, user_1: User, sport_1_cycling: Sport self, app: Flask, user_1: User, sport_1_cycling: Sport
@ -1017,6 +1018,60 @@ class TestUserSportPreferencesUpdate(ApiTestCaseMixin):
assert data['data']['stopped_speed_threshold'] == 0.5 assert data['data']['stopped_speed_threshold'] == 0.5
class TestUserSportPreferencesReset(ApiTestCaseMixin):
def test_it_returns_error_if_sport_does_not_exist(
self, app: Flask, user_1: User
) -> None:
client, auth_token = self.get_test_client_and_auth_token(app)
response = client.delete(
'/api/auth/profile/reset/sports/1',
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 404
data = json.loads(response.data.decode())
assert 'not found' in data['status']
assert 'sport does not exist' in data['message']
def test_it_resets_sport_preferences(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
user_sport_1_preference: UserSportPreference,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(app)
user_sport_1_preference.is_active = False
user_sport_1_preference.stopped_speed_threshold = 0.5
response = client.delete(
f'/api/auth/profile/reset/sports/{sport_1_cycling.id}',
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 204
assert (
UserSportPreference.query.filter_by(
user_id=user_1.id,
sport_id=sport_1_cycling.id,
).first()
is None
)
def test_it_does_not_raise_error_if_sport_preferences_do_not_exist(
self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None:
client, auth_token = self.get_test_client_and_auth_token(app)
response = client.delete(
f'/api/auth/profile/reset/sports/{sport_1_cycling.id}',
headers=dict(Authorization=f'Bearer {auth_token}'),
)
assert response.status_code == 204
class TestUserPicture(ApiTestCaseMixin): class TestUserPicture(ApiTestCaseMixin):
def test_it_updates_user_picture(self, app: Flask, user_1: User) -> None: def test_it_updates_user_picture(self, app: Flask, user_1: User) -> None:
client, auth_token = self.get_test_client_and_auth_token(app) client, auth_token = self.get_test_client_and_auth_token(app)

View File

@ -11,10 +11,10 @@ from werkzeug.utils import secure_filename
from fittrackee import appLog, bcrypt, db from fittrackee import appLog, bcrypt, db
from fittrackee.responses import ( from fittrackee.responses import (
DataNotFoundErrorResponse,
ForbiddenErrorResponse, ForbiddenErrorResponse,
HttpResponse, HttpResponse,
InvalidPayloadErrorResponse, InvalidPayloadErrorResponse,
NotFoundErrorResponse,
PayloadTooLargeErrorResponse, PayloadTooLargeErrorResponse,
UnauthorizedErrorResponse, UnauthorizedErrorResponse,
handle_error_and_return_response, handle_error_and_return_response,
@ -733,6 +733,8 @@ def edit_user_sport_preferences(
- provide a valid auth token - provide a valid auth token
- signature expired, please log in again - signature expired, please log in again
- invalid token, please log in again - invalid token, please log in again
:statuscode 404:
- sport does not exist
:statuscode 500: error, please try again or contact the administrator :statuscode 500: error, please try again or contact the administrator
""" """
@ -747,7 +749,7 @@ def edit_user_sport_preferences(
sport_id = post_data.get('sport_id') sport_id = post_data.get('sport_id')
sport = Sport.query.filter_by(id=sport_id).first() sport = Sport.query.filter_by(id=sport_id).first()
if not sport: if not sport:
return DataNotFoundErrorResponse('sports') return NotFoundErrorResponse('sport does not exist')
color = post_data.get('color') color = post_data.get('color')
is_active = post_data.get('is_active') is_active = post_data.get('is_active')
@ -787,6 +789,63 @@ def edit_user_sport_preferences(
return handle_error_and_return_response(e, db=db) return handle_error_and_return_response(e, db=db)
@auth_blueprint.route(
'/auth/profile/reset/sports/<sport_id>', methods=['DELETE']
)
@authenticate
def reset_user_sport_preferences(
auth_user: User, sport_id: int
) -> Union[Tuple[Dict, int], HttpResponse]:
"""
reset authenticated user preferences for a given sport
**Example request**:
.. sourcecode:: http
DELETE /api/auth/profile/reset/sports/1 HTTP/1.1
Content-Type: application/json
**Example response**:
.. sourcecode:: http
HTTP/1.1 204 OK
Content-Type: application/json
:param string sport_id: sport id
:reqheader Authorization: OAuth 2.0 Bearer Token
:statuscode 204: user preferences deleted
:statuscode 401:
- provide a valid auth token
- signature expired, please log in again
- invalid token, please log in again
:statuscode 404:
- sport does not exist
:statuscode 500: error, please try again or contact the administrator
"""
sport = Sport.query.filter_by(id=sport_id).first()
if not sport:
return NotFoundErrorResponse('sport does not exist')
try:
user_sport = UserSportPreference.query.filter_by(
user_id=auth_user.id,
sport_id=sport_id,
).first()
if user_sport:
db.session.delete(user_sport)
db.session.commit()
return {'status': 'no content'}, 204
# handler errors
except (exc.IntegrityError, exc.OperationalError) as e:
return handle_error_and_return_response(e, db=db)
@auth_blueprint.route('/auth/picture', methods=['POST']) @auth_blueprint.route('/auth/picture', methods=['POST'])
@authenticate @authenticate
def edit_picture(auth_user: User) -> Union[Dict, HttpResponse]: def edit_picture(auth_user: User) -> Union[Dict, HttpResponse]: