diff --git a/src/backend/app/tasks/task_routes.py b/src/backend/app/tasks/task_routes.py index 6c59b8ff..97e21d9f 100644 --- a/src/backend/app/tasks/task_routes.py +++ b/src/backend/app/tasks/task_routes.py @@ -33,25 +33,32 @@ async def read_task( """ SELECT ST_Area(ST_Transform(tasks.outline, 3857)) / 1000000 AS task_area, - task_events.created_at, - task_events.updated_at, + te.created_at, + te.updated_at, projects.name AS project_name, - project_task_index, + tasks.project_task_index, projects.front_overlap AS front_overlap, projects.side_overlap AS side_overlap, projects.gsd_cm_px AS gsd_cm_px, projects.gimble_angles_degrees AS gimble_angles_degrees - FROM - task_events - JOIN - tasks ON task_events.task_id = tasks.id - JOIN - projects ON task_events.project_id = projects.id - WHERE task_events.task_id = %(task_id)s""", + FROM ( + SELECT DISTINCT ON (te.task_id) + te.task_id, + te.created_at, + te.updated_at + FROM task_events te + WHERE te.task_id = %(task_id)s + ORDER BY te.task_id, te.created_at DESC + ) AS te + JOIN tasks ON te.task_id = tasks.id + JOIN projects ON tasks.project_id = projects.id + WHERE te.task_id = %(task_id)s; + """, {"task_id": task_id}, ) records = await cur.fetchone() return records + except Exception as e: raise HTTPException( status_code=HTTPStatus.INTERNAL_SERVER_ERROR, diff --git a/src/backend/app/users/user_routes.py b/src/backend/app/users/user_routes.py index a3fcb185..7d4bfcc2 100644 --- a/src/backend/app/users/user_routes.py +++ b/src/backend/app/users/user_routes.py @@ -76,6 +76,7 @@ async def update_user_profile( profile_update: UserProfileIn, db: Annotated[Connection, Depends(database.get_db)], user_data: Annotated[AuthUser, Depends(login_required)], + request: Request, ): """ Update user profile based on provided user_id and profile_update data. @@ -89,7 +90,6 @@ async def update_user_profile( """ user = await user_schemas.DbUser.get_user_by_id(db, user_id) - if user_data.id != user_id: raise HTTPException( status_code=HTTPStatus.FORBIDDEN, @@ -98,6 +98,16 @@ async def update_user_profile( if not user: raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail="User not found") + + if request.method == "PATCH": + if not user_logic.verify_password( + profile_update.old_password, user.get("password") + ): + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail="Old password is incorrect", + ) + user = await user_schemas.DbUserProfile.update(db, user_id, profile_update) return JSONResponse( status_code=HTTPStatus.OK, diff --git a/src/backend/app/users/user_schemas.py b/src/backend/app/users/user_schemas.py index 63c26df9..0ff79814 100644 --- a/src/backend/app/users/user_schemas.py +++ b/src/backend/app/users/user_schemas.py @@ -114,6 +114,7 @@ def srting_role_to_integer(cls, value: UserRole) -> str: class UserProfileIn(BaseUserProfile): password: Optional[str] = None + old_password: Optional[str] = None class DbUserProfile(BaseUserProfile): @@ -126,7 +127,9 @@ async def update(db: Connection, user_id: int, profile_update: UserProfileIn): """Update or insert a user profile.""" # Prepare data for insert or update - model_dump = profile_update.model_dump(exclude_none=True, exclude=["password"]) + model_dump = profile_update.model_dump( + exclude_none=True, exclude=["password", "old_password"] + ) columns = ", ".join(model_dump.keys()) value_placeholders = ", ".join(f"%({key})s" for key in model_dump.keys()) sql = f"""