Skip to content

Commit 33f7d68

Browse files
authored
Merge branch 'feature/relational-db' into rel-db-presenter-tests
2 parents 88fc7cd + 5d86429 commit 33f7d68

File tree

15 files changed

+1150
-1634
lines changed

15 files changed

+1150
-1634
lines changed

openslides_backend/action/actions/poll/delete.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def prefetch(self, action_data: ActionData) -> None:
3434
"option_ids",
3535
"global_option_id",
3636
"projection_ids",
37-
"meta_position",
3837
"state",
3938
],
4039
),
@@ -82,7 +81,6 @@ def prefetch(self, action_data: ActionData) -> None:
8281
"poll_id",
8382
"used_as_global_option_in_poll_id",
8483
"vote_ids",
85-
"meta_position",
8684
],
8785
),
8886
GetManyRequest(

openslides_backend/action/actions/poll/mixins.py

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,7 @@
66

77
from ....services.database.commands import GetManyRequest
88
from ....shared.exceptions import ActionException, VoteServiceException
9-
from ....shared.interfaces.write_request import WriteRequest
10-
from ....shared.patterns import (
11-
collection_from_fqid,
12-
collectionfield_and_fqid_from_fqfield,
13-
fqid_from_collection_and_id,
14-
)
9+
from ....shared.patterns import collection_from_fqid, fqid_from_collection_and_id
1510
from ...action import Action
1611
from ..option.set_auto_fields import OptionSetAutoFields
1712
from ..projector_countdown.mixins import CountdownCommand, CountdownControl
@@ -79,29 +74,6 @@ def check_permissions(self, instance: dict[str, Any]) -> None:
7974

8075

8176
class StopControl(CountdownControl, Action):
82-
def build_write_request(self) -> WriteRequest | None:
83-
"""
84-
Reduce locked fields
85-
"""
86-
self.datastore.locked_fields = {
87-
k: v
88-
for k, v in self.datastore.locked_fields.items()
89-
if collectionfield_and_fqid_from_fqfield(k)[0]
90-
not in (
91-
"meeting_user/user_id",
92-
"meeting_user/vote_delegated_to_id",
93-
"poll/pollmethod",
94-
"poll/global_option_id",
95-
"poll/meeting_id",
96-
"poll/content_object_id",
97-
"meeting/users_enable_vote_weight",
98-
"meeting/poll_couple_countdown",
99-
"meeting/poll_countdown_id",
100-
"option/meeting_id",
101-
)
102-
}
103-
return super().build_write_request()
104-
10577
def on_stop(self, instance: dict[str, Any]) -> None:
10678
poll = self.datastore.get(
10779
fqid_from_collection_and_id(self.model.collection, instance["id"]),

openslides_backend/action/actions/poll/update.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from typing import Any
22

3+
from psycopg.types.json import Jsonb
4+
35
from openslides_backend.action.mixins.extend_history_mixin import ExtendHistoryMixin
46
from openslides_backend.services.database.interface import PartialModel
57

@@ -155,6 +157,11 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]:
155157

156158
instance.pop("publish_immediately", None)
157159
self.check_anonymous_not_in_list_fields(instance, ["entitled_group_ids"])
160+
161+
if raw_entitled_users_at_stop := instance.get("entitled_users_at_stop"):
162+
if isinstance(raw_entitled_users_at_stop, list):
163+
instance["entitled_users_at_stop"] = Jsonb(raw_entitled_users_at_stop)
164+
158165
return instance
159166

160167
def check_onehundred_percent_base(self, instance: dict[str, Any]) -> None:
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
1-
import pytest
1+
from typing import Any
22

33
from tests.system.action.base import BaseActionTestCase
44

55

6-
@pytest.mark.skip(reason="During development of relational DB not necessary")
76
class BasePollTestCase(BaseActionTestCase):
87
def setUp(self) -> None:
98
super().setUp()
109
self.vote_service.clear_all()
10+
11+
def create_assignment(
12+
self, base: int, meeting_id: int, assignment_data: dict[str, Any] = {}
13+
) -> None:
14+
self.set_models(
15+
{
16+
f"assignment/{base}": {
17+
"title": "just do it",
18+
"meeting_id": meeting_id,
19+
**assignment_data,
20+
},
21+
f"list_of_speakers/{base + 100}": {
22+
"content_object_id": f"assignment/{base}",
23+
"meeting_id": meeting_id,
24+
},
25+
}
26+
)

tests/system/action/poll/poll_test_mixin.py

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,28 @@ def start_poll(self, id: int) -> None:
1010
def prepare_users_and_poll(self, user_count: int) -> list[int]:
1111
user_ids = list(range(2, user_count + 2))
1212
self.create_meeting()
13+
self.create_motion(1, 1)
1314
self.set_models(
1415
{
15-
"motion/1": {
16-
"meeting_id": 1,
17-
},
1816
"poll/1": {
1917
"content_object_id": "motion/1",
2018
"type": Poll.TYPE_NAMED,
2119
"pollmethod": "YNA",
2220
"backend": "fast",
2321
"state": Poll.STATE_STARTED,
24-
"option_ids": [1],
2522
"meeting_id": 1,
2623
"entitled_group_ids": [3],
2724
"onehundred_percent_base": "YNA",
2825
"title": "Poll 1",
2926
},
3027
"option/1": {"meeting_id": 1, "poll_id": 1},
28+
**{f"user/{i}": {**self._get_user_data(f"user{i}")} for i in user_ids},
3129
**{
32-
f"user/{i}": {
33-
**self._get_user_data(f"user{i}"),
34-
"is_present_in_meeting_ids": [1],
35-
"meeting_ids": [1],
36-
"meeting_user_ids": [i + 10],
37-
}
38-
for i in user_ids
39-
},
40-
**{
41-
f"meeting_user/{i+10}": {
42-
"meeting_id": 1,
43-
"user_id": i,
44-
"group_ids": [3],
45-
}
30+
f"meeting_user/{i+10}": {"meeting_id": 1, "user_id": i}
4631
for i in user_ids
4732
},
48-
"group/3": {
49-
"meeting_user_ids": [id_ + 10 for id_ in user_ids],
50-
"meeting_id": 1,
51-
},
52-
"meeting/1": {
53-
"user_ids": user_ids,
54-
"group_ids": [3],
55-
"name": "test",
56-
},
33+
"group/3": {"meeting_user_ids": [id_ + 10 for id_ in user_ids]},
34+
"meeting/1": {"present_user_ids": user_ids},
5735
}
5836
)
5937
self.start_poll(1)
Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
from typing import Any
2+
13
from openslides_backend.models.models import Poll
24
from openslides_backend.permissions.permissions import Permissions
5+
from openslides_backend.services.database.interface import PartialModel
36

47
from .base_poll_test import BasePollTestCase
58

@@ -8,113 +11,110 @@ class PollAnonymize(BasePollTestCase):
811
def setUp(self) -> None:
912
super().setUp()
1013
self.create_meeting()
11-
self.set_models(
12-
{
13-
"poll/1": {
14-
"option_ids": [1],
15-
"global_option_id": 2,
16-
"meeting_id": 1,
17-
"state": Poll.STATE_FINISHED,
18-
"type": Poll.TYPE_NAMED,
19-
"content_object_id": "topic/1",
20-
},
21-
"topic/1": {"meeting_id": 1},
22-
"option/1": {"vote_ids": [1], "meeting_id": 1},
23-
"option/2": {"vote_ids": [2], "meeting_id": 1},
24-
"vote/1": {
25-
"user_id": 1,
26-
"meeting_id": 1,
27-
"delegated_user_id": 1,
28-
},
29-
"vote/2": {
30-
"user_id": 1,
31-
"meeting_id": 1,
32-
"delegated_user_id": 1,
33-
},
34-
"user/1": {
35-
"meeting_user_ids": [11],
36-
"delegated_vote_ids": [1, 2],
37-
"vote_ids": [1, 2],
38-
},
39-
"meeting_user/11": {
40-
"meeting_id": 1,
41-
"user_id": 1,
42-
},
43-
}
44-
)
14+
self.create_topic(1, 1)
15+
self.set_user_groups(1, [1])
16+
self.test_data: dict[str, dict[str, Any]] = {
17+
"poll/1": {
18+
"title": "Poll 1",
19+
"global_option_id": 2,
20+
"meeting_id": 1,
21+
"state": Poll.STATE_FINISHED,
22+
"type": Poll.TYPE_NAMED,
23+
"content_object_id": "topic/1",
24+
"pollmethod": "Y",
25+
"onehundred_percent_base": Poll.ONEHUNDRED_PERCENT_BASE_Y,
26+
},
27+
"option/1": {"meeting_id": 1, "poll_id": 1},
28+
"option/2": {"meeting_id": 1, "poll_id": 1},
29+
"vote/1": {
30+
"user_id": 1,
31+
"meeting_id": 1,
32+
"delegated_user_id": 1,
33+
"user_token": "abc",
34+
"option_id": 1,
35+
},
36+
"vote/2": {
37+
"user_id": 1,
38+
"meeting_id": 1,
39+
"delegated_user_id": 1,
40+
"user_token": "edf",
41+
"option_id": 2,
42+
},
43+
}
44+
45+
def set_test_data(self, poll_data: PartialModel = {}) -> None:
46+
if poll_data:
47+
self.test_data["poll/1"].update(poll_data)
48+
self.set_models(self.test_data)
4549

4650
def assert_anonymize(self) -> None:
47-
poll = self.get_model("poll/1")
48-
assert poll.get("is_pseudoanonymized") is True
51+
self.assert_model_exists("poll/1", {"is_pseudoanonymized": True})
4952
for fqid in ("vote/1", "vote/2"):
50-
vote = self.get_model(fqid)
51-
assert vote.get("user_id") is None
52-
assert vote.get("delegated_user_id") is None
53-
self.assert_model_exists("user/1", {"vote_ids": [], "delegated_vote_ids": []})
53+
self.assert_model_exists(fqid, {"user_id": None, "delegated_user_id": None})
54+
self.assert_model_exists(
55+
"user/1", {"vote_ids": None, "delegated_vote_ids": None}
56+
)
5457

5558
def test_anonymize(self) -> None:
59+
self.set_test_data()
5660
response = self.request("poll.anonymize", {"id": 1})
5761
self.assert_status_code(response, 200)
5862
self.assert_anonymize()
5963
self.assert_history_information("topic/1", ["Voting anonymized"])
6064

6165
def test_anonymize_assignment_poll(self) -> None:
62-
self.set_models(
63-
{
64-
"assignment/1": {
65-
"meeting_id": 1,
66-
},
67-
"poll/1": {
68-
"content_object_id": "assignment/1",
69-
},
70-
}
71-
)
66+
self.create_assignment(1, 1)
67+
self.set_test_data({"content_object_id": "assignment/1"})
7268
response = self.request("poll.anonymize", {"id": 1})
7369
self.assert_status_code(response, 200)
7470
self.assert_history_information("assignment/1", ["Ballot anonymized"])
7571

7672
def test_anonymize_publish_state(self) -> None:
77-
self.update_model("poll/1", {"state": Poll.STATE_PUBLISHED})
73+
self.set_test_data({"state": Poll.STATE_PUBLISHED})
7874
response = self.request("poll.anonymize", {"id": 1})
7975
self.assert_status_code(response, 200)
8076
self.assert_anonymize()
8177

8278
def test_anonymize_wrong_state(self) -> None:
83-
self.update_model("poll/1", {"state": Poll.STATE_CREATED})
79+
self.set_test_data({"state": Poll.STATE_CREATED})
8480
response = self.request("poll.anonymize", {"id": 1})
8581
self.assert_status_code(response, 400)
8682
for vote_fqid in ("vote/1", "vote/2"):
87-
vote = self.get_model(vote_fqid)
88-
assert vote.get("user_id") == 1
89-
assert vote.get("delegated_user_id") == 1
83+
self.assert_model_exists(vote_fqid, {"user_id": 1, "delegated_user_id": 1})
84+
self.assertEqual(
85+
"Anonymizing can only be done after finishing a poll.",
86+
response.json["message"],
87+
)
9088

9189
def test_anonymize_wrong_type(self) -> None:
92-
self.update_model("poll/1", {"type": Poll.TYPE_ANALOG})
90+
self.set_test_data({"type": Poll.TYPE_ANALOG})
9391
response = self.request("poll.anonymize", {"id": 1})
9492
self.assert_status_code(response, 400)
9593
for vote_fqid in ("vote/1", "vote/2"):
96-
vote = self.get_model(vote_fqid)
97-
assert vote.get("user_id") == 1
98-
assert vote.get("delegated_user_id") == 1
94+
self.assert_model_exists(vote_fqid, {"user_id": 1, "delegated_user_id": 1})
95+
self.assertEqual(
96+
"You can only anonymize named polls.",
97+
response.json["message"],
98+
)
9999

100100
def test_anonymize_no_permissions(self) -> None:
101101
self.base_permission_test(
102-
{},
102+
self.test_data,
103103
"poll.anonymize",
104104
{"id": 1},
105105
)
106106

107107
def test_anonymize_permissions(self) -> None:
108108
self.base_permission_test(
109-
{},
109+
self.test_data,
110110
"poll.anonymize",
111111
{"id": 1},
112112
Permissions.Poll.CAN_MANAGE,
113113
)
114114

115115
def test_anonymize_permissions_locked_meeting(self) -> None:
116116
self.base_locked_out_superadmin_permission_test(
117-
{},
117+
self.test_data,
118118
"poll.anonymize",
119119
{"id": 1},
120120
)

0 commit comments

Comments
 (0)