API - replace 'Activity' with 'Workout' - #58
This commit is contained in:
346
fittrackee/workouts/sports.py
Normal file
346
fittrackee/workouts/sports.py
Normal file
@@ -0,0 +1,346 @@
|
||||
from typing import Dict, Union
|
||||
|
||||
from fittrackee import db
|
||||
from fittrackee.responses import (
|
||||
DataNotFoundErrorResponse,
|
||||
HttpResponse,
|
||||
InvalidPayloadErrorResponse,
|
||||
handle_error_and_return_response,
|
||||
)
|
||||
from flask import Blueprint, request
|
||||
from sqlalchemy import exc
|
||||
|
||||
from ..users.models import User
|
||||
from ..users.utils import authenticate, authenticate_as_admin
|
||||
from .models import Sport
|
||||
|
||||
sports_blueprint = Blueprint('sports', __name__)
|
||||
|
||||
|
||||
@sports_blueprint.route('/sports', methods=['GET'])
|
||||
@authenticate
|
||||
def get_sports(auth_user_id: int) -> Dict:
|
||||
"""
|
||||
Get all sports
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/sports HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
- for non admin user :
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": [
|
||||
{
|
||||
"id": 1,
|
||||
"img": "/img/sports/cycling-sport.png",
|
||||
"is_active": true,
|
||||
"label": "Cycling (Sport)"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"img": "/img/sports/cycling-transport.png",
|
||||
"is_active": true,
|
||||
"label": "Cycling (Transport)"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"img": "/img/sports/hiking.png",
|
||||
"is_active": true,
|
||||
"label": "Hiking"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"img": "/img/sports/mountain-biking.png",
|
||||
"is_active": true,
|
||||
"label": "Mountain Biking"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"img": "/img/sports/running.png",
|
||||
"is_active": true,
|
||||
"label": "Running"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"img": "/img/sports/walking.png",
|
||||
"is_active": true,
|
||||
"label": "Walking"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
- for admin user :
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": [
|
||||
{
|
||||
"has_workouts": true,
|
||||
"id": 1,
|
||||
"img": "/img/sports/cycling-sport.png",
|
||||
"is_active": true,
|
||||
"label": "Cycling (Sport)"
|
||||
},
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 2,
|
||||
"img": "/img/sports/cycling-transport.png",
|
||||
"is_active": true,
|
||||
"label": "Cycling (Transport)"
|
||||
},
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 3,
|
||||
"img": "/img/sports/hiking.png",
|
||||
"is_active": true,
|
||||
"label": "Hiking"
|
||||
},
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 4,
|
||||
"img": "/img/sports/mountain-biking.png",
|
||||
"is_active": true,
|
||||
"label": "Mountain Biking"
|
||||
},
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 5,
|
||||
"img": "/img/sports/running.png",
|
||||
"is_active": true,
|
||||
"label": "Running"
|
||||
},
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 6,
|
||||
"img": "/img/sports/walking.png",
|
||||
"is_active": true,
|
||||
"label": "Walking"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
:param integer auth_user_id: authenticate user id (from JSON Web Token)
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
|
||||
:statuscode 200: success
|
||||
:statuscode 401:
|
||||
- Provide a valid auth token.
|
||||
- Signature expired. Please log in again.
|
||||
- Invalid token. Please log in again.
|
||||
|
||||
"""
|
||||
user = User.query.filter_by(id=int(auth_user_id)).first()
|
||||
sports = Sport.query.order_by(Sport.id).all()
|
||||
return {
|
||||
'status': 'success',
|
||||
'data': {'sports': [sport.serialize(user.admin) for sport in sports]},
|
||||
}
|
||||
|
||||
|
||||
@sports_blueprint.route('/sports/<int:sport_id>', methods=['GET'])
|
||||
@authenticate
|
||||
def get_sport(auth_user_id: int, sport_id: int) -> Union[Dict, HttpResponse]:
|
||||
"""
|
||||
Get a sport
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/sports/1 HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
- success for non admin user :
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": [
|
||||
{
|
||||
"id": 1,
|
||||
"img": "/img/sports/cycling-sport.png",
|
||||
"is_active": true,
|
||||
"label": "Cycling (Sport)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
- success for admin user :
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": [
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 1,
|
||||
"img": "/img/sports/cycling-sport.png",
|
||||
"is_active": true,
|
||||
"label": "Cycling (Sport)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
- sport not found
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 404 NOT FOUND
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": []
|
||||
},
|
||||
"status": "not found"
|
||||
}
|
||||
|
||||
:param integer auth_user_id: authenticate user id (from JSON Web Token)
|
||||
:param integer sport_id: sport id
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
|
||||
:statuscode 200: success
|
||||
:statuscode 401:
|
||||
- Provide a valid auth token.
|
||||
- Signature expired. Please log in again.
|
||||
- Invalid token. Please log in again.
|
||||
:statuscode 404: sport not found
|
||||
|
||||
"""
|
||||
user = User.query.filter_by(id=int(auth_user_id)).first()
|
||||
sport = Sport.query.filter_by(id=sport_id).first()
|
||||
if sport:
|
||||
return {
|
||||
'status': 'success',
|
||||
'data': {'sports': [sport.serialize(user.admin)]},
|
||||
}
|
||||
return DataNotFoundErrorResponse('sports')
|
||||
|
||||
|
||||
@sports_blueprint.route('/sports/<int:sport_id>', methods=['PATCH'])
|
||||
@authenticate_as_admin
|
||||
def update_sport(
|
||||
auth_user_id: int, sport_id: int
|
||||
) -> Union[Dict, HttpResponse]:
|
||||
"""
|
||||
Update a sport
|
||||
Authenticated user must be an admin
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/sports/1 HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
**Example response**:
|
||||
|
||||
- success
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": [
|
||||
{
|
||||
"has_workouts": false,
|
||||
"id": 1,
|
||||
"img": "/img/sports/cycling-sport.png",
|
||||
"is_active": false,
|
||||
"label": "Cycling (Sport)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
- sport not found
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 404 NOT FOUND
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"data": {
|
||||
"sports": []
|
||||
},
|
||||
"status": "not found"
|
||||
}
|
||||
|
||||
:param integer auth_user_id: authenticate user id (from JSON Web Token)
|
||||
:param integer sport_id: sport id
|
||||
|
||||
:<json string is_active: sport active status
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
|
||||
:statuscode 200: sport updated
|
||||
:statuscode 400: invalid payload
|
||||
:statuscode 401:
|
||||
- Provide a valid auth token.
|
||||
- Signature expired. Please log in again.
|
||||
- Invalid token. Please log in again.
|
||||
:statuscode 403: You do not have permissions.
|
||||
:statuscode 404: sport not found
|
||||
:statuscode 500:
|
||||
|
||||
"""
|
||||
sport_data = request.get_json()
|
||||
if not sport_data or sport_data.get('is_active') is None:
|
||||
return InvalidPayloadErrorResponse()
|
||||
|
||||
try:
|
||||
sport = Sport.query.filter_by(id=sport_id).first()
|
||||
if not sport:
|
||||
return DataNotFoundErrorResponse('sports')
|
||||
|
||||
sport.is_active = sport_data.get('is_active')
|
||||
db.session.commit()
|
||||
return {
|
||||
'status': 'success',
|
||||
'data': {'sports': [sport.serialize(True)]},
|
||||
}
|
||||
|
||||
except (exc.IntegrityError, exc.OperationalError, ValueError) as e:
|
||||
return handle_error_and_return_response(e, db=db)
|
||||
Reference in New Issue
Block a user