bcms_cas 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +92 -0
- data/app/models/cas_user.rb +20 -0
- data/app/portlets/helpers/login_portlet_helper.rb +15 -0
- data/db/migrate/20091002162550_add_cas_user_group.rb +9 -0
- data/lib/bcms_cas/routes.rb +7 -0
- data/lib/bcms_cas.rb +2 -0
- data/lib/cas/authentication.rb +67 -0
- data/lib/cas/utils.rb +72 -0
- data/rails/init.rb +3 -0
- data/test/performance/browsing_test.rb +9 -0
- data/test/test_helper.rb +38 -0
- data/test/unit/cas/cas_authentication_test.rb +108 -0
- data/test/unit/cas_user_test.rb +35 -0
- data/test/unit/cas_utils_test.rb +83 -0
- data/test/unit/helpers/login_portlet_helper_test.rb +10 -0
- metadata +68 -0
data/README.markdown
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Central Authentication Server Module
|
2
|
+
|
3
|
+
This module allows BrowserCMS to integrate with a Central Authentication Server (CAS) to allow users to log in to a BrowserCMS site,
|
4
|
+
using credentials stored in an external system. This module requires an existing CAS server to be running (See http://code.google.com/p/rubycas-server/)
|
5
|
+
as an example of a server.
|
6
|
+
|
7
|
+
This module will allow user to login to the public area of the CMS, using the Login Form Portlet. It does not handle users that need to
|
8
|
+
log into the CMS administrative area. It also handles single logout by redirecting the user to cas /logout service.
|
9
|
+
|
10
|
+
## A. Instructions
|
11
|
+
Here are the necessary steps to install this module.
|
12
|
+
|
13
|
+
1. Configure your CAS server and test that you can login directly via their /login page.
|
14
|
+
2. Install the rubycas-client gem (See B below)
|
15
|
+
3. Install the bcms_cas module, and configure it to point to your CAS server (see C below).
|
16
|
+
4. Migrate the database to add the CAS Group (See D below)
|
17
|
+
5. Alter the Login Form Portlet to submit to the CAS server. (See E below)
|
18
|
+
|
19
|
+
## B. Installing RubyCAS-Client
|
20
|
+
This project depends on RubyCAS-client (http://code.google.com/p/rubycas-client/). RubyCAS-Client is a standard Rails PluginGem, and the instructions
|
21
|
+
for installing in into a Rails project can be found on their website. The following command will probably work though:
|
22
|
+
|
23
|
+
gem install rubycas-client
|
24
|
+
|
25
|
+
This will add the latest version of a gem. The bcms_cas module will require the necessary files, so you do not need to
|
26
|
+
make any configuration changes in your rails project.
|
27
|
+
|
28
|
+
## C. Installing/Configuring the Module
|
29
|
+
To install a BrowserCMS module follow the instructions here http://www.browsercms.org/doc/guides/html/installing_modules.html .
|
30
|
+
After that you will need to configure the rubycas-client to point to the correct CAS server, along with any other
|
31
|
+
configuration options you need. Add the following to your config/initializers/browsercms.rb:
|
32
|
+
|
33
|
+
|
34
|
+
CASClient::Frameworks::Rails::Filter.configure(
|
35
|
+
:cas_base_url => "https://cas.yourdomainname.org",
|
36
|
+
:extra_attributes_session_key => :cas_extra_attributes
|
37
|
+
)
|
38
|
+
|
39
|
+
Make sure your SITE_DOMAIN variable in production/development is correctly set to the right top level domain. This will be needed
|
40
|
+
to allow redirects between the servers to happen correctly (it requires Absolute URLs). For example, in config/environments/production.rb:
|
41
|
+
|
42
|
+
SITE_DOMAIN="www.yourdomainname.com"
|
43
|
+
|
44
|
+
### Extra Attributes (Optional)
|
45
|
+
The :extra_attributes_session_key may not be needed, depending on what type of Authenticator your CAS server is using. You can
|
46
|
+
safely leave it out if you are just using the normal CMS logic. A CAS server can send additional information back, and these will be stored as
|
47
|
+
session variables that can be accessed in other methods.
|
48
|
+
|
49
|
+
## D. Add/Configure the 'CAS Authenticated User' Group
|
50
|
+
When you run rake db:migrate, this module will add a new group to the CMS called 'CAS Authenticated Users'. All users that
|
51
|
+
log in successfully will be assigned to members of this group. You will potentially want to rename this group to something
|
52
|
+
that more accurately reflects who these users are (i.e. Members, Staff, etc) and then set which sections of the website this
|
53
|
+
group can visit.
|
54
|
+
|
55
|
+
## E. Configure Login Form Portlet
|
56
|
+
Alter the Login Form portlet to look something like this:
|
57
|
+
|
58
|
+
<% form_tag "https://cas.yourdomainname.org" do %>
|
59
|
+
<%= login_ticket_tag %>
|
60
|
+
<%= service_url_tag %>
|
61
|
+
<p>
|
62
|
+
<%= label_tag :login %>
|
63
|
+
<%= text_field_tag :username, @login %>
|
64
|
+
</p>
|
65
|
+
<p>
|
66
|
+
<%= label_tag :password %>
|
67
|
+
<%= password_field_tag :password %>
|
68
|
+
</p>
|
69
|
+
<p>
|
70
|
+
<%= label_tag :remember_me %>
|
71
|
+
<%= check_box_tag :remember_me, '1', @remember_me %>
|
72
|
+
</p>
|
73
|
+
<p><%= submit_tag "Login" %></p>
|
74
|
+
<% end %>
|
75
|
+
|
76
|
+
The key changes are:
|
77
|
+
|
78
|
+
1. The form needs to submit directly to the CAS server
|
79
|
+
2. You need to add helpers for login_ticket_tag and service_url_tag. These generate hidden parameters CAS services need.
|
80
|
+
3. Change the username parameter from :login to :username
|
81
|
+
|
82
|
+
F. Known Issues
|
83
|
+
|
84
|
+
* Every page is secured by the CASClient Gateway Filter, which means a lot of redirects. This is potentially a big performance hit, and would require modifying the filter so it only handles checking login_tickets, rather than redirects.
|
85
|
+
* A user logged in using CAS will be assigned to a single group. There is no way to map a user to different groups (i.e. Platnium or Gold Members). Could potentially be done via cas extra info.
|
86
|
+
* The internal CMS User database is bypassed/not used for login for front end pages. This means it would fail the cmsadmin user tried to login via the Login Form.
|
87
|
+
* [Low] LoginPortlet Form tag should pull from CAS automatically (requires changes to CMS core)
|
88
|
+
* [Low] username/login field is different between CMS and CAS (requires core changes)
|
89
|
+
* The CAS Login page has to be styled to match the look and feel of the site.
|
90
|
+
* If the user types in wrong username/pw on CMS login form, they will be left on the CAS Login page, with message.
|
91
|
+
* Every hit to a page with the login form portlet is fetching a LT from CAS. This is potentially slow. [Performance]
|
92
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# This represents a user was autheniticated using a CAS service. Their user data is not saved in the database (in the users table_,
|
3
|
+
# but is retrieved from an external service and stored purely as session data.
|
4
|
+
#
|
5
|
+
#
|
6
|
+
class CasUser < GuestUser
|
7
|
+
|
8
|
+
GROUP_NAME = "cas_group"
|
9
|
+
|
10
|
+
def initialize(attributes={})
|
11
|
+
super({ :first_name => "CAS", :last_name => "User"}.merge(attributes))
|
12
|
+
@guest = false
|
13
|
+
end
|
14
|
+
|
15
|
+
# Using a single group for now. (This will need to be mapped to more groups later).
|
16
|
+
def group
|
17
|
+
@group ||= Group.find_by_code(GROUP_NAME)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# This assumes there is no existing LoginPortletHelper defined in the Core CMS project, and provides one
|
2
|
+
# to simplify what users need to do in the form.
|
3
|
+
module LoginPortletHelper
|
4
|
+
|
5
|
+
# Generates the hidden field for the service_url that the CAS server expects, which tells it where to redirect to. Must create
|
6
|
+
# an absolute URL.
|
7
|
+
def service_url_tag
|
8
|
+
hidden_field_tag :service, Cas::Utils.service_url(@portlet, @page, session[:return_to])
|
9
|
+
end
|
10
|
+
|
11
|
+
# Generates the hidden field for the login ticket that CAS server expects.
|
12
|
+
def login_ticket_tag
|
13
|
+
hidden_field_tag :lt, Cas::Utils.fetch_lt_from_cas
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class AddCasUserGroup < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
group = Group.create!(:name=>"CAS Authenticated Users", :code=>"cas_group", :group_type=>GroupType.find_by_name("Registered Public User"))
|
4
|
+
group.sections = Section.all
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
end
|
9
|
+
end
|
data/lib/bcms_cas.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'cas/utils'
|
2
|
+
require 'casclient'
|
3
|
+
require 'casclient/frameworks/rails/filter'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Augments the core Cms::Controllers to add Cas Authentication behavior.
|
7
|
+
#
|
8
|
+
module Cas
|
9
|
+
module Authentication
|
10
|
+
|
11
|
+
# Called when this module is included on the given class.
|
12
|
+
def self.included(controller_class)
|
13
|
+
controller_class.send(:include, InstanceMethods)
|
14
|
+
|
15
|
+
controller_class.skip_filter :check_access_to_page
|
16
|
+
controller_class.before_filter CASClient::Frameworks::Rails::GatewayFilter
|
17
|
+
controller_class.before_filter :login_from_cas_ticket
|
18
|
+
controller_class.before_filter :check_access_to_page_normally
|
19
|
+
end
|
20
|
+
|
21
|
+
# Each instance of the controller will gain these methods.
|
22
|
+
module InstanceMethods
|
23
|
+
def check_access_to_page_normally
|
24
|
+
logger.warn "Checking auth using normal Cms filter."
|
25
|
+
check_access_to_page
|
26
|
+
end
|
27
|
+
|
28
|
+
# Attempts to set the current user based on the session attribute set by CAS.
|
29
|
+
def login_from_cas_ticket
|
30
|
+
logger.debug "Attempting to login using CAS session variable."
|
31
|
+
if session[:cas_user]
|
32
|
+
logger.warn "Who is @current_user '#{@current_user.login}'?" if @current_user
|
33
|
+
logger.warn "Who is User.current '#{User.current.login}'?" if User.current
|
34
|
+
|
35
|
+
user = CasUser.new(:login=>session[:cas_user])
|
36
|
+
|
37
|
+
# Having to set both of these feels very duplicative. Ideally I would like a way
|
38
|
+
# to set only once, but calling current_user= has sideeffects.
|
39
|
+
@current_user = User.current = user
|
40
|
+
|
41
|
+
logger.info "Found session[:cas_user]. Created CasUser with login '#{user.login}' and set as current_user." if @current_user
|
42
|
+
end
|
43
|
+
@current_user
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
Cms::ContentController.send(:include, Cas::Authentication)
|
48
|
+
|
49
|
+
|
50
|
+
# Extends the core SessionController to properly destroy the local session on logout, and redirect to CAS for Single Log out.
|
51
|
+
module SingleLogOut
|
52
|
+
def self.included(controller_class)
|
53
|
+
controller_class.send(:include, InstanceMethods)
|
54
|
+
controller_class.alias_method_chain :destroy, :cas
|
55
|
+
end
|
56
|
+
|
57
|
+
module InstanceMethods
|
58
|
+
|
59
|
+
def destroy_with_cas
|
60
|
+
logger.info "Handle single logout."
|
61
|
+
logout_user
|
62
|
+
Cas::Utils.logout(self, "http://#{SITE_DOMAIN}/")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
Cms::SessionsController.send(:include, Cas::SingleLogOut)
|
67
|
+
end
|
data/lib/cas/utils.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# Customizes behavior of CASFilter.
|
3
|
+
#
|
4
|
+
module Cas
|
5
|
+
class Utils
|
6
|
+
# This is a wrapper around the default behavior of the CASClient Rails filter.
|
7
|
+
#
|
8
|
+
# The only difference is that it generates a return URL that the user can click on to get back to the homepage.
|
9
|
+
def self.logout(controller, service = nil)
|
10
|
+
# Copy/Paste from Filter
|
11
|
+
referer = reset_session_and_get_referrer(controller, service)
|
12
|
+
|
13
|
+
# New lines
|
14
|
+
client = CASClient::Frameworks::Rails::Filter.client
|
15
|
+
|
16
|
+
# Adding gateway=true param to this logout URL will cause immediate redirect, which is preferable
|
17
|
+
# since it means users aren't left stranded on the CAS server logout page.
|
18
|
+
url = client.logout_url(referer, referer)
|
19
|
+
controller.send(:redirect_to, "#{url}&gateway=true")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Copy/Paste from CAS Filter
|
23
|
+
def self.reset_session_and_get_referrer(controller, service)
|
24
|
+
referer = service || controller.request.referer
|
25
|
+
st = controller.session[:cas_last_valid_ticket]
|
26
|
+
delete_service_session_lookup(st) if st
|
27
|
+
controller.send(:reset_session)
|
28
|
+
referer
|
29
|
+
end
|
30
|
+
#
|
31
|
+
# Gets a valid login_ticket from the CAS Server, which will allow us to submit directly from our CMS login forms.
|
32
|
+
#
|
33
|
+
def self.fetch_lt_from_cas
|
34
|
+
url = URI.parse("#{self.cas_server_url}/loginTicket")
|
35
|
+
post = Net::HTTP::Post.new(url.path)
|
36
|
+
post.set_form_data({'dummy'=>'data'})
|
37
|
+
|
38
|
+
https = Net::HTTP.new(url.host, url.port)
|
39
|
+
https.use_ssl = true
|
40
|
+
|
41
|
+
res = https.start {|http| http.request(post) }
|
42
|
+
lt = res.body
|
43
|
+
lt
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.check(portlet)
|
47
|
+
portlet.current_page.path
|
48
|
+
end
|
49
|
+
|
50
|
+
# Calculates which URL the user should be redirect to, after completing registration on the CAS server.
|
51
|
+
def self.service_url(portlet, page, redirect_to = nil)
|
52
|
+
path = page.path if page
|
53
|
+
path = "" unless page
|
54
|
+
goto = redirect_to || portlet.success_url || path
|
55
|
+
unless goto.starts_with?("http://")
|
56
|
+
goto = to_absolute_url(goto)
|
57
|
+
end
|
58
|
+
goto
|
59
|
+
end
|
60
|
+
|
61
|
+
# Looks up the URL of the CAS server from the environment
|
62
|
+
def self.cas_server_url
|
63
|
+
CASClient::Frameworks::Rails::Filter.config[:cas_base_url]
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def self.to_absolute_url(path)
|
69
|
+
"http://#{SITE_DOMAIN}#{path}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/rails/init.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
3
|
+
require 'test_help'
|
4
|
+
|
5
|
+
class ActiveSupport::TestCase
|
6
|
+
# Transactional fixtures accelerate your tests by wrapping each test method
|
7
|
+
# in a transaction that's rolled back on completion. This ensures that the
|
8
|
+
# test database remains unchanged so your fixtures don't have to be reloaded
|
9
|
+
# between every test method. Fewer database queries means faster tests.
|
10
|
+
#
|
11
|
+
# Read Mike Clark's excellent walkthrough at
|
12
|
+
# http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
|
13
|
+
#
|
14
|
+
# Every Active Record database supports transactions except MyISAM tables
|
15
|
+
# in MySQL. Turn off transactional fixtures in this case; however, if you
|
16
|
+
# don't care one way or the other, switching from MyISAM to InnoDB tables
|
17
|
+
# is recommended.
|
18
|
+
#
|
19
|
+
# The only drawback to using transactional fixtures is when you actually
|
20
|
+
# need to test transactions. Since your test is bracketed by a transaction,
|
21
|
+
# any transactions started in your code will be automatically rolled back.
|
22
|
+
self.use_transactional_fixtures = true
|
23
|
+
|
24
|
+
# Instantiated fixtures are slow, but give you @david where otherwise you
|
25
|
+
# would need people(:david). If you don't want to migrate your existing
|
26
|
+
# test cases which use the @david style and don't mind the speed hit (each
|
27
|
+
# instantiated fixtures translates to a database query per test method),
|
28
|
+
# then set this back to true.
|
29
|
+
self.use_instantiated_fixtures = false
|
30
|
+
|
31
|
+
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
32
|
+
#
|
33
|
+
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
34
|
+
# -- they do not yet inherit this setting
|
35
|
+
fixtures :all
|
36
|
+
|
37
|
+
# Add more helper methods to be used by all tests here...
|
38
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'mocha'
|
3
|
+
|
4
|
+
class MyController < ActionController::Base
|
5
|
+
include Cms::Authentication::Controller
|
6
|
+
|
7
|
+
def get_at_current_user
|
8
|
+
@current_user
|
9
|
+
end
|
10
|
+
|
11
|
+
def flash
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
"Exists only to be alias_method_chained"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class CasAuthTest < ActiveSupport::TestCase
|
21
|
+
|
22
|
+
def setup
|
23
|
+
MyController.expects(:skip_filter).with(:check_access_to_page)
|
24
|
+
MyController.expects(:before_filter).with(CASClient::Frameworks::Rails::GatewayFilter)
|
25
|
+
MyController.expects(:before_filter).with(:login_from_cas_ticket)
|
26
|
+
MyController.expects(:before_filter).with(:check_access_to_page_normally)
|
27
|
+
|
28
|
+
MyController.send(:include, Cas::Authentication)
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown
|
33
|
+
User.current = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
test "Alias's the existing filter to a different name." do
|
38
|
+
c = MyController.new
|
39
|
+
c.expects(:check_access_to_page)
|
40
|
+
|
41
|
+
c.check_access_to_page_normally
|
42
|
+
end
|
43
|
+
|
44
|
+
test "adds current_user and login from session to class" do
|
45
|
+
c = MyController.new
|
46
|
+
|
47
|
+
assert c.respond_to?(:current_user)
|
48
|
+
assert c.respond_to?(:login_from_cas_ticket)
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
test "login_from_cas_ticket will create and set the current user and User.current if a session attribute was found." do
|
54
|
+
c = MyController.new
|
55
|
+
c.session = {}
|
56
|
+
c.session[:cas_user] = "1234"
|
57
|
+
|
58
|
+
User.current = Group.find_by_code("guest")
|
59
|
+
|
60
|
+
c.login_from_cas_ticket
|
61
|
+
|
62
|
+
current_user = c.get_at_current_user
|
63
|
+
assert_equal CasUser, current_user.class
|
64
|
+
assert_equal "1234", current_user.login
|
65
|
+
assert_equal current_user, User.current
|
66
|
+
end
|
67
|
+
|
68
|
+
test "Cms::ContentController gets augmented" do
|
69
|
+
assert (Cms::ContentController.new.respond_to? :check_access_to_page_normally)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
class CasSessionControllerTest < ActiveSupport::TestCase
|
75
|
+
|
76
|
+
|
77
|
+
test "alias_method_chain the normal methods" do
|
78
|
+
MyController.send(:include, Cas::SingleLogOut)
|
79
|
+
|
80
|
+
c = MyController.new
|
81
|
+
|
82
|
+
assert( c.respond_to? :destroy)
|
83
|
+
assert( c.respond_to? :destroy_with_cas)
|
84
|
+
assert( c.respond_to? :destroy_without_cas)
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
test "destroy_with_cas redirects to server and calls logout_user" do
|
89
|
+
MyController.send(:include, Cas::SingleLogOut)
|
90
|
+
c = MyController.new
|
91
|
+
|
92
|
+
c.expects(:logout_user)
|
93
|
+
|
94
|
+
Cas::Utils.expects(:logout).with(c, "http://#{SITE_DOMAIN}/")
|
95
|
+
|
96
|
+
c.destroy_with_cas
|
97
|
+
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
test "that BrowserCMS 3.0.3 installed." do
|
102
|
+
assert Cms::SessionsController.new.respond_to?(:logout_user), "Need to have BrowserCMS 3.0.3 installed for Cas module to work."
|
103
|
+
end
|
104
|
+
|
105
|
+
test "Cms::SessionController gets augmented" do
|
106
|
+
assert (Cms::SessionsController.new.respond_to? :destroy_with_cas)
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CasUserTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@s = Section.create!(:name=>"root", :root=>true, :path=>"/")
|
7
|
+
@p = Page.create!(:name=>"Home", :section=>@s, :path=>"/p")
|
8
|
+
@g = Group.create!(:name=>"G", :code=>"cas_group")
|
9
|
+
@g.sections = Section.all
|
10
|
+
end
|
11
|
+
|
12
|
+
test "group returns the cas_group" do
|
13
|
+
user = CasUser.new
|
14
|
+
|
15
|
+
assert_equal @g, user.group
|
16
|
+
end
|
17
|
+
|
18
|
+
test "cas_user should be able to view all sections (based on group)" do
|
19
|
+
user = CasUser.new
|
20
|
+
|
21
|
+
assert user.able_to_view?(@p)
|
22
|
+
end
|
23
|
+
|
24
|
+
test "setting login" do
|
25
|
+
user = CasUser.new(:login=>"bob")
|
26
|
+
assert_equal "bob", user.login
|
27
|
+
end
|
28
|
+
|
29
|
+
test "that CasUsers are not considered guests" do
|
30
|
+
user = CasUser.new
|
31
|
+
assert !user.guest?
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'mocha'
|
3
|
+
|
4
|
+
class CasUtilsTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@current_page = Page.new(:path=>"/expected")
|
8
|
+
@portlet = LoginPortlet.new
|
9
|
+
end
|
10
|
+
|
11
|
+
test "service_url returns absolute success_url if specified" do
|
12
|
+
@portlet.success_url = "/stuff"
|
13
|
+
assert_equal "http://localhost:3000/stuff", Cas::Utils.service_url(@portlet, @current_page), "This really need to be an absolute path for it work w/ CAS."
|
14
|
+
end
|
15
|
+
|
16
|
+
test "service_url returns current page if specified" do
|
17
|
+
p = LoginPortlet.new
|
18
|
+
p.current_page = Page.new(:path=>"/expected")
|
19
|
+
|
20
|
+
s = Cas::Utils.service_url(p, @current_page)
|
21
|
+
assert_equal "http://localhost:3000/expected", s
|
22
|
+
end
|
23
|
+
|
24
|
+
test "service_url returns redirect_to if available" do
|
25
|
+
s = Cas::Utils.service_url(@portlet, @current_page, "/redirected")
|
26
|
+
assert_equal "http://localhost:3000/redirected", s
|
27
|
+
end
|
28
|
+
|
29
|
+
test "Nil page doesn't cause Nil exception" do
|
30
|
+
s = Cas::Utils.service_url(@portlet, nil, nil)
|
31
|
+
assert_equal "http://localhost:3000", s
|
32
|
+
end
|
33
|
+
|
34
|
+
test "Portlets work as expected (CMS Core check)" do
|
35
|
+
p = LoginPortlet.new
|
36
|
+
|
37
|
+
assert_equal nil, p.success_url, "Validate that LoginPortlet returns nil if no success_url is set (rather than an empty string."
|
38
|
+
end
|
39
|
+
|
40
|
+
test "cas_server_url looks up CAS server from config in environment" do
|
41
|
+
expected = "https://127.0.0.1"
|
42
|
+
CASClient::Frameworks::Rails::Filter.expects(:config).returns({:cas_base_url=>expected})
|
43
|
+
|
44
|
+
assert_equal expected, Cas::Utils.cas_server_url
|
45
|
+
end
|
46
|
+
|
47
|
+
test "get login ticket" do
|
48
|
+
expected_host = "https://random.com"
|
49
|
+
Cas::Utils.expects(:cas_server_url).with.returns(expected_host)
|
50
|
+
|
51
|
+
Net::HTTP.any_instance.stubs(:start).returns(mock(:body=>"Ticket 100"))
|
52
|
+
uri = stub(:path=>"#{expected_host}/loginTicket", :host=>"", :port=>80)
|
53
|
+
URI.expects(:parse).with("#{expected_host}/loginTicket").returns(uri)
|
54
|
+
|
55
|
+
ticket = Cas::Utils.fetch_lt_from_cas
|
56
|
+
assert_equal "Ticket 100", ticket
|
57
|
+
end
|
58
|
+
|
59
|
+
# Verification test of CasClient API behavior.
|
60
|
+
test "[CASClient] Verify expected behavior of CASClient#logout_url" do
|
61
|
+
destination_url = "localhost"
|
62
|
+
|
63
|
+
client = CASClient::Client.new({:cas_base_url=>"/", :logout_url=>"/"})
|
64
|
+
|
65
|
+
logout_url = client.logout_url(destination_url, destination_url)
|
66
|
+
assert_equal "/?destination=localhost&url=localhost", logout_url, "Verifies that logout_url generates a correct URL."
|
67
|
+
assert_equal String, logout_url.class
|
68
|
+
end
|
69
|
+
|
70
|
+
test "Cas::Utils#logout redirects and attaches gateway=true to logout_url" do
|
71
|
+
destination_url = "localhost"
|
72
|
+
logout_url = "/?destination=localhost&url=localhost"
|
73
|
+
|
74
|
+
CASClient::Frameworks::Rails::Filter.expects(:client).returns(CASClient::Client.new({:cas_base_url=>""}))
|
75
|
+
CASClient::Client.any_instance.expects(:logout_url).with(destination_url, destination_url).returns(logout_url)
|
76
|
+
|
77
|
+
controller = stub()
|
78
|
+
controller.expects(:redirect_to).with("#{logout_url}&gateway=true")
|
79
|
+
Cas::Utils.expects(:reset_session_and_get_referrer).returns(destination_url)
|
80
|
+
|
81
|
+
Cas::Utils.logout(controller, "/")
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'mocha'
|
3
|
+
|
4
|
+
class LoginPortletHelperTest < ActionView::TestCase
|
5
|
+
|
6
|
+
test "Fetching login ticket" do
|
7
|
+
ticket = Cas::Utils.expects(:fetch_lt_from_cas).with().returns("ABC")
|
8
|
+
assert_equal hidden_field_tag( :lt, "ABC"), login_ticket_tag
|
9
|
+
end
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bcms_cas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- BrowserMedia
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-05 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: github@browsermedia.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.markdown
|
24
|
+
files:
|
25
|
+
- app/models/cas_user.rb
|
26
|
+
- app/portlets/helpers/login_portlet_helper.rb
|
27
|
+
- db/migrate/20091002162550_add_cas_user_group.rb
|
28
|
+
- lib/bcms_cas.rb
|
29
|
+
- lib/bcms_cas/routes.rb
|
30
|
+
- lib/cas/authentication.rb
|
31
|
+
- lib/cas/utils.rb
|
32
|
+
- rails/init.rb
|
33
|
+
- README.markdown
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://browsercms.org
|
36
|
+
licenses: []
|
37
|
+
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options:
|
40
|
+
- --charset=UTF-8
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project: browsercms
|
58
|
+
rubygems_version: 1.3.4
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: A CAS Module for BrowserCMS
|
62
|
+
test_files:
|
63
|
+
- test/performance/browsing_test.rb
|
64
|
+
- test/test_helper.rb
|
65
|
+
- test/unit/cas/cas_authentication_test.rb
|
66
|
+
- test/unit/cas_user_test.rb
|
67
|
+
- test/unit/cas_utils_test.rb
|
68
|
+
- test/unit/helpers/login_portlet_helper_test.rb
|