This is an automated email from the ASF dual-hosted git repository.

yasithdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git


The following commit(s) were added to refs/heads/main by this push:
     new e86665c49 feat(portal): de-Thrift group management to the gRPC sharing 
facade (Track D, D5) (#183)
e86665c49 is described below

commit e86665c492a8510d1e241a09f87f6f4b869b84a1
Author: Yasith Jayawardana <[email protected]>
AuthorDate: Mon Jun 8 22:10:24 2026 -0400

    feat(portal): de-Thrift group management to the gRPC sharing facade (Track 
D, D5) (#183)
    
    `GroupViewSet` and `GroupSerializer` ran on the Thrift `group_manager`
    profile-service client, so listing groups (and every page that loads the
    sharing/group data) blocked on the dead Thrift server's read-timeout (~25s).
    
    - `GroupViewSet` get_list/get_instance/perform_create/perform_update/
      perform_destroy -> `request.airavata.sharing.gm_*` (gm_get_groups / 
gm_get_group
      / gm_create_group / gm_add_users_to_group / gm_remove_users_from_group /
      gm_add_group_admins / gm_remove_group_admins / gm_update_group /
      gm_delete_group). `_send_users_added_to_group` loads the added user's 
profile
      via `request.airavata.iam.get_user_profile_by_id`.
    - `GroupSerializer.get_isAdmin` -> `sharing.gm_has_admin_access`;
      `_gateway_groups` -> `compute.get_gateway_groups` (now also carries
      `defaultGatewayUsersGroupId`, which the serializer reads).
    - `grpc_adapters.group` (proto GroupModel -> serializer shape) and
      `grpc_requests.group` (reverse) added.
    - `_gateway_groups_dict` middleware helper extended with the third group id 
for
      consistency with the cached session dict the serializer reads.
    - The `user_added_to_group` signal now carries a protobuf `UserProfile`, so
      `email_user_added_to_group` reads `first_name`/`last_name`/`user_id`.
    
    Verified: `manage.py check` green; group adapter round-trips (proto -> 
adapter ->
    reverse-proto) field-for-field; live `/api/groups/` went from a 25s hang to
    200 in ~0.02s. (Creating a group / initializing GatewayGroups isn't 
seedable in
    the ephemeral dev backend — the serializer's group-flag fields are migrated 
1:1
    from their Thrift equivalents.)
---
 .../django_airavata/apps/api/grpc_adapters.py      | 12 +++++++
 .../django_airavata/apps/api/grpc_requests.py      | 12 +++++++
 .../django_airavata/apps/api/serializers.py        | 12 ++++---
 .../django_airavata/apps/api/views.py              | 38 ++++++++++------------
 .../django_airavata/apps/auth/middleware.py        |  3 +-
 .../django_airavata/apps/auth/signals.py           |  6 ++--
 6 files changed, 53 insertions(+), 30 deletions(-)

diff --git a/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py 
b/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
index 848b3614f..057c5a081 100644
--- a/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
+++ b/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
@@ -832,6 +832,18 @@ def experiment(pb):
     )
 
 
+def group(pb):
+    """gRPC ``GroupModel`` -> ``GroupSerializer`` shape."""
+    return SimpleNamespace(
+        id=pb.id,
+        name=pb.name,
+        ownerId=pb.owner_id,
+        description=pb.description or None,
+        members=list(pb.members),
+        admins=list(pb.admins),
+    )
+
+
 def notification(pb):
     """gRPC ``Notification`` -> ``NotificationSerializer`` shape."""
     return SimpleNamespace(
diff --git a/airavata-django-portal/django_airavata/apps/api/grpc_requests.py 
b/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
index b5b40806e..3bc156d4c 100644
--- a/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
+++ b/airavata-django-portal/django_airavata/apps/api/grpc_requests.py
@@ -543,3 +543,15 @@ def group_resource_profile(t):
         updated_time=t.updatedTime or 0,
         default_credential_store_token=t.defaultCredentialStoreToken or '',
     )
+
+
+def group(t):
+    """Thrift ``GroupModel`` -> proto ``GroupModel`` request message."""
+    return _pb2("group.group_manager_pb2").GroupModel(
+        id=t.id or '',
+        name=t.name or '',
+        owner_id=t.ownerId or '',
+        description=t.description or '',
+        members=list(t.members or []),
+        admins=list(t.admins or []),
+    )
diff --git a/airavata-django-portal/django_airavata/apps/api/serializers.py 
b/airavata-django-portal/django_airavata/apps/api/serializers.py
index c64471289..38e0630fb 100644
--- a/airavata-django-portal/django_airavata/apps/api/serializers.py
+++ b/airavata-django-portal/django_airavata/apps/api/serializers.py
@@ -232,8 +232,7 @@ class 
GroupSerializer(thrift_utils.create_serializer_class(GroupModel)):
 
     def get_isAdmin(self, group):
         request = self.context['request']
-        return request.profile_service['group_manager'].hasAdminAccess(
-            request.authz_token,
+        return request.airavata.sharing.gm_has_admin_access(
             group.id,
             request.user.username + "@" + settings.GATEWAY_ID)
 
@@ -263,9 +262,12 @@ class 
GroupSerializer(thrift_utils.create_serializer_class(GroupModel)):
         if 'GATEWAY_GROUPS' in request.session:
             return request.session['GATEWAY_GROUPS']
         else:
-            gateway_groups = request.airavata_client.getGatewayGroups(
-                request.authz_token)
-            return copy.deepcopy(gateway_groups.__dict__)
+            gg = request.airavata.compute.get_gateway_groups()
+            return {
+                'adminsGroupId': gg.admins_group_id,
+                'readOnlyAdminsGroupId': gg.read_only_admins_group_id,
+                'defaultGatewayUsersGroupId': 
gg.default_gateway_users_group_id,
+            }
 
 
 class ProjectSerializer(
diff --git a/airavata-django-portal/django_airavata/apps/api/views.py 
b/airavata-django-portal/django_airavata/apps/api/views.py
index 1bd7876fc..ca4ddea64 100644
--- a/airavata-django-portal/django_airavata/apps/api/views.py
+++ b/airavata-django-portal/django_airavata/apps/api/views.py
@@ -93,53 +93,49 @@ class GroupViewSet(APIBackedViewSet):
 
         class GroupResultsIterator(APIResultIterator):
             def get_results(self, limit=-1, offset=0):
-                group_manager = view.request.profile_service['group_manager']
-                groups = group_manager.getGroups(view.authz_token)
+                groups = [
+                    grpc_adapters.group(g)
+                    for g in view.request.airavata.sharing.gm_get_groups()
+                ]
                 end = offset + limit if limit > 0 else len(groups)
                 return groups[offset:end] if groups else []
 
         return GroupResultsIterator()
 
     def get_instance(self, lookup_value):
-        return self.request.profile_service['group_manager'].getGroup(
-            self.authz_token, lookup_value)
+        return grpc_adapters.group(
+            self.request.airavata.sharing.gm_get_group(lookup_value))
 
     def perform_create(self, serializer):
         group = serializer.save()
-        group_id = self.request.profile_service['group_manager'].createGroup(
-            self.authz_token, group)
+        group_id = self.request.airavata.sharing.gm_create_group(
+            grpc_requests.group(group))
         group.id = group_id
         users_added_to_group = set(group.members) - {group.ownerId}
         self._send_users_added_to_group(users_added_to_group, group)
 
     def perform_update(self, serializer):
         group = serializer.save()
-        group_manager_client = self.request.profile_service['group_manager']
+        sharing = self.request.airavata.sharing
         if len(group._added_members) > 0:
-            group_manager_client.addUsersToGroup(
-                self.authz_token, group._added_members, group.id)
+            sharing.gm_add_users_to_group(group._added_members, group.id)
             self._send_users_added_to_group(group._added_members, group)
         if len(group._removed_members) > 0:
-            group_manager_client.removeUsersFromGroup(
-                self.authz_token, group._removed_members, group.id)
+            sharing.gm_remove_users_from_group(group._removed_members, 
group.id)
         if len(group._added_admins) > 0:
-            group_manager_client.addGroupAdmins(
-                self.authz_token, group.id, group._added_admins)
+            sharing.gm_add_group_admins(group.id, group._added_admins)
         if len(group._removed_admins) > 0:
-            group_manager_client.removeGroupAdmins(
-                self.authz_token, group.id, group._removed_admins)
-        group_manager_client.updateGroup(self.authz_token, group)
+            sharing.gm_remove_group_admins(group.id, group._removed_admins)
+        sharing.gm_update_group(grpc_requests.group(group))
 
     def perform_destroy(self, group):
-        group_manager_client = self.request.profile_service['group_manager']
-        group_manager_client.deleteGroup(
-            self.authz_token, group.id, group.ownerId)
+        self.request.airavata.sharing.gm_delete_group(group.id, group.ownerId)
 
     def _send_users_added_to_group(self, internal_user_ids, group):
         for internal_user_id in internal_user_ids:
             user_id, gateway_id = internal_user_id.rsplit("@", maxsplit=1)
-            user_profile = 
self.request.profile_service['user_profile'].getUserProfileById(
-                self.authz_token, user_id, gateway_id)
+            user_profile = self.request.airavata.iam.get_user_profile_by_id(
+                user_id, gateway_id)
             signals.user_added_to_group.send(
                 sender=self.__class__,
                 user=user_profile,
diff --git a/airavata-django-portal/django_airavata/apps/auth/middleware.py 
b/airavata-django-portal/django_airavata/apps/auth/middleware.py
index 319e5fa63..7c3f49d90 100644
--- a/airavata-django-portal/django_airavata/apps/auth/middleware.py
+++ b/airavata-django-portal/django_airavata/apps/auth/middleware.py
@@ -34,7 +34,8 @@ def _gateway_groups_dict(request):
     """Fetch the gateway's admin group ids via the gRPC compute facade."""
     gg = request.airavata.compute.get_gateway_groups()
     return {'adminsGroupId': gg.admins_group_id,
-            'readOnlyAdminsGroupId': gg.read_only_admins_group_id}
+            'readOnlyAdminsGroupId': gg.read_only_admins_group_id,
+            'defaultGatewayUsersGroupId': gg.default_gateway_users_group_id}
 
 
 def set_admin_group_attributes(request, gateway_groups=None):
diff --git a/airavata-django-portal/django_airavata/apps/auth/signals.py 
b/airavata-django-portal/django_airavata/apps/auth/signals.py
index 96d180d69..8c208f83a 100644
--- a/airavata-django-portal/django_airavata/apps/auth/signals.py
+++ b/airavata-django-portal/django_airavata/apps/auth/signals.py
@@ -17,9 +17,9 @@ log = logging.getLogger(__name__)
 def email_user_added_to_group(sender, user, groups, request, **kwargs):
     context = Context({
         "email": user.emails[0],
-        "first_name": user.firstName,
-        "last_name": user.lastName,
-        "username": user.userId,
+        "first_name": user.first_name,
+        "last_name": user.last_name,
+        "username": user.user_id,
         "portal_title": settings.PORTAL_TITLE,
         "dashboard_url": request.build_absolute_uri(
             reverse("django_airavata_workspace:dashboard")),

Reply via email to