mirror of
https://github.com/joaovitoriasilva/endurain.git
synced 2026-01-10 08:17:59 -05:00
Finished backend structure migration
[backend] finished backend structure migration [backend] logic to edit activity added [backend] added 404 error if user or activity not found on edit logic
This commit is contained in:
@@ -497,6 +497,49 @@ def create_activity(activity: activities_schema.Activity, db: Session):
|
||||
) from err
|
||||
|
||||
|
||||
def edit_activity(user_id: int, activity: activities_schema.ActivityEdit, db: Session):
|
||||
try:
|
||||
# Get the activity from the database
|
||||
db_activity = (
|
||||
db.query(models.Activity)
|
||||
.filter(
|
||||
models.Activity.user_id == user_id,
|
||||
models.Activity.id == activity.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if db_activity is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Activity not found",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# Update the activity
|
||||
if activity.description is not None:
|
||||
db_activity.description = activity.description
|
||||
if activity.name is not None:
|
||||
db_activity.name = activity.name
|
||||
if activity.visibility is not None:
|
||||
db_activity.visibility = activity.visibility
|
||||
|
||||
# Commit the transaction
|
||||
db.commit()
|
||||
except Exception as err:
|
||||
# Rollback the transaction
|
||||
db.rollback()
|
||||
|
||||
# Log the exception
|
||||
logger.error(f"Error in edit_activity: {err}", exc_info=True)
|
||||
|
||||
# Raise an HTTPException with a 500 Internal Server Error status code
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Internal Server Error",
|
||||
) from err
|
||||
|
||||
|
||||
def add_gear_to_activity(activity_id: int, gear_id: int, db: Session):
|
||||
try:
|
||||
# Get the activity from the database
|
||||
|
||||
@@ -24,11 +24,11 @@ import activity_streams.crud as activity_streams_crud
|
||||
|
||||
import gpx.utils as gpx_utils
|
||||
|
||||
import fit.utils as fit_utils
|
||||
|
||||
import database
|
||||
import dependencies_global
|
||||
|
||||
from processors import fit_processor
|
||||
|
||||
# Define the API router
|
||||
router = APIRouter()
|
||||
|
||||
@@ -51,7 +51,7 @@ async def read_activities_useractivities_week(
|
||||
Callable, Security(session_security.check_scopes, scopes=["activities:read"])
|
||||
],
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -95,7 +95,7 @@ async def read_activities_useractivities_thisweek_distances(
|
||||
Callable, Security(session_security.check_scopes, scopes=["activities:read"])
|
||||
],
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -141,7 +141,7 @@ async def read_activities_useractivities_thismonth_distances(
|
||||
Callable, Security(session_security.check_scopes, scopes=["activities:read"])
|
||||
],
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -373,7 +373,7 @@ async def read_activities_activity_from_id(
|
||||
Callable, Security(session_security.check_scopes, scopes=["activities:read"])
|
||||
],
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -397,7 +397,7 @@ async def read_activities_contain_name(
|
||||
Callable, Security(session_security.check_scopes, scopes=["activities:read"])
|
||||
],
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -416,7 +416,7 @@ async def read_activities_contain_name(
|
||||
)
|
||||
async def create_activity_with_uploaded_file(
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
file: UploadFile,
|
||||
@@ -446,7 +446,7 @@ async def create_activity_with_uploaded_file(
|
||||
parsed_info = gpx_utils.parse_gpx_file(file.filename, token_user_id)
|
||||
elif file_extension.lower() == ".fit":
|
||||
# Parse the FIT file
|
||||
parsed_info = fit_processor.parse_fit_file(file.filename, token_user_id)
|
||||
parsed_info = fit_utils.parse_fit_file(file.filename, token_user_id)
|
||||
else:
|
||||
# file extension not supported raise an HTTPException with a 406 Not Acceptable status code
|
||||
raise HTTPException(
|
||||
@@ -490,6 +490,30 @@ async def create_activity_with_uploaded_file(
|
||||
) from err
|
||||
|
||||
|
||||
@router.put(
|
||||
"/edit",
|
||||
)
|
||||
async def edit_activity(
|
||||
token_user_id: Annotated[
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
activity_attributes: activities_schema.ActivityEdit,
|
||||
check_scopes: Annotated[
|
||||
Callable, Security(session_security.check_scopes, scopes=["activities:write"])
|
||||
],
|
||||
db: Annotated[
|
||||
Session,
|
||||
Depends(database.get_db),
|
||||
],
|
||||
):
|
||||
# Update the activity in the database
|
||||
activities_crud.edit_activity(token_user_id, activity_attributes, db)
|
||||
|
||||
# Return success message
|
||||
return {f"Activity ID {activity_attributes.id} updated successfully"}
|
||||
|
||||
|
||||
@router.put(
|
||||
"/{activity_id}/addgear/{gear_id}",
|
||||
)
|
||||
|
||||
@@ -32,4 +32,11 @@ class Activity(BaseModel):
|
||||
class ActivityDistances(BaseModel):
|
||||
swim: float
|
||||
bike: float
|
||||
run: float
|
||||
run: float
|
||||
|
||||
|
||||
class ActivityEdit(BaseModel):
|
||||
id: int
|
||||
description: str | None = None
|
||||
name: str
|
||||
visibility: int | None = None
|
||||
@@ -1,174 +0,0 @@
|
||||
from fastapi import Depends, HTTPException, status, Request, Security
|
||||
from fastapi.security import OAuth2PasswordBearer, SecurityScopes
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from session import dependencies_security
|
||||
|
||||
import users.schema as users_schema
|
||||
|
||||
import database
|
||||
|
||||
# Define the OAuth2 scheme for handling bearer tokens
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||
|
||||
|
||||
### Dependencies for access token validation
|
||||
|
||||
|
||||
def validate_access_token(request: Request):
|
||||
# Extract the access token from the cookies
|
||||
access_token = request.cookies.get("endurain_access_token")
|
||||
if not access_token:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Access token missing",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# Validate the token expiration
|
||||
dependencies_security.validate_token_expiration(access_token)
|
||||
|
||||
|
||||
def validate_token_and_return_access_token(request: Request):
|
||||
# Extract the access token from the cookies
|
||||
access_token = request.cookies.get("endurain_access_token")
|
||||
if not access_token:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Access token missing",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# Validate the token expiration
|
||||
dependencies_security.validate_token_expiration(access_token)
|
||||
|
||||
# Return token
|
||||
return access_token
|
||||
|
||||
|
||||
def validate_access_token_and_get_authenticated_user_id(
|
||||
access_token: Annotated[str, Depends(validate_token_and_return_access_token)],
|
||||
):
|
||||
# Return the user ID associated with the token
|
||||
return dependencies_security.get_token_user_id(access_token)
|
||||
|
||||
|
||||
def validate_access_token_and_validate_admin_access(
|
||||
access_token: Annotated[str, Depends(validate_token_and_return_access_token)],
|
||||
):
|
||||
# Check if the token has admin access
|
||||
dependencies_security.validate_token_admin_access(access_token)
|
||||
|
||||
|
||||
### Dependencies for refresh token validation
|
||||
|
||||
|
||||
def validate_token_and_return_refresh_token(request: Request):
|
||||
# Extract the refresh token from the cookies
|
||||
refresh_token = request.cookies.get("endurain_refresh_token")
|
||||
if not refresh_token:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="Refresh token missing",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# Validate the token expiration
|
||||
dependencies_security.validate_token_expiration(refresh_token)
|
||||
|
||||
# Return token
|
||||
return refresh_token
|
||||
|
||||
|
||||
def validate_refresh_token_and_get_authenticated_user_id(
|
||||
refresh_token: Annotated[str, Depends(validate_token_and_return_refresh_token)]
|
||||
):
|
||||
# Return the user ID associated with the token
|
||||
return dependencies_security.get_token_user_id(refresh_token)
|
||||
|
||||
|
||||
def validate_token_and_validate_admin_access(
|
||||
token: str = Depends(oauth2_scheme),
|
||||
db: Session = Depends(database.get_db),
|
||||
):
|
||||
# Validate the token expiration
|
||||
dependencies_security.validate_token_expiration(token)
|
||||
|
||||
# Check if the token has admin access
|
||||
dependencies_security.validate_token_admin_access(token)
|
||||
|
||||
|
||||
def validate_token_and_if_user_id_equals_token_user_id_if_not_validate_admin_access(
|
||||
user_id: int | None,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
db: Session = Depends(database.get_db),
|
||||
):
|
||||
# Validate the token expiration
|
||||
dependencies_security.validate_token_expiration(token)
|
||||
|
||||
# Check if user_id higher than 0
|
||||
if not (int(user_id) > 0):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Invalid user ID",
|
||||
)
|
||||
|
||||
# Check if token id is different from user id. If yes, check if the token has admin access
|
||||
if user_id != dependencies_security.get_token_user_id(token):
|
||||
# Check if the token has admin access
|
||||
dependencies_security.validate_token_admin_access(token)
|
||||
|
||||
|
||||
def validate_token_and_if_user_id_equals_token_user_attributtes_id_if_not_validate_admin_access(
|
||||
user_attributtes: users_schema.User,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
db: Session = Depends(database.get_db),
|
||||
):
|
||||
validate_token_user_id_admin_access(db, token, user_attributtes.id)
|
||||
|
||||
|
||||
def validate_token_and_if_user_id_equals_token_user_attributtes_password_id_if_not_validate_admin_access(
|
||||
user_attributtes: users_schema.UserEditPassword,
|
||||
token: str = Depends(oauth2_scheme),
|
||||
db: Session = Depends(database.get_db),
|
||||
):
|
||||
validate_token_user_id_admin_access(db, token, user_attributtes.id)
|
||||
|
||||
|
||||
def validate_token_user_id_admin_access(db, token, user_id):
|
||||
# Validate the token expiration
|
||||
dependencies_security.validate_token_expiration(token)
|
||||
|
||||
# Check if user_id higher than 0
|
||||
if not (int(user_id) > 0):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="Invalid user ID",
|
||||
)
|
||||
|
||||
# Check if token id is different from user id. If yes, check if the token has admin access
|
||||
if user_id != dependencies_security.get_token_user_id(token):
|
||||
# Check if the token has admin access
|
||||
dependencies_security.validate_token_admin_access(token)
|
||||
|
||||
|
||||
def check_scopes(
|
||||
security_scopes: SecurityScopes,
|
||||
# scopes: Annotated[list[str], Depends(dependencies_security.get_token_scopes)],
|
||||
access_token: Annotated[str, Depends(validate_token_and_return_access_token)],
|
||||
):
|
||||
# Get the scopes from the token
|
||||
scopes = dependencies_security.get_token_scopes(access_token)
|
||||
|
||||
# Check if the token has the required scopes
|
||||
for scope in security_scopes.scopes:
|
||||
if scope not in scopes:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail=f"Unauthorized Access - Not enough permissions - scope={security_scopes.scopes}",
|
||||
headers={
|
||||
"WWW-Authenticate": f'Bearer scope="{security_scopes.scopes}"'
|
||||
},
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from fastapi import FastAPI, Request, Depends, Security
|
||||
from fastapi import FastAPI, Depends, Security
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
@@ -32,14 +32,12 @@ import activities.router as activities_router
|
||||
import activity_streams.router as activity_streams_router
|
||||
import gears.router as gears_router
|
||||
import followers.router as followers_router
|
||||
|
||||
from routers import (
|
||||
router_strava,
|
||||
)
|
||||
import strava.router as strava_router
|
||||
import strava.utils as strava_utils
|
||||
import strava.activity_utils as strava_activity_utils
|
||||
|
||||
from config import API_VERSION
|
||||
from database import SessionLocal
|
||||
from processors import strava_processor, strava_activity_processor
|
||||
|
||||
|
||||
def startup_event():
|
||||
@@ -79,7 +77,7 @@ def refresh_strava_tokens_job():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
# Refresh Strava tokens
|
||||
strava_processor.refresh_strava_tokens(db=db)
|
||||
strava_utils.refresh_strava_tokens(db=db)
|
||||
finally:
|
||||
# Ensure the session is closed after use
|
||||
db.close()
|
||||
@@ -87,7 +85,7 @@ def refresh_strava_tokens_job():
|
||||
|
||||
def retrieve_strava_user_activities_for_last_day():
|
||||
# Get last day users Strava activities
|
||||
strava_activity_processor.retrieve_strava_users_activities_for_days(1)
|
||||
strava_activity_utils.retrieve_strava_users_activities_for_days(1)
|
||||
|
||||
|
||||
# Create loggger
|
||||
@@ -216,7 +214,15 @@ app.include_router(
|
||||
tags=["followers"],
|
||||
dependencies=[Depends(session_security.validate_access_token)],
|
||||
)
|
||||
app.include_router(router_strava.router, tags=["strava"])
|
||||
app.include_router(
|
||||
strava_router.router,
|
||||
prefix="/strava",
|
||||
tags=["strava"],
|
||||
dependencies=[
|
||||
Depends(session_security.validate_access_token),
|
||||
Security(session_security.check_scopes, scopes=["profile"]),
|
||||
],
|
||||
)
|
||||
|
||||
# Check if Jaeger tracing is enabled using the 'JAEGER_ENABLED' environment variable
|
||||
if os.environ.get("JAEGER_ENABLED") == "true":
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import logging
|
||||
|
||||
from typing import Annotated, Callable
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -69,7 +69,7 @@ async def read_users_me(
|
||||
async def upload_profile_image(
|
||||
file: UploadFile,
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -84,7 +84,7 @@ async def upload_profile_image(
|
||||
async def edit_user(
|
||||
user_attributtes: users_schema.User,
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -103,7 +103,7 @@ async def edit_user(
|
||||
async def edit_profile_password(
|
||||
user_attributtes: users_schema.UserEditPassword,
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
@@ -121,7 +121,7 @@ async def edit_profile_password(
|
||||
@router.put("/delete-photo")
|
||||
async def delete_profile_photo(
|
||||
token_user_id: Annotated[
|
||||
Callable,
|
||||
int,
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[
|
||||
|
||||
@@ -18,8 +18,9 @@ import users.crud as users_crud
|
||||
|
||||
import gears.crud as gears_crud
|
||||
|
||||
import strava.utils as strava_utils
|
||||
|
||||
from database import SessionLocal
|
||||
from processors import strava_processor
|
||||
|
||||
# Define a loggger created on main.py
|
||||
logger = logging.getLogger("myLogger")
|
||||
@@ -291,7 +292,7 @@ def process_activity(
|
||||
db: Session,
|
||||
):
|
||||
# Get the activity by Strava ID from the user
|
||||
activity_db = strava_processor.fetch_and_validate_activity(activity.id, user_id, db)
|
||||
activity_db = strava_utils.fetch_and_validate_activity(activity.id, user_id, db)
|
||||
|
||||
# Check if activity is None and return None if it is
|
||||
if activity_db is not None:
|
||||
@@ -336,7 +337,7 @@ def get_user_strava_activities_by_days(start_date: datetime, user_id: int):
|
||||
|
||||
try:
|
||||
# Get the user integrations by user ID
|
||||
user_integrations = strava_processor.fetch_user_integrations_and_validate_token(
|
||||
user_integrations = strava_utils.fetch_user_integrations_and_validate_token(
|
||||
user_id, db
|
||||
)
|
||||
|
||||
@@ -348,7 +349,7 @@ def get_user_strava_activities_by_days(start_date: datetime, user_id: int):
|
||||
logger.info(f"User {user_id}: Started Strava activities processing")
|
||||
|
||||
# Create a Strava client with the user's access token
|
||||
strava_client = strava_processor.create_strava_client(user_integrations)
|
||||
strava_client = strava_utils.create_strava_client(user_integrations)
|
||||
|
||||
# Fetch Strava activities after the specified start date
|
||||
num_strava_activities_processed = fetch_and_process_activities(
|
||||
@@ -1,9 +1,10 @@
|
||||
import logging
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from stravalib.client import Client
|
||||
|
||||
import strava.utils as strava_utils
|
||||
|
||||
import gears.schema as gears_schema
|
||||
import gears.crud as gears_crud
|
||||
|
||||
@@ -12,8 +13,9 @@ import activities.crud as activities_crud
|
||||
|
||||
import user_integrations.crud as user_integrations_crud
|
||||
|
||||
import strava.athlete_utils as strava_athlete_utils
|
||||
|
||||
from database import SessionLocal
|
||||
from processors import strava_processor, strava_athlete_processor
|
||||
|
||||
# Define a loggger created on main.py
|
||||
logger = logging.getLogger("myLogger")
|
||||
@@ -34,7 +36,7 @@ def get_strava_gear(gear_id: str, strava_client: Client):
|
||||
|
||||
def fetch_and_process_gear(strava_client: Client, user_id: int, db: Session) -> int:
|
||||
# Fetch Strava athlete
|
||||
strava_athlete = strava_athlete_processor.get_strava_athlete(strava_client)
|
||||
strava_athlete = strava_athlete_utils.get_strava_athlete(strava_client)
|
||||
|
||||
# Initialize an empty list for results
|
||||
strava_gear = []
|
||||
@@ -88,14 +90,14 @@ def process_gear(
|
||||
return new_gear
|
||||
|
||||
|
||||
def save_gears(gears: [gears_schema.Gear], user_id: int, db: Session):
|
||||
def save_gears(gears: list[gears_schema.Gear], user_id: int, db: Session):
|
||||
# Save the gear to the database
|
||||
gears_crud.create_multiple_gears(gears, user_id, db)
|
||||
|
||||
|
||||
def iterate_over_activities_and_set_gear(
|
||||
activity: activities_schema.Activity,
|
||||
gears: [gears_schema.Gear],
|
||||
gears: list[gears_schema.Gear],
|
||||
counter: int,
|
||||
user_id: int,
|
||||
db: Session,
|
||||
@@ -153,7 +155,7 @@ def get_user_gear(user_id: int):
|
||||
|
||||
try:
|
||||
# Get the user integrations by user ID
|
||||
user_integrations = strava_processor.fetch_user_integrations_and_validate_token(
|
||||
user_integrations = strava_utils.fetch_user_integrations_and_validate_token(
|
||||
user_id, db
|
||||
)
|
||||
|
||||
@@ -161,7 +163,7 @@ def get_user_gear(user_id: int):
|
||||
logger.info(f"User {user_id}: Started Strava gear processing")
|
||||
|
||||
# Create a Strava client with the user's access token
|
||||
strava_client = strava_processor.create_strava_client(user_integrations)
|
||||
strava_client = strava_utils.create_strava_client(user_integrations)
|
||||
|
||||
# Set the user's gear to sync to True
|
||||
user_integrations_crud.set_user_strava_sync_gear(user_id, True, db)
|
||||
@@ -2,29 +2,25 @@ import logging
|
||||
import requests
|
||||
import os
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Annotated
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
from fastapi.responses import RedirectResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
import session.security as session_security
|
||||
|
||||
import user_integrations.crud as user_integrations_crud
|
||||
|
||||
import gears.crud as gears_crud
|
||||
|
||||
import activities.crud as activities_crud
|
||||
|
||||
from processors import strava_activity_processor, strava_gear_processor
|
||||
from dependencies import (
|
||||
dependencies_session,
|
||||
)
|
||||
import strava.gear_utils as strava_gear_utils
|
||||
import strava.activity_utils as strava_activity_utils
|
||||
|
||||
import database
|
||||
|
||||
# Define the OAuth2 scheme for handling bearer tokens
|
||||
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||
|
||||
# Define the API router
|
||||
router = APIRouter()
|
||||
|
||||
@@ -33,7 +29,7 @@ logger = logging.getLogger("myLogger")
|
||||
|
||||
|
||||
@router.get(
|
||||
"/strava/link",
|
||||
"/link",
|
||||
tags=["strava"],
|
||||
)
|
||||
async def strava_link(
|
||||
@@ -101,7 +97,7 @@ async def strava_link(
|
||||
|
||||
|
||||
@router.get(
|
||||
"/strava/activities/days/{days}",
|
||||
"/activities/days/{days}",
|
||||
status_code=202,
|
||||
tags=["strava"],
|
||||
)
|
||||
@@ -109,17 +105,15 @@ async def strava_retrieve_activities_days(
|
||||
days: int,
|
||||
token_user_id: Annotated[
|
||||
int,
|
||||
Depends(
|
||||
dependencies_session.validate_access_token_and_get_authenticated_user_id
|
||||
),
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
# db: Annotated[Session, Depends(database.get_db)],
|
||||
background_tasks: BackgroundTasks,
|
||||
):
|
||||
# Process strava activities in the background
|
||||
background_tasks.add_task(
|
||||
strava_activity_processor.get_user_strava_activities_by_days,
|
||||
(datetime.utcnow() - timedelta(days=days)).strftime("%Y-%m-%dT%H:%M:%S"),
|
||||
strava_activity_utils.get_user_strava_activities_by_days,
|
||||
(datetime.now(timezone.utc) - timedelta(days=days)).strftime("%Y-%m-%dT%H:%M:%S"),
|
||||
token_user_id,
|
||||
)
|
||||
|
||||
@@ -133,53 +127,47 @@ async def strava_retrieve_activities_days(
|
||||
|
||||
|
||||
@router.put(
|
||||
"/strava/set-user-unique-state/{state}",
|
||||
"/set-user-unique-state/{state}",
|
||||
tags=["strava"],
|
||||
)
|
||||
async def strava_set_user_unique_state(
|
||||
state: str,
|
||||
user_id: Annotated[
|
||||
token_user_id: Annotated[
|
||||
int,
|
||||
Depends(
|
||||
dependencies_session.validate_access_token_and_get_authenticated_user_id
|
||||
),
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[Session, Depends(database.get_db)],
|
||||
):
|
||||
# Set the user Strava state
|
||||
user_integrations_crud.set_user_strava_state(user_id, state, db)
|
||||
user_integrations_crud.set_user_strava_state(token_user_id, state, db)
|
||||
|
||||
# Return success message
|
||||
return {"detail": f"Strava state for user {user_id} edited successfully"}
|
||||
return {f"Strava state for user {token_user_id} edited successfully"}
|
||||
|
||||
|
||||
@router.put(
|
||||
"/strava/unset-user-unique-state",
|
||||
"/unset-user-unique-state",
|
||||
tags=["strava"],
|
||||
)
|
||||
async def strava_unset_user_unique_state(
|
||||
user_id: Annotated[
|
||||
token_user_id: Annotated[
|
||||
int,
|
||||
Depends(
|
||||
dependencies_session.validate_access_token_and_get_authenticated_user_id
|
||||
),
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Annotated[Session, Depends(database.get_db)],
|
||||
):
|
||||
# Set the user Strava state
|
||||
user_integrations_crud.set_user_strava_state(user_id, None, db)
|
||||
user_integrations_crud.set_user_strava_state(token_user_id, None, db)
|
||||
|
||||
# Return success message
|
||||
return {"detail": f"Strava state for user {user_id} removed successfully"}
|
||||
return {f"Strava state for user {token_user_id} removed successfully"}
|
||||
|
||||
|
||||
@router.delete("/strava/unlink", tags=["strava"])
|
||||
@router.delete("/unlink", tags=["strava"])
|
||||
async def strava_unlink(
|
||||
token_user_id: Annotated[
|
||||
int,
|
||||
Depends(
|
||||
dependencies_session.validate_access_token_and_get_authenticated_user_id
|
||||
),
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
db: Session = Depends(database.get_db),
|
||||
):
|
||||
@@ -196,19 +184,17 @@ async def strava_unlink(
|
||||
return {"detail": f"Strava unlinked for user {token_user_id} successfully"}
|
||||
|
||||
|
||||
@router.get("/strava/gear", status_code=202, tags=["strava"])
|
||||
@router.get("/gear", status_code=202, tags=["strava"])
|
||||
async def strava_retrieve_gear(
|
||||
token_user_id: Annotated[
|
||||
int,
|
||||
Depends(
|
||||
dependencies_session.validate_access_token_and_get_authenticated_user_id
|
||||
),
|
||||
Depends(session_security.get_user_id_from_access_token),
|
||||
],
|
||||
background_tasks: BackgroundTasks,
|
||||
):
|
||||
# Process strava activities in the background
|
||||
background_tasks.add_task(
|
||||
strava_gear_processor.get_user_gear,
|
||||
strava_gear_utils.get_user_gear,
|
||||
token_user_id,
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import logging
|
||||
import os
|
||||
import requests
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from stravalib.client import Client
|
||||
@@ -36,7 +36,7 @@ def refresh_strava_tokens(db: Session):
|
||||
minutes=60
|
||||
)
|
||||
|
||||
if datetime.utcnow() > refresh_time:
|
||||
if datetime.now(timezone.utc) > refresh_time:
|
||||
# Strava token refresh endpoint
|
||||
token_url = "https://www.strava.com/oauth/token"
|
||||
# Parameters for the token refresh request
|
||||
@@ -301,6 +301,13 @@ def edit_user(user_id: int, user: users_schema.User, db: Session):
|
||||
# Get the user from the database
|
||||
db_user = db.query(models.User).filter(models.User.id == user_id).first()
|
||||
|
||||
if db_user is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="User not found",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
# Update the user
|
||||
if user.name is not None:
|
||||
db_user.name = user.name
|
||||
|
||||
Reference in New Issue
Block a user