🐛 fix(users.py): change route paths for user-related endpoints to improve consistency and readability

 feat(users.py): add support for resetting a user's password
🐛 fix(crud.py): fix update_user function to properly handle unchanged attributes and return 304 status code if nothing is updated
🐛 fix(user.py): change field name in UserUpdate model from 'username' to 'password' to reflect the intended functionality
🐛 fix(index.ts): update API routes in frontend controller functions to match the changed user-related endpoint paths
This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-09-05 17:19:11 -03:00
commit a7db386277
4 changed files with 60 additions and 22 deletions

View file

@ -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),

View file

@ -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)

View file

@ -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()

View file

@ -402,7 +402,7 @@ export async function renewAccessToken(token: string) {
export async function getLoggedUser(): Promise<Users | null> {
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<Users | null> {
export async function addUser(user: UserInputType): Promise<Array<Users>> {
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<Array<Users>> {
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;
}