Skip to content

Commit 04e71a8

Browse files
committed
♻️ refactor(model): 重构ItemModel和UserModel以符合CRUD操作
- 移除ItemModel中的密码哈希相关代码,并更名ItemModel为Item - 添加Item的类方法以支持CRUD操作 - 在UserService中添加密码哈希功能,并更名为UserModel - 优化用户密码更新逻辑 - 优化查询逻辑,支持超级用户和非超级用户的权限区分【model】 ♻️ refactor(service): 优化UserService服务 - 将UserService中的用户验证、密码更新等操作下放到UserModel中 - 优化用户密码更新逻辑,确保密码更新的安全性【service】
1 parent 9561bb9 commit 04e71a8

File tree

2 files changed

+91
-96
lines changed

2 files changed

+91
-96
lines changed

backend/app/model/item_model.py

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,56 @@
44
from sqlalchemy import func
55
from sqlmodel import Session, select
66

7-
from app.core.security import get_password_hash
8-
from app.models import Item, ItemCreate, ItemUpdate
7+
from app.models import ItemCreate, ItemUpdate
98

109

11-
class ItemModel:
10+
class Item:
1211
def __init__(self, session: Session):
1312
self.session = session
1413

15-
def create(self, item_create: ItemCreate, owner_id: uuid.UUID) -> Item:
16-
db_obj = Item.model_validate(
17-
item_create,
18-
update={"owner_id": owner_id},
19-
)
20-
self.session.add(db_obj)
21-
self.session.commit()
22-
self.session.refresh(db_obj)
23-
return db_obj
24-
25-
def update(self, db_item: Item, item_in: ItemUpdate) -> Item:
26-
item_data = item_in.model_dump(exclude_unset=True)
27-
db_item.sqlmodel_update(item_data)
28-
self.session.add(db_item)
29-
self.session.commit()
30-
self.session.refresh(db_item)
14+
def create(cls, item_in: ItemCreate, owner_id: uuid.UUID) -> "Item":
15+
db_item = Item.model_validate(item_in, update={"owner_id": owner_id})
16+
cls.session.add(db_item)
17+
cls.session.commit()
18+
cls.session.refresh(db_item)
3119
return db_item
3220

33-
def get_by_id(self, item_id: str) -> "Item | None":
34-
statement = select(Item).where(Item.id == uuid.UUID(item_id))
35-
return self.session.exec(statement).first()
36-
37-
def get_items(self, skip: int = 0, limit: int = 100, owner_id: uuid.UUID | None = None) -> dict:
38-
query = select(Item)
39-
if owner_id:
40-
query = query.where(Item.owner_id == owner_id)
41-
42-
count_statement = select(func.count()).select_from(query.subquery())
43-
count = self.session.exec(count_statement).one()
44-
45-
query = query.offset(skip).limit(limit)
46-
items = self.session.exec(query).all()
21+
def get_items(
22+
cls,
23+
owner_id: uuid.UUID,
24+
is_superuser: bool,
25+
skip: int = 0,
26+
limit: int = 100,
27+
) -> Any:
28+
if is_superuser:
29+
count_statement = select(func.count()).select_from(Item)
30+
count = cls.session.exec(count_statement).one()
31+
statement = select(Item).offset(skip).limit(limit)
32+
items = cls.session.exec(statement).all()
33+
else:
34+
count_statement = (
35+
select(func.count()).select_from(Item).where(Item.owner_id == owner_id)
36+
)
37+
count = cls.session.exec(count_statement).one()
38+
statement = (
39+
select(Item).where(Item.owner_id == owner_id).offset(skip).limit(limit)
40+
)
41+
items = cls.session.exec(statement).all()
4742
return {"data": items, "count": count}
4843

49-
def delete_item(self, item_id: str) -> None:
50-
item = self.get_by_id(item_id)
44+
def get_by_id(cls, item_id: uuid.UUID) -> "Item | None":
45+
return cls.session.get(Item, item_id)
46+
47+
def update(cls, item: "Item", item_in: ItemUpdate) -> "Item":
48+
update_dict = item_in.model_dump(exclude_unset=True)
49+
item.sqlmodel_update(update_dict)
50+
cls.session.add(item)
51+
cls.session.commit()
52+
cls.session.refresh(item)
53+
return item
54+
55+
def delete(cls, item_id: uuid.UUID) -> None:
56+
item = cls.session.get(Item, item_id)
5157
if item:
52-
self.session.delete(item)
53-
self.session.commit()
58+
cls.session.delete(item)
59+
cls.session.commit()
Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,57 @@
1+
import uuid
12
from typing import Any
23

3-
from sqlmodel import Session
4+
from sqlalchemy import func
5+
from sqlmodel import Session, select
46

5-
from app.core.security import verify_password
6-
from app.model.user_model import UserModel
7-
from app.models import User, UserCreate, UserUpdate, UserUpdateMe
7+
from app.core.security import get_password_hash
8+
from app.models import User, UserCreate, UserUpdate
89

910

10-
class UserService:
11+
class UserModel:
1112
def __init__(self, session: Session):
1213
self.session = session
1314

14-
def create_user(cls, user_create: UserCreate) -> User:
15-
return UserModel(cls.session).create(user_create)
16-
17-
def update_user(cls, db_user: User, user_in: UserUpdate) -> Any:
18-
return UserModel(cls.session).update(db_user, user_in)
19-
20-
def get_user_by_email(cls, email: str) -> User | None:
21-
return UserModel(cls.session).get_by_email(email)
22-
23-
def get_user_by_id(cls, user_id: str) -> User | None:
24-
return UserModel(cls.session).get_by_id(user_id)
25-
26-
def get_users(cls, skip: int = 0, limit: int = 100) -> dict[str, Any]:
27-
return UserModel(cls.session).get_users(skip, limit)
28-
29-
def update_user_me(cls, current_user: User, user_in: UserUpdateMe) -> User:
30-
if user_in.email:
31-
existing_user = cls.get_user_by_email(email=user_in.email)
32-
if existing_user and existing_user.id != current_user.id:
33-
raise ValueError("User with this email already exists")
34-
35-
# Convert UserUpdateMe to UserUpdate since model expects UserUpdate
36-
update_data = UserUpdate(email=user_in.email, full_name=user_in.full_name)
37-
return UserModel(cls.session).update(current_user, update_data)
38-
39-
def update_password(
40-
cls, current_user: User, current_password: str, new_password: str
41-
) -> None:
42-
if not verify_password(current_password, current_user.hashed_password):
43-
raise ValueError("Incorrect password")
44-
if current_password == new_password:
45-
raise ValueError("New password cannot be the same as the current one")
46-
47-
# Create UserUpdate with new password
48-
update_data = UserUpdate(password=new_password)
49-
UserModel(cls.session).update(current_user, update_data)
50-
51-
def delete_user(
52-
cls, user_id: str, current_user_id: str, is_superuser: bool
53-
) -> None:
54-
user = cls.get_user_by_id(user_id)
55-
if not user:
56-
raise ValueError("User not found")
57-
if user.id == current_user_id and is_superuser:
58-
raise ValueError("Super users are not allowed to delete themselves")
59-
60-
UserModel(cls.session).delete_user(user_id)
61-
62-
def authenticate(cls, email: str, password: str) -> User | None:
63-
db_user = cls.get_user_by_email(email)
64-
if not db_user:
65-
return None
66-
if not verify_password(password, db_user.hashed_password):
67-
return None
15+
def create(cls, user_create: UserCreate) -> "User":
16+
db_obj = User.model_validate(
17+
user_create,
18+
update={"hashed_password": get_password_hash(user_create.password)},
19+
)
20+
cls.session.add(db_obj)
21+
cls.session.commit()
22+
cls.session.refresh(db_obj)
23+
return db_obj
24+
25+
def update(cls, db_user: "User", user_in: UserUpdate) -> Any:
26+
user_data = user_in.model_dump(exclude_unset=True)
27+
extra_data = {}
28+
if "password" in user_data:
29+
password = user_data["password"]
30+
hashed_password = get_password_hash(password)
31+
extra_data["hashed_password"] = hashed_password
32+
db_user.sqlmodel_update(user_data, update=extra_data)
33+
cls.session.add(db_user)
34+
cls.session.commit()
35+
cls.session.refresh(db_user)
6836
return db_user
37+
38+
def get_by_email(cls, email: str) -> "User | None":
39+
statement = select(User).where(User.email == email)
40+
return cls.session.exec(statement).first()
41+
42+
def get_by_id(cls, user_id: str) -> "User | None":
43+
statement = select(User).where(User.id == uuid.UUID(user_id))
44+
return cls.session.exec(statement).first()
45+
46+
def get_users(cls, skip: int = 0, limit: int = 100) -> dict:
47+
count_statement = select(func.count()).select_from(User)
48+
count = cls.session.exec(count_statement).one()
49+
statement = select(User).offset(skip).limit(limit)
50+
users = cls.session.exec(statement).all()
51+
return {"data": users, "count": count}
52+
53+
def delete_user(cls, user_id: str) -> None:
54+
user = cls.get_by_id(user_id)
55+
if user:
56+
cls.session.delete(user)
57+
cls.session.commit()

0 commit comments

Comments
 (0)