Skip to content

Commit 47d90f2

Browse files
authored
Merge pull request #84 from shinonomeow/shino_aio
remove unuseful file,fix renamer monitor remove error
2 parents 2dbe838 + c83e561 commit 47d90f2

85 files changed

Lines changed: 760 additions & 978 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/src/main.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
import os
3-
from pathlib import Path
43

54
import uvicorn
65
from fastapi import FastAPI, Request
@@ -9,7 +8,6 @@
98
from fastapi.templating import Jinja2Templates
109
from module.api import lifespan, v1
1110
from module.conf import VERSION, settings, setup_logger
12-
from module.network import load_image
1311

1412
setup_logger(reset=True)
1513
logger = logging.getLogger(__name__)
@@ -40,26 +38,9 @@ def create_app() -> FastAPI:
4038
app = create_app()
4139

4240

43-
@app.get("/posters/{path:path}", tags=["posters"])
44-
async def posters(path: str):
45-
46-
# FIX: 有严重的安全问题, 需要修复
47-
# 例: "../index.html" 可以访问到根目录的文件"
48-
# TODO: 由于只有取的时候才会下载,所以会导致第一次请求的时候没有图片
49-
post_path = Path("data/posters") / path
50-
if not post_path.exists():
51-
await load_image(path)
52-
if post_path.exists():
53-
return FileResponse(post_path)
54-
else:
55-
# TODO: 404
56-
return FileResponse("")
57-
58-
5941
if VERSION != "DEV_VERSION":
6042
app.mount("/assets", StaticFiles(directory="dist/assets"), name="assets")
6143
app.mount("/images", StaticFiles(directory="dist/images"), name="images")
62-
# app.mount("/icons", StaticFiles(directory="dist/icons"), name="icons")
6344
templates = Jinja2Templates(directory="dist")
6445

6546
@app.get("/{path:path}")
@@ -89,4 +70,3 @@ def index():
8970
port=settings.program.webui_port,
9071
log_config=uvicorn_logging_config,
9172
)
92-

backend/src/module/ab_decorator/__init__.py

Lines changed: 0 additions & 44 deletions
This file was deleted.

backend/src/module/ab_decorator/timeout.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

backend/src/module/api/auth.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
@router.post("/login", response_model=dict)
2323
async def login(response: Response, form_data=Depends(OAuth2PasswordRequestForm)):
2424
user = User(username=form_data.username, password=form_data.password)
25-
25+
2626
from module.database import Database
27+
2728
with Database() as db:
2829
try:
2930
stored_user = db.user.get_user(user.username)
@@ -45,7 +46,10 @@ async def login(response: Response, form_data=Depends(OAuth2PasswordRequestForm)
4546
else:
4647
active_user.append(user.username)
4748
resp = ResponseModel(
48-
status_code=200, status=True, msg_en="Login successfully", msg_zh="登录成功"
49+
status_code=200,
50+
status=True,
51+
msg_en="Login successfully",
52+
msg_zh="登录成功",
4953
)
5054

5155
if resp.status:

backend/src/module/api/bangumi.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
from fastapi import APIRouter, Depends
2-
from fastapi.responses import JSONResponse
1+
import logging
2+
from pathlib import Path
3+
4+
from fastapi import APIRouter, Depends, HTTPException
5+
from fastapi.responses import FileResponse, JSONResponse
36
from sqlalchemy.util.concurrency import asyncio
47

58
from module.database import Database, engine
69
from module.manager import BangumiManager
710
from module.models import APIResponse, Bangumi, BangumiUpdate, ResponseModel
11+
from module.network import load_image
812
from module.security.api import get_current_user
913

1014
from .response import u_response
1115

1216
router = APIRouter(prefix="/bangumi", tags=["bangumi"])
17+
logger = logging.getLogger(__name__)
1318

1419

1520
# def str_to_list(data: Bangumi):
@@ -226,3 +231,48 @@ async def reset_all():
226231
"msg_zh": "重置所有规则成功。",
227232
},
228233
)
234+
235+
236+
@router.get("/poster/{path:path}", dependencies=[Depends(get_current_user)])
237+
async def get_poster(path: str):
238+
"""
239+
安全的poster图片访问端点
240+
- 添加了用户鉴权
241+
- 防止路径遍历攻击
242+
- 限制只能访问posters目录下的文件
243+
"""
244+
# 验证路径安全性 - 阻止路径遍历
245+
if ".." in path or path.startswith("/") or "\\" in path:
246+
logger.warning(f"[Poster] Blocked path traversal attempt: {path}")
247+
raise HTTPException(status_code=400, detail="Invalid path")
248+
249+
# 构建安全的文件路径
250+
poster_dir = Path("data/posters")
251+
post_path = poster_dir / Path(path)
252+
253+
# 确保解析后的路径仍在预期目录内
254+
try:
255+
post_path.resolve().relative_to(poster_dir.resolve())
256+
except ValueError:
257+
logger.warning(f"[Poster] Path outside allowed directory: {path}")
258+
raise HTTPException(status_code=400, detail="Path outside allowed directory")
259+
260+
logger.debug(f"[Poster] Accessing poster: {post_path}")
261+
262+
# 如果文件不存在,尝试下载
263+
if not post_path.exists():
264+
try:
265+
await load_image(path)
266+
except Exception as e:
267+
logger.warning(f"[Poster] Failed to load image {path}: {e}")
268+
269+
# 返回文件
270+
if post_path.exists() and post_path.is_file():
271+
return FileResponse(
272+
post_path,
273+
media_type="image/jpeg",
274+
headers={"Cache-Control": "public, max-age=86400"}, # 缓存1天
275+
)
276+
else:
277+
logger.warning(f"[Poster] File not found: {post_path}")
278+
raise HTTPException(status_code=404, detail="Poster not found")

backend/src/module/api/log.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ async def get_log():
1414
try:
1515
with open(LOG_PATH, "r", encoding="utf-8") as f:
1616
lines = f.readlines()
17-
17+
1818
# 只返回最后200行
1919
last_lines = lines[-200:] if len(lines) > 200 else lines
2020
content = "".join(last_lines)
21-
21+
2222
return Response(content, media_type="text/plain; charset=utf-8")
23-
23+
2424
except Exception as e:
2525
return Response(f"Error reading log file: {str(e)}", status_code=500)
2626
else:

backend/src/module/api/rss.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ async def analysis(rss: RSSItem):
254254
async def download_collection(data: Bangumi):
255255
resp = await engine.download_bangumi(bangumi=data)
256256

257-
258257
# TODO: resp 要等后面统一改
259258

260259
if resp:

backend/src/module/api/search.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import logging
2+
13
from fastapi import APIRouter, Depends, Query
24
from sse_starlette.sse import EventSourceResponse
35

46
from module.models import Bangumi
57
from module.searcher import SEARCH_CONFIG, SearchTorrent
68
from module.security.api import UNAUTHORIZED, get_current_user
7-
import logging
89

910
logger = logging.getLogger("api.search")
1011

backend/src/module/checker/checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,5 @@ def check_img_cache() -> bool:
6565

6666
if __name__ == "__main__":
6767
import asyncio
68-
pass
6968

69+
pass

backend/src/module/conf/config.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from .const import ENV_TO_ATTR
2121

22-
T_BaseModel = TypeVar('T_BaseModel', bound=BaseModel)
22+
T_BaseModel = TypeVar("T_BaseModel", bound=BaseModel)
2323

2424
logger = logging.getLogger(__name__)
2525

@@ -123,7 +123,6 @@ def update_config(base_config: BaseModel | dict, data: dict):
123123

124124

125125
class Settings(Config):
126-
127126
# def __init__(self):
128127
# super().__init__()
129128
def __init__(self, **data):

0 commit comments

Comments
 (0)