From e50556fcc8d81dae5978bcb3e1dd5104789aab0f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 10 Apr 2015 16:37:02 +0200 Subject: [PATCH] Let invites be declined. --- app/controllers/invites_controller.rb | 27 +++++++++++++++++++ app/mailers/emails/groups.rb | 13 +++++++++ app/mailers/emails/projects.rb | 13 +++++++++ app/models/member.rb | 14 ++++++++++ app/models/members/group_member.rb | 6 +++++ app/models/members/project_member.rb | 6 +++++ app/services/notification_service.rb | 8 ++++++ app/views/invites/show.html.haml | 1 + .../group_invite_declined_email.html.haml | 6 +++++ .../group_invite_declined_email.text.erb | 3 +++ .../group_member_invited_email.html.haml | 2 ++ .../group_member_invited_email.text.erb | 1 + .../project_invite_accepted_email.text.erb | 2 +- .../project_invite_declined_email.html.haml | 6 +++++ .../project_invite_declined_email.text.erb | 3 +++ .../project_member_invited_email.html.haml | 2 ++ .../project_member_invited_email.text.erb | 1 + config/routes.rb | 1 + spec/models/members_spec.rb | 17 ++++++++++++ 19 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 app/views/notify/group_invite_declined_email.html.haml create mode 100644 app/views/notify/group_invite_declined_email.text.erb create mode 100644 app/views/notify/project_invite_declined_email.html.haml create mode 100644 app/views/notify/project_invite_declined_email.text.erb diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 8b1f6eeba1b..1b236a48e90 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -1,5 +1,6 @@ class InvitesController < ApplicationController before_filter :member + skip_before_filter :authenticate_user!, only: :decline respond_to :html @@ -31,6 +32,32 @@ class InvitesController < ApplicationController end end + def decline + if member.decline_invite! + case member.source + when Project + project = member.source + source = "project #{project.name_with_namespace}" + when Group + group = member.source + source = "group #{group.name}" + else + source = "who knows what" + end + + path = + if current_user + dashboard_path + else + new_user_session_path + end + + redirect_to path, notice: "You have declined the invite to join #{source}." + else + redirect_to :back, alert: "The invite could not be declined." + end + end + private def member diff --git a/app/mailers/emails/groups.rb b/app/mailers/emails/groups.rb index 9db609006e0..f3da3990c5f 100644 --- a/app/mailers/emails/groups.rb +++ b/app/mailers/emails/groups.rb @@ -27,5 +27,18 @@ module Emails mail(to: @group_member.created_by.notification_email, subject: subject("Invite accepted")) end + + def group_invite_declined_email(group_id, invite_email, access_level, created_by_id) + return if created_by_id.nil? + + @group = Group.find(group_id) + @created_by = User.find(created_by_id) + @access_level = access_level + @invite_email = invite_email + @target_url = group_url(@group) + + mail(to: @created_by.notification_email, + subject: subject("Invite declined")) + end end end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index 64c35618a52..bbfb7a3e409 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -28,6 +28,19 @@ module Emails subject: subject("Invite accepted")) end + def project_invite_declined_email(project_id, invite_email, access_level, created_by_id) + return if created_by_id.nil? + + @project = Project.find(project_id) + @created_by = User.find(created_by_id) + @access_level = access_level + @invite_email = invite_email + @target_url = namespace_project_url(@project.namespace, @project) + + mail(to: @created_by.notification_email, + subject: subject("Invite declined")) + end + def project_was_moved_email(project_id, user_id) @current_user = @user = User.find user_id @project = Project.find project_id diff --git a/app/models/member.rb b/app/models/member.rb index d8cc65ca6cb..2421222eaa2 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -76,6 +76,16 @@ class Member < ActiveRecord::Base saved end + def decline_invite! + return false unless invite? + + destroyed = self.destroy + + after_decline_invite if destroyed + + destroyed + end + def generate_invite_token raw, enc = Devise.token_generator.generate(self.class, :invite_token) @raw_invite_token = raw @@ -116,6 +126,10 @@ class Member < ActiveRecord::Base post_create_hook end + def after_decline_invite + # override in subclass + end + def system_hook_service SystemHooksService.new end diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index 68b7c169f72..84c91372b3f 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -66,4 +66,10 @@ class GroupMember < Member super end + + def after_decline_invite + notification_service.decline_group_invite(self) + + super + end end diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 3b3b1bd4680..8af7499dd82 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -167,6 +167,12 @@ class ProjectMember < Member super end + def after_decline_invite + notification_service.decline_project_invite(self) + + super + end + def event_service EventCreateService.new end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index a97abe289f5..203e654c18f 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -173,6 +173,10 @@ class NotificationService mailer.project_invite_accepted_email(project_member.id) end + def decline_project_invite(project_member) + mailer.project_invite_declined_email(project_member.project.id, project_member.invite_email, project_member.access_level, project_member.created_by_id) + end + def new_project_member(project_member) mailer.project_access_granted_email(project_member.id) end @@ -189,6 +193,10 @@ class NotificationService mailer.group_invite_accepted_email(group_member.id) end + def decline_group_invite(group_member) + mailer.group_invite_declined_email(group_member.group.id, group_member.invite_email, group_member.access_level, group_member.created_by_id) + end + def new_group_member(group_member) mailer.group_access_granted_email(group_member.id) end diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml index e2657ac6df2..ab0ecffe4d2 100644 --- a/app/views/invites/show.html.haml +++ b/app/views/invites/show.html.haml @@ -26,3 +26,4 @@ - else .actions = link_to "Accept invitation", accept_invite_url(@token), method: :post, class: "btn btn-success" + = link_to "Decline", decline_invite_url(@token), method: :post, class: "btn btn-danger prepend-left-10" diff --git a/app/views/notify/group_invite_declined_email.html.haml b/app/views/notify/group_invite_declined_email.html.haml new file mode 100644 index 00000000000..80f39c3f1ea --- /dev/null +++ b/app/views/notify/group_invite_declined_email.html.haml @@ -0,0 +1,6 @@ +%p + #{@invite_email} + has declined your invitation to join group + = link_to @group.name, group_url(@group) + as #{Gitlab::Access.options_with_owner.key(@access_level)}. + diff --git a/app/views/notify/group_invite_declined_email.text.erb b/app/views/notify/group_invite_declined_email.text.erb new file mode 100644 index 00000000000..31cdac0e7fb --- /dev/null +++ b/app/views/notify/group_invite_declined_email.text.erb @@ -0,0 +1,3 @@ +<%= @invite_email %> has declined your invitation to join group <%= @group.name %> as <%= Gitlab::Access.options_with_owner.key(@access_level) %>. + +<%= group_url(@group) %> diff --git a/app/views/notify/group_member_invited_email.html.haml b/app/views/notify/group_member_invited_email.html.haml index 39798a2c0e6..163e88bfea3 100644 --- a/app/views/notify/group_member_invited_email.html.haml +++ b/app/views/notify/group_member_invited_email.html.haml @@ -9,4 +9,6 @@ %p = link_to 'Accept invitation', invite_url(@token) + or + = link_to 'decline', decline_invite_url(@token) diff --git a/app/views/notify/group_member_invited_email.text.erb b/app/views/notify/group_member_invited_email.text.erb index dec0cf0d01e..28ce4819b14 100644 --- a/app/views/notify/group_member_invited_email.text.erb +++ b/app/views/notify/group_member_invited_email.text.erb @@ -1,3 +1,4 @@ You have been invited <%= "by #{@group_member.created_by.name} " if @group_member.created_by %>to join group <%= @group.name %> as <%= @group_member.human_access %>. Accept invitation: <%= invite_url(@token) %> +Decline invitation: <%= decline_invite_url(@token) %> diff --git a/app/views/notify/project_invite_accepted_email.text.erb b/app/views/notify/project_invite_accepted_email.text.erb index e90217c1ab2..0bbe274931e 100644 --- a/app/views/notify/project_invite_accepted_email.text.erb +++ b/app/views/notify/project_invite_accepted_email.text.erb @@ -1,3 +1,3 @@ -<%= @project_member.invite_email %>, now known as <%= @project_member.user.name %>, has accepted your invitation to join project <%= @group.name_with_namespace %> as <%= @project_member.human_access %>. +<%= @project_member.invite_email %>, now known as <%= @project_member.user.name %>, has accepted your invitation to join project <%= @project.name_with_namespace %> as <%= @project_member.human_access %>. <%= namespace_project_url(@project.namespace, @project) %> diff --git a/app/views/notify/project_invite_declined_email.html.haml b/app/views/notify/project_invite_declined_email.html.haml new file mode 100644 index 00000000000..dad9f505b9e --- /dev/null +++ b/app/views/notify/project_invite_declined_email.html.haml @@ -0,0 +1,6 @@ +%p + #{@invite_email} + has declined your invitation to join project + = link_to @project.name_with_namespace, namespace_project_url(@project.namespace, @project) + as #{Gitlab::Access.options_with_owner.key(@access_level)}. + diff --git a/app/views/notify/project_invite_declined_email.text.erb b/app/views/notify/project_invite_declined_email.text.erb new file mode 100644 index 00000000000..06a0013cff5 --- /dev/null +++ b/app/views/notify/project_invite_declined_email.text.erb @@ -0,0 +1,3 @@ +<%= @invite_email %> has declined your invitation to join project <%= @project.name_with_namespace %> as <%= Gitlab::Access.options_with_owner.key(@access_level) %>. + +<%= namespace_project_url(@project.namespace, @project) %> diff --git a/app/views/notify/project_member_invited_email.html.haml b/app/views/notify/project_member_invited_email.html.haml index f44adc244c9..79eb89616de 100644 --- a/app/views/notify/project_member_invited_email.html.haml +++ b/app/views/notify/project_member_invited_email.html.haml @@ -9,3 +9,5 @@ %p = link_to 'Accept invitation', invite_url(@token) + or + = link_to 'decline', decline_invite_url(@token) diff --git a/app/views/notify/project_member_invited_email.text.erb b/app/views/notify/project_member_invited_email.text.erb index 55b16ef6c56..e0706272115 100644 --- a/app/views/notify/project_member_invited_email.text.erb +++ b/app/views/notify/project_member_invited_email.text.erb @@ -1,3 +1,4 @@ You have been invited <%= "by #{@project_member.created_by.name} " if @project_member.created_by %>to join project <%= @project.name_with_namespace %> as <%= @project_member.human_access %>. Accept invitation: <%= invite_url(@token) %> +Decline invitation: <%= decline_invite_url(@token) %> diff --git a/config/routes.rb b/config/routes.rb index 50d11fde57d..d90268c2180 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -60,6 +60,7 @@ Gitlab::Application.routes.draw do resources :invites, only: [:show], constraints: { id: /[A-Za-z0-9_-]+/ } do member do post :accept + match :decline, via: [:get, :post] end end diff --git a/spec/models/members_spec.rb b/spec/models/members_spec.rb index 3f14a111443..c3e47ab7e9a 100644 --- a/spec/models/members_spec.rb +++ b/spec/models/members_spec.rb @@ -88,6 +88,23 @@ describe Member do end end + describe "#decline_invite!" do + + let!(:member) { create(:project_member, invite_email: "user@example.com", user: nil) } + + it "destroys the member" do + member.decline_invite! + + expect(member).to be_destroyed + end + + it "calls #after_decline_invite" do + expect(member).to receive(:after_decline_invite) + + member.decline_invite! + end + end + describe "#generate_invite_token" do let!(:member) { create(:project_member, invite_email: "user@example.com", user: nil) }