refactor: dbcrud->dbuser

This commit is contained in:
2024-12-03 22:12:30 +09:00
parent 9f61ab300c
commit 6504d8d29f
7 changed files with 224 additions and 68 deletions

View File

@@ -1,6 +1,7 @@
from fastapi import APIRouter, Request, Depends, Response, Security, encoders from fastapi import APIRouter, Request, Depends, Response, Security, encoders
import typing as t import typing as t
from app.core.common import ApiReturnModel,ApiReturnPage
from app.core.apiexception import APIException
from app.db.session import get_db from app.db.session import get_db
from app.db.crud import ( from app.db.crud import (
get_allusers, get_allusers,
@@ -12,129 +13,174 @@ from app.db.crud import (
assign_userrole, assign_userrole,
get_roles, get_roles,
) )
from app.db.schemas import UserCreate, UserEdit, User, UserOut,Role from app.db.schemas import UserCreate, UserEdit, User, UserOut,RoleBase,Permission
from app.core.auth import get_current_user,get_current_active_user, get_current_active_superuser from app.core.auth import get_current_user,get_current_active_user, get_current_active_superuser
from app.db.cruddb.dbuser import dbuser
users_router = r = APIRouter() users_router = r = APIRouter()
@r.get( @r.get(
"/users", "/users",tags=["User"],
response_model=t.List[User], response_model=ApiReturnPage[User],
response_model_exclude_none=True, response_model_exclude_none=True,
) )
async def users_list( async def users_list(
response: Response, request: Request,
db=Depends(get_db), db=Depends(get_db),
current_user=Depends(get_current_active_user), current_user=Depends(get_current_active_user),
): ):
""" try:
Get all users
"""
if current_user.is_superuser: if current_user.is_superuser:
users = get_allusers(db) users = dbuser.get_users(db)
else: else:
users = get_users(db) users = dbuser.get_users_not_admin(db)
# This is necessary for react-admin to work
#response.headers["Content-Range"] = f"0-9/{len(users)}"
return users return users
except Exception as e:
raise APIException('user:users',request.url._url,f"Error occurred while get user list",e)
@r.get("/users/me", tags=["User"],
@r.get("/users/me", response_model=User, response_model_exclude_none=True) response_model=ApiReturnModel[User],
response_model_exclude_none=True,
)
async def user_me(current_user=Depends(get_current_active_user)): async def user_me(current_user=Depends(get_current_active_user)):
""" return ApiReturnModel(data = current_user)
Get own user
"""
return current_user
@r.get( @r.get(
"/users/{user_id}", "/users/{user_id}",tags=["User"],
response_model=User, response_model=ApiReturnModel[User|None],
response_model_exclude_none=True, response_model_exclude_none=True,
) )
async def user_details( async def user_details(
request: Request, request: Request,
user_id: int, user_id: int,
db=Depends(get_db), db=Depends(get_db),
current_user=Depends(get_current_active_superuser), current_user=Depends(get_current_active_user),
): ):
""" try:
Get any user details user = dbuser.get(db, user_id)
""" if user:
user = get_user(db, user_id) if user.is_superuser and not current_user.is_superuser:
return user user = None
# return encoders.jsonable_encoder( return ApiReturnModel(data = user)
# user, skip_defaults=True, exclude_none=True, except Exception as e:
# ) raise APIException('user:users',request.url._url,f"Error occurred while get user({user_id}) detail:",e)
@r.post("/users", response_model=User, response_model_exclude_none=True) @r.post("/users", tags=["User"],
response_model=ApiReturnModel[User|None],
response_model_exclude_none=True,
)
async def user_create( async def user_create(
request: Request, request: Request,
user: UserCreate, user: UserCreate,
db=Depends(get_db), db=Depends(get_db),
current_user=Depends(get_current_active_superuser), current_user=Depends(get_current_active_user),
): ):
""" try:
Create a new user if user.is_superuser and not current_user.is_superuser:
""" return ApiReturnModel(data = None)
return create_user(db, user) return ApiReturnModel(data =dbuser.create_user(db, user,current_user.id))
except Exception as e:
raise APIException('user:users',request.url._url,f"Error occurred while create user({user.email}):",e)
@r.put( @r.put(
"/users/{user_id}", response_model=User, response_model_exclude_none=True "/users/{user_id}", tags=["User"],
response_model=ApiReturnModel[User|None],
response_model_exclude_none=True,
) )
async def user_edit( async def user_edit(
request: Request, request: Request,
user_id: int, user_id: int,
user: UserEdit, user: UserEdit,
db=Depends(get_db), db=Depends(get_db),
current_user=Depends(get_current_active_superuser), current_user=Depends(get_current_active_user),
): ):
""" try:
Update existing user if user.is_superuser and not current_user.is_superuser:
""" return ApiReturnModel(data = None)
return edit_user(db, user_id, user) return ApiReturnModel(data = dbuser.edit_user(db,user_id,user,current_user.id))
except Exception as e:
raise APIException('user:users',request.url._url,f"Error occurred while edit user({user_id}):",e)
@r.delete( @r.delete(
"/users/{user_id}", response_model=User, response_model_exclude_none=True "/users/{user_id}", tags=["User"],
response_model=ApiReturnModel[UserOut|None],
response_model_exclude_none=True
) )
async def user_delete( async def user_delete(
request: Request, request: Request,
user_id: int, user_id: int,
db=Depends(get_db), db=Depends(get_db),
current_user=Depends(get_current_active_superuser), current_user=Depends(get_current_active_user),
): ):
""" try:
Delete existing user user = dbuser.get(db,user_id)
""" if user.is_superuser and not current_user.is_superuser:
return delete_user(db, user_id) return ApiReturnModel(data = None)
return ApiReturnModel(data = dbuser.delete_user(db, user_id))
except Exception as e:
raise APIException('user:users',request.url._url,f"Error occurred while delete user({user_id}):",e)
@r.post("/userrole", @r.post("/userrole",tags=["User"],
response_model=User, response_model=ApiReturnModel[User],
response_model_exclude_none=True,) response_model_exclude_none=True,)
async def assign_role( async def assign_role(
request: Request, request: Request,
userid:int, user_id:int,
roles:t.List[int], roles:t.List[int],
db=Depends(get_db) db=Depends(get_db)
): ):
try:
return assign_userrole(db,userid,roles) return ApiReturnModel(data = dbuser.assign_userrole(db,user_id,roles))
except Exception as e:
raise APIException('user:userrole',request.url._url,f"Error occurred while assign user({user_id}) roles({roles}):",e)
@r.get( @r.get(
"/roles", "/roles",tags=["User"],
response_model=t.List[Role], response_model=ApiReturnModel[t.List[RoleBase]|None],
response_model_exclude_none=True, response_model_exclude_none=True,
) )
async def roles_list( async def roles_list(
response: Response, request: Request,
db=Depends(get_db), db=Depends(get_db),
current_user=Security(get_current_active_user, scopes=["role_list"]), current_user=Depends(get_current_active_user),
#current_user=Security(get_current_active_user, scopes=["role_list"]),
): ):
roles = get_roles(db) try:
return roles if current_user.is_superuser:
roles = dbuser.get_roles(db)
else:
if len(current_user.roles)>0:
roles = dbuser.get_roles_by_level(db,current_user.roles[0].level)
else:
roles = []
return ApiReturnModel(data = roles)
except Exception as e:
raise APIException('user:roles',request.url._url,f"Error occurred while get roles:",e)
@r.get(
"/userpermssions",tags=["User"],
response_model=ApiReturnModel[t.List[Permission]|None],
response_model_exclude_none=True,
)
async def permssions_list(
request: Request,
db=Depends(get_db),
current_user=Depends(get_current_active_user),
#current_user=Security(get_current_active_user, scopes=["role_list"]),
):
try:
if current_user.is_superuser:
permissions = dbuser.get_permissions(db)
else:
if len(current_user.roles)>0:
permissions = dbuser.get_user_permissions(db,current_user.id)
else:
permissions = []
return ApiReturnModel(data = permissions)
except Exception as e:
raise APIException('user:userpermssions',request.url._url,f"Error occurred while get user(){current_user.id} permissions:",e)

View File

@@ -6,7 +6,7 @@ from jwt import PyJWTError
from app.db import models, schemas, session from app.db import models, schemas, session
from app.db.crud import get_user_by_email, create_user,get_user from app.db.crud import get_user_by_email, create_user,get_user
from app.core import security from app.core import security
from app.db.cruddb.dbuser import dbuser
async def get_current_user(security_scopes: SecurityScopes, async def get_current_user(security_scopes: SecurityScopes,
db=Depends(session.get_db), token: str = Depends(security.oauth2_scheme) db=Depends(session.get_db), token: str = Depends(security.oauth2_scheme)
@@ -35,7 +35,7 @@ async def get_current_user(security_scopes: SecurityScopes,
token_data = schemas.TokenData(id = id, permissions=permissions) token_data = schemas.TokenData(id = id, permissions=permissions)
except PyJWTError: except PyJWTError:
raise credentials_exception raise credentials_exception
user = get_user(db, token_data.id) user = dbuser.get_user(db, token_data.id)
if user is None: if user is None:
raise credentials_exception raise credentials_exception
return user return user

View File

@@ -78,7 +78,7 @@ def edit_user(
def get_roles( def get_roles(
db: Session db: Session
) -> t.List[schemas.Role]: ) -> t.List[schemas.RoleBase]:
return db.query(models.Role).all() return db.query(models.Role).all()
def assign_userrole( db: Session, user_id: int, roles: t.List[int]): def assign_userrole( db: Session, user_id: int, roles: t.List[int]):

View File

@@ -30,8 +30,12 @@ class crudbase:
and_conditions.append(column == filter_value) and_conditions.append(column == filter_value)
elif operator == '>': elif operator == '>':
and_conditions.append(column > filter_value) and_conditions.append(column > filter_value)
elif operator == '>=':
and_conditions.append(column >= filter_value)
elif operator == '<': elif operator == '<':
and_conditions.append(column < filter_value) and_conditions.append(column < filter_value)
elif operator == '<=':
and_conditions.append(column <= filter_value)
elif operator == 'in': elif operator == 'in':
if isinstance(filter_value, list): if isinstance(filter_value, list):
or_conditions.append(column.in_(filter_value)) or_conditions.append(column.in_(filter_value))

View File

@@ -0,0 +1,92 @@
from datetime import datetime
from fastapi import HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy import and_
import typing as t
from app.db.cruddb.crudbase import crudbase
from fastapi_pagination.ext.sqlalchemy import paginate
from app.core.common import ApiReturnPage
from app.db import models, schemas
from app.core.security import chacha20Decrypt, get_password_hash
class dbpermission(crudbase):
def __init__(self):
super().__init__(model=models.Permission)
dbpermission = dbpermission()
class dbrole(crudbase):
def __init__(self):
super().__init__(model=models.Role)
dbrole = dbrole()
class dbuser(crudbase):
def __init__(self):
super().__init__(model=models.User)
def get_user(self,db: Session, user_id: int) -> schemas.User:
return super().get(db,user_id)
def get_user_by_email(self,db: Session, email: str) -> schemas.User:
return super().get_by_conditions(db,{"email":email}).first()
def get_users(self,db: Session) -> ApiReturnPage[models.Base]:
return paginate(super().get_all())
def get_users_not_admin(self,db: Session) -> ApiReturnPage[models.Base]:
return paginate(super().get_by_conditions(db,{"is_superuser":False}))
def create_user(self,db: Session, user: schemas.UserCreate,userid:int):
hashed_password = get_password_hash(user.password)
user.hashed_password = hashed_password
user.createuserid = userid
user.updateuserid = userid
del user.password
return super().create(db,user)
def delete_user(self,db: Session, user_id: int):
return super().delete(db,user_id)
def edit_user(self,db: Session, user_id:int,user: schemas.UserEdit,userid: int) -> schemas.User:
if not user.password is None and user.password != "":
user.hashed_password = get_password_hash(user.password)
del user.password
user.updateuserid = userid
return super().update(db,user_id,user)
def get_roles(self,db: Session) -> t.List[schemas.RoleBase]:
return dbrole.get_all(db).all()
def get_roles_by_level(self,db: Session,level:int) -> t.List[schemas.RoleBase]:
return dbrole.get_by_conditions(db,{"level":{"operator":">=","value":level}}).all()
def assign_userrole(self,db: Session, user_id: int, roles: t.List[int]):
db_user = super().get(db,user_id)
if db_user:
for role in db_user.roles:
db_user.roles.remove(role)
for roleid in roles:
role = dbrole.get(db,roleid)
if role:
db_user.roles.append(role)
db.commit()
db.refresh(db_user)
return db_user
def get_permissions(self,db: Session,user_id: int) -> t.List[schemas.Permission]:
return dbpermission.get_by_conditions(db).all()
def get_user_permissions(self,db: Session,user_id: int) -> t.List[schemas.Permission]:
permissions =[]
db_user = super().get(db,user_id)
if db_user:
for role in db_user.roles:
permissions += role.permissions
return list(set(permissions))
dbuser = dbuser()

View File

@@ -35,6 +35,10 @@ class User(Base):
hashed_password = Column(String(200), nullable=False) hashed_password = Column(String(200), nullable=False)
is_active = Column(Boolean, default=True) is_active = Column(Boolean, default=True)
is_superuser = Column(Boolean, default=False) is_superuser = Column(Boolean, default=False)
createuserid = Column(Integer,ForeignKey("user.id"))
updateuserid = Column(Integer,ForeignKey("user.id"))
createuser = relationship('User',foreign_keys=[createuserid])
updateuser = relationship('User',foreign_keys=[updateuserid])
roles = relationship("Role",secondary=userrole,back_populates="users") roles = relationship("Role",secondary=userrole,back_populates="users")
@@ -43,6 +47,7 @@ class Role(Base):
name = Column(String(100)) name = Column(String(100))
description = Column(String(255)) description = Column(String(255))
level = Column(Integer)
users = relationship("User",secondary=userrole,back_populates="roles") users = relationship("User",secondary=userrole,back_populates="roles")
permissions = relationship("Permission",secondary=rolepermission,back_populates="roles") permissions = relationship("Permission",secondary=rolepermission,back_populates="roles")

View File

@@ -15,10 +15,14 @@ class Permission(BaseModel):
function:str function:str
privilege:str privilege:str
class Role(BaseModel): class RoleBase(BaseModel):
id: int id: int
name:str name:str
description:str description:str
level:int
class RoleWithPermission(RoleBase):
permissions:t.List[Permission] = [] permissions:t.List[Permission] = []
class UserBase(BaseModel): class UserBase(BaseModel):
@@ -27,7 +31,7 @@ class UserBase(BaseModel):
is_superuser: bool = False is_superuser: bool = False
first_name: str = None first_name: str = None
last_name: str = None last_name: str = None
roles:t.List[Role] = [] roles:t.List[RoleBase] = []
class UserOut(BaseModel): class UserOut(BaseModel):
@@ -42,10 +46,13 @@ class UserOut(BaseModel):
class UserCreate(UserBase): class UserCreate(UserBase):
email:str email:str
password: str password: str
hashed_password :str = None
first_name: str first_name: str
last_name: str last_name: str
is_active:bool is_active:bool
is_superuser:bool is_superuser:bool
createuserid:t.Optional[int] = None
updateuserid:t.Optional[int] = None
class ConfigDict: class ConfigDict:
orm_mode = True orm_mode = True
@@ -53,6 +60,8 @@ class UserCreate(UserBase):
class UserEdit(UserBase): class UserEdit(UserBase):
password: t.Optional[str] = None password: t.Optional[str] = None
hashed_password :str = None
updateuserid:t.Optional[int] = None
class ConfigDict: class ConfigDict:
orm_mode = True orm_mode = True