diff libervia/backend/memory/sqla.py @ 4385:a1ac33fe6b97

memory (sqla): Add columns and tables to handles permissions: Add columns to handle `access_model` and `publish_model` and a table for `affiliations`. With those new data, components handling pubsub can now manage permissions correctly. rel 462
author Goffi <goffi@goffi.org>
date Sun, 03 Aug 2025 23:45:45 +0200
parents 7ac28a270b7f
children
line wrap: on
line diff
--- a/libervia/backend/memory/sqla.py	Sun Aug 03 23:36:22 2025 +0200
+++ b/libervia/backend/memory/sqla.py	Sun Aug 03 23:45:45 2025 +0200
@@ -57,6 +57,7 @@
 from libervia.backend.memory import migration
 from libervia.backend.memory import sqla_config
 from libervia.backend.memory.sqla_mapping import (
+    AccessModel,
     Base,
     Component,
     File,
@@ -74,8 +75,11 @@
     PrivateInd,
     PrivateIndBin,
     Profile,
+    PublishModel,
+    PubsubAffiliation,
     PubsubItem,
     PubsubNode,
+    PubsubSub,
     Subject,
     SyncState,
     Thread,
@@ -1116,7 +1120,7 @@
 
         the older value will be retrieved from database, then update_cb will be applied to
         update it, and file will be updated checking that older value has not been changed
-        meanwhile by an other user. If it has changed, it tries again a couple of times
+        meanwhile by another user. If it has changed, it tries again a couple of times
         before failing
         @param column: column name (only "access" or "extra" are allowed)
         @param update_cb: method to update the value of the colum
@@ -1174,15 +1178,17 @@
         name: str,
         with_items: bool = False,
         with_subscriptions: bool = False,
+        with_affiliations: bool = False,
         create: bool = False,
-        create_kwargs: Optional[dict] = None,
-    ) -> Optional[PubsubNode]:
+        create_kwargs: dict|None = None,
+    ) -> PubsubNode|None:
         """Retrieve a PubsubNode from DB
 
         @param service: service hosting the node
         @param name: node's name
         @param with_items: retrieve items in the same query
         @param with_subscriptions: retrieve subscriptions in the same query
+        @param with_affiliations: retrieve affiliations in the same query
         @param create: if the node doesn't exist in DB, create it
         @param create_kwargs: keyword arguments to use with ``set_pubsub_node`` if the node
             needs to be created.
@@ -1197,6 +1203,8 @@
                 stmt = stmt.options(joinedload(PubsubNode.items))
             if with_subscriptions:
                 stmt = stmt.options(joinedload(PubsubNode.subscriptions))
+            if with_affiliations:
+                stmt = stmt.options(joinedload(PubsubNode.affiliations))
             result = await session.execute(stmt)
         ret = result.unique().scalar_one_or_none()
         if ret is None and create:
@@ -1219,6 +1227,7 @@
                             name,
                             with_items=with_items,
                             with_subscriptions=with_subscriptions,
+                            with_affiliations=with_affiliations,
                         )
                     )
                 else:
@@ -1227,25 +1236,59 @@
             return ret
 
     @aio
+    async def get_pubsub_nodes(
+        self,
+        client: SatXMPPEntity|None,
+        service: jid.JID|None
+    ) -> list[PubsubNode]:
+        """Retrieve pubsub nodes matching arguments.
+
+        @param client: If set, only return nodes of this client profile.
+        @param service: If set, only return nodes from this service.
+        @return: List of matching pubsub nodes.
+        """
+        async with self.session() as session:
+            stm = select(PubsubNode)
+            if client is not None:
+                profile_id = self.profiles[client.profile]
+                stm = stm.where(PubsubNode.profile_id == profile_id)
+            if service is not None:
+                stm = stm.where(PubsubNode.service == service)
+            result = await session.execute(stm)
+
+        return result.scalars().all()
+
+    @aio
     async def set_pubsub_node(
         self,
         client: SatXMPPEntity,
         service: jid.JID,
         name: str,
+        access_model: AccessModel|None = None,
+        publish_model: PublishModel|None = None,
         analyser: Optional[str] = None,
         type_: Optional[str] = None,
         subtype: Optional[str] = None,
         subscribed: bool = False,
+        extra: dict|None = None,
+        items: list[PubsubItem]|None = None,
+        affiliations: list[PubsubAffiliation]|None = None,
+        subscriptions: list[PubsubSub]|None = None,
     ) -> PubsubNode:
         node = PubsubNode(
             profile_id=self.profiles[client.profile],
             service=service,
             name=name,
+            access_model=access_model,
+            publish_model=publish_model,
             subscribed=subscribed,
             analyser=analyser,
             type_=type_,
             subtype=subtype,
-            subscriptions=[],
+            extra = extra,
+            items = items or [],
+            affiliations = affiliations or [],
+            subscriptions = subscriptions or []
         )
         async with self.session() as session:
             async with session.begin():