ror-rubycas-server 1.0.a

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.
Files changed (79) hide show
  1. data/CHANGELOG +292 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +26 -0
  4. data/README.textile +129 -0
  5. data/Rakefile +1 -0
  6. data/bin/rubycas-server +16 -0
  7. data/lib/casserver.rb +11 -0
  8. data/lib/casserver/authenticators/active_directory_ldap.rb +19 -0
  9. data/lib/casserver/authenticators/authlogic_crypto_providers/aes256.rb +43 -0
  10. data/lib/casserver/authenticators/authlogic_crypto_providers/bcrypt.rb +92 -0
  11. data/lib/casserver/authenticators/authlogic_crypto_providers/md5.rb +34 -0
  12. data/lib/casserver/authenticators/authlogic_crypto_providers/sha1.rb +59 -0
  13. data/lib/casserver/authenticators/authlogic_crypto_providers/sha512.rb +50 -0
  14. data/lib/casserver/authenticators/base.rb +67 -0
  15. data/lib/casserver/authenticators/client_certificate.rb +47 -0
  16. data/lib/casserver/authenticators/google.rb +58 -0
  17. data/lib/casserver/authenticators/ldap.rb +147 -0
  18. data/lib/casserver/authenticators/ntlm.rb +88 -0
  19. data/lib/casserver/authenticators/open_id.rb +22 -0
  20. data/lib/casserver/authenticators/sql.rb +133 -0
  21. data/lib/casserver/authenticators/sql_authlogic.rb +93 -0
  22. data/lib/casserver/authenticators/sql_encrypted.rb +75 -0
  23. data/lib/casserver/authenticators/sql_md5.rb +19 -0
  24. data/lib/casserver/authenticators/sql_rest_auth.rb +85 -0
  25. data/lib/casserver/authenticators/test.rb +22 -0
  26. data/lib/casserver/cas.rb +315 -0
  27. data/lib/casserver/localization.rb +91 -0
  28. data/lib/casserver/model.rb +270 -0
  29. data/lib/casserver/options_hash.rb +44 -0
  30. data/lib/casserver/server.rb +706 -0
  31. data/lib/casserver/utils.rb +32 -0
  32. data/lib/casserver/views/_login_form.erb +42 -0
  33. data/lib/casserver/views/layout.erb +18 -0
  34. data/lib/casserver/views/login.erb +30 -0
  35. data/lib/casserver/views/proxy.builder +12 -0
  36. data/lib/casserver/views/proxy_validate.builder +25 -0
  37. data/lib/casserver/views/service_validate.builder +18 -0
  38. data/lib/casserver/views/validate.erb +2 -0
  39. data/po/de_DE/rubycas-server.po +127 -0
  40. data/po/es_ES/rubycas-server.po +123 -0
  41. data/po/fr_FR/rubycas-server.po +128 -0
  42. data/po/ja_JP/rubycas-server.po +126 -0
  43. data/po/pl_PL/rubycas-server.po +123 -0
  44. data/po/pt_BR/rubycas-server.po +123 -0
  45. data/po/ru_RU/rubycas-server.po +118 -0
  46. data/po/rubycas-server.pot +112 -0
  47. data/po/zh_CN/rubycas-server.po +113 -0
  48. data/po/zh_TW/rubycas-server.po +113 -0
  49. data/public/themes/cas.css +121 -0
  50. data/public/themes/notice.png +0 -0
  51. data/public/themes/ok.png +0 -0
  52. data/public/themes/simple/bg.png +0 -0
  53. data/public/themes/simple/favicon.png +0 -0
  54. data/public/themes/simple/login_box_bg.png +0 -0
  55. data/public/themes/simple/logo.png +0 -0
  56. data/public/themes/simple/theme.css +28 -0
  57. data/public/themes/urbacon/bg.png +0 -0
  58. data/public/themes/urbacon/login_box_bg.png +0 -0
  59. data/public/themes/urbacon/logo.png +0 -0
  60. data/public/themes/urbacon/theme.css +33 -0
  61. data/public/themes/warning.png +0 -0
  62. data/resources/init.d.sh +58 -0
  63. data/rubycas-server.gemspec +57 -0
  64. data/setup.rb +1585 -0
  65. data/spec/alt_config.yml +50 -0
  66. data/spec/authenticators/ldap_spec.rb +53 -0
  67. data/spec/casserver_spec.rb +141 -0
  68. data/spec/database.yml +5 -0
  69. data/spec/default_config.yml +73 -0
  70. data/spec/model_spec.rb +42 -0
  71. data/spec/options_hash_spec.rb +146 -0
  72. data/spec/spec.opts +4 -0
  73. data/spec/spec_helper.rb +90 -0
  74. data/spec/utils_spec.rb +53 -0
  75. data/tasks/bundler.rake +4 -0
  76. data/tasks/db/migrate.rake +12 -0
  77. data/tasks/localization.rake +13 -0
  78. data/tasks/spec.rake +10 -0
  79. metadata +356 -0
@@ -0,0 +1,50 @@
1
+ server: webrick
2
+ port: 6543
3
+ #ssl_cert: test.pem
4
+ uri_path: /test
5
+ #bind_address: 0.0.0.0
6
+
7
+ # database:
8
+ # adapter: mysql
9
+ # database: casserver
10
+ # username: root
11
+ # password:
12
+ # host: localhost
13
+ # reconnect: true
14
+ database:
15
+ adapter: sqlite3
16
+ database: spec/casserver_spec.db
17
+
18
+ disable_auto_migrations: true
19
+
20
+ quiet: true
21
+
22
+ authenticator:
23
+ class: CASServer::Authenticators::Test
24
+ password: spec_password
25
+
26
+ theme: simple
27
+
28
+ organization: "RSPEC-TEST"
29
+
30
+ infoline: "This is an rspec test."
31
+
32
+ #custom_views: /path/to/custom/views
33
+
34
+ default_locale: en
35
+
36
+ log:
37
+ file: casserver_spec.log
38
+ level: DEBUG
39
+
40
+ #db_log:
41
+ # file: casserver_spec_db.log
42
+
43
+ enable_single_sign_out: true
44
+
45
+ #maximum_unused_login_ticket_lifetime: 300
46
+ #maximum_unused_service_ticket_lifetime: 300
47
+
48
+ #maximum_session_lifetime: 172800
49
+
50
+ #downcase_username: true
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/../spec_helper'
3
+
4
+ require 'casserver/authenticators/ldap'
5
+
6
+ describe CASServer::Authenticators::LDAP do
7
+ before do
8
+ @ldap_entry = mock(Net::LDAP::Entry.new)
9
+ @ldap_entry.stub!(:[]).and_return("Test")
10
+
11
+ @ldap = mock(Net::LDAP)
12
+ @ldap.stub!(:host=)
13
+ @ldap.stub!(:port=)
14
+ @ldap.stub!(:encryption)
15
+ @ldap.stub!(:bind_as).and_return(true)
16
+ @ldap.stub!(:authenticate).and_return(true)
17
+ @ldap.stub!(:search).and_return([@ldap_entry])
18
+
19
+ Net::LDAP.stub!(:new).and_return(@ldap)
20
+ end
21
+
22
+ describe '#validate' do
23
+
24
+ it 'validate with preauthentication and with extra attributes' do
25
+ auth = CASServer::Authenticators::LDAP.new
26
+
27
+ auth_config = HashWithIndifferentAccess.new(
28
+ :ldap => {
29
+ :host => "ad.example.net",
30
+ :port => 389,
31
+ :base => "dc=example,dc=net",
32
+ :filter => "(objectClass=person)",
33
+ :auth_user => "authenticator",
34
+ :auth_password => "itsasecret"
35
+ },
36
+ :extra_attributes => [:full_name, :address]
37
+ )
38
+
39
+ auth.configure(auth_config.merge('auth_index' => 0))
40
+ auth.validate(
41
+ :username => 'validusername',
42
+ :password => 'validpassword',
43
+ :service => 'test.service',
44
+ :request => {}
45
+ ).should == true
46
+
47
+ auth.extra_attributes.should == {:full_name => 'Test', :address => 'Test'}
48
+ end
49
+
50
+ end
51
+ end
52
+
53
+
@@ -0,0 +1,141 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ $LOG = Logger.new(File.basename(__FILE__).gsub('.rb','.log'))
5
+
6
+ RSpec.configure do |config|
7
+ config.include Capybara
8
+ end
9
+
10
+ VALID_USERNAME = 'spec_user'
11
+ VALID_PASSWORD = 'spec_password'
12
+
13
+ INVALID_PASSWORD = 'invalid_password'
14
+
15
+ describe 'CASServer' do
16
+
17
+ before do
18
+ @target_service = 'http://my.app.test'
19
+ end
20
+
21
+ describe "/login" do
22
+ before do
23
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
24
+ reset_spec_database
25
+ end
26
+
27
+ it "logs in successfully with valid username and password without a target service" do
28
+ visit "/login"
29
+
30
+ fill_in 'username', :with => VALID_USERNAME
31
+ fill_in 'password', :with => VALID_PASSWORD
32
+ click_button 'login-submit'
33
+
34
+ page.should have_content("You have successfully logged in")
35
+ end
36
+
37
+ it "fails to log in with invalid password" do
38
+ visit "/login"
39
+ fill_in 'username', :with => VALID_USERNAME
40
+ fill_in 'password', :with => INVALID_PASSWORD
41
+ click_button 'login-submit'
42
+
43
+ page.should have_content("Incorrect username or password")
44
+ end
45
+
46
+ it "logs in successfully with valid username and password and redirects to target service" do
47
+ visit "/login?service="+CGI.escape(@target_service)
48
+
49
+ fill_in 'username', :with => VALID_USERNAME
50
+ fill_in 'password', :with => VALID_PASSWORD
51
+
52
+ click_button 'login-submit'
53
+
54
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
55
+ end
56
+
57
+ it "preserves target service after invalid login" do
58
+ visit "/login?service="+CGI.escape(@target_service)
59
+
60
+ fill_in 'username', :with => VALID_USERNAME
61
+ fill_in 'password', :with => INVALID_PASSWORD
62
+ click_button 'login-submit'
63
+
64
+ page.should have_content("Incorrect username or password")
65
+ page.should have_xpath('//input[@id="service"]', :value => @target_service)
66
+ end
67
+
68
+ it "uses appropriate localization when 'lang' prameter is given (make sure you've run `rake localization:mo` first!!)" do
69
+ visit "/login?lang=pl"
70
+ page.should have_content("Użytkownik")
71
+
72
+ visit "/login?lang=pt_BR"
73
+ page.should have_content("Usuário")
74
+
75
+ visit "/login?lang=en"
76
+ page.should have_content("Username")
77
+ end
78
+
79
+ end # describe '/login'
80
+
81
+
82
+ describe '/logout' do
83
+
84
+ before do
85
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
86
+ reset_spec_database
87
+ end
88
+
89
+ it "logs out successfully" do
90
+ visit "/logout"
91
+
92
+ page.should have_content("You have successfully logged out")
93
+ end
94
+
95
+ it "logs out successfully and redirects to target service" do
96
+ visit "/logout?gateway=true&service="+CGI.escape(@target_service)
97
+
98
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?/
99
+ end
100
+
101
+ end # describe '/logout'
102
+
103
+ describe 'Configuration' do
104
+ it "uri_path value changes prefix of routes" do
105
+ load_server(File.dirname(__FILE__) + "/alt_config.yml")
106
+ @target_service = 'http://my.app.test'
107
+
108
+ visit "/test/login"
109
+ page.status_code.should_not == 404
110
+
111
+ visit "/test/logout"
112
+ page.status_code.should_not == 404
113
+ end
114
+ end
115
+
116
+ describe "proxyValidate" do
117
+ before do
118
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
119
+ reset_spec_database
120
+
121
+ visit "/login?service="+CGI.escape(@target_service)
122
+
123
+ fill_in 'username', :with => VALID_USERNAME
124
+ fill_in 'password', :with => VALID_PASSWORD
125
+
126
+ click_button 'login-submit'
127
+
128
+ page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
129
+ @ticket = page.current_url.match(/ticket=(.*)$/)[1]
130
+ end
131
+
132
+ it "should have extra attributes in proper format" do
133
+ visit "/serviceValidate?service=#{CGI.escape(@target_service)}&ticket=#{@ticket}"
134
+
135
+ encoded_utf_string = "Ютф" # actual string is "Ютф"
136
+ page.body.should match("<test_utf_string>#{encoded_utf_string}</test_utf_string>")
137
+ page.body.should match("<test_numeric>123.45</test_numeric>")
138
+ page.body.should match("<test_utf_string>&#1070;&#1090;&#1092;</test_utf_string>")
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,5 @@
1
+ development:
2
+ adapter: sqlite3
3
+
4
+ production:
5
+ adapter: postgresql
@@ -0,0 +1,73 @@
1
+ all: &all
2
+ server: webrick
3
+ port: 6543
4
+ #ssl_cert: test.pem
5
+ #uri_path: /cas
6
+ #bind_address: 0.0.0.0
7
+
8
+ # database:
9
+ # adapter: mysql
10
+ # database: casserver
11
+ # username: root
12
+ # password:
13
+ # host: localhost
14
+ # reconnect: true
15
+ database:
16
+ adapter: sqlite3
17
+ database: spec/casserver_spec.db
18
+
19
+ disable_auto_migrations: true
20
+
21
+ quiet: true
22
+
23
+ authenticator:
24
+ class: CASServer::Authenticators::Test
25
+ password: spec_password
26
+ database:
27
+ adapter: mysql
28
+
29
+ theme: simple
30
+
31
+ organization: "RSPEC-TEST"
32
+
33
+ infoline: "This is an rspec test."
34
+
35
+ #custom_views: /path/to/custom/views
36
+
37
+ default_locale: en
38
+
39
+ log:
40
+ file: casserver_spec.log
41
+ level: DEBUG
42
+
43
+ #db_log:
44
+ # file: casserver_spec_db.log
45
+
46
+ enable_single_sign_out: true
47
+
48
+ #maximum_unused_login_ticket_lifetime: 300
49
+ #maximum_unused_service_ticket_lifetime: 300
50
+
51
+ #maximum_session_lifetime: 172800
52
+
53
+ #downcase_username: true
54
+
55
+
56
+ production:
57
+ <<: *all
58
+ server: thin
59
+ authenticator:
60
+ class: CASServer::Authenticators::SQL
61
+ database: inherit
62
+ user_table: users
63
+ username_column: email
64
+ password_column: password
65
+
66
+
67
+ test:
68
+ <<: *all
69
+ server: mongrel
70
+
71
+ development:
72
+ <<: *all
73
+ server: apache
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ module CASServer
5
+ end
6
+ require 'casserver/model'
7
+
8
+ describe CASServer::Model::LoginTicket, '.cleanup(max_lifetime, max_unconsumed_lifetime)' do
9
+ let(:max_lifetime) { -1 }
10
+ let(:max_unconsumed_lifetime) { -2 }
11
+
12
+ before do
13
+ load_server(File.dirname(__FILE__) + "/default_config.yml")
14
+ reset_spec_database
15
+
16
+ CASServer::Model::LoginTicket.create :ticket => 'test', :client_hostname => 'test.local'
17
+ end
18
+
19
+ it 'should destroy all tickets created before the max lifetime' do
20
+ expect {
21
+ CASServer::Model::LoginTicket.cleanup(max_lifetime, max_unconsumed_lifetime)
22
+ }.to change(CASServer::Model::LoginTicket, :count).by(-1)
23
+ end
24
+
25
+ it 'should destroy all unconsumed tickets not exceeding the max lifetime' do
26
+ expect {
27
+ CASServer::Model::LoginTicket.cleanup(max_lifetime, max_unconsumed_lifetime)
28
+ }.to change(CASServer::Model::LoginTicket, :count).by(-1)
29
+ end
30
+ end
31
+
32
+ describe CASServer::Model::LoginTicket, '#to_s' do
33
+ let(:ticket) { 'test' }
34
+
35
+ before do
36
+ @login_ticket = CASServer::Model::LoginTicket.new :ticket => ticket
37
+ end
38
+
39
+ it 'should delegate #to_s to #ticket' do
40
+ @login_ticket.to_s.should == ticket
41
+ end
42
+ end
@@ -0,0 +1,146 @@
1
+ # encoding: UTF-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ # Hmmm.. Should I need to do this?
4
+ require 'casserver/options_hash'
5
+
6
+ describe OptionsHash do
7
+
8
+ describe "creation" do
9
+ it "should not raise" do
10
+ lambda {OptionsHash.new}.should_not raise_error
11
+ end
12
+ end
13
+
14
+ describe "environment method" do
15
+ before :each do
16
+ @options = OptionsHash.new
17
+ end
18
+ it "should store an environment attribute" do
19
+ @options.environment = :development
20
+ @options.environment.should == :development
21
+ end
22
+ end
23
+
24
+ describe "load_config method," do
25
+ before :each do
26
+ @options = OptionsHash.new
27
+ end
28
+ it "should raise when it doesn't know the environment" do
29
+ lambda {@options.load_config "spec/default_config.yml"}.should raise_error(OptionsHash::EnvironmentMissing)
30
+ end
31
+ describe "given a set environment," do
32
+ before :each do
33
+ @options.environment = :development
34
+ end
35
+ it "should raise an argument error when you pass something silly in" do
36
+ lambda {@options.load_config :silly}.should raise_error(ArgumentError)
37
+ lambda {@options.load_config 51117}.should raise_error(ArgumentError)
38
+ end
39
+ it "should load a config file string without error" do
40
+ lambda {@options.load_config "spec/default_config.yml"}.should_not raise_error
41
+ end
42
+ it "should load a config file without error" do
43
+ file = File.new "spec/default_config.yml"
44
+ lambda {@options.load_config file}.should_not raise_error
45
+ end
46
+
47
+ describe "data loading" do
48
+ before :each do
49
+ @options.environment = :development
50
+ @options.load_config "spec/default_config.yml"
51
+ end
52
+ it "should assign things correctly from all" do
53
+ @options[:port].should == 6543
54
+ end
55
+ it "should assign environment specific options" do
56
+ @options[:server].should == "apache"
57
+ production_options = OptionsHash.new
58
+ production_options.environment = :production
59
+ production_options.load_config "spec/default_config.yml"
60
+ production_options[:server].should == "thin"
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+
67
+ describe "load_database_config method" do
68
+ before :each do
69
+ @development_options = OptionsHash.new
70
+ @production_options = OptionsHash.new
71
+ end
72
+ it "should not work without assignment of environment" do
73
+ lambda {@development_options.load_database_config "spec/database.yml"}.should raise_error(OptionsHash::EnvironmentMissing)
74
+ end
75
+ describe "when environment attribute is assigned" do
76
+
77
+ before :each do
78
+ @development_options.environment = :development
79
+ @production_options.environment = :production
80
+ end
81
+
82
+ it "should not raise when a filename string is passed in" do
83
+ lambda {@development_options.load_database_config "spec/database.yml"}.should_not raise_error
84
+ end
85
+
86
+ it "should not raise when a file is passed in" do
87
+ file = File.new "spec/database.yml"
88
+ lambda {@development_options.load_database_config file}.should_not raise_error
89
+ end
90
+
91
+ describe "post data loading should have the appropriate data loaded" do
92
+ before :each do
93
+ @development_options.load_database_config "spec/database.yml"
94
+ @production_options.load_database_config "spec/database.yml"
95
+ end
96
+ it "for development" do
97
+ @development_options[:database][:adapter].should == "sqlite3"
98
+ end
99
+ it "for production" do
100
+ @production_options[:database][:adapter].should == "postgresql"
101
+ end
102
+ end
103
+
104
+ describe "primary configuration overriding" do
105
+ before :each do
106
+ @production_options.load_config "spec/default_config.yml"
107
+ end
108
+ it "should work" do
109
+ @production_options[:database][:adapter].should == "sqlite3"
110
+ @production_options.load_database_config "spec/database.yml"
111
+ @production_options[:database][:adapter].should == "postgresql"
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+ describe "inherit_authenticator_database! method" do
119
+ before :each do
120
+ @options = OptionsHash.new
121
+ @options.environment = :production
122
+ @options.load_config "spec/default_config.yml"
123
+ end
124
+ it "should work" do
125
+ @options[:authenticator][:database].should == "inherit"
126
+ @options.inherit_authenticator_database!
127
+ @options[:authenticator][:database].should_not == "inherit"
128
+ @options[:authenticator][:database][:adapter].should == "sqlite3"
129
+ end
130
+ it "should work after loading database.yml" do
131
+ @options.load_database_config "spec/database.yml"
132
+ @options[:authenticator][:database].should == "inherit"
133
+ @options.inherit_authenticator_database!
134
+ @options[:authenticator][:database].should_not == "inherit"
135
+ @options[:authenticator][:database][:adapter].should == "postgresql"
136
+ end
137
+ it "should do nothing when it should do nothing" do
138
+ options = OptionsHash.new
139
+ options.environment = :development
140
+ options.load_config "spec/default_config.yml"
141
+ options[:authenticator][:database][:adapter].should == "mysql"
142
+ options.inherit_authenticator_database!
143
+ options[:authenticator][:database][:adapter].should == "mysql"
144
+ end
145
+ end
146
+ end