def __init__(self, **kwargs): user = kwargs.pop("user") can_publish_for_groups = get_objects_for_user( user, "publish_event_for_group", klass=Group) if (event := kwargs.get("instance", None)) is not None: self.eventtype = event.type responsible_users = get_users_with_perms( event, only_with_perms_in=["change_event"], with_group_users=False) responsible_groups = get_groups_with_perms( event, only_with_perms_in=["change_event"]) visible_for = get_groups_with_perms( event, only_with_perms_in=["view_event" ]).exclude(id__in=responsible_groups) self.locked_visible_for_groups = set( visible_for.exclude(id__in=can_publish_for_groups)) kwargs["initial"] = { "visible_for": visible_for.filter(id__in=can_publish_for_groups), "responsible_users": responsible_users, "responsible_groups": responsible_groups, **kwargs.get("initial", {}), }
def test_event_copy_by_date(self, django_app, planner, event, groups, volunteer): managers, planners, volunteers = groups assign_perm("change_event", volunteer, event) # test that single user permissions are transferred response = django_app.get(reverse("core:event_copy", kwargs={"pk": event.id}), user=planner) event_count = Event.objects.all().count() form = response.form target_date = datetime.now() + timedelta(days=14) recurr = recurrence.Recurrence( dtstart=datetime.now(), rdates=[target_date], ) form["start_date"] = datetime.now().date() form["recurrence"] = str(recurr) form.submit() occurrences = recurr.between(datetime.now() - timedelta(days=1), datetime.now() + timedelta(days=365)) new_event = Event.objects.get(title=event.title, shifts__start_time__date=target_date) assert Event.objects.all().count() == event_count + 2 assert Shift.objects.filter( start_time__date__in=occurrences).count() == 2 self.assert_dates(event, occurrences, volunteers, planners) assert volunteer.has_perm("change_event", new_event) assert set(get_groups_with_perms(new_event, ["change_event"])) == set( get_groups_with_perms(event, ["change_event"]))
def test_event_to_next_day_copy(self, django_app, planner, event_to_next_day, groups): managers, planners, volunteers = groups response = django_app.get( reverse("core:event_copy", kwargs={"pk": event_to_next_day.id}), user=planner, ) event_count = Event.objects.all().count() form = response.form target_date = datetime.now() + timedelta(days=14) recurr = recurrence.Recurrence( dtstart=datetime.now(), rdates=[target_date], ) form["start_date"] = datetime.now().date() form["recurrence"] = str(recurr) form.submit() occurrences = recurr.between(datetime.now() - timedelta(days=1), datetime.now() + timedelta(days=365)) assert Event.objects.all().count() == event_count + 2 assert Shift.objects.filter( start_time__date__in=occurrences).count() == 2 for shift_date in occurrences: shift = Shift.objects.get(start_time__date=shift_date) assert shift.event.title == event_to_next_day.title assert shift.event.get_start_time() == shift.start_time assert shift.meeting_time.date() == shift.start_time.date() assert shift.end_time.date( ) == shift.start_time.date() + timedelta(days=1) assert (volunteers and planners) in get_groups_with_perms( shift.event, ["view_event"]) assert planners in get_groups_with_perms(shift.event, ["change_event"])
def form_valid(self, form): occurrences = form.cleaned_data["recurrence"].between( datetime.now() - timedelta(days=1), datetime.now() + timedelta(days=730), # allow dates up to two years in the future inc=True, dtstart=datetime.combine( DateField().to_python(self.request.POST["start_date"]), datetime.min.time()), ) for date in occurrences: event = self.get_object() start_date = event.get_start_time().date() shifts = event.shifts.all() event.pk = None event.save() assign_perm( "view_event", get_groups_with_perms(self.get_object(), ["view_event"]), event) assign_perm( "change_event", get_groups_with_perms(self.get_object(), ["change_event"]), event) assign_perm( "change_event", get_users_with_perms(self.get_object(), only_with_perms_in=["change_event"], with_group_users=False), event, ) shifts_to_create = [] for shift in shifts: shift.pk = None # shifts on following days should have the same offset from the new date offset = shift.start_time.date() - start_date # shifts ending on the next day should end on the next day to the new date end_offset = shift.end_time.date() - shift.start_time.date() current_tz = get_current_timezone() shift.end_time = make_aware( datetime.combine( date.date() + offset + end_offset, shift.end_time.astimezone(current_tz).time(), )) shift.meeting_time = make_aware( datetime.combine( date.date() + offset, shift.meeting_time.astimezone(current_tz).time())) shift.start_time = make_aware( datetime.combine( date.date() + offset, shift.start_time.astimezone(current_tz).time())) shift.event = event shifts_to_create.append(shift) Shift.objects.bulk_create(shifts_to_create) messages.success(self.request, _("Event copied successfully.")) return redirect(reverse("core:event_list"))
def assert_dates(self, event, occurrences, volunteers, planners): for shift_date in occurrences: shift = Shift.objects.get(start_time__date=shift_date) assert shift.event.title == event.title assert shift.event.get_start_time() == shift.start_time assert shift.meeting_time.date() == shift.start_time.date() assert shift.end_time.date() == shift.start_time.date() assert (volunteers and planners) in get_groups_with_perms( shift.event, ["view_event"]) assert planners in get_groups_with_perms(shift.event, ["change_event"])
def test_event_multi_shift_copy(self, django_app, planner, groups, multi_shift_event): managers, planners, volunteers = groups response = django_app.get( reverse("core:event_copy", kwargs={"pk": multi_shift_event.id}), user=planner, ) event_count = Event.objects.all().count() form = response.form recurr = recurrence.Recurrence( dtstart=datetime.now(), rrules=[ recurrence.Rule(freq=recurrence.WEEKLY, count=3, byday=datetime.now().weekday()) ], ) form["start_date"] = datetime.now().date() form["recurrence"] = str(recurr) form.submit() occurrences = recurr.between(datetime.now() - timedelta(days=1), datetime.now() + timedelta(days=365)) assert Event.objects.all().count() == event_count + 3 assert Shift.objects.filter( start_time__date__in=occurrences).count() == 3 for shift_date in occurrences: shift = Shift.objects.get(start_time__date=shift_date) assert shift.event.title == multi_shift_event.title assert shift.event.get_start_time() == shift.start_time assert shift.meeting_time.date() == shift.start_time.date() assert shift.end_time.date() in [ shift.start_time.date(), shift.start_time.date() + timedelta(days=1), ] assert (volunteers and planners) in get_groups_with_perms( shift.event, ["view_event"]) assert planners in get_groups_with_perms(shift.event, ["change_event"]) second_shift = shift.event.shifts.get(start_time__date=shift_date + timedelta(days=1)) assert second_shift.start_time.date( ) == shift.start_time.date() + timedelta(days=1)
def test_create_event(django_app, planner, superuser, service_event_type, groups): managers, planners, volunteers = groups event_form = django_app.get( reverse("core:event_create", kwargs=dict(type=service_event_type.pk)), user=planner, ).form event_form["title"] = "Seeed Concert" event_form["description"] = "when at location, call 0123456789" event_form["location"] = "BOS ARENA" event_form["mail_updates"] = True event_form["visible_for"] = [volunteers.id] event_form["responsible_groups"] = [planners.id] # event_form["responsible_users"] is prefilled with planner shift_form = event_form.submit().follow().form shift_form["date"] = date.today() shift_form["meeting_time"] = time(9, 0) shift_form["start_time"] = time(10, 0) shift_form["end_time"] = time(16, 0) event = shift_form.submit().follow().context["event"] assert event.title == "Seeed Concert" assert set(get_groups_with_perms(event, only_with_perms_in=["view_event"])) == { volunteers, planners, } assert set( get_groups_with_perms(event, only_with_perms_in=["change_event" ])) == {planners} assert set( get_users_with_perms(event, only_with_perms_in=["change_event"], with_group_users=False)) == {planner} assert set(get_users_with_perms(event, only_with_perms_in=["change_event"])) == { planner, superuser, } # superuser is in planner group
def save(self, commit=True): self.instance.type = self.eventtype event = super().save(commit=commit) # delete existing permissions # (better implement https://github.com/django-guardian/django-guardian/issues/654) for group in get_groups_with_perms( event, only_with_perms_in=["view_event", "change_event"]): remove_perm("view_event", group, event) remove_perm("change_event", group, event) for user in get_users_with_perms( event, only_with_perms_in=["view_event", "change_event"]): remove_perm("view_event", user, event) remove_perm("change_event", user, event) # assign designated permissions assign_perm( "view_event", Group.objects.filter( Q(id__in=self.cleaned_data["visible_for"]) | Q(id__in=self.cleaned_data["responsible_groups"]) | Q(id__in=(g.id for g in self.locked_visible_for_groups))), event, ) assign_perm("change_event", self.cleaned_data["responsible_groups"], event) assign_perm("change_event", self.cleaned_data["responsible_users"], event) # Assign view_event to responsible users and to non-responsible users # that already have some sort of participation for the event # (-> they saw and interacted with it) assign_perm( "view_event", UserProfile.objects.filter( Q(pk__in=self.cleaned_data["responsible_users"]) | Q(pk__in=LocalParticipation.objects.filter( shift_id__in=event.shifts.all()).values_list("user", flat=True))), event, ) return event
def new_event(event): messages = [] users = UserProfile.objects.filter(groups__in=get_groups_with_perms( event, only_with_perms_in=["view_event"]), is_active=True).distinct() responsible_users = get_users_with_perms( event, only_with_perms_in=["change_event"]).distinct() responsible_persons_mails = list( responsible_users.values_list("email", flat=True)) subject = _("New {type}: {title}").format(type=event.type, title=event.title) text_content = _("A new {type} ({title}, {location}) has been added.\n" "Further information: {description}\n" "You can view the event here: {url}").format( type=event.type, title=event.title, location=event.location, description=event.description, url=urljoin(settings.SITE_URL, event.get_absolute_url()), ) html_content = render_to_string("core/mails/new_event.html", { "event": event, "site_url": settings.SITE_URL }) for user in users: if user.preferences["notifications__new_event"]: message = EmailMultiAlternatives( to=[user.email], subject=subject, body=text_content, reply_to=responsible_persons_mails, ) message.attach_alternative(html_content, "text/html") messages.append(message) mail.get_connection().send_messages(messages)