voice state - also there was no git history here so im just force pushing
This commit is contained in:
commit
9c41144985
9 changed files with 207 additions and 0 deletions
46
cef_3M/__init__.py
Normal file
46
cef_3M/__init__.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
from fastapi import FastAPI, UploadFile, Request, Depends
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from minio import Minio
|
||||
import mimetypes
|
||||
import re
|
||||
|
||||
from . import sql
|
||||
from .auth import JWTBearer
|
||||
from . import util
|
||||
import config
|
||||
|
||||
|
||||
minioClient = Minio(
|
||||
config.MINIO_ADDR,
|
||||
access_key=config.MINIO_ACCESS_KEY,
|
||||
secret_key=config.MINIO_SECRET_KEY,
|
||||
).g
|
||||
|
||||
app = FastAPI()
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=config.ALLOWED_DOMAINS,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
@app.post("/upload", dependencies=[Depends(JWTBearer())])
|
||||
async def upload(file: UploadFile, request: Request):
|
||||
if file.size > config.MAX_FILE_SIZE:
|
||||
return {"error": "file too big"}
|
||||
spl = file.filename.rsplit(".", 1)
|
||||
safeFilename = util.safeName.sub("_", spl[0])
|
||||
if len(spl) == 2:
|
||||
safeFilename += "." + util.safeName.sub("_", spl[1])
|
||||
sha = await util.SHA256(file)
|
||||
if sql.SqlExecuteFetchOne("SELECT * FROM `uploads` WHERE `hash` = %s", sha):
|
||||
sql.SqlExecute("UPDATE `uploads` SET `expiry` = (NOW() + INTERVAL 1 WEEK) WHERE `hash` = %s", sha)
|
||||
else:
|
||||
mime = mimetypes.guess_type(safeFilename)
|
||||
minioClient.put_object("uploads", sha, file.file, file.size, content_type=mime[0])
|
||||
sql.SqlExecute("INSERT INTO `uploads`(`hash`) VALUES (%s)", sha)
|
||||
return {"url": f"https://{config.MINIO_ADDR}/uploads/{sha}/{safeFilename}"}
|
||||
|
||||
|
||||
__all__ = ["sql", "auth", "util"]
|
||||
45
cef_3M/auth.py
Normal file
45
cef_3M/auth.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import time
|
||||
import jwt
|
||||
from fastapi.security import HTTPBearer
|
||||
|
||||
import config
|
||||
from fastapi import Request, HTTPException
|
||||
|
||||
JWT_PUBKEY = open(config.SECRETKEY).read()
|
||||
JWT_ALGORITHM = "RS256"
|
||||
|
||||
|
||||
def decodeJWT(token: str) -> dict:
|
||||
try:
|
||||
decoded_token = jwt.decode(token, JWT_PUBKEY, algorithms=[JWT_ALGORITHM])
|
||||
return decoded_token if decoded_token["exp"] >= time.time() else None
|
||||
except:
|
||||
return {}
|
||||
|
||||
|
||||
class JWTBearer(HTTPBearer):
|
||||
def __init__(self, auto_error: bool = True):
|
||||
super(JWTBearer, self).__init__(auto_error=auto_error)
|
||||
|
||||
async def __call__(self, request: Request):
|
||||
credentials = await super(JWTBearer, self).__call__(request)
|
||||
if credentials:
|
||||
if not credentials.scheme == "Bearer":
|
||||
raise HTTPException(status_code=403, detail="Invalid authentication scheme.")
|
||||
if not self.verify_jwt(credentials.credentials):
|
||||
raise HTTPException(status_code=403, detail="Invalid or expired token.")
|
||||
request.state.jwt = decodeJWT(credentials.credentials)
|
||||
return credentials.credentials
|
||||
else:
|
||||
raise HTTPException(status_code=403, detail="Invalid authorization code.")
|
||||
|
||||
def verify_jwt(self, jwtoken: str) -> bool:
|
||||
isTokenValid: bool = False
|
||||
|
||||
try:
|
||||
payload = decodeJWT(jwtoken)
|
||||
except:
|
||||
payload = None
|
||||
if payload:
|
||||
isTokenValid = True
|
||||
return isTokenValid
|
||||
52
cef_3M/sql.py
Normal file
52
cef_3M/sql.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import pymysql
|
||||
import config
|
||||
from typing import Tuple
|
||||
|
||||
pymysql.install_as_MySQLdb()
|
||||
|
||||
import MySQLdb as maraidb
|
||||
|
||||
DB: pymysql = maraidb.connect(user=config.MARIADB_USER, password=config.MARIADB_PASSWORD, db=config.MARIADB_DB, autocommit=True)
|
||||
DB.autocommit(True)
|
||||
|
||||
def reconnect(f):
|
||||
def wrap(*args, **kwargs):
|
||||
DB.ping()
|
||||
return f(*args, **kwargs)
|
||||
return wrap
|
||||
|
||||
@reconnect
|
||||
def SqlExecute(query, *args):
|
||||
cursor = DB.cursor(pymysql.cursors.DictCursor)
|
||||
cursor.execute(query, args)
|
||||
cursor.close()
|
||||
return cursor.lastrowid
|
||||
|
||||
@reconnect
|
||||
def SqlExecuteFetchOne(query, *args):
|
||||
cursor = DB.cursor(pymysql.cursors.DictCursor)
|
||||
cursor.execute(query, args)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
return row
|
||||
|
||||
@reconnect
|
||||
def MultipleSqlExecuteFetchOne(*queries: Tuple[str, tuple]):
|
||||
cursor = DB.cursor(pymysql.cursors.DictCursor)
|
||||
ret = []
|
||||
for query, args in queries:
|
||||
cursor.execute(query, args)
|
||||
ret.append(cursor.fetchone())
|
||||
cursor.close()
|
||||
return ret
|
||||
|
||||
@reconnect
|
||||
def SqlExecuteFetchAll(query, *args):
|
||||
cursor = DB.cursor(pymysql.cursors.DictCursor)
|
||||
cursor.execute(query, args)
|
||||
rows = cursor.fetchall()
|
||||
cursor.close()
|
||||
return rows
|
||||
|
||||
|
||||
CACHE = {}
|
||||
15
cef_3M/util.py
Normal file
15
cef_3M/util.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import hashlib
|
||||
import re
|
||||
|
||||
from fastapi import UploadFile
|
||||
|
||||
|
||||
safeName = re.compile(r"[^\w\d\.-]")
|
||||
|
||||
# If this gets too out of hand, put an async breakpoint to allow other things to be handled while the hash occurs
|
||||
async def SHA256(f: UploadFile) -> str:
|
||||
sha = hashlib.sha256()
|
||||
while data := await f.read(65535):
|
||||
sha.update(data)
|
||||
await f.seek(0)
|
||||
return sha.hexdigest()
|
||||
Loading…
Add table
Add a link
Reference in a new issue