From: Michael Tremer Date: Tue, 15 Jul 2025 11:49:09 +0000 (+0000) Subject: builds: Give watchers an ID and export over the API X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5b7b26f05792617e45b6391aeb1aa97cc26f09f4;p=pbs.git builds: Give watchers an ID and export over the API Signed-off-by: Michael Tremer --- diff --git a/src/api/builds.py b/src/api/builds.py index dd7a265a..3caaec00 100644 --- a/src/api/builds.py +++ b/src/api/builds.py @@ -29,7 +29,7 @@ from . import backend # Import types from ..bugtracker import Bug -from ..builds import Build +from ..builds import Build, BuildWatcher from ..users import User # Import errors @@ -120,6 +120,49 @@ async def post( async def get(build: Build = fastapi.Depends(get_build_by_uuid)) -> Build: return build +# +# Watchers +# + +@router.get("/{uuid}/watchers") +async def get_watchers( + build: Build = fastapi.Depends(get_build_by_uuid), +) -> list[BuildWatcher]: + """ + Returns all watchers of a build + """ + return await build.get_watchers() + +@router.post("/{uuid}/watchers") +async def add_watcher( + build: Build = fastapi.Depends(get_build_by_uuid), + current_user: User = fastapi.Depends(auth.get_current_user), +) -> fastapi.Response: + """ + Adds yourself as a watcher to the build + """ + # Add the current user as a watcher + async with backend.db as session: + build.add_watcher(current_user) + + # Return 201 + return fastapi.Response(fastapi.status.HTTP_201_CREATED) + +@router.delete("/{uuid}/watchers") +async def remove_watcher( + build: Build = fastapi.Depends(get_build_by_uuid), + current_user: User = fastapi.Depends(auth.get_current_user), +) -> fastapi.Response: + """ + Removes yourself as a watcher from the build + """ + # Remove the current user as a watcher + async with backend.db as session: + build.remove_watcher(current_user) + + # Return 204 + return fastapi.Response(fastapi.status.HTTP_204_NO_CONTENT) + # # Bugs # diff --git a/src/buildservice/builds.py b/src/buildservice/builds.py index bb37e81d..d79b9c56 100644 --- a/src/buildservice/builds.py +++ b/src/buildservice/builds.py @@ -6,6 +6,7 @@ import functools import itertools import logging import os +import pydantic import re import sqlalchemy import sqlmodel @@ -688,7 +689,7 @@ class Build(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, # Select all build watchers .select(BuildWatcher) .where( - BuildWatcher.deleted_at == None, + BuildWatcher.removed_at == None, BuildWatcher.build == self, ) ) @@ -707,7 +708,7 @@ class Build(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, .where( BuildWatcher.build == self, BuildWatcher.user == user, - BuildWatcher.deleted_at == None, + BuildWatcher.removed_at == None, ) ) @@ -736,9 +737,9 @@ class Build(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, """ watcher = await self.watched_by(user) - # If we have found a watcher, we will delete it + # If we have found a watcher, we will remove it if watcher: - await watcher.delete() + await watcher.remove() async def _add_watchers(self): """ @@ -1653,7 +1654,7 @@ class BuildPoint(sqlmodel.SQLModel, database.BackendMixin, table=True): user: "User" = sqlmodel.Relationship() -class BuildWatcher(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, table=True): +class BuildWatcher(sqlmodel.SQLModel, database.BackendMixin, table=True): __tablename__ = "build_watchers" def __lt__(self, other): @@ -1662,6 +1663,9 @@ class BuildWatcher(sqlmodel.SQLModel, database.BackendMixin, database.SoftDelete return NotImplemented + def __hash__(self): + return hash(self.id) + # ID id: int = sqlmodel.Field(primary_key=True, exclude=True) @@ -1680,10 +1684,29 @@ class BuildWatcher(sqlmodel.SQLModel, database.BackendMixin, database.SoftDelete # User - user: "User" = sqlmodel.Relationship() + user: "User" = sqlmodel.Relationship( + sa_relationship_kwargs={ "lazy" : "joined", "innerjoin" : True }, + ) + + # Username + + @pydantic.computed_field + @property + def username(self) -> str: + return self.user.name # Added At added_at: datetime.datetime = sqlmodel.Field( sa_column_kwargs = {"server_default" : sqlalchemy.text("CURRENT_TIMESTAMP")} ) + + # Removed At + + removed_at: datetime.datetime = sqlmodel.Field(exclude=True) + + async def remove(self): + """ + Removes the current watcher + """ + self.removed_at = sqlalchemy.func.current_timestamp() diff --git a/src/database.sql b/src/database.sql index 96331870..6f17bf77 100644 --- a/src/database.sql +++ b/src/database.sql @@ -143,13 +143,33 @@ CREATE TABLE public.build_points ( -- CREATE TABLE public.build_watchers ( + id bigint NOT NULL, build_id integer NOT NULL, user_id integer NOT NULL, added_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, - deleted_at timestamp without time zone + removed_at timestamp without time zone ); +-- +-- Name: build_watchers_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.build_watchers_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: build_watchers_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.build_watchers_id_seq OWNED BY public.build_watchers.id; + + -- -- Name: builder_stats; Type: TABLE; Schema: public; Owner: - -- @@ -1200,6 +1220,13 @@ ALTER TABLE ONLY public.build_comments ALTER COLUMN id SET DEFAULT nextval('publ ALTER TABLE ONLY public.build_groups ALTER COLUMN id SET DEFAULT nextval('public.build_groups_id_seq'::regclass); +-- +-- Name: build_watchers id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.build_watchers ALTER COLUMN id SET DEFAULT nextval('public.build_watchers_id_seq'::regclass); + + -- -- Name: builders id; Type: DEFAULT; Schema: public; Owner: - -- @@ -1378,6 +1405,14 @@ ALTER TABLE ONLY public.build_groups ADD CONSTRAINT build_groups_pkey PRIMARY KEY (id); +-- +-- Name: build_watchers build_watchers_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.build_watchers + ADD CONSTRAINT build_watchers_pkey PRIMARY KEY (id); + + -- -- Name: builds builds_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -1610,7 +1645,7 @@ CREATE INDEX build_points_build_id ON public.build_points USING btree (build_id) -- Name: build_watchers_unique; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX build_watchers_unique ON public.build_watchers USING btree (build_id, user_id) WHERE (deleted_at IS NULL); +CREATE UNIQUE INDEX build_watchers_unique ON public.build_watchers USING btree (build_id, user_id) WHERE (removed_at IS NULL); --