aihs_devise_invitable 0.4.rc
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +27 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +117 -0
- data/LICENSE +20 -0
- data/README.rdoc +187 -0
- data/Rakefile +57 -0
- data/app/controllers/devise/invitations_controller.rb +47 -0
- data/app/views/devise/invitations/edit.html.erb +14 -0
- data/app/views/devise/invitations/new.html.erb +12 -0
- data/app/views/devise/mailer/invitation.html.erb +8 -0
- data/app/views/devise/mailer/invitation_instructions.html.erb +8 -0
- data/config/locales/en.yml +9 -0
- data/devise_invitable.gemspec +143 -0
- data/lib/devise_invitable.rb +16 -0
- data/lib/devise_invitable/controllers/helpers.rb +7 -0
- data/lib/devise_invitable/controllers/url_helpers.rb +24 -0
- data/lib/devise_invitable/mailer.rb +14 -0
- data/lib/devise_invitable/model.rb +130 -0
- data/lib/devise_invitable/rails.rb +13 -0
- data/lib/devise_invitable/routes.rb +13 -0
- data/lib/devise_invitable/schema.rb +33 -0
- data/lib/devise_invitable/version.rb +3 -0
- data/lib/generators/active_record/devise_invitable_generator.rb +13 -0
- data/lib/generators/active_record/templates/migration.rb +20 -0
- data/lib/generators/devise_invitable/devise_invitable_generator.rb +16 -0
- data/lib/generators/devise_invitable/install_generator.rb +35 -0
- data/lib/generators/devise_invitable/views_generator.rb +10 -0
- data/test/generators_test.rb +45 -0
- data/test/integration/invitation_test.rb +107 -0
- data/test/integration_tests_helper.rb +58 -0
- data/test/mailers/invitation_mail_test.rb +63 -0
- data/test/model_tests_helper.rb +41 -0
- data/test/models/invitable_test.rb +213 -0
- data/test/models_test.rb +32 -0
- data/test/rails_app/app/controllers/admins_controller.rb +6 -0
- data/test/rails_app/app/controllers/application_controller.rb +3 -0
- data/test/rails_app/app/controllers/home_controller.rb +4 -0
- data/test/rails_app/app/controllers/users_controller.rb +12 -0
- data/test/rails_app/app/helpers/application_helper.rb +2 -0
- data/test/rails_app/app/models/octopussy.rb +11 -0
- data/test/rails_app/app/models/user.rb +4 -0
- data/test/rails_app/app/views/home/index.html.erb +0 -0
- data/test/rails_app/app/views/layouts/application.html.erb +16 -0
- data/test/rails_app/app/views/users/invitations/new.html.erb +15 -0
- data/test/rails_app/config.ru +4 -0
- data/test/rails_app/config/application.rb +46 -0
- data/test/rails_app/config/boot.rb +14 -0
- data/test/rails_app/config/database.yml +22 -0
- data/test/rails_app/config/environment.rb +5 -0
- data/test/rails_app/config/environments/development.rb +26 -0
- data/test/rails_app/config/environments/production.rb +49 -0
- data/test/rails_app/config/environments/test.rb +35 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/devise.rb +174 -0
- data/test/rails_app/config/initializers/inflections.rb +10 -0
- data/test/rails_app/config/initializers/mime_types.rb +5 -0
- data/test/rails_app/config/initializers/secret_token.rb +7 -0
- data/test/rails_app/config/initializers/session_store.rb +8 -0
- data/test/rails_app/config/locales/en.yml +5 -0
- data/test/rails_app/config/routes.rb +4 -0
- data/test/rails_app/script/rails +6 -0
- data/test/routes_test.rb +20 -0
- data/test/test_helper.rb +31 -0
- metadata +222 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
<h2>Set your password</h2>
|
2
|
+
|
3
|
+
<%= form_for resource, :as => resource_name, :url => invitation_path(resource_name), :html => { :method => :put } do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
<%= f.hidden_field :invitation_token %>
|
6
|
+
|
7
|
+
<p><%= f.label :password %><br />
|
8
|
+
<%= f.password_field :password %></p>
|
9
|
+
|
10
|
+
<p><%= f.label :password_confirmation %><br />
|
11
|
+
<%= f.password_field :password_confirmation %></p>
|
12
|
+
|
13
|
+
<p><%= f.submit "Set my password" %></p>
|
14
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h2>Send invitation</h2>
|
2
|
+
|
3
|
+
<%= form_for resource, :as => resource_name, :url => invitation_path(resource_name) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<p><%= f.label :email %><br />
|
7
|
+
<%= f.text_field :email %></p>
|
8
|
+
|
9
|
+
<p><%= f.submit "Send an invitation" %></p>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= link_to "Home", after_sign_in_path_for(resource_name) %><br />
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<p>Hello <%= @resource.email %>!</p>
|
2
|
+
|
3
|
+
<p>Someone has invited you to <%= root_url %>, you can accept it through the link below.</p>
|
4
|
+
|
5
|
+
<p><%= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token) %></p>
|
6
|
+
|
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>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<p>Hello <%= @resource.email %>!</p>
|
2
|
+
|
3
|
+
<p>Someone has invited you to <%= root_url %>, you can accept it through the link below.</p>
|
4
|
+
|
5
|
+
<p><%= link_to 'Accept invitation', accept_invitation_url(@resource, :invitation_token => @resource.invitation_token) %></p>
|
6
|
+
|
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>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
en:
|
2
|
+
devise:
|
3
|
+
invitations:
|
4
|
+
send_instructions: 'An invitation email has been sent to %{email}.'
|
5
|
+
invitation_token_invalid: 'The invitation token provided is not valid!'
|
6
|
+
updated: 'Your password was set successfully. You are now signed in.'
|
7
|
+
mailer:
|
8
|
+
invitation_instructions:
|
9
|
+
subject: 'Invitation instructions'
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{devise_invitable}
|
8
|
+
s.version = "0.4.rc"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Sergio Cambra"]
|
12
|
+
s.date = %q{2010-10-05}
|
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
|
+
s.email = %q{sergio@entrecables.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"app/controllers/devise/invitations_controller.rb",
|
28
|
+
"app/views/devise/invitations/edit.html.erb",
|
29
|
+
"app/views/devise/invitations/new.html.erb",
|
30
|
+
"app/views/devise/mailer/invitation.html.erb",
|
31
|
+
"config/locales/en.yml",
|
32
|
+
"devise_invitable.gemspec",
|
33
|
+
"lib/devise_invitable.rb",
|
34
|
+
"lib/devise_invitable/controllers/helpers.rb",
|
35
|
+
"lib/devise_invitable/controllers/url_helpers.rb",
|
36
|
+
"lib/devise_invitable/mailer.rb",
|
37
|
+
"lib/devise_invitable/model.rb",
|
38
|
+
"lib/devise_invitable/rails.rb",
|
39
|
+
"lib/devise_invitable/routes.rb",
|
40
|
+
"lib/devise_invitable/schema.rb",
|
41
|
+
"lib/devise_invitable/version.rb",
|
42
|
+
"lib/generators/active_record/devise_invitable_generator.rb",
|
43
|
+
"lib/generators/active_record/templates/migration.rb",
|
44
|
+
"lib/generators/devise_invitable/devise_invitable_generator.rb",
|
45
|
+
"lib/generators/devise_invitable/install_generator.rb",
|
46
|
+
"lib/generators/devise_invitable/views_generator.rb",
|
47
|
+
"test/generators_test.rb",
|
48
|
+
"test/integration/invitation_test.rb",
|
49
|
+
"test/integration_tests_helper.rb",
|
50
|
+
"test/mailers/invitation_mail_test.rb",
|
51
|
+
"test/model_tests_helper.rb",
|
52
|
+
"test/models/invitable_test.rb",
|
53
|
+
"test/models_test.rb",
|
54
|
+
"test/rails_app/app/controllers/admins_controller.rb",
|
55
|
+
"test/rails_app/app/controllers/application_controller.rb",
|
56
|
+
"test/rails_app/app/controllers/home_controller.rb",
|
57
|
+
"test/rails_app/app/controllers/users_controller.rb",
|
58
|
+
"test/rails_app/app/helpers/application_helper.rb",
|
59
|
+
"test/rails_app/app/models/octopussy.rb",
|
60
|
+
"test/rails_app/app/models/user.rb",
|
61
|
+
"test/rails_app/app/views/home/index.html.erb",
|
62
|
+
"test/rails_app/app/views/layouts/application.html.erb",
|
63
|
+
"test/rails_app/app/views/users/invitations/new.html.erb",
|
64
|
+
"test/rails_app/config.ru",
|
65
|
+
"test/rails_app/config/application.rb",
|
66
|
+
"test/rails_app/config/boot.rb",
|
67
|
+
"test/rails_app/config/database.yml",
|
68
|
+
"test/rails_app/config/environment.rb",
|
69
|
+
"test/rails_app/config/environments/development.rb",
|
70
|
+
"test/rails_app/config/environments/production.rb",
|
71
|
+
"test/rails_app/config/environments/test.rb",
|
72
|
+
"test/rails_app/config/initializers/backtrace_silencers.rb",
|
73
|
+
"test/rails_app/config/initializers/devise.rb",
|
74
|
+
"test/rails_app/config/initializers/inflections.rb",
|
75
|
+
"test/rails_app/config/initializers/mime_types.rb",
|
76
|
+
"test/rails_app/config/initializers/secret_token.rb",
|
77
|
+
"test/rails_app/config/initializers/session_store.rb",
|
78
|
+
"test/rails_app/config/locales/en.yml",
|
79
|
+
"test/rails_app/config/routes.rb",
|
80
|
+
"test/rails_app/script/rails",
|
81
|
+
"test/routes_test.rb",
|
82
|
+
"test/test_helper.rb"
|
83
|
+
]
|
84
|
+
s.homepage = %q{http://github.com/scambra/devise_invitable}
|
85
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
86
|
+
s.require_paths = ["lib"]
|
87
|
+
s.rubygems_version = %q{1.3.7}
|
88
|
+
s.summary = %q{An invitation strategy for devise}
|
89
|
+
s.test_files = [
|
90
|
+
"test/generators_test.rb",
|
91
|
+
"test/integration/invitation_test.rb",
|
92
|
+
"test/integration_tests_helper.rb",
|
93
|
+
"test/mailers/invitation_mail_test.rb",
|
94
|
+
"test/model_tests_helper.rb",
|
95
|
+
"test/models/invitable_test.rb",
|
96
|
+
"test/models_test.rb",
|
97
|
+
"test/rails_app/app/controllers/admins_controller.rb",
|
98
|
+
"test/rails_app/app/controllers/application_controller.rb",
|
99
|
+
"test/rails_app/app/controllers/home_controller.rb",
|
100
|
+
"test/rails_app/app/controllers/users_controller.rb",
|
101
|
+
"test/rails_app/app/helpers/application_helper.rb",
|
102
|
+
"test/rails_app/app/models/octopussy.rb",
|
103
|
+
"test/rails_app/app/models/user.rb",
|
104
|
+
"test/rails_app/config/application.rb",
|
105
|
+
"test/rails_app/config/boot.rb",
|
106
|
+
"test/rails_app/config/environment.rb",
|
107
|
+
"test/rails_app/config/environments/development.rb",
|
108
|
+
"test/rails_app/config/environments/production.rb",
|
109
|
+
"test/rails_app/config/environments/test.rb",
|
110
|
+
"test/rails_app/config/initializers/backtrace_silencers.rb",
|
111
|
+
"test/rails_app/config/initializers/devise.rb",
|
112
|
+
"test/rails_app/config/initializers/inflections.rb",
|
113
|
+
"test/rails_app/config/initializers/mime_types.rb",
|
114
|
+
"test/rails_app/config/initializers/secret_token.rb",
|
115
|
+
"test/rails_app/config/initializers/session_store.rb",
|
116
|
+
"test/rails_app/config/routes.rb",
|
117
|
+
"test/routes_test.rb",
|
118
|
+
"test/test_helper.rb"
|
119
|
+
]
|
120
|
+
|
121
|
+
if s.respond_to? :specification_version then
|
122
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
123
|
+
s.specification_version = 3
|
124
|
+
|
125
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
126
|
+
s.add_development_dependency(%q<mocha>, [">= 0.9.8"])
|
127
|
+
s.add_development_dependency(%q<capybara>, [">= 0.3.9"])
|
128
|
+
s.add_development_dependency(%q<rails>, ["~> 3.0.0"])
|
129
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
130
|
+
else
|
131
|
+
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
132
|
+
s.add_dependency(%q<capybara>, [">= 0.3.9"])
|
133
|
+
s.add_dependency(%q<rails>, ["~> 3.0.0"])
|
134
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
135
|
+
end
|
136
|
+
else
|
137
|
+
s.add_dependency(%q<mocha>, [">= 0.9.8"])
|
138
|
+
s.add_dependency(%q<capybara>, [">= 0.3.9"])
|
139
|
+
s.add_dependency(%q<rails>, ["~> 3.0.0"])
|
140
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'devise'
|
2
|
+
|
3
|
+
require 'devise_invitable/mailer'
|
4
|
+
require 'devise_invitable/routes'
|
5
|
+
require 'devise_invitable/schema'
|
6
|
+
require 'devise_invitable/controllers/url_helpers'
|
7
|
+
require 'devise_invitable/controllers/helpers'
|
8
|
+
require 'devise_invitable/rails'
|
9
|
+
|
10
|
+
module Devise
|
11
|
+
# The period the generated invitation token is valid.
|
12
|
+
mattr_accessor :invite_for
|
13
|
+
@@invite_for = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
Devise.add_module :invitable, :controller => :invitations, :model => 'devise_invitable/model', :route => :invitation
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module DeviseInvitable
|
2
|
+
module Controllers
|
3
|
+
module UrlHelpers
|
4
|
+
[:path, :url].each do |path_or_url|
|
5
|
+
[nil, :new_, :accept_].each do |action|
|
6
|
+
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
7
|
+
def #{action}invitation_#{path_or_url}(resource, *args)
|
8
|
+
resource = case resource
|
9
|
+
when Symbol, String
|
10
|
+
resource
|
11
|
+
when Class
|
12
|
+
resource.name.underscore
|
13
|
+
else
|
14
|
+
resource.class.name.underscore
|
15
|
+
end
|
16
|
+
|
17
|
+
send("#{action}\#{resource}_invitation_#{path_or_url}", *args)
|
18
|
+
end
|
19
|
+
URL_HELPERS
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module DeviseInvitable
|
2
|
+
module Mailer
|
3
|
+
|
4
|
+
# Deliver an invitation email
|
5
|
+
def invitation_instructions(record)
|
6
|
+
setup_mail(record, :invitation_instructions)
|
7
|
+
end
|
8
|
+
|
9
|
+
def invitation(record)
|
10
|
+
ActiveSupport::Deprecation.warn('invitation has been renamed to invitation_instructions')
|
11
|
+
invitation_instructions(record)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,130 @@
|
|
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
|
+
# Accept an invitation by clearing invitation token and confirming it if model
|
25
|
+
# is confirmable
|
26
|
+
def accept_invitation!
|
27
|
+
if self.invited? && self.valid?
|
28
|
+
self.invitation_token = nil
|
29
|
+
self.save
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Verifies whether a user has been invited or not
|
34
|
+
def invited?
|
35
|
+
persisted? && invitation_token.present?
|
36
|
+
end
|
37
|
+
|
38
|
+
# Reset invitation token and send invitation again
|
39
|
+
def invite!
|
40
|
+
if new_record? || invited?
|
41
|
+
self.skip_confirmation! if self.new_record? && self.respond_to?(:skip_confirmation!)
|
42
|
+
generate_invitation_token if self.invitation_token.nil?
|
43
|
+
self.invitation_sent_at = Time.now.utc
|
44
|
+
save(:validate => false)
|
45
|
+
::Devise.mailer.invitation_instructions(self).deliver
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Verify whether a invitation is active or not. If the user has been
|
50
|
+
# invited, we need to calculate if the invitation time has not expired
|
51
|
+
# for this user, in other words, if the invitation is still valid.
|
52
|
+
def valid_invitation?
|
53
|
+
invited? && invitation_period_valid?
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
# Checks if the invitation for the user is within the limit time.
|
59
|
+
# We do this by calculating if the difference between today and the
|
60
|
+
# invitation sent date does not exceed the invite for time configured.
|
61
|
+
# Invite_for is a model configuration, must always be an integer value.
|
62
|
+
#
|
63
|
+
# Example:
|
64
|
+
#
|
65
|
+
# # invite_for = 1.day and invitation_sent_at = today
|
66
|
+
# invitation_period_valid? # returns true
|
67
|
+
#
|
68
|
+
# # invite_for = 5.days and invitation_sent_at = 4.days.ago
|
69
|
+
# invitation_period_valid? # returns true
|
70
|
+
#
|
71
|
+
# # invite_for = 5.days and invitation_sent_at = 5.days.ago
|
72
|
+
# invitation_period_valid? # returns false
|
73
|
+
#
|
74
|
+
# # invite_for = nil
|
75
|
+
# invitation_period_valid? # will always return true
|
76
|
+
#
|
77
|
+
def invitation_period_valid?
|
78
|
+
invitation_sent_at && (self.class.invite_for.to_i.zero? || invitation_sent_at.utc >= self.class.invite_for.ago)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Generates a new random token for invitation, and stores the time
|
82
|
+
# this token is being generated
|
83
|
+
def generate_invitation_token
|
84
|
+
self.invitation_token = self.class.invitation_token
|
85
|
+
end
|
86
|
+
|
87
|
+
module ClassMethods
|
88
|
+
# Attempt to find a user by it's email. If a record is not found, create a new
|
89
|
+
# user and send invitation to it. If user is found, returns the user with an
|
90
|
+
# email already exists error.
|
91
|
+
# Attributes must contain the user email, other attributes will be set in the record
|
92
|
+
def invite!(attributes={})
|
93
|
+
invitable = find_or_initialize_with_error_by(:email, attributes.delete(:email))
|
94
|
+
invitable.attributes = attributes
|
95
|
+
|
96
|
+
if invitable.new_record?
|
97
|
+
invitable.errors.clear if invitable.email.try(:match, Devise.email_regexp)
|
98
|
+
else
|
99
|
+
invitable.errors.add(:email, :taken) unless invitable.invited?
|
100
|
+
end
|
101
|
+
|
102
|
+
invitable.invite! if invitable.errors.empty?
|
103
|
+
invitable
|
104
|
+
end
|
105
|
+
|
106
|
+
# Attempt to find a user by it's invitation_token to set it's password.
|
107
|
+
# If a user is found, reset it's password and automatically try saving
|
108
|
+
# the record. If not user is found, returns a new user containing an
|
109
|
+
# error in invitation_token attribute.
|
110
|
+
# Attributes must contain invitation_token, password and confirmation
|
111
|
+
def accept_invitation!(attributes={})
|
112
|
+
invitable = find_or_initialize_with_error_by(:invitation_token, attributes.delete(:invitation_token))
|
113
|
+
invitable.errors.add(:invitation_token, :invalid) if invitable.invitation_token && invitable.persisted? && !invitable.valid_invitation?
|
114
|
+
if invitable.errors.empty?
|
115
|
+
invitable.attributes = attributes
|
116
|
+
invitable.accept_invitation!
|
117
|
+
end
|
118
|
+
invitable
|
119
|
+
end
|
120
|
+
|
121
|
+
# Generate a token checking if one does not already exist in the database.
|
122
|
+
def invitation_token
|
123
|
+
generate_token(:invitation_token)
|
124
|
+
end
|
125
|
+
|
126
|
+
Devise::Models.config(self, :invite_for)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module DeviseInvitable
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
ActiveSupport.on_load(:action_controller) { include DeviseInvitable::Controllers::UrlHelpers }
|
5
|
+
ActiveSupport.on_load(:action_view) { include DeviseInvitable::Controllers::UrlHelpers }
|
6
|
+
|
7
|
+
config.after_initialize do
|
8
|
+
require 'devise/mailer'
|
9
|
+
Devise::Mailer.send :include, DeviseInvitable::Mailer
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
class Mapper
|
3
|
+
|
4
|
+
protected
|
5
|
+
def devise_invitation(mapping, controllers)
|
6
|
+
resource :invitation, :only => [:new, :create, :update],
|
7
|
+
:path => mapping.path_names[:invitation], :controller => controllers[:invitations] do
|
8
|
+
get :edit, :path => mapping.path_names[:accept], :as => :accept
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DeviseInvitable
|
2
|
+
module Schema
|
3
|
+
# Add invitation_token and invitation_sent_at columns in the resource's database table.
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# # For a new resource migration:
|
8
|
+
# create_table :the_resources do
|
9
|
+
# t.database_authenticatable :null => false # you need at least this
|
10
|
+
# t.invitable
|
11
|
+
# ...
|
12
|
+
# end
|
13
|
+
# add_index :the_resources, :invitation_token # for invitable
|
14
|
+
#
|
15
|
+
# # or if the resource's table already exists, define a migration and put this in:
|
16
|
+
# change_table :the_resources do |t|
|
17
|
+
# t.string :invitation_token, :limit => 60
|
18
|
+
# t.datetime :invitation_sent_at
|
19
|
+
# t.index :invitation_token # for invitable
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # And allow encrypted_password to be null:
|
23
|
+
# change_column :the_resources, :encrypted_password, :string, :null => true
|
24
|
+
# # the following line is only if you use Devise's encryptable module!
|
25
|
+
# change_column :the_resources, :password_salt, :string, :null => true
|
26
|
+
def invitable
|
27
|
+
apply_devise_schema :invitation_token, String, :limit => 60
|
28
|
+
apply_devise_schema :invitation_sent_at, DateTime
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Devise::Schema.send :include, DeviseInvitable::Schema
|