Permalink
Browse files

Merge pull request #3136 from sharetribe/unsubscribe-link-to-invitati…

…on-emails

Add an unsubscribe link to invitation emails
  • Loading branch information...
thomasmalbaux committed Nov 10, 2017
2 parents 76efb57 + 4cca7ce commit 4e4e93885996e35512a5ad0e1e0d3c610e88cca0
@@ -1,10 +1,10 @@
class InvitationsController < ApplicationController
before_action do |controller|
before_action except: :unsubscribe do |controller|
controller.ensure_logged_in t("layouts.notifications.you_must_log_in_to_invite_new_users")
end
before_action :users_can_invite_new_users
before_action :users_can_invite_new_users, except: :unsubscribe
def new
@selected_tribe_navi_tab = "members"
@@ -26,7 +26,8 @@ def create
:message
)
invitation_emails = invitation_params[:email].split(",").map(&:strip)
raw_invitation_emails = invitation_params[:email].split(",").map(&:strip)
invitation_emails = Invitation::Unsubscribe.remove_unsubscribed_emails(@current_community, raw_invitation_emails)
unless validate_daily_limit(@current_user.id, invitation_emails.size, @current_community)
return redirect_to new_invitation_path, flash: { error: t("layouts.notifications.invitation_limit_reached")}
@@ -66,6 +67,16 @@ def create
redirect_to new_invitation_path
end
def unsubscribe
invitation_unsubscribe = Invitation::Unsubscribe.unsubscribe(params[:code])
if invitation_unsubscribe.persisted?
flash[:notice] = t("layouts.notifications.invitation_successfully_unsubscribed")
else
flash[:error] = t("layouts.notifications.invitation_cannot_unsubscribe")
end
redirect_to landing_page_path
end
private
def users_can_invite_new_users
@@ -197,8 +197,10 @@ def invitation_to_kassi(invitation)
@invitation_code_required = invitation.community.join_with_invite_only
set_up_layout_variables(nil, invitation.community)
@url_params[:locale] = mail_locale
@url_params[:code] = invitation.code
@invitation_community = invitation.community.full_name_with_separator(invitation.inviter.locale)
with_locale(mail_locale, invitation.community.locales.map(&:to_sym), invitation.community.id) do
subject = t("emails.invitation_to_kassi.you_have_been_invited_to_kassi", :inviter => PersonViewUtils.person_display_name(invitation.inviter, invitation.community), :community => invitation.community.full_name_with_separator(invitation.inviter.locale))
subject = t("emails.invitation_to_kassi.you_have_been_invited_to_kassi", :inviter => PersonViewUtils.person_display_name(invitation.inviter, invitation.community), :community => @invitation_community)
premailer_mail(:to => invitation.email,
:from => community_specific_sender(invitation.community),
:subject => subject,
@@ -0,0 +1,37 @@
# == Schema Information
#
# Table name: invitation_unsubscribes
#
# id :integer not null, primary key
# community_id :integer
# email :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_invitation_unsubscribes_on_community_id (community_id)
# index_invitation_unsubscribes_on_email (email)
#
class Invitation::Unsubscribe < ApplicationRecord
belongs_to :community
validates :community, :email, presence: true
scope :by_community_and_email, ->(community, email) { where(community: community, email: email) }
class << self
def unsubscribe(code)
invitation = Invitation.find_by(code: code.upcase)
if invitation
where(community: invitation.community,
email: invitation.email.downcase).first_or_create
end
end
def remove_unsubscribed_emails(community, invitation_emails)
invitation_emails.reject{ |email| by_community_and_email(community, email).any? }
end
end
end
@@ -34,7 +34,18 @@
%tr
%td{:align => "left", :style => "padding-top: 10px; padding-bottom: 30px;border-top:1px dotted grey;"}
%font{:size => 3, :color => "gray", :face => "font-family:Helvetica Neue, Arial, Helvetica, Arial, sans-serif;", :style => "font-size:12px;"}
- if @community
= t("emails.common.unsubscribe_from_these_emails_info", service_name: @community.full_name(I18n.locale))
= t("emails.welcome_email.welcome_email_footer_text", :settings_link => link_to(t("emails.welcome_email.settings_link_text"), notifications_person_settings_url(@recipient, @url_params))).html_safe
- if @email_type
= t("emails.common.or")
= link_to(t("emails.common.unsubscribe_from_these_emails"), unsubscribe_person_settings_url(@recipient, @url_params.merge({email_type: @email_type, auth: @unsubscribe_token}))) + "."
- if @invitation
%tr
%td{:align => "left", :style => "padding-top: 10px; padding-bottom: 30px;border-top:1px dotted grey;"}
%font{:size => 3, :color => "gray", :face => "font-family:Helvetica Neue, Arial, Helvetica, Arial, sans-serif;", :style => "font-size:12px;"}
= t("emails.common.unsubscribe_from_invitation_emails_info", service_name: @invitation_community)
= link_to(t("emails.common.unsubscribe_from_invitation_emails", service_name: @invitation_community),
unsubscribe_invitations_url(@url_params)) + "."
View
@@ -946,7 +946,10 @@ en:
message_not_displaying_correctly: "Is this email not displaying correctly?"
view_it_in_your_browser: "View it in your browser"
or: or
unsubscribe_from_these_emails_info: "You have received this email because you are a member of %{service_name}."
unsubscribe_from_these_emails: "unsubscribe from these emails"
unsubscribe_from_invitation_emails_info: "You have received this email because a member of %{service_name} has invited you to join them."
unsubscribe_from_invitation_emails: "Unsubscribe from invitation emails to join %{service_name}"
conversation_status_changed:
has_accepted_your_offer: "%{accepter} has accepted your offer %{listing}."
has_accepted_your_request: "%{accepter} has accepted your request %{listing}."
@@ -1412,8 +1415,10 @@ en:
feedback_sent_to: "Feedback sent to %{target_person}."
feedback_skipped: "Feedback skipped"
invitation_cannot_be_sent: "Invitation could not be sent"
invitation_cannot_unsubscribe: "Cannot unsubscribe from invitation emails"
invitation_limit_reached: "You were trying to send too many invitations. Daily limit reached."
invitation_sent: "Invitation sent successfully"
invitation_successfully_unsubscribed: "Successfully unsubscribed from invitation emails"
inviting_new_users_is_not_allowed_in_this_community: "Inviting new users is not allowed."
login_again: "Please log in again."
login_failed: "Login failed. Please enter the correct credentials."
View
@@ -318,7 +318,11 @@
resource :plan, only: [:show]
end
resources :invitations
resources :invitations, only: [:new, :create ] do
collection do
get :unsubscribe
end
end
resources :user_feedbacks, :controller => :feedbacks
resources :homepage do
collection do
@@ -0,0 +1,12 @@
class CreateInvitationUnsubscribes < ActiveRecord::Migration[5.1]
def change
create_table :invitation_unsubscribes do |t|
t.integer :community_id
t.string :email
t.timestamps
end
add_index :invitation_unsubscribes, :community_id
add_index :invitation_unsubscribes, :email
end
end
View
@@ -547,6 +547,20 @@ CREATE TABLE `follower_relationships` (
KEY `index_follower_relationships_on_person_id` (`person_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `invitation_unsubscribes`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `invitation_unsubscribes` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`community_id` int(11) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `index_invitation_unsubscribes_on_community_id` (`community_id`),
KEY `index_invitation_unsubscribes_on_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `invitations`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
@@ -2195,6 +2209,7 @@ INSERT INTO `schema_migrations` (version) VALUES
('20170728065012'),
('20170801125553'),
('20170814125622'),
('20170817035830');
('20170817035830'),
('20171107063241');
@@ -0,0 +1,7 @@
Feature: Visitor unsubscribe from invitaion to join community
Scenario: Visitor click on link to unsubscribe
Given community "test" admin sent invitation to "elaine@example.com" code "ABC"
When I go to the unsubscribe link with code "ABC" from invitation email to join community
Then I should see "Successfully unsubscribed from invitation emails"
@@ -0,0 +1,4 @@
Given(/^community "(.*?)" admin sent invitation to "(.*?)" code "(.*?)"$/) do |community, email, code|
community = Community.where(ident: community).first
FactoryGirl.create(:invitation, community: community, code: code, email: email)
end
@@ -94,6 +94,8 @@ def path_to(page_name)
admin_listing_shapes_path
when /the edit "(.*)" order type admin page/
edit_admin_listing_shape_path(id: $1)
when /the unsubscribe link with code "(.*)" from invitation email to join community/
unsubscribe_invitations_path(code: $1)
else
begin
page_name =~ /the (.*) page/
View
@@ -412,4 +412,9 @@ def build_association(association, opts = {})
sort_priority 0
end
factory :invitation_unsubscribe, class: 'Invitation::Unsubscribe' do
build_association(:community)
email 'sherry@example.com'
end
end
@@ -0,0 +1,47 @@
# == Schema Information
#
# Table name: invitation_unsubscribes
#
# id :integer not null, primary key
# community_id :integer
# email :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_invitation_unsubscribes_on_community_id (community_id)
# index_invitation_unsubscribes_on_email (email)
#
require 'spec_helper'
RSpec.describe Invitation::Unsubscribe, type: :model do
let(:invitation) { FactoryGirl.create(:invitation, code: 'ABC', email: 'cindy@example.com') }
let(:invitation_unsubscribe) { FactoryGirl.create(:invitation_unsubscribe) }
let(:community) { FactoryGirl.create(:community) }
context '#unsubscribe' do
it 'creates unsubscribe record' do
expect(Invitation::Unsubscribe.count).to eq 0
Invitation::Unsubscribe.unsubscribe(invitation.code)
expect(Invitation::Unsubscribe.count).to eq 1
end
end
context '#remove_unsubscribed_emails' do
it 'works' do
invitation_unsubscribe
invitation_emails = ['sherry@example.com', 'thelma@example.com']
result = Invitation::Unsubscribe.remove_unsubscribed_emails(invitation_unsubscribe.community, invitation_emails)
expect(result).to eq ['thelma@example.com']
end
it 'does not remove email related to another community' do
invitation_unsubscribe
invitation_emails = ['sherry@example.com', 'thelma@example.com']
result = Invitation::Unsubscribe.remove_unsubscribed_emails(community, invitation_emails)
expect(result).to eq ['sherry@example.com', 'thelma@example.com']
end
end
end
@@ -1,3 +1,28 @@
# == Schema Information
#
# Table name: listing_shapes
#
# id :integer not null, primary key
# community_id :integer not null
# transaction_process_id :integer not null
# price_enabled :boolean not null
# shipping_enabled :boolean not null
# availability :string(32) default("none")
# name :string(255) not null
# name_tr_key :string(255) not null
# action_button_tr_key :string(255) not null
# sort_priority :integer default(0), not null
# created_at :datetime not null
# updated_at :datetime not null
# deleted :boolean default(FALSE)
#
# Indexes
#
# index_listing_shapes_on_community_id (community_id)
# index_listing_shapes_on_name (name)
# multicol_index (community_id,deleted,sort_priority)
#
require 'spec_helper'
describe ListingShape, type: :model do

0 comments on commit 4e4e938

Please sign in to comment.