add profile picture support and rearrange things to be slightly more sane

This commit is contained in:
CEF Server 2024-05-19 23:22:40 +00:00
parent 9148e2068f
commit 15e1018476
6 changed files with 100 additions and 10 deletions

View file

@ -1,21 +1,13 @@
from fastapi import FastAPI, UploadFile, Request, Depends from fastapi import FastAPI, UploadFile, Request, Depends
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from minio import Minio
import mimetypes import mimetypes
import re
from .auth import JWTBearer from .auth import JWTBearer
from .sql import SessionMaker, Uploads from .sql import SessionMaker, Uploads
from . import util from . import util
import config import config
from datetime import datetime, timedelta from datetime import datetime, timedelta
from . import endpoints
minioClient = Minio(
config.MINIO_ADDR,
access_key=config.MINIO_ACCESS_KEY,
secret_key=config.MINIO_SECRET_KEY,
)
app = FastAPI() app = FastAPI()
app.add_middleware( app.add_middleware(
@ -26,6 +18,8 @@ app.add_middleware(
allow_headers=["*"], allow_headers=["*"],
) )
app.include_router(endpoints.router)
@app.post("/upload", dependencies=[Depends(JWTBearer())]) @app.post("/upload", dependencies=[Depends(JWTBearer())])
async def upload(file: UploadFile, request: Request): async def upload(file: UploadFile, request: Request):
if file.size > config.MAX_FILE_SIZE: if file.size > config.MAX_FILE_SIZE:
@ -40,11 +34,12 @@ async def upload(file: UploadFile, request: Request):
existing.expiry = datetime.now() + timedelta(days=7) existing.expiry = datetime.now() + timedelta(days=7)
else: else:
mime = mimetypes.guess_type(safeFilename) mime = mimetypes.guess_type(safeFilename)
minioClient.put_object("uploads", sha, file.file, file.size, content_type=mime[0]) util.minioClient.put_object("uploads", sha, file.file, file.size, content_type=mime[0])
up = Uploads(hash=sha) up = Uploads(hash=sha)
session.add(up) session.add(up)
session.commit() session.commit()
return {"url": f"https://{config.MINIO_ADDR}/uploads/{sha}/{safeFilename}"} return {"url": f"https://{config.MINIO_ADDR}/uploads/{sha}/{safeFilename}"}
__all__ = ["sql", "auth", "util"] __all__ = ["sql", "auth", "util"]

View file

@ -0,0 +1,9 @@
from fastapi import APIRouter
import os
import importlib
router = APIRouter()
for module in os.listdir(os.path.dirname(__file__)):
if module == '__init__.py' or module[-3:] != '.py':
continue
importlib.import_module("."+module[:-3], package="cef_3M.endpoints")

66
cef_3M/endpoints/pfp.py Normal file
View file

@ -0,0 +1,66 @@
import mimetypes
import time
from . import router
from fastapi import UploadFile, Request, Depends
from ..util import minioClient
from ..auth import JWTBearer
import config
from pywuffs import ImageDecoderType
from pywuffs.aux import (
ImageDecoder,
ImageDecoderConfig,
)
pfpConfig = ImageDecoderConfig()
pfpConfig.max_incl_dimension = 400
pfpConfig.enabled_decoders = [
ImageDecoderType.GIF,
ImageDecoderType.PNG,
ImageDecoderType.JPEG,
]
iconConfig = ImageDecoderConfig()
iconConfig.max_incl_dimension = 24
iconConfig.enabled_decoders = [
ImageDecoderType.PNG,
]
@router.post("/pfp/upload", dependencies=[Depends(JWTBearer())])
async def pfpUpload(file: UploadFile, request: Request):
if file.size > config.MAX_PFP_SIZE:
return {"error": "file too big"}
whoami = request.state.jwt
username = whoami["account"].lower()
# It's not the path I exactly wanted, but this will have to do - WUFFS ensures that the file is valid then we just save it to the server
# I hope there's no issue in doing that...
decoder = ImageDecoder(pfpConfig)
data = await file.read()
decoded = decoder.decode(data)
if decoded.error_message:
return {"error": "invalid file"}
file.file.seek(0)
mime = mimetypes.guess_type(file.filename)
minioClient.put_object("pfp", username, file.file, file.size, content_type=mime[0])
return {"url": f"https://{config.MINIO_ADDR}/pfp/{username}?{time.time():.0f}"}
@router.post("/pfp/uploadIcon", dependencies=[Depends(JWTBearer())])
async def pfpUpload(file: UploadFile, request: Request):
if file.size > config.MAX_PFP_SIZE:
return {"error": "file too big"}
whoami = request.state.jwt
username = whoami["account"].lower()
decoder = ImageDecoder(iconConfig)
data = await file.read()
decoded = decoder.decode(data)
if decoded.error_message:
return {"error": "invalid file"}
file.file.seek(0)
mime = mimetypes.guess_type(file.filename)
minioClient.put_object("pfp", username+"/icon", file.file, file.size, content_type=mime[0])
return {"url": f"https://{config.MINIO_ADDR}/pfp/{username}/icon?{time.time():.0f}"}

View file

@ -1,5 +1,8 @@
import hashlib import hashlib
import re import re
import config
from minio import Minio
from fastapi import UploadFile from fastapi import UploadFile
@ -13,3 +16,9 @@ async def SHA256(f: UploadFile) -> str:
sha.update(data) sha.update(data)
await f.seek(0) await f.seek(0)
return sha.hexdigest() return sha.hexdigest()
minioClient = Minio(
config.MINIO_ADDR,
access_key=config.MINIO_ACCESS_KEY,
secret_key=config.MINIO_SECRET_KEY,
)

View file

@ -6,5 +6,9 @@ MINIO_ACCESS_KEY = "access-key-goes-here"
MINIO_SECRET_KEY = "secret-key-goes-here" MINIO_SECRET_KEY = "secret-key-goes-here"
MAX_FILE_SIZE = 1024*1024*20 MAX_FILE_SIZE = 1024*1024*20
MAX_PFP_SIZE = 1024*1024*1.5
# It's a 24x24 image, you can fit that in 32k
MAX_ICON_SIZE = 1024*32
# Need to figure out how to make this cooperate more # Need to figure out how to make this cooperate more
ALLOWED_DOMAINS = ["*"] ALLOWED_DOMAINS = ["*"]

View file

@ -15,14 +15,18 @@ httpcore==1.0.5
httptools==0.6.1 httptools==0.6.1
httpx==0.27.0 httpx==0.27.0
idna==3.4 idna==3.4
inflect==7.2.1
Jinja2==3.1.4 Jinja2==3.1.4
Mako==1.3.5 Mako==1.3.5
markdown-it-py==3.0.0 markdown-it-py==3.0.0
MarkupSafe==2.1.5 MarkupSafe==2.1.5
mdurl==0.1.2 mdurl==0.1.2
minio==7.1.17 minio==7.1.17
more-itertools==10.2.0
mysqlclient==2.2.4 mysqlclient==2.2.4
numpy==1.26.4
orjson==3.10.3 orjson==3.10.3
pillow==10.3.0
pycparser==2.21 pycparser==2.21
pydantic==2.4.2 pydantic==2.4.2
pydantic_core==2.10.1 pydantic_core==2.10.1
@ -31,12 +35,15 @@ PyJWT==2.8.0
PyMySQL==1.1.0 PyMySQL==1.1.0
python-dotenv==1.0.1 python-dotenv==1.0.1
python-multipart==0.0.9 python-multipart==0.0.9
pywuffs==1.2.1
PyYAML==6.0.1 PyYAML==6.0.1
rich==13.7.1 rich==13.7.1
shellingham==1.5.4 shellingham==1.5.4
sniffio==1.3.0 sniffio==1.3.0
sqlacodegen @ git+https://github.com/agronholm/sqlacodegen@2a6053224d28da27c9b89aa611b9dd4c27637fe6
SQLAlchemy==2.0.30 SQLAlchemy==2.0.30
starlette==0.37.2 starlette==0.37.2
typeguard==4.2.1
typer==0.12.3 typer==0.12.3
typing_extensions==4.8.0 typing_extensions==4.8.0
ujson==5.10.0 ujson==5.10.0