devise_invitable 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of devise_invitable might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG +6 -0
- data/README.rdoc +10 -3
- data/app/controllers/devise/invitations_controller.rb +5 -2
- data/lib/devise_invitable/controllers/helpers.rb +2 -2
- data/lib/devise_invitable/model.rb +12 -10
- data/lib/devise_invitable/version.rb +1 -1
- data/test/functional/controller_helpers_test.rb +11 -6
- data/test/models/invitable_test.rb +18 -11
- data/test/rails_app/config/environments/test.rb +4 -0
- data/test/rails_app/config/initializers/devise.rb +1 -1
- data/test/test_helper.rb +11 -1
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: babfb02e4177cd88fe44772401f61014f8b462ea
         | 
| 4 | 
            +
              data.tar.gz: 1302cfd7ca394b79ed9f250fe49e9753c4ea0ac8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ec68260bfce3d59a7365e60e14d756815b85f8c65260cc5df7f74cdd5cc0cf443176a4ec8468e91c667150d88e7676bf5acbea6a5c7b30211e2dc76d5d6d9d56
         | 
| 7 | 
            +
              data.tar.gz: d4213cdfc200c4ba8fd5fee2eb0251cf2b892b6663caa0a9a7e307d62f2819307fcb00f43193d92815e8196277208994471f2a329c95931766cb13e5ef6f2cdb
         | 
    
        data/CHANGELOG
    CHANGED
    
    
    
        data/README.rdoc
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            = DeviseInvitable
         | 
| 2 | 
            -
            {<img src="https://badge.fury.io/rb/devise_invitable.svg"/>}[http://badge.fury.io/rb/devise_invitable] {<img src="https://travis-ci.org/scambra/devise_invitable.png"/>}[https://travis-ci.org/scambra/devise_invitable] {<img src="https://codeclimate.com/github/scambra/devise_invitable/badges/gpa.svg"/}[https://codeclimate.com/github/scambra/devise_invitable]
         | 
| 2 | 
            +
            {<img src="https://badge.fury.io/rb/devise_invitable.svg"/>}[http://badge.fury.io/rb/devise_invitable] {<img src="https://travis-ci.org/scambra/devise_invitable.png"/>}[https://travis-ci.org/scambra/devise_invitable] {<img src="https://codeclimate.com/github/scambra/devise_invitable/badges/gpa.svg"/}[https://codeclimate.com/github/scambra/devise_invitable] 
         | 
| 3 3 |  | 
| 4 4 | 
             
            It adds support to devise[https://github.com/plataformatec/devise] for sending invitations by email (it requires to be authenticated) and accept the invitation setting the password.
         | 
| 5 5 |  | 
| @@ -18,7 +18,7 @@ Install DeviseInvitable gem, it will also install dependencies (such as devise a | |
| 18 18 | 
             
            Add DeviseInvitable to your Gemfile (and Devise if you weren't using them):
         | 
| 19 19 |  | 
| 20 20 | 
             
              gem 'devise',           '~> 3.5.2'
         | 
| 21 | 
            -
              gem 'devise_invitable', '~> 1. | 
| 21 | 
            +
              gem 'devise_invitable', '~> 1.6.0'
         | 
| 22 22 |  | 
| 23 23 | 
             
            === Automatic installation
         | 
| 24 24 |  | 
| @@ -283,6 +283,11 @@ You can also set <tt>invited_by</tt> when using the <tt>invite!</tt> class metho | |
| 283 283 |  | 
| 284 284 | 
             
              User.invite!({:email => "new_user@example.com"}, current_user) # current_user will be set as invited_by
         | 
| 285 285 |  | 
| 286 | 
            +
            === Find by invitation token
         | 
| 287 | 
            +
             | 
| 288 | 
            +
            To find by invitation token use the <tt>find_by_invitation_token</tt> class method. 
         | 
| 289 | 
            +
             | 
| 290 | 
            +
              user = User.find_by_invitation_token(params[:invitation_token], true)
         | 
| 286 291 |  | 
| 287 292 |  | 
| 288 293 | 
             
            === Accept an invitation
         | 
| @@ -321,7 +326,7 @@ A pair of scopes to find those users that have accepted, and those that have not | |
| 321 326 | 
             
            Since the invitations controller take care of all the creation/acceptation of an invitation, in most cases you wouldn't call the <tt>invite!</tt> and <tt>accept_invitation!</tt> methods directly.
         | 
| 322 327 | 
             
            Instead, in your views, put a link to <tt>new_user_invitation_path</tt> or <tt>new_invitation_path(:user)</tt> or even <tt>/users/invitation/new</tt> to prepare and send an invitation (to a user in this example).
         | 
| 323 328 |  | 
| 324 | 
            -
            After an invitation is created and sent, the inviter will be redirected to after_invite_path_for( | 
| 329 | 
            +
            After an invitation is created and sent, the inviter will be redirected to after_invite_path_for(inviter, invitee), which is stored path or the same path as after_sign_in_path_for by default.
         | 
| 325 330 |  | 
| 326 331 | 
             
            After an invitation is accepted, the invitee will be redirected to after_accept_path_for(resource), which is the same path as after_sign_in_path_for by default. If you want to override the path, override invitations controller and define after_accept_path_for method. This is useful in the common case that a user is invited to a specific location in your application. More on {Devise's README}[https://github.com/plataformatec/devise], "Controller filters and helpers" section.
         | 
| 327 332 |  | 
| @@ -397,6 +402,8 @@ The DeviseInvitable mailer uses the same pattern as Devise to create mail subjec | |
| 397 402 |  | 
| 398 403 | 
             
            Take a look at the generated locale file (in <tt>config/locales/devise_invitable.en.yml</tt>) to check all available messages.
         | 
| 399 404 |  | 
| 405 | 
            +
            Translations are not included in gem (and they won't), they are available at wiki[https://github.com/scambra/devise_invitable/wiki/I18n].
         | 
| 406 | 
            +
             | 
| 400 407 | 
             
            == Other ORMs
         | 
| 401 408 |  | 
| 402 409 | 
             
            DeviseInvitable supports ActiveRecord and Mongoid, like Devise.
         | 
| @@ -32,7 +32,11 @@ class Devise::InvitationsController < DeviseController | |
| 32 32 | 
             
                  if is_flashing_format? && self.resource.invitation_sent_at
         | 
| 33 33 | 
             
                    set_flash_message :notice, :send_instructions, :email => self.resource.email
         | 
| 34 34 | 
             
                  end
         | 
| 35 | 
            -
                   | 
| 35 | 
            +
                  if self.method(:after_invite_path_for).arity == 1
         | 
| 36 | 
            +
                    respond_with resource, :location => after_invite_path_for(current_inviter)
         | 
| 37 | 
            +
                  else
         | 
| 38 | 
            +
                    respond_with resource, :location => after_invite_path_for(current_inviter, resource)
         | 
| 39 | 
            +
                  end
         | 
| 36 40 | 
             
                else
         | 
| 37 41 | 
             
                  respond_with_navigational(resource) { render :new }
         | 
| 38 42 | 
             
                end
         | 
| @@ -117,4 +121,3 @@ class Devise::InvitationsController < DeviseController | |
| 117 121 | 
             
                'devise.invitations'
         | 
| 118 122 | 
             
              end
         | 
| 119 123 | 
             
            end
         | 
| 120 | 
            -
             | 
| @@ -4,8 +4,8 @@ module DeviseInvitable::Controllers::Helpers | |
| 4 4 | 
             
              included do
         | 
| 5 5 | 
             
              end
         | 
| 6 6 |  | 
| 7 | 
            -
              def after_invite_path_for( | 
| 8 | 
            -
                after_sign_in_path_for( | 
| 7 | 
            +
              def after_invite_path_for(inviter, invitee = nil)
         | 
| 8 | 
            +
                after_sign_in_path_for(inviter)
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 11 | 
             
              def after_accept_path_for(resource)
         | 
| @@ -41,12 +41,14 @@ module Devise | |
| 41 41 | 
             
                      counter_cache = Devise.invited_by_counter_cache
         | 
| 42 42 | 
             
                      belongs_to_options.merge! :counter_cache => counter_cache if counter_cache
         | 
| 43 43 | 
             
                      belongs_to_options.merge! :optional => true if ActiveRecord::VERSION::MAJOR >= 5
         | 
| 44 | 
            +
                    elsif defined?(Mongoid) && defined?(Mongoid::Document) && self < Mongoid::Document && Mongoid::VERSION >= '6.0.0'
         | 
| 45 | 
            +
                      belongs_to_options.merge! :optional => true
         | 
| 44 46 | 
             
                    end
         | 
| 45 47 | 
             
                    belongs_to :invited_by, belongs_to_options
         | 
| 46 48 |  | 
| 47 | 
            -
                     | 
| 48 | 
            -
                     | 
| 49 | 
            -
                     | 
| 49 | 
            +
                    extend ActiveModel::Callbacks
         | 
| 50 | 
            +
                    define_model_callbacks :invitation_created
         | 
| 51 | 
            +
                    define_model_callbacks :invitation_accepted
         | 
| 50 52 |  | 
| 51 53 | 
             
                    scope :no_active_invitation, lambda { where(:invitation_token => nil) }
         | 
| 52 54 | 
             
                    if defined?(Mongoid) && defined?(Mongoid::Document) && self < Mongoid::Document
         | 
| @@ -88,12 +90,12 @@ module Devise | |
| 88 90 | 
             
                  # Accept an invitation by clearing invitation token and and setting invitation_accepted_at
         | 
| 89 91 | 
             
                  # Saves the model and confirms it if model is confirmable, running invitation_accepted callbacks
         | 
| 90 92 | 
             
                  def accept_invitation!
         | 
| 91 | 
            -
                     | 
| 92 | 
            -
             | 
| 93 | 
            +
                    if self.invited_to_sign_up?
         | 
| 94 | 
            +
                      @accepting_invitation = true
         | 
| 93 95 | 
             
                      run_callbacks :invitation_accepted do
         | 
| 94 96 | 
             
                        self.accept_invitation
         | 
| 95 97 | 
             
                        self.confirmed_at = self.invitation_accepted_at if self.respond_to?(:confirmed_at)
         | 
| 96 | 
            -
                        self.save | 
| 98 | 
            +
                        self.save
         | 
| 97 99 | 
             
                      end
         | 
| 98 100 | 
             
                    end
         | 
| 99 101 | 
             
                  end
         | 
| @@ -105,7 +107,7 @@ module Devise | |
| 105 107 |  | 
| 106 108 | 
             
                  # Verifies whether a user has been invited or not
         | 
| 107 109 | 
             
                  def invited_to_sign_up?
         | 
| 108 | 
            -
                    persisted? && invitation_token.present?
         | 
| 110 | 
            +
                    accepting_invitation? || (persisted? && invitation_token.present?)
         | 
| 109 111 | 
             
                  end
         | 
| 110 112 |  | 
| 111 113 | 
             
                  # Returns true if accept_invitation! was called
         | 
| @@ -113,12 +115,12 @@ module Devise | |
| 113 115 | 
             
                    @accepting_invitation
         | 
| 114 116 | 
             
                  end
         | 
| 115 117 |  | 
| 116 | 
            -
                  # Verifies whether a user accepted an invitation ( | 
| 118 | 
            +
                  # Verifies whether a user accepted an invitation (false when user is accepting it)
         | 
| 117 119 | 
             
                  def invitation_accepted?
         | 
| 118 | 
            -
                    invitation_accepted_at.present?
         | 
| 120 | 
            +
                    !accepting_invitation? && invitation_accepted_at.present?
         | 
| 119 121 | 
             
                  end
         | 
| 120 122 |  | 
| 121 | 
            -
                  # Verifies whether a user has accepted an invitation ( | 
| 123 | 
            +
                  # Verifies whether a user has accepted an invitation (false when user is accepting it), or was never invited
         | 
| 122 124 | 
             
                  def accepted_or_not_invited?
         | 
| 123 125 | 
             
                    invitation_accepted? || !invited_to_sign_up?
         | 
| 124 126 | 
             
                  end
         | 
| @@ -6,32 +6,37 @@ class ControllerHelpersTest < ActionController::TestCase | |
| 6 6 | 
             
              test "after invite path defaults to after sign in path" do
         | 
| 7 7 | 
             
                assert_equal @controller.send(:after_sign_in_path_for, :user), @controller.after_invite_path_for(:user)
         | 
| 8 8 | 
             
              end
         | 
| 9 | 
            -
             | 
| 9 | 
            +
             | 
| 10 10 | 
             
              test "after accept path defaults to after sign in path" do
         | 
| 11 11 | 
             
                assert_equal @controller.send(:after_sign_in_path_for, :user), @controller.after_accept_path_for(:user)
         | 
| 12 12 | 
             
              end
         | 
| 13 | 
            -
             | 
| 13 | 
            +
             | 
| 14 14 | 
             
              test 'after invite path is customizable from application controller' do
         | 
| 15 15 | 
             
                custom_path = 'customized/after/invite/path'
         | 
| 16 16 | 
             
                @controller.instance_eval "def after_invite_path_for(resource) '#{custom_path}' end"
         | 
| 17 17 | 
             
                assert_equal @controller.after_invite_path_for(:user), custom_path
         | 
| 18 18 | 
             
              end
         | 
| 19 | 
            -
             | 
| 19 | 
            +
             | 
| 20 | 
            +
              test 'after invite path is customizable from application controller with invited' do
         | 
| 21 | 
            +
                custom_path = 'customized/after/invite/path'
         | 
| 22 | 
            +
                @controller.instance_eval "def after_invite_path_for(resource, invited) '#{custom_path}' end"
         | 
| 23 | 
            +
                assert_equal @controller.after_invite_path_for(:user, :invited), custom_path
         | 
| 24 | 
            +
              end
         | 
| 20 25 | 
             
              test 'after accept path is customizable from application controller' do
         | 
| 21 26 | 
             
                custom_path = 'customized/after/accept/path'
         | 
| 22 27 | 
             
                @controller.instance_eval "def after_accept_path_for(resource) '#{custom_path}' end"
         | 
| 23 28 | 
             
                assert_equal @controller.after_accept_path_for(:user), custom_path
         | 
| 24 29 | 
             
              end
         | 
| 25 | 
            -
             | 
| 30 | 
            +
             | 
| 26 31 | 
             
              test 'is not a devise controller' do
         | 
| 27 32 | 
             
                assert !@controller.devise_controller?
         | 
| 28 33 | 
             
              end
         | 
| 29 | 
            -
             | 
| 34 | 
            +
             | 
| 30 35 | 
             
              test 'invitations controller respects definition for after invite path in application controller' do
         | 
| 31 36 | 
             
                assert Devise::InvitationsController.method_defined? :after_invite_path_for
         | 
| 32 37 | 
             
                assert !Devise::InvitationsController.instance_methods(false).include?(:after_invite_path_for)
         | 
| 33 38 | 
             
              end
         | 
| 34 | 
            -
             | 
| 39 | 
            +
             | 
| 35 40 | 
             
              test 'invitations controller respects definition for after accept path in application controller' do
         | 
| 36 41 | 
             
                assert Devise::InvitationsController.method_defined? :after_accept_path_for
         | 
| 37 42 | 
             
                assert !Devise::InvitationsController.instance_methods(false).include?(:after_accept_path_for)
         | 
| @@ -193,16 +193,16 @@ class InvitableTest < ActiveSupport::TestCase | |
| 193 193 | 
             
              end
         | 
| 194 194 |  | 
| 195 195 | 
             
              test 'should not accept invite without password' do
         | 
| 196 | 
            -
                 | 
| 197 | 
            -
                 | 
| 198 | 
            -
                refute_predicate  | 
| 196 | 
            +
                User.invite!(:email => "valid@email.com")
         | 
| 197 | 
            +
                User.accept_invitation!(:invitation_token => Thread.current[:token])
         | 
| 198 | 
            +
                refute_predicate User.where(:email => 'valid@email.com').first, :invitation_accepted?
         | 
| 199 199 | 
             
              end
         | 
| 200 200 |  | 
| 201 201 | 
             
              test 'should accept invite without password if enforce is disabled' do
         | 
| 202 202 | 
             
                Devise.stubs(:require_password_on_accepting => false)
         | 
| 203 | 
            -
                 | 
| 204 | 
            -
                 | 
| 205 | 
            -
                assert_predicate  | 
| 203 | 
            +
                User.invite!(:email => "valid@email.com")
         | 
| 204 | 
            +
                User.accept_invitation!(:invitation_token => Thread.current[:token])
         | 
| 205 | 
            +
                assert_predicate User.where(:email => 'valid@email.com').first, :invitation_accepted?
         | 
| 206 206 | 
             
              end
         | 
| 207 207 |  | 
| 208 208 | 
             
              test 'should set password and password confirmation from params' do
         | 
| @@ -607,12 +607,14 @@ class InvitableTest < ActiveSupport::TestCase | |
| 607 607 | 
             
                user.accept_invitation!
         | 
| 608 608 |  | 
| 609 609 | 
             
                assert user.confirmed?
         | 
| 610 | 
            +
                refute user.changed?
         | 
| 610 611 | 
             
              end
         | 
| 611 612 |  | 
| 612 613 | 
             
              test 'user.accept_invitation! should not confirm user if validation fails' do
         | 
| 613 614 | 
             
                user = User.invite!(:email => "valid@email.com")
         | 
| 614 615 | 
             
                user.username='a'*50
         | 
| 615 616 | 
             
                user.accept_invitation!
         | 
| 617 | 
            +
                user.reload
         | 
| 616 618 |  | 
| 617 619 | 
             
                refute_predicate user, :confirmed?
         | 
| 618 620 | 
             
              end
         | 
| @@ -652,23 +654,28 @@ class InvitableTest < ActiveSupport::TestCase | |
| 652 654 | 
             
              test 'should pass validation before accept if field is required in post-invited instance' do
         | 
| 653 655 | 
             
                user = User.invite!(:email => "valid@email.com")
         | 
| 654 656 | 
             
                user.testing_accepted_or_not_invited = true
         | 
| 655 | 
            -
                 | 
| 657 | 
            +
                user.valid?
         | 
| 658 | 
            +
                assert_empty user.errors
         | 
| 656 659 | 
             
              end
         | 
| 657 660 |  | 
| 658 661 | 
             
              test 'should fail validation after accept if field is required in post-invited instance' do
         | 
| 659 662 | 
             
                user = User.invite!(:email => "valid@email.com")
         | 
| 660 663 | 
             
                user.testing_accepted_or_not_invited = true
         | 
| 661 | 
            -
                user | 
| 662 | 
            -
                 | 
| 664 | 
            +
                assert_predicate user, :accept_invitation!
         | 
| 665 | 
            +
                user = User.where(:email => "valid@email.com").first
         | 
| 666 | 
            +
                user.valid?
         | 
| 667 | 
            +
                refute_empty user.errors
         | 
| 663 668 | 
             
              end
         | 
| 664 669 |  | 
| 665 670 | 
             
              test 'should pass validation after accept if field is required in post-invited instance' do
         | 
| 666 671 | 
             
                user = User.invite!(:email => "valid@email.com")
         | 
| 667 672 | 
             
                user.username = 'test'
         | 
| 668 673 | 
             
                user.testing_accepted_or_not_invited = true
         | 
| 674 | 
            +
                assert_predicate user, :accept_invitation!
         | 
| 675 | 
            +
                user = User.where(:email => "valid@email.com").first
         | 
| 669 676 | 
             
                user.bio = "Test"
         | 
| 670 | 
            -
                user. | 
| 671 | 
            -
                 | 
| 677 | 
            +
                user.valid?
         | 
| 678 | 
            +
                assert_empty user.errors
         | 
| 672 679 | 
             
              end
         | 
| 673 680 |  | 
| 674 681 | 
             
              test 'should return instance with errors if invitation_token is nil' do
         | 
| @@ -28,6 +28,10 @@ RailsApp::Application.configure do | |
| 28 28 | 
             
              # like if you have constraints or database-specific column types
         | 
| 29 29 | 
             
              # config.active_record.schema_format = :sql
         | 
| 30 30 |  | 
| 31 | 
            +
              if Rails.version >= '4.2' && config.respond_to?(:active_record)
         | 
| 32 | 
            +
                config.active_record.raise_in_transactional_callbacks = true
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 31 35 | 
             
              # Print deprecation notices to the stderr
         | 
| 32 36 | 
             
              config.active_support.deprecation = :stderr
         | 
| 33 37 |  | 
| @@ -172,7 +172,7 @@ Devise.setup do |config| | |
| 172 172 | 
             
              # Email regex used to validate email formats. It simply asserts that
         | 
| 173 173 | 
             
              # an one (and only one) @ exists in the given string. This is mainly
         | 
| 174 174 | 
             
              # to give user feedback and not to assert the e-mail validity.
         | 
| 175 | 
            -
               | 
| 175 | 
            +
              config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
         | 
| 176 176 |  | 
| 177 177 | 
             
              # ==> Configuration for :timeoutable
         | 
| 178 178 | 
             
              # The time you want to timeout the user session without activity. After this
         | 
    
        data/test/test_helper.rb
    CHANGED
    
    | @@ -20,5 +20,15 @@ class ActionDispatch::IntegrationTest | |
| 20 20 | 
             
              include Capybara::DSL
         | 
| 21 21 | 
             
            end
         | 
| 22 22 | 
             
            class ActionController::TestCase
         | 
| 23 | 
            -
               | 
| 23 | 
            +
              if defined? Devise::Test
         | 
| 24 | 
            +
                include Devise::Test::ControllerHelpers
         | 
| 25 | 
            +
              else
         | 
| 26 | 
            +
                include Devise::TestHelpers
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
              if Rails.version >= '5.0.0'
         | 
| 29 | 
            +
                self.use_transactional_tests = true
         | 
| 30 | 
            +
              else
         | 
| 31 | 
            +
                require 'test_after_commit' rescue nil
         | 
| 32 | 
            +
                self.use_transactional_fixtures = true
         | 
| 33 | 
            +
              end
         | 
| 24 34 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: devise_invitable
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.6. | 
| 4 | 
            +
              version: 1.6.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sergio Cambra
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016-04 | 
| 11 | 
            +
            date: 2016-08-04 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 163 163 | 
             
                  version: 1.3.6
         | 
| 164 164 | 
             
            requirements: []
         | 
| 165 165 | 
             
            rubyforge_project: 
         | 
| 166 | 
            -
            rubygems_version: 2. | 
| 166 | 
            +
            rubygems_version: 2.5.1
         | 
| 167 167 | 
             
            signing_key: 
         | 
| 168 168 | 
             
            specification_version: 4
         | 
| 169 169 | 
             
            summary: An invitation strategy for Devise
         |