devise_invitable 1.5.3 → 1.5.5
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 +7 -7
- data/CHANGELOG +11 -0
- data/README.rdoc +6 -6
- data/app/controllers/devise/invitations_controller.rb +4 -0
- data/app/views/devise/mailer/invitation_instructions.html.erb +4 -0
- data/config/locales/en.yml +7 -0
- data/lib/devise_invitable/controllers/helpers.rb +0 -1
- data/lib/devise_invitable/model.rb +33 -16
- data/lib/devise_invitable/version.rb +1 -1
- data/test/mailers/invitation_mail_test.rb +26 -0
- data/test/model_tests_helper.rb +1 -0
- data/test/models/invitable_test.rb +30 -0
- data/test/rails_app/config/locales/en.yml +3 -0
- metadata +48 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
5
|
-
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c73f548d678402b25124902905d122de26316161
|
4
|
+
data.tar.gz: 39b1f217bf6a01ab772a462f5488f75a519b15fb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6150c3a9debc6a2974662801bff49a4bc3ab5ef1c6c24ca9a31d355d5633f48b591c99d80349a3feb4319b6bddf33ad5ae6159e2131fcd03b17aeed52b593f15
|
7
|
+
data.tar.gz: a6e3025090643913f77bcbb4d20c8a31db17573eb62e26a13256d6ffc83bc4812f0b84182c2e75456575761192a22b8f637be0f0c859e5dc315641491dd00b5f
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
- Ensure that all invited user passwords conform to a format
|
2
|
+
- Call set_minimum_password_length (if exists) on accept invitation as devise does
|
3
|
+
- Controllers inheriting from Devise::InvitationsController will now use 'devise.invitations' translations
|
4
|
+
when using Devise >= 3.5. See https://github.com/plataformatec/devise/pull/3407 for more details.
|
5
|
+
- Add invitation due date to mailer
|
6
|
+
|
7
|
+
= 1.5.3
|
8
|
+
|
9
|
+
- Fix #585, avoid generating new password if there already is a encrypted one
|
10
|
+
- Give error if trying to register with a registered email
|
11
|
+
|
1
12
|
= 1.5.2
|
2
13
|
|
3
14
|
- Fix #571, accept invitation when password changes only if reset_password_token was present
|
data/README.rdoc
CHANGED
@@ -185,7 +185,7 @@ To change behaviour of inviting or accepting users, you can simply override two
|
|
185
185
|
# should return an instance of resource class
|
186
186
|
def invite_resource
|
187
187
|
## skip sending emails on invite
|
188
|
-
|
188
|
+
super do |u|
|
189
189
|
u.skip_invitation = true
|
190
190
|
end
|
191
191
|
end
|
@@ -247,21 +247,21 @@ the value is temporarily available when you invite a user and will be decrypted
|
|
247
247
|
|
248
248
|
accept_user_invitation_url(:invitation_token => user.raw_invitation_token)
|
249
249
|
|
250
|
-
When skip_invitation is used, you must also then set the invitation_sent_at field when the user is sent their
|
251
|
-
token. Failure to do so will yield
|
250
|
+
When <tt>skip_invitation</tt> is used, you must also then set the <tt>invitation_sent_at</tt> field when the user is sent their
|
251
|
+
token. Failure to do so will yield <tt>Invalid invitation token</tt> error when the user attempts to accept the invite.
|
252
252
|
You can set it like so:
|
253
253
|
|
254
254
|
user.deliver_invitation
|
255
255
|
|
256
|
-
You can add
|
256
|
+
You can add <tt>:skip_invitation</tt> to attributes hash if <tt>skip_invitation</tt> is added to <tt>attr_accessible</tt>.
|
257
257
|
|
258
258
|
User.invite!(:email => "new_user@example.com", :name => "John Doe", :skip_invitation => true)
|
259
259
|
# => the record will be created, but the invitation email will not be sent
|
260
260
|
|
261
|
-
|
261
|
+
<tt>skip_invitation</tt> skips sending the email, but sets <tt>invitation_token</tt>, so <tt>invited_to_sign_up?</tt> on the
|
262
262
|
resulting user returns true.
|
263
263
|
|
264
|
-
To check if a
|
264
|
+
To check if a particular user is created by invitation, irrespective to state of invitation one can use <tt>created_by_invite?</tt>
|
265
265
|
|
266
266
|
**Warning**
|
267
267
|
|
@@ -31,6 +31,7 @@ class Devise::InvitationsController < DeviseController
|
|
31
31
|
|
32
32
|
# GET /resource/invitation/accept?invitation_token=abcdef
|
33
33
|
def edit
|
34
|
+
set_minimum_password_length if respond_to? :set_minimum_password_length
|
34
35
|
resource.invitation_token = params[:invitation_token]
|
35
36
|
render :edit
|
36
37
|
end
|
@@ -103,5 +104,8 @@ class Devise::InvitationsController < DeviseController
|
|
103
104
|
devise_parameter_sanitizer.sanitize(:accept_invitation)
|
104
105
|
end
|
105
106
|
|
107
|
+
def translation_scope
|
108
|
+
'devise.invitations'
|
109
|
+
end
|
106
110
|
end
|
107
111
|
|
@@ -4,4 +4,8 @@
|
|
4
4
|
|
5
5
|
<p><%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, :invitation_token => @token) %></p>
|
6
6
|
|
7
|
+
<% if @resource.invitation_due_at %>
|
8
|
+
<p><%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %></p>
|
9
|
+
<% end %>
|
10
|
+
|
7
11
|
<p><%= t("devise.mailer.invitation_instructions.ignore").html_safe %></p>
|
data/config/locales/en.yml
CHANGED
@@ -21,4 +21,11 @@ en:
|
|
21
21
|
hello: "Hello %{email}"
|
22
22
|
someone_invited_you: "Someone has invited you to %{url}, you can accept it through the link below."
|
23
23
|
accept: "Accept invitation"
|
24
|
+
accept_until: "This invitation will be due in %{due_date}."
|
24
25
|
ignore: "If you don't want to accept the invitation, please ignore this email.<br />Your account won't be created until you access the link above and set your password."
|
26
|
+
time:
|
27
|
+
formats:
|
28
|
+
devise:
|
29
|
+
mailer:
|
30
|
+
invitation_instructions:
|
31
|
+
accept_until_format: "%B %d, %Y %I:%M %p"
|
@@ -34,9 +34,9 @@ module Devise
|
|
34
34
|
else
|
35
35
|
{:polymorphic => true}
|
36
36
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
if fk = Devise.invited_by_foreign_key
|
38
|
+
belongs_to_options[:foreign_key] = fk
|
39
|
+
end
|
40
40
|
if defined?(ActiveRecord) && defined?(ActiveRecord::Base) && self < ActiveRecord::Base
|
41
41
|
counter_cache = Devise.invited_by_counter_cache
|
42
42
|
belongs_to_options.merge! :counter_cache => counter_cache if counter_cache
|
@@ -109,8 +109,8 @@ module Devise
|
|
109
109
|
end
|
110
110
|
|
111
111
|
# Reset invitation token and send invitation again
|
112
|
-
def invite!(invited_by = nil)
|
113
|
-
# This is an order-dependant assignment, this can't be moved
|
112
|
+
def invite!(invited_by = nil, options = {})
|
113
|
+
# This is an order-dependant assignment, this can't be moved
|
114
114
|
was_invited = invited_to_sign_up?
|
115
115
|
|
116
116
|
# Required to workaround confirmable model's confirmation_required? method
|
@@ -131,7 +131,7 @@ module Devise
|
|
131
131
|
|
132
132
|
if save(:validate => false)
|
133
133
|
self.invited_by.decrement_invitation_limit! if !was_invited and self.invited_by.present?
|
134
|
-
deliver_invitation unless skip_invitation
|
134
|
+
deliver_invitation(options) unless skip_invitation
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
@@ -164,10 +164,10 @@ module Devise
|
|
164
164
|
end
|
165
165
|
|
166
166
|
# Deliver the invitation email
|
167
|
-
def deliver_invitation
|
167
|
+
def deliver_invitation(options = {})
|
168
168
|
generate_invitation_token! unless @raw_invitation_token
|
169
169
|
self.update_attribute :invitation_sent_at, Time.now.utc unless self.invitation_sent_at
|
170
|
-
send_devise_notification(:invitation_instructions, @raw_invitation_token)
|
170
|
+
send_devise_notification(:invitation_instructions, @raw_invitation_token, options)
|
171
171
|
end
|
172
172
|
|
173
173
|
# provide alias to the encrypted invitation_token stored by devise
|
@@ -179,6 +179,13 @@ module Devise
|
|
179
179
|
respond_to?(:confirmation_required?, true) && confirmation_required?
|
180
180
|
end
|
181
181
|
|
182
|
+
def invitation_due_at
|
183
|
+
return nil unless self.class.invite_for
|
184
|
+
|
185
|
+
time = self.invitation_created_at || self.invitation_sent_at
|
186
|
+
time + self.class.invite_for
|
187
|
+
end
|
188
|
+
|
182
189
|
protected
|
183
190
|
|
184
191
|
def block_from_invitation?
|
@@ -242,7 +249,7 @@ module Devise
|
|
242
249
|
# email is resent unless resend_invitation is set to false.
|
243
250
|
# Attributes must contain the user's email, other attributes will be
|
244
251
|
# set in the record
|
245
|
-
def _invite(attributes={}, invited_by=nil, &block)
|
252
|
+
def _invite(attributes={}, invited_by=nil, options = {}, &block)
|
246
253
|
invite_key_array = invite_key_fields
|
247
254
|
attributes_hash = {}
|
248
255
|
invite_key_array.each do |k,v|
|
@@ -255,7 +262,7 @@ module Devise
|
|
255
262
|
invitable.assign_attributes(attributes)
|
256
263
|
invitable.invited_by = invited_by
|
257
264
|
unless invitable.password || invitable.encrypted_password.present?
|
258
|
-
invitable.password =
|
265
|
+
invitable.password = random_password
|
259
266
|
end
|
260
267
|
|
261
268
|
invitable.valid? if self.validate_on_invite
|
@@ -268,16 +275,16 @@ module Devise
|
|
268
275
|
end
|
269
276
|
|
270
277
|
yield invitable if block_given?
|
271
|
-
mail = invitable.invite! if invitable.errors.empty?
|
278
|
+
mail = invitable.invite!(nil, options) if invitable.errors.empty?
|
272
279
|
[invitable, mail]
|
273
280
|
end
|
274
281
|
|
275
|
-
def invite!(attributes={}, invited_by=nil, &block)
|
276
|
-
_invite(attributes.with_indifferent_access, invited_by, &block).first
|
282
|
+
def invite!(attributes={}, invited_by=nil, options = {}, &block)
|
283
|
+
_invite(attributes.with_indifferent_access, invited_by, options, &block).first
|
277
284
|
end
|
278
285
|
|
279
|
-
def invite_mail!(attributes={}, invited_by=nil, &block)
|
280
|
-
_invite(attributes, invited_by, &block).last
|
286
|
+
def invite_mail!(attributes={}, invited_by=nil, options = {}, &block)
|
287
|
+
_invite(attributes, invited_by, options, &block).last
|
281
288
|
end
|
282
289
|
|
283
290
|
# Attempt to find a user by it's invitation_token to set it's password.
|
@@ -320,8 +327,18 @@ module Devise
|
|
320
327
|
Devise::Models.config(self, :resend_invitation)
|
321
328
|
Devise::Models.config(self, :allow_insecure_sign_in_after_accept)
|
322
329
|
|
330
|
+
private
|
331
|
+
|
332
|
+
# The random password, as set after an invitation, must conform
|
333
|
+
# to any password format validation rules of the application.
|
334
|
+
# This default fixes the most common scenarios: Passwords must contain
|
335
|
+
# lower + upper case, a digit and a symbol.
|
336
|
+
# For more unusual rules, this method can be overridden.
|
337
|
+
def random_password
|
338
|
+
"aA1!" + Devise.friendly_token[0, 20]
|
339
|
+
end
|
340
|
+
|
323
341
|
end
|
324
342
|
end
|
325
343
|
end
|
326
344
|
end
|
327
|
-
|
@@ -66,4 +66,30 @@ class InvitationMailTest < ActionMailer::TestCase
|
|
66
66
|
invitation_url_regexp = %r{<a href=\"http://#{host}/users/invitation/accept\?invitation_token=#{Thread.current[:token]}">}
|
67
67
|
assert_match invitation_url_regexp, body
|
68
68
|
end
|
69
|
+
|
70
|
+
test 'body should have invitation due date when it exists' do
|
71
|
+
host = ActionMailer::Base.default_url_options[:host]
|
72
|
+
user
|
73
|
+
body = mail.body.decoded
|
74
|
+
|
75
|
+
due_date_regexp = %r{#{I18n.l user.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format' }}
|
76
|
+
assert_match due_date_regexp, body
|
77
|
+
end
|
78
|
+
|
79
|
+
test 'options are passed to the delivery method' do
|
80
|
+
class CustomMailer < Devise::Mailer
|
81
|
+
class << self
|
82
|
+
def invitation_instructions(record, name, options = {})
|
83
|
+
fail 'Options not as expected' unless options[:invited_at].is_a?(Time)
|
84
|
+
new(record, name, options)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(*args); end
|
89
|
+
def deliver; end
|
90
|
+
end
|
91
|
+
Devise.mailer = CustomMailer
|
92
|
+
|
93
|
+
User.invite!({ email: 'valid@email.com' }, nil, { invited_at: Time.now })
|
94
|
+
end
|
69
95
|
end
|
data/test/model_tests_helper.rb
CHANGED
@@ -122,6 +122,22 @@ class InvitableTest < ActiveSupport::TestCase
|
|
122
122
|
assert !user.valid_invitation?
|
123
123
|
end
|
124
124
|
|
125
|
+
test 'should return token validity when there is invite_for' do
|
126
|
+
User.stubs(:invite_for).returns(1.day)
|
127
|
+
user = User.invite!(:email => "valid@email.com")
|
128
|
+
sent_at = user.invitation_created_at || user.invitation_sent_at
|
129
|
+
valid_until = sent_at + User.invite_for
|
130
|
+
|
131
|
+
assert_equal user.invitation_due_at, valid_until
|
132
|
+
end
|
133
|
+
|
134
|
+
test 'should return nil as token validity when there is not invite_for' do
|
135
|
+
User.stubs(:invite_for).returns(nil)
|
136
|
+
user = User.invite!(:email => "valid@email.com")
|
137
|
+
|
138
|
+
assert_equal user.invitation_due_at, nil
|
139
|
+
end
|
140
|
+
|
125
141
|
test 'should never generate the same invitation token for different users' do
|
126
142
|
invitation_tokens = []
|
127
143
|
3.times do
|
@@ -657,4 +673,18 @@ class InvitableTest < ActiveSupport::TestCase
|
|
657
673
|
retval = user.reset_password!('anewpassword', 'anewpassword')
|
658
674
|
assert_equal true, retval
|
659
675
|
end
|
676
|
+
|
677
|
+
test 'should set initial password with variety of characters' do
|
678
|
+
PASSWORD_FORMAT = /\A
|
679
|
+
(?=.*\d) # Must contain a digit
|
680
|
+
(?=.*[a-z]) # Must contain a lower case character
|
681
|
+
(?=.*[A-Z]) # Must contain an upper case character
|
682
|
+
(?=.*[[:^alnum:]]) # Must contain a symbol
|
683
|
+
/x
|
684
|
+
User.stubs(:invite_key).returns(:password => PASSWORD_FORMAT)
|
685
|
+
Devise.stubs(:friendly_token).returns('onlylowercaseletters')
|
686
|
+
user = User.invite!(:email => "valid@email.com")
|
687
|
+
assert user.persisted?
|
688
|
+
assert user.errors.empty?
|
689
|
+
end
|
660
690
|
end
|
metadata
CHANGED
@@ -1,71 +1,59 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_invitable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.5.5
|
5
5
|
platform: ruby
|
6
|
-
authors:
|
6
|
+
authors:
|
7
7
|
- Sergio Cambra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
|
12
|
+
date: 2015-12-17 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.1.0
|
20
16
|
type: :development
|
21
17
|
prerelease: false
|
22
|
-
|
23
|
-
requirements:
|
24
|
-
- -
|
25
|
-
- !ruby/object:Gem::Version
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
26
22
|
version: 1.1.0
|
27
|
-
|
23
|
+
version_requirements: *id001
|
24
|
+
- !ruby/object:Gem::Dependency
|
28
25
|
name: actionmailer
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 3.2.6
|
34
|
-
- - <
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: '5'
|
37
26
|
type: :runtime
|
38
27
|
prerelease: false
|
39
|
-
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
28
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
43
32
|
version: 3.2.6
|
44
33
|
- - <
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version:
|
47
|
-
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "5"
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
48
38
|
name: devise
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - '>='
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 3.2.0
|
54
39
|
type: :runtime
|
55
40
|
prerelease: false
|
56
|
-
|
57
|
-
requirements:
|
58
|
-
- -
|
59
|
-
- !ruby/object:Gem::Version
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
60
45
|
version: 3.2.0
|
61
|
-
|
62
|
-
|
63
|
-
email:
|
46
|
+
version_requirements: *id003
|
47
|
+
description: It adds support for send invitations by email (it requires to be authenticated) and accept the invitation by setting a password.
|
48
|
+
email:
|
64
49
|
- sergio@entrecables.com
|
65
50
|
executables: []
|
51
|
+
|
66
52
|
extensions: []
|
53
|
+
|
67
54
|
extra_rdoc_files: []
|
68
|
-
|
55
|
+
|
56
|
+
files:
|
69
57
|
- CHANGELOG
|
70
58
|
- LICENSE
|
71
59
|
- README.rdoc
|
@@ -146,33 +134,35 @@ files:
|
|
146
134
|
- test/routes_test.rb
|
147
135
|
- test/test_helper.rb
|
148
136
|
homepage: https://github.com/scambra/devise_invitable
|
149
|
-
licenses:
|
137
|
+
licenses:
|
150
138
|
- MIT
|
151
139
|
metadata: {}
|
140
|
+
|
152
141
|
post_install_message:
|
153
|
-
rdoc_options:
|
142
|
+
rdoc_options:
|
154
143
|
- --main
|
155
144
|
- README.rdoc
|
156
145
|
- --charset=UTF-8
|
157
|
-
require_paths:
|
146
|
+
require_paths:
|
158
147
|
- lib
|
159
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
-
requirements:
|
161
|
-
- -
|
162
|
-
- !ruby/object:Gem::Version
|
148
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
163
152
|
version: 1.8.6
|
164
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
-
requirements:
|
166
|
-
- -
|
167
|
-
- !ruby/object:Gem::Version
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - ">="
|
156
|
+
- !ruby/object:Gem::Version
|
168
157
|
version: 1.3.6
|
169
158
|
requirements: []
|
159
|
+
|
170
160
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.4.
|
161
|
+
rubygems_version: 2.4.6
|
172
162
|
signing_key:
|
173
163
|
specification_version: 4
|
174
164
|
summary: An invitation strategy for Devise
|
175
|
-
test_files:
|
165
|
+
test_files:
|
176
166
|
- test/functional/controller_helpers_test.rb
|
177
167
|
- test/functional/registrations_controller_test.rb
|
178
168
|
- test/generators/views_generator_test.rb
|