devise_invitable 1.1.8 → 1.3.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.
Files changed (70) hide show
  1. data/CHANGELOG +5 -0
  2. data/README.rdoc +39 -12
  3. data/app/controllers/devise/invitations_controller.rb +20 -6
  4. data/app/controllers/devise_invitable/registrations_controller.rb +2 -2
  5. data/app/views/devise/mailer/invitation_instructions.html.erb +1 -1
  6. data/lib/devise_invitable/mailer.rb +3 -7
  7. data/lib/devise_invitable/model.rb +53 -59
  8. data/lib/devise_invitable/parameter_sanitizer.rb +11 -0
  9. data/lib/devise_invitable/rails.rb +1 -0
  10. data/lib/devise_invitable/version.rb +1 -1
  11. data/lib/devise_invitable.rb +1 -0
  12. data/lib/generators/active_record/templates/migration.rb +3 -2
  13. data/test/functional/controller_helpers_test.rb +39 -0
  14. data/test/functional/registrations_controller_test.rb +59 -0
  15. data/test/generators/views_generator_test.rb +40 -0
  16. data/test/generators_test.rb +34 -0
  17. data/test/integration/invitation_remove_test.rb +29 -0
  18. data/test/integration/invitation_test.rb +222 -0
  19. data/test/integration_tests_helper.rb +48 -0
  20. data/test/mailers/invitation_mail_test.rb +69 -0
  21. data/test/model_tests_helper.rb +33 -0
  22. data/test/models/invitable_test.rb +558 -0
  23. data/test/models_test.rb +74 -0
  24. data/test/orm/active_record.rb +4 -0
  25. data/test/orm/mongoid.rb +20 -0
  26. data/test/rails_app/Rakefile +7 -0
  27. data/test/rails_app/app/controllers/admins_controller.rb +6 -0
  28. data/test/rails_app/app/controllers/application_controller.rb +10 -0
  29. data/test/rails_app/app/controllers/free_invitations_controller.rb +6 -0
  30. data/test/rails_app/app/controllers/home_controller.rb +4 -0
  31. data/test/rails_app/app/controllers/users_controller.rb +12 -0
  32. data/test/rails_app/app/helpers/application_helper.rb +2 -0
  33. data/test/rails_app/app/models/admin.rb +23 -0
  34. data/test/rails_app/app/models/octopussy.rb +15 -0
  35. data/test/rails_app/app/models/user.rb +56 -0
  36. data/test/rails_app/app/views/admins/new.html.erb +12 -0
  37. data/test/rails_app/app/views/free_invitations/new.html.erb +12 -0
  38. data/test/rails_app/app/views/home/index.html.erb +0 -0
  39. data/test/rails_app/app/views/layouts/application.html.erb +16 -0
  40. data/test/rails_app/app/views/users/invitations/new.html.erb +15 -0
  41. data/test/rails_app/config/application.rb +24 -0
  42. data/test/rails_app/config/boot.rb +11 -0
  43. data/test/rails_app/config/database.yml +22 -0
  44. data/test/rails_app/config/environment.rb +5 -0
  45. data/test/rails_app/config/environments/development.rb +25 -0
  46. data/test/rails_app/config/environments/production.rb +49 -0
  47. data/test/rails_app/config/environments/test.rb +33 -0
  48. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  49. data/test/rails_app/config/initializers/devise.rb +213 -0
  50. data/test/rails_app/config/initializers/inflections.rb +10 -0
  51. data/test/rails_app/config/initializers/mime_types.rb +5 -0
  52. data/test/rails_app/config/initializers/secret_token.rb +7 -0
  53. data/test/rails_app/config/initializers/session_store.rb +8 -0
  54. data/test/rails_app/config/initializers/wrap_parameters.rb +14 -0
  55. data/test/rails_app/config/locales/devise.en.yml +57 -0
  56. data/test/rails_app/config/locales/en.yml +14 -0
  57. data/test/rails_app/config/routes.rb +9 -0
  58. data/test/rails_app/config.ru +4 -0
  59. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +39 -0
  60. data/test/rails_app/mongoid.yml +10 -0
  61. data/test/rails_app/script/rails +6 -0
  62. data/test/routes_test.rb +20 -0
  63. data/test/test_helper.rb +24 -0
  64. metadata +135 -47
  65. data/app/controllers/devise_invitable/registrations_controller.rb~ +0 -15
  66. data/lib/devise_invitable/controllers/helpers.rb~ +0 -21
  67. data/lib/devise_invitable/controllers/registrations.rb~ +0 -21
  68. data/lib/devise_invitable/model.rb~ +0 -224
  69. data/lib/devise_invitable/rails.rb~ +0 -21
  70. data/lib/devise_invitable.rb~ +0 -65
@@ -1,224 +0,0 @@
1
- require 'active_support/deprecation'
2
-
3
- module Devise
4
- module Models
5
- # Invitable is responsible for sending invitation emails.
6
- # When an invitation is sent to an email address, an account is created for it.
7
- # Invitation email contains a link allowing the user to accept the invitation
8
- # by setting a password (as reset password from Devise's recoverable module).
9
- #
10
- # Configuration:
11
- #
12
- # invite_for: The period the generated invitation token is valid, after
13
- # this period, the invited resource won't be able to accept the invitation.
14
- # When invite_for is 0 (the default), the invitation won't expire.
15
- #
16
- # Examples:
17
- #
18
- # User.find(1).invited_to_sign_up? # => true/false
19
- # User.invite!(:email => 'someone@example.com') # => send invitation
20
- # User.accept_invitation!(:invitation_token => '...') # => accept invitation with a token
21
- # User.find(1).accept_invitation! # => accept invitation
22
- # User.find(1).invite! # => reset invitation status and send invitation again
23
- module Invitable
24
- extend ActiveSupport::Concern
25
-
26
- attr_accessor :skip_invitation
27
- attr_accessor :completing_invite
28
-
29
- included do
30
- include ::DeviseInvitable::Inviter
31
- belongs_to :invited_by, :polymorphic => true
32
-
33
- include ActiveSupport::Callbacks
34
- define_callbacks :invitation_accepted
35
-
36
- attr_writer :skip_password
37
- end
38
-
39
- # Accept an invitation by clearing invitation token and and setting invitation_accepted_at
40
- # Confirms it if model is confirmable
41
- def accept_invitation!
42
- self.completing_invite = true
43
- if self.invited_to_sign_up? && self.valid?
44
- run_callbacks :invitation_accepted do
45
- self.invitation_token = nil
46
- self.invitation_accepted_at = Time.now.utc if respond_to? :"invitation_accepted_at="
47
- self.completing_invite = false
48
- self.save(:validate => false)
49
- end
50
- end
51
- end
52
-
53
- # Verifies whether a user has accepted an invite, was never invited, or is in the process of accepting an invitation, or not
54
- def accepting_or_not_invited?
55
- !!completing_invite || invited_to_sign_up?
56
- end
57
-
58
- # Verifies whether a user has been invited or not
59
- def invited_to_sign_up?
60
- persisted? && invitation_token.present?
61
- end
62
-
63
- def invited?
64
- invited_to_sign_up?
65
- end
66
- deprecate :invited?
67
-
68
- # Reset invitation token and send invitation again
69
- def invite!
70
- was_invited = invited_to_sign_up?
71
- self.skip_confirmation! if self.new_record? && self.respond_to?(:skip_confirmation!)
72
- generate_invitation_token if self.invitation_token.nil?
73
- self.invitation_sent_at = Time.now.utc
74
-
75
- # Call these before_validate methods since we aren't validating on save
76
- self.downcase_keys if self.new_record? && self.respond_to?(:downcase_keys)
77
- self.strip_whitespace if self.new_record? && self.respond_to?(:strip_whitespace)
78
-
79
- if save(:validate => false)
80
- self.invited_by.decrement_invitation_limit! if !was_invited and self.invited_by.present?
81
- deliver_invitation unless @skip_invitation
82
- end
83
- end
84
-
85
- # Verify whether a invitation is active or not. If the user has been
86
- # invited, we need to calculate if the invitation time has not expired
87
- # for this user, in other words, if the invitation is still valid.
88
- def valid_invitation?
89
- invited_to_sign_up? && invitation_period_valid?
90
- end
91
-
92
- # Only verify password when is not invited
93
- def valid_password?(password)
94
- super unless invited_to_sign_up?
95
- end
96
-
97
- def reset_password!(new_password, new_password_confirmation)
98
- super
99
- accept_invitation!
100
- end
101
-
102
- protected
103
- # Overriding the method in Devise's :validatable module so password is not required on inviting
104
- def password_required?
105
- !@skip_password && super
106
- end
107
-
108
- # Deliver the invitation email
109
- def deliver_invitation
110
- ::Devise.mailer.invitation_instructions(self).deliver
111
- end
112
-
113
- # Checks if the invitation for the user is within the limit time.
114
- # We do this by calculating if the difference between today and the
115
- # invitation sent date does not exceed the invite for time configured.
116
- # Invite_for is a model configuration, must always be an integer value.
117
- #
118
- # Example:
119
- #
120
- # # invite_for = 1.day and invitation_sent_at = today
121
- # invitation_period_valid? # returns true
122
- #
123
- # # invite_for = 5.days and invitation_sent_at = 4.days.ago
124
- # invitation_period_valid? # returns true
125
- #
126
- # # invite_for = 5.days and invitation_sent_at = 5.days.ago
127
- # invitation_period_valid? # returns false
128
- #
129
- # # invite_for = nil
130
- # invitation_period_valid? # will always return true
131
- #
132
- def invitation_period_valid?
133
- invitation_sent_at && (self.class.invite_for.to_i.zero? || invitation_sent_at.utc >= self.class.invite_for.ago)
134
- end
135
-
136
- # Generates a new random token for invitation, and stores the time
137
- # this token is being generated
138
- def generate_invitation_token
139
- self.invitation_token = self.class.invitation_token
140
- end
141
-
142
- module ClassMethods
143
- # Attempt to find a user by it's email. If a record is not found, create a new
144
- # user and send invitation to it. If user is found, returns the user with an
145
- # email already exists error.
146
- # If user is found and still have pending invitation, email is resend unless
147
- # resend_invitation is set to false
148
- # Attributes must contain the user email, other attributes will be set in the record
149
- def _invite(attributes={}, invited_by=nil, &block)
150
- invitable = find_or_initialize_with_error_by(invite_key, attributes.delete(invite_key))
151
- invitable.assign_attributes(attributes, :as => inviter_role(invited_by))
152
- invitable.invited_by = invited_by
153
-
154
- invitable.skip_password = true
155
- invitable.valid? if self.validate_on_invite
156
- if invitable.new_record?
157
- invitable.errors.clear if !self.validate_on_invite and invitable.email.try(:match, Devise.email_regexp)
158
- else
159
- invitable.errors.add(invite_key, :taken) unless invitable.invited_to_sign_up? && self.resend_invitation
160
- end
161
-
162
- if invitable.errors.empty?
163
- yield invitable if block_given?
164
- mail = invitable.invite!
165
- end
166
- [invitable, mail]
167
- end
168
-
169
- # Override this method if the invitable is using Mass Assignment Security
170
- # and the inviter has a non-default role.
171
- def inviter_role(inviter)
172
- :default
173
- end
174
-
175
- def invite!(attributes={}, invited_by=nil, &block)
176
- invitable, mail = _invite(attributes, invited_by, &block)
177
- invitable
178
- end
179
-
180
- def invite_mail!(attributes={}, invited_by=nil, &block)
181
- invitable, mail = _invite(attributes, invited_by, &block)
182
- mail
183
- end
184
-
185
- # Attempt to find a user by it's invitation_token to set it's password.
186
- # If a user is found, reset it's password and automatically try saving
187
- # the record. If not user is found, returns a new user containing an
188
- # error in invitation_token attribute.
189
- # Attributes must contain invitation_token, password and confirmation
190
- def accept_invitation!(attributes={})
191
- invitable = find_or_initialize_with_error_by(:invitation_token, attributes.delete(:invitation_token))
192
- invitable.errors.add(:invitation_token, :invalid) if invitable.invitation_token && invitable.persisted? && !invitable.valid_invitation?
193
- if invitable.errors.empty?
194
- invitable.attributes = attributes
195
- invitable.accept_invitation!
196
- end
197
- invitable
198
- end
199
-
200
- # Generate a token checking if one does not already exist in the database.
201
- def invitation_token
202
- generate_token(:invitation_token)
203
- end
204
-
205
- # Callback convenience methods
206
- def before_invitation_accepted(*args, &blk)
207
- set_callback(:invitation_accepted, :before, *args, &blk)
208
- end
209
-
210
- def after_invitation_accepted(*args, &blk)
211
- set_callback(:invitation_accepted, :after, *args, &blk)
212
- end
213
-
214
-
215
- Devise::Models.config(self, :invite_for)
216
- Devise::Models.config(self, :validate_on_invite)
217
- Devise::Models.config(self, :invitation_limit)
218
- Devise::Models.config(self, :invite_key)
219
- Devise::Models.config(self, :resend_invitation)
220
- end
221
- end
222
- end
223
- end
224
-
@@ -1,21 +0,0 @@
1
- module DeviseInvitable
2
- class Engine < ::Rails::Engine
3
-
4
- ActiveSupport.on_load(:action_controller) do
5
- include DeviseInvitable::Controllers::UrlHelpers
6
- include DeviseInvitable::Controllers::Helpers
7
- end
8
- ActiveSupport.on_load(:action_view) { include DeviseInvitable::Controllers::UrlHelpers }
9
-
10
- # We use to_prepare instead of after_initialize here because Devise is a Rails engine; its
11
- # mailer is reloaded like the rest of the user's app. Got to make sure that our mailer methods
12
- # are included each time Devise::Mailer is (re)loaded.
13
- config.to_prepare do
14
- require 'devise/mailer'
15
- Devise::Mailer.send :include, DeviseInvitable::Mailer
16
- Devise::Mapping.send :include, DeviseInvitable::Mapping
17
- end
18
- config.after_initialize do
19
- end
20
- end
21
- end
@@ -1,65 +0,0 @@
1
- module DeviseInvitable
2
- autoload :Inviter, 'devise_invitable/inviter'
3
- autoload :Mailer, 'devise_invitable/mailer'
4
- module Controllers
5
- autoload :UrlHelpers, 'devise_invitable/controllers/url_helpers'
6
- autoload :Registrations, 'devise_invitable/controllers/registrations'
7
- autoload :Helpers, 'devise_invitable/controllers/helpers'
8
- end
9
- end
10
-
11
- require 'devise'
12
- require 'devise_invitable/routes'
13
- require 'devise_invitable/rails'
14
-
15
- module Devise
16
- # Public: Validity period of the invitation token (default: 0). If
17
- # invite_for is 0 or nil, the invitation will never expire.
18
- # Set invite_for in the Devise configuration file (in config/initializers/devise.rb).
19
- #
20
- # config.invite_for = 2.weeks # => The invitation token will be valid 2 weeks
21
- mattr_accessor :invite_for
22
- @@invite_for = 0
23
-
24
- # Public: Flag that force a record to be valid before being actually invited
25
- # (default: false).
26
- #
27
- # Examples (in config/initializers/devise.rb)
28
- #
29
- # config.validate_on_invite = true
30
- mattr_accessor :validate_on_invite
31
- @@validate_on_invite = false
32
-
33
- # Public: number of invitations the user is allowed to send
34
- #
35
- # Examples (in config/initializers/devise.rb)
36
- #
37
- # config.invitation_limit = nil
38
- mattr_accessor :invitation_limit
39
- @@invitation_limit = nil
40
-
41
- # Public: The key to be used to check existing users when sending an invitation,
42
- # and the regexp used to test it when validate_on_invite is not set.
43
- #
44
- # Examples (in config/initializers/devise.rb)
45
- #
46
- # config.invite_key = {:email => /\A[^@]+@[^@]+\z/}
47
- mattr_accessor :invite_key
48
- @@invite_key = {:email => Devise.email_regexp}
49
-
50
- # Public: Resend invitation if user with invited status is invited again
51
- # (default: true)
52
- #
53
- # Example (in config/initializers/devise.rb)
54
- #
55
- # config.resend_invitation = false
56
- mattr_accessor :resend_invitation
57
- @@resend_invitation = true
58
-
59
- # Public: The class name of the inviting model. If this is nil,
60
- # the #invited_by association is declared to be polymorphic. (default: nil)
61
- mattr_accessor :invited_by_class_name
62
- @@invited_by_class_name = nil
63
- end
64
-
65
- Devise.add_module :invitable, :controller => :invitations, :model => 'devise_invitable/model', :route => :invitation