devise_certifiable 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +10 -0
- data/LICENSE +19 -0
- data/README.rdoc +53 -0
- data/Rakefile +26 -0
- data/app/controllers/devise/certifications_controller.rb +34 -0
- data/app/views/devise/certifications/edit.html.erb +14 -0
- data/app/views/devise/mailer/certification_request.html.erb +8 -0
- data/config/locales/en.yml +17 -0
- data/devise_certifiable.gemspec +25 -0
- data/lib/devise_certifiable.rb +13 -0
- data/lib/devise_certifiable/controllers/helpers.rb +7 -0
- data/lib/devise_certifiable/controllers/url_helpers.rb +24 -0
- data/lib/devise_certifiable/mailer.rb +10 -0
- data/lib/devise_certifiable/model.rb +98 -0
- data/lib/devise_certifiable/rails.rb +12 -0
- data/lib/devise_certifiable/routes.rb +10 -0
- data/lib/devise_certifiable/schema.rb +12 -0
- data/lib/devise_certifiable/version.rb +3 -0
- data/lib/generators/active_record/devise_certifiable_generator.rb +13 -0
- data/lib/generators/active_record/templates/migration.rb +18 -0
- data/lib/generators/devise_certifiable/devise_certifiable_generator.rb +16 -0
- data/lib/generators/devise_certifiable/install_generator.rb +11 -0
- data/test/controllers/url_helpers_test.rb +34 -0
- data/test/generators/active_record_generator_test.rb +24 -0
- data/test/generators/devise_certifiable_generator_test.rb +27 -0
- data/test/generators/install_generator_test.rb +15 -0
- data/test/integration/certification_test.rb +80 -0
- data/test/mailers/certification_request_test.rb +63 -0
- data/test/models/certifiable_test.rb +172 -0
- data/test/models_test.rb +26 -0
- data/test/orm/active_record.rb +4 -0
- data/test/rails_app/Rakefile +10 -0
- data/test/rails_app/app/active_record/user.rb +7 -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 +3 -0
- data/test/rails_app/app/models/monster.rb +5 -0
- data/test/rails_app/app/views/home/index.html.erb +1 -0
- data/test/rails_app/app/views/layouts/application.html.erb +20 -0
- data/test/rails_app/app/views/users/index.html.erb +1 -0
- data/test/rails_app/config.ru +4 -0
- data/test/rails_app/config/application.rb +29 -0
- data/test/rails_app/config/boot.rb +11 -0
- data/test/rails_app/config/database.yml +18 -0
- data/test/rails_app/config/environment.rb +5 -0
- data/test/rails_app/config/environments/development.rb +22 -0
- data/test/rails_app/config/environments/production.rb +33 -0
- data/test/rails_app/config/environments/test.rb +33 -0
- data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_app/config/initializers/devise.rb +179 -0
- data/test/rails_app/config/initializers/inflections.rb +2 -0
- data/test/rails_app/config/initializers/secret_token.rb +2 -0
- data/test/rails_app/config/routes.rb +6 -0
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +17 -0
- data/test/rails_app/lib/shared_user.rb +7 -0
- data/test/rails_app/script/rails +6 -0
- data/test/routes_test.rb +11 -0
- data/test/support/assertions.rb +24 -0
- data/test/support/helpers.rb +39 -0
- data/test/support/integration.rb +59 -0
- data/test/support/locale/en.yml +4 -0
- data/test/test_helper.rb +20 -0
- metadata +203 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2011 Luis Gracia
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
= devise_certifiable
|
2
|
+
|
3
|
+
Sign up certification strategy for devise[http://github.com/plataformatec/devise]. New sign up users need to be certified before they can sign in. After sign up an email is sent to the email address specified in the devise configuration option _config.mailer_sender_.
|
4
|
+
|
5
|
+
Devise_certifiable has been tested with Devise 1.2.1 and Rails 3.0.6 using ActiveRecord, but similar version should work as well (ie. Devise 1.2.x and Rails 3.0.x).
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
rails generate devise_certifiable MODEL
|
10
|
+
|
11
|
+
will add _:certifiable_ to model _MODEL_ and create a migration file.
|
12
|
+
|
13
|
+
== Configuration
|
14
|
+
|
15
|
+
There are no configuration options at the moment.
|
16
|
+
|
17
|
+
=== Controllers
|
18
|
+
|
19
|
+
By default devise_certifiable follows Devise authentication to allow certifications. You can customize how to authenticate for a certifier overriding _:authenticate_certifier!_ in _application_controller.rb_. For example using CanCan[https://github.com/ryanb/cancan]:
|
20
|
+
|
21
|
+
def authenticate_certifier!
|
22
|
+
authorize! :certify, User
|
23
|
+
end
|
24
|
+
|
25
|
+
=== Views
|
26
|
+
|
27
|
+
You can customize the views and mails by doing:
|
28
|
+
|
29
|
+
rails generate devise_certifiable:install views
|
30
|
+
|
31
|
+
This will copy the views to app/views/devise.
|
32
|
+
|
33
|
+
=== Localization
|
34
|
+
|
35
|
+
Localization can be customized by:
|
36
|
+
|
37
|
+
rails generate devise_certifiable:install
|
38
|
+
|
39
|
+
This will copy the locale file to your rails tree.
|
40
|
+
|
41
|
+
== Contributing to devise_certifiable
|
42
|
+
|
43
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
44
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
45
|
+
* Fork the project
|
46
|
+
* Start a feature/bugfix branch
|
47
|
+
* Commit and push until you are happy with your contribution
|
48
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
49
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
50
|
+
|
51
|
+
== Copyright
|
52
|
+
|
53
|
+
Copyright (c) 2011 Luis Gracia. See LICENSE for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
desc 'Default: run tests for all ORMs.'
|
7
|
+
task :default => :pre_commit
|
8
|
+
|
9
|
+
desc 'Run Devise tests for all ORMs.'
|
10
|
+
task :pre_commit do
|
11
|
+
Dir[File.join(File.dirname(__FILE__), 'test', 'orm', '*.rb')].each do |file|
|
12
|
+
orm = File.basename(file).split(".").first
|
13
|
+
# "Some day, my son, rake's inner wisdom will reveal itself. Until then,
|
14
|
+
# take this `system` -- may its brute force protect you well."
|
15
|
+
#exit 1 unless system "rake test DEVISE_ORM=#{orm}"
|
16
|
+
system "rake test DEVISE_ORM=#{orm}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Run std unit tests.'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib'
|
23
|
+
test.libs << 'test'
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Devise::CertificationsController < ApplicationController
|
2
|
+
include Devise::Controllers::InternalHelpers
|
3
|
+
before_filter :authenticate_certifier!
|
4
|
+
|
5
|
+
# GET /resource/certification/edit?certification_token=abcdef
|
6
|
+
def edit
|
7
|
+
self.resource = resource_class.find_resource_by_token(params[:certification_token])
|
8
|
+
|
9
|
+
if resource.errors.empty?
|
10
|
+
render_with_scope :edit
|
11
|
+
else
|
12
|
+
set_flash_message(:alert, :certification_token_invalid)
|
13
|
+
redirect_to self.resource
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# PUT /resource/certification
|
18
|
+
def update
|
19
|
+
self.resource = resource_class.certify_by_token(params[resource_name][:certification_token], current_certifier)
|
20
|
+
params[resource_name].delete(:certification_token)
|
21
|
+
self.resource.update_attributes(params[resource_name])
|
22
|
+
if resource.errors.empty?
|
23
|
+
set_flash_message :notice, :certified
|
24
|
+
redirect_to self.resource
|
25
|
+
else
|
26
|
+
render_with_scope :edit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
def current_certifier
|
32
|
+
current_user
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<h2><%= resource_name.capitalize %> Certification</h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => certification_path(resource_name), :html => { :method => :put }) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<table>
|
7
|
+
<tr>
|
8
|
+
<td><%= f.label :email %></td>
|
9
|
+
<td><%= f.label :email, resource.email %></td>
|
10
|
+
</tr>
|
11
|
+
</table>
|
12
|
+
<%= f.hidden_field :certification_token -%>
|
13
|
+
<p><%= f.submit "Certify" %></p>
|
14
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<p>Dear Admin,</p>
|
2
|
+
|
3
|
+
<p>The following user has requested access to the site:</p>
|
4
|
+
<table>
|
5
|
+
<tr><td>Email:</td><td><%= @resource.email %></td></tr>
|
6
|
+
</table>
|
7
|
+
|
8
|
+
<p><%= link_to 'Certify', edit_certification_url(@resource, :certification_token => @resource.certification_token) %></p>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
en:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
certification_authority_missing: '(certification authority) not specified'
|
5
|
+
already_certified: 'was already certified!'
|
6
|
+
|
7
|
+
|
8
|
+
devise:
|
9
|
+
failure:
|
10
|
+
:uncertified: 'Your account needs to be certified.'
|
11
|
+
mailer:
|
12
|
+
certification_request:
|
13
|
+
subject: 'Certification request'
|
14
|
+
certifications:
|
15
|
+
certification_token_invalid: 'The certification token provided is not valid!'
|
16
|
+
certified: 'Successfuly certified user'
|
17
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "devise_certifiable/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "devise_certifiable"
|
7
|
+
s.version = DeviseCertifiable::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Luis Gracia"]
|
10
|
+
s.email = ["lgraval@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/luisico/devise_certifiable"
|
12
|
+
s.summary = %q{Sign up certification strategy for devise}
|
13
|
+
s.description = %q{New sign ups need to be certified before they can sign in}
|
14
|
+
|
15
|
+
s.add_dependency('rails', '~> 3.0.0')
|
16
|
+
s.add_dependency('devise', '~> 1.2.0')
|
17
|
+
|
18
|
+
s.add_development_dependency('devise_invitable', '~> 0.4.0')
|
19
|
+
s.add_development_dependency('bundler', '~> 1.0.12')
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'devise'
|
2
|
+
|
3
|
+
require 'devise_certifiable/mailer'
|
4
|
+
require 'devise_certifiable/routes'
|
5
|
+
require 'devise_certifiable/schema'
|
6
|
+
require 'devise_certifiable/controllers/url_helpers'
|
7
|
+
require 'devise_certifiable/controllers/helpers'
|
8
|
+
require 'devise_certifiable/rails'
|
9
|
+
|
10
|
+
module Devise
|
11
|
+
end
|
12
|
+
|
13
|
+
Devise.add_module :certifiable, :model => 'devise_certifiable/model', :route => :certification, :controller => :certifications
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module DeviseCertifiable
|
2
|
+
module Controllers
|
3
|
+
module UrlHelpers
|
4
|
+
[:path, :url].each do |path_or_url|
|
5
|
+
[nil, :edit_].each do |action|
|
6
|
+
class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
|
7
|
+
def #{action}certification_#{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}_certification_#{path_or_url}", *args)
|
18
|
+
end
|
19
|
+
URL_HELPERS
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Devise
|
2
|
+
module Models
|
3
|
+
module Certifiable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
belongs_to :certified_by, :polymorphic => true
|
8
|
+
before_create :generate_certification_token, :if => :certification_required?
|
9
|
+
after_create :request_certification, :if => :certification_required?
|
10
|
+
alias_method_chain :send_confirmation_instructions, :certification
|
11
|
+
end
|
12
|
+
|
13
|
+
def certify!(certification_authority)
|
14
|
+
unless_certified do
|
15
|
+
unless certification_authority.blank?
|
16
|
+
self.certification_token = nil
|
17
|
+
self.certified_at = Time.now
|
18
|
+
self.certified_by = certification_authority
|
19
|
+
save(:validate => false)
|
20
|
+
send_confirmation_instructions if confirmation_required?
|
21
|
+
else
|
22
|
+
self.errors.add(:certified_by, :certification_authority_missing)
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def certified?
|
29
|
+
!!certified_at
|
30
|
+
end
|
31
|
+
|
32
|
+
# Deliver certification request to certification authority
|
33
|
+
def request_certification
|
34
|
+
if self.respond_to?(:invite!) && self.invitation_token.present?
|
35
|
+
certify!(self.invited_by)
|
36
|
+
else
|
37
|
+
generate_certification_token! if self.certification_token.nil?
|
38
|
+
::Devise.mailer.certification_request(self).deliver
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def active_for_authentication?
|
43
|
+
super && certified?
|
44
|
+
end
|
45
|
+
|
46
|
+
def inactive_message
|
47
|
+
!certified? ? :uncertified : super
|
48
|
+
end
|
49
|
+
protected
|
50
|
+
|
51
|
+
def certification_required?
|
52
|
+
!certified?
|
53
|
+
end
|
54
|
+
|
55
|
+
def send_confirmation_instructions_with_certification
|
56
|
+
send_confirmation_instructions_without_certification if certified?
|
57
|
+
end
|
58
|
+
|
59
|
+
def unless_certified
|
60
|
+
unless certified?
|
61
|
+
yield
|
62
|
+
else
|
63
|
+
self.errors.add(:email, :already_certified)
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generate certification token
|
69
|
+
def generate_certification_token
|
70
|
+
self.certification_token = self.class.certification_token
|
71
|
+
self.certified_at = nil
|
72
|
+
self.certified_by = nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def generate_certification_token!
|
76
|
+
generate_certification_token && save(:validate => false)
|
77
|
+
end
|
78
|
+
|
79
|
+
module ClassMethods
|
80
|
+
# Generate token
|
81
|
+
def certification_token
|
82
|
+
generate_token(:certification_token)
|
83
|
+
end
|
84
|
+
|
85
|
+
def certify_by_token(certification_token, certification_authority)
|
86
|
+
certifiable = find_resource_by_token(certification_token)
|
87
|
+
certifiable.certify!(certification_authority) if certifiable.persisted?
|
88
|
+
certifiable
|
89
|
+
end
|
90
|
+
|
91
|
+
def find_resource_by_token(certification_token)
|
92
|
+
certifiable = find_or_initialize_with_error_by(:certification_token, certification_token)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module DeviseCertifiable
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
ActiveSupport.on_load(:action_controller) { include DeviseCertifiable::Controllers::UrlHelpers }
|
5
|
+
ActiveSupport.on_load(:action_view) { include DeviseCertifiable::Controllers::UrlHelpers }
|
6
|
+
|
7
|
+
config.to_prepare do
|
8
|
+
require 'devise/mailer'
|
9
|
+
Devise::Mailer.send :include, DeviseCertifiable::Mailer
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
class Mapper
|
3
|
+
|
4
|
+
protected
|
5
|
+
def devise_certification(mapping, controllers)
|
6
|
+
resource :certification, :only => [:edit, :update],
|
7
|
+
:path => mapping.path_names[:certification], :controller => controllers[:certifications]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module DeviseCertifiable
|
2
|
+
module Schema
|
3
|
+
def certifiable
|
4
|
+
apply_devise_schema :certification_token, String, :limit => 60
|
5
|
+
apply_devise_schema :certified_at, DateTime
|
6
|
+
apply_devise_schema :certified_by_id, Integer
|
7
|
+
apply_devise_schema :certified_by_type, String
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Devise::Schema.send :include, DeviseCertifiable::Schema
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Generators
|
5
|
+
class DeviseCertifiableGenerator < ActiveRecord::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __FILE__)
|
7
|
+
|
8
|
+
def copy_devise_migration
|
9
|
+
migration_template "migration.rb", "db/migrate/devise_certifiable_add_to_#{table_name}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class DeviseCertifiableAddTo<%= table_name.camelize %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
change_table :<%= table_name %> do |t|
|
4
|
+
t.string :certification_token, :limit => 60
|
5
|
+
t.datetime :certified_at
|
6
|
+
t.references :certified_by, :polymorphic => true
|
7
|
+
t.index :certification_token
|
8
|
+
t.index :certified_by_id
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
change_table :<%= table_name %> do |t|
|
14
|
+
t.remove_references :certified_by, :polymorphic => true
|
15
|
+
t.remove :certification_token, :certified_at
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|