Esempio n. 1
0
def can_status_be_set_by_gov_user(user: GovUser, original_status: str,
                                  new_status: str, is_mod: bool) -> bool:
    """
    Check that a status can be set by a gov user. Gov users can not set a case's status to
    `Applicant editing`. They also cannot set a case's status to `Finalised` or open a closed case
    without additional permissions.
    """
    if new_status == CaseStatusEnum.APPLICANT_EDITING:
        return False

    elif CaseStatusEnum.is_terminal(
            original_status) and not assert_user_has_permission(
                user, GovPermissions.REOPEN_CLOSED_CASES):
        return False

    if new_status == CaseStatusEnum.FINALISED:
        if is_mod:
            if not assert_user_has_permission(
                    user, GovPermissions.MANAGE_CLEARANCE_FINAL_ADVICE):
                return False
        else:
            if not assert_user_has_permission(
                    user, GovPermissions.MANAGE_LICENCE_FINAL_ADVICE):
                return False
    return True
Esempio n. 2
0
    def get(self, request, pk):
        """
        Concatenates all advice for a case and returns it or just returns if final advice already exists
        """
        if len(self.final_advice) == 0:
            assert_user_has_permission(
                request.user.govuser,
                constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)

            group_advice(self.case, self.team_advice, request.user,
                         AdviceLevel.FINAL)

            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.CREATED_FINAL_ADVICE,
                target=self.case,
            )
            final_advice = Advice.objects.filter(
                case=self.case).order_by("-created_at")
        else:
            final_advice = self.final_advice

        serializer = AdviceViewSerializer(final_advice, many=True)
        return JsonResponse(data={"advice": serializer.data},
                            status=status.HTTP_200_OK)
Esempio n. 3
0
    def post(self, request, org_pk):
        """
        Create a role
        """
        assert_user_has_permission(
            request.user.exporteruser,
            ExporterPermissions.EXPORTER_ADMINISTER_ROLES, org_pk)
        data = JSONParser().parse(request)
        data["organisation"] = str(org_pk)
        data["type"] = UserType.EXPORTER

        if Role.objects.filter(organisation=org_pk,
                               name__iexact=data["name"].strip()):
            error = {
                "name":
                [ErrorDetail(string="Name is not unique.", code="invalid")]
            }
            return JsonResponse(data={"errors": error},
                                status=status.HTTP_400_BAD_REQUEST)

        serializer = RoleSerializer(data=data)

        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return JsonResponse(data={"role": serializer.data},
                                status=status.HTTP_201_CREATED)
Esempio n. 4
0
    def get_queryset(self):
        _status = self.request.GET.get("status")
        exclude_permission = self.request.GET.get("exclude_permission")
        organisation_id = self.kwargs["org_pk"]

        if hasattr(self.request.user, "exporteruser"):
            assert_user_has_permission(self.request.user.exporteruser,
                                       ExporterPermissions.ADMINISTER_USERS,
                                       organisation_id)

        query = [Q(relationship__organisation__id=organisation_id)]

        if _status:
            query.append(
                Q(relationship__status=UserStatuses.from_string(_status)))

        return (ExporterUser.objects.filter(reduce(
            operator.and_, query)).exclude(
                relationship__role__permissions__in=[exclude_permission]).
                select_related("relationship__role").values(
                    "baseuser_ptr_id",
                    first_name=F("baseuser_ptr__first_name"),
                    last_name=F("baseuser_ptr__last_name"),
                    email=F("baseuser_ptr__email"),
                    status=F("relationship__status"),
                    role_name=F("relationship__role__name"),
                ))
Esempio n. 5
0
 def perform_update(self, serializer):
     # if status is being updated, ensure user has permission
     if self.request.data.get("status"):
         assert_user_has_permission(self.request.user.govuser,
                                    GovPermissions.ACTIVATE_FLAGS)
     serializer.save()
     apply_flagging_rule_for_flag(self.kwargs["pk"])
Esempio n. 6
0
    def put(self, request, pk):
        """ Respond to a control list classification."""
        assert_user_has_permission(request.user.govuser, constants.GovPermissions.RESPOND_PV_GRADING)

        query = get_exporter_query(pk)
        if CaseStatusEnum.is_terminal(query.status.status):
            return JsonResponse(
                data={"errors": [strings.Applications.Generic.TERMINAL_CASE_CANNOT_PERFORM_OPERATION_ERROR]},
                status=status.HTTP_400_BAD_REQUEST,
            )

        data = request.data

        pv_grading_good_serializer = PVGradingResponseSerializer(data=data)

        if pv_grading_good_serializer.is_valid():
            if not str_to_bool(data.get("validate_only")):
                pv_grading = pv_grading_good_serializer.save()
                self.update_query_and_good(query, data, pv_grading)
                self.generate_audit_trail(request.user, query)

                # Send a notification to the user
                for user_relationship in UserOrganisationRelationship.objects.filter(organisation=query.organisation):
                    user_relationship.send_notification(content_object=query, case=query)

                return JsonResponse(
                    data={"pv_grading_query": pv_grading_good_serializer.data}, status=status.HTTP_200_OK,
                )

            return JsonResponse(data={"pv_grading_query": data}, status=status.HTTP_200_OK)

        return JsonResponse(data={"errors": pv_grading_good_serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
Esempio n. 7
0
 def post(self, request, pk):
     """
     Creates advice for a case
     """
     assert_user_has_permission(
         request.user.govuser,
         constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)
     return post_advice(request, self.case, AdviceLevel.FINAL, team=True)
Esempio n. 8
0
    def perform_create(self, serializer):
        assert_user_has_permission(self.request.user.govuser, constants.GovPermissions.MAINTAIN_OGL)

        if not self.request.data.get("validate_only", False):
            instance = serializer.save()

            audit_trail_service.create(
                actor=self.request.user, verb=AuditType.OGL_CREATED, action_object=instance,
            )
Esempio n. 9
0
 def get(self, request, pk):
     assert_user_has_permission(
         request.user.govuser,
         constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)
     approved, refused = good_type_to_country_decisions(pk)
     return JsonResponse({
         "approved": list(approved.values()),
         "refused": list(refused.values())
     })
Esempio n. 10
0
 def get(self, request, pk):
     assert_user_has_permission(
         request.user.govuser,
         constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)
     return JsonResponse(
         data={
             "decision":
             AdviceType.APPROVE if GoodCountryDecision.objects.filter(
                 case_id=pk, approve=True).exists() else AdviceType.REFUSE
         })
Esempio n. 11
0
    def get_serializer_class(self):
        if hasattr(self.request.user, "exporteruser"):
            assert_user_has_permission(self.request.user.exporteruser,
                                       ExporterPermissions.ADMINISTER_SITES,
                                       self.kwargs["org_pk"])

        if self.request.method.lower() == "get":
            return SiteViewSerializer
        else:
            return SiteCreateUpdateSerializer
Esempio n. 12
0
    def change_status(self,
                      user,
                      status: CaseStatus,
                      note: Optional[str] = ""):
        """
        Sets the status for the case, runs validation on various parameters,
        creates audit entries and also runs flagging and automation rules
        """
        from api.cases.helpers import can_set_status
        from api.audit_trail import service as audit_trail_service
        from api.applications.libraries.application_helpers import can_status_be_set_by_gov_user
        from api.workflow.automation import run_routing_rules
        from api.workflow.flagging_rules_automation import apply_flagging_rules_to_case
        from api.licences.helpers import update_licence_status

        old_status = self.status.status

        # Only allow the final decision if the user has the MANAGE_FINAL_ADVICE permission
        if status.status == CaseStatusEnum.FINALISED:
            assert_user_has_permission(
                user.govuser, GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)

        if not can_set_status(self, status.status):
            raise ValidationError({"status": [strings.Statuses.BAD_STATUS]})

        if not can_status_be_set_by_gov_user(
                user.govuser, old_status, status.status, is_mod=False):
            raise ValidationError({"status": ["Status cannot be set by user"]})

        self.status = status
        self.save()

        # Update licence status if applicable case status change
        update_licence_status(self, status.status)

        if CaseStatusEnum.is_terminal(
                old_status) and not CaseStatusEnum.is_terminal(
                    self.status.status):
            apply_flagging_rules_to_case(self)

        audit_trail_service.create(
            actor=user,
            verb=AuditType.UPDATED_STATUS,
            target=self,
            payload={
                "status": {
                    "new": CaseStatusEnum.get_text(self.status.status),
                    "old": old_status
                },
                "additional_text": note,
            },
        )

        if old_status != self.status.status:
            run_routing_rules(case=self, keep_status=True)
Esempio n. 13
0
    def post(self, request, queue_pk):
        assert_user_has_permission(request.user.govuser,
                                   GovPermissions.ENFORCEMENT_CHECK)
        file = request.data.get("file")
        if not file:
            raise ValidationError(
                {"file": [Cases.EnforcementUnit.NO_FILE_ERROR]})

        queue = get_object_or_404(Queue, id=queue_pk)
        import_cases_xml(file, queue)
        return JsonResponse({"file": Cases.EnforcementUnit.SUCCESSFUL_UPLOAD})
Esempio n. 14
0
    def put(self, request, pk):
        """
        Finalise & grant a Licence
        """
        case = get_case(pk)

        # Check Permissions
        if CaseTypeSubTypeEnum.is_mod_clearance(case.case_type.sub_type):
            assert_user_has_permission(
                request.user.govuser,
                GovPermissions.MANAGE_CLEARANCE_FINAL_ADVICE)
Esempio n. 15
0
    def post(self, request, pk):
        assert_user_has_permission(
            request.user.govuser,
            constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)

        data = {k: v for k, v in request.data.items() if v is not None}

        # Get list of all required item id's
        required_decisions = get_required_good_type_to_country_combinations(pk)
        required_decision_ids = set()
        for goods_type, country_list in required_decisions.items():
            for country in country_list:
                required_decision_ids.add(f"{goods_type}.{country}")

        if not required_decision_ids.issubset(data):
            missing_ids = required_decision_ids.difference(request.data)
            raise ParseError({
                missing_id: [Cases.GoodCountryMatrix.MISSING_ITEM]
                for missing_id in missing_ids
            })

        # Delete existing decision documents if decision changes
        existing_decisions = get_existing_good_type_to_country_decisions(pk)
        for decision_id in required_decision_ids:
            if (data.get(decision_id) !=
                    AdviceType.REFUSE) != existing_decisions.get(decision_id):
                # Proviso N/A as there is no proviso document type
                GeneratedCaseDocument.objects.filter(
                    case_id=pk,
                    advice_type__in=[AdviceType.APPROVE, AdviceType.REFUSE],
                    visible_to_exporter=False).delete()
                break

        # Update or create GoodCountryDecisions
        for id in required_decision_ids:
            goods_type_id, country_id = id.split(".")
            value = data[id] == AdviceType.APPROVE
            GoodCountryDecision.objects.update_or_create(
                case_id=pk,
                goods_type_id=goods_type_id,
                country_id=country_id,
                defaults={"approve": value})

        audit_trail_service.create(
            actor=request.user,
            verb=AuditType.UPDATED_GOOD_ON_DESTINATION_MATRIX,
            target=get_case(pk),
        )

        return JsonResponse(
            data={"good_country_decisions": list(required_decision_ids)},
            status=status.HTTP_201_CREATED)
Esempio n. 16
0
    def get(self, request, pk):
        """
        Get user from pk
        """
        user = get_user_by_pk(pk)
        organisation = get_request_user_organisation(request)
        if request.user.pk != pk:
            assert_user_has_permission(request.user.exporteruser,
                                       ExporterPermissions.ADMINISTER_USERS,
                                       organisation)
        relationship = get_user_organisation_relationship(user, organisation)

        serializer = ExporterUserViewSerializer(user, context=relationship)
        return JsonResponse(data={"user": serializer.data})
Esempio n. 17
0
    def post(self, request, org_pk):
        if hasattr(request.user, "exporteruser"):
            assert_user_has_permission(request.user.exporteruser,
                                       ExporterPermissions.ADMINISTER_SITES,
                                       org_pk)

        data = request.data

        if "records_located_step" in data:
            if "site_records_stored_here" not in data:
                return JsonResponse(
                    data={
                        "errors": {
                            "site_records_stored_here":
                            [strings.Site.NO_RECORDS_LOCATED_AT]
                        }
                    },
                    status=status.HTTP_400_BAD_REQUEST,
                )

            if not str_to_bool(data["site_records_stored_here"]
                               ) and "site_records_located_at" not in data:
                return JsonResponse(
                    data={
                        "errors": {
                            "site_records_located_at":
                            [strings.Site.NO_SITE_SELECTED]
                        }
                    },
                    status=status.HTTP_400_BAD_REQUEST,
                )

        data["organisation"] = org_pk
        serializer = SiteCreateUpdateSerializer(data=data)

        if serializer.is_valid(raise_exception=True):
            if "validate_only" not in data or data["validate_only"] == "False":
                site = serializer.save()
                audit_trail_service.create(
                    actor=request.user,
                    verb=AuditType.CREATED_SITE,
                    target=site,
                    payload={
                        "site_name": site.name,
                    },
                )
                return JsonResponse(
                    data={"site": SiteViewSerializer(site).data},
                    status=status.HTTP_201_CREATED)
            return JsonResponse(data={})
Esempio n. 18
0
    def post(self, request):
        assert_user_has_permission(self.request.user.govuser,
                                   GovPermissions.MANAGE_FLAGGING_RULES)
        json = request.data
        json["team"] = self.request.user.govuser.team.id

        serializer = FlaggingRuleSerializer(data=request.data)

        if serializer.is_valid():
            flagging_rule = serializer.save()
            apply_flagging_rule_to_all_open_cases(flagging_rule)
            return JsonResponse(data=serializer.data,
                                status=status.HTTP_201_CREATED)

        return JsonResponse(data={"errors": serializer.errors},
                            status=status.HTTP_400_BAD_REQUEST)
Esempio n. 19
0
    def perform_update(self, serializer):
        assert_user_has_permission(self.request.user.govuser, constants.GovPermissions.MAINTAIN_OGL)

        # Don't update the data during validate_only requests
        if not self.request.data.get("validate_only", False):
            fields = [
                ("name", OpenGeneralLicences.ActivityFieldDisplay.NAME),
                ("description", OpenGeneralLicences.ActivityFieldDisplay.DESCRIPTION),
                ("url", OpenGeneralLicences.ActivityFieldDisplay.URL),
                ("case_type", OpenGeneralLicences.ActivityFieldDisplay.CASE_TYPE),
                ("registration_required", OpenGeneralLicences.ActivityFieldDisplay.REGISTRATION_REQUIRED),
                ("status", OpenGeneralLicences.ActivityFieldDisplay.STATUS),
            ]
            m2m_fields = [
                ("countries", OpenGeneralLicences.ActivityFieldDisplay.COUNTRIES),
                ("control_list_entries", OpenGeneralLicences.ActivityFieldDisplay.CONTROL_LIST_ENTRIES),
            ]
            # data setup for audit checks
            original_instance = self.get_object()
            original_m2m_sets = {}
            for field, display in m2m_fields:
                original_m2m_sets[field] = set(getattr(original_instance, field).all())

            # save model
            updated_instance = serializer.save()

            for field, display in fields:
                if getattr(original_instance, field) != getattr(updated_instance, field):
                    audit_trail_service.create(
                        actor=self.request.user,
                        verb=AuditType.OGL_FIELD_EDITED,
                        action_object=updated_instance,
                        payload={
                            "key": display,
                            "old": getattr(original_instance, field),
                            "new": getattr(updated_instance, field),
                        },
                    )

            for field, display in m2m_fields:
                if original_m2m_sets[field] != set(getattr(updated_instance, field).all()):
                    audit_trail_service.create(
                        actor=self.request.user,
                        verb=AuditType.OGL_MULTI_FIELD_EDITED,
                        action_object=updated_instance,
                        payload={"key": display},
                    )
Esempio n. 20
0
 def delete(self, request, pk):
     """
     Clears team level advice and reopens the advice for user level for that team
     """
     assert_user_has_permission(
         request.user.govuser,
         constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)
     self.final_advice.delete()
     # Delete GoodCountryDecisions as final advice is no longer applicable
     GoodCountryDecision.objects.filter(case_id=pk).delete()
     audit_trail_service.create(
         actor=request.user,
         verb=AuditType.CLEARED_FINAL_ADVICE,
         target=self.case,
     )
     return JsonResponse(data={"status": "success"},
                         status=status.HTTP_200_OK)
Esempio n. 21
0
    def post(self, request):
        """ Create a role """
        assert_user_has_permission(request.user.govuser, constants.GovPermissions.ADMINISTER_ROLES)
        data = JSONParser().parse(request)
        data["type"] = UserType.INTERNAL

        if Role.objects.filter(organisation=None, name__iexact=data["name"].strip()):
            error = {"name": [ErrorDetail(string="Name is not unique.", code="invalid")]}
            return JsonResponse(data={"errors": error}, status=status.HTTP_400_BAD_REQUEST)

        serializer = RoleSerializer(data=data)

        if serializer.is_valid():
            serializer.save()
            return JsonResponse(data={"role": serializer.data}, status=status.HTTP_201_CREATED)

        return JsonResponse(data={"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
Esempio n. 22
0
    def get(self, request, pk):
        assert_user_has_permission(request.user.govuser, constants.GovPermissions.MAINTAIN_OGL)
        filter_data = audit_trail_service.get_filters(request.GET)
        content_type = ContentType.objects.get_for_model(OpenGeneralLicence)
        audit_trail_qs = audit_trail_service.filter_object_activity(
            object_id=pk, object_content_type=content_type, **filter_data
        )

        data = AuditSerializer(audit_trail_qs, many=True).data

        if isinstance(request.user, GovUser):
            # Delete notifications related to audits
            GovNotification.objects.filter(user_id=request.user.pk, object_id__in=[obj["id"] for obj in data]).delete()

        filters = audit_trail_service.get_objects_activity_filters(pk, content_type)

        return JsonResponse(data={"activity": data, "filters": filters}, status=status.HTTP_200_OK)
Esempio n. 23
0
    def post(self, request, org_pk):
        """
        Create an exporter user within the specified organisation
        """
        if hasattr(request.user, "exporteruser"):
            assert_user_has_permission(request.user.exporteruser,
                                       ExporterPermissions.ADMINISTER_USERS,
                                       org_pk)
        data = JSONParser().parse(request)
        data["organisation"] = str(org_pk)
        serializer = ExporterUserCreateUpdateSerializer(data=data)

        if serializer.is_valid():
            serializer.save()
            return JsonResponse(data={"user": serializer.data},
                                status=status.HTTP_201_CREATED)

        return JsonResponse(data={"errors": serializer.errors},
                            status=status.HTTP_400_BAD_REQUEST)
Esempio n. 24
0
    def get_queryset(self):
        assert_user_has_permission(self.request.user.govuser,
                                   GovPermissions.MANAGE_FLAGGING_RULES)
        rules = FlaggingRule.objects.all().prefetch_related("flag", "team")

        include_deactivated = self.request.query_params.get(
            "include_deactivated", "")
        if not include_deactivated:
            rules = rules.filter(status=FlagStatuses.ACTIVE)

        level = self.request.query_params.get("level", "")
        if level:
            rules = rules.filter(level=level)

        only_my_team = self.request.query_params.get("only_my_team", "")
        if only_my_team:
            rules = rules.filter(team=self.request.user.govuser.team)

        return rules
Esempio n. 25
0
    def put(self, request, pk):
        assert_user_has_permission(self.request.user.govuser,
                                   GovPermissions.MANAGE_FLAGGING_RULES)
        flagging_rule = get_flagging_rule(pk)

        if request.user.govuser.team != flagging_rule.team:
            return JsonResponse(data={"errors": strings.Flags.FORBIDDEN},
                                status=status.HTTP_403_FORBIDDEN)

        serializer = FlaggingRuleSerializer(instance=flagging_rule,
                                            data=request.data,
                                            partial=True)

        if serializer.is_valid():
            flagging_rule = serializer.save()
            apply_flagging_rule_to_all_open_cases(flagging_rule)
            return JsonResponse(data={"flagging_rule": serializer.data})

        return JsonResponse(data={"errors": serializer.errors},
                            status=status.HTTP_400_BAD_REQUEST)
Esempio n. 26
0
    def filter_queryset(self, queryset):
        filter_data = self.request.GET

        if self.request.user.type == UserType.INTERNAL:
            assert_user_has_permission(self.request.user.govuser, constants.GovPermissions.MAINTAIN_OGL)
        elif self.request.user.type == UserType.EXPORTER:
            if filter_data.get("site"):
                queryset = queryset.filter(cases__site_id=filter_data.get("site"))

            if str_to_bool(filter_data.get("active_only")):
                queryset = queryset.filter(
                    cases__status__status__in=[
                        CaseStatusEnum.FINALISED,
                        CaseStatusEnum.REGISTERED,
                        CaseStatusEnum.UNDER_ECJU_REVIEW,
                    ]
                )

            if str_to_bool(filter_data.get("registered")):
                organisation = get_request_user_organisation(self.request)
                sites = Site.objects.get_by_user_and_organisation(self.request.user.exporteruser, organisation)
                queryset = queryset.filter(cases__site__in=sites).distinct()

        if filter_data.get("name"):
            queryset = queryset.filter(name__icontains=filter_data.get("name"))

        if filter_data.get("case_type"):
            queryset = queryset.filter(case_type_id=filter_data.get("case_type"))

        if filter_data.get("control_list_entry"):
            queryset = queryset.filter(control_list_entries__rating=filter_data.get("control_list_entry"))

        if filter_data.get("country"):
            queryset = queryset.filter(countries__id__contains=filter_data.get("country"))

        if filter_data.get("status"):
            queryset = queryset.filter(status=filter_data.get("status"))

        return queryset
Esempio n. 27
0
    def post(self, request):
        """
        Add a new picklist item
        """
        assert_user_has_permission(self.request.user.govuser,
                                   GovPermissions.MANAGE_PICKLISTS)
        data = JSONParser().parse(request)
        data["team"] = request.user.govuser.team.id
        serializer = PicklistUpdateCreateSerializer(data=data, partial=True)

        if serializer.is_valid():
            serializer.save()
            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.CREATED_PICKLIST,
                target=serializer.instance,
            )
            return JsonResponse(data={"picklist_item": serializer.data},
                                status=status.HTTP_201_CREATED)

        return JsonResponse(data={"errors": serializer.errors},
                            status=status.HTTP_400_BAD_REQUEST)
Esempio n. 28
0
    def get(self, request, queue_pk):
        """
        Fetch enforcement check XML for cases on queue
        """
        assert_user_has_permission(request.user.govuser,
                                   GovPermissions.ENFORCEMENT_CHECK)
        cases = Case.objects.filter(
            queues=queue_pk,
            flags=Flag.objects.get(id=SystemFlags.ENFORCEMENT_CHECK_REQUIRED))

        if not cases:
            return HttpResponse(status=status.HTTP_204_NO_CONTENT)

        xml = export_cases_xml(cases)

        for case in cases:
            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.ENFORCEMENT_CHECK,
                target=case,
            )

        return HttpResponse(xml, content_type="text/xml")
Esempio n. 29
0
    def post(self, request, *args, **kwargs):
        assert_user_has_permission(
            request.user.govuser, constants.GovPermissions.CONFIGURE_TEMPLATES)
        data = request.data
        data["case_types"] = CaseTypeEnum.references_to_ids(
            data.get("case_types"))
        data["decisions"] = [
            AdviceType.ids[decision] for decision in data.get("decisions", [])
        ]
        serializer_class = self.get_serializer_class()
        serializer = serializer_class(data=data)

        if serializer.is_valid(raise_exception=True):
            serializer.save()

            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.CREATED_DOCUMENT_TEMPLATE,
                target=serializer.instance,
                payload={"template_name": data["name"]},
            )

            return JsonResponse(data=serializer.data,
                                status=status.HTTP_201_CREATED)
Esempio n. 30
0
    def put(self, request, org_pk, pk):
        """
        update a role
        """
        if pk in Roles.IMMUTABLE_ROLES:
            return JsonResponse(
                data={"errors": "You cannot edit the super user role"},
                status=status.HTTP_400_BAD_REQUEST)

        assert_user_has_permission(
            request.user.exporteruser,
            ExporterPermissions.EXPORTER_ADMINISTER_ROLES, org_pk)

        data = JSONParser().parse(request)
        role = get_role_by_pk(pk, org_pk)

        serializer = RoleSerializer(role, data=data, partial=True)

        if serializer.is_valid():
            serializer.save()
            return JsonResponse(data={"role": serializer.data},
                                status=status.HTTP_200_OK)
        return JsonResponse(data={"errors": serializer.errors},
                            status=status.HTTP_400_BAD_REQUEST)