main.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. # fastapi
  2. from fastapi import FastAPI, Request, Response, HTTPException, status, Depends
  3. from fastapi import templating
  4. from fastapi.templating import Jinja2Templates
  5. from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
  6. from fastapi.middleware.cors import CORSMiddleware
  7. # static file
  8. from fastapi.staticfiles import StaticFiles
  9. # fastapi view function parameters
  10. from typing import List, Optional
  11. # path
  12. import os
  13. # time
  14. import datetime
  15. from datetime import timedelta
  16. # db
  17. import dataset
  18. from passlib import context
  19. import models
  20. # authorize
  21. from passlib.context import CryptContext
  22. pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
  23. from jose import JWTError, jwt
  24. from fastapi_jwt_auth import AuthJWT
  25. from fastapi_jwt_auth.exceptions import AuthJWTException
  26. from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordRequestForm
  27. # app
  28. app = FastAPI()
  29. app.add_middleware(
  30. CORSMiddleware,
  31. allow_origins=["*"],
  32. allow_credentials=True,
  33. allow_methods=["*"],
  34. allow_headers=["*"],
  35. )
  36. SECRET_KEY = "df2f77bd544240801a048bd4293afd8eeb7fff3cb7050e42c791db4b83ebadcd"
  37. ALGORITHM = "HS256"
  38. ACCESS_TOKEN_EXPIRE_MINUTES = 3000
  39. pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
  40. #
  41. app.mount(path='/templates', app=StaticFiles(directory='templates'), name='templates')
  42. app.mount(path='/static', app=StaticFiles(directory='static'), name='static ')
  43. #
  44. templates = Jinja2Templates(directory='templates')
  45. # view
  46. @app.get('/', response_class=HTMLResponse)
  47. async def index(request: Request):
  48. print(request)
  49. return templates.TemplateResponse(name='index.html', context={'request': request})
  50. # @app.get('/make_video', response_class=HTMLResponse)
  51. # async def index(request: Request):
  52. # print(request)
  53. # return templates.TemplateResponse(name='make_video.html', context={'request': request})
  54. @app.get('/login', response_class=HTMLResponse)
  55. async def login(request: Request):
  56. return templates.TemplateResponse(name='login.html', context={'request': request})
  57. @app.post("/login")
  58. async def login_for_access_token(request: Request, form_data: OAuth2PasswordRequestForm = Depends(), Authorize: AuthJWT = Depends()):
  59. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
  60. user = authenticate_user(form_data.username, form_data.password)
  61. if not user:
  62. raise HTTPException(
  63. status_code=status.HTTP_401_UNAUTHORIZED,
  64. detail="Incorrect username or password",
  65. headers={"WWW-Authenticate": "Bearer"},
  66. )
  67. access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
  68. access_token = create_access_token(
  69. data={"sub": user.username}, expires_delta=access_token_expires
  70. )
  71. table = db['users']
  72. user.token = access_token
  73. table.update(dict(user), ['username'])
  74. access_token = Authorize.create_access_token(subject=user.username)
  75. refresh_token = Authorize.create_refresh_token(subject=user.username)
  76. Authorize.set_access_cookies(access_token)
  77. Authorize.set_refresh_cookies(refresh_token)
  78. #return templates.TemplateResponse("index.html", {"request": request, "msg": 'Login'})
  79. return {"access_token": access_token, "token_type": "bearer"}
  80. @app.get('/home', response_class=HTMLResponse)
  81. async def login(request: Request):
  82. return templates.TemplateResponse(name='home.html', context={'request': request})
  83. @app.get('/tower', response_class=HTMLResponse)
  84. async def login(request: Request):
  85. return templates.TemplateResponse(name='tower.html', context={'request': request})
  86. @app.get('/optim', response_class=HTMLResponse)
  87. async def login(request: Request):
  88. return templates.TemplateResponse(name='optim.html', context={'request': request})
  89. @app.get('/vibration', response_class=HTMLResponse)
  90. async def login(request: Request):
  91. return templates.TemplateResponse(name='vibration.html', context={'request': request})
  92. @app.get('/history', response_class=HTMLResponse)
  93. async def login(request: Request):
  94. return templates.TemplateResponse(name='history.html', context={'request': request})
  95. @app.get('/device', response_class=HTMLResponse)
  96. async def login(request: Request):
  97. return templates.TemplateResponse(name='device.html', context={'request': request})
  98. @app.get('/system', response_class=HTMLResponse)
  99. async def login(request: Request):
  100. return templates.TemplateResponse(name='system.html', context={'request': request})
  101. # Login funtion part
  102. def check_user_exists(username):
  103. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
  104. if int(next(iter(db.query('SELECT COUNT(*) FROM aaron_testdb.user WHERE username = "'+username+'"')))['COUNT(*)']) > 0:
  105. return True
  106. else:
  107. return False
  108. def get_user(username: str):
  109. """ 取得使用者資訊(Model) """
  110. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
  111. if not check_user_exists(username): # if user don't exist
  112. return False
  113. user_dict = next(
  114. iter(db.query('SELECT * FROM aaron_testdb.user where username ="'+username+'"')))
  115. user = models.User(**user_dict)
  116. return user
  117. # def user_register(user):
  118. # db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
  119. # table = db['users']
  120. # user.password = get_password_hash(user.password)
  121. # table.insert(dict(user))
  122. def get_password_hash(password):
  123. """ 加密密碼 """
  124. return pwd_context.hash(password)
  125. def verify_password(plain_password, hashed_password):
  126. """ 驗證密碼(hashed) """
  127. return pwd_context.verify(plain_password, hashed_password)
  128. def authenticate_user(username: str, password: str):
  129. """ 連線DB,讀取使用者是否存在。 """
  130. db = dataset.connect('mysql://choozmo:pAssw0rd@db.ptt.cx:3306/aaron_testdb?charset=utf8mb4')
  131. if not check_user_exists(username): # if user don't exist
  132. return False
  133. user_dict = next(iter(db.query('SELECT * FROM aaron_testdb.user where username ="'+username+'"')))
  134. user = models.User(**user_dict)
  135. if not verify_password(password, user.password):
  136. return False
  137. return user
  138. def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
  139. """ 創建token,並設定過期時間。 """
  140. to_encode = data.copy()
  141. if expires_delta:
  142. expire = datetime.utcnow() + expires_delta
  143. else:
  144. expire = datetime.utcnow() + timedelta(minutes=15)
  145. to_encode.update({"exp": expire})
  146. encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
  147. return encoded_jwt