From ee5beb2261010ea9004b50cd616a6d1d920c866e Mon Sep 17 00:00:00 2001 From: lan Date: Mon, 16 Jan 2023 16:03:25 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=B8=AD=EF=BC=8C=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=AD=98=E5=85=A5=E6=95=B0=E6=8D=AE=E5=BA=93=EF=BC=8C?= =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E6=99=BA=E8=83=BD=E7=94=9F=E6=88=90?= =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E5=90=8E=E5=8F=B0=E5=9C=B0=E5=9D=80=EF=BC=8C?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/FUNDING.yml | 4 +- core/__init__.py | 0 core/database.py | 76 ++++++++++++++++ depends.py => core/depends.py | 5 +- storage.py => core/storage.py | 32 ++++--- utils.py => core/utils.py | 8 +- database.py | 42 --------- main.py | 164 +++++++++++----------------------- settings.py | 124 +++++++++++++------------ templates/admin.html | 3 +- templates/index.html | 2 +- 11 files changed, 230 insertions(+), 230 deletions(-) create mode 100644 core/__init__.py create mode 100644 core/database.py rename depends.py => core/depends.py (86%) rename storage.py => core/storage.py (82%) rename utils.py => core/utils.py (91%) delete mode 100644 database.py diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 046ad83..fb71d7f 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,4 +1,4 @@ # These are supported funding model platforms -github: [vastsa] -custom: [https://share.lanol.cn] +github: [ vastsa ] +custom: [ https://share.lanol.cn ] diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/database.py b/core/database.py new file mode 100644 index 0000000..908222f --- /dev/null +++ b/core/database.py @@ -0,0 +1,76 @@ +import datetime + +from sqlalchemy import Boolean, Column, Integer, String, DateTime, JSON, Text, select, insert, delete +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.ext.asyncio import create_async_engine +from sqlalchemy.ext.asyncio.session import AsyncSession +from settings import settings + +engine = create_async_engine(settings.DATABASE_URL) + +Base = declarative_base() + + +class Options(Base): + __tablename__ = 'options' + id = Column(Integer, primary_key=True, index=True) + key = Column(String, unique=True, index=True) + value = Column(JSON) + + +class Codes(Base): + __tablename__ = "codes" + id = Column(Integer, primary_key=True, index=True) + code = Column(String(10), unique=True, index=True) + key = Column(String(30), unique=True) + name = Column(String(500)) + size = Column(Integer) + type = Column(String(20)) + text = Column(Text) + used = Column(Boolean, default=False) + count = Column(Integer, default=-1) + use_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) + exp_time = Column(DateTime, nullable=True) + + +async def init_models(): + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + if await conn.scalar(select(Options).filter(Options.key == 'INSTALL')) is None: + # 如果没有存在install,则清空表,并插入默认数据 + await conn.execute(delete(table=Options)) + await conn.execute(insert(table=Options, values=[ + {'key': 'INSTALL', 'value': settings.VERSION}, + {'key': 'BANNERS', 'value': settings.BANNERS}, + {'key': 'ENABLE_UPLOAD', 'value': settings.ENABLE_UPLOAD}, + {'key': 'MAX_DAYS', 'value': settings.MAX_DAYS}, + {'key': 'ERROR_COUNT', 'value': settings.ERROR_COUNT}, + {'key': 'ERROR_MINUTE', 'value': settings.ERROR_COUNT}, + {'key': 'UPLOAD_COUNT', 'value': settings.UPLOAD_COUNT}, + {'key': 'UPLOAD_MINUTE', 'value': settings.UPLOAD_MINUTE}, + {'key': 'DELETE_EXPIRE_FILES_INTERVAL', 'value': settings.DELETE_EXPIRE_FILES_INTERVAL}, + {'key': 'ADMIN_ADDRESS', 'value': settings.ADMIN_ADDRESS}, + {'key': 'ADMIN_PASSWORD', 'value': settings.ADMIN_PASSWORD}, + {'key': 'FILE_SIZE_LIMIT', 'value': settings.FILE_SIZE_LIMIT}, + {'key': 'TITLE', 'value': settings.TITLE}, + {'key': 'DESCRIPTION', 'value': settings.DESCRIPTION}, + {'key': 'KEYWORDS', 'value': settings.KEYWORDS}, + {'key': 'STORAGE_ENGINE', 'value': settings.STORAGE_ENGINE}, + {'key': 'STORAGE_CONFIG', 'value': {}}, + ])) + print( + f'初始化数据库成功!\n' + f'如您未配置.env文件,将为您随机生成信息\n' + f'您的后台地址为:/{settings.ADMIN_ADDRESS}\n' + f'您的管理员密码为:{settings.ADMIN_PASSWORD}\n' + f'请尽快修改后台信息!\n' + f'FileCodeBox https://github.com/vastsa/FileCodeBox' + ) + else: + # 从数据库更新缓存中的setting + await settings.update(await conn.execute(select(Options).filter())) + + +async def get_session(): + async with AsyncSession(engine, expire_on_commit=False) as s: + yield s diff --git a/depends.py b/core/depends.py similarity index 86% rename from depends.py rename to core/depends.py index 40a5f46..4282259 100644 --- a/depends.py +++ b/core/depends.py @@ -3,7 +3,7 @@ from datetime import datetime, timedelta from fastapi import Header, HTTPException, Request -import settings +from settings import settings async def admin_required(pwd: Union[str, None] = Header(default=None), request: Request = None): @@ -11,6 +11,9 @@ async def admin_required(pwd: Union[str, None] = Header(default=None), request: if pwd != settings.ADMIN_PASSWORD and not settings.ENABLE_UPLOAD: raise HTTPException(status_code=403, detail='本站上传功能已关闭,仅管理员可用') else: + print(settings.ADMIN_PASSWORD) + if settings.ADMIN_PASSWORD is None: + raise HTTPException(status_code=404, detail='您未设置管理员密码,无法使用此功能,请更新配置文件后,重启系统') if not pwd or pwd != settings.ADMIN_PASSWORD: raise HTTPException(status_code=401, detail="密码错误,请重新登录") diff --git a/storage.py b/core/storage.py similarity index 82% rename from storage.py rename to core/storage.py index caf0978..1d88f4a 100644 --- a/storage.py +++ b/core/storage.py @@ -4,11 +4,19 @@ from datetime import datetime from pathlib import Path from typing import BinaryIO from fastapi import UploadFile -import settings -import oss2 + +from core.database import Codes +from settings import settings + +if settings.STORAGE_ENGINE == 'aliyunsystem': + try: + import oss2 + except ImportError: + os.system('pip install oss2') + import oss2 -class AliyunFileStore: +class AliyunFileStorage: def __init__(self): auth = oss2.Auth(settings.KeyId, settings.KeySecret) self.bucket = oss2.Bucket(auth, settings.OSS_ENDPOINT, settings.BUCKET_NAME) @@ -21,10 +29,10 @@ class AliyunFileStore: now = datetime.now() path = f"FileCodeBox/upload/{now.year}/{now.month}/{now.day}" text = f"{path}/{f'{key}.{ext}'}" - return text + return f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/{text}" - async def get_filepath(self, text: str): - text = text.strip(f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/") + async def get_url(self, info: Codes): + text = info.text.strip(f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/") url = self.bucket.sign_url('GET', text, settings.ACCESSTIME, slash_safe=True) return url @@ -47,10 +55,10 @@ class AliyunFileStore: async def save_file(self, file: UploadFile, remote_filepath: str): now = int(datetime.now().timestamp()) - upload_filepath = settings.DATA_ROOT+str(now) + upload_filepath = settings.DATA_ROOT + str(now) await asyncio.to_thread(self._save, upload_filepath, file.file) - self.upload_file(upload_filepath,remote_filepath) - await asyncio.to_thread(os.remove,upload_filepath) + self.upload_file(upload_filepath, remote_filepath) + await asyncio.to_thread(os.remove, upload_filepath) async def delete_files(self, texts): tasks = [self.delete_file(text) for text in texts] @@ -66,10 +74,14 @@ class FileSystemStorage: self.DATA_ROOT = Path(settings.DATA_ROOT) self.STATIC_URL = settings.STATIC_URL self.NAME = "filesystem" + self.DOWN_PATH = '/select' async def get_filepath(self, text: str): return self.DATA_ROOT / text.lstrip(self.STATIC_URL + '/') + async def get_url(self, info: Codes): + return f'{self.DOWN_PATH}?code={info.code}' + async def get_text(self, file: UploadFile, key: str): ext = file.filename.split('.')[-1] now = datetime.now() @@ -122,5 +134,5 @@ class FileSystemStorage: STORAGE_ENGINE = { "filesystem": FileSystemStorage, - "aliyunsystem": AliyunFileStore + "aliyunsystem": AliyunFileStorage } diff --git a/utils.py b/core/utils.py similarity index 91% rename from utils.py rename to core/utils.py index 6290c40..8b0f949 100644 --- a/utils.py +++ b/core/utils.py @@ -3,10 +3,10 @@ import random import asyncio from sqlalchemy import or_, select, delete from sqlalchemy.ext.asyncio.session import AsyncSession -import settings -from database import Codes, engine -from depends import IPRateLimit -from storage import STORAGE_ENGINE +from .database import Codes, engine +from .depends import IPRateLimit +from .storage import STORAGE_ENGINE +from settings import settings storage = STORAGE_ENGINE[settings.STORAGE_ENGINE]() diff --git a/database.py b/database.py deleted file mode 100644 index 53c9b9c..0000000 --- a/database.py +++ /dev/null @@ -1,42 +0,0 @@ -import datetime -from sqlalchemy import Boolean, Column, Integer, String, DateTime, JSON, Text -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.ext.asyncio import create_async_engine -from sqlalchemy.ext.asyncio.session import AsyncSession -import settings - -engine = create_async_engine(settings.DATABASE_URL) - -Base = declarative_base() - - -async def init_models(): - async with engine.begin() as conn: - await conn.run_sync(Base.metadata.create_all) - - -async def get_session(): - async with AsyncSession(engine, expire_on_commit=False) as s: - yield s - - -class Values(Base): - __tablename__ = 'values' - id = Column(Integer, primary_key=True, index=True) - key = Column(String, unique=True) - value = Column(JSON) - - -class Codes(Base): - __tablename__ = "codes" - id = Column(Integer, primary_key=True, index=True) - code = Column(String(10), unique=True, index=True) - key = Column(String(30), unique=True, index=True) - name = Column(String(500)) - size = Column(Integer) - type = Column(String(20)) - text = Column(Text) - used = Column(Boolean, default=False) - count = Column(Integer, default=-1) - use_time = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) - exp_time = Column(DateTime, nullable=True) diff --git a/main.py b/main.py index 1172008..43fd831 100644 --- a/main.py +++ b/main.py @@ -1,29 +1,18 @@ import datetime import uuid -import asyncio from pathlib import Path -import os +from sqlalchemy import select, func, update +from sqlalchemy.ext.asyncio import AsyncSession +from starlette.requests import Request +from starlette.responses import HTMLResponse, FileResponse +from starlette.staticfiles import StaticFiles -try: - from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks - from starlette.requests import Request - from starlette.responses import HTMLResponse, FileResponse - from starlette.staticfiles import StaticFiles - from sqlalchemy import select, update, func - from sqlalchemy.ext.asyncio.session import AsyncSession -except ImportError: - os.system("pip install -r requirements.txt") - from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks - from starlette.requests import Request - from starlette.responses import HTMLResponse, FileResponse - from starlette.staticfiles import StaticFiles - from sqlalchemy import select, update, func - from sqlalchemy.ext.asyncio.session import AsyncSession +from core.utils import error_ip_limit, upload_ip_limit, get_code, storage +from core.depends import admin_required +from settings import settings +from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks -import settings -from utils import delete_expire_files, storage, get_code, error_ip_limit, upload_ip_limit -from database import get_session, Codes, init_models, Values -from depends import admin_required +from core.database import init_models, Options, Codes, get_session # 实例化FastAPI app = FastAPI(debug=settings.DEBUG, docs_url=None, redoc_url=None) @@ -34,28 +23,30 @@ if not DATA_ROOT.exists(): DATA_ROOT.mkdir(parents=True) # 静态文件夹,这个固定就行了,静态资源都放在这里 -app.mount(settings.STATIC_URL, StaticFiles(directory='./static'), name="static") +app.mount('/static', StaticFiles(directory='./static'), name="static") +# 首页页面 +index_html = open('templates/index.html', 'r', encoding='utf-8').read() \ + .replace('{{title}}', settings.TITLE) \ + .replace('{{description}}', settings.DESCRIPTION) \ + .replace('{{keywords}}', settings.KEYWORDS) \ + .replace("'{{fileSizeLimit}}'", str(settings.FILE_SIZE_LIMIT)) +# 管理页面 +admin_html = open('templates/admin.html', 'r', encoding='utf-8').read() \ + .replace('{{title}}', settings.TITLE) \ + .replace('{{description}}', settings.DESCRIPTION) \ + .replace('{{admin_address}}', settings.ADMIN_ADDRESS) \ + .replace('{{keywords}}', settings.KEYWORDS) @app.on_event('startup') async def startup(): # 初始化数据库 await init_models() - # 启动后台任务,不定时删除过期文件 - asyncio.create_task(delete_expire_files()) -# 首页页面 -index_html = open('templates/index.html', 'r', encoding='utf-8').read() \ - .replace('{{title}}', settings.TITLE) \ - .replace('{{description}}', settings.DESCRIPTION) \ - .replace('{{keywords}}', settings.KEYWORDS) \ - .replace("'{{fileSizeLimit}}'", str(settings.FILE_SIZE_LIMIT)) \ - # 管理页面 -admin_html = open('templates/admin.html', 'r', encoding='utf-8').read() \ - .replace('{{title}}', settings.TITLE) \ - .replace('{{description}}', settings.DESCRIPTION) \ - .replace('{{keywords}}', settings.KEYWORDS) +@app.get('/') +async def index(): + return HTMLResponse(index_html) @app.get(f'/{settings.ADMIN_ADDRESS}', description='管理页面') @@ -65,26 +56,19 @@ async def admin(): @app.post(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='查询数据库列表') async def admin_post(page: int = Form(default=1), size: int = Form(default=10), s: AsyncSession = Depends(get_session)): - codes = (await s.execute(select(Codes).offset((page - 1) * size).limit(size))).scalars().all() - total = (await s.execute(select(func.count(Codes.id)))).scalar() - return {'detail': '查询成功', 'data': codes, 'paginate': { - 'page': page, - 'size': size, - 'total': total - }} + return { + 'detail': '查询成功', + 'data': (await s.execute(select(Codes).offset((page - 1) * size).limit(size))).scalars().all(), + 'paginate': { + 'page': page, + 'size': size, + 'total': (await s.execute(select(func.count(Codes.id)))).scalar() + }} -@app.patch(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='修改数据库数据') -async def admin_patch(request: Request, s: AsyncSession = Depends(get_session)): - # 从数据库获取系统配置 - # 如果不存在config这个key,就创建一个 - value = (await s.execute(select(Values).filter(Values.key == 'config'))).scalar_one_or_none() - if not value: - s.add(Values(key='config', value=await request.json())) - else: - await s.execute(update(Values).where(Values.key == 'config').values(value=await request.json())) - await s.commit() - return {'detail': '修改成功'} +# @app.patch(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='修改数据库数据') +# async def admin_patch(request: Request, s: AsyncSession = Depends(get_session)): +# return {'detail': '修改成功'} @app.delete(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)], description='删除数据库记录') @@ -103,11 +87,9 @@ async def admin_delete(code: str, s: AsyncSession = Depends(get_session)): return {'detail': '删除成功'} -@app.get('/config', description='获取系统配置', dependencies=[Depends(admin_required)]) +@app.get(f'/{settings.ADMIN_ADDRESS}/config', description='获取系统配置', dependencies=[Depends(admin_required)]) async def config(s: AsyncSession = Depends(get_session)): - # 从数据库获取系统配置 - data = (await s.execute(select(Values).filter(Values.key == 'config'))).scalar_one_or_none() - return {'detail': '获取成功', 'data': data.value if data else {'banners': []}} + return {'detail': '获取成功', 'data': (await s.execute(select(Options))).scalars().all()} @app.get('/') @@ -127,57 +109,25 @@ async def index(code: str, ip: str = Depends(error_ip_limit), s: AsyncSession = await s.execute(update(Codes).where(Codes.id == info.id).values(count=info.count - 1)) await s.commit() if info.type != 'text': - if settings.STORAGE_ENGINE == 'filesystem': - info.text = f'/select?code={code}' - return { - 'detail': f'取件成功,文件将在{settings.DELETE_EXPIRE_FILES_INTERVAL}分钟后删除', - 'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code} - } - elif settings.STORAGE_ENGINE == 'aliyunsystem': - info.text = await storage.get_filepath(info.text) - return { - 'detail': f'取件成功,链接将在{settings.ACCESSTIME}秒后失效', - 'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code} - } + info.text = await storage.get_url(info) + return { + 'detail': f'取件成功,文件将在{settings.DELETE_EXPIRE_FILES_INTERVAL}分钟后删除', + 'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code} + } + + +@app.post(f'/{settings.ADMIN_ADDRESS}/download', dependencies=[Depends(admin_required)]) +async def admin_download_file(filetext: str): + return await storage.get_text(filetext) -@app.post('/adminDownloadFile',dependencies=[Depends(admin_required)], description='管理员获取资源链接') -async def admindownloadfile(filetext: str, s: AsyncSession = Depends(get_session)): - if storage.STORAGE_ENGINE == 'aliyunsystem': - filetext = await storage.get_filepath(filetext) - return { - 'detail': f'获取文件链接成功,链接将在{settings.ACCESSTIME}秒后失效', - 'fileURL': filetext - } - elif storage.STORAGE_ENGINE == 'filesystem': - return { - 'detail': f'获取文件链接成功', - 'fileURL':filetext - } @app.get('/banner') -async def banner(request: Request, s: AsyncSession = Depends(get_session)): +async def banner(request: Request): # 数据库查询config - config = (await s.execute(select(Values).filter(Values.key == 'config'))).scalar_one_or_none() - # 如果存在config,就返回config的value - if config and config.value.get('banners'): - return { - 'detail': '查询成功', - 'data': config.value['banners'], - 'enable': request.headers.get('pwd', '') == settings.ADMIN_PASSWORD or settings.ENABLE_UPLOAD, - } - # 如果不存在config,就返回默认的banner return { - 'detail': 'banner', + 'detail': '查询成功', + 'data': settings.BANNERS, 'enable': request.headers.get('pwd', '') == settings.ADMIN_PASSWORD or settings.ENABLE_UPLOAD, - 'data': [{ - 'text': 'FileCodeBox', - 'url': 'https://github.com/vastsa/FileCodeBox', - 'src': '/static/banners/img_1.png' - }, { - 'text': 'FileCodeBox', - 'url': 'https://www.lanol.cn', - 'src': '/static/banners/img_2.png' - }] } @@ -196,10 +146,7 @@ async def get_file(code: str, ip: str = Depends(error_ip_limit), s: AsyncSession # 如果是文件,返回文件 else: filepath = await storage.get_filepath(info.text) - if settings.STORAGE_ENGINE == 'filesystem': - return FileResponse(filepath, filename=info.name) - else: - return {'detail': '查询成功', 'data': filepath} + return FileResponse(filepath, filename=info.name) @app.post('/share', dependencies=[Depends(admin_required)], description='分享文件') @@ -229,10 +176,7 @@ async def share(background_tasks: BackgroundTasks, text: str = Form(default=None background_tasks.add_task(storage.save_file, file, _text) else: size, _text, _type, name = len(text), text, 'text', '文本分享' - if settings.STORAGE_ENGINE == 'aliyunsystem': - _text = f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/"+_text - info = Codes(code=code, text=_text, size=size, type=_type, name=name, count=exp_count, exp_time=exp_time, key=key) - s.add(info) + s.add(Codes(code=code, text=_text, size=size, type=_type, name=name, count=exp_count, exp_time=exp_time, key=key)) await s.commit() upload_ip_limit.add_ip(ip) return { diff --git a/settings.py b/settings.py index 8788f9b..9cc1b66 100644 --- a/settings.py +++ b/settings.py @@ -1,63 +1,71 @@ +import uuid from starlette.config import Config -import os -import shutil # 配置文件.env # 请将.env移动至data目录,方便docker部署 -# 判断根目录下是否存在.env文件 -if os.path.exists('.env'): - # 将文件复制到data目录 - shutil.copy('.env', 'data/.env') - config = Config("data/.env") -# 是否开启DEBUG模式 -DEBUG = config('DEBUG', cast=bool, default=False) -# 端口 -PORT = config('PORT', cast=int, default=12345) -# Sqlite数据库文件 -DATABASE_FILE = config('DATABASE_FILE', cast=str, default='data/database.db') -# Sqlite套接字 -DATABASE_URL = config('DATABASE_URL', cast=str, default=f"sqlite+aiosqlite:///{DATABASE_FILE}") -# 数据存储文件夹,文件就不暴露在静态资源里面了 -DATA_ROOT = './data/' + config('DATA_ROOT', cast=str, default=f"static") -# 静态文件夹URL -STATIC_URL = config('STATIC_URL', cast=str, default="/static") -# 开启上传 -ENABLE_UPLOAD = config('ENABLE_UPLOAD', cast=bool, default=True) -# 最长天数 -MAX_DAYS = config('MAX_DAYS', cast=int, default=7) -# 错误次数 -ERROR_COUNT = config('ERROR_COUNT', cast=int, default=5) -# 错误限制分钟数 -ERROR_MINUTE = config('ERROR_MINUTE', cast=int, default=10) -# 上传次数 -UPLOAD_COUNT = config('UPLOAD_COUNT', cast=int, default=60) -# 上传限制分钟数 -UPLOAD_MINUTE = config('UPLOAD_MINUTE', cast=int, default=1) -# 删除过期文件的间隔(分钟) -DELETE_EXPIRE_FILES_INTERVAL = config('DELETE_EXPIRE_FILES_INTERVAL', cast=int, default=10) -# 管理地址 -ADMIN_ADDRESS = config('ADMIN_ADDRESS', cast=str, default="admin") -# 管理密码 -ADMIN_PASSWORD = config('ADMIN_PASSWORD', cast=str, default="admin") -# 文件大小限制,默认10MB -FILE_SIZE_LIMIT = config('FILE_SIZE_LIMIT', cast=int, default=10) * 1024 * 1024 -# 网站标题 -TITLE = config('TITLE', cast=str, default="文件快递柜") -# 网站描述 -DESCRIPTION = config('DESCRIPTION', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件等文件") -# 网站关键词 -KEYWORDS = config('KEYWORDS', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件等文件") -# 存储引擎:['aliyunsystem','filesystem'] -STORAGE_ENGINE = config('STORAGE_ENGINE', cast=str, default="filesystem") -# 如果使用阿里云OSS的话需要创建如下参数 -# 阿里云账号AccessKey -KeyId = config('KeyId', cast=str, default="阿里云账号AccessKey") -# 阿里云账号AccessKeySecret -KeySecret = config('KeySecret', cast=str, default="阿里云账号AccessKeySecret") -# 阿里云OSS Bucket的地域节点 -OSS_ENDPOINT = config('BUCKET_URL', cast=str, default="阿里云OSS Bucket的地域节点") -# 阿里云OSS Bucket的BucketName -BUCKET_NAME = config('BUCKET_NAME', cast=str, default="阿里云OSS Bucket的BucketName") -# 访问文件的读取时长(s) -ACCESSTIME = config('ACCESSTIME', cast=int, default=60) + + +class Settings: + # 项目版本 + VERSION: str = config("VERSION", default="1.6") + # 是否开启DEBUG模式 + DEBUG = config('DEBUG', cast=bool, default=False) + # 端口 + PORT = config('PORT', cast=int, default=12345) + # Sqlite数据库文件 + DATABASE_FILE = config('DATABASE_FILE', cast=str, default='data/database.db') + # Sqlite套接字 + DATABASE_URL = config('DATABASE_URL', cast=str, default=f"sqlite+aiosqlite:///{DATABASE_FILE}") + # 数据存储文件夹,文件就不暴露在静态资源里面了 + DATA_ROOT = './data/' + config('DATA_ROOT', cast=str, default=f"static") + # 静态文件夹URL + STATIC_URL = config('STATIC_URL', cast=str, default="/static") + # 开启上传 + ENABLE_UPLOAD = config('ENABLE_UPLOAD', cast=bool, default=True) + # 最长天数 + MAX_DAYS = config('MAX_DAYS', cast=int, default=7) + # 错误次数 + ERROR_COUNT = config('ERROR_COUNT', cast=int, default=5) + # 错误限制分钟数 + ERROR_MINUTE = config('ERROR_MINUTE', cast=int, default=10) + # 上传次数 + UPLOAD_COUNT = config('UPLOAD_COUNT', cast=int, default=60) + # 上传限制分钟数 + UPLOAD_MINUTE = config('UPLOAD_MINUTE', cast=int, default=1) + # 删除过期文件的间隔(分钟) + DELETE_EXPIRE_FILES_INTERVAL = config('DELETE_EXPIRE_FILES_INTERVAL', cast=int, default=10) + # 管理地址 + ADMIN_ADDRESS = config('ADMIN_ADDRESS', cast=str, default=uuid.uuid4().hex) + # 管理密码 + ADMIN_PASSWORD = config('ADMIN_PASSWORD', cast=str, default=uuid.uuid4().hex) + # 文件大小限制,默认10MB + FILE_SIZE_LIMIT = config('FILE_SIZE_LIMIT', cast=int, default=10) * 1024 * 1024 + # 网站标题 + TITLE = config('TITLE', cast=str, default="文件快递柜") + # 网站描述 + DESCRIPTION = config('DESCRIPTION', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件") + # 网站关键词 + KEYWORDS = config('KEYWORDS', cast=str, default="FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件") + # 存储引擎:['aliyunsystem','filesystem'] + STORAGE_ENGINE = config('STORAGE_ENGINE', cast=str, default="filesystem") + # 存储引擎配置 + STORAGE_CONFIG = {} + # Banners + BANNERS = [{ + 'text': 'FileCodeBox', + 'url': 'https://github.com/vastsa/FileCodeBox', + 'src': '/static/banners/img_1.png' + }, { + 'text': 'LanBlog', + 'url': 'https://www.lanol.cn', + 'src': '/static/banners/img_2.png' + }] + + async def update(self, options) -> None: + for i, key, value in options: + if hasattr(self, key): + setattr(self, key, value) + + +settings = Settings() diff --git a/templates/admin.html b/templates/admin.html index ccd006a..09efc1c 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -126,12 +126,11 @@ if (pwd) { login = true; this.pwd = pwd; - axios.get('/config', { + axios.get('{{admin_address}}/config', { headers: { pwd: pwd } }).then(res => { - console.log(res.data.data) this.config = res.data.data; }); this.loginAdmin(); diff --git a/templates/index.html b/templates/index.html index 68a7349..72111dc 100644 --- a/templates/index.html +++ b/templates/index.html @@ -11,7 +11,7 @@ - +