Spaces:
Running
Running
增加github密匙支持
Browse files- models.py +2 -0
- router_items.py +6 -0
- router_proxy.py +9 -4
models.py
CHANGED
|
@@ -64,6 +64,7 @@ class ItemCreate(BaseModel):
|
|
| 64 |
coverUrl: Optional[str] = None
|
| 65 |
author: str
|
| 66 |
price: int = 0
|
|
|
|
| 67 |
|
| 68 |
class FollowToggle(BaseModel):
|
| 69 |
user_id: str
|
|
@@ -88,6 +89,7 @@ class ItemUpdate(BaseModel):
|
|
| 88 |
link: Optional[str] = None
|
| 89 |
coverUrl: Optional[str] = None
|
| 90 |
price: Optional[int] = None
|
|
|
|
| 91 |
|
| 92 |
class RechargeRequest(BaseModel):
|
| 93 |
account: str
|
|
|
|
| 64 |
coverUrl: Optional[str] = None
|
| 65 |
author: str
|
| 66 |
price: int = 0
|
| 67 |
+
github_token: Optional[str] = None
|
| 68 |
|
| 69 |
class FollowToggle(BaseModel):
|
| 70 |
user_id: str
|
|
|
|
| 89 |
link: Optional[str] = None
|
| 90 |
coverUrl: Optional[str] = None
|
| 91 |
price: Optional[int] = None
|
| 92 |
+
github_token: Optional[str] = None
|
| 93 |
|
| 94 |
class RechargeRequest(BaseModel):
|
| 95 |
account: str
|
router_items.py
CHANGED
|
@@ -35,6 +35,10 @@ async def get_items(type: str = "tool", sort: str = "time", limit: int = 50): #
|
|
| 35 |
item["commentsData"] = comments_db.get(item["id"], [])
|
| 36 |
item["comments"] = len(item["commentsData"])
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
if sort == "likes": filtered_items.sort(key=lambda x: x.get("likes", 0), reverse=True)
|
| 39 |
elif sort == "favorites": filtered_items.sort(key=lambda x: x.get("favorites", 0), reverse=True)
|
| 40 |
elif sort == "downloads": filtered_items.sort(key=lambda x: x.get("uses", 0), reverse=True)
|
|
@@ -105,6 +109,7 @@ async def create_item(item: ItemCreate):
|
|
| 105 |
new_item = {
|
| 106 |
"id": f"{item.type}_{int(time.time())}_{uuid.uuid4().hex[:6]}", "type": item.type, "title": item.title, "author": item.author,
|
| 107 |
"shortDesc": item.shortDesc, "fullDesc": item.fullDesc, "link": item.link, "coverUrl": item.coverUrl, "price": item.price,
|
|
|
|
| 108 |
"likes": 0, "favorites": 0, "comments": 0, "uses": 0, "use_history": {}, "created_at": int(time.time()), "liked_by": [], "favorited_by": []
|
| 109 |
}
|
| 110 |
items_db.insert(0, new_item)
|
|
@@ -130,6 +135,7 @@ async def update_item(item_id: str, update_data: ItemUpdate, author: str):
|
|
| 130 |
if update_data.link is not None: item["link"] = update_data.link
|
| 131 |
if update_data.coverUrl is not None: item["coverUrl"] = update_data.coverUrl
|
| 132 |
if update_data.price is not None: item["price"] = update_data.price
|
|
|
|
| 133 |
|
| 134 |
db.save_data("items.json", items_db)
|
| 135 |
return {"status": "success"}
|
|
|
|
| 35 |
item["commentsData"] = comments_db.get(item["id"], [])
|
| 36 |
item["comments"] = len(item["commentsData"])
|
| 37 |
|
| 38 |
+
# 🔴 【绝对核心防线】:在下发给前端前,强行在内存中抹除创作者的 Token!
|
| 39 |
+
# 这样即使资源是公开展示的,普通用户也绝对抓不到源仓库的密钥。
|
| 40 |
+
item.pop("github_token", None)
|
| 41 |
+
|
| 42 |
if sort == "likes": filtered_items.sort(key=lambda x: x.get("likes", 0), reverse=True)
|
| 43 |
elif sort == "favorites": filtered_items.sort(key=lambda x: x.get("favorites", 0), reverse=True)
|
| 44 |
elif sort == "downloads": filtered_items.sort(key=lambda x: x.get("uses", 0), reverse=True)
|
|
|
|
| 109 |
new_item = {
|
| 110 |
"id": f"{item.type}_{int(time.time())}_{uuid.uuid4().hex[:6]}", "type": item.type, "title": item.title, "author": item.author,
|
| 111 |
"shortDesc": item.shortDesc, "fullDesc": item.fullDesc, "link": item.link, "coverUrl": item.coverUrl, "price": item.price,
|
| 112 |
+
"github_token": item.github_token, # 【新增】保存密钥到云端 JSON
|
| 113 |
"likes": 0, "favorites": 0, "comments": 0, "uses": 0, "use_history": {}, "created_at": int(time.time()), "liked_by": [], "favorited_by": []
|
| 114 |
}
|
| 115 |
items_db.insert(0, new_item)
|
|
|
|
| 135 |
if update_data.link is not None: item["link"] = update_data.link
|
| 136 |
if update_data.coverUrl is not None: item["coverUrl"] = update_data.coverUrl
|
| 137 |
if update_data.price is not None: item["price"] = update_data.price
|
| 138 |
+
if update_data.github_token is not None: item["github_token"] = update_data.github_token # 【新增】允许更新密钥
|
| 139 |
|
| 140 |
db.save_data("items.json", items_db)
|
| 141 |
return {"status": "success"}
|
router_proxy.py
CHANGED
|
@@ -42,14 +42,19 @@ async def proxy_github_zip(req_data: ProxyGithubZipRequest, db: Session = Depend
|
|
| 42 |
# GitHub 官方提供的打包下载 API
|
| 43 |
github_zip_api = f"https://api.github.com/repos/{owner}/{repo}/zipball/main"
|
| 44 |
|
| 45 |
-
#
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
headers = {
|
| 48 |
"Accept": "application/vnd.github.v3+json",
|
| 49 |
"User-Agent": "ComfyUI-Ranking-SaaS"
|
| 50 |
}
|
| 51 |
-
if
|
| 52 |
-
headers["Authorization"] = f"Bearer {
|
| 53 |
|
| 54 |
# 3. 异步请求 GitHub API 并以流形式透传回客户端 (防内存打爆)
|
| 55 |
async def stream_generator():
|
|
|
|
| 42 |
# GitHub 官方提供的打包下载 API
|
| 43 |
github_zip_api = f"https://api.github.com/repos/{owner}/{repo}/zipball/main"
|
| 44 |
|
| 45 |
+
# 【核心修改】:优先读取该资源在数据库中绑定的专属创作者 Token
|
| 46 |
+
creator_token = item.get("github_token")
|
| 47 |
+
# 如果没填,尝试使用官方全局兜底的 PAT
|
| 48 |
+
fallback_token = os.environ.get("GITHUB_PAT")
|
| 49 |
+
|
| 50 |
+
active_token = creator_token if creator_token else fallback_token
|
| 51 |
+
|
| 52 |
headers = {
|
| 53 |
"Accept": "application/vnd.github.v3+json",
|
| 54 |
"User-Agent": "ComfyUI-Ranking-SaaS"
|
| 55 |
}
|
| 56 |
+
if active_token:
|
| 57 |
+
headers["Authorization"] = f"Bearer {active_token}"
|
| 58 |
|
| 59 |
# 3. 异步请求 GitHub API 并以流形式透传回客户端 (防内存打爆)
|
| 60 |
async def stream_generator():
|