mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-11-08 06:02:30 +01:00
Compare commits
4
Commits
e0e250d023
...
7367325819
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7367325819 | ||
|
|
3738df3b93 | ||
|
|
f5c9095222 | ||
|
|
d4ff7fce81 |
@@ -663,8 +663,9 @@ def setup_document_routes(session_manager, upload_handler=None) -> APIRouter:
|
|||||||
try:
|
try:
|
||||||
# Verify ownership before listing versions
|
# Verify ownership before listing versions
|
||||||
doc = db.query(Document).filter(Document.id == doc_id).first()
|
doc = db.query(Document).filter(Document.id == doc_id).first()
|
||||||
if doc:
|
if not doc:
|
||||||
_verify_doc_owner(db, doc, user)
|
raise HTTPException(404, "Document not found")
|
||||||
|
_verify_doc_owner(db, doc, user)
|
||||||
versions = db.query(DocumentVersion).filter(
|
versions = db.query(DocumentVersion).filter(
|
||||||
DocumentVersion.document_id == doc_id
|
DocumentVersion.document_id == doc_id
|
||||||
).order_by(DocumentVersion.version_number.desc()).all()
|
).order_by(DocumentVersion.version_number.desc()).all()
|
||||||
@@ -687,8 +688,9 @@ def setup_document_routes(session_manager, upload_handler=None) -> APIRouter:
|
|||||||
try:
|
try:
|
||||||
# Verify ownership
|
# Verify ownership
|
||||||
doc = db.query(Document).filter(Document.id == doc_id).first()
|
doc = db.query(Document).filter(Document.id == doc_id).first()
|
||||||
if doc:
|
if not doc:
|
||||||
_verify_doc_owner(db, doc, user)
|
raise HTTPException(404, "Document not found")
|
||||||
|
_verify_doc_owner(db, doc, user)
|
||||||
ver = db.query(DocumentVersion).filter(
|
ver = db.query(DocumentVersion).filter(
|
||||||
DocumentVersion.document_id == doc_id,
|
DocumentVersion.document_id == doc_id,
|
||||||
DocumentVersion.version_number == num,
|
DocumentVersion.version_number == num,
|
||||||
|
|||||||
@@ -1316,6 +1316,7 @@ def setup_gallery_routes() -> APIRouter:
|
|||||||
@router.post("/api/image/sharpen")
|
@router.post("/api/image/sharpen")
|
||||||
async def sharpen_image(request: Request):
|
async def sharpen_image(request: Request):
|
||||||
"""Apply unsharp-mask sharpening to an image."""
|
"""Apply unsharp-mask sharpening to an image."""
|
||||||
|
require_privilege(request, "can_generate_images")
|
||||||
body = await request.json()
|
body = await request.json()
|
||||||
image_b64 = body.get("image")
|
image_b64 = body.get("image")
|
||||||
amount = body.get("amount", 50) / 100.0
|
amount = body.get("amount", 50) / 100.0
|
||||||
|
|||||||
@@ -497,6 +497,15 @@ def setup_task_routes(task_scheduler) -> APIRouter:
|
|||||||
else bool(req.notifications_enabled) if req.notifications_enabled is not None
|
else bool(req.notifications_enabled) if req.notifications_enabled is not None
|
||||||
else True
|
else True
|
||||||
)
|
)
|
||||||
|
# Validate chained task belongs to same owner
|
||||||
|
if req.then_task_id:
|
||||||
|
chain_target = db.query(ScheduledTask).filter(
|
||||||
|
ScheduledTask.id == req.then_task_id
|
||||||
|
).first()
|
||||||
|
if not chain_target:
|
||||||
|
raise HTTPException(400, "Chained task not found")
|
||||||
|
if chain_target.owner != user:
|
||||||
|
raise HTTPException(403, "Cannot chain to another user's task")
|
||||||
task = ScheduledTask(
|
task = ScheduledTask(
|
||||||
id=task_id,
|
id=task_id,
|
||||||
owner=user,
|
owner=user,
|
||||||
@@ -671,6 +680,14 @@ def setup_task_routes(task_scheduler) -> APIRouter:
|
|||||||
if req.trigger_count is not None:
|
if req.trigger_count is not None:
|
||||||
task.trigger_count = req.trigger_count
|
task.trigger_count = req.trigger_count
|
||||||
if req.then_task_id is not None:
|
if req.then_task_id is not None:
|
||||||
|
if req.then_task_id:
|
||||||
|
chain_target = db.query(ScheduledTask).filter(
|
||||||
|
ScheduledTask.id == req.then_task_id
|
||||||
|
).first()
|
||||||
|
if not chain_target:
|
||||||
|
raise HTTPException(400, "Chained task not found")
|
||||||
|
if chain_target.owner != user:
|
||||||
|
raise HTTPException(403, "Cannot chain to another user's task")
|
||||||
task.then_task_id = req.then_task_id or None
|
task.then_task_id = req.then_task_id or None
|
||||||
if req.notifications_enabled is not None:
|
if req.notifications_enabled is not None:
|
||||||
task.notifications_enabled = bool(req.notifications_enabled)
|
task.notifications_enabled = bool(req.notifications_enabled)
|
||||||
|
|||||||
+6
-4
@@ -86,10 +86,12 @@ def validate_caldav_url(raw_url: str) -> str:
|
|||||||
return urlunparse(parsed._replace(fragment="")).rstrip("/")
|
return urlunparse(parsed._replace(fragment="")).rstrip("/")
|
||||||
|
|
||||||
|
|
||||||
def _stable_cal_id(remote_url: str) -> str:
|
def _stable_cal_id(remote_url: str, owner: str = "") -> str:
|
||||||
"""Deterministic local id for a remote CalDAV calendar — same URL
|
"""Deterministic local id for a remote CalDAV calendar — same URL
|
||||||
always maps to the same local row across restarts and re-syncs."""
|
always maps to the same local row across restarts and re-syncs.
|
||||||
h = hashlib.sha256(remote_url.encode("utf-8")).hexdigest()[:24]
|
Owner is included in the hash to prevent PK collisions when multiple
|
||||||
|
users sync the same CalDAV endpoint."""
|
||||||
|
h = hashlib.sha256(f"{owner}:{remote_url}".encode("utf-8")).hexdigest()[:24]
|
||||||
return f"caldav-{h}"
|
return f"caldav-{h}"
|
||||||
|
|
||||||
|
|
||||||
@@ -170,7 +172,7 @@ def _sync_blocking(owner: str, url: str, username: str, password: str) -> dict:
|
|||||||
for remote_cal in calendars:
|
for remote_cal in calendars:
|
||||||
try:
|
try:
|
||||||
remote_url = str(remote_cal.url)
|
remote_url = str(remote_cal.url)
|
||||||
cal_id = _stable_cal_id(remote_url)
|
cal_id = _stable_cal_id(remote_url, owner)
|
||||||
display_name = (remote_cal.name or "").strip() or "CalDAV"
|
display_name = (remote_cal.name or "").strip() or "CalDAV"
|
||||||
|
|
||||||
local_cal = db.query(CalendarCal).filter(
|
local_cal = db.query(CalendarCal).filter(
|
||||||
|
|||||||
Reference in New Issue
Block a user