devise_invitable 1.1.6 → 1.1.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise_invitable might be problematic. Click here for more details.

data/README.rdoc CHANGED
@@ -32,12 +32,14 @@ Replace MODEL by the class name you want to add DeviseInvitable, like User, Admi
32
32
 
33
33
  Follow the walkthrough for Devise and after it's done, follow this walkthrough.
34
34
 
35
+ == Devise Configuration
35
36
  Add :invitable to the <tt>devise</tt> call in your model (we’re assuming here you already have a User model with some Devise modules):
36
37
 
37
38
  class User < ActiveRecord::Base
38
39
  devise :database_authenticatable, :confirmable, :invitable
39
40
  end
40
41
 
42
+ == ActiveRecord Migration
41
43
  Add t.invitable to your Devise model migration:
42
44
 
43
45
  create_table :users do
@@ -67,6 +69,25 @@ or for a model that already exists, define a migration to add DeviseInvitable to
67
69
 
68
70
  # Allow null encrypted_password
69
71
  change_column :users, :encrypted_password, :string, :null => true
72
+ # Allow null password_salt (add it if you are using Devise's encryptable module)
73
+ change_column :users, :password_salt, :string, :null => true
74
+
75
+ == Mongoid Field Definitions
76
+ If you are using Mongoid, define the following fields and indexes within your invitable model:
77
+
78
+ field :invitation_token, type: String
79
+ field :invitation_sent_at, type: Time
80
+ field :invitation_accepted_at, type: Time
81
+ field :invitation_limit, type: Integer
82
+
83
+ index( {invitation_token: 1}, {:background => true} )
84
+ index( {invitation_by_id: 1}, {:background => true} )
85
+
86
+ You do not need to define a belongs_to relationship, as DeviseInvitable does this on your behalf:
87
+ belongs_to :invited_by, :polymorphic => true
88
+
89
+ Remember to create indexes within the MongoDB database after deploying your changes.
90
+ rake db:mongoid:create_indexes
70
91
 
71
92
  == Model configuration
72
93
 
@@ -153,6 +174,9 @@ You can add :skip_invitation to attributes hash if skip_invitation is added to a
153
174
  User.invite!(:email => "new_user@example.com", :name => "John Doe", :skip_invitation => true)
154
175
  # => the record will be created, but the invitation email will not be sent
155
176
 
177
+ Skip_invitation skips sending the email, but sets invitation_token, so invited_to_sign_up? on the
178
+ resulting user returns true.
179
+
156
180
  You can send an invitation to an existing user if your workflow creates them separately:
157
181
 
158
182
  user = User.find(42)
@@ -2,7 +2,8 @@ class Devise::InvitationsController < DeviseController
2
2
 
3
3
  before_filter :authenticate_inviter!, :only => [:new, :create]
4
4
  before_filter :has_invitations_left?, :only => [:create]
5
- before_filter :require_no_authentication, :only => [:edit, :update]
5
+ before_filter :require_no_authentication, :only => [:edit, :update, :destroy]
6
+ before_filter :resource_from_invitation_token, :only => [:edit, :destroy]
6
7
  helper_method :after_sign_in_path_for
7
8
 
8
9
  # GET /resource/invitation/new
@@ -25,12 +26,7 @@ class Devise::InvitationsController < DeviseController
25
26
 
26
27
  # GET /resource/invitation/accept?invitation_token=abcdef
27
28
  def edit
28
- if params[:invitation_token] && self.resource = resource_class.to_adapter.find_first( :invitation_token => params[:invitation_token] )
29
- render :edit
30
- else
31
- set_flash_message(:alert, :invitation_token_invalid)
32
- redirect_to after_sign_out_path_for(resource_name)
33
- end
29
+ render :edit
34
30
  end
35
31
 
36
32
  # PUT /resource/invitation
@@ -46,6 +42,13 @@ class Devise::InvitationsController < DeviseController
46
42
  respond_with_navigational(resource){ render :edit }
47
43
  end
48
44
  end
45
+
46
+ # GET /resource/invitation/remove?invitation_token=abcdef
47
+ def destroy
48
+ resource.destroy
49
+ set_flash_message :notice, :invitation_removed
50
+ redirect_to after_sign_out_path_for(resource_name)
51
+ end
49
52
 
50
53
  protected
51
54
  def current_inviter
@@ -59,5 +62,13 @@ class Devise::InvitationsController < DeviseController
59
62
  respond_with_navigational(resource) { render :new }
60
63
  end
61
64
  end
65
+
66
+ def resource_from_invitation_token
67
+ unless params[:invitation_token] && self.resource = resource_class.to_adapter.find_first(params.slice(:invitation_token))
68
+ set_flash_message(:alert, :invitation_token_invalid)
69
+ redirect_to after_sign_out_path_for(resource_name)
70
+ end
71
+ end
72
+
62
73
  end
63
74
 
@@ -7,7 +7,7 @@ class DeviseInvitable::RegistrationsController < Devise::RegistrationsController
7
7
  self.resource = resource_class.where(:email => hash[:email], :encrypted_password => '').first
8
8
  if self.resource
9
9
  self.resource.attributes = hash
10
- self.resource.accept_invitation!
10
+ self.resource.accept_invitation
11
11
  end
12
12
  end
13
13
  self.resource ||= super
@@ -5,6 +5,7 @@ en:
5
5
  invitation_token_invalid: 'The invitation token provided is not valid!'
6
6
  updated: 'Your password was set successfully. You are now signed in.'
7
7
  no_invitations_remaining: "No invitations remaining"
8
+ invitation_removed: 'Your invitation was removed.'
8
9
  new:
9
10
  header: "Send invitation"
10
11
  submit_button: "Send an invitation"
@@ -36,13 +36,17 @@ module Devise
36
36
 
37
37
  include ActiveSupport::Callbacks
38
38
  define_callbacks :invitation_accepted
39
+ before_update :generate_confirmation_token, :if => :confirmation_required_for_invited?
40
+ after_update :send_on_create_confirmation_instructions, :if => :confirmation_required_for_invited?
39
41
 
40
42
  attr_writer :skip_password
41
43
 
42
- scope :invitation_not_accepted, lambda { where(:invitation_accepted_at => nil) }
44
+ scope :active, lambda { where(:confirmation_token => nil) }
43
45
  if defined?(Mongoid) && self < Mongoid::Document
46
+ scope :invitation_not_accepted, lambda { where(:invitation_accepted_at => nil, :confirmation_token.ne => nil) }
44
47
  scope :invitation_accepted, lambda { where(:invitation_accepted_at.ne => nil) }
45
48
  else
49
+ scope :invitation_not_accepted, lambda { where(arel_table[:confirmation_token].not_eq(nil)).where(:invitation_accepted_at => nil) }
46
50
  scope :invitation_accepted, lambda { where(arel_table[:invitation_accepted_at].not_eq(nil)) }
47
51
 
48
52
  [:before_invitation_accepted, :after_invitation_accepted].each do |callback_method|
@@ -71,12 +75,17 @@ module Devise
71
75
  end
72
76
 
73
77
  # Accept an invitation by clearing invitation token and and setting invitation_accepted_at
74
- # Confirms it if model is confirmable
78
+ def accept_invitation
79
+ self.invitation_accepted_at = Time.now.utc
80
+ self.invitation_token = nil
81
+ end
82
+
83
+ # Accept an invitation by clearing invitation token and and setting invitation_accepted_at
84
+ # Saves the model and confirms it if model is confirmable, running invitation_accepted callbacks
75
85
  def accept_invitation!
76
86
  if self.invited_to_sign_up? && self.valid?
77
- self.invitation_accepted_at = Time.now.utc
78
87
  run_callbacks :invitation_accepted do
79
- self.invitation_token = nil
88
+ self.accept_invitation
80
89
  self.confirmed_at = self.invitation_accepted_at if self.respond_to?(:confirmed_at)
81
90
  self.save(:validate => false)
82
91
  end
@@ -120,7 +129,7 @@ module Devise
120
129
  end
121
130
 
122
131
  generate_invitation_token if self.invitation_token.nil?
123
- self.invitation_sent_at = Time.now.utc
132
+ self.invitation_sent_at = Time.now.utc unless @skip_invitation
124
133
  self.invited_by = invited_by if invited_by
125
134
 
126
135
  # Call these before_validate methods since we aren't validating on save
@@ -163,6 +172,10 @@ module Devise
163
172
  !@skip_password && super
164
173
  end
165
174
 
175
+ def confirmation_required_for_invited?
176
+ respond_to?(:confirmation_required?) && confirmation_required? && invitation_accepted?
177
+ end
178
+
166
179
  # Deliver the invitation email
167
180
  def deliver_invitation
168
181
  send_devise_notification(:invitation_instructions)
@@ -6,6 +6,7 @@ module ActionDispatch::Routing
6
6
  resource :invitation, :only => [:new, :create, :update],
7
7
  :path => mapping.path_names[:invitation], :controller => controllers[:invitations] do
8
8
  get :edit, :path => mapping.path_names[:accept], :as => :accept
9
+ get :destroy, :path => mapping.path_names[:remove], :as => :remove
9
10
  end
10
11
  end
11
12
 
@@ -1,3 +1,3 @@
1
1
  module DeviseInvitable
2
- VERSION = '1.1.6'
2
+ VERSION = '1.1.7'
3
3
  end
@@ -6,7 +6,7 @@ class DeviseInvitableAddTo<%= table_name.camelize %> < ActiveRecord::Migration
6
6
  t.datetime :invitation_accepted_at
7
7
  t.integer :invitation_limit
8
8
  t.references :invited_by, :polymorphic => true
9
- t.index :invitation_token # for invitable
9
+ t.index :invitation_token, :unique => true # for invitable
10
10
  t.index :invited_by_id
11
11
  end
12
12
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_invitable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 6
10
- version: 1.1.6
9
+ - 7
10
+ version: 1.1.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sergio Cambra
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-02-21 00:00:00 Z
18
+ date: 2013-04-01 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bundler
@@ -162,3 +162,4 @@ specification_version: 3
162
162
  summary: An invitation strategy for Devise
163
163
  test_files: []
164
164
 
165
+ has_rdoc: