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
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)
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)
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"), ))
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"])
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)
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)
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, )
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()) })
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 })
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
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)
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})
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)
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)
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})
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={})
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)
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}, )
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)
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)
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)
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)
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
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)
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
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)
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")
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)
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)