DeviseInvitable

repository·master·Indexed 25 days ago

https://github.com/scambra/devise_invitable

An extension for the Devise authentication framework that adds support for inviting users via email and allowing them to accept invitations by setting a password. It provides tools for managing invitation tokens, configuring invitation limits, and customizing invitation controllers and views for both ActiveRecord and Mongoid.

Tokens
5.6K
Snippets
16
Records
37
Agent score
83%

What's inside devise_invitable

  1. Automatic Installation via Generators

    master

    You can automate the setup using Rails generators:

    1. Install Configuration: Run the following to add configuration options to config/initializers/devise.rb:

      rails generate devise_invitable:install
    2. Add to Model: Run the following to add :invitable to a specific Devise model (e.g., User) and generate necessary migrations:

      rails generate devise_invitable MODEL

      Replace MODEL with your class name.

  2. Install DeviseInvitable

    master

    To use DeviseInvitable, add the gem to your Gemfile and run bundle install.

    Requirements:

    • Devise >= 4.6 (for latest DeviseInvitable)
    • For Devise versions 4.0 <= x < 4.6, use DeviseInvitable version 1.7.5.
    gem 'devise_invitable', '~> 2.0.0'
  3. Customize DeviseInvitable Views

    master

    To customize the invitation views, copy them to your application using a generator.

    Global views:

    rails generate devise_invitable:views

    Scoped views (e.g., for 'users'):

    rails generate devise_invitable:views users

    If using scoped views, ensure config.scoped_views = true is set in config/initializers/devise.rb.

  4. Restrict who can send invitations via authenticate_inviter!

    master

    The InvitationsController uses the authenticate_inviter! filter. By default, it requires the inviter to be authenticated as the same resource type as the invitee.

    To restrict invitations to a specific role (e.g., only Admins), override authenticate_inviter! in your ApplicationController and include DeviseInvitable::Inviter in the model allowed to send invitations.

    ```ruby
    # In ApplicationController
    class ApplicationController < ActionController::Base
      protected
    
        def authenticate_inviter!
          authenticate_admin!(force: true)
        end
    end
    
    # In Admin model
    class Admin < ActiveRecord::Base
      devise :database_authenticatable, :validatable
      include DeviseInvitable::Inviter
    end
    ```埋
  5. Customize Invitations Controller

    master

    To change behavior, inherit from Devise::InvitationsController. You can override actions like new, create, edit, and update.

    Example: Overriding update and internal methods:

    class Users::InvitationsController < Devise::InvitationsController
      def update
        if some_condition
          redirect_to root_path
        else
          super
        end
      end
    
      private
    
      # Called when creating an invitation
      def invite_resource
        super { |user| user.skip_invitation = true }
      end
    
      # Called when accepting an invitation
      def accept_resource
        resource = resource_class.accept_invitation!(update_resource_params)
        Analytics.report('invite.accept', resource.id)
        resource
      end
    end

    Routing: Update routes.rb to use your custom controller:

    devise_for :users, controllers: { invitations: 'users/invitations' }
    class Users::InvitationsController < Devise::InvitationsController
      def update
        if some_condition
          redirect_to root_path
        else
          super
        end
      end
    end
  6. Configure 'has_many' association for invitations

    master

    To track which users were invited by a specific resource, define a has_many association on the inviter model.

    If Admins invite Users, add this to the Admin model: has_many :invitations, class_name: 'User', as: :invited_by

  7. Manual Installation for ActiveRecord

    master

    If you prefer manual setup:

    1. Model Configuration: Add :invitable to your devise call in the model.
    2. Migration: Add the following columns to your table and an index on invitation_token.

    Required Columns:

    • invitation_token (string, unique index)
    • invitation_created_at (datetime)
    • invitation_sent_at (datetime)
    • invitation_accepted_at (datetime)
    • invitation_limit (integer)
    • invited_by_id (integer)
    • invited_by_type (string)
    class User < ActiveRecord::Base
      devise :database_authenticatable, :confirmable, :invitable
    end
  8. Configure Strong Parameters for Invitations

    master

    DeviseInvitable requires parameter sanitization for the invite and accept_invitation actions. If you add custom fields (like first_name or role) to your invitation forms, you must permit them in your controller.

    Example: Permitting custom attributes in ApplicationController:

    class ApplicationController < ActionController::Base
      before_action :configure_permitted_parameters, if: :devise_controller?
    
      protected
    
      def configure_permitted_parameters
        # Permit custom fields for the 'invite' action
        devise_parameter_sanitizer.permit(:invite, keys: [:first_name, :last_name, :role])
      end
    end
      before_action :configure_permitted_parameters, if: :devise_controller?
    
      protected
    
      def configure_permitted_parameters
        devise_parameter_sanitizer.permit(:invite, keys: [:first_name, :last_name, :role])
      end
  9. Manual Installation for Mongoid

    master

    For Mongoid users, define these fields and indexes in your model:

    field :invitation_token, type: String
    field :invitation_created_at, type: Time
    field :invitation_sent_at, type: Time
    field :invitation_accepted_at, type: Time
    field :invitation_limit, type: Integer
    
    index( { invitation_token: 1 }, { background: true} )
    index( { invitation_by_id: 1 }, { background: true} )

    Note: DeviseInvitable handles the belongs_to :invited_by, polymorphic: true relationship automatically. After deploying, run rake db:mongoid:create_indexes to ensure indexes are created.

  10. Customize invitation I18n messages

    master

    You can customize the flash messages used by DeviseInvitable by modifying your locale files. The primary keys are:

    • devise.invitations.send_instructions
    • devise.invitations.invitation_token_invalid
    • devise.invitations.updated
    • devise.invitations.updated_not_active

    You can also scope these by resource name (e.g., devise.invitations.user.send_instructions).

    ```yaml
    en:
      devise:
        invitations:
          send_instructions: 'An invitation email has been sent to %{email}.'
          invitation_token_invalid: 'The invitation token provided is not valid!'
          updated: 'Your password was set successfully. You are now signed in.'
          updated_not_active: 'Your password was set successfully.'
    ```埋
  11. Configure :invitable options

    master

    You can configure DeviseInvitable globally in config/initializers/devise.rb or per-model via the devise method.

    Key Configuration Options:

    • invite_for: Period the invitation token is valid (e.g., 2.weeks). Default is 0 (never expires).
    • invitation_limit: Number of invitations a user can send. nil means unlimited; 0 means none.
    • invite_key: Hash used to check existing users when sending invites (default uses email).
    • validate_on_invite: Force record to be valid before inviting.
    • resend_invitation: Resend invitation if user is already in invited status (enabled by default).
    • invited_by_class_name: Class name of the inviting model (if nil, uses polymorphic association).
    • invited_by_foreign_key: Foreign key for the inviting model.
    • invited_by_counter_cache: Column name for counter cache.
    • allow_insecure_sign_in_after_accept: Automatically sign in user after password set (enabled by default).
    • require_password_on_accepting: Require password when accepting invitation (enabled by default).