Add per-page history endpoint and file-scoped diff filter
This commit is contained in:
+29
-5
@@ -41,9 +41,10 @@ _SESSION_DOMAIN = os.environ.get("SESSION_DOMAIN") or None
|
|||||||
_SESSION_TTL = 30 * 24 * 3600 # 30 days (matches bincio_activity)
|
_SESSION_TTL = 30 * 24 * 3600 # 30 days (matches bincio_activity)
|
||||||
_SESSION_COOKIE = "bincio_session"
|
_SESSION_COOKIE = "bincio_session"
|
||||||
|
|
||||||
_SAFE_SLUG = re.compile(r"^[a-zA-Z0-9_][a-zA-Z0-9_\-/]*$")
|
_SAFE_SLUG = re.compile(r"^[a-zA-Z0-9_][a-zA-Z0-9_\-/]*$")
|
||||||
_SAFE_HANDLE = re.compile(r"^[a-z][a-z0-9_-]{1,19}$")
|
_SAFE_HANDLE = re.compile(r"^[a-z][a-z0-9_-]{1,19}$")
|
||||||
_SAFE_HASH = re.compile(r"^[0-9a-f]{4,40}$")
|
_SAFE_HASH = re.compile(r"^[0-9a-f]{4,40}$")
|
||||||
|
_SAFE_REL_PATH = re.compile(r"^(pages|blog)/[a-zA-Z0-9_][a-zA-Z0-9_\-/]*\.md$")
|
||||||
_ALLOWED_IMAGE_TYPES = {"image/jpeg", "image/png", "image/webp", "image/gif"}
|
_ALLOWED_IMAGE_TYPES = {"image/jpeg", "image/png", "image/webp", "image/gif"}
|
||||||
_MAX_IMAGE_BYTES = 10 * 1024 * 1024 # 10 MB
|
_MAX_IMAGE_BYTES = 10 * 1024 * 1024 # 10 MB
|
||||||
|
|
||||||
@@ -288,12 +289,15 @@ async def get_wiki_log(user: User = Depends(require_auth)) -> JSONResponse:
|
|||||||
|
|
||||||
|
|
||||||
@app.get("/api/diff/{commit_hash}")
|
@app.get("/api/diff/{commit_hash}")
|
||||||
async def get_diff(commit_hash: str, user: User = Depends(require_auth)) -> JSONResponse:
|
async def get_diff(commit_hash: str, file: Optional[str] = None, user: User = Depends(require_auth)) -> JSONResponse:
|
||||||
if not _SAFE_HASH.match(commit_hash):
|
if not _SAFE_HASH.match(commit_hash):
|
||||||
raise HTTPException(status_code=400, detail="invalid hash")
|
raise HTTPException(status_code=400, detail="invalid hash")
|
||||||
|
if file is not None and not _SAFE_REL_PATH.match(file):
|
||||||
|
raise HTTPException(status_code=400, detail="invalid file path")
|
||||||
|
paths = [file] if file else ["pages/", "blog/"]
|
||||||
env = _git_env()
|
env = _git_env()
|
||||||
proc = await asyncio.create_subprocess_exec(
|
proc = await asyncio.create_subprocess_exec(
|
||||||
"git", "show", commit_hash, "-p", "--no-color", "--format=", "--", "pages/", "blog/",
|
"git", "show", commit_hash, "-p", "--no-color", "--format=", "--", *paths,
|
||||||
cwd=str(_ROOT), env=env,
|
cwd=str(_ROOT), env=env,
|
||||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
|
||||||
)
|
)
|
||||||
@@ -303,6 +307,26 @@ async def get_diff(commit_hash: str, user: User = Depends(require_auth)) -> JSON
|
|||||||
return JSONResponse({"diff": stdout.decode(errors="replace")})
|
return JSONResponse({"diff": stdout.decode(errors="replace")})
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/history/{slug:path}")
|
||||||
|
async def get_history(slug: str, user: User = Depends(require_auth)) -> JSONResponse:
|
||||||
|
if not _SAFE_SLUG.match(slug):
|
||||||
|
raise HTTPException(status_code=400, detail="invalid slug")
|
||||||
|
env = _git_env()
|
||||||
|
proc = await asyncio.create_subprocess_exec(
|
||||||
|
"git", "log", "--format=%h|%ar|%aN|%s", "--author=@bincio.wiki", "-n", "50",
|
||||||
|
"--", f"pages/{slug}.md", f"blog/{slug}.md",
|
||||||
|
cwd=str(_ROOT), env=env,
|
||||||
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
stdout, _ = await proc.communicate()
|
||||||
|
entries = []
|
||||||
|
for line in stdout.decode().strip().splitlines():
|
||||||
|
parts = line.split("|", 3)
|
||||||
|
if len(parts) == 4:
|
||||||
|
entries.append({"hash": parts[0], "date": parts[1], "author": parts[2], "message": parts[3]})
|
||||||
|
return JSONResponse({"log": entries})
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/me")
|
@app.get("/api/me")
|
||||||
async def me(user: User = Depends(require_auth)) -> JSONResponse:
|
async def me(user: User = Depends(require_auth)) -> JSONResponse:
|
||||||
return JSONResponse({
|
return JSONResponse({
|
||||||
|
|||||||
+1
-1
Submodule site updated: 64d16dbbdf...e6b9ba56b1
Reference in New Issue
Block a user