コード例 #1
0
 def test_thread_returned_with_thread_id_returns_404(self):
     """retrieves thread using id that doesn't exist"""
     with self.app.app_context():
         with current_app.test_request_context():
             with self.assertRaises(NotFound):
                 Retriever.retrieve_thread('anotherThreadId',
                                           self.user_respondent)
コード例 #2
0
 def test_msg_returned_with_msg_id_returns_404(self):
     """retrieves message using id that doesn't exist"""
     message_id = "1"
     with self.app.app_context():
         with current_app.test_request_context():
             with self.assertRaises(NotFound):
                 Retriever.retrieve_message(message_id, self.user_internal)
コード例 #3
0
    def test_latest_message_from_each_thread_chosen_desc(self):
        """checks the message chosen for each thread is the latest message within that thread"""
        for _ in range(5):
            self.create_thread(no_of_messages=3)

        with self.app.app_context():
            with current_app.test_request_context():
                args = get_args(limit=MESSAGE_QUERY_LIMIT)
                response = Retriever.retrieve_thread_list(
                    self.user_internal, args)

                date = []
                thread_ids = []
                msg_ids = []
                for message in response.items:
                    serialized_msg = message.serialize(self.user_internal)
                    if 'sent_date' in serialized_msg:
                        date.append(serialized_msg['sent_date'])
                    elif 'modified_date' in serialized_msg:
                        date.append(serialized_msg['modified_date'])
                    thread_ids.append(serialized_msg['thread_id'])
                    msg_ids.append(serialized_msg['msg_id'])

                self.assertEqual(len(msg_ids), 5)

                args = get_args(page=1, limit=MESSAGE_QUERY_LIMIT)

                for x in range(0, len(thread_ids)):
                    thread = Retriever.retrieve_thread(thread_ids[x],
                                                       self.user_internal)
                    self.assertEqual(date[x],
                                     str(thread.all()[0].events[0].date_time))
                    self.assertEqual(msg_ids[x],
                                     thread.all()[0].events[0].msg_id)
コード例 #4
0
    def test_thread_count_by_survey_my_conversations_on(self):
        """checks that the returned thread count is the same for every internal user
        even if they are not part of the conversations"""
        request_args = MessageArgs(page=0,
                                   limit=100,
                                   business_id=None,
                                   cc=None,
                                   label=None,
                                   desc=None,
                                   ce=None,
                                   surveys=[self.BRES_SURVEY],
                                   is_closed=False,
                                   my_conversations=True,
                                   new_respondent_conversations=False,
                                   all_conversation_types=False,
                                   unread_conversations=False)

        for _ in range(5):
            self.create_thread(no_of_messages=2)

        with self.app.app_context():
            with current_app.test_request_context():
                thread_count_internal = Retriever.thread_count_by_survey(
                    request_args,
                    User(self.default_internal_actor, role='internal'))
                thread_count_second_internal = Retriever.thread_count_by_survey(
                    request_args,
                    User(self.second_internal_actor, role='internal'))
                self.assertEqual(thread_count_internal, 5)
                self.assertEqual(thread_count_second_internal, 0)
コード例 #5
0
    def get():
        """Get count of all conversations for a specific internal user
        Typically for a specific survey, supports filtering by case, collection exercise, business party id etc

        :returns: if all_conversation_types is set 'true' returns json representing all 4 counts
                  else returns the count for the single type combination requested.
        """
        logger.info("Getting count of threads for user",
                    user_uuid=g.user.user_uuid)
        message_args = get_options(request.args)

        if message_args.all_conversation_types:
            logger.info("Getting counts for all conversation states for user",
                        user_uuid=g.user.user_uuid)
            return jsonify(totals=Retriever.
                           thread_count_by_survey_and_conversation_states(
                               message_args, g.user))

        if message_args.unread_conversations:
            logger.info("Getting counts of unread conversations",
                        user_uuid=g.user.user_uuid)
            return jsonify(total=Retriever.unread_message_count(g.user))

        return jsonify(
            total=Retriever.thread_count_by_survey(message_args, g.user))
コード例 #6
0
 def test_all_messages_in_conversation_marked_unread(self):
     # create a thread with two messages
     conversation_id = self.create_conversation_with_respondent_as_unread(
         user=self.user_respondent, message_count=2)
     with self.app.app_context():
         conversation = Retriever.retrieve_thread(conversation_id,
                                                  self.user_respondent)
         for msg in conversation.all():
             # as there's two ways that a message is unread, first check the `read at` time isn't set
             self.assertIsNone(msg.read_at)
             # now collect all the message labels
             labels = []
             for status in msg.statuses:
                 labels.append(status.label)
             # and check the unread is present
             self.assertTrue("UNREAD" in labels)
         # now mark the first message as read and check the whole conversation is now read
         Modifier.mark_message_as_read(
             conversation[0].serialize(self.user_respondent),
             self.user_respondent)
         con = Retriever.retrieve_thread(conversation_id,
                                         self.user_respondent)
         for msg in con.all():
             # message `read at` should now be set
             self.assertIsNotNone(msg.read_at)
             # collect the labels again
             labels = []
             for status in msg.statuses:
                 labels.append(status.label)
             # and there should be no unread
             self.assertFalse("UNREAD" in labels)
コード例 #7
0
 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)
コード例 #8
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)
コード例 #9
0
 def test_db_connection_test_fails(self):
     """runs check_db_connection function after dropping database"""
     with self.app.app_context():
         database.db.drop_all()
         with current_app.test_request_context():
             response = Retriever.check_db_connection()
             self.assertEqual(response.status_code, 500)
コード例 #10
0
    def test_all_msg_returned_for_thread_id(self):
        """retrieves messages for thread_id from database"""
        thread_id = self.create_thread(no_of_messages=6)

        with self.app.app_context():
            with current_app.test_request_context():
                response = Retriever.retrieve_thread(thread_id,
                                                     self.user_respondent)
                self.assertEqual(len(response.all()), 6)
コード例 #11
0
 def test_msg_returned_with_msg_id_true(self):
     """retrieves message using id"""
     self.create_thread(no_of_messages=2)
     with self.engine.connect() as con:
         query = con.execute(
             'SELECT msg_id FROM securemessage.secure_message LIMIT 1')
         msg_id = query.first()[0]
         with self.app.app_context():
             with current_app.test_request_context():
                 response = Retriever.retrieve_message(
                     msg_id, self.user_internal)
                 self.assertEqual(response['msg_id'], msg_id)
コード例 #12
0
    def test_read_date_is_set(self):
        """testing message read_date is set when unread label is removed"""
        thread_id = self.populate_database(1, mark_as_read=False)
        with self.app.app_context():
            thread = Retriever.retrieve_thread(thread_id,
                                               self.user_respondent).all()
            serialised_message = Retriever.retrieve_message(
                thread[0].msg_id, self.user_internal)
            Modifier.mark_message_as_read(serialised_message,
                                          self.user_internal)
            serialised_message = Retriever.retrieve_message(
                thread[0].msg_id, self.user_internal)
            db_message = SecureMessage.query.filter(
                SecureMessage.msg_id == serialised_message['msg_id']).one()

            self.assertIsNotNone(serialised_message['read_date'])
            self.assertTrue(isinstance(db_message.read_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() - db_message.read_at
            self.assertTrue(delta.total_seconds() < 3)
コード例 #13
0
    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)
コード例 #14
0
 def test_read_date_is_not_reset(self):
     """testing message read_date is not reset when unread label is removed again"""
     self.populate_database(1)
     with self.engine.connect() as con:
         query = con.execute(
             'SELECT msg_id FROM securemessage.secure_message LIMIT 1')
         msg_id = query.first()[0]
     with self.app.app_context():
         with current_app.test_request_context():
             message = Retriever.retrieve_message(msg_id,
                                                  self.user_internal)
             Modifier.mark_message_as_read(message, self.user_internal)
             message = Retriever.retrieve_message(msg_id,
                                                  self.user_internal)
             read_date_set = message['read_date']
             Modifier.add_unread(message, self.user_internal)
             message = Retriever.retrieve_message(msg_id,
                                                  self.user_internal)
             Modifier.mark_message_as_read(message, self.user_internal)
             message = Retriever.retrieve_message(msg_id,
                                                  self.user_internal)
             self.assertEqual(message['read_date'], read_date_set)
コード例 #15
0
 def test_correct_labels_returned_external(self):
     """retrieves message using id and checks the labels are correct"""
     self.create_thread()
     with self.engine.connect() as con:
         query = con.execute(
             'SELECT msg_id FROM securemessage.secure_message LIMIT 1')
         msg_id = query.first()[0]
         with self.app.app_context():
             with current_app.test_request_context():
                 response = Retriever.retrieve_message(
                     msg_id, self.user_respondent)
                 labels = ['SENT']
                 self.assertCountEqual(response['labels'], labels)
コード例 #16
0
 def test_sent_date_returned_for_message(self):
     """retrieves message using id and checks the sent date returned"""
     self.create_thread()
     with self.engine.connect() as con:
         query = con.execute(
             'SELECT msg_id FROM securemessage.secure_message LIMIT 1')
         msg_id = query.first()[0]
         with self.app.app_context():
             with current_app.test_request_context():
                 response = Retriever.retrieve_message(
                     msg_id, self.user_internal)
                 self.assertTrue('modified_date' not in response)
                 self.assertTrue(response['sent_date'] != "N/A")
コード例 #17
0
    def test_respondent_can_only_see_their_messages(self):
        """tests that a respondent can only see their messages i.e. they should not
        see any messages sent to another respondent"""
        first_respondent_thread_id = self.create_thread(
            no_of_messages=1,
            external_actor=self.default_external_actor,
            internal_actor=self.default_internal_actor)
        second_respondent_thread_id = self.create_thread(
            no_of_messages=1,
            external_actor=self.second_external_actor,
            internal_actor=self.default_internal_actor)

        with self.app.app_context():
            with current_app.test_request_context():
                args = get_args()
                first_respondent_thread_list = Retriever.retrieve_thread_list(
                    self.user_respondent, args)
                self.assertEqual(first_respondent_thread_list.total, 1)
                second_respondent_thread_list = Retriever.retrieve_thread_list(
                    self.second_user_respondent, args)
                self.assertEqual(second_respondent_thread_list.total, 1)
                internal_thread_list = Retriever.retrieve_thread_list(
                    self.user_internal, args)
                self.assertEqual(internal_thread_list.total, 2)

                # first respondent can retrieve the message they sent
                first_respondent_thread = Retriever.retrieve_thread(
                    first_respondent_thread_id, self.user_respondent)
                self.assertIsNotNone(first_respondent_thread)

                # second respondent can retrieve the message they sent
                second_respondent_thread = Retriever.retrieve_thread(
                    second_respondent_thread_id, self.second_user_respondent)
                self.assertIsNotNone(second_respondent_thread)

                # first respondent shouldn't be able to retrieve second respondent's message
                with self.assertRaises(Forbidden):
                    Retriever.retrieve_thread(first_respondent_thread_id,
                                              self.second_user_respondent)

                # second respondent shouldn't be able to retrieve first respondent's message
                with self.assertRaises(Forbidden):
                    Retriever.retrieve_thread(second_respondent_thread_id,
                                              self.user_respondent)
コード例 #18
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
        })
コード例 #19
0
 def test_correct_to_and_from_returned_internal_user(self):
     """retrieves message using id and checks the to and from urns are correct"""
     self.create_thread(internal_actor=self.user_internal.user_uuid)
     with self.engine.connect() as con:
         query = con.execute(
             'SELECT msg_id FROM securemessage.secure_message LIMIT 1')
         msg_id = query.first()[0]
         with self.app.app_context():
             with current_app.test_request_context():
                 response = Retriever.retrieve_message(
                     msg_id, self.user_respondent)
                 self.assertEqual(response['msg_to'][0],
                                  self.user_internal.user_uuid)
                 self.assertEqual(response['msg_from'],
                                  self.user_respondent.user_uuid)
コード例 #20
0
 def test_read_date_returned_for_message(self):
     """retrieves message using id and checks the read date returned"""
     self.create_thread(no_of_messages=2)
     with self.engine.connect() as con:
         query_sql = "SELECT securemessage.secure_message.msg_id FROM securemessage.secure_message " \
                     "JOIN securemessage.events ON securemessage.secure_message.msg_id = securemessage.events.msg_id " \
                     "WHERE securemessage.events.event = '" + EventsApi.READ.value + "' LIMIT 1"
         query = con.execute(query_sql)
         msg_id = query.first()[0]
         with self.app.app_context():
             with current_app.test_request_context():
                 response = Retriever.retrieve_message(
                     msg_id, self.user_internal)
                 self.assertTrue('modified_date' not in response)
                 self.assertTrue(response['read_date'] != "N/A")
コード例 #21
0
    def test_thread_returned_in_desc_order(self):
        """check thread returned in correct order"""
        thread_id = self.create_thread(no_of_messages=6)

        with self.app.app_context():
            with current_app.test_request_context():
                response = Retriever.retrieve_thread(thread_id,
                                                     self.user_respondent)
                self.assertEqual(len(response.all()), 6)

                sent = [
                    str(message.events[0].date_time)
                    for message in response.all()
                ]

                desc_date = sorted(sent, reverse=True)
                self.assertEqual(len(sent), 6)
                self.assertListEqual(desc_date, sent)
コード例 #22
0
    def get():
        """Get thread list"""
        logger.info("Getting list of threads for user",
                    user_uuid=g.user.user_uuid)
        message_args = get_options(request.args)

        ThreadList._validate_request(message_args, g.user)

        result = Retriever.retrieve_thread_list(g.user, message_args)

        logger.info("Successfully retrieved threads for user",
                    user_uuid=g.user.user_uuid)
        messages, links = process_paginated_list(result, request.host_url,
                                                 g.user, message_args,
                                                 THREAD_LIST_ENDPOINT)
        if messages:
            messages = add_users_and_business_details(messages)
        return jsonify({"messages": messages, "_links": links})
コード例 #23
0
 def test_two_unread_labels_are_added_to_message(self):
     """testing duplicate message labels are not added to the database"""
     self.populate_database(1)
     with self.engine.connect() as con:
         query = con.execute(
             'SELECT msg_id FROM securemessage.secure_message LIMIT 1')
         msg_id = query.first()[0]
     with self.app.app_context():
         with current_app.test_request_context():
             message = Retriever.retrieve_message(msg_id,
                                                  self.user_internal)
             Modifier.add_unread(message, self.user_internal)
             Modifier.add_unread(message, self.user_internal)
     with self.engine.connect() as con:
         query = f"SELECT count(label) FROM securemessage.status WHERE msg_id = '{msg_id}' AND label = 'UNREAD'"
         query_x = con.execute(query)
         unread_label_total = []
         for row in query_x:
             unread_label_total.append(row[0])
         self.assertTrue(unread_label_total[0] == 1)
コード例 #24
0
    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
コード例 #25
0
    def put(message_id):
        """Update message by status"""

        request_data = request.get_json()
        action, label = MessageModifyById._validate_request(request_data)
        message = Retriever.retrieve_message(message_id, g.user)

        if label == Labels.UNREAD.value:
            resp = MessageModifyById._try_modify_unread(action, message, g.user)
        else:
            resp = MessageModifyById._modify_label(action, message, g.user, label)

        if resp:
            res = jsonify({'status': 'ok'})
            res.status_code = 200

        else:
            res = jsonify({'status': 'error'})
            res.status_code = 400
            logger.error('Error updating message', msg_id=message_id, status_code=res.status_code)
        return res
コード例 #26
0
    def test_thread_list_returned_in_descending_order_respondent(self):
        """retrieves threads from database in desc sent_date order for respondent"""
        for _ in range(5):
            self.create_thread(no_of_messages=2)

        with self.app.app_context():
            with current_app.test_request_context():
                args = get_args(limit=MESSAGE_QUERY_LIMIT)
                response = Retriever.retrieve_thread_list(
                    self.user_respondent, args)

                date = []
                for message in response.items:
                    serialized_msg = message.serialize(self.user_respondent)
                    if 'sent_date' in serialized_msg:
                        date.append(serialized_msg['sent_date'])
                    elif 'modified_date' in serialized_msg:
                        date.append(serialized_msg['modified_date'])

                desc_date = sorted(date, reverse=True)
                self.assertEqual(len(date), 5)
                self.assertListEqual(desc_date, date)
コード例 #27
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
コード例 #28
0
 def get():
     return Retriever.check_db_connection()