54 lines
1.9 KiB
Python
54 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import sqlite3
|
|
|
|
from backend.app.api.errors import AppError
|
|
from backend.app.api.schemas import BookmarkDeleteResponse, BookmarkItem, BookmarkListResponse
|
|
from backend.app.db.bookmark_repository import BookmarkRepository
|
|
from backend.app.security.path_guard import PathGuard
|
|
|
|
|
|
class BookmarkService:
|
|
def __init__(self, path_guard: PathGuard, repository: BookmarkRepository):
|
|
self._path_guard = path_guard
|
|
self._repository = repository
|
|
|
|
def create_bookmark(self, path: str, label: str) -> BookmarkItem:
|
|
normalized_label = (label or "").strip()
|
|
if not normalized_label:
|
|
raise AppError(
|
|
code="invalid_request",
|
|
message="Label is required",
|
|
status_code=400,
|
|
details={"label": label},
|
|
)
|
|
|
|
resolved = self._path_guard.resolve_path(path)
|
|
|
|
try:
|
|
bookmark = self._repository.create_bookmark(path=resolved.relative, label=normalized_label)
|
|
except sqlite3.IntegrityError:
|
|
raise AppError(
|
|
code="already_exists",
|
|
message="Bookmark already exists for path",
|
|
status_code=409,
|
|
details={"path": resolved.relative},
|
|
)
|
|
|
|
return BookmarkItem(**bookmark)
|
|
|
|
def list_bookmarks(self) -> BookmarkListResponse:
|
|
items = [BookmarkItem(**row) for row in self._repository.list_bookmarks()]
|
|
return BookmarkListResponse(items=items)
|
|
|
|
def delete_bookmark(self, bookmark_id: int) -> BookmarkDeleteResponse:
|
|
deleted = self._repository.delete_bookmark(bookmark_id)
|
|
if not deleted:
|
|
raise AppError(
|
|
code="path_not_found",
|
|
message="Bookmark was not found",
|
|
status_code=404,
|
|
details={"bookmark_id": str(bookmark_id)},
|
|
)
|
|
return BookmarkDeleteResponse(id=bookmark_id)
|