From 0e07750925d78c3480097bc8eacabdd266290c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Pereira=20de=20Lucena?= Date: Thu, 3 Nov 2022 17:25:33 +0100 Subject: [PATCH] Backport 'Fix conference invitations' to v0.27 (#10003) * Fix conference invitations * Fix conference invitations * Clarify the unauthorized errors when accepting/rejecting conference invitation * Fix redirecting back to the same URL (accept/reject) after sign in * Clarify the conference invitation text when inviting a new user * Fix decline conference invitation link * Add spaces to the links * Fix re-joining already joined conference In case the user already joined the conference, broadcast ok. * Change the i18n key for invite existing users * Add omitted value in keyword argument * Add omitted value in keyword argument Co-authored-by: Antti Hukkanen --- .../admin/invite_user_to_join_conference.rb | 2 +- .../decidim/conferences/join_conference.rb | 5 ++ .../conference_registrations_controller.rb | 17 +++++ .../decidim/conferences/permissions.rb | 1 + .../invite.html.erb | 6 +- .../devise/mailer/join_conference.html.erb | 4 +- .../devise/mailer/join_conference.text.erb | 4 +- decidim-conferences/config/locales/en.yml | 5 +- .../invite_user_to_join_conference_spec.rb | 63 +++++++++++++++++++ .../spec/commands/join_conference_spec.rb | 8 +++ .../system/conference_registrations_spec.rb | 22 +++++++ 11 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 decidim-conferences/spec/commands/admin/invite_user_to_join_conference_spec.rb diff --git a/decidim-conferences/app/commands/decidim/conferences/admin/invite_user_to_join_conference.rb b/decidim-conferences/app/commands/decidim/conferences/admin/invite_user_to_join_conference.rb index ba0a1677ec15..a12d526614a7 100644 --- a/decidim-conferences/app/commands/decidim/conferences/admin/invite_user_to_join_conference.rb +++ b/decidim-conferences/app/commands/decidim/conferences/admin/invite_user_to_join_conference.rb @@ -98,7 +98,7 @@ def user def invite_user_to_sign_up user.skip_reconfirmation! - user.invite!(invited_by, invitation_instructions: "join_conference", conference: conference) + user.invite!(invited_by, invitation_instructions: "join_conference", conference: conference, registration_type: form.registration_type) end end end diff --git a/decidim-conferences/app/commands/decidim/conferences/join_conference.rb b/decidim-conferences/app/commands/decidim/conferences/join_conference.rb index e65064d0ee80..f3d3b26dab4b 100644 --- a/decidim-conferences/app/commands/decidim/conferences/join_conference.rb +++ b/decidim-conferences/app/commands/decidim/conferences/join_conference.rb @@ -21,6 +21,7 @@ def initialize(conference, registration_type, user) # Broadcasts :ok if successful, :invalid otherwise. def call return broadcast(:invalid) unless can_join_conference? + return broadcast(:ok) if already_joined_conference? conference.with_lock do create_registration @@ -58,6 +59,10 @@ def can_join_conference? conference.registrations_enabled? && conference.has_available_slots? end + def already_joined_conference? + conference.conference_registrations.where(user: user).any? + end + def send_email_pending_validation Decidim::Conferences::ConferenceRegistrationMailer.pending_validation(user, conference, @registration_type).deliver_later end diff --git a/decidim-conferences/app/controllers/decidim/conferences/conference_registrations_controller.rb b/decidim-conferences/app/controllers/decidim/conferences/conference_registrations_controller.rb index bef723e877ef..f4cbb493209a 100644 --- a/decidim-conferences/app/controllers/decidim/conferences/conference_registrations_controller.rb +++ b/decidim-conferences/app/controllers/decidim/conferences/conference_registrations_controller.rb @@ -4,6 +4,8 @@ module Decidim module Conferences # Exposes the registration resource so users can join and leave conferences. class ConferenceRegistrationsController < Decidim::Conferences::ApplicationController + before_action :ensure_signed_in + def create enforce_permission_to :join, :conference, conference: conference @@ -54,6 +56,20 @@ def decline_invitation private + def ensure_signed_in + return if user_signed_in? + + case action_name + when "create" + flash[:alert] = t("conference_registrations.create.unauthorized", scope: "decidim.conferences") + when "decline_invitation" + flash[:alert] = t("conference_registrations.decline_invitation.unauthorized", scope: "decidim.conferences") + else + raise Decidim::ActionForbidden + end + redirect_to(user_has_no_permission_referer || user_has_no_permission_path) + end + def conference @conference ||= Conference.find_by(slug: params[:conference_slug]) end @@ -65,6 +81,7 @@ def registration_type def redirect_after_path referer = request.headers["Referer"] return redirect_to(conference_path(conference)) if referer =~ /invitation_token/ + return redirect_to(conference_path(conference)) if referer =~ %r{users/sign_in} redirect_back fallback_location: conference_path(conference) end diff --git a/decidim-conferences/app/permissions/decidim/conferences/permissions.rb b/decidim-conferences/app/permissions/decidim/conferences/permissions.rb index d00b6cbbf82f..c1eab3c4c7b4 100644 --- a/decidim-conferences/app/permissions/decidim/conferences/permissions.rb +++ b/decidim-conferences/app/permissions/decidim/conferences/permissions.rb @@ -77,6 +77,7 @@ def can_leave_conference? end def can_decline_invitation? + return unless user return unless conference.presence return unless conference.registrations_enabled? && conference.conference_invites.exists?(user: user) && diff --git a/decidim-conferences/app/views/decidim/conferences/admin/invite_join_conference_mailer/invite.html.erb b/decidim-conferences/app/views/decidim/conferences/admin/invite_join_conference_mailer/invite.html.erb index 34fd0a15e1eb..25dccb02ac01 100644 --- a/decidim-conferences/app/views/decidim/conferences/admin/invite_join_conference_mailer/invite.html.erb +++ b/decidim-conferences/app/views/decidim/conferences/admin/invite_join_conference_mailer/invite.html.erb @@ -1,12 +1,12 @@ diff --git a/decidim-conferences/app/views/devise/mailer/join_conference.html.erb b/decidim-conferences/app/views/devise/mailer/join_conference.html.erb index cb3edb920dcd..02f5a1d9f457 100644 --- a/decidim-conferences/app/views/devise/mailer/join_conference.html.erb +++ b/decidim-conferences/app/views/devise/mailer/join_conference.html.erb @@ -1,10 +1,10 @@ - + <% if @resource.invitation_due_at %> diff --git a/decidim-conferences/app/views/devise/mailer/join_conference.text.erb b/decidim-conferences/app/views/devise/mailer/join_conference.text.erb index 16145da08600..7de23b44a295 100644 --- a/decidim-conferences/app/views/devise/mailer/join_conference.text.erb +++ b/decidim-conferences/app/views/devise/mailer/join_conference.text.erb @@ -1,8 +1,8 @@ <%= t("devise.mailer.invitation_instructions.hello", email: @resource.name) %> -<%= t("decidim.conferences.admin.invite_join_conference_mailer.invite.invited_you_to_join_a_conference", invited_by: @resource.invited_by.name, application: @resource.organization.name) %> +<%= t("decidim.conferences.admin.invite_join_conference_mailer.invite.invited_existing_user_to_join_a_conference", invited_by: @resource.invited_by.name, application: @resource.organization.name) %> -<%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, invitation_token: @token, invite_redirect: Decidim::EngineRouter.main_proxy(@opts[:conference]).conference_conference_registration_path(conference_slug: @opts[:conference]), host: @resource.organization.host) %> +<%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, invitation_token: @token, invite_redirect: Decidim::EngineRouter.main_proxy(@opts[:conference]).conference_registration_type_conference_registration_path(conference_slug: @opts[:conference], registration_type_id: @opts[:registration_type]), host: @resource.organization.host) %> <% if @resource.invitation_due_at %> <%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :long)) %> diff --git a/decidim-conferences/config/locales/en.yml b/decidim-conferences/config/locales/en.yml index 02fecde7708b..854df0bf37b2 100644 --- a/decidim-conferences/config/locales/en.yml +++ b/decidim-conferences/config/locales/en.yml @@ -380,7 +380,8 @@ en: invite_join_conference_mailer: invite: decline: Decline invitation '%{conference_title}' - invited_you_to_join_a_conference: "%{invited_by} has invited you to join a conference at %{application}. You can decline or accept it through the links below." + invited_existing_user_to_join_a_conference: "%{invited_by} has invited you to join a conference at %{application}. You can decline or accept it through the links below." + invited_user_to_join_a_conference: "%{invited_by} has invited you to join a conference at %{application}. You can accept it through the link below." registration: Registration for '%{conference_title}' partners: index: @@ -431,9 +432,11 @@ en: create: invalid: There was a problem joining this conference. success: You have successfully joined the conference. + unauthorized: You need to sign in before registering to the conference. decline_invitation: invalid: There was a problem declining the invitation. success: You have successfully declined the invitation. + unauthorized: You need to sign in before declining the invitation. destroy: invalid: There was a problem leaving this conference. success: You have successfully left the conference. diff --git a/decidim-conferences/spec/commands/admin/invite_user_to_join_conference_spec.rb b/decidim-conferences/spec/commands/admin/invite_user_to_join_conference_spec.rb new file mode 100644 index 000000000000..35805f29c247 --- /dev/null +++ b/decidim-conferences/spec/commands/admin/invite_user_to_join_conference_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim::Conferences::Admin + describe InviteUserToJoinConference do + let(:command) { described_class.new(form, conference, invited_by) } + + let(:conference) { create :conference } + let(:invited_by) { create :user, :admin, :confirmed, organization: conference.organization } + let(:invited_user) { create :user, :confirmed, organization: conference.organization } + let(:form) do + double( + invalid?: invalid, + existing_user: true, + current_organization: conference.organization, + user: invited_user, + registration_type: registration_type + ) + end + let(:invalid) { false } + let(:registration_type) { create(:registration_type, conference: conference) } + + describe "call" do + it "broadcasts ok" do + expect { command.call }.to broadcast(:ok) + end + + it "sends the invitation to the existing user" do + perform_enqueued_jobs { command.call } + + email = last_email + expect(email.to).to eq([invited_user.email]) + expect(email.subject).to eq("Invitation to join a conference") + end + + describe "when the user is a new user" do + let(:form) do + double( + invalid?: invalid, + existing_user: false, + current_organization: conference.organization, + email: "jdoe@example.org", + name: "John Doe", + registration_type: registration_type + ) + end + + it "broadcasts ok" do + expect { command.call }.to broadcast(:ok) + end + + it "sends the invitation to the user" do + perform_enqueued_jobs { command.call } + + email = last_email + expect(email.to).to eq(["jdoe@example.org"]) + expect(email.subject).to eq("Invitation to join a conference") + end + end + end + end +end diff --git a/decidim-conferences/spec/commands/join_conference_spec.rb b/decidim-conferences/spec/commands/join_conference_spec.rb index 773f13c49ab5..4675ea48ee53 100644 --- a/decidim-conferences/spec/commands/join_conference_spec.rb +++ b/decidim-conferences/spec/commands/join_conference_spec.rb @@ -158,5 +158,13 @@ module Decidim::Conferences expect { subject.call }.to broadcast(:invalid) end end + + context "when the user has already joined the conference" do + let!(:registration) { create(:conference_registration, conference: conference, user: user) } + + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + end end end diff --git a/decidim-conferences/spec/system/conference_registrations_spec.rb b/decidim-conferences/spec/system/conference_registrations_spec.rb index 8863d5313322..104f0a45d302 100644 --- a/decidim-conferences/spec/system/conference_registrations_spec.rb +++ b/decidim-conferences/spec/system/conference_registrations_spec.rb @@ -34,6 +34,10 @@ def visit_conference_registration_types visit decidim_conferences.conference_registration_types_path(conference) end + def visit_conference_registration_type + visit decidim_conferences.conference_registration_type_conference_registration_path(conference_slug: conference, registration_type_id: registration_type) + end + before do switch_to_host(organization.host) @@ -136,4 +140,22 @@ def visit_conference_registration_types end end end + + context "and the user has been invited to the conference" do + let!(:invite) { create(:conference_invite, user: user, registration_type: registration_type) } + + it "requires the user to sign in" do + visit_conference_registration_type + expect(page).to have_current_path("/users/sign_in") + end + + context "when the user is signed in" do + before { login_as user, scope: :user } + + it "accepts the invitation successfully" do + visit_conference_registration_type + expect(page).to have_content("successfully") + end + end + end end