devise-multi-radius-authenticatable 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +3 -0
  6. data/MIT-LICENSE +21 -0
  7. data/README.md +85 -0
  8. data/Rakefile +16 -0
  9. data/devise-multi-radius-authenticatable.gemspec +32 -0
  10. data/lib/devise-radius-authenticatable.rb +8 -0
  11. data/lib/devise/models/radius_authenticatable.rb +187 -0
  12. data/lib/devise/radius_authenticatable.rb +45 -0
  13. data/lib/devise/radius_authenticatable/test_helpers.rb +126 -0
  14. data/lib/devise/radius_authenticatable/version.rb +5 -0
  15. data/lib/devise/strategies/radius_authenticatable.rb +30 -0
  16. data/lib/generators/devise_radius_authenticatable/install_generator.rb +93 -0
  17. data/spec/devise/models/radius_authenticatable_spec.rb +170 -0
  18. data/spec/factories/admins.rb +10 -0
  19. data/spec/fixtures/devise.rb +238 -0
  20. data/spec/generators/install_generator_spec.rb +66 -0
  21. data/spec/integration/radius_authenticatable_spec.rb +115 -0
  22. data/spec/rails_app/.gitignore +15 -0
  23. data/spec/rails_app/Gemfile +4 -0
  24. data/spec/rails_app/Rakefile +7 -0
  25. data/spec/rails_app/app/assets/images/rails.png +0 -0
  26. data/spec/rails_app/app/assets/javascripts/application.js +13 -0
  27. data/spec/rails_app/app/assets/stylesheets/application.css +13 -0
  28. data/spec/rails_app/app/controllers/admins_controller.rb +83 -0
  29. data/spec/rails_app/app/controllers/application_controller.rb +11 -0
  30. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  31. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  32. data/spec/rails_app/app/models/.gitkeep +0 -0
  33. data/spec/rails_app/app/models/admin.rb +11 -0
  34. data/spec/rails_app/app/views/admins/_form.html.erb +17 -0
  35. data/spec/rails_app/app/views/admins/edit.html.erb +6 -0
  36. data/spec/rails_app/app/views/admins/index.html.erb +21 -0
  37. data/spec/rails_app/app/views/admins/new.html.erb +5 -0
  38. data/spec/rails_app/app/views/admins/show.html.erb +5 -0
  39. data/spec/rails_app/app/views/devise/confirmations/new.html.erb +12 -0
  40. data/spec/rails_app/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  41. data/spec/rails_app/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  42. data/spec/rails_app/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  43. data/spec/rails_app/app/views/devise/passwords/edit.html.erb +16 -0
  44. data/spec/rails_app/app/views/devise/passwords/new.html.erb +12 -0
  45. data/spec/rails_app/app/views/devise/registrations/edit.html.erb +29 -0
  46. data/spec/rails_app/app/views/devise/registrations/new.html.erb +18 -0
  47. data/spec/rails_app/app/views/devise/sessions/new.html.erb +17 -0
  48. data/spec/rails_app/app/views/devise/shared/_links.erb +25 -0
  49. data/spec/rails_app/app/views/devise/unlocks/new.html.erb +12 -0
  50. data/spec/rails_app/app/views/layouts/application.html.erb +25 -0
  51. data/spec/rails_app/bin/bundle +3 -0
  52. data/spec/rails_app/bin/rails +4 -0
  53. data/spec/rails_app/bin/rake +4 -0
  54. data/spec/rails_app/config.ru +4 -0
  55. data/spec/rails_app/config/application.rb +23 -0
  56. data/spec/rails_app/config/boot.rb +4 -0
  57. data/spec/rails_app/config/database.yml +25 -0
  58. data/spec/rails_app/config/environment.rb +5 -0
  59. data/spec/rails_app/config/environments/development.rb +29 -0
  60. data/spec/rails_app/config/environments/production.rb +80 -0
  61. data/spec/rails_app/config/environments/test.rb +36 -0
  62. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/rails_app/config/initializers/devise.rb +308 -0
  64. data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  65. data/spec/rails_app/config/initializers/inflections.rb +16 -0
  66. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  67. data/spec/rails_app/config/initializers/secret_token.rb +12 -0
  68. data/spec/rails_app/config/initializers/session_store.rb +3 -0
  69. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  70. data/spec/rails_app/config/locales/devise.en.yml +59 -0
  71. data/spec/rails_app/config/locales/en.yml +23 -0
  72. data/spec/rails_app/config/routes.rb +63 -0
  73. data/spec/rails_app/db/migrate/20120627042556_devise_create_admins.rb +48 -0
  74. data/spec/rails_app/db/schema.rb +37 -0
  75. data/spec/rails_app/db/seeds.rb +7 -0
  76. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  77. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  78. data/spec/rails_app/public/404.html +26 -0
  79. data/spec/rails_app/public/422.html +26 -0
  80. data/spec/rails_app/public/500.html +25 -0
  81. data/spec/rails_app/public/favicon.ico +0 -0
  82. data/spec/rails_app/public/robots.txt +5 -0
  83. data/spec/rails_app/script/rails +6 -0
  84. data/spec/spec_helper.rb +28 -0
  85. data/spec/support/devise_helpers.rb +18 -0
  86. data/spec/support/generator_helpers.rb +16 -0
  87. metadata +359 -0
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'generators/devise_radius_authenticatable/install_generator'
3
+
4
+ describe DeviseRadiusAuthenticatable::InstallGenerator do
5
+ destination File.expand_path("../../../tmp", __FILE__)
6
+
7
+ before do
8
+ prepare_devise
9
+ end
10
+
11
+ it "requires the radius server IP to be specified" do
12
+ expect { run_generator }.
13
+ to raise_error(Thor::RequiredArgumentMissingError,
14
+ /required arguments 'server'/)
15
+ end
16
+
17
+ it "requires the radius server shared secret to be specified" do
18
+ expect { run_generator ['1.1.1.1'] }.
19
+ to raise_error(Thor::RequiredArgumentMissingError,
20
+ /required arguments 'secret'/)
21
+ end
22
+
23
+ context "with required arguments" do
24
+
25
+ subject { file('config/initializers/devise.rb') }
26
+
27
+ context "with default options" do
28
+ before do
29
+ run_generator ['1.1.1.1', 'secret']
30
+ end
31
+
32
+ it { should exist }
33
+ it { should contain('==> Configuration for radius_authenticatable') }
34
+ it { should contain("config.radius_server = '1.1.1.1'") }
35
+ it { should contain("config.radius_server_port = 1812") }
36
+ it { should contain("config.radius_server_secret = 'secret'") }
37
+ it { should contain("config.radius_server_timeout = 60") }
38
+ it { should contain("config.radius_server_retries = 0") }
39
+ it { should contain("config.radius_uid_field = :uid") }
40
+ it { should contain("config.radius_uid_generator =") }
41
+ it { should contain("config.radius_dictionary_path =") }
42
+ it { should contain("config.handle_radius_timeout_as_failure = false") }
43
+ end
44
+
45
+ context "with custom options" do
46
+ before do
47
+ run_generator ['1.1.1.2', 'password', '--port=1813',
48
+ '--timeout=120', '--retries=3', '--uid_field=email',
49
+ '--dictionary_path=/tmp/dictionaries',
50
+ '--handle_timeout_as_failure=true']
51
+ end
52
+
53
+ it { should exist }
54
+ it { should contain('==> Configuration for radius_authenticatable') }
55
+ it { should contain("config.radius_server = '1.1.1.2'") }
56
+ it { should contain("config.radius_server_port = 1813") }
57
+ it { should contain("config.radius_server_secret = 'password'") }
58
+ it { should contain("config.radius_server_timeout = 120") }
59
+ it { should contain("config.radius_server_retries = 3") }
60
+ it { should contain("config.radius_uid_field = :email") }
61
+ it { should contain("config.radius_uid_generator =") }
62
+ it { should contain("config.radius_dictionary_path = '/tmp/dictionaries'") }
63
+ it { should contain("config.handle_radius_timeout_as_failure = true") }
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe "login" do
4
+ before do
5
+ @admin = FactoryGirl.create(:admin, :password => 'password')
6
+ create_radius_user('testuser', 'password')
7
+ visit new_admin_session_path
8
+ end
9
+
10
+ it "is successful for a database user with HTTP Basic Authentication" do
11
+ page.driver.browser.basic_authorize(@admin.email, 'password')
12
+ visit root_path
13
+
14
+ current_path.should == root_path
15
+ end
16
+
17
+ it "is successful for a database user with params authentication" do
18
+ fill_in "Login", :with => @admin.email
19
+ fill_in "Password", :with => 'password'
20
+ click_button "Sign in"
21
+
22
+ current_path.should == root_path
23
+ page.should have_content("Signed in successfully")
24
+ end
25
+
26
+ it "is successful for a radius user with HTTP Basic Authentication" do
27
+ page.driver.browser.basic_authorize('testuser', 'password')
28
+ visit root_path
29
+
30
+ current_path.should == root_path
31
+ end
32
+
33
+ it "is successful for a radius user with params authentication" do
34
+ fill_in "Login", :with => 'testuser'
35
+ fill_in "Password", :with => 'password'
36
+ click_button "Sign in"
37
+
38
+ current_path.should == root_path
39
+ page.should have_content("Signed in successfully")
40
+ end
41
+
42
+ it "fails for wrong database password" do
43
+ fill_in "Login", :with => @admin.email
44
+ fill_in "Password", :with => 'password2'
45
+ click_button "Sign in"
46
+
47
+ current_path.should == new_admin_session_path
48
+ page.should have_content("Invalid email or password")
49
+ end
50
+
51
+ it "fails for wrong radius password" do
52
+ fill_in "Login", :with => 'testuser'
53
+ fill_in "Password", :with => 'password2'
54
+ click_button "Sign in"
55
+
56
+ current_path.should == new_admin_session_path
57
+ page.should have_content("Invalid email or password")
58
+ end
59
+
60
+ it "invokes the after_radius_authentication callback" do
61
+ fill_in "Login", :with => 'testuser'
62
+ fill_in "Password", :with => 'password'
63
+ click_button "Sign in"
64
+
65
+ uid = Admin.radius_uid_generator.call('testuser', Admin.radius_server)
66
+ Admin.where(Admin.radius_uid_field => uid).count.should == 1
67
+ end
68
+
69
+ it "successfully logs in a user with case insensitive username" do
70
+ swap(Devise, :case_insensitive_keys => [Admin.authentication_keys.first]) do
71
+ fill_in "Login", :with => 'TESTUSER'
72
+ fill_in "Password", :with => 'password'
73
+ click_button "Sign in"
74
+
75
+ current_path.should == root_path
76
+ page.should have_content("Signed in successfully")
77
+ end
78
+ end
79
+
80
+ it "fails to log in a user with case sensitive username" do
81
+ swap(Devise, :case_insensitive_keys => []) do
82
+ fill_in "Login", :with => 'TESTUSER'
83
+ fill_in "Password", :with => 'password'
84
+ click_button "Sign in"
85
+
86
+ current_path.should == new_admin_session_path
87
+ page.should have_content("Invalid email or password")
88
+ end
89
+ end
90
+
91
+ context "when radius authentication is the first strategy" do
92
+ before do
93
+ @admin2 = FactoryGirl.create(:admin, :password => 'password')
94
+ create_radius_user(@admin2.email, 'password2')
95
+
96
+ @orig_order = Devise.warden_config.default_strategies(:scope => :admin)
97
+ Devise.warden_config.default_strategies(:radius_authenticatable,
98
+ :database_authenticatable,
99
+ {:scope => :admin})
100
+ end
101
+
102
+ after do
103
+ Devise.warden_config.default_strategies(@orig_order, {:scope => :admin})
104
+ end
105
+
106
+ it "proceeds with the next strategy if radius authentication fails" do
107
+ fill_in "Login", :with => @admin2.email
108
+ fill_in "Password", :with => 'password'
109
+ click_button "Sign in"
110
+
111
+ current_path.should == root_path
112
+ page.should have_content("Signed in successfully")
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,15 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ # Ignore all logfiles and tempfiles.
14
+ /log/*.log
15
+ /tmp
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec :path => File.expand_path("../../../", __FILE__)
4
+
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ RailsApp::Application.load_tasks
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,83 @@
1
+ class AdminsController < ApplicationController
2
+ # GET /admins
3
+ # GET /admins.json
4
+ def index
5
+ @admins = Admin.all
6
+
7
+ respond_to do |format|
8
+ format.html # index.html.erb
9
+ format.json { render json: @admins }
10
+ end
11
+ end
12
+
13
+ # GET /admins/1
14
+ # GET /admins/1.json
15
+ def show
16
+ @admin = Admin.find(params[:id])
17
+
18
+ respond_to do |format|
19
+ format.html # show.html.erb
20
+ format.json { render json: @admin }
21
+ end
22
+ end
23
+
24
+ # GET /admins/new
25
+ # GET /admins/new.json
26
+ def new
27
+ @admin = Admin.new
28
+
29
+ respond_to do |format|
30
+ format.html # new.html.erb
31
+ format.json { render json: @admin }
32
+ end
33
+ end
34
+
35
+ # GET /admins/1/edit
36
+ def edit
37
+ @admin = Admin.find(params[:id])
38
+ end
39
+
40
+ # POST /admins
41
+ # POST /admins.json
42
+ def create
43
+ @admin = Admin.new(params[:admin])
44
+
45
+ respond_to do |format|
46
+ if @admin.save
47
+ format.html { redirect_to @admin, notice: 'Admin was successfully created.' }
48
+ format.json { render json: @admin, status: :created, location: @admin }
49
+ else
50
+ format.html { render action: "new" }
51
+ format.json { render json: @admin.errors, status: :unprocessable_entity }
52
+ end
53
+ end
54
+ end
55
+
56
+ # PUT /admins/1
57
+ # PUT /admins/1.json
58
+ def update
59
+ @admin = Admin.find(params[:id])
60
+
61
+ respond_to do |format|
62
+ if @admin.update_attributes(params[:admin])
63
+ format.html { redirect_to @admin, notice: 'Admin was successfully updated.' }
64
+ format.json { head :no_content }
65
+ else
66
+ format.html { render action: "edit" }
67
+ format.json { render json: @admin.errors, status: :unprocessable_entity }
68
+ end
69
+ end
70
+ end
71
+
72
+ # DELETE /admins/1
73
+ # DELETE /admins/1.json
74
+ def destroy
75
+ @admin = Admin.find(params[:id])
76
+ @admin.destroy
77
+
78
+ respond_to do |format|
79
+ format.html { redirect_to admins_url }
80
+ format.json { head :no_content }
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,11 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+
4
+ before_filter :authenticate_admin!
5
+
6
+ protected
7
+
8
+ def after_sign_out_path_for(resource)
9
+ new_admin_session_path
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ class Admin < ActiveRecord::Base
2
+ devise :database_authenticatable, :radius_authenticatable
3
+
4
+ attr_accessor :login
5
+
6
+ def self.find_for_database_authentication(conditions)
7
+ login = conditions.delete(:login)
8
+ conditions[:email] = login
9
+ super
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ <%= form_for(@admin) do |f| %>
2
+ <% if @admin.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(@admin.errors.count, "error") %> prohibited this admin from being saved:</h2>
5
+
6
+ <ul>
7
+ <% @admin.errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="actions">
15
+ <%= f.submit %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing admin</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Show', @admin %> |
6
+ <%= link_to 'Back', admins_path %>
@@ -0,0 +1,21 @@
1
+ <h1>Listing admins</h1>
2
+
3
+ <table>
4
+ <tr>
5
+ <th></th>
6
+ <th></th>
7
+ <th></th>
8
+ </tr>
9
+
10
+ <% @admins.each do |admin| %>
11
+ <tr>
12
+ <td><%= link_to 'Show', admin %></td>
13
+ <td><%= link_to 'Edit', edit_admin_path(admin) %></td>
14
+ <td><%= link_to 'Destroy', admin, method: :delete, data: { confirm: 'Are you sure?' } %></td>
15
+ </tr>
16
+ <% end %>
17
+ </table>
18
+
19
+ <br />
20
+
21
+ <%= link_to 'New Admin', new_admin_path %>
@@ -0,0 +1,5 @@
1
+ <h1>New admin</h1>
2
+
3
+ <%= render 'form' %>
4
+
5
+ <%= link_to 'Back', admins_path %>
@@ -0,0 +1,5 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+
4
+ <%= link_to 'Edit', edit_admin_path(@admin) %> |
5
+ <%= link_to 'Back', admins_path %>
@@ -0,0 +1,12 @@
1
+ <h2>Resend confirmation instructions</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
4
+ <%= devise_error_messages! %>
5
+
6
+ <div><%= f.label :email %><br />
7
+ <%= f.email_field :email, autofocus: true %></div>
8
+
9
+ <div><%= f.submit "Resend confirmation instructions" %></div>
10
+ <% end %>
11
+
12
+ <%= render "devise/shared/links" %>
@@ -0,0 +1,5 @@
1
+ <p>Welcome <%= @email %>!</p>
2
+
3
+ <p>You can confirm your account email through the link below:</p>
4
+
5
+ <p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>