用户注册接口完成

This commit is contained in:
qiangyanwen 2022-05-29 11:56:43 +08:00
parent f7350f7226
commit 2eada0d5b2
14 changed files with 488 additions and 3 deletions

View File

@ -0,0 +1,24 @@
"""first comment
Revision ID: 147ef859a38e
Revises:
Create Date: 2022-05-29 11:20:41.685332
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '147ef859a38e'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
pass
def downgrade():
pass

View File

@ -5,10 +5,20 @@
# @File :user_api.py
from fastapi import APIRouter, Body, Depends, Query
from typing_extensions import Annotated
from entity.user_entity import UserFrom
from sqlalchemy.orm import Session
from config.db_session import get_db
from service.user_service import user_service
from utils.response import success_200,error_211
router = APIRouter(prefix="/api", tags=["用户模块"])
@router.post("/register/user")
def register():
return {"code": 200, "message": "用户注册成功"}
@router.post("/register/user", summary="注册用户", name="注册用户")
def register(user: Annotated[UserFrom, Body(...)], db: Session = Depends(get_db)):
user = user_service(db, user)
if isinstance(user,dict):
return success_200(data=user, message="用户注册成功")
return error_211(message=user)

37
config/db_session.py Normal file
View File

@ -0,0 +1,37 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:26
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :db_session.py.py
from typing import Generator
from config.database import SessionLocal
from sqlalchemy.orm import Session
def get_db() -> Generator:
db = SessionLocal()
try:
yield db
finally:
db.close()
def db_add(db: Session, model: object):
db.add(model)
db.commit()
db.refresh(model)
def db_save(db: Session, model: object):
db.commit()
db.flush()
db.refresh(model)
def db_delete(db: Session, model: object):
db.delete(model)
db.commit()
db.flush()
__all__ = ["get_db", "db_add", "db_save","db_delete"]

25
config/factory.py Normal file
View File

@ -0,0 +1,25 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:51
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :factory.py
from datetime import datetime
class AutomationResponse(object):
@staticmethod
def model_to_dict(obj, *ignore: str):
data = dict()
for c in obj.__table__.columns:
if c.name in ignore:
continue
val = getattr(obj, c.name)
if isinstance(val, datetime):
data[c.name] = val.strftime("%Y-%m-%d %H:%M:%S")
else:
data[c.name] = val
return data
@staticmethod
def model_to_list(data: list, *ignore: str):
return [AutomationResponse.model_to_dict(x, *ignore) for x in data]

13
entity/user_entity.py Normal file
View File

@ -0,0 +1,13 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:22
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :user_entity.py.py
from pydantic import BaseModel, EmailStr
from typing import Optional
class UserFrom(BaseModel):
username: str
password: str
email: EmailStr

15
enums/enums.py Normal file
View File

@ -0,0 +1,15 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:47
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :enums.py.py
from enum import Enum
class RegisterUser(Enum):
USER_IS_EXISTS_ALREADY = "用户名或邮箱已存在,请使用您的用户名登录"
USER_CONST = "用户可以进行注册"
USER_ID_ERROR = "用户不存在,请检查规范数据"
DELETE_USER_SUCCESS = "用户删除成功"
LOGIN_USER_ERROR = "用户名或密码错误"
USER_DISABLED = "用户已被禁用,请联系管理员"

View File

@ -318,3 +318,53 @@
2022-05-29 11:13:54 | MainThread:8595076608 | create_app:app:37 - INFO - Server address http://192.168.1.107:8000
2022-05-29 11:13:54 | MainThread:8595076608 | create_app:app:38 - INFO - Api doc address http://192.168.1.107:8000/docs
2022-05-29 11:13:54 | MainThread:8595076608 | create_app:app:39 - INFO - Api redoc address http://192.168.1.107:8000/redoc
2022-05-29 11:20:51 | MainThread:8642307584 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:20:51 | MainThread:8642307584 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:21:09 | MainThread:8671749632 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:21:09 | MainThread:8671749632 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:23:47 | MainThread:8639759872 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:23:47 | MainThread:8639759872 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:15 - INFO - loading application configuration
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:16 - INFO - create FastApi app object
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:25 - INFO - Adding a New route success
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:26 - INFO - Start registering middleware
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:36 - INFO - Application started successfully:CORSMiddleware
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:37 - INFO - Server address http://192.168.1.107:8000
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:38 - INFO - Api doc address http://192.168.1.107:8000/docs
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:39 - INFO - Api redoc address http://192.168.1.107:8000/redoc
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:15 - INFO - loading application configuration
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:16 - INFO - create FastApi app object
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:25 - INFO - Adding a New route success
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:26 - INFO - Start registering middleware
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:36 - INFO - Application started successfully:CORSMiddleware
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:37 - INFO - Server address http://192.168.1.107:8000
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:38 - INFO - Api doc address http://192.168.1.107:8000/docs
2022-05-29 11:23:47 | MainThread:8639759872 | create_app:app:39 - INFO - Api redoc address http://192.168.1.107:8000/redoc
2022-05-29 11:26:08 | MainThread:8675997184 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:26:08 | MainThread:8675997184 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:15 - INFO - loading application configuration
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:16 - INFO - create FastApi app object
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:25 - INFO - Adding a New route success
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:26 - INFO - Start registering middleware
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:36 - INFO - Application started successfully:CORSMiddleware
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:37 - INFO - Server address http://192.168.1.107:8000
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:38 - INFO - Api doc address http://192.168.1.107:8000/docs
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:39 - INFO - Api redoc address http://192.168.1.107:8000/redoc
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:15 - INFO - loading application configuration
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:16 - INFO - create FastApi app object
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:25 - INFO - Adding a New route success
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:26 - INFO - Start registering middleware
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:36 - INFO - Application started successfully:CORSMiddleware
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:37 - INFO - Server address http://192.168.1.107:8000
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:38 - INFO - Api doc address http://192.168.1.107:8000/docs
2022-05-29 11:26:08 | MainThread:8675997184 | create_app:app:39 - INFO - Api redoc address http://192.168.1.107:8000/redoc
2022-05-29 11:41:47 | MainThread:8607176192 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:41:47 | MainThread:8607176192 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:47:43 | MainThread:8594392576 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:47:43 | MainThread:8594392576 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:48:30 | MainThread:8627926528 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:48:30 | MainThread:8627926528 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:51:39 | MainThread:8638133760 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:51:39 | MainThread:8638133760 | <module>:__init__:22 - INFO - loading environment configuration file
2022-05-29 11:56:17 | MainThread:8672949760 | <module>:__init__:16 - INFO - start the automation service development environment
2022-05-29 11:56:17 | MainThread:8672949760 | <module>:__init__:22 - INFO - loading environment configuration file

5
repository/__init__.py Normal file
View File

@ -0,0 +1,5 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:28
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :__init__.py.py

View File

@ -0,0 +1,25 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:29
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :user_repository.py
from sqlalchemy import or_
from sqlalchemy.orm import Session
from config.db_session import db_add
from config.factory import AutomationResponse
from entity.user_entity import UserFrom
from models.model import User
def check_user_email(db: Session, user: UserFrom) -> bool:
user = db.query(User).filter(or_(User.username == user.username, user.email == user.email)).first()
if user:
return True
return False
def register_user(db: Session, user: UserFrom)->dict:
us_er = User(**user.dict())
db_add(db, us_er)
return AutomationResponse.model_to_dict(us_er, "password")

5
service/__init__.py Normal file
View File

@ -0,0 +1,5 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:44
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :__init__.py.py

19
service/user_service.py Normal file
View File

@ -0,0 +1,19 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:45
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :user_service.py
from sqlalchemy.orm import Session
from entity.user_entity import UserFrom
from enums.enums import RegisterUser
from repository.user_repository import check_user_email
from utils.jwt_token import get_md5_pwd
from repository.user_repository import register_user
def user_service(db: Session, user: UserFrom):
user.password = get_md5_pwd(user.password)
is_true = check_user_email(db, user)
if is_true:
return RegisterUser.USER_IS_EXISTS_ALREADY
return register_user(db, user)

158
utils/jsonable_encoder.py Normal file
View File

@ -0,0 +1,158 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:40
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :jsonable_encoder.py.py
import dataclasses
from collections import defaultdict
from enum import Enum
from pathlib import PurePath
from types import GeneratorType
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union
from pydantic import BaseModel
from pydantic.json import ENCODERS_BY_TYPE
SetIntStr = Set[Union[int, str]]
DictIntStrAny = Dict[Union[int, str], Any]
def generate_encoders_by_class_tuples(
type_encoder_map: Dict[Any, Callable[[Any], Any]]
) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(
tuple
)
for type_, encoder in type_encoder_map.items():
encoders_by_class_tuples[encoder] += (type_,)
return encoders_by_class_tuples
encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE)
def jsonable_encoder(
obj: Any,
include: Optional[Union[SetIntStr, DictIntStrAny]] = None,
exclude: Optional[Union[SetIntStr, DictIntStrAny]] = None,
by_alias: bool = True,
exclude_unset: bool = False,
exclude_defaults: bool = False,
exclude_none: bool = False,
custom_encoder: Dict[Any, Callable[[Any], Any]] = {},
sqlalchemy_safe: bool = True,
) -> Any:
if include is not None and not isinstance(include, (set, dict)):
include = set(include)
if exclude is not None and not isinstance(exclude, (set, dict)):
exclude = set(exclude)
if isinstance(obj, BaseModel):
encoder = getattr(obj.__config__, "json_encoders", {})
if custom_encoder:
encoder.update(custom_encoder)
obj_dict = obj.dict(
include=include, # type: ignore # in Pydantic
exclude=exclude, # type: ignore # in Pydantic
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_none=exclude_none,
exclude_defaults=exclude_defaults,
)
if "__root__" in obj_dict:
obj_dict = obj_dict["__root__"]
return jsonable_encoder(
obj_dict,
exclude_none=exclude_none,
exclude_defaults=exclude_defaults,
custom_encoder=encoder,
sqlalchemy_safe=sqlalchemy_safe,
)
if dataclasses.is_dataclass(obj):
return dataclasses.asdict(obj)
if isinstance(obj, Enum):
return obj.value
if isinstance(obj, PurePath):
return str(obj)
if isinstance(obj, (str, int, float, type(None))):
return obj
if isinstance(obj, dict):
encoded_dict = {}
for key, value in obj.items():
if (
(
not sqlalchemy_safe
or (not isinstance(key, str))
or (not key.startswith("_sa"))
)
and (value is not None or not exclude_none)
and ((include and key in include) or not exclude or key not in exclude)
):
encoded_key = jsonable_encoder(
key,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_none=exclude_none,
custom_encoder=custom_encoder,
sqlalchemy_safe=sqlalchemy_safe,
)
encoded_value = jsonable_encoder(
value,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_none=exclude_none,
custom_encoder=custom_encoder,
sqlalchemy_safe=sqlalchemy_safe,
)
encoded_dict[encoded_key] = encoded_value
return encoded_dict
if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)):
encoded_list = []
for item in obj:
encoded_list.append(
jsonable_encoder(
item,
include=include,
exclude=exclude,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
custom_encoder=custom_encoder,
sqlalchemy_safe=sqlalchemy_safe,
)
)
return encoded_list
if custom_encoder:
if type(obj) in custom_encoder:
return custom_encoder[type(obj)](obj)
else:
for encoder_type, encoder in custom_encoder.items():
if isinstance(obj, encoder_type):
return encoder(obj)
if type(obj) in ENCODERS_BY_TYPE:
return ENCODERS_BY_TYPE[type(obj)](obj)
for encoder, classes_tuple in encoders_by_class_tuples.items():
if isinstance(obj, classes_tuple):
return encoder(obj)
errors: List[Exception] = []
try:
data = dict(obj)
except Exception as e:
errors.append(e)
try:
data = vars(obj)
except Exception as e:
errors.append(e)
raise ValueError(errors)
return jsonable_encoder(
data,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
custom_encoder=custom_encoder,
sqlalchemy_safe=sqlalchemy_safe,
)

55
utils/jwt_token.py Normal file
View File

@ -0,0 +1,55 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:41
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :jwt_token.py.py
import hashlib
from datetime import datetime, timedelta
from fastapi.security import OAuth2PasswordBearer
from fastapi import Depends, HTTPException, status
from passlib.context import CryptContext
from jose import jwt, JWTError
from config import settings
crypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_hash_pwd(password: str):
return crypt_context.hash(password)
def get_md5_pwd(pwd: str):
m = hashlib.md5()
m.update(pwd.encode("utf-8"))
return m.hexdigest()
def create_token(data: dict, expire_time):
if expire_time:
expire = datetime.utcnow() + expire_time
else:
expire = datetime.utcnow() + timedelta(minutes=30)
data.update({"exp": expire})
token = jwt.encode(data, settings.ACCESS.SECRET_KEY, algorithm=settings.ACCESS.ALGORITHM)
return token
oauth_scame = OAuth2PasswordBearer(tokenUrl="/api/login")
def parse_token(token: str = Depends(oauth_scame)):
token_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="token不正确或已过期",
headers={"WWW-Authenticate": "Bearer"}
)
try:
jwt_data = jwt.decode(token, settings.ACCESS.SECRET_KEY, algorithms=settings.ACCESS.ALGORITHM)
id = jwt_data.get("id")
if id is None or id == "":
raise token_exception
except JWTError:
raise token_exception
return id

44
utils/response.py Normal file
View File

@ -0,0 +1,44 @@
# _*_ coding: utf-8 _*_
# @Time :2022/5/29 11:39
# @Email :508737091@qq.com
# @Author :qiangyanwen
# @File :response.py
from dataclasses import make_dataclass
from typing import Union
from fastapi.responses import JSONResponse
from fastapi import status
from .jsonable_encoder import jsonable_encoder
def success_200(data: Union[list, dict, str] = None, code: int = 200, message: str = "Success") -> JSONResponse:
return response_base(status.HTTP_200_OK, data, code, message).Success()
def error_211(data: Union[list, dict, str] = None, code: int = 211, message: str = "error") -> JSONResponse:
return response_base(status.HTTP_200_OK, data, code, message).Success()
def error_400(data: Union[list, dict, str] = None, code: int = 400, message: str = "请求失败") -> JSONResponse:
return response_base(status.HTTP_400_BAD_REQUEST, data, code, message).Success()
def error_403(data: Union[list, dict, str] = None, code: int = 403, message: str = "Token 认证失败") -> JSONResponse:
return response_base(status.HTTP_403_FORBIDDEN, data, code, message).Success()
def error_500(data: Union[list, dict, str] = None, code: int = 500,
message: str = "Internal Server Error") -> JSONResponse:
return response_base(status.HTTP_500_INTERNAL_SERVER_ERROR, data, code, message).Success()
response_base = make_dataclass(
"response_base",
[('http_status', int, None), ('data', Union[list, dict, str], None), ('code', int, None), ('message', str, None)],
namespace={
"Success": lambda self: JSONResponse(
status_code=self.http_status,
content=jsonable_encoder({'code': self.code, 'message': self.message, 'data': self.data})
)
}
)