Skip to content

Commit

Permalink
Chat group and message (#1025)
Browse files Browse the repository at this point in the history
* Add chat_message collection and update the chat_group collection.

* Modify chat_group.create, add a check_name_unique and add a test.

* Modify chat_group.update: Add a name unique check, add a test.

* Change restriction_mode of user/chat_message_.

* Fix models, add missing restriciton_mode.

* Fix tests.

* Fix example-data.

* Fix meeting.clone.

* Add the chat_message.create action and tests.

* Add chat_message.update action and some tests.

* Add chat_message.delete action and some tests.

* Add a cascade to chat_group/chat_message_ids.

* Add a CheckNameUniqueMixin and use it. Update a test.

* Use meeting interferring create action for chat_message.create.
  • Loading branch information
reiterl committed Nov 18, 2021
1 parent 7ff8bdb commit e1f83b6
Show file tree
Hide file tree
Showing 21 changed files with 388 additions and 9 deletions.
9 changes: 8 additions & 1 deletion global/data/example-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
],
"vote_delegated_$_to_id": [],
"vote_delegations_$_from_ids": [],
"chat_message_$_ids": [],
"meeting_ids": [
1
]
Expand Down Expand Up @@ -231,6 +232,7 @@
"vote_delegated_vote_$_ids": [],
"vote_delegated_$_to_id": [],
"vote_delegations_$_from_ids": [],
"chat_message_$_ids": [],
"meeting_ids": [
1
]
Expand Down Expand Up @@ -319,6 +321,7 @@
"vote_delegated_vote_$_ids": [],
"vote_delegated_$_to_id": [],
"vote_delegations_$_from_ids": [],
"chat_message_$_ids": [],
"meeting_ids": [
1
]
Expand Down Expand Up @@ -849,6 +852,7 @@
1,
2
],
"chat_message_ids": [],
"logo_$_id": [
"web_header"
],
Expand Down Expand Up @@ -3364,6 +3368,7 @@
2,
5
],
"chat_message_ids": [],
"meeting_id": 1
},
"2": {
Expand All @@ -3378,7 +3383,9 @@
2,
5
],
"chat_message_ids": [],
"meeting_id": 1
}
}
},
"chat_message": {}
}
5 changes: 4 additions & 1 deletion global/data/initial-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"projection_$_ids": [],
"vote_delegated_$_to_id": [],
"vote_delegations_$_from_ids": [],
"chat_message_$_ids": [],
"meeting_ids": []
}
},
Expand Down Expand Up @@ -426,6 +427,7 @@
"assignment_candidate_ids": [],
"personal_note_ids": [],
"chat_group_ids": [],
"chat_message_ids": [],
"logo_$_id": [],
"font_$_id": [],
"committee_id": 1,
Expand Down Expand Up @@ -1148,5 +1150,6 @@
"meeting_id": 1
}
},
"chat_group": {}
"chat_group": {},
"chat_message": {}
}
49 changes: 48 additions & 1 deletion global/meta/models.yml
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,14 @@ user:
type: relation-list
to: user/vote_delegated_$_to_id
restriction_mode: C
chat_message_$_ids:
type: template
replacement_collection: meeting
restriction_mode: B
fields:
type: relation-list
to: chat_message/user_id

meeting_ids:
type: number[]
description: Calculated. All ids from group_$_ids as integers.
Expand Down Expand Up @@ -1371,6 +1379,11 @@ meeting:
to: chat_group/meeting_id
on_delete: CASCADE
restriction_mode: B
chat_message_ids:
type: relation-list
to: chat_message/meeting_id
on_delete: CASCADE
restriction_mode: B

# Logos and Fonts
logo_$_id:
Expand Down Expand Up @@ -3187,7 +3200,13 @@ chat_group:
type: number
default: 10000
restriction_mode: A


chat_message_ids:
type: relation-list
to: chat_message/chat_group_id
equal_fields: meeting_id
restriction_mode: A
on_delete: CASCADE
read_group_ids:
type: relation-list
to: group/read_chat_group_ids
Expand All @@ -3203,3 +3222,31 @@ chat_group:
to: meeting/chat_group_ids
required: true
restriction_mode: A

chat_message:
id:
type: number
restriction_mode: A
content:
type: HTMLStrict
required: true
restriction_mode: A
created:
type: timestamp
required: true
restriction_mode: A
user_id:
type: relation
to: user/chat_message_$_ids
restriction_mode: A
required: true
chat_group_id:
type: relation
to: chat_group/chat_message_ids
restriction_mode: A
required: true
meeting_id:
type: relation
to: meeting/chat_message_ids
required: true
restriction_mode: A
1 change: 1 addition & 0 deletions openslides_backend/action/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def prepare_actions_map() -> None:
assignment,
assignment_candidate,
chat_group,
chat_message,
committee,
group,
list_of_speakers,
Expand Down
5 changes: 3 additions & 2 deletions openslides_backend/action/actions/chat_group/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from ...generics.create import CreateAction
from ...util.default_schema import DefaultSchema
from ...util.register import register_action
from .mixins import ChatEnabledMixin
from .mixins import ChatEnabledMixin, CheckUniqueNameMixin


@register_action("chat_group.create")
class ChatGroupCreate(ChatEnabledMixin, CreateAction):
class ChatGroupCreate(ChatEnabledMixin, CheckUniqueNameMixin, CreateAction):
"""
Action to create a chat group.
"""
Expand All @@ -25,6 +25,7 @@ class ChatGroupCreate(ChatEnabledMixin, CreateAction):

def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
instance = super().update_instance(instance)
self.check_name_unique(instance)
instance["weight"] = self.get_weight(instance["meeting_id"])
return instance

Expand Down
11 changes: 11 additions & 0 deletions openslides_backend/action/actions/chat_group/mixins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any, Dict

from ....shared.exceptions import ActionException
from ....shared.filters import FilterOperator
from ....shared.patterns import Collection, FullQualifiedId
from ...action import Action

Expand All @@ -20,3 +21,13 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
if not meeting.get("enable_chat"):
raise ActionException("Chat is not enabled.")
return instance


class CheckUniqueNameMixin(Action):
def check_name_unique(self, instance: Dict[str, Any]) -> None:
name_exists = self.datastore.exists(
self.model.collection,
FilterOperator("name", "=", instance["name"]),
)
if name_exists:
raise ActionException("The name of a chat group must be unique.")
19 changes: 16 additions & 3 deletions openslides_backend/action/actions/chat_group/update.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
from typing import Any, Dict

from ....models.models import ChatGroup
from ....permissions.permissions import Permissions
from ....shared.patterns import FullQualifiedId
from ...generics.update import UpdateAction
from ...util.default_schema import DefaultSchema
from ...util.register import register_action
from .mixins import ChatEnabledMixin
from .mixins import ChatEnabledMixin, CheckUniqueNameMixin


@register_action("chat_group.update")
class ChatGroupUpdate(ChatEnabledMixin, UpdateAction):
class ChatGroupUpdate(ChatEnabledMixin, CheckUniqueNameMixin, UpdateAction):
"""
Action to update a projector message.
Action to update a chat group.
"""

model = ChatGroup()
schema = DefaultSchema(ChatGroup()).get_update_schema(
optional_properties=["name", "read_group_ids", "write_group_ids"],
)
permission = Permissions.Chat.CAN_MANAGE

def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
instance = super().update_instance(instance)
if "name" in instance:
chat_group = self.datastore.get(
FullQualifiedId(self.model.collection, instance["id"]), ["name"]
)
if instance["name"] != chat_group.get("name"):
self.check_name_unique(instance)
return instance
1 change: 1 addition & 0 deletions openslides_backend/action/actions/chat_message/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import create, delete, update # noqa
45 changes: 45 additions & 0 deletions openslides_backend/action/actions/chat_message/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from time import time
from typing import Any, Dict

from ....models.models import ChatMessage
from ....shared.exceptions import PermissionDenied
from ....shared.patterns import Collection, FullQualifiedId
from ...mixins.create_action_with_inferred_meeting import (
CreateActionWithInferredMeeting,
)
from ...util.default_schema import DefaultSchema
from ...util.register import register_action


@register_action("chat_message.create")
class ChatMessageCreate(CreateActionWithInferredMeeting):
"""
Action to create a chat message.
"""

model = ChatMessage()
schema = DefaultSchema(ChatMessage()).get_create_schema(
required_properties=["chat_group_id", "content"],
)
relation_field_for_meeting = "chat_group_id"

def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
instance = super().update_instance(instance)
instance["user_id"] = self.user_id
instance["created"] = round(time())
return instance

def check_permissions(self, instance: Dict[str, Any]) -> None:
chat_group = self.datastore.get(
FullQualifiedId(Collection("chat_group"), instance["chat_group_id"]),
["meeting_id", "write_group_ids"],
)
write_group_set = set(chat_group.get("write_group_ids", []))
meeting_id = chat_group["meeting_id"]
user = self.datastore.get(
FullQualifiedId(Collection("user"), self.user_id),
[f"group_${meeting_id}_ids"],
)
user_group_set = set(user.get(f"group_${meeting_id}_ids", []))
if not (write_group_set & user_group_set):
raise PermissionDenied("You are not allowed to write in this chat group.")
35 changes: 35 additions & 0 deletions openslides_backend/action/actions/chat_message/delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from typing import Any, Dict

from ....models.models import ChatMessage
from ....permissions.permission_helper import has_perm
from ....permissions.permissions import Permissions
from ....shared.exceptions import PermissionDenied
from ....shared.patterns import FullQualifiedId
from ...generics.delete import DeleteAction
from ...util.default_schema import DefaultSchema
from ...util.register import register_action


@register_action("chat_message.delete")
class ChatMessageDelete(DeleteAction):
"""
Action to delet a chat message.
"""

model = ChatMessage()
schema = DefaultSchema(ChatMessage()).get_delete_schema()

def check_permissions(self, instance: Dict[str, Any]) -> None:
chat_message = self.datastore.get(
FullQualifiedId(self.model.collection, instance["id"]),
["user_id", "meeting_id"],
)
if chat_message.get("user_id") != self.user_id and not has_perm(
self.datastore,
self.user_id,
Permissions.Chat.CAN_MANAGE,
chat_message["meeting_id"],
):
raise PermissionDenied(
"You are not allowed to perform action chat_message.delete"
)
27 changes: 27 additions & 0 deletions openslides_backend/action/actions/chat_message/update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from typing import Any, Dict

from ....models.models import ChatMessage
from ....shared.exceptions import PermissionDenied
from ....shared.patterns import FullQualifiedId
from ...generics.update import UpdateAction
from ...util.default_schema import DefaultSchema
from ...util.register import register_action


@register_action("chat_message.update")
class ChatMessageUpdate(UpdateAction):
"""
Action to update a chat message.
"""

model = ChatMessage()
schema = DefaultSchema(ChatMessage()).get_update_schema(
optional_properties=["content"],
)

def check_permissions(self, instance: Dict[str, Any]) -> None:
chat_message = self.datastore.get(
FullQualifiedId(self.model.collection, instance["id"]), ["user_id"]
)
if chat_message.get("user_id") != self.user_id:
raise PermissionDenied("You must be creator of a chat message to edit it.")
1 change: 1 addition & 0 deletions openslides_backend/action/actions/meeting/export_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def get_collections_with_meeting_id() -> List[str]:
"projector_message",
"projector_countdown",
"chat_group",
"chat_message",
]
return collections

Expand Down
1 change: 1 addition & 0 deletions openslides_backend/models/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ def __init__(
"projector_message",
"projector_countdown",
"chat_group",
"chat_message",
]
if self.mode == "all":
self.allowed_collections = [
Expand Down
Loading

0 comments on commit e1f83b6

Please sign in to comment.