def test_open_conversation(self):
     """Test re-opening conversation works"""
     conversation_id = self.add_conversation(is_closed=True)
     with self.app.app_context():
         # msg_id is the same as thread id for a conversation of 1
         metadata = Retriever.retrieve_conversation_metadata(
             conversation_id)
         Modifier.open_conversation(metadata, self.user_internal)
         metadata = Retriever.retrieve_conversation_metadata(
             conversation_id)
         self.assertFalse(metadata.is_closed)
         self.assertIsNone(metadata.closed_by)
         self.assertIsNone(metadata.closed_by_uuid)
         self.assertIsNone(metadata.closed_at)
Exemple #2
0
 def test_get_nonexistant_conversation_returns_none(self):
     """retrieves message using id that doesn't exist"""
     random_uuid = str(uuid.uuid4())
     with self.app.app_context():
         with current_app.test_request_context():
             result = Retriever.retrieve_conversation_metadata(random_uuid)
             self.assertIsNone(result)
    def test_close_conversation(self):
        """Test close conversation works"""
        conversation_id = self.populate_database(1)
        with self.app.app_context():
            internal_user_service.use_mock_service()
            # msg_id is the same as thread id for a conversation of 1
            metadata = Retriever.retrieve_conversation_metadata(
                conversation_id)
            Modifier.close_conversation(metadata, self.user_internal)
            metadata = Retriever.retrieve_conversation_metadata(
                conversation_id)

            self.assertTrue(metadata.is_closed)
            self.assertEqual(metadata.closed_by, "Selphie Tilmitt")
            self.assertEqual(metadata.closed_by_uuid,
                             "ce12b958-2a5f-44f4-a6da-861e59070a31")
            self.assertTrue(isinstance(metadata.closed_at, datetime.datetime))
            # Test that timestamp on read message is less than 3 seconds old to prove it
            # was only just created
            delta = datetime.datetime.utcnow() - metadata.closed_at
            self.assertTrue(delta.total_seconds() < 3)
    def _validate_post_data(post_data):
        if 'msg_id' in post_data:
            raise BadRequest(description="Message can not include msg_id")

        message = MessageSchema().load(post_data)

        if post_data.get('thread_id'):
            if post_data['from_internal'] and not party.get_users_details(post_data['msg_to']):
                # If an internal person is sending a message to a respondent, we need to check that they exist.
                # If they don't exist (because they've been deleted) then we raise a NotFound exception as the
                # respondent can't be found in the system.
                raise NotFound(description="Respondent not found")

            conversation_metadata = Retriever.retrieve_conversation_metadata(post_data.get('thread_id'))
            # Ideally, we'd return a 404 if there isn't a record in the conversation table.  But until we
            # ensure there is a record in here for every thread_id in the secure_message table, we just have to
            # assume that it's fine if it's empty.
            if conversation_metadata and conversation_metadata.is_closed:
                raise BadRequest(description="Cannot reply to a closed conversation")
        return message
Exemple #5
0
    def patch(thread_id):
        """Modify conversation metadata"""
        bound_logger = logger.bind(thread_id=thread_id,
                                   user_uuid=g.user.user_uuid)
        bound_logger.info("Validating request")
        if not g.user.is_internal:
            bound_logger.info("Thread modification is forbidden")
            abort(403)
        if request.headers.get('Content-Type',
                               '').lower() != 'application/json':
            bound_logger.info(
                'Request must set accept content type "application/json" in header.'
            )
            raise BadRequest(
                description=
                'Request must set accept content type "application/json" in header.'
            )

        bound_logger.info("Retrieving metadata for thread")
        request_data = request.get_json()
        metadata = Retriever.retrieve_conversation_metadata(thread_id)
        if metadata is None:
            abort(404)
        ThreadById._validate_request(request_data, metadata)

        bound_logger.info("Attempting to modify metadata for thread")
        if request_data.get('is_closed'):
            bound_logger.info("About to close conversation")
            Modifier.close_conversation(metadata, g.user)
        else:
            bound_logger.info("About to re-open conversation")
            Modifier.open_conversation(metadata, g.user)

        bound_logger.info("Thread metadata update successful")
        bound_logger.unbind('thread_id', 'user_uuid')
        return '', 204
Exemple #6
0
    def get(thread_id):
        """Get messages by thread id"""
        logger.info("Getting messages from thread",
                    thread_id=thread_id,
                    user_uuid=g.user.user_uuid)

        conversation = Retriever.retrieve_thread(thread_id, g.user)
        conversation_metadata = Retriever.retrieve_conversation_metadata(
            thread_id)

        logger.info("Successfully retrieved messages from thread",
                    thread_id=thread_id,
                    user_uuid=g.user.user_uuid)
        messages = []
        for message in conversation.all():
            msg = message.serialize(g.user, body_summary=False)
            messages.append(msg)

        if conversation_metadata and conversation_metadata.is_closed:
            return jsonify({
                "messages":
                add_users_and_business_details(messages),
                "is_closed":
                conversation_metadata.is_closed,
                "closed_by":
                conversation_metadata.closed_by,
                "closed_by_uuid":
                conversation_metadata.closed_by_uuid,
                "closed_at":
                conversation_metadata.closed_at.isoformat()
            })

        return jsonify({
            "messages": add_users_and_business_details(messages),
            "is_closed": False
        })