diff --git a/src/backend/langflow/api/v1/users.py b/src/backend/langflow/api/v1/users.py index 517dd7f69..deb350414 100644 --- a/src/backend/langflow/api/v1/users.py +++ b/src/backend/langflow/api/v1/users.py @@ -20,13 +20,14 @@ from langflow.services.auth.utils import ( get_password_hash, ) from langflow.services.database.models.user.crud import ( + get_user_by_id, update_user, ) -router = APIRouter(tags=["Users"]) +router = APIRouter(tags=["Users"], prefix="/users") -@router.post("/user", response_model=UserRead, status_code=201) +@router.post("/", response_model=UserRead, status_code=201) def add_user( user: UserCreate, session: Session = Depends(get_session), @@ -50,7 +51,7 @@ def add_user( return new_user -@router.get("/user", response_model=UserRead) +@router.get("/whoami", response_model=UserRead) def read_current_user( current_user: User = Depends(get_current_active_user), ) -> User: @@ -60,7 +61,7 @@ def read_current_user( return current_user -@router.get("/users", response_model=UsersResponse) +@router.get("/", response_model=UsersResponse) def read_all_users( skip: int = 0, limit: int = 10, @@ -82,20 +83,53 @@ def read_all_users( ) -@router.patch("/user/{user_id}", response_model=UserRead) +@router.patch("/{user_id}", response_model=UserRead) def patch_user( user_id: UUID, - user: UserUpdate, - _: Session = Depends(get_current_active_user), + user_update: UserUpdate, + user: Session = Depends(get_current_active_user), session: Session = Depends(get_session), ) -> User: """ Update an existing user's data. """ - return update_user(user_id, user, session) + if not user.is_superuser and user.id != user_id: + raise HTTPException( + status_code=403, detail="You don't have the permission to update this user" + ) + + if user_db := get_user_by_id(session, user_id): + return update_user(user_db, user_update, session) + else: + raise HTTPException(status_code=404, detail="User not found") -@router.delete("/user/{user_id}") +@router.patch("/{user_id}/reset-password", response_model=UserRead) +def reset_password( + user_id: UUID, + user_update: UserUpdate, + user: Session = Depends(get_current_active_user), + session: Session = Depends(get_session), +) -> User: + """ + Reset a user's password. + """ + if user_id != user.id: + raise HTTPException( + status_code=400, detail="You can't change another user's password" + ) + + if not user: + raise HTTPException(status_code=404, detail="User not found") + + user.password = get_password_hash(user_update.password) + session.commit() + session.refresh(user) + + return user + + +@router.delete("/{user_id}", response_model=dict) def delete_user( user_id: UUID, current_user: User = Depends(get_current_active_superuser), diff --git a/src/backend/langflow/services/database/models/user/crud.py b/src/backend/langflow/services/database/models/user/crud.py index 3dc02a499..93d5dd801 100644 --- a/src/backend/langflow/services/database/models/user/crud.py +++ b/src/backend/langflow/services/database/models/user/crud.py @@ -20,20 +20,24 @@ def get_user_by_id(db: Session, id: UUID) -> Union[User, None]: def update_user( - user_id: UUID, user: UserUpdate, db: Session = Depends(get_session) + user_db: User, user: UserUpdate, db: Session = Depends(get_session) ) -> User: - user_db = get_user_by_id(db, user_id) if not user_db: raise HTTPException(status_code=404, detail="User not found") - user_db_by_username = get_user_by_username(db, user.username) # type: ignore - if user_db_by_username and user_db_by_username.id != user_id: - raise HTTPException(status_code=409, detail="Username already exists") + # user_db_by_username = get_user_by_username(db, user.username) # type: ignore + # if user_db_by_username and user_db_by_username.id != user_id: + # raise HTTPException(status_code=409, detail="Username already exists") user_data = user.dict(exclude_unset=True) + changed = False for attr, value in user_data.items(): if hasattr(user_db, attr) and value is not None: setattr(user_db, attr, value) + changed = True + + if not changed: + raise HTTPException(status_code=304, detail="Nothing to update") user_db.updated_at = datetime.now(timezone.utc) flag_modified(user_db, "updated_at") @@ -49,5 +53,5 @@ def update_user( def update_user_last_login_at(user_id: UUID, db: Session = Depends(get_session)): user_data = UserUpdate(last_login_at=datetime.now(timezone.utc)) # type: ignore - - return update_user(user_id, user_data, db) + user = get_user_by_id(db, user_id) + return update_user(user, user_data, db) diff --git a/src/backend/langflow/services/database/models/user/user.py b/src/backend/langflow/services/database/models/user/user.py index 5f83b4d88..b58f7226a 100644 --- a/src/backend/langflow/services/database/models/user/user.py +++ b/src/backend/langflow/services/database/models/user/user.py @@ -40,7 +40,7 @@ class UserRead(SQLModel): class UserUpdate(SQLModel): - username: Optional[str] = Field() + password: Optional[str] = Field() is_active: Optional[bool] = Field() is_superuser: Optional[bool] = Field() last_login_at: Optional[datetime] = Field() diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 2d18b7cfe..182f2c802 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -402,7 +402,7 @@ export async function renewAccessToken(token: string) { export async function getLoggedUser(): Promise { try { - const res = await api.get(`${BASE_URL_API}user`); + const res = await api.get(`${BASE_URL_API}users/whoami`); if (res.status === 200) { return res.data; @@ -416,7 +416,7 @@ export async function getLoggedUser(): Promise { export async function addUser(user: UserInputType): Promise> { try { - const res = await api.post(`${BASE_URL_API}user`, user); + const res = await api.post(`${BASE_URL_API}users/`, user); if (res.status === 200) { return res.data; } @@ -433,7 +433,7 @@ export async function getUsersPage( ): Promise> { try { const res = await api.get( - `${BASE_URL_API}users?skip=${skip}&limit=${limit}` + `${BASE_URL_API}users/?skip=${skip}&limit=${limit}` ); if (res.status === 200) { return res.data; @@ -447,7 +447,7 @@ export async function getUsersPage( export async function deleteUser(user_id: string) { try { - const res = await api.delete(`${BASE_URL_API}user/${user_id}`); + const res = await api.delete(`${BASE_URL_API}users/${user_id}`); if (res.status === 200) { return res.data; } @@ -459,7 +459,7 @@ export async function deleteUser(user_id: string) { export async function updateUser(user_id: string, user: Users) { try { - const res = await api.patch(`${BASE_URL_API}user/${user_id}`, user); + const res = await api.patch(`${BASE_URL_API}users/${user_id}`, user); if (res.status === 200) { return res.data; }