From f4e75a53eed1ce9e950543439ea2a9a380d5c616 Mon Sep 17 00:00:00 2001 From: Odysseus Chiu Date: Wed, 18 Dec 2024 07:51:38 -0800 Subject: [PATCH 1/3] 24651 - updates for contact_centre_staff KC group --- auth-api/src/auth_api/resources/v1/activity_log.py | 2 +- auth-api/src/auth_api/resources/v1/org.py | 2 +- auth-api/src/auth_api/resources/v1/task.py | 4 ++-- auth-api/src/auth_api/services/authorization.py | 3 +-- auth-api/src/auth_api/services/org.py | 7 +++++-- auth-api/src/auth_api/utils/roles.py | 6 ++++++ auth-api/src/auth_api/utils/user_context.py | 6 ++++-- 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/auth-api/src/auth_api/resources/v1/activity_log.py b/auth-api/src/auth_api/resources/v1/activity_log.py index a4b82b0afa..e245de3542 100644 --- a/auth-api/src/auth_api/resources/v1/activity_log.py +++ b/auth-api/src/auth_api/resources/v1/activity_log.py @@ -29,7 +29,7 @@ @bp.route("", methods=["GET", "OPTIONS"]) @cross_origin(origins="*", methods="GET") -@_jwt.has_one_of_roles([Role.SYSTEM.value, Role.STAFF.value, Role.ACCOUNT_HOLDER.value]) +@_jwt.has_one_of_roles([Role.SYSTEM.value, Role.STAFF.value, Role.ACCOUNT_HOLDER.value, Role.VIEW_ACTIVITY_LOGS.value]) def get_activities(org_id): """Fetch activities.""" try: diff --git a/auth-api/src/auth_api/resources/v1/org.py b/auth-api/src/auth_api/resources/v1/org.py index 7192cf60b9..3d0c8c5855 100644 --- a/auth-api/src/auth_api/resources/v1/org.py +++ b/auth-api/src/auth_api/resources/v1/org.py @@ -81,7 +81,7 @@ def search_organizations(): roles = token.get("realm_access").get("roles") # public user can only get status of orgs in search, unless they have special roles. - allowed_roles = [Role.STAFF.value, Role.SYSTEM.value, Role.ACCOUNT_IDENTITY] + allowed_roles = [Role.STAFF.value, Role.SYSTEM.value, Role.ACCOUNT_IDENTITY, Role.STAFF_VIEW_ACCOUNTS.value] if Role.PUBLIC_USER.value in roles and not set(roles).intersection(set(allowed_roles)): if response and response.get("orgs"): status = HTTPStatus.OK diff --git a/auth-api/src/auth_api/resources/v1/task.py b/auth-api/src/auth_api/resources/v1/task.py index 7304a3f30a..b47738c688 100644 --- a/auth-api/src/auth_api/resources/v1/task.py +++ b/auth-api/src/auth_api/resources/v1/task.py @@ -34,7 +34,7 @@ @bp.route("", methods=["GET", "OPTIONS"]) @cross_origin(origins="*", methods=["GET"]) -@_jwt.has_one_of_roles([Role.STAFF.value]) +@_jwt.has_one_of_roles([Role.STAFF.value, Role.STAFF_TASK_SEARCH.value]) def get_tasks(): """Fetch tasks.""" try: @@ -62,7 +62,7 @@ def get_tasks(): @bp.route("/", methods=["GET", "OPTIONS"]) @cross_origin(origins="*", methods=["GET", "PUT"]) -@_jwt.has_one_of_roles([Role.STAFF.value]) +@_jwt.has_one_of_roles([Role.STAFF.value, Role.VIEW_TASK_DETAILS.value]) def get_task(task_id): """Fetch task by id.""" try: diff --git a/auth-api/src/auth_api/services/authorization.py b/auth-api/src/auth_api/services/authorization.py index c85b473051..174f981342 100644 --- a/auth-api/src/auth_api/services/authorization.py +++ b/auth-api/src/auth_api/services/authorization.py @@ -52,8 +52,7 @@ def get_account_authorizations_for_org( auth = None token_roles = user_from_context.roles - # todo the service account level access has not been defined - if Role.STAFF.value in token_roles: + if Role.STAFF.value in token_roles or Role.CONTACT_CENTRE_STAFF.value in token_roles: if expanded: # Query Authorization view by business identifier auth = AuthorizationView.find_authorization_for_admin_by_org_id(account_id) diff --git a/auth-api/src/auth_api/services/org.py b/auth-api/src/auth_api/services/org.py index 8576fb3b47..f92c8d44df 100644 --- a/auth-api/src/auth_api/services/org.py +++ b/auth-api/src/auth_api/services/org.py @@ -772,14 +772,17 @@ def get_orgs(user_id, valid_statuses=VALID_STATUSES): return MembershipModel.find_orgs_for_user(user_id, valid_statuses) @staticmethod - def search_orgs(search: OrgSearch, environment): # pylint: disable=too-many-locals + @user_context + def search_orgs(search: OrgSearch, environment, **kwargs): # pylint: disable=too-many-locals """Search for orgs based on input parameters.""" orgs_result = {"orgs": [], "page": search.page, "limit": search.limit, "total": 0} include_invitations: bool = False + user_from_context: UserContext = kwargs["user_context"] + roles = user_from_context.roles search.access_type, is_staff_admin = Org.refine_access_type(search.access_type) if search.statuses and OrgStatus.PENDING_ACTIVATION.value in search.statuses: # only staff admin can see director search accounts - if not is_staff_admin: + if not is_staff_admin and Role.VIEW_ACCOUNT_PENDING_INVITATIONS.value not in roles: raise BusinessException(Error.INVALID_USER_CREDENTIALS, None) org_models, orgs_result["total"] = OrgModel.search_pending_activation_orgs(name=search.name) include_invitations = True diff --git a/auth-api/src/auth_api/utils/roles.py b/auth-api/src/auth_api/utils/roles.py index 2194138055..168d80c13a 100644 --- a/auth-api/src/auth_api/utils/roles.py +++ b/auth-api/src/auth_api/utils/roles.py @@ -44,6 +44,12 @@ class Role(Enum): # Used by Business-AR to create affiliations that may already have a passcode (bypass passcode check) SKIP_AFFILIATION_AUTH = "skip_affiliation_auth" + CONTACT_CENTRE_STAFF = "contact_centre_staff" + STAFF_TASK_SEARCH = "staff_task_search" + VIEW_TASK_DETAILS = "view_task_details" + VIEW_ACCOUNT_PENDING_INVITATIONS = "view_account_pending_invitations" + VIEW_ACTIVITY_LOGS = "view_activity_logs" + # Membership types STAFF = "STAFF" diff --git a/auth-api/src/auth_api/utils/user_context.py b/auth-api/src/auth_api/utils/user_context.py index a71dbd23ed..8b48e0dabe 100644 --- a/auth-api/src/auth_api/utils/user_context.py +++ b/auth-api/src/auth_api/utils/user_context.py @@ -81,8 +81,10 @@ def has_role(self, role_name: str) -> bool: return role_name in self._roles def is_staff(self) -> bool: - """Return True if the user is staff user.""" - return Role.STAFF.value in self._roles if self._roles else False + """Return True if the user is staff user or contact centre staff.""" + if self._roles: + return Role.STAFF.value in self._roles or Role.CONTACT_CENTRE_STAFF.value in self._roles + return False def is_staff_admin(self) -> bool: """Return True if the user is staff user.""" From b64f92ec335596fbf700e07622a1c7bccd3113c4 Mon Sep 17 00:00:00 2001 From: Odysseus Chiu Date: Wed, 18 Dec 2024 08:30:54 -0800 Subject: [PATCH 2/3] PR Feedback --- auth-api/src/auth_api/services/authorization.py | 2 +- auth-api/src/auth_api/utils/user_context.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/auth-api/src/auth_api/services/authorization.py b/auth-api/src/auth_api/services/authorization.py index 174f981342..667534ba6f 100644 --- a/auth-api/src/auth_api/services/authorization.py +++ b/auth-api/src/auth_api/services/authorization.py @@ -52,7 +52,7 @@ def get_account_authorizations_for_org( auth = None token_roles = user_from_context.roles - if Role.STAFF.value in token_roles or Role.CONTACT_CENTRE_STAFF.value in token_roles: + if any(role in [Role.STAFF.value, Role.CONTACT_CENTRE_STAFF.value] for role in token_roles): if expanded: # Query Authorization view by business identifier auth = AuthorizationView.find_authorization_for_admin_by_org_id(account_id) diff --git a/auth-api/src/auth_api/utils/user_context.py b/auth-api/src/auth_api/utils/user_context.py index 8b48e0dabe..76c2024569 100644 --- a/auth-api/src/auth_api/utils/user_context.py +++ b/auth-api/src/auth_api/utils/user_context.py @@ -82,9 +82,7 @@ def has_role(self, role_name: str) -> bool: def is_staff(self) -> bool: """Return True if the user is staff user or contact centre staff.""" - if self._roles: - return Role.STAFF.value in self._roles or Role.CONTACT_CENTRE_STAFF.value in self._roles - return False + return any(role in [Role.STAFF.value, Role.CONTACT_CENTRE_STAFF.value] for role in self._roles) def is_staff_admin(self) -> bool: """Return True if the user is staff user.""" From 6621c65a8a478d09f72fd8b39098f4cf80ef31a7 Mon Sep 17 00:00:00 2001 From: Odysseus Chiu Date: Wed, 18 Dec 2024 08:34:18 -0800 Subject: [PATCH 3/3] fix --- auth-api/src/auth_api/utils/user_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth-api/src/auth_api/utils/user_context.py b/auth-api/src/auth_api/utils/user_context.py index 76c2024569..bea14bd2c7 100644 --- a/auth-api/src/auth_api/utils/user_context.py +++ b/auth-api/src/auth_api/utils/user_context.py @@ -82,7 +82,7 @@ def has_role(self, role_name: str) -> bool: def is_staff(self) -> bool: """Return True if the user is staff user or contact centre staff.""" - return any(role in [Role.STAFF.value, Role.CONTACT_CENTRE_STAFF.value] for role in self._roles) + return self._roles and any(role in [Role.STAFF.value, Role.CONTACT_CENTRE_STAFF.value] for role in self._roles) def is_staff_admin(self) -> bool: """Return True if the user is staff user."""