def test_update_editor_follows_signal(client, factory, reverse): m1, m2 = factory.create_batch(2) u1, u2, u3, u4 = UserFactory.create_batch(4) if not reverse: for user in [u1, u2, u3, u4]: user.groups.add(m1.editors_group, m2.editors_group) for user in [u3, u4]: user.groups.remove(m1.editors_group) for user in [u1, u2, u3, u4]: user.groups.remove(m2.editors_group) else: g = Group.objects.filter(name=m1.editors_group).get() g.user_set.add(u1, u2, u3, u4) g.user_set.remove(u3, u4) assert is_following(u1, m1) assert is_following(u2, m1) assert not is_following(u3, m1) assert not is_following(u4, m1) assert not is_following(u1, m2) assert not is_following(u2, m2) assert not is_following(u3, m2) assert not is_following(u4, m2) # Test clearing if reverse: u1.groups.clear() else: g = Group.objects.filter(name=m1.editors_group).get() g.user_set.clear() assert not is_following(u1, m1)
def test_permission_request_notifications_flow_for_accept_verified_users( client, factory, namespace, request_model, request_attr): base_object = factory(access_request_handling=AccessRequestHandlingOptions. ACCEPT_VERIFIED_USERS) if namespace == "participants": permission_create_url = reverse( f"{namespace}:registration-create", kwargs={"challenge_short_name": base_object.short_name}, ) assert base_object.admins_group.user_set.count() == 1 editor = base_object.admins_group.user_set.get() # challenge creation results in a notification, delete this notification Notification.objects.all().delete() else: editor = UserFactory() base_object.add_editor(editor) permission_create_url = reverse( f"{namespace}:permission-request-create", kwargs={"slug": base_object.slug}, ) assert base_object.editors_group.user_set.count() == 1 not_verified_user = UserFactory() verified_user = UserFactory() Verification.objects.create(user=verified_user, is_verified=True) # the verified users gets accepted automatically, no follows and no notifcations _ = get_view_for_user( client=client, user=verified_user, url=permission_create_url, method=client.post, ) pr = request_model.objects.get() assert pr.status == request_model.ACCEPTED assert pr.user == verified_user assert not is_following(user=verified_user, obj=pr) assert Notification.objects.count() == 0 pr.delete() # for the not verified user, a follow is created, the request is pending and # the admin gets a notification _ = get_view_for_user( client=client, user=not_verified_user, url=permission_create_url, method=client.post, ) pr = request_model.objects.get() assert pr.status == request_model.PENDING assert pr.user == not_verified_user assert is_following(user=not_verified_user, obj=pr) assert Notification.objects.count() == 1 assert Notification.objects.get().user == editor
def test_participants_follow_forum(group): u = UserFactory() c = ChallengeFactory() add_method = getattr(c, f"add_{group}") remove_method = getattr(c, f"remove_{group}") add_method(user=u) assert is_following(user=u, obj=c.forum) remove_method(user=u) assert is_following(user=u, obj=c.forum) is False # No actions should be created assert Action.objects.exists() is False
def test_follow(self): """Test bulk following""" public_foia = FOIARequestFactory() private_foia = FOIARequestFactory(embargo=True) user = UserFactory() RequestList()._follow( FOIARequest.objects.filter( pk__in=[public_foia.pk, private_foia.pk]), user, {}, ) ok_(is_following(user, public_foia)) assert_false(is_following(user, private_foia))
def star_project(request, username, project): project = Project.retrieve(username, project, request.user) if is_following(request.user, project): unfollow(request.user, project) else: follow(request.user, project, actor_only=False) return HttpResponseRedirect(project.link())
def save(self, *args, **kwargs): adding = self._state.adding super().save(*args, **kwargs) if adding: self.set_default_interfaces() self.assign_permissions() for admin in self.challenge.get_admins(): if not is_following(admin, self): follow( user=admin, obj=self, actor_only=False, send_action=False, ) if self.public != self._orig_public: on_commit( assign_evaluation_permissions.signature( kwargs={"phase_pks": [self.pk]} ).apply_async ) on_commit( assign_submission_permissions.signature( kwargs={"phase_pk": self.pk} ).apply_async ) on_commit( lambda: calculate_ranks.apply_async(kwargs={"phase_pk": self.pk}) )
def follow_user(request, username): user = get_object_or_404(User, username=username) if user != request.user: if is_following(request.user, user): unfollow(request.user, user) else: follow(request.user, user, actor_only=False) return HttpResponseRedirect(reverse("profile", args=[username]))
def test_reader_study_delete(client): rs = ReaderStudyFactory(use_display_sets=False) editor = UserFactory() reader = UserFactory() rs.add_editor(editor) rs.add_reader(reader) assert ReaderStudy.objects.count() == 1 assert is_following(user=editor, obj=rs) response = get_view_for_user( viewname="reader-studies:delete", client=client, method=client.get, reverse_kwargs={"slug": rs.slug}, follow=True, user=reader, ) assert response.status_code == 403 assert ReaderStudy.objects.count() == 1 response = get_view_for_user( viewname="reader-studies:delete", client=client, method=client.get, reverse_kwargs={"slug": rs.slug}, follow=True, user=editor, ) assert response.status_code == 200 assert "Confirm Deletion" in response.rendered_content response = get_view_for_user( viewname="reader-studies:delete", client=client, method=client.post, reverse_kwargs={"slug": rs.slug}, follow=True, user=editor, ) assert response.status_code == 200 assert ReaderStudy.objects.count() == 0 assert not is_following(user=editor, obj=rs)
def test_unfollow(self): """Test bulk unfollowing""" follow_foia = FOIARequestFactory() unfollow_foia = FOIARequestFactory() user = UserFactory() follow(user, follow_foia, actor_only=False) RequestList()._unfollow( FOIARequest.objects.filter( pk__in=[follow_foia.pk, unfollow_foia.pk]), user, {}, ) assert_false(is_following(user, follow_foia)) assert_false(is_following(user, unfollow_foia))
def create_relationship(self, user, me): """Start blocking the user if exists and is not the logged in user.""" if user.pk is me.pk: return HttpBadRequest("A user can't block itself.") me.relationships.add(user, status=RelationshipStatus.objects.blocking()) if actions.is_following(user, me): actions.unfollow(user, me)
def test_topic_subscribe_and_unsubscribe(client): user1 = UserFactory() user2 = UserFactory() f = ForumFactory(type=Forum.FORUM_POST) UserForumPermission.objects.create( permission=ForumPermission.objects.filter( codename="can_read_forum").get(), user=user1, forum=f, has_perm=True, ) t = TopicFactory(forum=f, poster=user2, type=Topic.TOPIC_POST) assert not is_following(user1, t) response = get_view_for_user( viewname="notifications:follow-create", client=client, method=client.post, data={ "user": user1.id, "content_type": ContentType.objects.get( app_label=t._meta.app_label, model=t._meta.model_name, ).id, "object_id": t.id, "actor_only": False, }, user=user1, ) assert response.status_code == 302 assert is_following(user1, t) response = get_view_for_user( viewname="notifications:follow-delete", client=client, method=client.post, reverse_kwargs={"pk": Follow.objects.filter(user=user1).first().id}, user=user1, ) assert response.status_code == 302 assert not is_following(user1, t)
def get_is_following(self, obj): user = self.context.get('user') if user and user.id != obj.user.id and not isinstance( user, AnonymousUser): return is_following(user, obj.user) return False
def test_participants_follow_forum(group): u = UserFactory() c = ChallengeFactory() add_method = getattr(c, f"add_{group}") remove_method = getattr(c, f"remove_{group}") add_method(user=u) assert is_following(user=u, obj=c.forum) remove_method(user=u) assert is_following(user=u, obj=c.forum) is False # No actions involving the forum should be created for i in Action.objects.all(): assert c.forum != i.target assert c.forum != i.action_object assert c.forum != i.actor
def test_follow_clean_up_after_forum_removal(): u = UserFactory() f1 = ForumFactory(type=Forum.FORUM_POST) f2 = ForumFactory(type=Forum.FORUM_POST) follow(u, f1, send_action=False) follow(u, f2, send_action=False) f1.delete() assert not is_following(u, f1)
def test_follow_clean_up_after_topic_removal(): u = UserFactory() f = ForumFactory(type=Forum.FORUM_POST) t1 = TopicFactory(forum=f, type=Topic.TOPIC_POST) t2 = TopicFactory(forum=f, type=Topic.TOPIC_POST) follow(u, t1, send_action=False) follow(u, t2, send_action=False) t1.delete() assert not is_following(u, t1)
def user_timeline(request, username): user = User.objects.select_related('profile').get(username=username) user_actions = [] if is_following(request.user, user) or not user.profile.private: user_actions = actor_stream(user) context = { 'user': user, 'activities': user_actions, } return render(request, 'timeline.html', context)
def add_to_agora(self, request=None, agora_name=None, agora_id=None): ''' Add the user to the specified agora. The agora is specified by its full name or id, for example agora_name="username/agoraname" or agora_id=3. ''' if agora_name: username, agoraname = agora_name.split("/") agora = get_object_or_404(Agora, name=agoraname, creator__username=username) agora.members.add(self.user) agora.save() else: agora = get_object_or_404(Agora, pk=agora_id) agora.members.add(self.user) agora.save() send_action(self.user, verb='joined', action_object=agora, request=request) if not is_following(self.user, agora): follow(self.user, agora, actor_only=False, request=request) # Mail to the user if not self.has_perms('receive_email_updates'): return translation.activate(self.user.get_profile().lang_code) context = get_base_email_context(request) context.update( dict(agora=agora, other_user=self.user, notification_text=_('You just joined %(agora)s. ' 'Congratulations!') % dict(agora=agora.get_full_name()), to=self.user)) email = EmailMultiAlternatives( subject=_('%(site)s - you are now member of %(agora)s') % dict(site=Site.objects.get_current().domain, agora=agora.get_full_name()), body=render_to_string('agora_core/emails/agora_notification.txt', context), to=[self.user.email]) email.attach_alternative( render_to_string('agora_core/emails/agora_notification.html', context), "text/html") email.send() translation.deactivate()
def test_follow_clean_up_after_post_removal(): u = UserFactory() f = ForumFactory(type=Forum.FORUM_POST) t = TopicFactory(forum=f, type=Topic.TOPIC_POST) p1 = PostFactory(topic=t, poster=u) p2 = PostFactory(topic=t, poster=u) follow(u, p1) follow(u, p2) p1.delete() assert not is_following(u, p1)
def save(self, *args, **kwargs): adding = self._state.adding if adding: self.init_viewers_group() super().save(*args, **kwargs) if adding: self.init_permissions() followers = list( self.algorithm_image.algorithm.editors_group.user_set.all() ) if self.creator: followers.append(self.creator) for follower in set(followers): if not is_following( user=follower, obj=self.algorithm_image.algorithm, flag="job-active", ) and not is_following( user=follower, obj=self.algorithm_image.algorithm, flag="job-inactive", ): follow( user=follower, obj=self.algorithm_image.algorithm, actor_only=False, send_action=False, flag="job-active", ) if adding or self._public_orig != self.public: self.update_viewer_groups_for_public() self._public_orig = self.public if self._status_orig != self.status and self.status == self.SUCCESS: self.algorithm_image.algorithm.update_average_duration()
def add_to_agora(self, request=None, agora_name=None, agora_id=None): ''' Add the user to the specified agora. The agora is specified by its full name or id, for example agora_name="username/agoraname" or agora_id=3. ''' if agora_name: username, agoraname = agora_name.split("/") agora = get_object_or_404(Agora, name=agoraname, creator__username=username) agora.members.add(self.user) agora.save() else: agora = get_object_or_404(Agora, pk=agora_id) agora.members.add(self.user) agora.save() send_action(self.user, verb='joined', action_object=agora, request=request) if not is_following(self.user, agora): follow(self.user, agora, actor_only=False, request=request) # Mail to the user if not self.has_perms('receive_email_updates'): return translation.activate(self.user.get_profile().lang_code) context = get_base_email_context(request) context.update(dict( agora=agora, other_user=self.user, notification_text=_('You just joined %(agora)s. ' 'Congratulations!') % dict(agora=agora.get_full_name()), to=self.user )) email = EmailMultiAlternatives( subject=_('%(site)s - you are now member of %(agora)s') % dict( site=Site.objects.get_current().domain, agora=agora.get_full_name() ), body=render_to_string('agora_core/emails/agora_notification.txt', context), to=[self.user.email]) email.attach_alternative( render_to_string('agora_core/emails/agora_notification.html', context), "text/html") email.send() translation.deactivate()
def handle_following(self, user, obj): if not user.is_authenticated(): return False registry.register(obj.__class__) # TODO remove this following = is_following(user, obj) if self.action == 'follow_toggle': # Toggle follow! [follow, unfollow][int(following)](user, obj) # toggle what we return following = not following return following
def test_failed_image_import_notification(): image = ["corrupt.png"] session, _ = create_raw_upload_image_session(images=image) build_images(upload_session_pk=session.pk) session.refresh_from_db() assert RawImageUploadSession.objects.count() == 1 assert is_following( user=RawImageUploadSession.objects.get().creator, obj=RawImageUploadSession.objects.get(), ) assert Notification.objects.count() == 1 assert (Notification.objects.get().user == RawImageUploadSession.objects.get().creator)
def test_reader_study_create(client, uploaded_image): # The study creator should automatically get added to the editors group creator = get_rs_creator() ws = WorkstationFactory() def try_create_rs(allow_case_navigation): return get_view_for_user( viewname="reader-studies:create", client=client, method=client.post, data={ "title": "foo bar", "logo": uploaded_image(), "workstation": ws.pk, "allow_answer_modification": True, "allow_case_navigation": allow_case_navigation, }, follow=True, user=creator, ) response = try_create_rs(False) assert "error_1_id_workstation" in response.rendered_content # The editor must have view permissions for the workstation to add it ws.add_user(user=creator) response = try_create_rs(False) assert "error_1_id_workstation" not in response.rendered_content assert ( "`allow_case_navigation` must be checked if `allow_answer_modification` is" in response.rendered_content ) response = try_create_rs(True) assert "error_1_id_workstation" not in response.rendered_content assert ( "`allow_case_navigation` must be checked if `allow_answer_modification` is" not in response.rendered_content ) assert response.status_code == 200 rs = ReaderStudy.objects.get(title="foo bar") assert rs.slug == "foo-bar" assert rs.is_editor(user=creator) assert not rs.is_reader(user=creator) assert is_following(user=creator, obj=rs)
def test_algorithm_create(client, uploaded_image): # The algorithm creator should automatically get added to the editors group creator = get_algorithm_creator() VerificationFactory(user=creator, is_verified=True) ws = WorkstationFactory() ci = ComponentInterface.objects.get(slug="generic-medical-image") def try_create_algorithm(): return get_view_for_user( viewname="algorithms:create", client=client, method=client.post, data={ "title": "foo bar", "logo": uploaded_image(), "workstation": ws.pk, "credits_per_job": 1, "image_requires_gpu": False, "image_requires_memory_gb": 4, "inputs": [ci.pk], "outputs": [ComponentInterfaceFactory().pk], "contact_email": creator.email, "display_editors": True, "access_request_handling": AccessRequestHandlingOptions.MANUAL_REVIEW, "view_content": "{}", }, follow=True, user=creator, ) response = try_create_algorithm() assert "error_1_id_workstation" in response.rendered_content # The editor must have view permissions for the workstation to add it ws.add_user(user=creator) response = try_create_algorithm() assert "error_1_id_workstation" not in response.rendered_content assert response.status_code == 200 alg = Algorithm.objects.get(title="foo bar") assert alg.slug == "foo-bar" assert alg.is_editor(user=creator) assert not alg.is_user(user=creator) assert is_following(user=creator, obj=alg)
def to_representation(self, obj): returnObj = super(AccountSerializer, self).to_representation(obj) follower_count = len(followers(obj)) print(follower_count) following_count = len(following(obj)) total_posts = len(Topic.objects.filter(author = obj.id)) new_obj = {} if self.context['request'].user.id == obj.id: new_obj["email"] = obj.email new_obj.update({ "following": following_count, "follower": 0, "total_posts": total_posts, "am_I_following": is_following(self.context['request'].user, obj)}) returnObj.update(new_obj) return returnObj
def to_representation(self, obj): returnObj = super(AccountSerializer,self).to_representation(obj) followers_count = len(followers(obj)) following_count = len(following(obj)) total_posts = len(Post.objects.filter(author=obj.id)) new_obj = {} # if isinstance(self.context['request'].user, User): if self.context['request'].user.id == obj.id: new_obj["email"] = obj.email new_obj.update({ "following": following_count, "followers": followers_count, 'total_posts': total_posts, "am_I_following": is_following(self.context['request'].user, obj) }) returnObj.update(new_obj) return returnObj
def save(self, *args, **kwargs): adding = self._state.adding super().save(*args, **kwargs) if adding: self.assign_permissions() if not is_following(self.creator, self.phase): follow( user=self.creator, obj=self.phase, actor_only=False, send_action=False, ) e = create_evaluation.signature( kwargs={"submission_pk": self.pk}, immutable=True ) on_commit(e.apply_async)
def test_follows_deleted_when_request_deleted(client): base_object = AlgorithmFactory( access_request_handling=AccessRequestHandlingOptions.MANUAL_REVIEW) editor = UserFactory() base_object.add_editor(editor) permission_create_url = reverse( "algorithms:permission-request-create", kwargs={"slug": base_object.slug}, ) user = UserFactory() _ = get_view_for_user(client=client, user=user, url=permission_create_url, method=client.post) pr = AlgorithmPermissionRequest.objects.get() assert is_following(user, pr) pr.delete() assert not Follow.objects.filter(object_id=pr.pk)
def join_action(self, request, agora, **kwargs): ''' Action that an user can execute to join an agora if it has permissions ''' agora.members.add(request.user) agora.save() action.send(request.user, verb='joined', action_object=agora, ipaddr=request.META.get('REMOTE_ADDR'), geolocation=json.dumps(geolocate_ip(request.META.get('REMOTE_ADDR')))) if not is_following(request.user, agora): follow(request.user, agora, actor_only=False, request=request) # Mail to the user user = request.user if user.get_profile().has_perms('receive_email_updates'): translation.activate(user.get_profile().lang_code) context = get_base_email_context(request) context.update(dict( agora=agora, other_user=user, notification_text=_('You just joined %(agora)s. ' 'Congratulations!') % dict(agora=agora.get_full_name()), to=user )) email = EmailMultiAlternatives( subject=_('%(site)s - you are now member of %(agora)s') % dict( site=Site.objects.get_current().domain, agora=agora.get_full_name() ), body=render_to_string('agora_core/emails/agora_notification.txt', context), to=[user.email]) email.attach_alternative( render_to_string('agora_core/emails/agora_notification.html', context), "text/html") email.send() translation.deactivate() return self.create_response(request, dict(status="success"))
def test_archive_create(client, uploaded_image): # The archive creator should automatically get added to the editors group creator = UserFactory() add_archive_perm = Permission.objects.get( codename=f"add_{Archive._meta.model_name}" ) creator.user_permissions.add(add_archive_perm) ws = WorkstationFactory() def try_create_archive(): return get_view_for_user( viewname="archives:create", client=client, method=client.post, data={ "title": "foo bar", "logo": uploaded_image(), "workstation": ws.pk, "access_request_handling": AccessRequestHandlingOptions.MANUAL_REVIEW, "view_content": "{}", }, follow=True, user=creator, ) response = try_create_archive() assert "error_1_id_workstation" in response.rendered_content # The editor must have view permissions for the workstation to add it ws.add_user(user=creator) response = try_create_archive() assert "error_1_id_workstation" not in response.rendered_content assert response.status_code == 200 archive = Archive.objects.get(title="foo bar") assert archive.slug == "foo-bar" assert archive.is_editor(user=creator) assert not archive.is_user(user=creator) assert is_following(user=creator, obj=archive)
def test_permission_request_notifications_flow_for_accept_all( client, factory, namespace, request_model, request_attr): # when access_request_handling is set to accept all, # no notifications are sent, no follows are created # and the request is automatically accepted base_object = factory( access_request_handling=AccessRequestHandlingOptions.ACCEPT_ALL) if namespace == "participants": permission_create_url = reverse( f"{namespace}:registration-create", kwargs={"challenge_short_name": base_object.short_name}, ) assert base_object.admins_group.user_set.count() == 1 editor = base_object.admins_group.user_set.get() # challenge creation results in a notification, delete this notification Notification.objects.all().delete() else: editor = UserFactory() base_object.add_editor(editor) permission_create_url = reverse( f"{namespace}:permission-request-create", kwargs={"slug": base_object.slug}, ) assert base_object.editors_group.user_set.count() == 1 user3 = UserFactory() _ = get_view_for_user( client=client, user=user3, url=permission_create_url, method=client.post, ) pr = request_model.objects.get() assert pr.status == request_model.ACCEPTED assert pr.user == user3 assert not is_following(user=user3, obj=pr) assert Notification.objects.count() == 0
def request_membership_action(self, request, agora, **kwargs): ''' Requests membership from authenticated user to an agora ''' assign('requested_membership', request.user, agora) action.send(request.user, verb='requested membership', action_object=agora, ipaddr=request.META.get('REMOTE_ADDR'), geolocation=json.dumps(geolocate_ip(request.META.get('REMOTE_ADDR')))) if not is_following(request.user, agora): follow(request.user, agora, actor_only=False, request=request) kwargs=dict( agora_id=agora.id, user_id=request.user.id, is_secure=request.is_secure(), site_id=Site.objects.get_current().id, remote_addr=request.META.get('REMOTE_ADDR') ) send_request_membership_mails.apply_async(kwargs=kwargs) return self.create_response(request, dict(status="success"))
def process_registration(instance: RegistrationRequest = None, created: bool = False, *_, **__): if created and not instance.challenge.require_participant_review: instance.status = RegistrationRequest.ACCEPTED RegistrationRequest.objects.filter(pk=instance.pk).update( status=instance.status) elif created and instance.challenge.require_participant_review: Notification.send( type=NotificationType.NotificationTypeChoices.ACCESS_REQUEST, message="requested access to", actor=instance.user, target=instance.challenge, ) if not is_following(instance.user, instance): follow( user=instance.user, obj=instance, actor_only=False, send_action=False, ) if instance.status == RegistrationRequest.ACCEPTED: instance.challenge.add_participant(instance.user) Notification.send( type=NotificationType.NotificationTypeChoices.REQUEST_UPDATE, message="was approved", target=instance, ) elif instance.status == RegistrationRequest.REJECTED: instance.challenge.remove_participant(instance.user) Notification.send( type=NotificationType.NotificationTypeChoices.REQUEST_UPDATE, message="was rejected", target=instance, )
def test_permission_request_notifications_flow_for_manual_review( client, factory, namespace, request_model, request_attr): base_object = factory( access_request_handling=AccessRequestHandlingOptions.MANUAL_REVIEW) if namespace == "participants": permission_create_url = reverse( f"{namespace}:registration-create", kwargs={"challenge_short_name": base_object.short_name}, ) assert base_object.admins_group.user_set.count() == 1 editor = base_object.admins_group.user_set.get() # challenge creation results in a notification, delete this notification Notification.objects.all().delete() else: editor = UserFactory() base_object.add_editor(editor) permission_create_url = reverse( f"{namespace}:permission-request-create", kwargs={"slug": base_object.slug}, ) assert base_object.editors_group.user_set.count() == 1 user = UserFactory() assert request_model.objects.count() == 0 # editors automatically follow the base_obj assert is_following(user=editor, obj=base_object) # Create the permission request _ = get_view_for_user(client=client, user=user, url=permission_create_url, method=client.post) pr = request_model.objects.get() assert pr.status == request_model.PENDING assert pr.user == user # check that requester follows the request object assert is_following(user=user, obj=pr) # check request results in notification for followers of base_obj assert Notification.objects.count() == 1 assert Notification.objects.get().user == editor base_obj_str = format_html('<a href="{}">{}</a>', base_object.get_absolute_url(), base_object) assert (f"{user_profile_link(user)} requested access to {base_obj_str}" in Notification.objects.get().print_notification(user=editor)) if namespace == "participants": permission_update_url = reverse( f"{namespace}:registration-update", kwargs={ "challenge_short_name": base_object.short_name, "pk": pr.pk, }, ) else: permission_update_url = reverse( f"{namespace}:permission-request-update", kwargs={ "slug": base_object.slug, "pk": pr.pk }, ) # accepting the permission request _ = get_view_for_user( client=client, user=editor, url=permission_update_url, method=client.post, data={"status": pr.ACCEPTED}, ) pr.refresh_from_db() assert pr.status == request_model.ACCEPTED # check that status update results in notification for follower of request object, # and removal of the notification for the editor assert Notification.objects.count() == 1 assert Notification.objects.all()[0].user == user assert (f"Your registration request for {base_obj_str} was accepted" in Notification.objects.all()[0].print_notification(user=user)) # reject permission request _ = get_view_for_user( client=client, user=editor, url=permission_update_url, method=client.post, data={"status": pr.REJECTED}, ) pr.refresh_from_db() assert pr.status == request_model.REJECTED assert Notification.objects.count() == 2 assert Notification.objects.all()[1].user == user assert (f"Your registration request for {base_obj_str} was rejected" in Notification.objects.all()[1].print_notification(user=user))
def activity_register(_user, _action_object): """ Registers and activity when an object is saved. Takes a diff with a previous version of edited objects, put it as message content in a timeline, uses the verbs 'created' or 'edited' for actions on actstream. """ from lxml.html.diff import htmldiff from django.db.models.loading import get_model from django.forms import ValidationError from django.forms.models import model_to_dict from django.template.loader import render_to_string from actstream import action from actstream.actions import follow, is_following from actstream.models import action_object_stream klass = _action_object.__class__.__name__.lower() if klass not in ['problem', 'criteria', 'idea', 'alternative', 'comment']: raise forms.ValidationError(_('Wrong object type')) # Last activity last = (action_object_stream(_action_object)[:1] or [None])[0] _content_old = render_to_string('diffbase_' + klass + '.html', {klass: last}) if last else '' _content = render_to_string('diffbase_' + klass + '.html', {klass: _action_object}) _emsg = _action_object.edit_message if hasattr(_action_object, 'edit_message') else '' _diff = htmldiff(_content_old, _content) # Set target problem if klass in ['comment']: if getattr(_action_object, 'problem'): _target = getattr(_action_object, 'problem') else: for attr in ['criteria', 'idea', 'alternative']: if getattr(_action_object, attr): _target = getattr(_action_object, attr) break _target = getattr(_target, 'problem') elif klass in ['criteria', 'idea', 'alternative']: _target = getattr(_action_object, 'problem') elif klass in ['problem']: _target = _action_object # Don't do anything if the problem or the action object is a draft if hasattr(_action_object, 'published') and not getattr(_action_object, 'published'): return None # Set verb _verb = 'edited' if klass == 'comment': _verb = 'commented' _notification = True elif not last: _verb = 'created' _notification = True # Add user as collaborator _target.collaborator.add(_user) _follow = _target # Action a = action.send(_user, verb=_verb, action_object=_action_object, target=_target) a[0][1].data = { 'diff': _diff, 'content': _content, 'edit_message': _emsg, 'object': model_to_dict(_action_object)} a[0][1].save() activity_count(_target) follow(_user, _follow, actor_only=False) if not is_following(_user, _follow) else None
def activity_register(_user, _action_object): """ Registers and activity when an object is saved. Takes a diff with a previous version of edited objects, put it as message content in a timeline, uses the verbs 'created' or 'edited' for actions on actstream. """ from lxml.html.diff import htmldiff from django.db.models.loading import get_model from django.forms import ValidationError from django.forms.models import model_to_dict from django.template.loader import render_to_string from actstream import action from actstream.actions import follow, is_following from actstream.models import action_object_stream klass = _action_object.__class__.__name__.lower() if klass not in ['problem', 'criteria', 'idea', 'alternative', 'comment']: raise forms.ValidationError(_('Wrong object type')) # Last activity last = (action_object_stream(_action_object)[:1] or [None])[0] _content_old = render_to_string('diffbase_' + klass + '.html', {klass: last}) if last else '' _content = render_to_string('diffbase_' + klass + '.html', {klass: _action_object}) _emsg = _action_object.edit_message if hasattr(_action_object, 'edit_message') else '' _diff = htmldiff(_content_old, _content) # Set target problem if klass in ['comment']: if getattr(_action_object, 'problem'): _target = getattr(_action_object, 'problem') else: for attr in ['criteria', 'idea', 'alternative']: if getattr(_action_object, attr): _target = getattr(_action_object, attr) break _target = getattr(_target, 'problem') elif klass in ['criteria', 'idea', 'alternative']: _target = getattr(_action_object, 'problem') elif klass in ['problem']: _target = _action_object # Don't do anything if the problem or the action object is a draft if hasattr(_action_object, 'published') and not getattr(_action_object, 'published'): return None # Set verb _verb = 'edited' if klass == 'comment': _verb = 'commented' _notification = True elif not last: _verb = 'created' _notification = True # Add user as collaborator _target.collaborator.add(_user) _follow = _target # Action a = action.send(_user, verb=_verb, action_object=_action_object, target=_target) a[0][1].data = { 'diff': _diff, 'content': _content, 'edit_message': _emsg, 'object': model_to_dict(_action_object) } a[0][1].save() activity_count(_target) follow(_user, _follow, actor_only=False) if not is_following(_user, _follow) else None
def save(self, *args, **kwargs): # invalidate older votes from the same voter to the same election old_votes = self.election.cast_votes.filter(is_direct=True, invalidated_at_date=None, voter=self.request.user) for old_vote in old_votes: old_vote.invalidated_at_date = datetime.datetime.now() old_vote.is_counted = False old_vote.save() vote = super(VoteForm, self).save(commit=False) # generate vote data = { "a": "vote", "answers": [], "election_hash": {"a": "hash/sha256/value", "value": self.election.hash}, "election_uuid": self.election.uuid } i = 0 for question in self.election.questions: data["answers"] += [self.cleaned_data['question%d' % i]] i += 1 # fill the vote vote.voter = self.request.user vote.election = self.election vote.is_counted = self.election.has_perms('vote_counts', self.request.user) vote.is_direct = True # stablish if the vote is secret if self.election.is_vote_secret and self.cleaned_data['is_vote_secret']: vote.is_public = False vote.reason = None else: vote.reason = self.cleaned_data['reason'] vote.is_public = True # assign data, create hash etc vote.data = data vote.casted_at_date = datetime.datetime.now() vote.create_hash() # create action actstream_action.send(self.request.user, verb='voted', action_object=self.election, target=self.election.agora, geolocation=json.dumps(geolocate_ip(self.request.META.get('REMOTE_ADDR')))) vote.action_id = Action.objects.filter(actor_object_id=self.request.user.id, verb='voted', action_object_object_id=self.election.id, target_object_id=self.election.agora.id).order_by('-timestamp').all()[0].id # send email vote.save() context = get_base_email_context(self.request) context.update(dict( to=self.request.user, election=self.election, election_url=self.election.get_link(), agora_url=self.election.get_link(), )) if self.request.user.has_perms('receive_email_updates'): translation.activate(self.request.user.get_profile().lang_code) email = EmailMultiAlternatives( subject=_('Vote casted for election %s') % self.election.pretty_name, body=render_to_string('agora_core/emails/vote_casted.txt', context), to=[self.request.user.email]) email.attach_alternative( render_to_string('agora_core/emails/vote_casted.html', context), "text/html") email.send() translation.deactivate() if not is_following(self.request.user, self.election): follow(self.request.user, self.election, actor_only=False, request=self.request) return vote
def send(type, **kwargs): # noqa: C901 actor = kwargs.pop("actor", None) action_object = kwargs.pop("action_object", None) target = kwargs.pop("target", None) message = kwargs.pop("message", None) description = kwargs.pop("description", None) context_class = kwargs.pop("context_class", None) if (type == NotificationType.NotificationTypeChoices.FORUM_POST or type == NotificationType.NotificationTypeChoices.FORUM_POST_REPLY or type == NotificationType.NotificationTypeChoices.ACCESS_REQUEST and target._meta.model_name != "algorithm" or type == NotificationType.NotificationTypeChoices.REQUEST_UPDATE): if actor: receivers = [ follower for follower in followers(target) if follower != actor ] else: receivers = followers(target) elif (type == NotificationType.NotificationTypeChoices.ACCESS_REQUEST and target._meta.model_name == "algorithm"): receivers = [ follower for follower in followers(target, flag="access_request") if follower != actor ] elif type == NotificationType.NotificationTypeChoices.NEW_ADMIN: receivers = [action_object] elif (type == NotificationType.NotificationTypeChoices.EVALUATION_STATUS): receivers = [ admin for admin in target.challenge.get_admins() if is_following(admin, target) ] if actor and is_following(actor, target): receivers.append(actor) elif type == NotificationType.NotificationTypeChoices.MISSING_METHOD: receivers = [ admin for admin in target.challenge.get_admins() if is_following(admin, target) ] elif type == NotificationType.NotificationTypeChoices.JOB_STATUS: receivers = [ editor for editor in target.editors_group.user_set.all() if is_following(editor, target, flag="job-active") ] if actor and is_following(actor, target, flag="job-active"): receivers.append(actor) elif (type == NotificationType.NotificationTypeChoices.IMAGE_IMPORT_STATUS): receivers = followers(action_object) for receiver in set(receivers): Notification.objects.create( user=receiver, type=type, message=message, actor=actor, action_object=action_object, target=target, description=description, context_class=context_class, )
def save(self, *args, **kwargs): # invalidate older votes from the same voter to the same election old_votes = self.agora.delegation_election.cast_votes.filter( is_direct=False, invalidated_at_date=None, voter=self.request.user) for old_vote in old_votes: old_vote.invalidated_at_date = timezone.now() old_vote.save() # Forge the delegation vote vote = CastVote() vote.data = { "a": "delegated-vote", "answers": [ { "a": "plaintext-delegate", "choices": [ { 'user_id': self.delegate.id, # id of the User in which the voter delegates 'username': self.delegate.username, 'user_name': self.delegate.first_name, # data of the User in which the voter delegates } ] } ], "election_hash": {"a": "hash/sha256/value", "value": self.agora.delegation_election.hash}, "election_uuid": self.agora.delegation_election.uuid } vote.voter = self.request.user vote.election = self.agora.delegation_election vote.is_counted = True # if the user can delegate, it means vote counts vote.is_direct = False vote.is_public = not self.agora.is_vote_secret vote.casted_at_date = timezone.now() vote.reason = self.cleaned_data['reason'] if not self.agora.is_vote_secret else '' vote.create_hash() vote.save() # Create the delegation action actstream_action.send(self.request.user, verb='delegated', action_object=vote, target=self.agora, ipaddr=self.request.META.get('REMOTE_ADDR'), geolocation=json.dumps(geolocate_ip(self.request.META.get('REMOTE_ADDR')))) vote.action_id = Action.objects.filter(actor_object_id=self.request.user.id, verb='delegated', action_object_object_id=vote.id, target_object_id=self.agora.id).order_by('-timestamp').all()[0].id # Send the email to the voter (and maybe to the delegate too!) context = get_base_email_context(self.request) context.update(dict( agora=self.agora, delegate=self.delegate, vote=vote )) # Mail to the voter if vote.voter.get_profile().has_perms('receive_email_updates'): translation.activate(self.request.user.get_profile().lang_code) context['to'] = vote.voter email = EmailMultiAlternatives( subject=_('%(site)s - You delegated your vote in %(agora)s') %\ dict( site=Site.objects.get_current().domain, agora=self.agora.get_full_name() ), body=render_to_string('agora_core/emails/user_delegated.txt', context), to=[vote.voter.email]) email.attach_alternative( render_to_string('agora_core/emails/user_delegated.html', context), "text/html") translation.deactivate() email.send() if vote.is_public and self.delegate.get_profile().has_perms('receive_email_updates'): translation.activate(self.request.user.get_profile().lang_code) context['to'] = self.delegate email = EmailMultiAlternatives( subject=_('%(site)s - You have a new delegation in %(agora)s') %\ dict( site=Site.objects.get_current().domain, agora=self.agora.get_full_name() ), body=render_to_string('agora_core/emails/new_delegation.txt', context), to=[self.delegate.email]) email.attach_alternative( render_to_string('agora_core/emails/new_delegation.html', context), "text/html") email.send() translation.deactivate() if not is_following(self.request.user, self.delegate) and vote.is_public: follow(self.request.user, self.delegate, actor_only=False, request=self.request) return vote
def follow_book(request, pk): book = get_object_or_404(Book, pk=pk) if not is_following(request.user, book): follow(request.user, book) return render(request, 'detail.html', {'book': book, 'form': ReviewForm, 'message': 'You are following this book.'}) return render(request, 'detail.html', {'book': book, 'form': ReviewForm, 'message': 'You already follow this book.'})
def unfollow_book(request, pk): book = get_object_or_404(Book, pk=pk) if is_following(request.user, book): unfollow(request.user, book) return render(request, 'detail.html', {'book': book, 'form': ReviewForm(), 'message': 'You unfollowed this book.'}) return render(request, 'detail.html', {'book': book, 'form': ReviewForm(), 'message': 'You do not follow this book yet.'})
def es_favorito(request, post): return is_following(request.user,post)