devise_invitable 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise_invitable might be problematic. Click here for more details.

data/README.rdoc CHANGED
@@ -1,10 +1,11 @@
1
1
  = DeviseInvitable
2
+ {<img src="https://secure.travis-ci.org/scambra/devise_invitable.png"/>}[http://travis-ci.org/scambra/devise_invitable]
2
3
 
3
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.
4
5
 
5
6
  DeviseInvitable currently only support Rails 3, 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]
6
7
 
7
- == Installation for Rails ~> 3.0 and Devise ~> 1.2
8
+ == Installation
8
9
 
9
10
  Install DeviseInvitable gem, it will also install dependencies (such as devise and warden):
10
11
 
@@ -12,8 +13,8 @@ Install DeviseInvitable gem, it will also install dependencies (such as devise a
12
13
 
13
14
  Add DeviseInvitable to your Gemfile (and Devise if you weren't using them):
14
15
 
15
- gem 'devise', '~> 2.0.0'
16
- gem 'devise_invitable', '~> 0.7.0'
16
+ gem 'devise', '>= 2.0.0'
17
+ gem 'devise_invitable', '~> 1.0.0'
17
18
 
18
19
  === Automatic installation
19
20
 
@@ -50,7 +51,7 @@ Add t.invitable to your Devise model migration:
50
51
  t.string :invited_by_type
51
52
  ...
52
53
  end
53
- add_index :users, :invitation_token
54
+ add_index :users, :invitation_token, :unique => true
54
55
 
55
56
  or for a model that already exists, define a migration to add DeviseInvitable to your model:
56
57
 
@@ -65,9 +66,9 @@ or for a model that already exists, define a migration to add DeviseInvitable to
65
66
  end
66
67
 
67
68
  # Allow null encrypted_password
68
- change_column_null :users, :encrypted_password, true
69
+ change_column :users, :encrypted_password, :string, :null => true
69
70
  # Allow null password_salt (add it if you are using Devise's encryptable module)
70
- change_column_null :users, :password_salt, true
71
+ change_column :users, :password_salt, :string, :null => true
71
72
 
72
73
  == Model configuration
73
74
 
@@ -165,7 +166,7 @@ A callback event is fired before and after an invitation is accepted (User#accep
165
166
  after_invitation_accepted :email_invited_by
166
167
 
167
168
  def email_invited_by
168
- # ...
169
+ # ...
169
170
  end
170
171
 
171
172
  The callbacks support all options and arguments available to the standard callbacks provided by AR.
@@ -262,7 +263,7 @@ http://github.com/scambra/devise_invitable/contributors
262
263
  Special thanks to rymai[http://github.com/rymai] for the Rails 3 support, his fork was a great help.
263
264
 
264
265
  == Note on Patches/Pull Requests
265
-
266
+
266
267
  * Fork the project.
267
268
  * Make your feature addition or bug fix.
268
269
  * Add tests for it. This is important so I don't break it in a future version unintentionally.
@@ -0,0 +1,36 @@
1
+ module DeviseInvitable::Controllers::Registrations
2
+ def self.included(controller)
3
+ controller.send :around_filter, :destroy_if_previously_invited, :only => :create
4
+ end
5
+
6
+ protected
7
+
8
+ def destroy_if_previously_invited
9
+ invitation_info = {}
10
+
11
+ hash = params[resource_name]
12
+ if hash && hash[:email]
13
+ resource = resource_class.first(:conditions => { :email => hash[:email], :encrypted_password => '' })
14
+ if resource
15
+ invitation_info[:invitation_sent_at] = resource[:invitation_sent_at]
16
+ invitation_info[:invited_by_id] = resource[:invited_by_id]
17
+ invitation_info[:invited_by_type] = resource[:invited_by_type]
18
+ resource.destroy
19
+ end
20
+ end
21
+
22
+ # execute the action (create)
23
+ yield
24
+ # Note that the after_filter is executed at THIS position !
25
+
26
+ # Restore info about the last invitation (for later reference)
27
+ # Reset the invitation_info only, if invited_by_id is still nil at this stage:
28
+ resource = resource_class.first(:conditions => { :email => hash[:email], :invited_by_id => nil })
29
+ if resource
30
+ resource[:invitation_sent_at] = invitation_info[:invitation_sent_at]
31
+ resource[:invited_by_id] = invitation_info[:invited_by_id]
32
+ resource[:invited_by_type] = invitation_info[:invited_by_type]
33
+ resource.save!
34
+ end
35
+ end
36
+ end
@@ -13,7 +13,7 @@ module DeviseInvitable
13
13
  else
14
14
  resource.class.name.underscore
15
15
  end
16
-
16
+
17
17
  send("#{action}\#{resource}_invitation_#{path_or_url}", *args)
18
18
  end
19
19
  URL_HELPERS
@@ -56,6 +56,11 @@ module Devise
56
56
  self.skip_confirmation! if self.new_record? && self.respond_to?(:skip_confirmation!)
57
57
  generate_invitation_token if self.invitation_token.nil?
58
58
  self.invitation_sent_at = Time.now.utc
59
+
60
+ # Call these before_validate methods since we aren't validating on save
61
+ self.downcase_keys if self.new_record? && self.respond_to?(:downcase_keys)
62
+ self.strip_whitespace if self.new_record? && self.respond_to?(:strip_whitespace)
63
+
59
64
  if save(:validate => false)
60
65
  self.invited_by.decrement_invitation_limit! if !was_invited and self.invited_by.present?
61
66
  deliver_invitation unless @skip_invitation
@@ -1,16 +1,16 @@
1
1
  module DeviseInvitable
2
2
  class Engine < ::Rails::Engine
3
-
3
+
4
4
  ActiveSupport.on_load(:action_controller) { include DeviseInvitable::Controllers::UrlHelpers }
5
5
  ActiveSupport.on_load(:action_view) { include DeviseInvitable::Controllers::UrlHelpers }
6
-
6
+
7
7
  # We use to_prepare instead of after_initialize here because Devise is a Rails engine; its
8
8
  # mailer is reloaded like the rest of the user's app. Got to make sure that our mailer methods
9
9
  # are included each time Devise::Mailer is (re)loaded.
10
10
  config.to_prepare do
11
11
  require 'devise/mailer'
12
12
  Devise::Mailer.send :include, DeviseInvitable::Mailer
13
+ Devise::RegistrationsController.send :include, DeviseInvitable::Controllers::Registrations
13
14
  end
14
-
15
15
  end
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module DeviseInvitable
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
@@ -7,11 +7,12 @@ end
7
7
  require 'devise_invitable/mailer'
8
8
  require 'devise_invitable/routes'
9
9
  require 'devise_invitable/controllers/url_helpers'
10
+ require 'devise_invitable/controllers/registrations'
10
11
  require 'devise_invitable/controllers/helpers'
11
12
  require 'devise_invitable/rails'
12
13
 
13
14
  module Devise
14
- # Public: Validity period of the invitation token (default: 0). If
15
+ # Public: Validity period of the invitation token (default: 0). If
15
16
  # invite_for is 0 or nil, the invitation will never expire.
16
17
  # Set invite_for in the Devise configuration file (in config/initializers/devise.rb).
17
18
  #
@@ -19,7 +20,7 @@ module Devise
19
20
  mattr_accessor :invite_for
20
21
  @@invite_for = 0
21
22
 
22
- # Public: Flag that force a record to be valid before being actually invited
23
+ # Public: Flag that force a record to be valid before being actually invited
23
24
  # (default: false).
24
25
  #
25
26
  # Examples (in config/initializers/devise.rb)
@@ -35,7 +36,7 @@ module Devise
35
36
  # config.invitation_limit = nil
36
37
  mattr_accessor :invitation_limit
37
38
  @@invitation_limit = nil
38
-
39
+
39
40
  # Public: The key to be used to check existing users when sending an invitation
40
41
  #
41
42
  # Examples (in config/initializers/devise.rb)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_invitable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 0
10
- version: 1.0.0
9
+ - 1
10
+ version: 1.0.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sergio Cambra
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-31 00:00:00 Z
18
+ date: 2012-04-03 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bundler
@@ -25,12 +25,12 @@ dependencies:
25
25
  requirements:
26
26
  - - ~>
27
27
  - !ruby/object:Gem::Version
28
- hash: 25
28
+ hash: 19
29
29
  segments:
30
30
  - 1
31
+ - 1
31
32
  - 0
32
- - 7
33
- version: 1.0.7
33
+ version: 1.1.0
34
34
  type: :development
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
@@ -54,7 +54,7 @@ dependencies:
54
54
  requirement: &id003 !ruby/object:Gem::Requirement
55
55
  none: false
56
56
  requirements:
57
- - - ~>
57
+ - - ">="
58
58
  - !ruby/object:Gem::Version
59
59
  hash: 15
60
60
  segments:
@@ -79,21 +79,21 @@ files:
79
79
  - app/views/devise/invitations/new.html.erb
80
80
  - app/views/devise/mailer/invitation_instructions.html.erb
81
81
  - config/locales/en.yml
82
- - lib/devise_invitable.rb
82
+ - lib/devise_invitable/controllers/helpers.rb
83
+ - lib/devise_invitable/controllers/registrations.rb
84
+ - lib/devise_invitable/controllers/url_helpers.rb
85
+ - lib/devise_invitable/inviter.rb
83
86
  - lib/devise_invitable/mailer.rb
84
87
  - lib/devise_invitable/model.rb
85
88
  - lib/devise_invitable/rails.rb
86
89
  - lib/devise_invitable/routes.rb
87
- - lib/devise_invitable/controllers/helpers.rb
88
- - lib/devise_invitable/controllers/url_helpers.rb
89
90
  - lib/devise_invitable/version.rb
90
- - lib/devise_invitable/inviter.rb
91
- - lib/devise_invitable/model.rb~
91
+ - lib/devise_invitable.rb
92
92
  - lib/generators/active_record/devise_invitable_generator.rb
93
93
  - lib/generators/active_record/templates/migration.rb
94
- - lib/generators/devise_invitable/views_generator.rb
95
94
  - lib/generators/devise_invitable/devise_invitable_generator.rb
96
95
  - lib/generators/devise_invitable/install_generator.rb
96
+ - lib/generators/devise_invitable/views_generator.rb
97
97
  - lib/generators/mongoid/devise_invitable_generator.rb
98
98
  - LICENSE
99
99
  - README.rdoc
@@ -132,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
132
  requirements: []
133
133
 
134
134
  rubyforge_project:
135
- rubygems_version: 1.8.10
135
+ rubygems_version: 1.8.15
136
136
  signing_key:
137
137
  specification_version: 3
138
138
  summary: An invitation strategy for Devise
@@ -1,210 +0,0 @@
1
- module Devise
2
- module Models
3
- # Invitable is responsible for sending invitation emails.
4
- # When an invitation is sent to an email address, an account is created for it.
5
- # Invitation email contains a link allowing the user to accept the invitation
6
- # by setting a password (as reset password from Devise's recoverable module).
7
- #
8
- # Configuration:
9
- #
10
- # invite_for: The period the generated invitation token is valid, after
11
- # this period, the invited resource won't be able to accept the invitation.
12
- # When invite_for is 0 (the default), the invitation won't expire.
13
- #
14
- # Examples:
15
- #
16
- # User.find(1).invited? # => true/false
17
- # User.invite!(:email => 'someone@example.com') # => send invitation
18
- # User.accept_invitation!(:invitation_token => '...') # => accept invitation with a token
19
- # User.find(1).accept_invitation! # => accept invitation
20
- # User.find(1).invite! # => reset invitation status and send invitation again
21
- module Invitable
22
- extend ActiveSupport::Concern
23
-
24
- attr_accessor :skip_invitation
25
-
26
- included do
27
- include ::DeviseInvitable::Inviter
28
- belongs_to :invited_by, :polymorphic => true
29
-
30
- include ActiveSupport::Callbacks
31
- define_callbacks :invitation_accepted
32
-
33
- attr_writer :skip_password
34
- end
35
-
36
- # Accept an invitation by clearing invitation token and and setting invitation_accepted_at
37
- # Confirms it if model is confirmable
38
- def accept_invitation!
39
- if self.invited? && self.valid?
40
- run_callbacks :invitation_accepted do
41
- self.invitation_token = nil
42
- self.invitation_accepted_at = Time.now.utc if respond_to? :"invitation_accepted_at="
43
- self.save(:validate => false)
44
- end
45
- end
46
- end
47
-
48
- # Verifies whether a user has been invited or not
49
- def invited?
50
- persisted? && invitation_token.present?
51
- end
52
-
53
- # Reset invitation token and send invitation again
54
- def invite!
55
- was_invited = invited?
56
- self.skip_confirmation! if self.new_record? && self.respond_to?(:skip_confirmation!)
57
- generate_invitation_token if self.invitation_token.nil?
58
- self.invitation_sent_at = Time.now.utc
59
- if save(:validate => false)
60
- self.invited_by.decrement_invitation_limit! if !was_invited and self.invited_by.present?
61
- deliver_invitation unless @skip_invitation
62
- end
63
- end
64
-
65
- # Verify whether a invitation is active or not. If the user has been
66
- # invited, we need to calculate if the invitation time has not expired
67
- # for this user, in other words, if the invitation is still valid.
68
- def valid_invitation?
69
- invited? && invitation_period_valid?
70
- end
71
-
72
- # Only verify password when is not invited
73
- def valid_password?(password)
74
- super unless invited?
75
- end
76
- =begin
77
- def reset_password!(new_password, new_password_confirmation)
78
- super
79
- accept_invitation!
80
- end
81
- =end
82
- protected
83
- # Overriding the method in Devise's :validatable module so password is not required on inviting
84
- def password_required?
85
- !@skip_password && super
86
- end
87
-
88
- # Deliver the invitation email
89
- def deliver_invitation
90
- ::Devise.mailer.invitation_instructions(self).deliver
91
- end
92
-
93
- # Clear invitation token when reset password token is cleared too
94
- def clear_reset_password_token
95
- self.invitation_token = nil if invited?
96
- super
97
- end
98
-
99
- # Checks if the invitation for the user is within the limit time.
100
- # We do this by calculating if the difference between today and the
101
- # invitation sent date does not exceed the invite for time configured.
102
- # Invite_for is a model configuration, must always be an integer value.
103
- #
104
- # Example:
105
- #
106
- # # invite_for = 1.day and invitation_sent_at = today
107
- # invitation_period_valid? # returns true
108
- #
109
- # # invite_for = 5.days and invitation_sent_at = 4.days.ago
110
- # invitation_period_valid? # returns true
111
- #
112
- # # invite_for = 5.days and invitation_sent_at = 5.days.ago
113
- # invitation_period_valid? # returns false
114
- #
115
- # # invite_for = nil
116
- # invitation_period_valid? # will always return true
117
- #
118
- def invitation_period_valid?
119
- invitation_sent_at && (self.class.invite_for.to_i.zero? || invitation_sent_at.utc >= self.class.invite_for.ago)
120
- end
121
-
122
- # Generates a new random token for invitation, and stores the time
123
- # this token is being generated
124
- def generate_invitation_token
125
- self.invitation_token = self.class.invitation_token
126
- end
127
-
128
- module ClassMethods
129
- # Attempt to find a user by it's email. If a record is not found, create a new
130
- # user and send invitation to it. If user is found, returns the user with an
131
- # email already exists error.
132
- # If user is found and still have pending invitation, email is resend unless
133
- # resend_invitation is set to false
134
- # Attributes must contain the user email, other attributes will be set in the record
135
- def _invite(attributes={}, invited_by=nil, &block)
136
- invitable = find_or_initialize_with_error_by(invite_key, attributes.delete(invite_key))
137
- invitable.assign_attributes(attributes, :as => inviter_role(invited_by))
138
- invitable.invited_by = invited_by
139
-
140
- invitable.skip_password = true
141
- invitable.valid? if self.validate_on_invite
142
- if invitable.new_record?
143
- invitable.errors.clear if !self.validate_on_invite and invitable.email.try(:match, Devise.email_regexp)
144
- else
145
- invitable.errors.add(invite_key, :taken) unless invitable.invited? && self.resend_invitation
146
- end
147
-
148
- if invitable.errors.empty?
149
- yield invitable if block_given?
150
- mail = invitable.invite!
151
- end
152
- [invitable, mail]
153
- end
154
-
155
- # Override this method if the invitable is using Mass Assignment Security
156
- # and the inviter has a non-default role.
157
- def inviter_role(inviter)
158
- :default
159
- end
160
-
161
- def invite!(attributes={}, invited_by=nil, &block)
162
- invitable, mail = _invite(attributes, invited_by, &block)
163
- invitable
164
- end
165
-
166
- def invite_mail!(attributes={}, invited_by=nil, &block)
167
- invitable, mail = _invite(attributes, invited_by, &block)
168
- mail
169
- end
170
-
171
- # Attempt to find a user by it's invitation_token to set it's password.
172
- # If a user is found, reset it's password and automatically try saving
173
- # the record. If not user is found, returns a new user containing an
174
- # error in invitation_token attribute.
175
- # Attributes must contain invitation_token, password and confirmation
176
- def accept_invitation!(attributes={})
177
- invitable = find_or_initialize_with_error_by(:invitation_token, attributes.delete(:invitation_token))
178
- invitable.errors.add(:invitation_token, :invalid) if invitable.invitation_token && invitable.persisted? && !invitable.valid_invitation?
179
- if invitable.errors.empty?
180
- invitable.attributes = attributes
181
- invitable.accept_invitation!
182
- end
183
- invitable
184
- end
185
-
186
- # Generate a token checking if one does not already exist in the database.
187
- def invitation_token
188
- generate_token(:invitation_token)
189
- end
190
-
191
- # Callback convenience methods
192
- def before_invitation_accepted(*args, &blk)
193
- set_callback(:invitation_accepted, :before, *args, &blk)
194
- end
195
-
196
- def after_invitation_accepted(*args, &blk)
197
- set_callback(:invitation_accepted, :after, *args, &blk)
198
- end
199
-
200
-
201
- Devise::Models.config(self, :invite_for)
202
- Devise::Models.config(self, :validate_on_invite)
203
- Devise::Models.config(self, :invitation_limit)
204
- Devise::Models.config(self, :invite_key)
205
- Devise::Models.config(self, :resend_invitation)
206
- end
207
- end
208
- end
209
- end
210
-