devise_invitable 3.0.4 → 3.1.0
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +259 -23
- data/app/controllers/devise/invitations_controller.rb +2 -1
- data/app/controllers/devise_invitable/registrations_controller.rb +1 -1
- data/lib/devise_invitable/acceptance_token.rb +58 -0
- data/lib/devise_invitable/invitation.rb +26 -5
- data/lib/devise_invitable/invitation_delivery.rb +114 -0
- data/lib/devise_invitable/invitation_delivery_job.rb +15 -0
- data/lib/devise_invitable/models.rb +160 -35
- data/lib/devise_invitable/version.rb +1 -1
- data/lib/devise_invitable.rb +42 -2
- data/lib/generators/devise_invitable/install_generator.rb +21 -0
- data/test/integration/invitation_test.rb +26 -0
- data/test/jobs/invitation_delivery_job_test.rb +138 -0
- data/test/lazy_loading_test.rb +17 -0
- data/test/mailers/invitation_mail_test.rb +9 -5
- data/test/models/invitable_test.rb +61 -7
- data/test/models/separate_invitations_test.rb +144 -3
- data/test/models_test.rb +17 -0
- data/test/rails_app/app/models/user.rb +4 -1
- data/test/rails_app/db/migrate/20261103170000_add_options_to_users.rb +5 -0
- metadata +10 -1
|
@@ -55,11 +55,12 @@ class InvitationMailTest < ActionMailer::TestCase
|
|
|
55
55
|
test 'body should have link to confirm the account' do
|
|
56
56
|
host = ActionMailer::Base.default_url_options[:host]
|
|
57
57
|
body = mail.html_part.body.decoded
|
|
58
|
-
|
|
58
|
+
token = Regexp.escape(ERB::Util.url_encode(Thread.current[:token]))
|
|
59
|
+
invitation_url_regexp = %r{<a href=\"http://#{host}/users/invitation/accept\?invitation_token=#{token}">}
|
|
59
60
|
assert_match invitation_url_regexp, body
|
|
60
61
|
|
|
61
62
|
body = mail.text_part.body.decoded
|
|
62
|
-
invitation_url_regexp = %r{http://#{host}/users/invitation/accept\?invitation_token=#{
|
|
63
|
+
invitation_url_regexp = %r{http://#{host}/users/invitation/accept\?invitation_token=#{token}}
|
|
63
64
|
assert_match invitation_url_regexp, body
|
|
64
65
|
end
|
|
65
66
|
|
|
@@ -68,11 +69,12 @@ class InvitationMailTest < ActionMailer::TestCase
|
|
|
68
69
|
user
|
|
69
70
|
@user = User.find(user.id).invite!
|
|
70
71
|
body = mail.html_part.body.decoded
|
|
71
|
-
|
|
72
|
+
token = Regexp.escape(ERB::Util.url_encode(Thread.current[:token]))
|
|
73
|
+
invitation_url_regexp = %r{<a href=\"http://#{host}/users/invitation/accept\?invitation_token=#{token}">}
|
|
72
74
|
assert_match invitation_url_regexp, body
|
|
73
75
|
|
|
74
76
|
body = mail.text_part.body.decoded
|
|
75
|
-
invitation_url_regexp = %r{http://#{host}/users/invitation/accept\?invitation_token=#{
|
|
77
|
+
invitation_url_regexp = %r{http://#{host}/users/invitation/accept\?invitation_token=#{token}}
|
|
76
78
|
assert_match invitation_url_regexp, body
|
|
77
79
|
end
|
|
78
80
|
|
|
@@ -105,6 +107,8 @@ class InvitationMailTest < ActionMailer::TestCase
|
|
|
105
107
|
end
|
|
106
108
|
Devise.mailer = 'InvitationMailTest::CustomMailer'
|
|
107
109
|
|
|
108
|
-
|
|
110
|
+
assert_nothing_raised do
|
|
111
|
+
User.invite!({ email: 'valid@email.com' }, nil, { invited_at: Time.now })
|
|
112
|
+
end
|
|
109
113
|
end
|
|
110
114
|
end
|
|
@@ -27,13 +27,13 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
test 'should update the invitations count counter cache' do
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
assert_equal current_user.reload.invitations_count, 2
|
|
30
|
+
skip unless defined?(ActiveRecord)
|
|
31
|
+
|
|
32
|
+
current_user = new_user
|
|
33
|
+
2.times do |index|
|
|
34
|
+
User.invite!({ email: "valid#{index}@email.com" }, current_user)
|
|
36
35
|
end
|
|
36
|
+
assert_equal current_user.reload.invitations_count, 2
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
test 'should not generate the raw invitation token after creating a record' do
|
|
@@ -92,7 +92,61 @@ class InvitableTest < ActiveSupport::TestCase
|
|
|
92
92
|
# stub the generator so the tokens are the same
|
|
93
93
|
Devise.token_generator.stubs(:generate).returns([raw, enc])
|
|
94
94
|
user.invite!
|
|
95
|
-
|
|
95
|
+
payload = DeviseInvitable::AcceptanceToken.decode(user.raw_invitation_token)
|
|
96
|
+
|
|
97
|
+
refute_includes user.raw_invitation_token, user.email
|
|
98
|
+
assert_equal raw, payload[:raw_token]
|
|
99
|
+
assert_equal({ 'email' => user.email }, payload[:invite_key].to_h.stringify_keys)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
test 'should reject a tampered encrypted invitation token' do
|
|
103
|
+
user = User.invite!(email: 'valid@email.com')
|
|
104
|
+
token = user.raw_invitation_token.dup
|
|
105
|
+
token[-1] = token[-1] == 'a' ? 'b' : 'a'
|
|
106
|
+
|
|
107
|
+
invited_user = User.accept_invitation!(invitation_token: token)
|
|
108
|
+
|
|
109
|
+
assert_equal [{ error: :invalid }], invited_user.errors.details[:invitation_token]
|
|
110
|
+
assert_predicate user.reload.current_invitation, :pending?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
test 'should accept a legacy raw token with plaintext invite keys' do
|
|
114
|
+
raw, encrypted = Devise.token_generator.generate(DeviseInvitable::Invitation, :invitation_token)
|
|
115
|
+
invitation = DeviseInvitable::Invitation.create!(
|
|
116
|
+
invitable_type: 'User',
|
|
117
|
+
invitation_token: encrypted,
|
|
118
|
+
invitation_created_at: Time.now.utc,
|
|
119
|
+
invitation_sent_at: Time.now.utc,
|
|
120
|
+
invite_key: { email: 'legacy@email.com' }
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
invited_user = User.accept_invitation!(
|
|
124
|
+
invitation_token: raw,
|
|
125
|
+
password: '123456789',
|
|
126
|
+
password_confirmation: '123456789'
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
assert_predicate invited_user, :persisted?
|
|
130
|
+
assert_equal 'legacy@email.com', invited_user.email
|
|
131
|
+
assert_equal invited_user, invitation.reload.invitable
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
test 'should restore placeholder invite keys from the encrypted token' do
|
|
135
|
+
user = User.invite!(email: 'private@email.com', skip_invitation: true)
|
|
136
|
+
acceptance_token = user.raw_invitation_token
|
|
137
|
+
invitation = user.current_invitation
|
|
138
|
+
invite_key_digest = invitation.invite_key_digest
|
|
139
|
+
user.update_attribute(:email, nil)
|
|
140
|
+
|
|
141
|
+
invited_user = User.accept_invitation!(
|
|
142
|
+
invitation_token: acceptance_token,
|
|
143
|
+
password: '123456789',
|
|
144
|
+
password_confirmation: '123456789'
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
assert_equal 'private@email.com', invited_user.email
|
|
148
|
+
assert_empty invitation.reload.invite_key
|
|
149
|
+
assert_equal invite_key_digest, invitation.invite_key_digest
|
|
96
150
|
end
|
|
97
151
|
|
|
98
152
|
test 'should set invitation created and sent at each time' do
|
|
@@ -4,11 +4,15 @@ require 'model_tests_helper'
|
|
|
4
4
|
class SeparateInvitationsTest < ActiveSupport::TestCase
|
|
5
5
|
setup do
|
|
6
6
|
@create_resource_on_invitation = User.create_resource_on_invitation
|
|
7
|
+
@store_invite_keys_until_delivery = User.store_invite_keys_until_delivery
|
|
8
|
+
@supersede_other_invitations_on_accept = User.supersede_other_invitations_on_accept
|
|
7
9
|
DeviseInvitable::Invitation.delete_all
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
teardown do
|
|
11
13
|
User.create_resource_on_invitation = @create_resource_on_invitation
|
|
14
|
+
User.store_invite_keys_until_delivery = @store_invite_keys_until_delivery
|
|
15
|
+
User.supersede_other_invitations_on_accept = @supersede_other_invitations_on_accept
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
test 'an invitation can be persisted without creating a resource' do
|
|
@@ -20,7 +24,9 @@ class SeparateInvitationsTest < ActiveSupport::TestCase
|
|
|
20
24
|
|
|
21
25
|
assert_predicate invited, :new_record?
|
|
22
26
|
assert_equal 0, User.where(email: 'deferred@example.com').count
|
|
23
|
-
|
|
27
|
+
assert_empty invitation.invite_key
|
|
28
|
+
payload = DeviseInvitable::AcceptanceToken.decode(invited.raw_invitation_token)
|
|
29
|
+
assert_equal({ 'email' => 'deferred@example.com' }, payload[:invite_key].to_h.stringify_keys)
|
|
24
30
|
assert_nil invitation.invitable_id
|
|
25
31
|
assert_nil invitation.resource_created_at
|
|
26
32
|
assert_includes User.no_active_invitation, registered
|
|
@@ -28,18 +34,21 @@ class SeparateInvitationsTest < ActiveSupport::TestCase
|
|
|
28
34
|
|
|
29
35
|
test 'an unsent resource-less invitation can be delivered later' do
|
|
30
36
|
User.create_resource_on_invitation = false
|
|
37
|
+
User.store_invite_keys_until_delivery = true
|
|
31
38
|
User.stubs(:invite_for).returns(1.day)
|
|
32
39
|
|
|
33
40
|
invited = User.invite!(email: 'deferred@example.com', skip_invitation: true)
|
|
34
|
-
invitation = invited.current_invitation
|
|
41
|
+
invitation = DeviseInvitable::Invitation.find(invited.current_invitation.id)
|
|
35
42
|
invitation.update!(invitation_created_at: 2.days.ago)
|
|
36
43
|
|
|
37
44
|
assert_nil invitation.invitation_sent_at
|
|
45
|
+
assert_equal({ 'email' => 'deferred@example.com' }, invitation.invite_key.to_h.stringify_keys)
|
|
38
46
|
assert_difference('ActionMailer::Base.deliveries.size', 1) do
|
|
39
47
|
invitation.reload.deliver
|
|
40
48
|
end
|
|
41
49
|
|
|
42
50
|
assert_predicate invitation.reload, :invitation_sent_at
|
|
51
|
+
assert_empty invitation.invite_key
|
|
43
52
|
assert invitation.invitation_period_valid?(1.day)
|
|
44
53
|
assert_equal ['deferred@example.com'], ActionMailer::Base.deliveries.last.to
|
|
45
54
|
|
|
@@ -64,12 +73,30 @@ class SeparateInvitationsTest < ActiveSupport::TestCase
|
|
|
64
73
|
|
|
65
74
|
test 'a failed later delivery remains unsent and can be retried' do
|
|
66
75
|
User.create_resource_on_invitation = false
|
|
76
|
+
User.store_invite_keys_until_delivery = true
|
|
67
77
|
invited = User.invite!(email: 'retry@example.com', skip_invitation: true)
|
|
68
|
-
invitation = invited.current_invitation.
|
|
78
|
+
invitation = DeviseInvitable::Invitation.find(invited.current_invitation.id)
|
|
69
79
|
User.any_instance.stubs(:send_devise_notification).raises('delivery failed')
|
|
70
80
|
|
|
71
81
|
assert_raises(RuntimeError) { invitation.deliver }
|
|
72
82
|
assert_nil invitation.reload.invitation_sent_at
|
|
83
|
+
assert_equal({ 'email' => 'retry@example.com' }, invitation.invite_key.to_h.stringify_keys)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
test 'the sent timestamp is available while rendering but saved after delivery' do
|
|
87
|
+
User.create_resource_on_invitation = false
|
|
88
|
+
User.store_invite_keys_until_delivery = true
|
|
89
|
+
invited = User.invite!(email: 'timestamp@example.com', skip_invitation: true)
|
|
90
|
+
invitation = DeviseInvitable::Invitation.find(invited.current_invitation.id)
|
|
91
|
+
|
|
92
|
+
User.any_instance.stubs(:send_devise_notification).with do
|
|
93
|
+
assert_predicate invitation, :invitation_sent_at
|
|
94
|
+
assert_nil DeviseInvitable::Invitation.find(invitation.id).invitation_sent_at
|
|
95
|
+
true
|
|
96
|
+
end.returns(:delivery)
|
|
97
|
+
|
|
98
|
+
assert_equal :delivery, invitation.deliver
|
|
99
|
+
assert_predicate invitation.reload, :invitation_sent_at
|
|
73
100
|
end
|
|
74
101
|
|
|
75
102
|
test 'accepting one of multiple invitations creates the resource and supersedes the others' do
|
|
@@ -97,6 +124,120 @@ class SeparateInvitationsTest < ActiveSupport::TestCase
|
|
|
97
124
|
assert_equal user, first.invitable
|
|
98
125
|
end
|
|
99
126
|
|
|
127
|
+
test 'multiple invitations can be accepted independently without changing the password' do
|
|
128
|
+
User.create_resource_on_invitation = false
|
|
129
|
+
User.supersede_other_invitations_on_accept = false
|
|
130
|
+
|
|
131
|
+
first_invited = User.invite!(
|
|
132
|
+
{ email: 'multiple@example.com' },
|
|
133
|
+
nil,
|
|
134
|
+
invitation_data: { organization_id: 1 }
|
|
135
|
+
)
|
|
136
|
+
first_token = first_invited.raw_invitation_token
|
|
137
|
+
first = DeviseInvitable::Invitation.last
|
|
138
|
+
second_invited = User.invite!(
|
|
139
|
+
{ email: 'multiple@example.com' },
|
|
140
|
+
nil,
|
|
141
|
+
invitation_data: { organization_id: 2 }
|
|
142
|
+
)
|
|
143
|
+
second_token = second_invited.raw_invitation_token
|
|
144
|
+
second = DeviseInvitable::Invitation.last
|
|
145
|
+
|
|
146
|
+
user = User.accept_invitation!(
|
|
147
|
+
invitation_token: first_token,
|
|
148
|
+
password: '123456789',
|
|
149
|
+
password_confirmation: '123456789'
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
assert_predicate first.reload, :provisioning?
|
|
153
|
+
refute_predicate first, :pending?
|
|
154
|
+
assert_predicate second.reload, :pending?
|
|
155
|
+
assert_equal user, second.invitable
|
|
156
|
+
assert_nil second.superseded_at
|
|
157
|
+
refute_nil second.invitation_token
|
|
158
|
+
|
|
159
|
+
found_user = User.find_by_invitation_token(second_token, true)
|
|
160
|
+
assert_equal({ 'organization_id' => 2 }, found_user.current_invitation.invitation_data.to_h.stringify_keys)
|
|
161
|
+
encrypted_password = user.encrypted_password
|
|
162
|
+
|
|
163
|
+
accepted_again = User.accept_invitation!(
|
|
164
|
+
invitation_token: second_token,
|
|
165
|
+
password: 'different-password',
|
|
166
|
+
password_confirmation: 'different-password'
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
assert_equal user, accepted_again
|
|
170
|
+
assert_equal encrypted_password, accepted_again.reload.encrypted_password
|
|
171
|
+
assert accepted_again.valid_password?('123456789')
|
|
172
|
+
refute accepted_again.valid_password?('different-password')
|
|
173
|
+
refute_predicate second.reload, :pending?
|
|
174
|
+
assert_nil second.resource_created_at
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
test 'accepting a later placeholder invitation transfers provisioning to it' do
|
|
178
|
+
User.create_resource_on_invitation = true
|
|
179
|
+
User.supersede_other_invitations_on_accept = false
|
|
180
|
+
|
|
181
|
+
user = User.invite!(email: 'placeholder@example.com')
|
|
182
|
+
first = user.current_invitation
|
|
183
|
+
User.invite!(email: 'placeholder@example.com')
|
|
184
|
+
second = DeviseInvitable::Invitation.last
|
|
185
|
+
second_token = Thread.current[:token]
|
|
186
|
+
|
|
187
|
+
accepted_user = User.accept_invitation!(
|
|
188
|
+
invitation_token: second_token,
|
|
189
|
+
password: '123456789',
|
|
190
|
+
password_confirmation: '123456789'
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
refute_predicate accepted_user, :invitation_pending?
|
|
194
|
+
assert_predicate second.reload, :provisioning?
|
|
195
|
+
refute_predicate second, :pending?
|
|
196
|
+
assert_predicate first.reload, :pending?
|
|
197
|
+
refute_predicate first, :provisioning?
|
|
198
|
+
assert_equal accepted_user, first.invitable
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
test 'invitation data is encrypted into the acceptance token but not persisted' do
|
|
202
|
+
User.create_resource_on_invitation = false
|
|
203
|
+
|
|
204
|
+
invited = User.invite!(
|
|
205
|
+
{ email: 'context@example.com' },
|
|
206
|
+
nil,
|
|
207
|
+
invitation_data: { organization_id: 42, role: 'member' }
|
|
208
|
+
)
|
|
209
|
+
invitation = invited.current_invitation
|
|
210
|
+
expected_data = { 'organization_id' => 42, 'role' => 'member' }
|
|
211
|
+
|
|
212
|
+
assert_equal expected_data, invited.invitation_data_before_creation.to_h.stringify_keys
|
|
213
|
+
assert_nil DeviseInvitable::Invitation.find(invitation.id).invitation_data
|
|
214
|
+
|
|
215
|
+
found_user = User.find_by_invitation_token(invited.raw_invitation_token, true)
|
|
216
|
+
|
|
217
|
+
assert_equal expected_data, found_user.current_invitation.invitation_data.to_h.stringify_keys
|
|
218
|
+
|
|
219
|
+
accepted_user = User.accept_invitation!(
|
|
220
|
+
invitation_token: invited.raw_invitation_token,
|
|
221
|
+
password: '123456789',
|
|
222
|
+
password_confirmation: '123456789'
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
assert_equal expected_data, accepted_user.invitation_data_after_acceptance.to_h.stringify_keys
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
test 'invitation data has a bounded serialized size' do
|
|
229
|
+
error = assert_raises DeviseInvitable::InvitationDataTooLargeError do
|
|
230
|
+
User.invite!(
|
|
231
|
+
{ email: 'context@example.com' },
|
|
232
|
+
nil,
|
|
233
|
+
invitation_data: { value: 'x' * 1_024 }
|
|
234
|
+
)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
assert_includes error.message, '1024 serialized bytes'
|
|
238
|
+
assert_equal 0, DeviseInvitable::Invitation.count
|
|
239
|
+
end
|
|
240
|
+
|
|
100
241
|
test 'resending stages the new inviter without changing the previous invitation' do
|
|
101
242
|
User.create_resource_on_invitation = true
|
|
102
243
|
first_inviter = User.create!(email: 'first@example.com', password: '123456789')
|
data/test/models_test.rb
CHANGED
|
@@ -36,6 +36,23 @@ class ModelsTest < ActiveSupport::TestCase
|
|
|
36
36
|
assert_equal false, Devise.create_resource_on_invitation
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
test 'does not store invite keys until delivery by default' do
|
|
40
|
+
assert_equal false, Devise.store_invite_keys_until_delivery
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'does not deliver invitations later by default' do
|
|
44
|
+
assert_equal false, Devise.deliver_invitation_later
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
test 'uses the default invitation delivery job and queue' do
|
|
48
|
+
assert_equal 'DeviseInvitable::InvitationDeliveryJob', Devise.invitation_delivery_job
|
|
49
|
+
assert_equal :mailers, Devise.invitation_delivery_queue_name
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test 'supersedes other invitations on acceptance by default' do
|
|
53
|
+
assert_equal true, Devise.supersede_other_invitations_on_accept
|
|
54
|
+
end
|
|
55
|
+
|
|
39
56
|
test 'should have a default value for invite_key' do
|
|
40
57
|
assert !User.invite_key.nil?
|
|
41
58
|
end
|
|
@@ -32,7 +32,8 @@ class User < PARENT_MODEL_CLASS
|
|
|
32
32
|
create_resource_on_invitation: true
|
|
33
33
|
|
|
34
34
|
attr_accessor :before_invitation_created_callback_works, :after_invitation_created_callback_works,
|
|
35
|
-
:after_invitation_accepted_callback_works, :bio, :
|
|
35
|
+
:after_invitation_accepted_callback_works, :bio, :invitation_data_after_acceptance,
|
|
36
|
+
:invitation_data_before_creation, :token
|
|
36
37
|
validates :username, length: { maximum: 20 }
|
|
37
38
|
|
|
38
39
|
attr_accessor :testing_accepted_or_not_invited
|
|
@@ -50,10 +51,12 @@ class User < PARENT_MODEL_CLASS
|
|
|
50
51
|
|
|
51
52
|
before_invitation_created do |object|
|
|
52
53
|
object.before_invitation_created_callback_works = true
|
|
54
|
+
object.invitation_data_before_creation = object.current_invitation.invitation_data
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
after_invitation_accepted do |object|
|
|
56
58
|
object.after_invitation_accepted_callback_works = true
|
|
59
|
+
object.invitation_data_after_acceptance = object.current_invitation.invitation_data
|
|
57
60
|
end
|
|
58
61
|
|
|
59
62
|
def send_devise_notification(method, raw = nil, *args)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devise_invitable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sergio Cambra
|
|
@@ -94,8 +94,11 @@ files:
|
|
|
94
94
|
- config/locales/zh-HK.yml
|
|
95
95
|
- config/locales/zh-TW.yml
|
|
96
96
|
- lib/devise_invitable.rb
|
|
97
|
+
- lib/devise_invitable/acceptance_token.rb
|
|
97
98
|
- lib/devise_invitable/controllers/helpers.rb
|
|
98
99
|
- lib/devise_invitable/invitation.rb
|
|
100
|
+
- lib/devise_invitable/invitation_delivery.rb
|
|
101
|
+
- lib/devise_invitable/invitation_delivery_job.rb
|
|
99
102
|
- lib/devise_invitable/inviter.rb
|
|
100
103
|
- lib/devise_invitable/mailer.rb
|
|
101
104
|
- lib/devise_invitable/mapping.rb
|
|
@@ -126,6 +129,8 @@ files:
|
|
|
126
129
|
- test/integration/invitation_remove_test.rb
|
|
127
130
|
- test/integration/invitation_test.rb
|
|
128
131
|
- test/integration_tests_helper.rb
|
|
132
|
+
- test/jobs/invitation_delivery_job_test.rb
|
|
133
|
+
- test/lazy_loading_test.rb
|
|
129
134
|
- test/mailers/invitation_mail_test.rb
|
|
130
135
|
- test/mailers/parent_mailer_test.rb
|
|
131
136
|
- test/model_tests_helper.rb
|
|
@@ -174,6 +179,7 @@ files:
|
|
|
174
179
|
- test/rails_app/config/master.key
|
|
175
180
|
- test/rails_app/config/routes.rb
|
|
176
181
|
- test/rails_app/db/migrate/20100401102949_create_tables.rb
|
|
182
|
+
- test/rails_app/db/migrate/20261103170000_add_options_to_users.rb
|
|
177
183
|
- test/rails_app/mongoid.yml
|
|
178
184
|
- test/rails_app/script/rails
|
|
179
185
|
- test/routes_test.rb
|
|
@@ -210,6 +216,8 @@ test_files:
|
|
|
210
216
|
- test/integration/invitation_remove_test.rb
|
|
211
217
|
- test/integration/invitation_test.rb
|
|
212
218
|
- test/integration_tests_helper.rb
|
|
219
|
+
- test/jobs/invitation_delivery_job_test.rb
|
|
220
|
+
- test/lazy_loading_test.rb
|
|
213
221
|
- test/mailers/invitation_mail_test.rb
|
|
214
222
|
- test/mailers/parent_mailer_test.rb
|
|
215
223
|
- test/model_tests_helper.rb
|
|
@@ -258,6 +266,7 @@ test_files:
|
|
|
258
266
|
- test/rails_app/config/master.key
|
|
259
267
|
- test/rails_app/config/routes.rb
|
|
260
268
|
- test/rails_app/db/migrate/20100401102949_create_tables.rb
|
|
269
|
+
- test/rails_app/db/migrate/20261103170000_add_options_to_users.rb
|
|
261
270
|
- test/rails_app/mongoid.yml
|
|
262
271
|
- test/rails_app/script/rails
|
|
263
272
|
- test/routes_test.rb
|