Example #1
0
    def get(
        self,
        request,
        case_id=None,
        contact_id=None,
        submission_id=None,
        invitation_id=None,
        organisation_id=None,
        *args,
        **kwargs,
    ):
        if invitation_id:
            invitation = Invitation.objects.get_user_invite(
                invitation_id, requested_by=request.user
            )
            return ResponseSuccess({"result": invitation.to_dict()})

        invitations = Invitation.objects.filter(deleted_at__isnull=True, organisation__isnull=False)
        if contact_id:
            try:
                contact = Contact.objects.select_related("userprofile", "organisation").get(
                    id=contact_id
                )
            except Contact.DoesNotExist:
                raise NotFoundApiExceptions("Invalid contact id.")
            invitations = invitations.filter(contact=contact)
        if case_id:
            try:
                case = Case.objects.get(id=case_id)
            except Case.DoesNotExist:
                raise InvalidRequestParams("Invalid case id")
Example #2
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 = PasswordResetRequestSerializer(data=request.data)
        password_serializer = PasswordSerializer(data=request.data)
        user_pk = request.data.get("user_pk")

        if token_serializer.is_valid() and password_serializer.is_valid():
            if PasswordResetRequest.objects.password_reset(
                    token_serializer.initial_data["token"],
                    token_serializer.initial_data["user_pk"],
                    token_serializer.initial_data["password"],
            ):
                logger.info(f"Password reset completed for: {user_pk}")
                return ResponseSuccess({"result": {
                    "reset": True
                }},
                                       http_status=status.HTTP_200_OK)
        elif not password_serializer.is_valid():
            raise ValidationAPIException(
                serializer_errors=password_serializer.errors)
        else:
            logger.warning(f"Could not reset password for user {user_pk}")
            raise InvalidRequestParams("Invalid or expired link")
Example #3
0
 def post(
     self, request, contact_id, case_id, case_role_id=None, submission_id=None, *args, **kwargs
 ):
     notify_template_key = None
     try:
         contact = Contact.objects.select_related("userprofile", "organisation").get(
             id=contact_id
         )
         case_role = get_role(case_role_id)
         case = Case.objects.get(id=case_id)
         notify_template_key = case.type.meta.get("invite_notify_template_key")
     except Contact.DoesNotExist:
         raise NotFoundApiExceptions("Invalid contact id.")
     except CaseRole.DoesNotExist:
         raise NotFoundApiExceptions("Invalid case role id")
     except Case.DoesNotExist:
         raise InvalidRequestParams("Invalid case id")
     if not contact.organisation and contact.has_user:
         contact.organisation = contact.user.organisation.organisation
     # check if an invite exists already
     created = False
     invitation_kwargs = {}
     if submission_id:
         invitation_kwargs["submission__id"] = submission_id
     organisation_id = request.data.get("organisation_id")
     if organisation_id:
         organisation = Organisation.objects.get(id=organisation_id)
     else:
         organisation = contact.organisation
     try:
         invitation = Invitation.objects.get(
             contact=contact,
             case=case,
             organisation=organisation,
             deleted_at__isnull=True,
             **invitation_kwargs,
         )
     except Invitation.DoesNotExist:
         invitation = Invitation.objects.create(
             created_by=request.user,
             contact=contact,
             case=case,
             case_role=case_role,
             organisation=organisation,
             short_code=crypto.get_random_string(8),
             code=str(uuid.uuid4()),
             email=contact.email,
         )
         created = True
     values = {key: request.data.get(key) for key in request.data.keys()}
     invitation.send(
         sent_by=request.user, context=values, direct=True, template_key=notify_template_key
     )
     return ResponseSuccess(
         {
             "result": invitation.to_dict(),
             "created": created,
         },
         http_status=status.HTTP_201_CREATED,
     )
Example #4
0
    def post(request, code: str = None):
        """
        A multipurpose endpoint (for the moment), if code is provided it will verify the code is correct and note the
        email verification in the database.

        If code is not provided, it will send out a verification email to the request.user

        Arguments:
            request: a Django Request object
            code: an email verification code
        Returns:
            ResponseSuccess response if the email was validated / a new link was sent out.
        Raises:
            InvalidRequestParams if the link was incorrect.
        """
        if code:
            user = request.user
            try:
                profile = user.userprofile
            except UserProfile.DoesNotExist:
                profile = UserProfile.objects.filter(
                    email_verify_code=code).first()
                user = profile.user

            serializer = VerifyEmailSerializer(data={"code": code},
                                               context={"profile": profile})
            if serializer.is_valid():
                profile.email_verified_at = timezone.now()
                profile.save()
                user.refresh_from_db()
                return ResponseSuccess({"result": user.to_dict()})
            else:
                raise InvalidRequestParams(serializer.errors)
        elif not request.user.is_anonymous:
            response = request.user.userprofile.verify_email()
            return ResponseSuccess({"result": response})
        else:
            raise InvalidRequestParams("User unknown")
Example #5
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")
Example #6
0
    def get(self, request, document_id, submission_id=None, *args, **kwargs):
        document = Document.objects.get(id=document_id)
        is_tra = request.user.is_tra()

        if (not is_tra and not submission_id
                and not request.user.email == settings.TRUSTED_USER_EMAIL):
            raise InvalidRequestParams("Invalid request params")
        if submission_id:
            submission = Submission.objects.get_submission(id=submission_id)
            doc_submission = SubmissionDocument.objects.get(
                submission=submission, document=document)
            if not is_tra and not doc_submission.downloadable_by(request.user):
                raise NotFoundApiExceptions(
                    "Document not found or access is denied")
            doc_submission.downloads += 1
            doc_submission.save()
        return stream_s3_file_download(document.s3_bucket,
                                       document.s3_key,
                                       filename=document.name)
Example #7
0
    def get(
        self,
        request,
        note_id=None,
        model_id=None,
        content_type=None,
        case_id=None,
        model_key=None,
        *args,
        **kwargs,
    ):
        if note_id:
            try:
                note = Note.objects.get(id=note_id)
                return ResponseSuccess({"result": note.to_dict()})
            except Note.DoesNotExist:
                raise NotFoundApiExceptions("Invalid note id")
        else:
            notes = Note.objects.filter(deleted_at__isnull=True)
        if case_id:
            notes = notes.filter(case__id=case_id)
        if model_id and content_type:
            _content_type = get_content_type(content_type)
            if model_key:
                notes = notes.filter(model_id=model_id,
                                     content_type=_content_type,
                                     model_key=model_key)
            else:
                notes = notes.filter(model_id=model_id,
                                     content_type=_content_type)

        else:
            raise InvalidRequestParams(
                "A note id, case id or a model identifiers are required")
        notes = notes.order_by("created_at")
        return ResponseSuccess(
            {"results": [_note.to_dict() for _note in notes]})
Example #8
0
    def post(
        self,
        request,
        document_id=None,
        case_id=None,
        organisation_id=None,
        submission_id=None,
        bundle_id=None,
        *args,
        **kwargs,
    ):
        if document_id is None:
            document_id = request.data.get("document_id", None)
        _files = request.FILES.getlist("file", None)
        _issued = request.data.get("issued") or False
        _case_document = request.data.get("case_document")
        _parent_id = request.data.get("parent_id") or False
        _replace_id = request.data.get("replace_id") or False
        _bundle_id = bundle_id or request.data.get("bundle_id")
        _system = request.data.get("system") or bool(_bundle_id)
        _confidential = request.data.get("confidential")
        _submission_document_type = request.data.get(
            "submission_document_type")
        if _submission_document_type:
            submission_document_type = SubmissionDocumentType.objects.get(
                key=_submission_document_type)
        else:
            submission_document_type = SubmissionDocumentType.type_by_user(
                request.user)
        if _confidential is None:
            _confidential = True
        submission_type_id = request.data.get("submission_type_id")
        if (not _case_document and not _bundle_id and not submission_id
                and not submission_type_id and not _system
                and not document_id):
            raise InvalidRequestParams("Submission id or type id are required")
        if not _files and not document_id and not request.data.get(
                "file_name"):
            raise InvalidRequestParams("No file or documents provided")
        case = get_case(case_id)
        submission = None
        if submission_id:
            submission = Submission.objects.get_submission(id=submission_id,
                                                           case=case)
        elif submission_type_id:
            submission_type = SubmissionType.objects.get(id=submission_type_id)
            submission = Submission.objects.create(
                name=submission_type.name,
                case=case,
                organisation=self.organisation,
                type=submission_type,
                status=submission_type.default_status,
                created_by=request.user,
                user_context=[request.user],
            )
        if not _files and request.data.get("file_name"):
            _files = [{
                "name": request.data.get("file_name"),
                "size": request.data.get("file_size"),
                "document_name": request.data.get("document_name"),
            }]
        if _files:
            result = []
            for _file in _files:
                _parent = None
                if _parent_id:
                    try:
                        _parent = Document.objects.get(id=_parent_id)
                    except Document.DoesNotExist:
                        raise NotFoundApiExceptions(
                            "Parent document is not found")
                try:
                    document = Document.objects.create_document(
                        file=_file,
                        user=request.user,
                        confidential=_confidential,
                        system=bool(_system),
                        parent=_parent,
                        document=Document.objects.get(
                            id=document_id) if document_id else None,
                        case=case,
                    )
                except InvalidFile as e:
                    raise InvalidFileUpload(str(e))
                if _replace_id and submission:
                    # We are being asked to replace the given doc in this submission
                    try:
                        # Find the document to replace and get its child
                        _replace_doc = Document.objects.get(id=_replace_id)
                        _child_doc = Document.objects.filter(
                            parent_id=_replace_id).first()
                        replace_submission_document = SubmissionDocument.objects.get(
                            submission=submission, document=_replace_doc)
                        replace_submission_document.set_user_context(
                            request.user)
                        if _child_doc:
                            child_submission_document = SubmissionDocument.objects.get(
                                submission=submission, document=_child_doc)
                            child_submission_document.set_user_context(
                                request.user)
                            # Clone the child doc and add link to parent
                            _child_doc.id = None
                            _child_doc.parent = document
                            _child_doc.save()
                            # Update submission_doc to point to new child doc.
                            child_submission_document.document = _child_doc
                            child_submission_document.save()
                        replace_submission_document.delete()
                    except (Document.DoesNotExist,
                            SubmissionDocument.DoesNotExist) as e:
                        logger.warning(
                            f"Document to replace with id '{_replace_id}' was not found: {e}"
                        )
                if submission:
                    if _submission_document_type:
                        submission_document_type = SubmissionDocumentType.objects.get(
                            key=_submission_document_type)
                    else:
                        submission_document_type = SubmissionDocumentType.type_by_user(
                            request.user)
                    submission_document = submission.add_document(
                        document=document,
                        document_type=submission_document_type,
                        issued=_issued,
                        issued_by=request.user,
                    )
                    result_item = submission_document.to_dict()
                elif _bundle_id:
                    bundle = DocumentBundle.objects.get(id=_bundle_id)
                    bundle.documents.add(document)
                    document.generic_audit(
                        message=f"Attached to bundle {bundle.name}",
                        audit_type=AUDIT_TYPE_ATTACH,
                        id=str(document.id),
                    )
                    result_item = document.to_dict()
                else:
                    result_item = document.to_dict()
                result.append(result_item)
            return ResponseSuccess({"result": result},
                                   http_status=status.HTTP_201_CREATED)
        elif document_id:
            # We just want to attach a document
            document = Document.objects.get(id=document_id)
            if submission_id:
                submission_document = submission.add_document(
                    document=document,
                    document_type=submission_document_type,
                    issued=_issued,
                    issued_by=request.user,
                )
                if not request.user.is_tra():
                    submission.received_at = timezone.now()
                    submission.status = submission.type.received_status
                submission.save()

                return ResponseSuccess(
                    {"result": submission_document.to_dict()},
                    http_status=status.HTTP_201_CREATED)
            document.confidential = _confidential
            document.save()
            return ResponseSuccess(
                {"result": {
                    "document": document.to_dict()
                }})