devise_invitable 1.1.6 → 1.1.7
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.
- data/README.rdoc +24 -0
- data/app/controllers/devise/invitations_controller.rb +18 -7
- data/app/controllers/devise_invitable/registrations_controller.rb +1 -1
- data/config/locales/en.yml +1 -0
- data/lib/devise_invitable/model.rb +18 -5
- data/lib/devise_invitable/routes.rb +1 -0
- data/lib/devise_invitable/version.rb +1 -1
- data/lib/generators/active_record/templates/migration.rb +1 -1
- metadata +5 -4
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
|
-
|
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
|
data/config/locales/en.yml
CHANGED
@@ -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 :
|
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
|
-
|
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.
|
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
|
|
@@ -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:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 1.1.
|
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-
|
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:
|