Merge pull request #4553 from FinnStutzenstein/removeMotionLogs

Remove motion logs
This commit is contained in:
Finn Stutzenstein 2019-04-02 12:12:31 +02:00 committed by GitHub
commit 2f10fad375
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 17 additions and 160 deletions

View File

@ -0,0 +1,14 @@
# Generated by Django 2.1.7 on 2019-04-01 06:58
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [("motions", "0022_auto_20190320_0840")]
operations = [
migrations.RemoveField(model_name="motionlog", name="motion"),
migrations.RemoveField(model_name="motionlog", name="person"),
migrations.DeleteModel(name="MotionLog"),
]

View File

@ -6,7 +6,6 @@ from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ImproperlyConfigured, ValidationError from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.db import IntegrityError, models, transaction from django.db import IntegrityError, models, transaction
from django.db.models import Max from django.db.models import Max
from django.utils import formats, timezone
from jsonfield import JSONField from jsonfield import JSONField
from openslides.agenda.models import Item from openslides.agenda.models import Item
@ -81,7 +80,6 @@ class MotionManager(models.Manager):
"comments__section", "comments__section",
"comments__section__read_groups", "comments__section__read_groups",
"agenda_items", "agenda_items",
"log_messages",
"polls", "polls",
"attachments", "attachments",
"tags", "tags",
@ -540,17 +538,6 @@ class Motion(RESTModelMixin, models.Model):
""" """
return self.agenda_item.pk return self.agenda_item.pk
def write_log(self, message_list, person=None, skip_autoupdate=False):
"""
Write a log message.
The message should be in English.
"""
if person and not person.is_authenticated:
person = None
motion_log = MotionLog(motion=self, message_list=message_list, person=person)
motion_log.save(skip_autoupdate=skip_autoupdate)
def is_amendment(self): def is_amendment(self):
""" """
Returns True if the motion is an amendment. Returns True if the motion is an amendment.
@ -903,50 +890,6 @@ class MotionBlock(RESTModelMixin, models.Model):
return {"title": self.title} return {"title": self.title}
class MotionLog(RESTModelMixin, models.Model):
"""Save a logmessage for a motion."""
motion = models.ForeignKey(
Motion, on_delete=models.CASCADE, related_name="log_messages"
)
"""The motion to witch the object belongs."""
message_list = JSONField()
"""
The log message. It should be a list of strings in English.
"""
person = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=SET_NULL_AND_AUTOUPDATE, null=True
)
"""A user object, who created the log message. Optional."""
time = models.DateTimeField(auto_now=True)
"""The Time, when the loged action was performed."""
class Meta:
default_permissions = ()
ordering = ["-time"]
def __str__(self):
"""
Return a string, representing the log message.
"""
localtime = timezone.localtime(self.time)
time = formats.date_format(localtime, "DATETIME_FORMAT")
message_list = "".join(self.message_list)
time_and_messages = f"{time} {message_list}"
if self.person is not None:
return f"{time_and_messages} by {self.person}"
return time_and_messages
def get_root_rest_element(self):
"""
Returns the motion to this instance which is the root REST element.
"""
return self.motion
class MotionVote(RESTModelMixin, BaseVote): class MotionVote(RESTModelMixin, BaseVote):
"""Saves the votes for a MotionPoll. """Saves the votes for a MotionPoll.

View File

@ -25,7 +25,6 @@ from .models import (
MotionChangeRecommendation, MotionChangeRecommendation,
MotionComment, MotionComment,
MotionCommentSection, MotionCommentSection,
MotionLog,
MotionPoll, MotionPoll,
State, State,
StatuteParagraph, StatuteParagraph,
@ -171,24 +170,6 @@ class AmendmentParagraphsJSONSerializerField(Field):
return data return data
class MotionLogSerializer(ModelSerializer):
"""
Serializer for motion.models.MotionLog objects.
"""
message = SerializerMethodField()
class Meta:
model = MotionLog
fields = ("message_list", "person", "time", "message")
def get_message(self, obj):
"""
Concats the message parts to one string. Useful for smart template code.
"""
return str(obj)
class MotionPollSerializer(ModelSerializer): class MotionPollSerializer(ModelSerializer):
""" """
Serializer for motion.models.MotionPoll objects. Serializer for motion.models.MotionPoll objects.
@ -385,7 +366,6 @@ class MotionSerializer(ModelSerializer):
""" """
comments = MotionCommentSerializer(many=True, read_only=True) comments = MotionCommentSerializer(many=True, read_only=True)
log_messages = MotionLogSerializer(many=True, read_only=True)
polls = MotionPollSerializer(many=True, read_only=True) polls = MotionPollSerializer(many=True, read_only=True)
modified_final_version = CharField(allow_blank=True, required=False) modified_final_version = CharField(allow_blank=True, required=False)
reason = CharField(allow_blank=True, required=False) reason = CharField(allow_blank=True, required=False)
@ -435,7 +415,6 @@ class MotionSerializer(ModelSerializer):
"agenda_item_id", "agenda_item_id",
"agenda_type", "agenda_type",
"agenda_parent_id", "agenda_parent_id",
"log_messages",
"sort_parent", "sort_parent",
"weight", "weight",
"created", "created",

View File

@ -223,9 +223,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
for submitter in submitters: for submitter in submitters:
Submitter.objects.add(submitter, motion) Submitter.objects.add(submitter, motion)
# Write the log message and initiate response.
motion.write_log(["Motion created"], request.user)
# Send new submitters and supporters via autoupdate because users # Send new submitters and supporters via autoupdate because users
# without permission to see users may not have them but can get it now. # without permission to see users may not have them but can get it now.
# TODO: Skip history. # TODO: Skip history.
@ -298,16 +295,13 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
updated_motion = serializer.save() updated_motion = serializer.save()
# Write the log message, check removal of supporters and initiate response. # Check removal of supporters and initiate response.
# TODO: Log if a motion was updated.
updated_motion.write_log(["Motion updated"], request.user)
if ( if (
config["motions_remove_supporters"] config["motions_remove_supporters"]
and updated_motion.state.allow_support and updated_motion.state.allow_support
and not has_perm(request.user, "motions.can_manage") and not has_perm(request.user, "motions.can_manage")
): ):
updated_motion.supporters.clear() updated_motion.supporters.clear()
updated_motion.write_log(["All supporters removed"], request.user)
# Send new supporters via autoupdate because users # Send new supporters via autoupdate because users
# without permission to see users may not have them but can get it now. # without permission to see users may not have them but can get it now.
@ -390,19 +384,15 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
comment.comment = comment_value comment.comment = comment_value
comment.save() comment.save()
# write log
motion.write_log([f"Comment {section.name} updated"], request.user)
message = ["Comment {arg1} updated", section.name] message = ["Comment {arg1} updated", section.name]
else: # DELETE else: # DELETE
try: try:
comment = MotionComment.objects.get(motion=motion, section=section) comment = MotionComment.objects.get(motion=motion, section=section)
except MotionComment.DoesNotExist: except MotionComment.DoesNotExist:
# Be silent about not existing comments, but do not create a log entry. # Be silent about not existing comments.
pass pass
else: else:
comment.delete() comment.delete()
motion.write_log([f"Comment {section.name} deleted"], request.user)
message = ["Comment {arg1} deleted", section.name] message = ["Comment {arg1} deleted", section.name]
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
@ -512,7 +502,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
): ):
raise ValidationError({"detail": "You can not support this motion."}) raise ValidationError({"detail": "You can not support this motion."})
motion.supporters.add(request.user) motion.supporters.add(request.user)
motion.write_log(["Motion supported"], request.user)
# Send new supporter via autoupdate because users without permission # Send new supporter via autoupdate because users without permission
# to see users may not have it but can get it now. # to see users may not have it but can get it now.
# TODO: Skip history. # TODO: Skip history.
@ -524,7 +513,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
if not motion.state.allow_support or not motion.is_supporter(request.user): if not motion.state.allow_support or not motion.is_supporter(request.user):
raise ValidationError({"detail": "You can not unsupport this motion."}) raise ValidationError({"detail": "You can not unsupport this motion."})
motion.supporters.remove(request.user) motion.supporters.remove(request.user)
motion.write_log(["Motion unsupported"], request.user)
message = "You have unsupported this motion successfully." message = "You have unsupported this motion successfully."
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
@ -580,13 +568,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
) )
message = f"The state of the motion was set to {motion.state.name}." message = f"The state of the motion was set to {motion.state.name}."
# Write the log message and initiate response.
motion.write_log(
message_list=[f"State set to {motion.state.name}"],
person=request.user,
skip_autoupdate=True,
)
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
inform_changed_data( inform_changed_data(
motion, motion,
@ -661,13 +642,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
skip_autoupdate=True, skip_autoupdate=True,
) )
# Write the log message.
motion.write_log(
message_list=["State set to", " ", motion.state.name],
person=request.user,
skip_autoupdate=True,
)
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
inform_changed_data( inform_changed_data(
motion, motion,
@ -731,13 +705,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
) )
message = f"The recommendation of the motion was set to {label}." message = f"The recommendation of the motion was set to {label}."
# Write the log message and initiate response.
motion.write_log(
message_list=["Recommendation set to", " ", label],
person=request.user,
skip_autoupdate=True,
)
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
inform_changed_data( inform_changed_data(
motion, motion,
@ -820,13 +787,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
else "None" else "None"
) )
# Write the log message.
motion.write_log(
message_list=["Recommendation set to", " ", label],
person=request.user,
skip_autoupdate=True,
)
# Fire autoupdate and save information to OpenSlides history. # Fire autoupdate and save information to OpenSlides history.
inform_changed_data( inform_changed_data(
motion, motion,
@ -850,7 +810,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
motion.follow_recommendation() motion.follow_recommendation()
# Save and write log.
motion.save( motion.save(
update_fields=[ update_fields=[
"state", "state",
@ -861,11 +820,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
], ],
skip_autoupdate=True, skip_autoupdate=True,
) )
motion.write_log(
message_list=["State set to", " ", motion.state.name],
person=request.user,
skip_autoupdate=True,
)
# Now send all changes to the clients. # Now send all changes to the clients.
inform_changed_data( inform_changed_data(
@ -891,7 +845,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
poll = motion.create_poll(skip_autoupdate=True) poll = motion.create_poll(skip_autoupdate=True)
except WorkflowError as err: except WorkflowError as err:
raise ValidationError({"detail": err}) raise ValidationError({"detail": err})
motion.write_log(["Vote created"], request.user, skip_autoupdate=True)
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
inform_changed_data( inform_changed_data(
@ -989,7 +942,6 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
""" """
response = super().update(*args, **kwargs) response = super().update(*args, **kwargs)
poll = self.get_object() poll = self.get_object()
poll.motion.write_log(["Vote updated"], self.request.user)
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
inform_changed_data( inform_changed_data(
@ -1004,7 +956,6 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
""" """
poll = self.get_object() poll = self.get_object()
result = super().destroy(*args, **kwargs) result = super().destroy(*args, **kwargs)
poll.motion.write_log(["Vote deleted"], self.request.user)
# Fire autoupdate again to save information to OpenSlides history. # Fire autoupdate again to save information to OpenSlides history.
inform_changed_data( inform_changed_data(
@ -1362,12 +1313,6 @@ class MotionBlockViewSet(ModelViewSet):
# Follow recommendation. # Follow recommendation.
motion.follow_recommendation() motion.follow_recommendation()
motion.save(skip_autoupdate=True) motion.save(skip_autoupdate=True)
# Write the log message.
motion.write_log(
message_list=["State set to", " ", motion.state.name],
person=request.user,
skip_autoupdate=True,
)
# Fire autoupdate and save information to OpenSlides history. # Fire autoupdate and save information to OpenSlides history.
inform_changed_data( inform_changed_data(
motion, motion,

View File

@ -15,7 +15,6 @@ from openslides.motions.models import (
MotionChangeRecommendation, MotionChangeRecommendation,
MotionComment, MotionComment,
MotionCommentSection, MotionCommentSection,
MotionLog,
State, State,
StatuteParagraph, StatuteParagraph,
Submitter, Submitter,
@ -44,7 +43,6 @@ def test_motion_db_queries():
* 1 request for all motion comment sections required for the comments * 1 request for all motion comment sections required for the comments
* 1 request for all users required for the read_groups of the sections * 1 request for all users required for the read_groups of the sections
* 1 request to get the agenda item, * 1 request to get the agenda item,
* 1 request to get the motion log,
* 1 request to get the polls, * 1 request to get the polls,
* 1 request to get the attachments, * 1 request to get the attachments,
* 1 request to get the tags, * 1 request to get the tags,
@ -71,7 +69,7 @@ def test_motion_db_queries():
) )
# TODO: Create some polls etc. # TODO: Create some polls etc.
assert count_queries(Motion.get_elements) == 13 assert count_queries(Motion.get_elements) == 12
@pytest.mark.django_db(transaction=False) @pytest.mark.django_db(transaction=False)
@ -914,12 +912,6 @@ class ManageComments(TestCase):
comment = MotionComment.objects.get() comment = MotionComment.objects.get()
self.assertEqual(comment.comment, "test_comment_fk3jrnfwsdg%fj=feijf") self.assertEqual(comment.comment, "test_comment_fk3jrnfwsdg%fj=feijf")
# Check for a log entry
motion_logs = MotionLog.objects.filter(motion=self.motion)
self.assertEqual(motion_logs.count(), 1)
comment_log = motion_logs.get()
self.assertTrue(self.section_read_write.name in comment_log.message_list[0])
def test_update_comment(self): def test_update_comment(self):
comment = MotionComment( comment = MotionComment(
motion=self.motion, motion=self.motion,
@ -940,12 +932,6 @@ class ManageComments(TestCase):
comment = MotionComment.objects.get() comment = MotionComment.objects.get()
self.assertEqual(comment.comment, "test_comment_fk3jrnfwsdg%fj=feijf") self.assertEqual(comment.comment, "test_comment_fk3jrnfwsdg%fj=feijf")
# Check for a log entry
motion_logs = MotionLog.objects.filter(motion=self.motion)
self.assertEqual(motion_logs.count(), 1)
comment_log = motion_logs.get()
self.assertTrue(self.section_read_write.name in comment_log.message_list[0])
def test_delete_comment(self): def test_delete_comment(self):
comment = MotionComment( comment = MotionComment(
motion=self.motion, motion=self.motion,
@ -962,12 +948,6 @@ class ManageComments(TestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(MotionComment.objects.count(), 0) self.assertEqual(MotionComment.objects.count(), 0)
# Check for a log entry
motion_logs = MotionLog.objects.filter(motion=self.motion)
self.assertEqual(motion_logs.count(), 1)
comment_log = motion_logs.get()
self.assertTrue(self.section_read_write.name in comment_log.message_list[0])
def test_delete_not_existing_comment(self): def test_delete_not_existing_comment(self):
""" """
This should fail silently; no error, if the user wants to delete This should fail silently; no error, if the user wants to delete
@ -981,10 +961,6 @@ class ManageComments(TestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(MotionComment.objects.count(), 0) self.assertEqual(MotionComment.objects.count(), 0)
# Check that no log entry was created
motion_logs = MotionLog.objects.filter(motion=self.motion)
self.assertEqual(motion_logs.count(), 0)
def test_create_comment_no_write_permission(self): def test_create_comment_no_write_permission(self):
response = self.client.post( response = self.client.post(
reverse("motion-manage-comments", args=[self.motion.pk]), reverse("motion-manage-comments", args=[self.motion.pk]),