3232from auth_api .models import Org as OrgModel
3333from auth_api .models .dataclass import Activity
3434from auth_api .schemas import MembershipSchema
35- from auth_api .utils .enums import ActivityAction , LoginSource , NotificationType , Status
36- from auth_api .utils .roles import ADMIN , ALL_ALLOWED_ROLES , COORDINATOR , STAFF
35+ from auth_api .utils .constants import GROUP_CONTACT_CENTRE_STAFF , GROUP_MAXIMUS_STAFF
36+ from auth_api .utils .enums import ActivityAction , LoginSource , NotificationType , OrgType , Status
37+ from auth_api .utils .roles import ADMIN , ALL_ALLOWED_ROLES , COORDINATOR , STAFF , USER
3738from auth_api .utils .user_context import UserContext , user_context
3839
3940from ..utils .account_mailer import publish_to_mailer
4748CONFIG = get_named_config ()
4849logger = StructuredLogging .get_logger ()
4950
51+ org_type_to_group_mapping = {
52+ OrgType .MAXIMUS_STAFF .value : GROUP_MAXIMUS_STAFF ,
53+ OrgType .CONTACT_CENTRE_STAFF .value : GROUP_CONTACT_CENTRE_STAFF ,
54+ }
55+
5056
5157class Membership : # pylint: disable=too-many-instance-attributes,too-few-public-methods
5258 """Manages all aspects of the Membership Entity.
@@ -214,6 +220,10 @@ def update_membership(self, updated_fields, **kwargs):
214220 logger .debug ("<update_membership" )
215221 user_from_context : UserContext = kwargs ["user_context" ]
216222 check_auth (org_id = self ._model .org_id , one_of_roles = (COORDINATOR , ADMIN , STAFF ))
223+ updated_membership_status = updated_fields .get ("membership_status" )
224+
225+ # When adding to organization, check if user is already in an ACTIVE STAFF org, if so raise exception
226+ Membership ._check_if_add_user_has_active_staff_org (updated_membership_status , self ._model .user .id )
217227
218228 # bceid Members cant be ADMIN's.Unless they have an affidavit approved.
219229 # TODO when multiple teams for bceid are present , do if the user has affidavit present check
@@ -225,8 +235,8 @@ def update_membership(self, updated_fields, **kwargs):
225235 if self ._model .membership_type .code == COORDINATOR and updated_fields .get ("membership_type" , None ) == ADMIN :
226236 check_auth (org_id = self ._model .org_id , one_of_roles = (ADMIN , STAFF ))
227237
228- updated_membership_status = updated_fields .get ("membership_status" )
229238 admin_getting_removed : bool = False
239+
230240 # Admin can be removed by other admin or staff. #4909
231241 if (
232242 updated_membership_status
@@ -317,14 +327,41 @@ def _add_or_remove_group(model: MembershipModel):
317327 """Add or remove the user from/to account holders / product keycloak group."""
318328 if model .membership_status .id == Status .ACTIVE .value :
319329 KeycloakService .join_account_holders_group (model .user .keycloak_guid )
320- elif (
321- model .membership_status .id == Status .INACTIVE .value
322- and len (MembershipModel .find_orgs_for_user (model .user .id )) == 0
323- ):
330+ elif model .membership_status .id == Status .INACTIVE .value :
324331 # Check if the user has any other active org membership, if none remove from the group
325- KeycloakService .remove_from_account_holders_group (model .user .keycloak_guid )
332+ if len (MembershipModel .find_orgs_for_user (model .user .id )) == 0 :
333+ KeycloakService .remove_from_account_holders_group (model .user .keycloak_guid )
334+
335+ # Add or Remove from STAFF group in keycloak
336+ Membership ._add_or_remove_group_for_staff (model )
326337 ProductService .update_users_products_keycloak_groups ([model .user .id ])
327338
339+ @staticmethod
340+ def _add_or_remove_group_for_staff (model : MembershipModel ):
341+ mapping_group = org_type_to_group_mapping .get (model .org .type_code )
342+ if not mapping_group :
343+ return
344+
345+ user_groups = KeycloakService .get_user_groups (model .user .keycloak_guid )
346+ is_in_group = any (group ["name" ] == mapping_group for group in user_groups )
347+
348+ if model .membership_status .id == Status .ACTIVE .value and not is_in_group :
349+ KeycloakService .add_user_to_group (model .user .keycloak_guid , mapping_group )
350+ elif model .membership_status .id == Status .INACTIVE .value and is_in_group :
351+ KeycloakService .remove_user_from_group (model .user .keycloak_guid , mapping_group )
352+
353+ @staticmethod
354+ def _check_if_add_user_has_active_staff_org (updated_membership_status , user_id ):
355+ """Check if user is already associated with an active STAFF org."""
356+ staff_org_types = list (org_type_to_group_mapping .keys ())
357+ memberships = MembershipModel .find_memberships_by_user_id_and_status (user_id , Status .ACTIVE .value )
358+ staff_orgs = OrgModel .find_by_org_ids_and_org_types (
359+ org_ids = [membership .org_id for membership in memberships ], org_types = staff_org_types
360+ )
361+
362+ if updated_membership_status and updated_membership_status .id == Status .ACTIVE .value and len (staff_orgs ) > 0 :
363+ raise BusinessException (Error .MAX_NUMBER_OF_STAFF_ORGS_LIMIT , None )
364+
328365 @staticmethod
329366 def get_membership_for_org_and_user (org_id , user_id ):
330367 """Get the membership for the given org and user id."""
0 commit comments