devise_invitable 1.2.1 → 1.3.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.
- checksums.yaml +7 -0
- data/CHANGELOG +5 -0
- data/README.rdoc +49 -15
- data/app/controllers/devise/invitations_controller.rb +10 -4
- data/app/views/devise/mailer/invitation_instructions.html.erb +1 -1
- data/lib/devise_invitable/mailer.rb +3 -7
- data/lib/devise_invitable/model.rb +46 -40
- data/lib/devise_invitable/parameter_sanitizer.rb +17 -2
- data/lib/devise_invitable/version.rb +1 -1
- data/lib/generators/active_record/templates/migration.rb +1 -1
- data/test/integration/invitation_remove_test.rb +5 -5
- data/test/integration/invitation_test.rb +5 -6
- data/test/mailers/invitation_mail_test.rb +12 -2
- data/test/models/invitable_test.rb +83 -29
- data/test/models_test.rb +4 -0
- data/test/rails_app/app/models/user.rb +9 -2
- data/test/rails_app/config/initializers/devise.rb +7 -1
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +2 -0
- metadata +10 -46
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA512:
|
|
3
|
+
metadata.gz: f63e9220602bf9934658384637404fdf89b2dfcd4f7b2b7ed77c31cddfbab70e6ca7fa89a2fa2dccf489db7b2e80ff6634cfadf320ee366769b42000da4e9ac5
|
|
4
|
+
data.tar.gz: d54dfb69ad95bf58f8a69c5c358ba64e9cfdf569536682f6e8614cc2f10550984657cb74353ab64a9fd59e1fed16991b9e8e4e5d120ec3583ad01f36b961bd1c
|
|
5
|
+
SHA1:
|
|
6
|
+
metadata.gz: 861482f2cb8845f6335441e94c3da04912511e1b
|
|
7
|
+
data.tar.gz: 54799f3b072ffc7dcd3080d5f394fa2c62e64990
|
data/CHANGELOG
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
= 1.3.0
|
|
2
|
+
Now devise 3.1 compatible, @token must be used instead of @resource.invitation_token in mail views
|
|
3
|
+
|
|
4
|
+
= 1.2.0
|
|
5
|
+
Add invitation_created_at column which is set when invitation is created even when sending is skipped. This new field is used to check invitation period valid
|
data/README.rdoc
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
It adds support to devise[http://github.com/plataformatec/devise] for send invitations by email (it requires to be authenticated) and accept the invitation setting the password.
|
|
5
5
|
|
|
6
|
-
DeviseInvitable currently
|
|
6
|
+
DeviseInvitable currently supports Rails 3 and 4, if you want to use it with Rails 2.3 you must install version {0.2.3}[http://rubygems.org/gems/devise_invitable/versions/0.2.3]
|
|
7
7
|
|
|
8
|
-
If you want to use
|
|
9
|
-
|
|
10
|
-
gem 'devise_invitable', :github => 'scambra/devise_invitable'
|
|
8
|
+
If you want to use devise 3.0.x, you must use 1.2.1, newer versions require devise >= 3.1.0
|
|
11
9
|
|
|
12
10
|
== Installation
|
|
13
11
|
|
|
@@ -49,7 +47,7 @@ Add t.invitable to your Devise model migration:
|
|
|
49
47
|
create_table :users do
|
|
50
48
|
...
|
|
51
49
|
## Invitable
|
|
52
|
-
t.string :invitation_token
|
|
50
|
+
t.string :invitation_token
|
|
53
51
|
t.datetime :invitation_created_at
|
|
54
52
|
t.datetime :invitation_sent_at
|
|
55
53
|
t.datetime :invitation_accepted_at
|
|
@@ -62,15 +60,15 @@ Add t.invitable to your Devise model migration:
|
|
|
62
60
|
|
|
63
61
|
or for a model that already exists, define a migration to add DeviseInvitable to your model:
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
def change
|
|
64
|
+
add_column :users, :invitation_token, :string
|
|
65
|
+
add_column :users, :invitation_created_at, :datetime
|
|
66
|
+
add_column :users, :invitation_sent_at, :datetime
|
|
67
|
+
add_column :users, :invitation_accepted_at, :datetime
|
|
68
|
+
add_column :users, :invitation_limit, :integer
|
|
69
|
+
add_column :users, :invited_by_id, :integer
|
|
70
|
+
add_column :users, :invited_by_type, :string
|
|
71
|
+
add_index :users, :invitation_token, :unique => true
|
|
74
72
|
end
|
|
75
73
|
|
|
76
74
|
# Allow null encrypted_password
|
|
@@ -78,6 +76,16 @@ or for a model that already exists, define a migration to add DeviseInvitable to
|
|
|
78
76
|
# Allow null password_salt (add it if you are using Devise's encryptable module)
|
|
79
77
|
change_column :users, :password_salt, :string, :null => true
|
|
80
78
|
|
|
79
|
+
If you previously used devise_invitable with a :limit on :invitation_token, remove it:
|
|
80
|
+
|
|
81
|
+
def up
|
|
82
|
+
change_column :users, :invitation_token, :string, :limit => nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def down
|
|
86
|
+
change_column :users, :invitation_token, :string, :limit => 60
|
|
87
|
+
end
|
|
88
|
+
|
|
81
89
|
== Mongoid Field Definitions
|
|
82
90
|
If you are using Mongoid, define the following fields and indexes within your invitable model:
|
|
83
91
|
|
|
@@ -116,7 +124,7 @@ or directly as parameters to the <tt>devise</tt> method:
|
|
|
116
124
|
|
|
117
125
|
* invitation_limit: The number of invitations users can send. The default value of nil means users can send as many invites as they want, there is no limit for any user, invitation_limit column is not used. A setting of 0 means they can't send invitations. A setting n > 0 means they can send n invitations. You can change invitation_limit column for some users so they can send more or less invitations, even with global invitation_limit = 0.
|
|
118
126
|
|
|
119
|
-
* invite_key: The key to be used to check existing users when sending an invitation. You can use multiple keys. This value must be a hash with the invite key as hash keys, and
|
|
127
|
+
* invite_key: The key to be used to check existing users when sending an invitation. You can use multiple keys. This value must be a hash with the invite key as hash keys, and values that respond to the === operator(includes procs and regexes). The default value is looking for users by email and validating with Devise.email_regexp {:email => Devise.email_regexp}.
|
|
120
128
|
|
|
121
129
|
* validate_on_invite: force a record to be valid before being actually invited.
|
|
122
130
|
|
|
@@ -164,6 +172,32 @@ be sure that you generate the views and put them into the controller that you ge
|
|
|
164
172
|
|
|
165
173
|
rails generate devise_invitable:views users/invitations
|
|
166
174
|
|
|
175
|
+
== Strong Parameters
|
|
176
|
+
|
|
177
|
+
When you customize your own views, you may end up adding new attributes to forms. Rails 4 moved the parameter sanitization from the model to the controller, causing DeviseInvitable to handle this concern at the controller as well. Read about it in {devise README}[http://github.com/plataformatec/devise#strong-parameters]
|
|
178
|
+
|
|
179
|
+
There are just two actions in DeviseInvitable that allows any set of parameters to be passed down to the model, therefore requiring sanitization. Their names and the permited parameters by default are:
|
|
180
|
+
|
|
181
|
+
* invite (Devise::InvitationsController#create) - Permits only the authentication keys (like email)
|
|
182
|
+
* accept_invitation (Devise::InvitationsController#update) - Permits invitation_token plus password and password_confirmation
|
|
183
|
+
|
|
184
|
+
Here is an example of what your application controller might need to include in order to add these parameters to the invitation view:
|
|
185
|
+
|
|
186
|
+
before_filter :configure_permitted_parameters, if: :devise_controller?
|
|
187
|
+
|
|
188
|
+
protected
|
|
189
|
+
|
|
190
|
+
def configure_permitted_parameters
|
|
191
|
+
# Only add some parameters
|
|
192
|
+
devise_parameter_sanitizer.for(:accept_invitation).concat [:first_name, :last_name, :phone]
|
|
193
|
+
# Override accepted parameters
|
|
194
|
+
devise_parameter_sanitizer.for(:accept_invitation) do |u|
|
|
195
|
+
u.permit(:first_name, :last_name, :phone, :password, :password_confirmation,
|
|
196
|
+
:invitation_token)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
|
|
167
201
|
== Usage
|
|
168
202
|
|
|
169
203
|
=== Send an invitation
|
|
@@ -14,7 +14,7 @@ class Devise::InvitationsController < DeviseController
|
|
|
14
14
|
|
|
15
15
|
# POST /resource/invitation
|
|
16
16
|
def create
|
|
17
|
-
self.resource =
|
|
17
|
+
self.resource = invite_resource
|
|
18
18
|
|
|
19
19
|
if resource.errors.empty?
|
|
20
20
|
set_flash_message :notice, :send_instructions, :email => self.resource.email if self.resource.invitation_sent_at
|
|
@@ -26,6 +26,7 @@ class Devise::InvitationsController < DeviseController
|
|
|
26
26
|
|
|
27
27
|
# GET /resource/invitation/accept?invitation_token=abcdef
|
|
28
28
|
def edit
|
|
29
|
+
resource.invitation_token = params[:invitation_token]
|
|
29
30
|
render :edit
|
|
30
31
|
end
|
|
31
32
|
|
|
@@ -51,6 +52,11 @@ class Devise::InvitationsController < DeviseController
|
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
protected
|
|
55
|
+
|
|
56
|
+
def invite_resource
|
|
57
|
+
resource_class.invite!(invite_params, current_inviter)
|
|
58
|
+
end
|
|
59
|
+
|
|
54
60
|
def current_inviter
|
|
55
61
|
@current_inviter ||= authenticate_inviter!
|
|
56
62
|
end
|
|
@@ -64,18 +70,18 @@ class Devise::InvitationsController < DeviseController
|
|
|
64
70
|
end
|
|
65
71
|
|
|
66
72
|
def resource_from_invitation_token
|
|
67
|
-
unless params[:invitation_token] && self.resource = resource_class.
|
|
73
|
+
unless params[:invitation_token] && self.resource = resource_class.find_by_invitation_token(params[:invitation_token], true)
|
|
68
74
|
set_flash_message(:alert, :invitation_token_invalid)
|
|
69
75
|
redirect_to after_sign_out_path_for(resource_name)
|
|
70
76
|
end
|
|
71
77
|
end
|
|
72
78
|
|
|
73
79
|
def invite_params
|
|
74
|
-
devise_parameter_sanitizer.
|
|
80
|
+
devise_parameter_sanitizer.sanitize(:invite)
|
|
75
81
|
end
|
|
76
82
|
|
|
77
83
|
def update_resource_params
|
|
78
|
-
devise_parameter_sanitizer.
|
|
84
|
+
devise_parameter_sanitizer.sanitize(:accept_invitation)
|
|
79
85
|
end
|
|
80
86
|
|
|
81
87
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<p>Someone has invited you to <%= root_url %>, you can accept it through the link below.</p>
|
|
4
4
|
|
|
5
|
-
<p><%= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @
|
|
5
|
+
<p><%= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @token) %></p>
|
|
6
6
|
|
|
7
7
|
<p>If you don't want to accept the invitation, please ignore this email.<br />
|
|
8
8
|
Your account won't be created until you access the link above and set your password.</p>
|
|
@@ -4,13 +4,9 @@ module DeviseInvitable
|
|
|
4
4
|
module Mailer
|
|
5
5
|
|
|
6
6
|
# Deliver an invitation email
|
|
7
|
-
def invitation_instructions(record, opts={})
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
devise_mail(record, :invitation_instructions)
|
|
11
|
-
else
|
|
12
|
-
devise_mail(record, :invitation_instructions, opts)
|
|
13
|
-
end
|
|
7
|
+
def invitation_instructions(record, token, opts={})
|
|
8
|
+
@token = token
|
|
9
|
+
devise_mail(record, :invitation_instructions, opts)
|
|
14
10
|
end
|
|
15
11
|
end
|
|
16
12
|
end
|
|
@@ -25,6 +25,7 @@ module Devise
|
|
|
25
25
|
|
|
26
26
|
attr_accessor :skip_invitation
|
|
27
27
|
attr_accessor :completing_invite
|
|
28
|
+
attr_reader :raw_invitation_token
|
|
28
29
|
|
|
29
30
|
included do
|
|
30
31
|
include ::DeviseInvitable::Inviter
|
|
@@ -64,14 +65,6 @@ module Devise
|
|
|
64
65
|
fields
|
|
65
66
|
end
|
|
66
67
|
|
|
67
|
-
def invitation_fields
|
|
68
|
-
fields = [:invitation_created_at, :invitation_sent_at, :invited_by_id, :invited_by_type]
|
|
69
|
-
if Devise.invited_by_class_name
|
|
70
|
-
fields -= [:invited_by_type]
|
|
71
|
-
end
|
|
72
|
-
fields
|
|
73
|
-
end
|
|
74
|
-
|
|
75
68
|
# Accept an invitation by clearing invitation token and and setting invitation_accepted_at
|
|
76
69
|
def accept_invitation
|
|
77
70
|
self.invitation_accepted_at = Time.now.utc
|
|
@@ -111,11 +104,6 @@ module Devise
|
|
|
111
104
|
invitation_accepted? || !invited_to_sign_up?
|
|
112
105
|
end
|
|
113
106
|
|
|
114
|
-
def invited?
|
|
115
|
-
ActiveSupport::Deprecation.warn "invited? is deprecated and will be removed from DeviseInvitable 1.1.0 (use invited_to_sign_up? instead)"
|
|
116
|
-
invited_to_sign_up?
|
|
117
|
-
end
|
|
118
|
-
|
|
119
107
|
# Reset invitation token and send invitation again
|
|
120
108
|
def invite!(invited_by = nil)
|
|
121
109
|
was_invited = invited_to_sign_up?
|
|
@@ -126,7 +114,7 @@ module Devise
|
|
|
126
114
|
def self.confirmation_required?; false; end
|
|
127
115
|
end
|
|
128
116
|
|
|
129
|
-
generate_invitation_token if self.invitation_token.nil?
|
|
117
|
+
generate_invitation_token if self.invitation_token.nil? || (!@skip_invitation && @raw_invitation_token.nil?)
|
|
130
118
|
self.invitation_created_at = Time.now.utc
|
|
131
119
|
self.invitation_sent_at = self.invitation_created_at unless @skip_invitation
|
|
132
120
|
self.invited_by = invited_by if invited_by
|
|
@@ -158,13 +146,24 @@ module Devise
|
|
|
158
146
|
accept_invitation! if invited_to_sign_up?
|
|
159
147
|
end
|
|
160
148
|
|
|
161
|
-
def
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
regexp.nil? || self.send(key).try(:match, regexp)
|
|
149
|
+
def clear_errors_on_valid_keys
|
|
150
|
+
self.class.invite_key.each do |key, value|
|
|
151
|
+
self.errors.delete(key) if value === self.send(key)
|
|
165
152
|
end
|
|
166
153
|
end
|
|
167
154
|
|
|
155
|
+
# Deliver the invitation email
|
|
156
|
+
def deliver_invitation
|
|
157
|
+
generate_invitation_token! unless @raw_invitation_token
|
|
158
|
+
self.update_attribute :invitation_sent_at, Time.now.utc unless self.invitation_sent_at
|
|
159
|
+
send_devise_notification(:invitation_instructions, @raw_invitation_token)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# provide alias to the encrypted invitation_token stored by devise
|
|
163
|
+
def encrypted_invitation_token
|
|
164
|
+
self.invitation_token
|
|
165
|
+
end
|
|
166
|
+
|
|
168
167
|
protected
|
|
169
168
|
# Overriding the method in Devise's :validatable module so password is not required on inviting
|
|
170
169
|
def password_required?
|
|
@@ -175,12 +174,6 @@ module Devise
|
|
|
175
174
|
respond_to?(:confirmation_required?, true) && confirmation_required? && invitation_accepted?
|
|
176
175
|
end
|
|
177
176
|
|
|
178
|
-
# Deliver the invitation email
|
|
179
|
-
def deliver_invitation
|
|
180
|
-
self.update_attribute :invitation_sent_at, Time.now.utc unless self.invitation_sent_at
|
|
181
|
-
send_devise_notification(:invitation_instructions)
|
|
182
|
-
end
|
|
183
|
-
|
|
184
177
|
# Checks if the invitation for the user is within the limit time.
|
|
185
178
|
# We do this by calculating if the difference between today and the
|
|
186
179
|
# invitation sent date does not exceed the invite for time configured.
|
|
@@ -208,18 +201,19 @@ module Devise
|
|
|
208
201
|
# Generates a new random token for invitation, and stores the time
|
|
209
202
|
# this token is being generated
|
|
210
203
|
def generate_invitation_token
|
|
211
|
-
|
|
204
|
+
raw, enc = Devise.token_generator.generate(self.class, :invitation_token)
|
|
205
|
+
@raw_invitation_token = raw
|
|
206
|
+
self.invitation_token = enc
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def generate_invitation_token!
|
|
210
|
+
generate_invitation_token && save(:validate => false)
|
|
212
211
|
end
|
|
213
212
|
|
|
214
213
|
module ClassMethods
|
|
215
214
|
# Return fields to invite
|
|
216
215
|
def invite_key_fields
|
|
217
|
-
|
|
218
|
-
invite_key.keys
|
|
219
|
-
else
|
|
220
|
-
ActiveSupport::Deprecation.warn("invite_key should be a hash like {#{invite_key.inspect} => /.../}")
|
|
221
|
-
Array(invite_key)
|
|
222
|
-
end
|
|
216
|
+
invite_key.keys
|
|
223
217
|
end
|
|
224
218
|
|
|
225
219
|
# Attempt to find a user by its email. If a record is not found,
|
|
@@ -233,7 +227,9 @@ module Devise
|
|
|
233
227
|
invite_key_array = invite_key_fields
|
|
234
228
|
attributes_hash = {}
|
|
235
229
|
invite_key_array.each do |k,v|
|
|
236
|
-
|
|
230
|
+
attribute = attributes.delete(k)
|
|
231
|
+
attribute = attribute.to_s.strip if strip_whitespace_keys.include?(k)
|
|
232
|
+
attributes_hash[k] = attribute
|
|
237
233
|
end
|
|
238
234
|
|
|
239
235
|
invitable = find_or_initialize_with_errors(invite_key_array, attributes_hash)
|
|
@@ -243,22 +239,20 @@ module Devise
|
|
|
243
239
|
invitable.skip_password = true
|
|
244
240
|
invitable.valid? if self.validate_on_invite
|
|
245
241
|
if invitable.new_record?
|
|
246
|
-
invitable.
|
|
242
|
+
invitable.clear_errors_on_valid_keys if !self.validate_on_invite
|
|
247
243
|
elsif !invitable.invited_to_sign_up? || !self.resend_invitation
|
|
248
244
|
invite_key_array.each do |key|
|
|
249
245
|
invitable.errors.add(key, :taken)
|
|
250
246
|
end
|
|
251
247
|
end
|
|
252
248
|
|
|
253
|
-
if
|
|
254
|
-
|
|
255
|
-
mail = invitable.invite!
|
|
256
|
-
end
|
|
249
|
+
yield invitable if block_given?
|
|
250
|
+
mail = invitable.invite! if invitable.errors.empty?
|
|
257
251
|
[invitable, mail]
|
|
258
252
|
end
|
|
259
253
|
|
|
260
254
|
def invite!(attributes={}, invited_by=nil, &block)
|
|
261
|
-
invitable, mail = _invite(attributes, invited_by, &block)
|
|
255
|
+
invitable, mail = _invite(attributes.with_indifferent_access, invited_by, &block)
|
|
262
256
|
invitable
|
|
263
257
|
end
|
|
264
258
|
|
|
@@ -273,8 +267,8 @@ module Devise
|
|
|
273
267
|
# error in invitation_token attribute.
|
|
274
268
|
# Attributes must contain invitation_token, password and confirmation
|
|
275
269
|
def accept_invitation!(attributes={})
|
|
276
|
-
|
|
277
|
-
invitable
|
|
270
|
+
original_token = attributes.delete(:invitation_token)
|
|
271
|
+
invitable = find_by_invitation_token(original_token, false)
|
|
278
272
|
if invitable.errors.empty?
|
|
279
273
|
invitable.assign_attributes(attributes)
|
|
280
274
|
invitable.accept_invitation!
|
|
@@ -282,6 +276,18 @@ module Devise
|
|
|
282
276
|
invitable
|
|
283
277
|
end
|
|
284
278
|
|
|
279
|
+
def find_by_invitation_token(original_token, only_valid)
|
|
280
|
+
invitation_token = Devise.token_generator.digest(self, :invitation_token, original_token)
|
|
281
|
+
|
|
282
|
+
invitable = find_or_initialize_with_error_by(:invitation_token, invitation_token)
|
|
283
|
+
if !invitable.persisted? && Devise.allow_insecure_token_lookup
|
|
284
|
+
invitable = find_or_initialize_with_error_by(:invitation_token, original_token)
|
|
285
|
+
end
|
|
286
|
+
invitable.errors.add(:invitation_token, :invalid) if invitable.invitation_token && invitable.persisted? && !invitable.valid_invitation?
|
|
287
|
+
invitable.invitation_token = original_token
|
|
288
|
+
invitable unless only_valid && invitable.errors.present?
|
|
289
|
+
end
|
|
290
|
+
|
|
285
291
|
# Generate a token checking if one does not already exist in the database.
|
|
286
292
|
def invitation_token
|
|
287
293
|
generate_token(:invitation_token)
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
module DeviseInvitable
|
|
2
2
|
module ParameterSanitizer
|
|
3
3
|
def invite
|
|
4
|
-
default_params.permit(
|
|
4
|
+
default_params.permit self.for(:invite)
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
def accept_invitation
|
|
8
|
-
default_params.permit(
|
|
8
|
+
default_params.permit self.for(:accept_invitation)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.included(base)
|
|
12
|
+
base.alias_method_chain :attributes_for, :invitable
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
def attributes_for_with_invitable(kind)
|
|
17
|
+
case kind
|
|
18
|
+
when :invite
|
|
19
|
+
resource_class.invite_key_fields
|
|
20
|
+
when :accept_invitation
|
|
21
|
+
[:password, :password_confirmation, :invitation_token]
|
|
22
|
+
else attributes_for_without_invitable(kind)
|
|
23
|
+
end
|
|
9
24
|
end
|
|
10
25
|
end
|
|
11
26
|
end
|
|
@@ -21,7 +21,7 @@ class DeviseInvitableAddTo<%= table_name.camelize %> < ActiveRecord::Migration
|
|
|
21
21
|
def down
|
|
22
22
|
change_table :<%= table_name %> do |t|
|
|
23
23
|
t.remove_references :invited_by, :polymorphic => true
|
|
24
|
-
t.remove :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token
|
|
24
|
+
t.remove :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
end
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
require 'integration_tests_helper'
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class InvitationRemoveTest < ActionDispatch::IntegrationTest
|
|
5
5
|
|
|
6
6
|
test 'invited user can choose to remove his account/invite' do
|
|
7
7
|
user = User.invite!(:email => "valid@email.com")
|
|
8
8
|
|
|
9
9
|
# remove!
|
|
10
|
-
visit remove_user_invitation_path(:invitation_token =>
|
|
10
|
+
visit remove_user_invitation_path(:invitation_token => Thread.current[:token])
|
|
11
11
|
assert_equal root_path, current_path
|
|
12
12
|
assert page.has_css?('p#notice', :text => 'Your invitation was removed.')
|
|
13
13
|
|
|
14
14
|
# try to remove again!
|
|
15
|
-
visit remove_user_invitation_path(:invitation_token =>
|
|
15
|
+
visit remove_user_invitation_path(:invitation_token => Thread.current[:token])
|
|
16
16
|
assert_equal root_path, current_path
|
|
17
17
|
assert page.has_css?('p#alert', :text => 'The invitation token provided is not valid!')
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
test 'accepted user cannot remove his account (by using the original invitation token)' do
|
|
21
21
|
user = User.invite!(:email => "valid@email.com")
|
|
22
|
-
saved_token =
|
|
22
|
+
saved_token = Thread.current[:token]
|
|
23
23
|
user.accept_invitation!
|
|
24
24
|
|
|
25
25
|
visit remove_user_invitation_path(:invitation_token => saved_token)
|
|
26
26
|
assert_equal root_path, current_path
|
|
27
27
|
assert page.has_css?('p#alert', :text => 'The invitation token provided is not valid!')
|
|
28
28
|
end
|
|
29
|
-
end
|
|
29
|
+
end
|
|
@@ -75,7 +75,7 @@ class InvitationTest < ActionDispatch::IntegrationTest
|
|
|
75
75
|
|
|
76
76
|
test 'not authenticated user with valid invitation token but invalid password should not be able to set his password' do
|
|
77
77
|
user = User.invite!(:email => "valid@email.com")
|
|
78
|
-
set_password :invitation_token =>
|
|
78
|
+
set_password :invitation_token => Thread.current[:token] do
|
|
79
79
|
fill_in 'Password confirmation', :with => 'other_password'
|
|
80
80
|
end
|
|
81
81
|
assert_equal user_invitation_path, current_path
|
|
@@ -85,7 +85,7 @@ class InvitationTest < ActionDispatch::IntegrationTest
|
|
|
85
85
|
|
|
86
86
|
test 'not authenticated user with valid data should be able to change his password' do
|
|
87
87
|
user = User.invite!(:email => "valid@email.com")
|
|
88
|
-
set_password :invitation_token =>
|
|
88
|
+
set_password :invitation_token => Thread.current[:token]
|
|
89
89
|
|
|
90
90
|
assert_equal root_path, current_path
|
|
91
91
|
assert page.has_css?('p#notice', :text => 'Your password was set successfully. You are now signed in.')
|
|
@@ -94,7 +94,7 @@ class InvitationTest < ActionDispatch::IntegrationTest
|
|
|
94
94
|
|
|
95
95
|
test 'after entering invalid data user should still be able to set his password' do
|
|
96
96
|
user = User.invite!(:email => "valid@email.com")
|
|
97
|
-
set_password :invitation_token =>
|
|
97
|
+
set_password :invitation_token => Thread.current[:token] do
|
|
98
98
|
fill_in 'Password confirmation', :with => 'other_password'
|
|
99
99
|
end
|
|
100
100
|
assert_equal user_invitation_path, current_path
|
|
@@ -108,7 +108,7 @@ class InvitationTest < ActionDispatch::IntegrationTest
|
|
|
108
108
|
|
|
109
109
|
test 'sign in user automatically after setting it\'s password' do
|
|
110
110
|
user = User.invite!(:email => "valid@email.com")
|
|
111
|
-
set_password :invitation_token =>
|
|
111
|
+
set_password :invitation_token => Thread.current[:token]
|
|
112
112
|
assert_equal root_path, current_path
|
|
113
113
|
end
|
|
114
114
|
|
|
@@ -119,8 +119,7 @@ class InvitationTest < ActionDispatch::IntegrationTest
|
|
|
119
119
|
fill_in 'user_email', :with => 'valid@email.com'
|
|
120
120
|
click_button 'Send me reset password instructions'
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
visit edit_user_password_path(:reset_password_token => user.reset_password_token)
|
|
122
|
+
visit edit_user_password_path(:reset_password_token => Thread.current[:token])
|
|
124
123
|
set_password :visit => false, :button => 'Change my password'
|
|
125
124
|
|
|
126
125
|
user.reload
|
|
@@ -53,7 +53,17 @@ class InvitationMailTest < ActionMailer::TestCase
|
|
|
53
53
|
|
|
54
54
|
test 'body should have link to confirm the account' do
|
|
55
55
|
host = ActionMailer::Base.default_url_options[:host]
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
body = mail.body.decoded
|
|
57
|
+
invitation_url_regexp = %r{<a href=\"http://#{host}/users/invitation/accept\?invitation_token=#{Thread.current[:token]}">}
|
|
58
|
+
assert_match invitation_url_regexp, body
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
test 'body should have link to confirm the account on resend' do
|
|
62
|
+
host = ActionMailer::Base.default_url_options[:host]
|
|
63
|
+
user
|
|
64
|
+
@user = User.find(user.id).invite!
|
|
65
|
+
body = mail.body.decoded
|
|
66
|
+
invitation_url_regexp = %r{<a href=\"http://#{host}/users/invitation/accept\?invitation_token=#{Thread.current[:token]}">}
|
|
67
|
+
assert_match invitation_url_regexp, body
|
|
58
68
|
end
|
|
59
69
|
end
|
|
@@ -11,18 +11,39 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
11
11
|
assert_nil new_user.invitation_token
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
test 'should not
|
|
14
|
+
test 'should not generate the raw invitation token after creating a record' do
|
|
15
|
+
assert_nil new_user.raw_invitation_token
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test 'should regenerate invitation token each time' do
|
|
15
19
|
user = new_user
|
|
16
20
|
user.invite!
|
|
17
21
|
token = user.invitation_token
|
|
18
22
|
assert_not_nil user.invitation_token
|
|
19
23
|
assert_not_nil user.invitation_created_at
|
|
20
24
|
3.times do
|
|
25
|
+
user = User.find(user.id)
|
|
21
26
|
user.invite!
|
|
22
|
-
|
|
27
|
+
assert_not_equal token, user.invitation_token
|
|
28
|
+
token = user.invitation_token
|
|
23
29
|
end
|
|
24
30
|
end
|
|
25
31
|
|
|
32
|
+
test 'should alias the invitation_token method with encrypted_invitation_token' do
|
|
33
|
+
user = new_user
|
|
34
|
+
user.invite!
|
|
35
|
+
assert_equal user.invitation_token, user.encrypted_invitation_token
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test 'should return the correct raw_invitation_token ' do
|
|
39
|
+
user = new_user
|
|
40
|
+
raw, enc = Devise.token_generator.generate(user.class, :invitation_token)
|
|
41
|
+
#stub the generator so the tokens are the same
|
|
42
|
+
Devise.token_generator.stubs(:generate).returns([raw, enc])
|
|
43
|
+
user.invite!
|
|
44
|
+
assert_equal user.raw_invitation_token, raw
|
|
45
|
+
end
|
|
46
|
+
|
|
26
47
|
test 'should set invitation created and sent at each time' do
|
|
27
48
|
user = new_user
|
|
28
49
|
user.invite!
|
|
@@ -32,22 +53,11 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
32
53
|
3.times do
|
|
33
54
|
user.invite!
|
|
34
55
|
assert_not_equal old_invitation_sent_at, user.invitation_sent_at
|
|
35
|
-
assert_not_equal old_invitation_created_at, user.
|
|
56
|
+
assert_not_equal old_invitation_created_at, user.invitation_created_at
|
|
36
57
|
user.update_attributes(:invitation_sent_at => old_invitation_sent_at, :invitation_created_at => old_invitation_created_at)
|
|
37
58
|
end
|
|
38
59
|
end
|
|
39
60
|
|
|
40
|
-
test 'should not regenerate invitation token even after the invitation token is not valid' do
|
|
41
|
-
User.stubs(:invite_for).returns(1.day)
|
|
42
|
-
user = new_user
|
|
43
|
-
user.invite!
|
|
44
|
-
token = user.invitation_token
|
|
45
|
-
user.invitation_created_at = 3.days.ago
|
|
46
|
-
user.save
|
|
47
|
-
user.invite!
|
|
48
|
-
assert_equal token, user.invitation_token
|
|
49
|
-
end
|
|
50
|
-
|
|
51
61
|
test 'should test invitation sent at with invite_for configuration value' do
|
|
52
62
|
user = User.invite!(:email => "valid@email.com")
|
|
53
63
|
|
|
@@ -87,18 +97,29 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
87
97
|
end
|
|
88
98
|
end
|
|
89
99
|
|
|
90
|
-
test 'should invite with
|
|
100
|
+
test 'should invite with multiple columns for invite key' do
|
|
91
101
|
User.stubs(:invite_key).returns(:email => Devise.email_regexp, :username => /\A.+\z/)
|
|
92
102
|
user = User.invite!(:email => "valid@email.com", :username => "name")
|
|
93
103
|
assert user.persisted?
|
|
94
104
|
assert user.errors.empty?
|
|
95
105
|
end
|
|
96
106
|
|
|
107
|
+
test 'should allow non-string columns for invite key' do
|
|
108
|
+
User.stubs(:invite_key).returns(:email => Devise.email_regexp, :profile_id => :present?.to_proc, :active => true)
|
|
109
|
+
user = User.invite!(:email => "valid@email.com", :profile_id => 1, :active => true)
|
|
110
|
+
assert user.persisted?
|
|
111
|
+
assert user.errors.empty?
|
|
112
|
+
end
|
|
113
|
+
|
|
97
114
|
test 'should not invite with some missing columns when invite key is an array' do
|
|
98
|
-
User.stubs(:invite_key).returns(:email => Devise.email_regexp, :username => /\A.+\z
|
|
115
|
+
User.stubs(:invite_key).returns(:email => Devise.email_regexp, :username => /\A.+\z/, :profile_id => :present?.to_proc, :active => true)
|
|
99
116
|
user = User.invite!(:email => "valid@email.com")
|
|
100
117
|
assert user.new_record?
|
|
101
118
|
assert user.errors.present?
|
|
119
|
+
assert user.errors[:username]
|
|
120
|
+
assert user.errors[:profile_id]
|
|
121
|
+
assert user.errors[:active]
|
|
122
|
+
assert user.errors[:email].empty?
|
|
102
123
|
end
|
|
103
124
|
|
|
104
125
|
test 'should return mail object' do
|
|
@@ -113,14 +134,14 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
113
134
|
|
|
114
135
|
test 'should set password and password confirmation from params' do
|
|
115
136
|
invited_user = User.invite!(:email => "valid@email.com")
|
|
116
|
-
user = User.accept_invitation!(:invitation_token =>
|
|
137
|
+
user = User.accept_invitation!(:invitation_token => Thread.current[:token], :password => '123456789', :password_confirmation => '123456789')
|
|
117
138
|
assert user.valid_password?('123456789')
|
|
118
139
|
end
|
|
119
140
|
|
|
120
141
|
test 'should set password and save the record' do
|
|
121
142
|
user = User.invite!(:email => "valid@email.com")
|
|
122
143
|
old_encrypted_password = user.encrypted_password
|
|
123
|
-
user = User.accept_invitation!(:invitation_token =>
|
|
144
|
+
user = User.accept_invitation!(:invitation_token => Thread.current[:token], :password => '123456789', :password_confirmation => '123456789')
|
|
124
145
|
assert_not_equal old_encrypted_password, user.encrypted_password
|
|
125
146
|
end
|
|
126
147
|
|
|
@@ -147,10 +168,14 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
147
168
|
test 'should clear invitation token while resetting the password' do
|
|
148
169
|
user = User.invite!(:email => "valid@email.com")
|
|
149
170
|
assert user.invited_to_sign_up?
|
|
150
|
-
user.
|
|
171
|
+
token, user.reset_password_token = Devise.token_generator.generate(User, :reset_password_token)
|
|
172
|
+
user.reset_password_sent_at = Time.now.utc
|
|
173
|
+
user.save
|
|
174
|
+
|
|
151
175
|
assert_present user.reset_password_token
|
|
152
176
|
assert_present user.invitation_token
|
|
153
|
-
User.reset_password_by_token(:reset_password_token =>
|
|
177
|
+
User.reset_password_by_token(:reset_password_token => token, :password => '123456789', :password_confirmation => '123456789')
|
|
178
|
+
assert_nil user.reload.reset_password_token
|
|
154
179
|
assert_nil user.reload.invitation_token
|
|
155
180
|
assert !user.invited_to_sign_up?
|
|
156
181
|
end
|
|
@@ -158,10 +183,14 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
158
183
|
test 'should not accept invitation on failing to reset the password' do
|
|
159
184
|
user = User.invite!(:email => "valid@email.com")
|
|
160
185
|
assert user.invited_to_sign_up?
|
|
161
|
-
user.
|
|
186
|
+
token, user.reset_password_token = Devise.token_generator.generate(User, :reset_password_token)
|
|
187
|
+
user.reset_password_sent_at = Time.now.utc
|
|
188
|
+
user.save
|
|
189
|
+
|
|
162
190
|
assert_present user.reset_password_token
|
|
163
191
|
assert_present user.invitation_token
|
|
164
|
-
User.reset_password_by_token(:reset_password_token =>
|
|
192
|
+
User.reset_password_by_token(:reset_password_token => token, :password => '123456789', :password_confirmation => '12345678')
|
|
193
|
+
assert_present user.reload.reset_password_token
|
|
165
194
|
assert_present user.reload.invitation_token
|
|
166
195
|
assert user.invited_to_sign_up?
|
|
167
196
|
end
|
|
@@ -169,10 +198,13 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
169
198
|
test 'should not set invitation_accepted_at if just resetting password' do
|
|
170
199
|
user = User.create!(:email => "valid@email.com", :password => "123456780")
|
|
171
200
|
assert !user.invited_to_sign_up?
|
|
172
|
-
user.
|
|
201
|
+
token, user.reset_password_token = Devise.token_generator.generate(User, :reset_password_token)
|
|
202
|
+
user.reset_password_sent_at = Time.now.utc
|
|
203
|
+
user.save
|
|
204
|
+
|
|
173
205
|
assert_present user.reset_password_token
|
|
174
206
|
assert_nil user.invitation_token
|
|
175
|
-
User.reset_password_by_token(:reset_password_token =>
|
|
207
|
+
User.reset_password_by_token(:reset_password_token => token, :password => '123456789', :password_confirmation => '123456789')
|
|
176
208
|
assert_nil user.reload.invitation_token
|
|
177
209
|
assert_nil user.reload.invitation_accepted_at
|
|
178
210
|
end
|
|
@@ -241,6 +273,9 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
241
273
|
user = User.invite!(:email => "valid@email.com")
|
|
242
274
|
assert_equal user, existing_user
|
|
243
275
|
assert_equal ['has already been taken'], user.errors[:email]
|
|
276
|
+
same_user = User.invite!("email" => "valid@email.com")
|
|
277
|
+
assert_equal same_user, existing_user
|
|
278
|
+
assert_equal ['has already been taken'], same_user.errors[:email]
|
|
244
279
|
end
|
|
245
280
|
|
|
246
281
|
test 'should return a record with errors if user with pending invitation was found by e-mail' do
|
|
@@ -297,7 +332,7 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
297
332
|
test 'should find a user to set his password based on invitation_token' do
|
|
298
333
|
user = new_user
|
|
299
334
|
user.invite!
|
|
300
|
-
invited_user = User.accept_invitation!(:invitation_token =>
|
|
335
|
+
invited_user = User.accept_invitation!(:invitation_token => Thread.current[:token])
|
|
301
336
|
assert_equal invited_user, user
|
|
302
337
|
end
|
|
303
338
|
|
|
@@ -318,7 +353,7 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
318
353
|
invited_user = User.invite!(:email => "valid@email.com")
|
|
319
354
|
invited_user.invitation_created_at = 2.days.ago
|
|
320
355
|
invited_user.save(:validate => false)
|
|
321
|
-
user = User.accept_invitation!(:invitation_token =>
|
|
356
|
+
user = User.accept_invitation!(:invitation_token => Thread.current[:token])
|
|
322
357
|
assert_equal user, invited_user
|
|
323
358
|
assert_equal ["is invalid"], user.errors[:invitation_token]
|
|
324
359
|
end
|
|
@@ -336,7 +371,7 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
336
371
|
user.invite!
|
|
337
372
|
|
|
338
373
|
invited_user = User.accept_invitation!(
|
|
339
|
-
:invitation_token =>
|
|
374
|
+
:invitation_token => Thread.current[:token],
|
|
340
375
|
:password => 'new_password',
|
|
341
376
|
:password_confirmation => 'new_password'
|
|
342
377
|
)
|
|
@@ -350,16 +385,34 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
350
385
|
user.invite!
|
|
351
386
|
|
|
352
387
|
invited_user = User.accept_invitation!(
|
|
353
|
-
:invitation_token =>
|
|
388
|
+
:invitation_token => Thread.current[:token],
|
|
354
389
|
:password => 'new_password',
|
|
355
390
|
:password_confirmation => 'new_password',
|
|
356
391
|
:username => 'a'*50
|
|
357
392
|
)
|
|
358
393
|
assert invited_user.errors[:username].present?
|
|
359
394
|
|
|
395
|
+
user.reload
|
|
360
396
|
assert !user.valid_password?('new_password')
|
|
361
397
|
end
|
|
362
398
|
|
|
399
|
+
test 'should set other attributes on accepting invitation' do
|
|
400
|
+
user = new_user(:password => nil, :password_confirmation => nil)
|
|
401
|
+
user.invite!
|
|
402
|
+
|
|
403
|
+
invited_user = User.accept_invitation!(
|
|
404
|
+
:invitation_token => Thread.current[:token],
|
|
405
|
+
:password => 'new_password',
|
|
406
|
+
:password_confirmation => 'new_password',
|
|
407
|
+
:username => 'a'
|
|
408
|
+
)
|
|
409
|
+
assert invited_user.errors[:username].blank?
|
|
410
|
+
|
|
411
|
+
user.reload
|
|
412
|
+
assert_equal 'a', user.username
|
|
413
|
+
assert user.valid_password?('new_password')
|
|
414
|
+
end
|
|
415
|
+
|
|
363
416
|
test 'should not confirm user on invite' do
|
|
364
417
|
user = new_user
|
|
365
418
|
|
|
@@ -478,8 +531,9 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
478
531
|
|
|
479
532
|
test "user.invite! should strip whitespace from the class's strip_whitespace_keys" do
|
|
480
533
|
# Devise default is email
|
|
481
|
-
user = User.invite!(:email => " valid@email.com ")
|
|
534
|
+
user = User.invite!(:email => " valid@email.com ", :active => true)
|
|
482
535
|
assert user.email == "valid@email.com"
|
|
536
|
+
assert user.active == true
|
|
483
537
|
end
|
|
484
538
|
|
|
485
539
|
test 'should pass validation before accept if field is required in post-invited instance' do
|
data/test/models_test.rb
CHANGED
|
@@ -70,5 +70,9 @@ class ModelsTest < ActiveSupport::TestCase
|
|
|
70
70
|
test 'invitable attributes' do
|
|
71
71
|
assert_nil User.new.invitation_token
|
|
72
72
|
assert_nil User.new.invitation_sent_at
|
|
73
|
+
#raw token
|
|
74
|
+
assert_nil User.new.raw_invitation_token
|
|
75
|
+
#encrypted token - alias to invitation token
|
|
76
|
+
assert_nil User.new.encrypted_invitation_token
|
|
73
77
|
end
|
|
74
78
|
end
|
|
@@ -26,15 +26,17 @@ class User < PARENT_MODEL_CLASS
|
|
|
26
26
|
field :invited_by_id, :type => Integer
|
|
27
27
|
field :invited_by_type, :type => String
|
|
28
28
|
|
|
29
|
-
|
|
30
29
|
field :username
|
|
30
|
+
field :profile_id
|
|
31
|
+
field :active
|
|
32
|
+
|
|
31
33
|
validates_presence_of :email
|
|
32
34
|
validates_presence_of :encrypted_password, :if => :password_required?
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
devise :database_authenticatable, :registerable, :validatable, :confirmable, :invitable, :recoverable
|
|
36
38
|
|
|
37
|
-
attr_accessor :callback_works, :bio
|
|
39
|
+
attr_accessor :callback_works, :bio, :token
|
|
38
40
|
validates :username, :length => { :maximum => 20 }
|
|
39
41
|
|
|
40
42
|
attr_accessor :testing_accepting_or_not_invited
|
|
@@ -48,4 +50,9 @@ class User < PARENT_MODEL_CLASS
|
|
|
48
50
|
after_invitation_accepted do |object|
|
|
49
51
|
object.callback_works = true
|
|
50
52
|
end
|
|
53
|
+
|
|
54
|
+
def send_devise_notification(method, raw, *args)
|
|
55
|
+
Thread.current[:token] = raw
|
|
56
|
+
super
|
|
57
|
+
end
|
|
51
58
|
end
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
# Use this hook to configure devise mailer, warden hooks and so forth.
|
|
2
2
|
# Many of these configuration options can be set straight in your model.
|
|
3
3
|
Devise.setup do |config|
|
|
4
|
+
# The secret key used by Devise. Devise uses this key to generate
|
|
5
|
+
# random tokens. Changing this key will render invalid all existing
|
|
6
|
+
# confirmation, reset password and unlock tokens in the database.
|
|
7
|
+
config.secret_key = 'e5151770530bba4c845256482be72bf598f723bebc057f4b8c15a7e63d7ffb61e7b8a0615e92a78127498ac509c43589b39bd13df397a4a2a7b3796c836e6ef8'
|
|
8
|
+
|
|
4
9
|
# ==> Mailer Configuration
|
|
5
10
|
# Configure the e-mail address which will be shown in Devise::Mailer,
|
|
6
|
-
# note that it will be overwritten if you use your own mailer class
|
|
11
|
+
# note that it will be overwritten if you use your own mailer class
|
|
12
|
+
# with default "from" parameter.
|
|
7
13
|
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
|
|
8
14
|
|
|
9
15
|
# Configure the class responsible to send e-mails.
|
metadata
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devise_invitable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
5
|
-
prerelease:
|
|
6
|
-
segments:
|
|
7
|
-
- 1
|
|
8
|
-
- 2
|
|
9
|
-
- 1
|
|
10
|
-
version: 1.2.1
|
|
4
|
+
version: 1.3.1
|
|
11
5
|
platform: ruby
|
|
12
6
|
authors:
|
|
13
7
|
- Sergio Cambra
|
|
@@ -15,21 +9,15 @@ autorequire:
|
|
|
15
9
|
bindir: bin
|
|
16
10
|
cert_chain: []
|
|
17
11
|
|
|
18
|
-
date: 2013-
|
|
12
|
+
date: 2013-11-05 00:00:00 Z
|
|
19
13
|
dependencies:
|
|
20
14
|
- !ruby/object:Gem::Dependency
|
|
21
15
|
name: bundler
|
|
22
16
|
prerelease: false
|
|
23
17
|
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
-
none: false
|
|
25
18
|
requirements:
|
|
26
19
|
- - ">="
|
|
27
20
|
- !ruby/object:Gem::Version
|
|
28
|
-
hash: 19
|
|
29
|
-
segments:
|
|
30
|
-
- 1
|
|
31
|
-
- 1
|
|
32
|
-
- 0
|
|
33
21
|
version: 1.1.0
|
|
34
22
|
type: :development
|
|
35
23
|
version_requirements: *id001
|
|
@@ -37,21 +25,12 @@ dependencies:
|
|
|
37
25
|
name: actionmailer
|
|
38
26
|
prerelease: false
|
|
39
27
|
requirement: &id002 !ruby/object:Gem::Requirement
|
|
40
|
-
none: false
|
|
41
28
|
requirements:
|
|
42
29
|
- - ">="
|
|
43
30
|
- !ruby/object:Gem::Version
|
|
44
|
-
hash: 3
|
|
45
|
-
segments:
|
|
46
|
-
- 3
|
|
47
|
-
- 2
|
|
48
|
-
- 6
|
|
49
31
|
version: 3.2.6
|
|
50
32
|
- - <
|
|
51
33
|
- !ruby/object:Gem::Version
|
|
52
|
-
hash: 9
|
|
53
|
-
segments:
|
|
54
|
-
- 5
|
|
55
34
|
version: "5"
|
|
56
35
|
type: :runtime
|
|
57
36
|
version_requirements: *id002
|
|
@@ -59,16 +38,10 @@ dependencies:
|
|
|
59
38
|
name: devise
|
|
60
39
|
prerelease: false
|
|
61
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
|
62
|
-
none: false
|
|
63
41
|
requirements:
|
|
64
|
-
- -
|
|
42
|
+
- - ">="
|
|
65
43
|
- !ruby/object:Gem::Version
|
|
66
|
-
|
|
67
|
-
segments:
|
|
68
|
-
- 3
|
|
69
|
-
- 0
|
|
70
|
-
- 0
|
|
71
|
-
version: 3.0.0
|
|
44
|
+
version: 3.1.0
|
|
72
45
|
type: :runtime
|
|
73
46
|
version_requirements: *id003
|
|
74
47
|
description: It adds support for send invitations by email (it requires to be authenticated) and accept the invitation by setting a password.
|
|
@@ -108,6 +81,7 @@ files:
|
|
|
108
81
|
- lib/generators/mongoid/devise_invitable_generator.rb
|
|
109
82
|
- LICENSE
|
|
110
83
|
- README.rdoc
|
|
84
|
+
- CHANGELOG
|
|
111
85
|
- test/functional/controller_helpers_test.rb
|
|
112
86
|
- test/functional/registrations_controller_test.rb
|
|
113
87
|
- test/generators/views_generator_test.rb
|
|
@@ -160,7 +134,9 @@ files:
|
|
|
160
134
|
- test/routes_test.rb
|
|
161
135
|
- test/test_helper.rb
|
|
162
136
|
homepage: https://github.com/scambra/devise_invitable
|
|
163
|
-
licenses:
|
|
137
|
+
licenses:
|
|
138
|
+
- MIT
|
|
139
|
+
metadata: {}
|
|
164
140
|
|
|
165
141
|
post_install_message:
|
|
166
142
|
rdoc_options:
|
|
@@ -170,33 +146,21 @@ rdoc_options:
|
|
|
170
146
|
require_paths:
|
|
171
147
|
- lib
|
|
172
148
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
173
|
-
none: false
|
|
174
149
|
requirements:
|
|
175
150
|
- - ">="
|
|
176
151
|
- !ruby/object:Gem::Version
|
|
177
|
-
hash: 59
|
|
178
|
-
segments:
|
|
179
|
-
- 1
|
|
180
|
-
- 8
|
|
181
|
-
- 6
|
|
182
152
|
version: 1.8.6
|
|
183
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
|
-
none: false
|
|
185
154
|
requirements:
|
|
186
155
|
- - ">="
|
|
187
156
|
- !ruby/object:Gem::Version
|
|
188
|
-
hash: 23
|
|
189
|
-
segments:
|
|
190
|
-
- 1
|
|
191
|
-
- 3
|
|
192
|
-
- 6
|
|
193
157
|
version: 1.3.6
|
|
194
158
|
requirements: []
|
|
195
159
|
|
|
196
160
|
rubyforge_project:
|
|
197
|
-
rubygems_version:
|
|
161
|
+
rubygems_version: 2.0.7
|
|
198
162
|
signing_key:
|
|
199
|
-
specification_version:
|
|
163
|
+
specification_version: 4
|
|
200
164
|
summary: An invitation strategy for Devise
|
|
201
165
|
test_files:
|
|
202
166
|
- test/functional/controller_helpers_test.rb
|