refactor: all task mutations require auth — actor from JWT/token, no ?actor= or ?slug= params
Some checks failed
Deploy Tracker / deploy (push) Failing after 1s
Some checks failed
Deploy Tracker / deploy (push) Failing after 1s
This commit is contained in:
parent
2f0c4d1636
commit
904c105174
@ -11,6 +11,7 @@ from sqlalchemy.orm import selectinload, joinedload
|
||||
|
||||
from tracker.database import get_db
|
||||
from tracker.models import Task, Step, Project, Member, Message, Chat
|
||||
from tracker.api.auth import get_current_member
|
||||
|
||||
router = APIRouter(tags=["tasks"])
|
||||
|
||||
@ -231,6 +232,7 @@ async def get_task(task_id: str, db: AsyncSession = Depends(get_db)):
|
||||
async def create_task(
|
||||
project_slug: str = Query(...),
|
||||
req: TaskCreate = ...,
|
||||
current_member: Member = Depends(get_current_member),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
# Find project
|
||||
@ -298,14 +300,14 @@ async def create_task(
|
||||
async def update_task(
|
||||
task_id: str,
|
||||
req: TaskUpdate,
|
||||
actor: Optional[str] = Query(None, description="Who made the change"),
|
||||
current_member: Member = Depends(get_current_member),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
task = await _get_task(task_id, db)
|
||||
slug = task.project.slug if task.project else ""
|
||||
prefix = slug[:2].upper() if slug else "XX"
|
||||
key = f"{prefix}-{task.number}"
|
||||
who = f"@{actor}" if actor else "Кто-то"
|
||||
who = f"@{current_member.slug}"
|
||||
|
||||
old_status = task.status
|
||||
old_assignee = task.assignee_slug
|
||||
@ -338,7 +340,7 @@ async def update_task(
|
||||
chat_text=f"{key}: {old_status} → {req.status}",
|
||||
task_text=f"{who} изменил статус: {old_status} → {req.status} ({now_str})",
|
||||
project_slug=slug,
|
||||
actor_slug=actor or "system",
|
||||
actor_slug=current_member.slug,
|
||||
)
|
||||
if req.assignee_slug is not None and req.assignee_slug != old_assignee:
|
||||
if req.assignee_slug:
|
||||
@ -347,7 +349,7 @@ async def update_task(
|
||||
chat_text=f"{key}: назначена на @{req.assignee_slug}",
|
||||
task_text=f"{who} назначил задачу на @{req.assignee_slug} ({now_str})",
|
||||
project_slug=slug,
|
||||
actor_slug=actor or "system",
|
||||
actor_slug=current_member.slug,
|
||||
)
|
||||
else:
|
||||
await _system_message(
|
||||
@ -355,7 +357,7 @@ async def update_task(
|
||||
chat_text=f"{key}: исполнитель снят",
|
||||
task_text=f"{who} снял исполнителя @{old_assignee} ({now_str})",
|
||||
project_slug=slug,
|
||||
actor_slug=actor or "system",
|
||||
actor_slug=current_member.slug,
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
@ -375,7 +377,7 @@ async def update_task(
|
||||
|
||||
|
||||
@router.delete("/tasks/{task_id}")
|
||||
async def delete_task(task_id: str, db: AsyncSession = Depends(get_db)):
|
||||
async def delete_task(task_id: str, current_member: Member = Depends(get_current_member), db: AsyncSession = Depends(get_db)):
|
||||
task = await _get_task(task_id, db)
|
||||
project_id = str(task.project_id)
|
||||
task_data = {"id": str(task.id), "project_id": project_id}
|
||||
@ -387,8 +389,9 @@ async def delete_task(task_id: str, db: AsyncSession = Depends(get_db)):
|
||||
|
||||
|
||||
@router.post("/tasks/{task_id}/take", response_model=TaskOut)
|
||||
async def take_task(task_id: str, slug: str = Query(...), db: AsyncSession = Depends(get_db)):
|
||||
async def take_task(task_id: str, current_member: Member = Depends(get_current_member), db: AsyncSession = Depends(get_db)):
|
||||
"""Atomically take a task — only if unassigned and in backlog/todo."""
|
||||
slug = current_member.slug
|
||||
task = await _get_task(task_id, db)
|
||||
if task.assignee_slug:
|
||||
raise HTTPException(409, f"Task already assigned to {task.assignee_slug}")
|
||||
@ -431,7 +434,7 @@ async def take_task(task_id: str, slug: str = Query(...), db: AsyncSession = Dep
|
||||
|
||||
|
||||
@router.post("/tasks/{task_id}/reject")
|
||||
async def reject_task(task_id: str, req: RejectRequest, db: AsyncSession = Depends(get_db)):
|
||||
async def reject_task(task_id: str, req: RejectRequest, current_member: Member = Depends(get_current_member), db: AsyncSession = Depends(get_db)):
|
||||
"""Reject a task with reason — unassign and return to todo."""
|
||||
task = await _get_task(task_id, db)
|
||||
old_assignee = task.assignee_slug
|
||||
@ -456,7 +459,7 @@ async def reject_task(task_id: str, req: RejectRequest, db: AsyncSession = Depen
|
||||
|
||||
|
||||
@router.post("/tasks/{task_id}/assign", response_model=TaskOut)
|
||||
async def assign_task(task_id: str, req: AssignRequest, db: AsyncSession = Depends(get_db)):
|
||||
async def assign_task(task_id: str, req: AssignRequest, current_member: Member = Depends(get_current_member), db: AsyncSession = Depends(get_db)):
|
||||
"""Assign task to a member."""
|
||||
# Verify assignee exists
|
||||
result = await db.execute(select(Member).where(Member.slug == req.assignee_slug))
|
||||
@ -495,7 +498,8 @@ async def assign_task(task_id: str, req: AssignRequest, db: AsyncSession = Depen
|
||||
|
||||
|
||||
@router.post("/tasks/{task_id}/watch")
|
||||
async def watch_task(task_id: str, slug: str = Query(...), db: AsyncSession = Depends(get_db)):
|
||||
async def watch_task(task_id: str, current_member: Member = Depends(get_current_member), db: AsyncSession = Depends(get_db)):
|
||||
slug = current_member.slug
|
||||
task = await _get_task(task_id, db)
|
||||
if slug not in (task.watchers or []):
|
||||
task.watchers = (task.watchers or []) + [slug]
|
||||
@ -504,7 +508,8 @@ async def watch_task(task_id: str, slug: str = Query(...), db: AsyncSession = De
|
||||
|
||||
|
||||
@router.delete("/tasks/{task_id}/watch")
|
||||
async def unwatch_task(task_id: str, slug: str = Query(...), db: AsyncSession = Depends(get_db)):
|
||||
async def unwatch_task(task_id: str, current_member: Member = Depends(get_current_member), db: AsyncSession = Depends(get_db)):
|
||||
slug = current_member.slug
|
||||
task = await _get_task(task_id, db)
|
||||
task.watchers = [w for w in (task.watchers or []) if w != slug]
|
||||
await db.commit()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user