mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 07:11:28 +02:00
The name validator added in 048abbf3 went on ProjectBase, which
ProjectRead inherits, so it ran when the API serialised a project as
well as when it accepted one. A project saved with a blank name before
that rule existed then failed response validation, and GET /projects
returned a 500 for every caller — the sidebar showed "Loading..." and no
project could be selected.
A rule about what a client may send belongs on the request model. It now
sits on ProjectCreate, so stored rows written before the rule still read
back. The equivalent validators on engines, contexts and schedules were
already request-only and are unaffected; all thirteen list endpoints
were checked.
The scan launch also had its own wording for an unreadable target value;
it now uses the same sentence as every other target path.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6LcH8uUddjJbKrahf34ys
49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
from functools import partial
|
|
|
|
from pydantic import BaseModel, field_validator
|
|
from sqlmodel import Field, SQLModel
|
|
|
|
from shared.utils.datetime import utc_now
|
|
from shared.utils.validation import clean_name
|
|
|
|
|
|
class ProjectBase(SQLModel):
|
|
name: str = Field(max_length=50)
|
|
|
|
|
|
class Project(ProjectBase, table=True):
|
|
__tablename__ = "projects"
|
|
|
|
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True, index=True)
|
|
slug: str = Field(max_length=100, unique=True, index=True)
|
|
description: str | None = Field(default=None, max_length=1000)
|
|
label: str | None = Field(default=None, max_length=50)
|
|
is_active: bool = Field(default=True)
|
|
created_at: datetime = Field(default_factory=utc_now)
|
|
created_by: uuid.UUID = Field(foreign_key="users.id")
|
|
|
|
|
|
class ProjectCreate(ProjectBase):
|
|
description: str | None = None
|
|
label: str | None = None
|
|
|
|
# on the request only: a stored name from before this rule must still read back
|
|
_validate_name = field_validator("name")(partial(clean_name, max_len=50))
|
|
|
|
|
|
class ProjectRead(ProjectBase):
|
|
id: uuid.UUID
|
|
slug: str
|
|
description: str | None = None
|
|
label: str | None = None
|
|
is_active: bool
|
|
created_at: datetime
|
|
created_by: uuid.UUID
|
|
|
|
|
|
class ProjectSummary(BaseModel):
|
|
project: ProjectRead
|
|
stats: dict[str, int]
|