devise_invitable 0.3.1 → 0.3.2
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.
- data/Gemfile.lock +1 -1
- data/README.rdoc +24 -13
- data/VERSION +1 -1
- data/app/controllers/devise/invitations_controller.rb +2 -2
- data/app/views/devise/mailer/invitation.html.erb +5 -5
- data/devise_invitable.gemspec +3 -3
- data/lib/devise_invitable/model.rb +23 -17
- data/lib/devise_invitable/rails.rb +2 -4
- data/lib/generators/devise_invitable/views_generator.rb +10 -0
- data/test/models/invitable_test.rb +27 -11
- metadata +5 -5
- data/init.rb +0 -1
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -2,21 +2,18 @@
|
|
2
2
|
|
3
3
|
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
4
|
|
5
|
-
|
6
|
-
|
7
|
-
All gems are on gemcutter, so you need to add gemcutter to your sources if you haven’t yet:
|
5
|
+
DeviseInvitable currently only support rails 3, if you want to use it with rails 2.3 you must install version 0.2.3
|
8
6
|
|
9
|
-
|
7
|
+
== Installation
|
10
8
|
|
11
9
|
Install devise_invitable gem, it should install dependencies (such as devise and warden):
|
12
10
|
|
13
11
|
sudo gem install devise_invitable
|
14
12
|
|
15
|
-
Configure devise_invitable inside your app (and
|
13
|
+
Configure devise_invitable inside your app (and devise if you weren't using them):
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
config.gem 'devise_invitable'
|
15
|
+
gem 'devise'
|
16
|
+
gem 'devise_invitable'
|
20
17
|
|
21
18
|
== Basic Usage
|
22
19
|
|
@@ -48,6 +45,12 @@ If you are using devise :all, you can add :invitable to config.all in devise ini
|
|
48
45
|
|
49
46
|
DeviseInvitable adds a new configuration option, :invite_for. It's the time a invitation is valid for. Default value is nil, which means invitation doesn't expire.
|
50
47
|
|
48
|
+
== Configuring views
|
49
|
+
|
50
|
+
All of the views are packaged inside the gem. If you'd like to customize the views, invoke the the following generator and it will copy all views to your application:
|
51
|
+
|
52
|
+
# rails generate devise_invitable:views
|
53
|
+
|
51
54
|
== Controller filters
|
52
55
|
|
53
56
|
It adds authenticate_resource! filter to restrict who can send invitations. You can override this method in your ApplicationController. Default behavior is require authentication of the same resource_name, so if you only have a model with devise it will allow to all authenticated users to send invitations.
|
@@ -56,19 +59,19 @@ You have to configure mailer as it's required for confirmable and recoverable.
|
|
56
59
|
|
57
60
|
== I18n
|
58
61
|
|
59
|
-
It uses two flash messages, :
|
62
|
+
It uses two flash messages, :send_instructions and :updated, which are translated as other flash messages from devise.
|
60
63
|
|
61
64
|
== Sending an invitation
|
62
65
|
|
63
|
-
To
|
66
|
+
To invite a user use invite class model. You must set email in the attributes hash:
|
64
67
|
|
65
|
-
User.
|
68
|
+
User.invite!(:email => 'new_user@example.com')
|
66
69
|
|
67
|
-
To accept an invitation with a token use accept_invitation! class model. You must set invitiation_token attribute, and you can include other
|
70
|
+
To accept an invitation with a token use accept_invitation! class model. You must set invitiation_token attribute, and you can include other attributes in the hash, which will be updated in the record.
|
68
71
|
|
69
72
|
User.accept_invitation!(:invitation_token => params[:invitation_token])
|
70
73
|
|
71
|
-
Invitations controller implement this. You can go to /users/invitation/new to send an invitation and an email will be sent with a link to accept
|
74
|
+
Invitations controller implement this. You can go to /users/invitation/new to send an invitation and an email will be sent with a link to accept the invitation with a URL like /users/invitation/accept?invitation_token=...
|
72
75
|
|
73
76
|
== Adding Invitable to a running application
|
74
77
|
|
@@ -88,6 +91,14 @@ Add :invitable to the devise line of your model, or to config.all in devise init
|
|
88
91
|
|
89
92
|
Override authenticate_resource! filter if you need to customize who can send invitations as it's explained in controller filters section.
|
90
93
|
|
94
|
+
== Contributors
|
95
|
+
|
96
|
+
Check them all at:
|
97
|
+
|
98
|
+
http://github.com/scambra/devise_invitable/contributors
|
99
|
+
|
100
|
+
Special thanks to http://github.com/rymai:"rymai" for rails3 support, his fork was a great help.
|
101
|
+
|
91
102
|
== Note on Patches/Pull Requests
|
92
103
|
|
93
104
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2
|
@@ -13,11 +13,11 @@ class Devise::InvitationsController < ApplicationController
|
|
13
13
|
|
14
14
|
# POST /resource/invitation
|
15
15
|
def create
|
16
|
-
self.resource = resource_class.
|
16
|
+
self.resource = resource_class.invite!(params[resource_name])
|
17
17
|
|
18
18
|
if resource.errors.empty?
|
19
19
|
set_flash_message :notice, :send_instructions
|
20
|
-
redirect_to
|
20
|
+
redirect_to after_update_path_for(resource_name)
|
21
21
|
else
|
22
22
|
render_with_scope :new
|
23
23
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
Hello <%= @resource.email
|
1
|
+
<p>Hello <%= @resource.email %>!</p>
|
2
2
|
|
3
|
-
Someone has invited you to <%= root_url %>, you can accept it through the link below
|
3
|
+
<p>Someone has invited you to <%= root_url %>, you can accept it through the link below.</p>
|
4
4
|
|
5
|
-
|
5
|
+
<p><%= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token) %></p>
|
6
6
|
|
7
|
-
If you don't want to accept the invitation, please ignore this email
|
8
|
-
Your account won't be created until you access the link above and set your password
|
7
|
+
<p>If you don't want to accept the invitation, please ignore this email.<br />
|
8
|
+
Your account won't be created until you access the link above and set your password.</p>
|
data/devise_invitable.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{devise_invitable}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Sergio Cambra"]
|
12
|
-
s.date = %q{2010-09-
|
12
|
+
s.date = %q{2010-09-15}
|
13
13
|
s.description = %q{It adds support for send invitations by email (it requires to be authenticated) and accept the invitation setting the password}
|
14
14
|
s.email = %q{sergio@entrecables.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -31,7 +31,6 @@ Gem::Specification.new do |s|
|
|
31
31
|
"app/views/devise/mailer/invitation.html.erb",
|
32
32
|
"config/locales/en.yml",
|
33
33
|
"devise_invitable.gemspec",
|
34
|
-
"init.rb",
|
35
34
|
"lib/devise_invitable.rb",
|
36
35
|
"lib/devise_invitable/controllers/helpers.rb",
|
37
36
|
"lib/devise_invitable/controllers/url_helpers.rb",
|
@@ -40,6 +39,7 @@ Gem::Specification.new do |s|
|
|
40
39
|
"lib/devise_invitable/rails.rb",
|
41
40
|
"lib/devise_invitable/routes.rb",
|
42
41
|
"lib/devise_invitable/schema.rb",
|
42
|
+
"lib/generators/devise_invitable/views_generator.rb",
|
43
43
|
"test/integration/invitable_test.rb",
|
44
44
|
"test/integration_tests_helper.rb",
|
45
45
|
"test/mailers/invitation_test.rb",
|
@@ -13,29 +13,25 @@ module Devise
|
|
13
13
|
# Examples:
|
14
14
|
#
|
15
15
|
# User.find(1).invited? # true/false
|
16
|
-
# User.
|
16
|
+
# User.invite!(:email => 'someone@example.com') # send invitation
|
17
17
|
# User.accept_invitation!(:invitation_token => '...') # accept invitation with a token
|
18
18
|
# User.find(1).accept_invitation! # accept invitation
|
19
|
-
# User.find(1).
|
19
|
+
# User.find(1).invite! # reset invitation status and send invitation again
|
20
20
|
module Invitable
|
21
|
-
|
22
|
-
base.class_eval do
|
23
|
-
extend ClassMethods
|
24
|
-
end
|
25
|
-
end
|
21
|
+
extend ActiveSupport::Concern
|
26
22
|
|
27
23
|
# Accept an invitation by clearing invitation token and confirming it if model
|
28
24
|
# is confirmable
|
29
25
|
def accept_invitation!
|
30
26
|
if self.invited?
|
31
27
|
self.invitation_token = nil
|
32
|
-
self.save
|
28
|
+
self.save
|
33
29
|
end
|
34
30
|
end
|
35
31
|
|
36
32
|
# Verifies whether a user has been invited or not
|
37
33
|
def invited?
|
38
|
-
|
34
|
+
persisted? && invitation_token.present?
|
39
35
|
end
|
40
36
|
|
41
37
|
# Send invitation by email
|
@@ -44,7 +40,7 @@ module Devise
|
|
44
40
|
end
|
45
41
|
|
46
42
|
# Reset invitation token and send invitation again
|
47
|
-
def
|
43
|
+
def invite!
|
48
44
|
if new_record? || invited?
|
49
45
|
self.skip_confirmation! if self.new_record? and self.respond_to? :skip_confirmation!
|
50
46
|
generate_invitation_token
|
@@ -53,6 +49,11 @@ module Devise
|
|
53
49
|
end
|
54
50
|
end
|
55
51
|
|
52
|
+
def resend_invitation!
|
53
|
+
ActiveSupport::Deprecation.warn('resend_invitation! has been renamed to invite!')
|
54
|
+
self.invite!
|
55
|
+
end
|
56
|
+
|
56
57
|
# Verify whether a invitation is active or not. If the user has been
|
57
58
|
# invited, we need to calculate if the invitation time has not expired
|
58
59
|
# for this user, in other words, if the invitation is still valid.
|
@@ -96,21 +97,26 @@ module Devise
|
|
96
97
|
# Attempt to find a user by it's email. If a record is not found, create a new
|
97
98
|
# user and send invitation to it. If user is found, returns the user with an
|
98
99
|
# email already exists error.
|
99
|
-
#
|
100
|
-
def
|
101
|
-
invitable =
|
100
|
+
# Attributes must contain the user email, other attributes will be set in the record
|
101
|
+
def invite!(attributes={})
|
102
|
+
invitable = find_or_initialize_with_error_by(:email, attributes.delete(:email))
|
103
|
+
invitable.attributes = attributes
|
102
104
|
|
103
105
|
if invitable.new_record?
|
104
|
-
invitable.errors.
|
105
|
-
invitable.errors.add(:email, :invalid) unless invitable.email.match Devise.email_regexp
|
106
|
+
invitable.errors.clear if invitable.email.match Devise.email_regexp
|
106
107
|
else
|
107
108
|
invitable.errors.add(:email, :taken) unless invitable.invited?
|
108
109
|
end
|
109
110
|
|
110
|
-
invitable.
|
111
|
+
invitable.invite! if invitable.errors.empty?
|
111
112
|
invitable
|
112
113
|
end
|
113
114
|
|
115
|
+
def send_invitation(attributes = {})
|
116
|
+
ActiveSupport::Deprecation.warn('send_invitation has been renamed to invite!')
|
117
|
+
self.invite!(attributes)
|
118
|
+
end
|
119
|
+
|
114
120
|
# Attempt to find a user by it's invitation_token to set it's password.
|
115
121
|
# If a user is found, reset it's password and automatically try saving
|
116
122
|
# the record. If not user is found, returns a new user containing an
|
@@ -121,7 +127,7 @@ module Devise
|
|
121
127
|
invitable.errors.add(:invitation_token, :invalid) if attributes[:invitation_token] && !invitable.new_record? && !invitable.valid_invitation?
|
122
128
|
if invitable.errors.empty?
|
123
129
|
invitable.attributes = attributes
|
124
|
-
invitable.accept_invitation!
|
130
|
+
invitable.accept_invitation!
|
125
131
|
end
|
126
132
|
invitable
|
127
133
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module DeviseInvitable
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
ActionView::Base.send :include, DeviseInvitable::Controllers::UrlHelpers
|
7
|
-
end
|
4
|
+
ActiveSupport.on_load(:action_controller) { include DeviseInvitable::Controllers::UrlHelpers }
|
5
|
+
ActiveSupport.on_load(:action_view) { include DeviseInvitable::Controllers::UrlHelpers }
|
8
6
|
|
9
7
|
config.after_initialize do
|
10
8
|
Devise::Mailer.send :include, DeviseInvitable::Mailer
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'generators/devise/views_generator'
|
2
|
+
|
3
|
+
module DeviseInvitable
|
4
|
+
module Generators
|
5
|
+
class ViewsGenerator < Devise::Generators::ViewsGenerator
|
6
|
+
source_root File.expand_path('../../../../app/views', __FILE__)
|
7
|
+
desc 'Copies all DeviseInvitable views to your application.'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -15,13 +15,13 @@ class InvitableTest < ActiveSupport::TestCase
|
|
15
15
|
user = new_user
|
16
16
|
3.times do
|
17
17
|
token = user.invitation_token
|
18
|
-
user.
|
18
|
+
user.invite!
|
19
19
|
assert_not_equal token, user.invitation_token
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
test 'should test invitation sent at with invite_for configuration value' do
|
24
|
-
user = create_user_with_invitation('')
|
24
|
+
user = create_user_with_invitation('token')
|
25
25
|
|
26
26
|
User.stubs(:invite_for).returns(nil)
|
27
27
|
user.invitation_sent_at = Time.now.utc
|
@@ -52,7 +52,7 @@ class InvitableTest < ActiveSupport::TestCase
|
|
52
52
|
invitation_tokens = []
|
53
53
|
3.times do
|
54
54
|
user = new_user
|
55
|
-
user.
|
55
|
+
user.invite!
|
56
56
|
token = user.invitation_token
|
57
57
|
assert !invitation_tokens.include?(token)
|
58
58
|
invitation_tokens << token
|
@@ -96,40 +96,56 @@ class InvitableTest < ActiveSupport::TestCase
|
|
96
96
|
user = new_user
|
97
97
|
assert_difference('ActionMailer::Base.deliveries.size') do
|
98
98
|
token = user.invitation_token
|
99
|
-
user.
|
99
|
+
user.invite!
|
100
100
|
assert_not_equal token, user.invitation_token
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
104
|
test 'should return a record with invitation token and no errors to send invitation by email' do
|
105
|
-
invited_user = User.
|
105
|
+
invited_user = User.invite!(:email => "valid@email.com")
|
106
106
|
assert invited_user.errors.blank?
|
107
107
|
assert_present invited_user.invitation_token
|
108
|
+
assert_equal 'valid@email.com', invited_user.email
|
109
|
+
assert invited_user.persisted?
|
110
|
+
end
|
111
|
+
|
112
|
+
test 'should set all attributes with no errors' do
|
113
|
+
invited_user = User.invite!(:email => "valid@email.com", :username => 'first name')
|
114
|
+
assert invited_user.errors.blank?
|
115
|
+
assert_equal 'first name', invited_user.username
|
116
|
+
assert invited_user.persisted?
|
108
117
|
end
|
109
118
|
|
110
119
|
test 'should return a record with errors if user was found by e-mail' do
|
111
120
|
user = create_user_with_invitation('')
|
112
121
|
user.update_attribute(:invitation_token, nil)
|
113
|
-
invited_user = User.
|
122
|
+
invited_user = User.invite!(:email => user.email)
|
114
123
|
assert_equal invited_user, user
|
115
124
|
assert_equal ['has already been taken'], invited_user.errors[:email]
|
116
125
|
end
|
117
126
|
|
118
127
|
test 'should return a new record with errors if e-mail is blank' do
|
119
|
-
invited_user = User.
|
128
|
+
invited_user = User.invite!(:email => '')
|
120
129
|
assert invited_user.new_record?
|
121
|
-
assert_equal ["can't be blank"
|
130
|
+
assert_equal ["can't be blank"], invited_user.errors[:email]
|
122
131
|
end
|
123
132
|
|
124
133
|
test 'should return a new record with errors if e-mail is invalid' do
|
125
|
-
invited_user = User.
|
134
|
+
invited_user = User.invite!(:email => 'invalid_email')
|
126
135
|
assert invited_user.new_record?
|
127
136
|
assert_equal ["is invalid"], invited_user.errors[:email]
|
128
137
|
end
|
129
138
|
|
139
|
+
test 'should set all attributes with errors if e-mail is invalid' do
|
140
|
+
invited_user = User.invite!(:email => "invalid_email.com", :username => 'first name')
|
141
|
+
assert invited_user.new_record?
|
142
|
+
assert_equal 'first name', invited_user.username
|
143
|
+
assert invited_user.errors.present?
|
144
|
+
end
|
145
|
+
|
130
146
|
test 'should find a user to set his password based on invitation_token' do
|
131
147
|
user = new_user
|
132
|
-
user.
|
148
|
+
user.invite!
|
133
149
|
|
134
150
|
invited_user = User.accept_invitation!(:invitation_token => user.invitation_token)
|
135
151
|
assert_equal invited_user, user
|
@@ -158,7 +174,7 @@ class InvitableTest < ActiveSupport::TestCase
|
|
158
174
|
|
159
175
|
test 'should set successfully user password given the new password and confirmation' do
|
160
176
|
user = new_user(:password => nil, :password_confirmation => nil)
|
161
|
-
user.
|
177
|
+
user.invite!
|
162
178
|
|
163
179
|
invited_user = User.accept_invitation!(
|
164
180
|
:invitation_token => user.invitation_token,
|
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:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 2
|
10
|
+
version: 0.3.2
|
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: 2010-09-
|
18
|
+
date: 2010-09-15 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -120,7 +120,6 @@ files:
|
|
120
120
|
- app/views/devise/mailer/invitation.html.erb
|
121
121
|
- config/locales/en.yml
|
122
122
|
- devise_invitable.gemspec
|
123
|
-
- init.rb
|
124
123
|
- lib/devise_invitable.rb
|
125
124
|
- lib/devise_invitable/controllers/helpers.rb
|
126
125
|
- lib/devise_invitable/controllers/url_helpers.rb
|
@@ -129,6 +128,7 @@ files:
|
|
129
128
|
- lib/devise_invitable/rails.rb
|
130
129
|
- lib/devise_invitable/routes.rb
|
131
130
|
- lib/devise_invitable/schema.rb
|
131
|
+
- lib/generators/devise_invitable/views_generator.rb
|
132
132
|
- test/integration/invitable_test.rb
|
133
133
|
- test/integration_tests_helper.rb
|
134
134
|
- test/mailers/invitation_test.rb
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'devise_invitable'
|