You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
6.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# !/usr/bin/env python3
# -*- encoding : utf-8 -*-
# @Filename : user.py
# @Software : VSCode
# @Datetime : 2021/11/04 21:25:44
# @Author : leo liu
# @Version : 1.0
# @Description :
from datetime import datetime
from typing import Optional
from loguru import logger
from pydantic.types import conint
from sqlalchemy import func, desc
from sqlalchemy.orm import Session
from sqlalchemy.sql.expression import and_, or_, join
from core.security import get_password_hash, verify_password
from extensions.curd_base import CRUDBase
from models import User, Role, LoginHistory
from .role import crud_role
from ..schemas import user_schema
class CRUDUser(CRUDBase[User, user_schema.UserCreate, user_schema.UserUpdate]):
@staticmethod
def query_all(db: Session, *, col_val: str = "", is_delete: int = 0, role: str = "", page: int = 1, page_size: conint(le=50) = 20, order_by: str = "id", is_desc: bool = False) -> dict:
"""
查询用户列表
:param db:
:param page:
:param page_size:
:return:
"""
temp_page = (page - 1) * page_size
search = None
order_type = None
# 处理多个字段的模糊查询username、nickname、email
if col_val:
search = and_(User.is_delete == is_delete, or_(User.username.like('%' + col_val + "%"), User.nickname.like('%' + col_val + "%"), User.email.like('%' + col_val + "%")))
else:
search = User.is_delete == is_delete
# 处理角色查询role
if role:
search = and_(search, Role.role_id == role)
# 处理排序方式
# 利用属性名反射类属性
if is_desc:
order_type = desc(User.getAttrFromName(User, order_by))
else:
order_type = User.getAttrFromName(User, order_by)
# 查询数量
total = db.query(func.count(User.user_id)).outerjoin(User.roles).filter(search).scalar()
# 查询结果集
if page > 0: # page > 0 分页查询
query_obj = db.query(User).outerjoin(User.roles).filter(search).order_by(order_type).offset(temp_page).limit(page_size).all()
else: # page <= 0 全量查询
query_obj = db.query(User).outerjoin(User.roles).filter(search).order_by(order_type).all()
items = [{
"id": obj.id,
"user_id": obj.user_id,
"username": obj.username,
"nickname": obj.nickname,
"email": obj.email,
"avatar": obj.avatar,
"phone": obj.phone,
"gender": obj.gender,
"register_time": obj.register_time,
"last_login_time": obj.last_login_time,
"last_login_ip": obj.last_login_ip,
"wechat_openid": obj.wechat_openid,
"country": obj.country,
"province": obj.province,
"city": obj.city,
"roles": obj.roles,
"is_delete": obj.is_delete,
"update_time": obj.update_time
} for obj in query_obj]
return {
"items": items,
"total": total
}
@staticmethod
def get_by_email(db: Session, *, email: str) -> Optional[User]:
"""
通过email获取用户
参数里面的* 表示 后面调用的时候 要用指定参数的方法调用
正确调用方式
curd_user.get_by_email(db, email="xxx")
错误调用方式
curd_user.get_by_email(db, "xxx")
:param db:
:param email:
:return:
"""
return db.query(User).filter(User.email == email).first()
@staticmethod
def get_by_username(db: Session, *, username: str) -> Optional[User]:
"""
通过用户名获取用户
"""
return db.query(User).filter(User.username == username).first()
def authenticate(self, db: Session, *, username: str, password: str, ip: str) -> Optional[User]:
user = self.get_by_username(db, username=username)
if not user:
return None
if not verify_password(password, user.hashed_password):
return None
user.last_login_time = datetime.now()
user.last_login_ip = ip
login_history = LoginHistory(
user_id = user.user_id,
username = user.username,
login_time = user.last_login_time,
login_ipv4 = user.last_login_ip
)
user.login_histories.append(login_history)
db.commit()
db.refresh(user)
return user
def authenticate_by_email(self, db: Session, *, email: str, password: str) -> Optional[User]:
user = self.get_by_email(db, email=email)
if not user:
return None
if not verify_password(password, user.hashed_password):
return None
return user
@staticmethod
def is_active(user: User) -> bool:
return user.is_active == 1
@staticmethod
def is_delete(user: User) -> bool:
return user.is_delete == 1
@staticmethod
def is_exist(db: Session, user_in: user_schema.UserCreate) -> bool:
user = db.query(User).filter(User.username == user_in.username).first()
if user:
return True
else:
return False
@staticmethod
def create(db: Session, *, obj_in: user_schema.UserCreate) -> User:
db_user = User(
username=obj_in.username,
nickname=obj_in.nickname,
email=obj_in.email,
hashed_password=get_password_hash(obj_in.password),
q_limit_day=obj_in.q_limit_day,
tokens_limit=obj_in.tokens_limit,
# avatar=obj_in.avatar,
is_active=obj_in.is_active
)
for role_id in obj_in.roles:
role = crud_role.get_by_id(db, role_id=role_id)
if (role):
db_user.roles.append(role)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
@staticmethod
def update(db: Session, *, obj_in: user_schema.UserUpdate) -> User:
db_obj = db.query(User).filter(User.username == obj_in.username).first()
if db_obj:
db_obj.nickname = obj_in.nickname
db_obj.email = obj_in.email
db_obj.hashed_password = get_password_hash(obj_in.password) if obj_in.password else db_obj.hashed_password
if obj_in.q_day_limit >= 0:
db_obj.q_day_limit = obj_in.q_day_limit
if obj_in.tokens_limit >= 0:
db_obj.tokens_limit = obj_in.tokens_limit
db_obj.roles.clear()
for role_id in obj_in.roles:
role = crud_role.get_by_id(db, role_id=role_id)
if (role):
db_obj.roles.append(role)
db_obj.is_active = obj_in.is_active
db_obj.is_delete = obj_in.is_delete
db.commit()
db.refresh(db_obj)
return db_obj