Exemple #1
0
    def validate_public_invite(self, short_code, user):
        """
        Validate a public invite not issued to a specific organisation,
        but to the general public via
        a code. Members of this invite will by default go to the awaiting approval group and
        will not have access to the case while in that group.
        Returns a tuple of the invite model and the organisation used.
        Raises an InvitationFailure if the code is not found
        """
        try:

            invite = self.get(short_code=short_code, deleted_at__isnull=True)
            organisation_user = invite.process_invitation(user=user,
                                                          accept=False)
            organisation = organisation_user.organisation
            audit_log(
                audit_type=AUDIT_TYPE_EVENT,
                user=user,
                case=self.case,
                data={
                    "invite_id": str(invite.id),
                    "accepted_by": str(user.id),
                    "organisation_id": str(organisation.id),
                },
            )
            return invite
        except Invitation.DoesNotExist:
            raise InvitationFailure(f"Invalid short code: {short_code}")
Exemple #2
0
 def save(self, **kwargs):
     if not self.instance:  # This is a new user
         new_user = User.objects.create_user(
             contact_country=self.initial_data["mobile_country_code"],
             contact_address=self.initial_data["address_snippet"],
             contact_post_code=self.initial_data["post_code"],
             contact_phone=self.initial_data["mobile"],
             **self.validated_data)
         self.instance = new_user
         organisation = Organisation.objects.create_or_update_organisation(
             user=new_user,
             assign_user=True,
             name=self.initial_data["name"],
             address=self.initial_data["address_snippet"],
             country=self.initial_data["country"],
             post_code=self.initial_data["post_code"],
             vat_number=self.initial_data["company_vat_number"],
             eori_number=self.initial_data["company_eori_number"],
             duns_number=self.initial_data["company_duns_number"],
             organisation_website=self.initial_data["company_website"],
             companies_house_id=self.initial_data["company_number"],
             contact_object=new_user.contact,
         )
         security_group_name = OrganisationUser.objects.user_organisation_security_group(
             new_user, organisation)
         new_user.groups.add(
             security_group_name)  # Add the user to same group
         audit_log(audit_type=AUDIT_TYPE_USER_CREATED, user=new_user)
         return new_user
     else:
         return super().save(**kwargs)
Exemple #3
0
def check_measure_expiry():
    """
    Check all archived cases which are not already set to Measure Expired stage,
    and determine if all their meaures are expired.
    """
    cases = Case.objects.filter(
        initiated_at__isnull=False,
        archived_at__isnull=False,
    ).exclude(stage__key="MEASURES_EXPIRED")
    for case in cases:
        latest_expiry = case.get_state_key("LATEST_MEASURE_EXPIRY")
        if latest_expiry and latest_expiry.value:
            # print( TODO - remove if not needed
            #     timezone.now().date() <= parse(latest_expiry.value).date(),
            #     timezone.now().date(),
            #     parse(latest_expiry.value).date(),
            # )
            if timezone.now().date() >= parse(latest_expiry.value).date():
                case.set_stage_by_key("MEASURES_EXPIRED")
                audit_log(
                    audit_type=AUDIT_TYPE_EVENT,
                    model=case,
                    case=case,
                    milestone=True,
                    data={"message": "Measures expired"},
                )
Exemple #4
0
 def save(self, **kwargs):
     if not self.instance.email_verified_at:
         # If they have already verified their email, we don't want to overwrite the time
         self.instance.email_verified_at = timezone.now()
         audit_log(audit_type=AUDIT_TYPE_EMAIL_VERIFIED,
                   user=self.instance.user)
     return self.instance.save()
 def execute(self):
     value = self.evaluate_rules()
     if value == "PUBLISHED":
         self.case.set_user_context(self.kwargs.get("requested_by"))
         self.case.initiated_at = timezone.now()
         self.case.save()
         self.case.set_stage_by_key("CASE_INITIATED")
         audit_log(
             audit_type=AUDIT_TYPE_EVENT,
             model=self.case,
             case=self.case,
             milestone=True,
             data={"message": "Case initiated"},
         )
 def execute(self):
     next_stage = self.evaluate_rules()
     if next_stage:
         self.case.set_user_context(self.kwargs.get("requested_by"))
         stage = self.case.set_stage_by_key(next_stage)
         if stage:
             stage_name = stage.name if stage else "N/A"
             # Add to audit
             audit_log(
                 audit_type=AUDIT_TYPE_EVENT,
                 model=self.case,
                 case=self.case,
                 milestone=True,
                 data={"message": stage_name},
             )
Exemple #7
0
    def test_custom_audit_log(self):
        audit_log(
            audit_type=AUDIT_TYPE_LOGIN,
            user=self.user,
            assisted_by=self.caseworker,
            case=self.assisted_case,
            model=self.unassisted_case,
            data={"a": "b"},
            milestone=True,
        )

        self.assertEqual(Audit.objects.count(), 1)
        audit = Audit.objects.first()
        self.assertEqual(audit.created_by, self.user)
        self.assertTrue(audit.milestone)
        self.assertIn("a", audit.data)
        self.assertEqual(audit.case_id, self.assisted_case.id)
        self.assertEqual(audit.get_model(), self.unassisted_case)
        self.assertEqual(audit.created_at, timezone.now())
Exemple #8
0
 def delete(self, request, case_id, organisation_id, *args, **kwargs):
     # Remove from case
     organisation = Organisation.objects.get(id=organisation_id)
     case = Case.objects.get(id=case_id)
     case_role, _ = OrganisationCaseRole.objects.get_or_create(
         case=case, organisation=organisation)
     case_role.delete()
     audit_log(
         audit_type=AUDIT_TYPE_EVENT,
         user=request.user,
         model=case,
         case=case,
         milestone=True,
         data={
             "message":
             f"Organisation {organisation} was removed from case {case.name}"
         },
     )
     return ResponseSuccess({"result": organisation.to_dict()})
Exemple #9
0
    def validate(self, attrs):
        email = attrs.get("email")
        password = attrs.get("password")
        request = self.context.get("request")

        if email and password:
            try:
                user = authenticate(
                    request=self.context.get("request"), email=email, password=password
                )
            except AxesLockedOutException:
                # The user has been locked out after too many incorrect attempts
                raise CustomValidationError(error_key="login_incorrect_timeout")

            if not user or user.deleted_at:
                audit_log(audit_type=AUDIT_TYPE_LOGIN_FAILED, data={"email": email})
                raise CustomValidationError(error_key="wrong_email_password_combination")

            audit_log(audit_type=AUDIT_TYPE_LOGIN, user=user)
            # ensure the origin of the request is allowed for this user group
            env_key = request.META.get("HTTP_X_ORIGIN_ENVIRONMENT")
            if not user.has_groups(groups=ENVIRONMENT_GROUPS[env_key]):
                if not env_key:
                    logger.error(f"env_key not defined while logging {user.email}")
                else:
                    logger.error(
                        f"{user.email} does not have access to {ENVIRONMENT_GROUPS[env_key]}"
                    )
                raise CustomValidationError(error_key="invalid_access")

            email_verified = user.is_tra() or user.userprofile.email_verified_at
            if not email_verified:
                self.response_dict["needs_verify"] = True
            self.response_dict["token"] = str(user.get_access_token())

        else:
            raise AuthenticationFailed(
                _("Email and password are required to log in."), code="authorization"
            )

        attrs["user"] = user
        return attrs
    def execute(self):
        from cases.models import ArchiveReason
        from cases.models import CaseWorkflowState

        next_stage = self.evaluate_rules()
        if next_stage:
            archive_reason = ArchiveReason.objects.get(key=next_stage.upper())
            self.case.set_user_context(self.kwargs.get("requested_by"))
            self.case.archive_reason = archive_reason
            self.case.archived_at = timezone.now()
            self.case.set_stage_by_key("CASE_CLOSED")
            self.case.save()
            CaseWorkflowState.objects.set_next_action(
                self.case, "", requested_by=self.kwargs.get("requested_by")
            )
            audit_log(
                audit_type=AUDIT_TYPE_EVENT,
                model=self.case,
                case=self.case,
                milestone=True,
                data={"message": "Case archived"},
            )
Exemple #11
0
    def post(request, *args, **kwargs):
        """
        Changes a user's password.

        Arguments:
            request: a Django Request object
        Returns:
            ResponseSuccess response if the password was successfully changed.
        Raises:
            InvalidRequestParams if link is invalid or password is not complex enough.
        """
        token_serializer = PasswordResetRequestSerializerV2(data=request.data)
        password_serializer = PasswordSerializer(data=request.data)
        request_id = request.data.get("request_id")

        if token_serializer.is_valid() and password_serializer.is_valid():
            if PasswordResetRequest.objects.password_reset_v2(
                    token_serializer.initial_data["token"],
                    token_serializer.initial_data["request_id"],
                    token_serializer.initial_data["password"],
            ):
                logger.info(
                    f"Password reset completed for: request {request_id}")
                user_pk = PasswordResetRequest.objects.get(
                    request_id=request_id).user.pk
                user = User.objects.get(pk=user_pk)
                audit_log(audit_type=AUDIT_TYPE_PASSWORD_RESET, user=user)
                return ResponseSuccess({"result": {
                    "reset": True
                }},
                                       http_status=status.HTTP_200_OK)
        elif not password_serializer.is_valid():
            user_pk = PasswordResetRequest.objects.get(
                request_id=request_id).user.pk
            user = User.objects.get(pk=user_pk)
            audit_log(audit_type=AUDIT_TYPE_PASSWORD_RESET_FAILED, user=user)
            raise ValidationAPIException(
                serializer_errors=password_serializer.errors)
        else:
            logger.warning(
                f"Could not reset password for request {request_id}")
            user_pk = PasswordResetRequest.objects.get(
                request_id=request_id).user.pk
            user = User.objects.get(pk=user_pk)
            audit_log(audit_type=AUDIT_TYPE_PASSWORD_RESET_FAILED, user=user)
            raise InvalidRequestParams("Invalid or expired link")
Exemple #12
0
    def post(self,
             request,
             case_id,
             organisation_id,
             role_key=None,
             *args,
             **kwargs):
        sampled = request.data.get("sampled", "true") == "true"
        organisation = Organisation.objects.get(id=organisation_id)
        case = Case.objects.get(id=case_id)
        case_role, _ = OrganisationCaseRole.objects.get_or_create(
            case=case, organisation=organisation)

        # Add/update LOA contact
        if self.post_type == "loa":
            # Create a contact to store LOA details if present
            loa_updated = False
            loa_contact = case_role.auth_contact
            auth_contact_details = (pluck(
                request.data,
                [
                    "LOA_contact_id", "name", "org_name", "email", "phone",
                    "address"
                ],
            ) or {})
            contact_id = auth_contact_details.get("LOA_contact_id")
            email = auth_contact_details.get("email")
            if not loa_contact or loa_contact.id != contact_id:
                # If we get an id, stick with that
                if contact_id:
                    try:
                        loa_contact = Contact.objects.get(id=contact_id)
                    except Exception:
                        pass
                if email:
                    # No contact so try to find one based on email
                    try:
                        loa_contact = Contact.objects.get(email__iexact=email)
                    except Exception:
                        loa_contact = Contact.objects.create(
                            created_by=request.user)
                    # Create a new org if there isn't one, or it doesn't match supplied name
                    loa_org_name = auth_contact_details.get("org_name")
                    loa_contact.organisation = organisation

                    for field, value in auth_contact_details.items():
                        if (value and hasattr(loa_contact, field)
                                and getattr(loa_contact, field) != value):
                            setattr(loa_contact, field, value)
                            loa_updated = True
                    if loa_updated:
                        loa_contact.save()
                    # write back
                case_role.auth_contact = loa_contact
                case_role.save()

            return ResponseSuccess(
                {"result": {
                    "success": case_role.to_dict()
                }})
        # Approve into case and set case role
        approve = request.data.get("approve")
        if approve:
            if approve == "accept":
                if not case_role.approved_at:
                    case_role.approved_at = timezone.now()
                    case_role.approved_by = request.user
                    case_role.save()
            elif approve == "reject":
                role_key = "rejected"
                if case_role.approved_at:
                    case_role.approved_at = None
                    case_role.approved_by = None
                    case_role.save()

        if self.verify:
            case_role.validated_by = request.user
            case_role.validated_at = timezone.now()
            case_role.save()
            return ResponseSuccess(
                {"result": {
                    "validated_at": case_role.to_dict()
                }})
        role = CaseRole.objects.get(key=role_key)
        case_role.role = role
        case_role.sampled = sampled
        case_role.save()
        audit_log(
            audit_type=AUDIT_TYPE_EVENT,
            user=request.user,
            model=case,
            case=case,
            milestone=True,
            data={
                "message":
                f"The role of {organisation} was set to {role} in case {case.name}"
            },
        )
        return ResponseSuccess({"result": {"new_role": role.to_dict()}})
Exemple #13
0
    def post(self, request, case_id, organisation_id, action, *args, **kwargs):
        values = {key: request.data.get(key) for key in request.data.keys()}
        contact_id = values.pop("contact_id")
        organisation = Organisation.objects.get(id=organisation_id)
        case = Case.objects.get(id=case_id)
        values["case_number"] = case.reference
        values["case_name"] = case.name
        values["login_url"] = public_login_url()
        values["company_name"] = titlecase(organisation.name)
        user_granted_access = None

        if action in ("approve", "change"):
            role_key = values.pop("organisation_type", None)
            role = CaseRole.objects.get(key=role_key)
            values["role"] = role.contributor_or_interested()
            if action == "change":
                previous_role = case.organisationcaserole_set.filter(
                    organisation=organisation).first()
                values[
                    "previous_role"] = previous_role.role.contributor_or_interested(
                    )
                values["new_role"] = values["role"]
            try:
                contact = Contact.objects.select_related(
                    "userprofile",
                    "organisation").get(id=contact_id,
                                        casecontact__case=case,
                                        casecontact__organisation=organisation)
            except Contact.DoesNotExist:
                contact = Contact.objects.select_related(
                    "userprofile", "organisation").get(id=contact_id)
                CaseContact.objects.get_or_create(contact=contact,
                                                  case=case,
                                                  organisation=organisation)
            caserole, created = organisation.assign_case(case, role)
            user_granted_access = caserole.created_by
            # assign the user registering access to the case
            case.assign_user(user_granted_access,
                             created_by=request.user,
                             organisation=organisation)
            message = f"Organisation {organisation.name} approved as {role.name}"
        else:
            role = CaseRole.objects.get(key="rejected")
            values["new_role"] = "rejected"
            caserole, created = organisation.assign_case(case, role)
            user_granted_access = caserole.created_by
            contact = Contact.objects.select_related(
                "userprofile", "organisation").get(id=contact_id)
            message = f"Organisation {organisation.name} was rejected"
        values["full_name"] = contact.name
        # Send the message
        if action == "approve" or values.get("previous_role") != values.get(
                "new_role"):
            organisation.notify_approval_status(action, contact, values, case,
                                                request.user)
        if action == "approve":
            audit_log(
                audit_type=AUDIT_TYPE_EVENT,
                user=request.user,
                model=case,
                case=case,
                milestone=True,
                data={
                    "action":
                    "assign_user",
                    "message":
                    f"User {user_granted_access} "
                    f"was granted access to the case for {organisation}",
                },
            )
        return ResponseSuccess({"result": values})
Exemple #14
0
     case = Case.objects.get(id=case_id)
     organisation = Organisation.objects.get(id=organisation_id)
 except Case.DoesNotExist:
     raise NotFoundApiExceptions("Case not found or access denied")
 except Organisation.DoesNotExist:
     raise NotFoundApiExceptions(
         "Organisation not found or access denied")
 sampled = request.data.get("sampled")
 org_case_role = OrganisationCaseRole.objects.get(
     case=case, organisation=organisation)
 org_case_role.sampled = sampled if sampled is not None else not org_case_role.sampled
 org_case_role.save()
 sampled_str = "sampled" if org_case_role.sampled else "non-sampled"
 audit_log(
     audit_type=AUDIT_TYPE_EVENT,
     user=request.user,
     model=organisation,
     case=case,
     milestone=True,
     data={"message": f"{organisation.name} flagged as {sampled_str}"},
 )
 return ResponseSuccess(
     {
         "result": {
             "organisation_id": organisation_id,
             "case_id": case_id,
             "sampled": org_case_role.sampled,
             "organisation": organisation.to_embedded_dict(),
         }
     },
     http_status=status.HTTP_201_CREATED,