Merge branch 'KIN-UI-015-backend_dev'
This commit is contained in:
commit
abd58e00f0
2 changed files with 43 additions and 2 deletions
|
|
@ -266,12 +266,28 @@ def get_task(conn: sqlite3.Connection, id: str) -> dict | None:
|
||||||
return _row_to_dict(row)
|
return _row_to_dict(row)
|
||||||
|
|
||||||
|
|
||||||
|
VALID_TASK_SORT_FIELDS = frozenset({
|
||||||
|
"updated_at", "created_at", "priority", "status", "title", "id",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def list_tasks(
|
def list_tasks(
|
||||||
conn: sqlite3.Connection,
|
conn: sqlite3.Connection,
|
||||||
project_id: str | None = None,
|
project_id: str | None = None,
|
||||||
status: str | None = None,
|
status: str | None = None,
|
||||||
|
limit: int | None = None,
|
||||||
|
sort: str = "updated_at",
|
||||||
|
sort_dir: str = "desc",
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
"""List tasks with optional project/status filters."""
|
"""List tasks with optional project/status filters, limit, and sort.
|
||||||
|
|
||||||
|
sort: column name (validated against VALID_TASK_SORT_FIELDS, default 'updated_at')
|
||||||
|
sort_dir: 'asc' or 'desc' (default 'desc')
|
||||||
|
"""
|
||||||
|
# Validate sort field to prevent SQL injection
|
||||||
|
sort_col = sort if sort in VALID_TASK_SORT_FIELDS else "updated_at"
|
||||||
|
sort_direction = "DESC" if sort_dir.lower() != "asc" else "ASC"
|
||||||
|
|
||||||
query = "SELECT * FROM tasks WHERE 1=1"
|
query = "SELECT * FROM tasks WHERE 1=1"
|
||||||
params: list = []
|
params: list = []
|
||||||
if project_id:
|
if project_id:
|
||||||
|
|
@ -280,7 +296,10 @@ def list_tasks(
|
||||||
if status:
|
if status:
|
||||||
query += " AND status = ?"
|
query += " AND status = ?"
|
||||||
params.append(status)
|
params.append(status)
|
||||||
query += " ORDER BY priority, created_at"
|
query += f" ORDER BY {sort_col} {sort_direction}"
|
||||||
|
if limit is not None:
|
||||||
|
query += " LIMIT ?"
|
||||||
|
params.append(limit)
|
||||||
return _rows_to_list(conn.execute(query, params).fetchall())
|
return _rows_to_list(conn.execute(query, params).fetchall())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
22
web/api.py
22
web/api.py
|
|
@ -654,6 +654,28 @@ def start_project_phase(project_id: str):
|
||||||
# Tasks
|
# Tasks
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@app.get("/api/tasks")
|
||||||
|
def list_tasks(
|
||||||
|
status: str | None = Query(default=None),
|
||||||
|
limit: int = Query(default=20, ge=1, le=500),
|
||||||
|
sort: str = Query(default="updated_at"),
|
||||||
|
project_id: str | None = Query(default=None),
|
||||||
|
):
|
||||||
|
"""List tasks with optional filters. sort defaults to updated_at desc."""
|
||||||
|
from core.models import VALID_TASK_SORT_FIELDS
|
||||||
|
conn = get_conn()
|
||||||
|
tasks = models.list_tasks(
|
||||||
|
conn,
|
||||||
|
project_id=project_id,
|
||||||
|
status=status,
|
||||||
|
limit=limit,
|
||||||
|
sort=sort if sort in VALID_TASK_SORT_FIELDS else "updated_at",
|
||||||
|
sort_dir="desc",
|
||||||
|
)
|
||||||
|
conn.close()
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/tasks/{task_id}")
|
@app.get("/api/tasks/{task_id}")
|
||||||
def get_task(task_id: str):
|
def get_task(task_id: str):
|
||||||
conn = get_conn()
|
conn = get_conn()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue