Skip to content

Commit

Permalink
feat: update tests + define PA role and permissions (#693)
Browse files Browse the repository at this point in the history
  • Loading branch information
hamzawaleed01 authored Aug 13, 2024
1 parent 6d9b896 commit f3455bf
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 131 deletions.
15 changes: 0 additions & 15 deletions license_manager/apps/api/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,3 @@ class CanRetireUser(permissions.BasePermission):

def has_permission(self, request, view):
return request.user.username == settings.RETIREMENT_SERVICE_WORKER_USERNAME or request.user.is_superuser


class IsInProvisioningAdminGroup(permissions.BasePermission):
"""
Grant access to those users only who are part of the license provisiioning django group
"""
ALLOWED_API_GROUPS = ['provisioning_admins_group']
message = 'Access denied: You do not have the necessary permissions to access this.'

def has_permission(self, request, view):
return (
super().has_permission(request, view) and (
request.user.groups.filter(name__in=self.ALLOWED_API_GROUPS).exists()
)
)
1 change: 0 additions & 1 deletion license_manager/apps/api/v1/tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

# Constants for subscriptions API tests
SUBSCRIPTION_RENEWAL_DAYS_OFFSET = 500
PROVISIONING_ADMINS_GROUP = "provisioning_admins_group"

ADMIN_ROLES = {
'system_role': constants.SYSTEM_ENTERPRISE_ADMIN_ROLE,
Expand Down
214 changes: 106 additions & 108 deletions license_manager/apps/api/v1/tests/test_views.py

Large diffs are not rendered by default.

18 changes: 11 additions & 7 deletions license_manager/apps/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema, extend_schema_view
from edx_rbac.decorators import permission_required
from edx_rbac.mixins import PermissionRequiredForListingMixin
from edx_rbac.mixins import (
PermissionRequiredForListingMixin,
PermissionRequiredMixin,
)
from edx_rest_framework_extensions.auth.jwt.authentication import (
JwtAuthentication,
)
Expand All @@ -30,10 +33,7 @@
from license_manager.apps.api.filters import LicenseFilter
from license_manager.apps.api.mixins import UserDetailsFromJwtMixin
from license_manager.apps.api.models import BulkEnrollmentJob
from license_manager.apps.api.permissions import (
CanRetireUser,
IsInProvisioningAdminGroup,
)
from license_manager.apps.api.permissions import CanRetireUser
from license_manager.apps.api.tasks import (
create_braze_aliases_task,
execute_post_revocation_tasks,
Expand Down Expand Up @@ -311,13 +311,15 @@ def _check_subscription_licenses(self, customer_agreement, plan, user_email):
),
)
class CustomerAgreementProvisioningAdminViewset(
PermissionRequiredMixin,
viewsets.GenericViewSet,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin
):
""" Viewset for Provisioning Admins write operations."""
authentication_classes = [JwtAuthentication, SessionAuthentication]
permission_classes = [permissions.IsAuthenticated, IsInProvisioningAdminGroup]
permission_classes = [permissions.IsAuthenticated]
permission_required = constants.SUBSCRIPTIONS_CUSTOMER_AGREEMENT_PROVISIONING_ADMIN_ACCESS_PERMISSION
lookup_field = 'uuid'
lookup_url_kwarg = 'customer_agreement_uuid'
serializer_class = serializers.CustomerAgreementSerializer
Expand Down Expand Up @@ -460,13 +462,15 @@ def list(self, request, *args, **kwargs):
),
)
class SubscriptionPlanProvisioningAdminViewset(
PermissionRequiredMixin,
mixins.CreateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet
):
""" Viewset for Provisioning Admins write operations."""
authentication_classes = [JwtAuthentication, SessionAuthentication]
permission_classes = [permissions.IsAuthenticated, IsInProvisioningAdminGroup]
permission_classes = [permissions.IsAuthenticated]
permission_required = constants.SUBSCRIPTIONS_PROVISIONING_ADMIN_ACCESS_PERMISSION
lookup_field = 'uuid'
lookup_url_kwarg = 'subscription_uuid' # URL keyword for the lookup field

Expand Down
9 changes: 9 additions & 0 deletions license_manager/apps/subscriptions/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,23 @@ class SegmentEvents:
# Role-based access control
SUBSCRIPTIONS_ADMIN_ROLE = 'enterprise_subscriptions_admin'
SUBSCRIPTIONS_LEARNER_ROLE = 'enterprise_subscriptions_learner'
# Role-based access control - Provisioning admins
PROVISIONING_SUBSCRIPTION_ADMIN_ROLE = 'provisioning_subscription_admin'
PROVISIONING_CUSTOMER_AGREEMENT_ADMIN_ROLE = 'provisioning_customer_agreement_admin'

SYSTEM_ENTERPRISE_ADMIN_ROLE = 'enterprise_admin'
SYSTEM_ENTERPRISE_LEARNER_ROLE = 'enterprise_learner'
SYSTEM_ENTERPRISE_OPERATOR_ROLE = 'enterprise_openedx_operator'
SYSTEM_ENTERPRISE_PROVISIONING_ADMIN_ROLE = 'enterprise_provisioning_admin'

SUBSCRIPTIONS_ADMIN_ACCESS_PERMISSION = 'subscriptions.has_admin_access'
SUBSCRIPTIONS_ADMIN_LEARNER_ACCESS_PERMISSION = 'subscriptions.has_learner_or_admin_access'

# Provisioning admins permissions
SUBSCRIPTIONS_PROVISIONING_ADMIN_ACCESS_PERMISSION = 'subscriptions.has_provisioning_admin_access'
SUBSCRIPTIONS_CUSTOMER_AGREEMENT_PROVISIONING_ADMIN_ACCESS_PERMISSION = \
'agreements.has_provisioning_admin_access'

# Subsidy constants
PERCENTAGE_DISCOUNT_TYPE = 'percentage'
LICENSE_DISCOUNT_VALUE = 100 # Represents a 100% off value
Expand Down
44 changes: 44 additions & 0 deletions license_manager/apps/subscriptions/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,47 @@ def has_explicit_access_to_subscriptions_learner(user, enterprise_customer_uuid)
constants.SUBSCRIPTIONS_ADMIN_LEARNER_ACCESS_PERMISSION,
has_admin_access | has_learner_access,
)


@rules.predicate
def has_implicit_access_to_subscription_plan_provisioning(user, enterprise_customer_uuid): # pylint: disable=unused-argument
"""
Check that if request user has implicit access as PROVISIONING_SUBSCRIPTION_ADMIN_ROLE.
Returns:
boolean: whether the request user has access.
"""
return request_user_has_implicit_access_via_jwt(
get_decoded_jwt(crum.get_current_request()),
constants.PROVISIONING_SUBSCRIPTION_ADMIN_ROLE,
str(enterprise_customer_uuid),
)


# Grants access permission if the user is a provisioning admin
rules.add_perm(
constants.SUBSCRIPTIONS_PROVISIONING_ADMIN_ACCESS_PERMISSION,
has_implicit_access_to_subscription_plan_provisioning,
)


@rules.predicate
def has_implicit_access_to_customer_agreement_provisioning(user, enterprise_customer_uuid): # pylint: disable=unused-argument
"""
Check that if request user has implicit access as PROVISIONING_SUBSCRIPTION_ADMIN_ROLE.
Returns:
boolean: whether the request user has access.
"""
return request_user_has_implicit_access_via_jwt(
get_decoded_jwt(crum.get_current_request()),
constants.PROVISIONING_CUSTOMER_AGREEMENT_ADMIN_ROLE,
str(enterprise_customer_uuid),
)


# Grants access permission if the user is a provisioning admin
rules.add_perm(
constants.SUBSCRIPTIONS_CUSTOMER_AGREEMENT_PROVISIONING_ADMIN_ACCESS_PERMISSION,
has_implicit_access_to_customer_agreement_provisioning,
)
7 changes: 7 additions & 0 deletions license_manager/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
from corsheaders.defaults import default_headers as corsheaders_default_headers

from license_manager.apps.subscriptions.constants import (
PROVISIONING_SUBSCRIPTION_ADMIN_ROLE,
PROVISIONING_CUSTOMER_AGREEMENT_ADMIN_ROLE,
SUBSCRIPTIONS_ADMIN_ROLE,
SUBSCRIPTIONS_LEARNER_ROLE,
SYSTEM_ENTERPRISE_ADMIN_ROLE,
SYSTEM_ENTERPRISE_LEARNER_ROLE,
SYSTEM_ENTERPRISE_OPERATOR_ROLE,
SYSTEM_ENTERPRISE_PROVISIONING_ADMIN_ROLE,
)
from license_manager.settings.utils import get_logger_config

Expand Down Expand Up @@ -405,6 +408,10 @@
SYSTEM_ENTERPRISE_OPERATOR_ROLE: [SUBSCRIPTIONS_ADMIN_ROLE],
SYSTEM_ENTERPRISE_ADMIN_ROLE: [SUBSCRIPTIONS_ADMIN_ROLE],
SYSTEM_ENTERPRISE_LEARNER_ROLE: [SUBSCRIPTIONS_LEARNER_ROLE],
SYSTEM_ENTERPRISE_PROVISIONING_ADMIN_ROLE: [
PROVISIONING_SUBSCRIPTION_ADMIN_ROLE,
PROVISIONING_CUSTOMER_AGREEMENT_ADMIN_ROLE,
]
}

SOCIAL_MEDIA_FOOTER_URLS = os.environ.get('SOCIAL_MEDIA_FOOTER_URLS', '')
Expand Down

0 comments on commit f3455bf

Please sign in to comment.