From ae24fa17d5464b573a957382787c0c1bffa19ae7 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Thu, 11 Nov 2021 17:33:23 +0100 Subject: [PATCH 1/6] Refactor Mobilizon.Service.Activity.Member Signed-off-by: Thomas Citharel --- lib/service/activity/member.ex | 85 ++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/lib/service/activity/member.ex b/lib/service/activity/member.ex index 72d0f55f8..2cebec490 100644 --- a/lib/service/activity/member.ex +++ b/lib/service/activity/member.ex @@ -18,19 +18,19 @@ defmodule Mobilizon.Service.Activity.Member do ) do subject = Keyword.get(options, :subject) - with author_id <- get_author(new_member, options), - object_id <- if(subject == "member_removed", do: nil, else: to_string(member_id)) do - ActivityBuilder.enqueue(:build_activity, %{ - "type" => "member", - "subject" => subject, - "subject_params" => get_subject_params(new_member, options), - "group_id" => parent_id, - "author_id" => author_id, - "object_type" => "member", - "object_id" => object_id, - "inserted_at" => DateTime.utc_now() - }) - end + author_id = get_author(new_member, options) + object_id = if(subject == "member_removed", do: nil, else: to_string(member_id)) + + ActivityBuilder.enqueue(:build_activity, %{ + "type" => "member", + "subject" => subject, + "subject_params" => get_subject_params(new_member, options), + "group_id" => parent_id, + "author_id" => author_id, + "object_type" => "member", + "object_id" => object_id, + "inserted_at" => DateTime.utc_now() + }) end def insert_activity(_, _), do: {:ok, nil} @@ -66,38 +66,41 @@ defmodule Mobilizon.Service.Activity.Member do end end - moderator = Keyword.get(options, :moderator) - old_member = Keyword.get(options, :old_member) - - subject_params = %{ + %{ member_role: String.upcase(to_string(role)) } + |> maybe_add_actor(actor) + |> maybe_add_old_member(Keyword.get(options, :old_member)) + |> maybe_add_moderator(Keyword.get(options, :moderator)) + end - subject_params = - if(is_nil(actor), - do: subject_params, - else: - subject_params - |> Map.put( - :member_actor_federated_username, - Actor.preferred_username_and_domain(actor) - ) - |> Map.put(:member_actor_name, actor.name) - ) + @spec maybe_add_actor(map(), Actor.t() | nil) :: map() + defp maybe_add_actor(subject_params, nil), do: subject_params - subject_params = - if(is_nil(old_member), - do: subject_params, - else: Map.put(subject_params, :old_role, String.upcase(to_string(old_member.role))) - ) + defp maybe_add_actor(subject_params, %Actor{} = actor) do + subject_params + |> Map.put( + :member_actor_federated_username, + Actor.preferred_username_and_domain(actor) + ) + |> Map.put(:member_actor_name, actor.name) + end - if is_nil(moderator), - do: subject_params, - else: - Map.put( - subject_params, - :moderator_preferred_username, - Actor.preferred_username_and_domain(moderator) - ) + @spec maybe_add_old_member(map(), Member.t() | nil) :: map() + defp maybe_add_old_member(subject_params, nil), do: subject_params + + defp maybe_add_old_member(subject_params, old_member) do + Map.put(subject_params, :old_role, String.upcase(to_string(old_member.role))) + end + + @spec maybe_add_moderator(map(), Actor.t() | nil) :: map() + defp maybe_add_moderator(subject_params, nil), do: subject_params + + defp maybe_add_moderator(subject_params, moderator) do + Map.put( + subject_params, + :moderator_preferred_username, + Actor.preferred_username_and_domain(moderator) + ) end end From 6eba531c89db4bff397b286ce304ebdaf30decf3 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 12 Nov 2021 15:42:52 +0100 Subject: [PATCH 2/6] Allow group admins to moderate new members Closes #881 Signed-off-by: Thomas Citharel --- .../components/Activity/GroupActivityItem.vue | 5 + .../Activity/MemberActivityItem.vue | 34 +++--- js/src/components/Group/InvitationCard.vue | 113 ++++++++++-------- js/src/components/Group/Invitations.vue | 67 +++++++---- js/src/graphql/member.ts | 16 ++- js/src/i18n/en_US.json | 15 ++- js/src/i18n/fr_FR.json | 17 ++- js/src/mixins/group.ts | 4 + js/src/views/Group/Group.vue | 105 ++++++++-------- js/src/views/Group/GroupMembers.vue | 83 ++++++++++--- js/src/views/Group/GroupSettings.vue | 13 ++ lib/federation/activity_pub/actions/accept.ex | 53 ++++++-- lib/federation/activity_pub/actions/leave.ex | 12 +- lib/federation/activity_pub/actions/reject.ex | 25 ++++ lib/federation/activity_pub/actions/remove.ex | 10 +- lib/federation/activity_pub/transmogrifier.ex | 31 +++-- lib/federation/activity_pub/types/actors.ex | 8 +- lib/graphql/resolvers/member.ex | 88 +++++++++++--- lib/graphql/schema/actors/member.ex | 24 +++- lib/service/activity/renderer/member.ex | 8 ++ lib/service/notifications/scheduler.ex | 2 +- lib/web/email/member.ex | 56 ++++++++- .../email/group_membership_approval.html.heex | 69 +++++++++++ .../email/group_membership_approval.text.eex | 5 + .../group_membership_rejection.html.heex | 49 ++++++++ .../email/group_membership_rejection.text.eex | 4 + .../activity_pub/activity_pub_test.exs | 2 +- test/graphql/resolvers/member_test.exs | 89 +++++++++++++- 28 files changed, 795 insertions(+), 212 deletions(-) create mode 100644 lib/web/templates/email/group_membership_approval.html.heex create mode 100644 lib/web/templates/email/group_membership_approval.text.eex create mode 100644 lib/web/templates/email/group_membership_rejection.html.heex create mode 100644 lib/web/templates/email/group_membership_rejection.text.eex diff --git a/js/src/components/Activity/GroupActivityItem.vue b/js/src/components/Activity/GroupActivityItem.vue index ba8d0d19c..8a58660b6 100644 --- a/js/src/components/Activity/GroupActivityItem.vue +++ b/js/src/components/Activity/GroupActivityItem.vue @@ -148,6 +148,11 @@ export default class GroupActivityItem extends mixins(ActivityMixin) { case Openness.INVITE_ONLY: details.push("The group can now only be joined with an invite."); break; + case Openness.MODERATED: + details.push( + "The group can now be joined by anyone, but new members need to be approved by an administrator." + ); + break; case Openness.OPEN: details.push("The group can now be joined by anyone."); break; diff --git a/js/src/components/Activity/MemberActivityItem.vue b/js/src/components/Activity/MemberActivityItem.vue index 3434c4dfc..d927438b6 100644 --- a/js/src/components/Activity/MemberActivityItem.vue +++ b/js/src/components/Activity/MemberActivityItem.vue @@ -9,13 +9,7 @@ :inline="true" slot="member" > - - {{ - $t("@{username}", { - username: usernameWithDomain(activity.object.actor), - }) - }} {{ displayName(activity.object.actor) }} {{ subjectParams.member_actor_federated_username @@ -25,13 +19,7 @@ :inline="true" slot="profile" > - - {{ - $t("@{username}", { - username: usernameWithDomain(activity.author), - }) - }} {{ displayName(activity.author) }} {{ @@ -41,7 +29,7 @@