def modify_conversations( user: User, conversation_ids: List[int], read: bool = None, deleted: bool = None, ): conversations = [] failed: List[str] = [] for conv_id in conversation_ids: pm_state = PrivateConversationState.from_attrs(conv_id=conv_id, user_id=user.id, deleted='f') if not pm_state: failed.append(str(conv_id)) else: conversations.append(pm_state) if failed: raise _403Exception( f'You cannot modify conversations that you are not a member of: {", ".join(failed)}.' ) for conv in conversations: if read: conv.read = read if deleted: conv.deleted = deleted db.session.commit() PrivateConversation.clear_cache_keys(user.id) return flask.jsonify( f'Successfully modified conversations {", ".join(str(c.conv_id) for c in conversations)}.' )
def test_delete_conversation(app, authed_client): add_permissions(app, MessagePermissions.VIEW_DELETED) response = authed_client.put('/messages/conversations/1', data=json.dumps({'deleted': True })).get_json()['response'] assert response == 'Successfully modified conversation 1.' convs = PrivateConversation.from_user(1, filter='deleted') assert len(convs) == 1 assert convs[0].id == 1 convs = PrivateConversation.from_user(1, filter='inbox') assert len(convs) == 1
def view_conversations(user: User, page: int = 1, limit: int = 50, filter: str = 'inbox'): return flask.jsonify({ 'conversations_count': PrivateConversation.count_from_user(user.id, filter=filter), 'conversations': PrivateConversation.from_user(user_id=user.id, page=page, limit=limit, filter=filter), })
def test_clear_cache_keys(client): for uid in [1, 2]: for f in ['inbox', 'sentbox', 'deleted']: cache.set( PrivateConversation.__cache_key_of_user__.format(user_id=uid, filter=f), 1, ) PrivateConversation.clear_cache_keys(1) for f in ['inbox', 'sentbox', 'deleted']: assert not cache.has( PrivateConversation.__cache_key_of_user__.format(user_id=1, filter=f)) assert cache.has( PrivateConversation.__cache_key_of_user__.format(user_id=2, filter=f))
def delete_members(id: int, user_ids: List[int]): conv = PrivateConversation.from_pk(id, _404=True, asrt=MessagePermissions.VIEW_OTHERS) not_members = [ str(uid) for uid in user_ids if uid not in {u.id for u in conv.members} ] if not_members: raise APIException( 'The following user_ids are not in the conversation: ' # type: ignore f'{", ".join(not_members)}.') states = [] og_members = [] for uid in list(set(user_ids)): st = PrivateConversationState.from_attrs(conv_id=id, user_id=uid) states.append(st) if st.original_member: og_members.append(User.from_pk(st.user_id).username) if og_members: raise APIException( 'The following original members cannot be removed from the conversation: ' f'{", ".join(og_members)}.') for st in states: st.deleted = True db.session.commit() conv.del_property_cache('members') cache.delete( PrivateConversationState.__cache_key_members__.format(conv_id=conv.id)) return flask.jsonify(conv.members)
def test_conversation_set_state(client): pm = PrivateConversation.from_pk(2) pm.set_state(2) assert pm.read is False assert pm.sticky is False pm.set_state(1) assert pm.read is True assert pm.sticky is True
def modify_conversation(user: User, id: int, read: bool = None, deleted: bool = None): pm_state = PrivateConversationState.from_attrs(conv_id=id, user_id=user.id, deleted='f') if not pm_state: raise _403Exception( 'You cannot modify a conversation that you are not a member of.') if read: pm_state.read = read if deleted: pm_state.deleted = deleted db.session.commit() PrivateConversation.clear_cache_keys(user.id) return flask.jsonify(f'Successfully modified conversation {id}.')
def view_conversation(id: int, page: int = 1, limit: int = 50): conv = PrivateConversation.from_pk(id, _404=True, asrt=MessagePermissions.VIEW_OTHERS) conv.set_state(flask.g.user.id) conv.set_messages(page, limit) if page * limit > conv.messages_count: conv.mark_read() return flask.jsonify(conv)
def test_make_message(client): pm = PrivateConversation.from_pk(1) pm.set_state(1) pm_state = PrivateConversationState.from_attrs(conv_id=1, user_id=1) assert (datetime.utcnow().replace(tzinfo=pytz.utc) - pm.last_response_time).total_seconds() > 60 * 60 assert cache.has(pm_state.cache_key) PrivateMessage.new(conv_id=1, user_id=2, contents='hi') assert not cache.has(pm_state.cache_key) pm.set_state(1) assert (datetime.utcnow().replace(tzinfo=pytz.utc) - pm.last_response_time).total_seconds() < 15
def create_conversation(topic: str, recipient_ids: List[int], message: str): if len(recipient_ids) > 1 and not flask.g.user.has_permission( MessagePermissions.MULTI_USER): raise _403Exception( 'You cannot create a conversation with multiple users.') pm = PrivateConversation.new( topic=topic, sender_id=flask.g.user.id, recipient_ids=recipient_ids, initial_message=message, ) pm.set_state(flask.g.user.id) return flask.jsonify(pm)
def test_create_new_conversation_and_messages_from_conversation(client): pm = PrivateConversation.new( topic='test1', sender_id=3, recipient_ids=[2], initial_message='testing', ) assert pm.topic == 'test1' assert pm.id == 5 pm_messages = PrivateMessage.from_conversation(5) assert len(pm_messages) == 1 assert pm_messages[0].contents == 'testing' assert pm_messages[0].user_id == 3
def test_delete_conversation_in_bulk(app, authed_client): response = authed_client.put( '/messages/conversations', data=json.dumps({ 'conversation_ids': [1, 2], 'deleted': True }), ).get_json()['response'] assert response == 'Successfully modified conversations 1, 2.' assert (PrivateConversationState.from_attrs(conv_id=1, user_id=1).deleted is True) assert (PrivateConversationState.from_attrs(conv_id=2, user_id=1).deleted is True) assert len(PrivateConversation.from_user(1)) == 0
def add_members(id: int, user_ids: List[int]): conv = PrivateConversation.from_pk(id, _404=True, asrt=MessagePermissions.VIEW_OTHERS) already_members = [ u.username for u in conv.members if u.id in set(user_ids) ] if already_members: raise APIException( 'The following members are already in the conversation: ' f'{", ".join(already_members)}.') for uid in list(set(user_ids)): PrivateConversationState.new(conv_id=id, user_id=uid) conv.del_property_cache('members') return flask.jsonify(conv.members)
def test_not_belongs_to_user(authed_client): assert not PrivateConversation.from_pk(4).belongs_to_user()
def test_set_messages_limit(client): pm = PrivateConversation.from_pk(2) pm.set_messages(page=1, limit=1) assert len(pm.messages) == 1 assert pm.messages[0].id == 55
def test_set_messages_pagination(client): pm = PrivateConversation.from_pk(2) pm.set_messages(page=2, limit=1) assert len(pm.messages) == 1
def test_serialize_basic_perms(authed_client): pm = PrivateConversation.from_pk(1) pm.set_state(1) data = NewJSONEncoder().default(pm) check_dictionary(data, {'id': 1, 'topic': 'New Private Message!'})
def test_serialize_view_fail(authed_client): pm = PrivateConversation.from_pk(4) data = NewJSONEncoder().default(pm) assert data is None
def test_conversation_from_user_deletebox_no_perm(authed_client): with pytest.raises(_403Exception): PrivateConversation.from_user(1, filter='deleted')
def test_conversation_from_user_deletebox_empty(app, authed_client): add_permissions(app, MessagePermissions.VIEW_DELETED) convs = PrivateConversation.from_user(1, filter='deleted') assert len(convs) == 0
def test_belongs_to_user(authed_client): assert PrivateConversation.from_pk(1).belongs_to_user() assert PrivateConversation.from_pk(2).belongs_to_user()
def test_serialize_view_others(app, authed_client): add_permissions(app, MessagePermissions.VIEW_OTHERS) pm = PrivateConversation.from_pk(4) pm.set_state(2) data = NewJSONEncoder().default(pm) check_dictionary(data, {'id': 4, 'topic': 'detingstings'})
def test_get_conversation_multiple_members(client): pm = PrivateConversation.from_pk(2) assert len(pm.members) == 3 assert all(m.id in {1, 2, 3} for m in pm.members) assert len(pm.messages) == 2
def test_get_conversation(client): pm = PrivateConversation.from_pk(1) assert pm.id == 1 assert pm.topic == 'New Private Message!' assert len(pm.members) == 3 assert all(m.id in {1, 2, 3} for m in pm.members)
def test_conversation_from_user_inbox(client): convs = PrivateConversation.from_user(1) assert len(convs) == 2 assert all(c.id in {1, 2} for c in convs)
def test_conversation_from_user_sentbox(client): convs = PrivateConversation.from_user(1, filter='sentbox') assert len(convs) == 3 assert all(c.id in {1, 2, 3} for c in convs)
def create_reply(conv_id: int, message: str): conv = PrivateConversation.from_pk(conv_id, _404=True) return flask.jsonify( PrivateMessage.new(conv_id=conv.id, user_id=flask.g.user.id, contents=message))
def test_conversation_set_state_nonexistent(client): pm = PrivateConversation.from_pk(1) with pytest.raises(PMStateNotFound): pm.set_state(5)