devise_invitable 0.6.0 → 0.6.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.

@@ -61,7 +61,7 @@ class Devise::InvitationsController < ApplicationController
61
61
  end
62
62
 
63
63
  def after_invite_path_for(resource)
64
- redirect_location(resource_name, resource)
64
+ after_sign_in_path_for(resource)
65
65
  end
66
66
 
67
67
  def after_accept_path_for(resource)
@@ -29,10 +29,12 @@ module Devise
29
29
 
30
30
  include ActiveSupport::Callbacks
31
31
  define_callbacks :invitation_accepted
32
+
33
+ attr_writer :skip_password
32
34
  end
33
35
 
34
- # Accept an invitation by clearing invitation token and confirming it if model
35
- # is confirmable
36
+ # Accept an invitation by clearing invitation token and and setting invitation_accepted_at
37
+ # Confirms it if model is confirmable
36
38
  def accept_invitation!
37
39
  if self.invited? && self.valid?
38
40
  run_callbacks :invitation_accepted do
@@ -50,7 +52,6 @@ module Devise
50
52
 
51
53
  # Reset invitation token and send invitation again
52
54
  def invite!
53
- @skip_password = true
54
55
  was_invited = invited?
55
56
  self.skip_confirmation! if self.new_record? && self.respond_to?(:skip_confirmation!)
56
57
  generate_invitation_token if self.invitation_token.nil?
@@ -72,6 +73,11 @@ module Devise
72
73
  def valid_password?(password)
73
74
  super unless invited?
74
75
  end
76
+
77
+ def reset_password!(new_password, new_password_confirmation)
78
+ super
79
+ accept_invitation!
80
+ end
75
81
 
76
82
  protected
77
83
  # Overriding the method in Devise's :validatable module so password is not required on inviting
@@ -84,12 +90,6 @@ module Devise
84
90
  ::Devise.mailer.invitation_instructions(self).deliver
85
91
  end
86
92
 
87
- # Clear invitation token when reset password token is cleared too
88
- def clear_reset_password_token
89
- self.invitation_token = nil if invited?
90
- super
91
- end
92
-
93
93
  # Checks if the invitation for the user is within the limit time.
94
94
  # We do this by calculating if the difference between today and the
95
95
  # invitation sent date does not exceed the invite for time configured.
@@ -128,9 +128,10 @@ module Devise
128
128
  # Attributes must contain the user email, other attributes will be set in the record
129
129
  def _invite(attributes={}, invited_by=nil, &block)
130
130
  invitable = find_or_initialize_with_error_by(invite_key, attributes.delete(invite_key))
131
- invitable.attributes = attributes
131
+ invitable.assign_attributes(attributes, :as => inviter_role(invited_by))
132
132
  invitable.invited_by = invited_by
133
133
 
134
+ invitable.skip_password = true
134
135
  invitable.valid? if self.validate_on_invite
135
136
  if invitable.new_record?
136
137
  invitable.errors.clear if !self.validate_on_invite and invitable.email.try(:match, Devise.email_regexp)
@@ -144,6 +145,12 @@ module Devise
144
145
  end
145
146
  [invitable, mail]
146
147
  end
148
+
149
+ # Override this method if the invitable is using Mass Assignment Security
150
+ # and the inviter has a non-default role.
151
+ def inviter_role(inviter)
152
+ :default
153
+ end
147
154
 
148
155
  def invite!(attributes={}, invited_by=nil, &block)
149
156
  invitable, mail = _invite(attributes, invited_by, &block)
@@ -0,0 +1,210 @@
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
+
@@ -1,3 +1,3 @@
1
1
  module DeviseInvitable
2
- VERSION = '0.6.0'
2
+ VERSION = '0.6.1'
3
3
  end
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: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 0
10
- version: 0.6.0
9
+ - 1
10
+ version: 0.6.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: 2011-11-15 00:00:00 Z
18
+ date: 2011-12-27 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bundler
@@ -39,21 +39,14 @@ dependencies:
39
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 7
45
- segments:
46
- - 3
47
- - 0
48
- - 0
49
- version: 3.0.0
50
- - - <
42
+ - - ~>
51
43
  - !ruby/object:Gem::Version
52
44
  hash: 3
53
45
  segments:
54
46
  - 3
55
- - 2
56
- version: "3.2"
47
+ - 1
48
+ - 0
49
+ version: 3.1.0
57
50
  type: :runtime
58
51
  version_requirements: *id002
59
52
  - !ruby/object:Gem::Dependency
@@ -104,6 +97,7 @@ files:
104
97
  - lib/devise_invitable/controllers/url_helpers.rb
105
98
  - lib/devise_invitable/version.rb
106
99
  - lib/devise_invitable/inviter.rb
100
+ - lib/devise_invitable/model.rb~
107
101
  - lib/generators/active_record/devise_invitable_generator.rb
108
102
  - lib/generators/active_record/templates/migration.rb
109
103
  - lib/generators/devise_invitable/views_generator.rb