From: Michael Tremer Date: Fri, 20 Jun 2025 12:10:01 +0000 (+0000) Subject: backend: Drop server-side sessions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d6ab6ed341a636b53515bcd662714f053f4a0ba0;p=pbs.git backend: Drop server-side sessions Authentication is now entirely handled using decentralised JWTs. Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index a71c5866..d7c406e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -106,7 +106,6 @@ pkgpython_PYTHON = \ src/buildservice/releases.py \ src/buildservice/releasemonitoring.py \ src/buildservice/repos.py \ - src/buildservice/sessions.py \ src/buildservice/sources.py \ src/buildservice/uploads.py \ src/buildservice/users.py diff --git a/src/buildservice/__init__.py b/src/buildservice/__init__.py index b1f80bf3..1fd18ebb 100644 --- a/src/buildservice/__init__.py +++ b/src/buildservice/__init__.py @@ -34,7 +34,6 @@ from . import packages from . import ratelimiter from . import releasemonitoring from . import repos -from . import sessions from . import sources from . import uploads from . import users @@ -82,7 +81,6 @@ class Backend(object): self.monitorings = releasemonitoring.Monitorings(self) self.ratelimiter = ratelimiter.RateLimiter(self) self.repos = repos.Repos(self) - self.sessions = sessions.Sessions(self) self.sources = sources.Sources(self) self.uploads = uploads.Uploads(self) self.users = users.Users(self) @@ -582,9 +580,6 @@ class Backend(object): # Ratelimiter await self.ratelimiter.cleanup() - # Sessions - await self.sessions.cleanup() - # Uploads await self.uploads.cleanup() diff --git a/src/buildservice/sessions.py b/src/buildservice/sessions.py deleted file mode 100644 index 574db879..00000000 --- a/src/buildservice/sessions.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/python - -import datetime -import logging -import sqlalchemy -import sqlmodel - -from sqlalchemy.dialects.postgresql import INET - -from . import base -from . import misc - -# Setup logging -log = logging.getLogger("pbs.sessions") - -class Sessions(base.Object): - async def create(self, user, address, user_agent=None): - """ - Creates a new session in the data. - - The user is not checked and it is assumed that the user exists - and has the right to log in. - """ - session_id = misc.generate_random_string(48) - - session = await self.db.insert( - Session, - session_id = session_id, - user = user, - address = address, - user_agent = user_agent, - ) - - # Log what we have done - log.info("Created new session %s" % session) - - return session - - async def get_by_session_id(self, session_id): - stmt = ( - sqlmodel - .select(Session) - .where( - Session.session_id == session_id, - Session.expires_at > sqlalchemy.func.current_timestamp(), - ) - ) - - return await self.db.fetch_one(stmt) - - # Alias function - get = get_by_session_id - - async def cleanup(self): - """ - Deletes all sessions that are not valid any more - """ - stmt = ( - sqlmodel - .delete( - Session, - ) - .where( - Session.expires_at <= sqlalchemy.func.current_timestamp(), - ) - ) - - # Run the query - async with await self.db.transaction(): - await self.db.execute(stmt) - - -class Session(sqlmodel.SQLModel, table=True): - __tablename__ = "sessions" - - def __lt__(self, other): - if isinstance(other, self.__class__): - return self.user < other.user - - return NotImplemented - - # ID - - id : int = sqlmodel.Field(primary_key=True) - - # Session ID - - session_id : str = sqlmodel.Field(unique=True) - - # User ID - - user_id : int = sqlmodel.Field(foreign_key="users.id") - - # User - - user : "User" = sqlmodel.Relationship() - - # Created At - - created_at : datetime.datetime = sqlmodel.Field( - sa_column_kwargs = {"server_default" : sqlalchemy.text("CURRENT_TIMESTAMP")} - ) - - # Expires At - - expires_at : datetime.datetime = sqlmodel.Field( - sa_column_kwargs = {"server_default" : sqlalchemy.text("CURRENT_TIMESTAMP + INTERVAL '14 days'")} - ) - - # Address - - address : str = sqlmodel.Field(default=None, sa_column=sqlalchemy.Column(INET)) - - # User Agent - - user_agent : str | None - - # Logout! - - async def logout(self): - """ - Destroys this session - """ - await self.db.delete(self) diff --git a/src/buildservice/users.py b/src/buildservice/users.py index c7c7a938..352f0428 100644 --- a/src/buildservice/users.py +++ b/src/buildservice/users.py @@ -530,10 +530,6 @@ class User(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, t async def delete(self): await self._set_attribute("deleted", True) - # Destroy all sessions - for session in self.sessions: - session.destroy() - # Fetch any attributes from LDAP @functools.cached_property diff --git a/src/database.sql b/src/database.sql index df20b5bc..61207ed0 100644 --- a/src/database.sql +++ b/src/database.sql @@ -2,12 +2,13 @@ -- PostgreSQL database dump -- --- Dumped from database version 15.10 (Debian 15.10-0+deb12u1) --- Dumped by pg_dump version 15.10 (Debian 15.10-0+deb12u1) +-- Dumped from database version 17.5 (Debian 17.5-1) +-- Dumped by pg_dump version 17.5 (Debian 17.5-1) SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; +SET transaction_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config('search_path', '', false); @@ -952,40 +953,6 @@ CREATE SEQUENCE public.repository_builds_id_seq ALTER SEQUENCE public.repository_builds_id_seq OWNED BY public.repository_builds.id; --- --- Name: sessions; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.sessions ( - id integer NOT NULL, - session_id text DEFAULT gen_random_uuid() NOT NULL, - created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, - expires_at timestamp without time zone NOT NULL, - user_id integer NOT NULL, - address inet, - user_agent text -); - - --- --- Name: sessions_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.sessions_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: sessions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.sessions_id_seq OWNED BY public.sessions.id; - - -- -- Name: source_commit_jobs; Type: TABLE; Schema: public; Owner: - -- @@ -1345,13 +1312,6 @@ ALTER TABLE ONLY public.repositories ALTER COLUMN id SET DEFAULT nextval('public ALTER TABLE ONLY public.repository_builds ALTER COLUMN id SET DEFAULT nextval('public.repository_builds_id_seq'::regclass); --- --- Name: sessions id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.sessions ALTER COLUMN id SET DEFAULT nextval('public.sessions_id_seq'::regclass); - - -- -- Name: source_commit_jobs id; Type: DEFAULT; Schema: public; Owner: - -- @@ -1578,22 +1538,6 @@ ALTER TABLE ONLY public.repository_builds ADD CONSTRAINT repository_builds_pkey PRIMARY KEY (id); --- --- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.sessions - ADD CONSTRAINT sessions_pkey PRIMARY KEY (id); - - --- --- Name: sessions sessions_session_id_key; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.sessions - ADD CONSTRAINT sessions_session_id_key UNIQUE (session_id); - - -- -- Name: source_commit_jobs source_commit_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -2511,14 +2455,6 @@ ALTER TABLE ONLY public.repository_builds ADD CONSTRAINT repository_builds_repo_id FOREIGN KEY (repo_id) REFERENCES public.repositories(id); --- --- Name: sessions sessions_user_id; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.sessions - ADD CONSTRAINT sessions_user_id FOREIGN KEY (user_id) REFERENCES public.users(id); - - -- -- Name: source_commit_jobs source_commit_jobs_commit_id; Type: FK CONSTRAINT; Schema: public; Owner: - --