init
This commit is contained in:
1
fuware/__init__.py
Normal file
1
fuware/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__version__ = "develop"
|
15
fuware/const.py
Normal file
15
fuware/const.py
Normal file
@ -0,0 +1,15 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
SERCET_KEY = b"oWNhXlfo666JlMHk6UHYxeNB6z_CA2MisDDZJe4N0yc="
|
||||
COOKIE_KEY = os.getenv('VITE_LOGIN_KEY') or '7fo24CMyIc'
|
||||
# URL_DATABASE = "postgresql://{0}:{1}@{2}:{3}/{4}".format(
|
||||
# os.getenv('LOL_DB_USER'),
|
||||
# os.getenv('LOL_DB_PASSWORD'),
|
||||
# os.getenv('LOL_DB_HOST'),
|
||||
# os.getenv('LOL_DB_PORT'),
|
||||
# os.getenv('LOL_DB_NAME'),
|
||||
# )
|
||||
URL_DATABASE = "sqlite:///./test.db"
|
1
fuware/db/__init__.py
Normal file
1
fuware/db/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .db_setup import *
|
1
fuware/db/controller/__init__.py
Normal file
1
fuware/db/controller/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .user import *
|
20
fuware/db/controller/user.py
Normal file
20
fuware/db/controller/user.py
Normal file
@ -0,0 +1,20 @@
|
||||
from sqlalchemy.orm import Session
|
||||
from db.models import User
|
||||
from ultis import get_password_hash
|
||||
import schemas
|
||||
|
||||
def get_user(db: Session, user_id: str):
|
||||
return db.query(User).filter(User.id == user_id).first()
|
||||
|
||||
def get_user_by_username(db: Session, usn: str):
|
||||
return db.query(User).filter(User.username == usn).first()
|
||||
|
||||
def get_users(db: Session, skip: int = 0, limit: int = 100):
|
||||
return db.query(User).offset(skip).limit(limit).all()
|
||||
|
||||
def create_user(db: Session, user: schemas.UserCreate):
|
||||
db_user = User(username=user.username, password=get_password_hash(user.password), name=user.name)
|
||||
db.add(db_user)
|
||||
db.commit()
|
||||
db.refresh(db_user)
|
||||
return db_user
|
17
fuware/db/db_setup.py
Normal file
17
fuware/db/db_setup.py
Normal file
@ -0,0 +1,17 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from const import URL_DATABASE
|
||||
|
||||
engine = create_engine(URL_DATABASE)
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False ,autoflush=False, bind=engine)
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
def get_db():
|
||||
db = SessionLocal()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
1
fuware/db/models/__init__.py
Normal file
1
fuware/db/models/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .user import *
|
8
fuware/db/models/mixins.py
Normal file
8
fuware/db/models/mixins.py
Normal file
@ -0,0 +1,8 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Column, DateTime
|
||||
from sqlalchemy.orm import declarative_mixin
|
||||
|
||||
@declarative_mixin
|
||||
class Timestamp:
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
15
fuware/db/models/user.py
Normal file
15
fuware/db/models/user.py
Normal file
@ -0,0 +1,15 @@
|
||||
from db import Base
|
||||
from sqlalchemy import Boolean, Column, String
|
||||
from .mixins import Timestamp
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
import uuid
|
||||
|
||||
class User(Base, Timestamp):
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
|
||||
username = Column(String(100), unique=True, index=True, nullable=False)
|
||||
password = Column(String, index=True, nullable=False)
|
||||
name = Column(String, index=True, nullable=True)
|
||||
is_admin = Column(Boolean, default=False)
|
||||
is_lock = Column(Boolean, default=False)
|
34
fuware/main.py
Normal file
34
fuware/main.py
Normal file
@ -0,0 +1,34 @@
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from routes import authR, userR
|
||||
# from db import engine, models
|
||||
# from sqlalchemy import event
|
||||
# from db.seeds import initialize_table
|
||||
import uvicorn
|
||||
|
||||
# event.listen(models.User.__table__, 'after_create', initialize_table)
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
# models.Base.metadata.create_all(bind=engine)
|
||||
|
||||
@app.exception_handler(HTTPException)
|
||||
async def unicorn_exception_handler(request: Request, exc: HTTPException):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"status": exc.status_code, "data": exc.detail},
|
||||
)
|
||||
|
||||
app.include_router(authR.authRouter)
|
||||
app.include_router(userR.userRouter)
|
||||
|
||||
def main():
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
port=8000,
|
||||
host="0.0.0.0",
|
||||
reload=True
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
50
fuware/routes/authR.py
Normal file
50
fuware/routes/authR.py
Normal file
@ -0,0 +1,50 @@
|
||||
from typing import Any
|
||||
from fastapi import APIRouter, HTTPException, Response, Request, Depends
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from schemas import ReturnValue, User, UserCreate, UserRequest
|
||||
from ultis import root_api_path_build, encryptString, decryptString, verify_password
|
||||
from const import COOKIE_KEY
|
||||
from sqlalchemy.orm import Session
|
||||
from db.controller import get_user_by_username, create_user
|
||||
from db import get_db
|
||||
|
||||
authRouter=APIRouter(prefix=root_api_path_build('/auth'))
|
||||
|
||||
@authRouter.put('/register')
|
||||
def register_user(user: UserCreate, db: Session = Depends(get_db)) -> ReturnValue[Any]:
|
||||
db_user = get_user_by_username(db=db, usn=user.username)
|
||||
if db_user:
|
||||
raise HTTPException(status_code=400, detail="Username already registered!")
|
||||
user_return = create_user(db=db, user=user)
|
||||
return ReturnValue(status=200, data=jsonable_encoder(user_return))
|
||||
|
||||
@authRouter.post('/login', response_model=ReturnValue[User])
|
||||
def user_login(user: UserRequest, response: Response, db: Session = Depends(get_db)) -> ReturnValue[Any]:
|
||||
db_user = get_user_by_username(db, user.username)
|
||||
if not db_user:
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
if not verify_password(user.password, db_user.password):
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
if db_user.is_lock is True:
|
||||
raise HTTPException(status_code=401, detail="Your Account is banned")
|
||||
cookieEncode = encryptString(user.username + ',' + user.password)
|
||||
response.set_cookie(key=COOKIE_KEY, value=cookieEncode.decode('utf-8'))
|
||||
return ReturnValue(status=200, data=jsonable_encoder(db_user))
|
||||
|
||||
@authRouter.get('/logout')
|
||||
def user_logout(response: Response) -> ReturnValue[Any]:
|
||||
response.delete_cookie(key=COOKIE_KEY)
|
||||
return ReturnValue(status=200, data='Logged out')
|
||||
|
||||
def get_auth_user(request: Request, db: Session = Depends(get_db)):
|
||||
"""verify that user has a valid session"""
|
||||
session_id = request.cookies.get(COOKIE_KEY)
|
||||
if not session_id:
|
||||
raise HTTPException(status_code=401, detail="Unauthorized")
|
||||
decrypt_user = decryptString(session_id).split(',')
|
||||
db_user = get_user_by_username(db, decrypt_user[0])
|
||||
if not db_user:
|
||||
raise HTTPException(status_code=403)
|
||||
if not verify_password(decrypt_user[1], db_user.password):
|
||||
raise HTTPException(status_code=401, detail="Your username or password input is wrong!")
|
||||
return True
|
11
fuware/routes/userR.py
Normal file
11
fuware/routes/userR.py
Normal file
@ -0,0 +1,11 @@
|
||||
from typing import Any
|
||||
from fastapi import APIRouter, Depends
|
||||
from schemas import ReturnValue
|
||||
from ultis import root_api_path_build
|
||||
from routes import authR
|
||||
|
||||
userRouter=APIRouter(prefix=root_api_path_build('/user'))
|
||||
|
||||
@userRouter.get('/get-data/', dependencies=[Depends(authR.get_auth_user)])
|
||||
def get_data(url: str = '') -> ReturnValue[Any]:
|
||||
return ReturnValue(status=200, data=url)
|
2
fuware/schemas/__init__.py
Normal file
2
fuware/schemas/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from .common import *
|
||||
from .user import *
|
8
fuware/schemas/common.py
Normal file
8
fuware/schemas/common.py
Normal file
@ -0,0 +1,8 @@
|
||||
from typing import Generic, TypeVar
|
||||
from pydantic import BaseModel
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
class ReturnValue(BaseModel, Generic[T]):
|
||||
status: int
|
||||
data: T
|
24
fuware/schemas/user.py
Normal file
24
fuware/schemas/user.py
Normal file
@ -0,0 +1,24 @@
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
from fastapi import Form
|
||||
|
||||
class UserBase(BaseModel):
|
||||
username: str = Form(...)
|
||||
|
||||
class UserRequest(UserBase):
|
||||
password: str = Form(...)
|
||||
|
||||
class UserCreate(UserRequest):
|
||||
password: str = Form(...)
|
||||
name: str
|
||||
|
||||
class User(UserBase):
|
||||
id: str
|
||||
name: str
|
||||
is_admin: bool
|
||||
is_lock: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
23
fuware/ultis.py
Normal file
23
fuware/ultis.py
Normal file
@ -0,0 +1,23 @@
|
||||
from cryptography.fernet import Fernet
|
||||
from passlib.context import CryptContext
|
||||
from const import SERCET_KEY
|
||||
|
||||
root_path = '/api'
|
||||
pwd_context = CryptContext(schemes=["sha256_crypt"], deprecated="auto")
|
||||
|
||||
def root_api_path_build(path):
|
||||
return root_path + path
|
||||
|
||||
def encryptString(strEncode: str):
|
||||
fernet = Fernet(SERCET_KEY)
|
||||
return fernet.encrypt(strEncode.encode())
|
||||
|
||||
def decryptString(strDecode: str):
|
||||
fernet = Fernet(SERCET_KEY)
|
||||
return fernet.decrypt(strDecode).decode()
|
||||
|
||||
def verify_password(plain_password, hashed_password):
|
||||
return pwd_context.verify(plain_password, hashed_password)
|
||||
|
||||
def get_password_hash(password):
|
||||
return pwd_context.hash(password)
|
Reference in New Issue
Block a user