Skip to content

Commit

Permalink
Merge branch 'master' of github.com:gunark/rubycas-server
Browse files Browse the repository at this point in the history
  • Loading branch information
zuk committed Jul 8, 2011
2 parents bf57b77 + 25f118d commit c7f4ecd
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 5 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
source "http://rubygems.org"
gemspec

17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@ See https://github.com/gunark/rubycas-server/commits/

## Installation

on ubuntu using unicorn:

git clone [email protected]:seven1240/rubycas-server.git
cd rubycas-server
sudo bundle install

If it complains mysql connectivity, do this

apt-get install libmysqlclient16-dev
sudo gem install mysql2

copy resources/config.example.yml into /etc/rubycas-server/config.yml, there's way to put the config in other place, yet to document. Change the config to meet your requests.

You might also want to change config/unicorn.conf

unicorn -D -c config/unicorn.conf

For info and detailed installation instructions please see http://code.google.com/p/rubycas-server

## License
Expand Down
125 changes: 125 additions & 0 deletions lib/casserver/authenticators/active_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
require 'casserver/authenticators/base'

begin
require 'active_resource'
rescue LoadError
require 'rubygems'
begin
gem 'activeresource', '~> 3.0.0'
rescue Gem::LoadError
$stderr.puts
$stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
$stderr.puts
$stderr.puts "To use the ActiveResource authenticator, you must first install the 'activeresource' gem."
$stderr.puts
$stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
exit 1
end
require 'active_resource'
end

module CASServer
module Authenticators

module Helpers
class Identity < ActiveResource::Base

# define method_name accessor
cattr_accessor(:method_name) do
:authenticate # default value
end

def self.method_type
@@method_type ||= :post
end

def self.method_type= type
methods = [:get, :post, :put, :delete]
raise ArgumentError, "Method type should be one of #{methods.map { |m| m.to_s.upcase }.join(', ')}" unless methods.include? type.to_sym
@@method_type = type
end

# Autenticate an identity using the given method
# @param [Hash] credentials
def self.authenticate(credentials = {})
response = send(method_type, method_name, credentials)
new.from_authentication_data(response)
end

# Used to load object attributes from the given response
def from_authentication_data response
load_attributes_from_response(response)
end
end
end

class ActiveResource < Base

# This is called at server startup.
# Any class-wide initializiation for the authenticator should be done here.
# (e.g. establish database connection).
# You can leave this empty if you don't need to set up anything.
def self.setup(options)
raise AuthenticatorError, 'You must define at least site option' unless options[:site]
# apply options to active resource object
options.each do |method, arg|
Helpers::Identity.send "#{method}=", arg if Helpers::Identity.respond_to? "#{method}="
end
$LOG.info "ActiveResource configuration loaded"
end

# Override this to implement your authentication credential validation.
# This is called each time the user tries to log in. The credentials hash
# holds the credentials as entered by the user (generally under :username
# and :password keys; :service and :request are also included by default)
#
# Note that the standard credentials can be read in to instance variables
# by calling #read_standard_credentials.
def validate(credentials)
begin
$LOG.debug("Starting Active Resource authentication")
result = Helpers::Identity.authenticate(credentials.except(:request))
extract_extra_attributes(result) if result
!!result
rescue ::ActiveResource::ConnectionError => e
$LOG.warn("Error during authentication: #{e}")
false
end
end

private

def extract_extra_attributes(resource)
@extra_attributes = {}
$LOG.debug("Parsing extra attributes")
if @options[:extra_attributes]
extra_attributes_to_extract.each do |attr|
@extra_attributes[attr] = resource.send(attr).to_s
end
else
@extra_attributes = resource.attributes
end
# do filtering
extra_attributes_to_filter.each do |attr|
@extra_attributes.delete(attr)
end
end

# extract attributes to filter from the given configuration
def extra_attributes_to_filter
# default value if not set
return ['password'] unless @options[:filter_attributes]
# parse option value
if @options[:filter_attributes].kind_of? Array
attrs = @options[:filter_attributes]
elsif @options[:filter_attributes].kind_of? String
attrs = @options[:filter_attributes].split(',').collect { |col| col.strip }
else
$LOG.error("Can't figure out attribute list from #{@options[:filter_attributes].inspect}. This must be an Aarray of column names or a comma-separated list.")
attrs = []
end
attrs
end
end
end
end
38 changes: 35 additions & 3 deletions lib/casserver/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,9 @@ def self.init_logger!
end

def self.init_database!
#CASServer::Model::Base.establish_connection(config[:database])
ActiveRecord::Base.establish_connection(config[:database])


unless config[:disable_auto_migrations]
ActiveRecord::Base.establish_connection(config[:database])
print_cli_message "Running migrations to make sure your database schema is up to date..."
prev_db_log = ActiveRecord::Base.logger
ActiveRecord::Base.logger = Logger.new(STDOUT)
Expand All @@ -264,6 +263,8 @@ def self.init_database!
ActiveRecord::Base.logger = prev_db_log
print_cli_message "Your database is now up to date."
end

CASServer::Model::Base.establish_connection(config[:database])
end

configure do
Expand Down Expand Up @@ -549,6 +550,37 @@ def self.init_database!
render @template_engine, :login
end
end


# Handler for obtaining login tickets.
# This is useful when you want to build a custom login form located on a
# remote server. Your form will have to include a valid login ticket
# value, and this can be fetched from the CAS server using the POST handler.

get "#{uri_path}/loginTicket" do
CASServer::Utils::log_controller_action(self.class, params)

$LOG.error("Tried to use login ticket dispenser with get method!")

status 422

"To generate a login ticket, you must make a POST request."
end


# Renders a page with a login ticket (and only the login ticket)
# in the response body.
post "#{uri_path}/loginTicket" do
CASServer::Utils::log_controller_action(self.class, params)

lt = generate_login_ticket

$LOG.debug("Dispensing login ticket #{lt} to host #{(@env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']).inspect}")

@lt = lt.ticket

@lt
end


# 2.4
Expand Down
4 changes: 2 additions & 2 deletions po/ru_RU/rubycas-server.po
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ msgid ""
"Could not guess the CAS login URI. Please supply a submitToURI parameter "
"with your request."
msgstr ""
"Не возможно угадать адрес входа на CAS. Пожалуйста, передайте с запросом "
"Невозможно угадать адрес входа на CAS. Пожалуйста, передайте с запросом "
"параметр submitToURI."

#: lib/casserver/controllers.rb:168
Expand Down Expand Up @@ -99,7 +99,7 @@ msgstr " Центральный вход"

#: lib/casserver/views.rb:68
msgid "Please wait..."
msgstr ""
msgstr "Подождите..."

#: lib/casserver/views.rb:74
msgid "Username"
Expand Down
1 change: 1 addition & 0 deletions rubycas-server.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ to build the LOCALE_LC files.

# for authenticator specs
s.add_development_dependency("net-ldap", "~> 0.1.1")
s.add_development_dependency("activeresource", "~> 3.0.0")

s.rdoc_options = [
'--quiet', '--title', 'RubyCAS-Server Documentation', '--opname',
Expand Down
109 changes: 109 additions & 0 deletions spec/authenticators/active_resource_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# encoding: UTF-8
require File.dirname(__FILE__) + '/../spec_helper'

require 'casserver/authenticators/active_resource'

describe CASServer::Authenticators::Helpers::Identity do

it { should be_an ActiveResource::Base }

it "class should respond to :authenticate" do
subject.class.should respond_to :authenticate
end

it "class should have a method_name accessor" do
CASServer::Authenticators::Helpers::Identity.method_name.should == :authenticate
end

it "class should have a method_name accessor" do
CASServer::Authenticators::Helpers::Identity.method_type.should == :post
end

it "class method_type accessor should validate type" do
expect {
CASServer::Authenticators::Helpers::Identity.method_type = :foo
}.to raise_error(ArgumentError)
end

end

describe CASServer::Authenticators::ActiveResource do

describe "#setup" do

it "should configure the identity object" do
CASServer::Authenticators::Helpers::Identity.should_receive(:user=).with('httpuser').once
CASServer::Authenticators::ActiveResource.setup :site => 'http://api.example.org', :user => 'httpuser'
end

it "should configure the method_type" do
CASServer::Authenticators::Helpers::Identity.should_receive(:method_type=).with('get').once
CASServer::Authenticators::ActiveResource.setup :site => 'http://api.example.org', :method_type => 'get'
end

it "should raise if site option is missing" do
expect {
CASServer::Authenticators::ActiveResource.setup({}).should
}.to raise_error(CASServer::AuthenticatorError, /site option/)
end
end

describe "#validate" do

let(:credentials) { {:username => 'validusername',
:password => 'validpassword',
:service => 'test.service'} }

let(:auth) { CASServer::Authenticators::ActiveResource.new }

def mock_authenticate identity = nil
identity = CASServer::Authenticators::Helpers::Identity.new if identity.nil?
CASServer::Authenticators::Helpers::Identity.stub!(:authenticate).and_return(identity)
end

def sample_identity attrs = {}
identity = CASServer::Authenticators::Helpers::Identity.new
attrs.each { |k,v| identity.send "#{k}=", v }
identity
end

it "should call Identity#autenticate with the given params" do
CASServer::Authenticators::Helpers::Identity.should_receive(:authenticate).with(credentials).once
auth.validate(credentials)
end

it "should return identity object attributes as extra attributes" do
auth.configure({}.with_indifferent_access)
identity = sample_identity({:email => '[email protected]'})
mock_authenticate identity
auth.validate(credentials).should be_true
auth.extra_attributes.should == identity.attributes
end

it "should return false when http raises" do
CASServer::Authenticators::Helpers::Identity.stub!(:authenticate).and_raise(ActiveResource::ForbiddenAccess.new({}))
auth.validate(credentials).should be_false
end

it "should apply extra_attribute filter" do
auth.configure({ :extra_attributes => 'age'}.with_indifferent_access)
mock_authenticate sample_identity({ :email => '[email protected]', :age => 28 })
auth.validate(credentials).should be_true
auth.extra_attributes.should == { "age" => "28" }
end

it "should only extract not filtered attributes" do
auth.configure({ :filter_attributes => 'age'}.with_indifferent_access)
mock_authenticate sample_identity({ :email => '[email protected]', :age => 28 })
auth.validate(credentials).should be_true
auth.extra_attributes.should == { "email" => '[email protected]' }
end

it "should filter password if filter attributes is not given" do
auth.configure({}.with_indifferent_access)
mock_authenticate sample_identity({ :email => '[email protected]', :password => 'secret' })
auth.validate(credentials).should be_true
auth.extra_attributes.should == { "email" => '[email protected]' }
end
end
end

0 comments on commit c7f4ecd

Please sign in to comment.