bookmarks: account-synced saved locations API

This commit is contained in:
emi 2026-07-26 18:27:43 +00:00
parent 3fafd67600
commit 53fd5d9225

View file

@ -16,6 +16,11 @@ from data import grading
ALLOWED_METRICS = tuple(grading.CLIMO_METRICS) ALLOWED_METRICS = tuple(grading.CLIMO_METRICS)
DEFAULT_METRICS = ["tmax", "feels", "precip"] DEFAULT_METRICS = ["tmax", "feels", "precip"]
# Bookmark limits, shared by the single-create and bulk-import paths.
BOOKMARK_LABEL_MAX_LEN = 80
BOOKMARK_MAX_PER_USER = 200
BOOKMARK_IMPORT_MAX_ITEMS = 200
# --- users (fastapi-users) --------------------------------------------------- # --- users (fastapi-users) ---------------------------------------------------
class UserRead(schemas.BaseUser[uuid.UUID]): class UserRead(schemas.BaseUser[uuid.UUID]):
@ -135,3 +140,69 @@ class PushSubscriptionIn(BaseModel):
class PushUnsubscribeIn(BaseModel): class PushUnsubscribeIn(BaseModel):
endpoint: str endpoint: str
# --- bookmarks ----------------------------------------------------------------
def _check_label(v: str) -> str:
v = v.strip()
if not v:
raise ValueError("label is required")
if len(v) > BOOKMARK_LABEL_MAX_LEN:
raise ValueError(f"label must be at most {BOOKMARK_LABEL_MAX_LEN} characters")
return v
class BookmarkIn(BaseModel):
lat: float = Field(ge=-90, le=90)
lon: float = Field(ge=-180, le=180)
label: str
@field_validator("label")
@classmethod
def _label(cls, v):
return _check_label(v)
class BookmarkPatch(BaseModel):
label: str
@field_validator("label")
@classmethod
def _label(cls, v):
return _check_label(v)
class BookmarkOut(BaseModel):
id: int
cell_id: str
label: str
lat: float
lon: float
created_at: float
model_config = {"from_attributes": True}
class BookmarkList(BaseModel):
bookmarks: list[BookmarkOut]
class BookmarkImportItem(BaseModel):
lat: float = Field(ge=-90, le=90)
lon: float = Field(ge=-180, le=180)
label: str
@field_validator("label")
@classmethod
def _label(cls, v):
return _check_label(v)
class BookmarkImportIn(BaseModel):
items: list[BookmarkImportItem] = Field(max_length=BOOKMARK_IMPORT_MAX_ITEMS)
class BookmarkImportOut(BaseModel):
imported: int
skipped: int
bookmarks: list[BookmarkOut]