Skip to content

Improvements for Rails and ActiveRecord Integration #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*.gem
*.rbc
log
.bundle
.config
.yardoc
Expand All @@ -16,3 +17,4 @@ test/tmp
test/version_tmp
tmp
*.DS_Store
*.db
19 changes: 2 additions & 17 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
source 'https://rubygems.org'
gemspec

group :development do
# for gems that are nice in development
# but don't break the build when missing
# Example: debugger
gem 'debugger'
gem "guard"
gem "guard-rspec"

gem 'rb-inotify', :require => false
gem 'rb-fsevent', :require => false
gem 'rb-fchange', :require => false
end

group :test do
gem 'rake'
gem 'rspec'
end
gem 'rake'
gem 'rspec'
1 change: 1 addition & 0 deletions lib/rubycas-server-core.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "logger"
require "r18n-core"
require "rubycas-server-core/version"
require "rubycas-server-core/error"
require "rubycas-server-core/authenticator"
require "rubycas-server-core/settings"
require "rubycas-server-core/database"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module RubyCAS
module Server
module Core
module Tickets
class ServiceTicket < Storage
class ServiceTicket < RubyCAS::Server::Core::Tickets::TicketGrantingTicket

attr_accessor :id, :ticket, :consumed, :client_hostname,
:username, :created_at, :updated_at, :proxy_granting_ticket,
Expand Down
5 changes: 5 additions & 0 deletions lib/rubycas-server-core/adapters/in_memory/storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ def save
return true
end

def save!
self.class.storage[@id] = self
return true
end

end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Tickets
class TicketGrantingTicket < Storage
attr_accessor :id, :ticket, :client_hostname, :username,
:extra_attributes, :service_tickets, :proxy_tickets,
:created_at, :updated_at
:remember_me, :created_at, :updated_at

def initialize(tgt = {})
@id = SecureRandom.uuid
Expand All @@ -15,6 +15,7 @@ def initialize(tgt = {})
@extra_attributes = tgt[:extra_attributes]
@service_tickets = tgt[:service_tickets]
@proxy_tickets = tgt[:proxy_tickets]
@remember_me = tgt[:remember_me]
@created_at = DateTime.now
@updated_at = DateTime.now
super()
Expand All @@ -31,6 +32,10 @@ def expired?(max_lifetime)
lifetime = Time.now.to_i - created_at.to_time.to_i
lifetime > max_lifetime
end

def service_tickets
ServiceTicket
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rubycas-server-core/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Core
module Database
extend self
def setup(config_file)
raise NotImplementedError, "Database adapter is missing, add it to your Gemfile, please refer to https://github.com/rubycas/rubycas-server-core/wiki for more details"
#raise NotImplementedError, "Database adapter is missing, add it to your Gemfile, please refer to https://github.com/rubycas/rubycas-server-core/wiki for more details"
end
end
end
Expand Down
18 changes: 18 additions & 0 deletions lib/rubycas-server-core/error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module RubyCAS::Server::Core
# TODO: Add better dependency injection
# TODO: add predefined messages/errors
module Error
class Error
attr_reader :code, :message

def initialize(code, message)
@code = code
@message = message
end

def to_s
message
end
end
end
end
9 changes: 6 additions & 3 deletions lib/rubycas-server-core/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ module Settings
@_settings = HashWithIndifferentAccess.new
attr_reader :_settings

def load!(file_name)
config = YAML::load_file(file_name).with_indifferent_access
@_settings.merge!(config)
def load!(config)
if config.is_a? String
config = YAML::load_file(config).with_indifferent_access
elsif config.is_a? Hash
@_settings.merge!(config)
end
end

def method_missing(name, *args, &block)
Expand Down
16 changes: 11 additions & 5 deletions lib/rubycas-server-core/tickets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def self.generate_login_ticket(client)
lt = LoginTicket.new
lt.ticket = "LT-" + Util.random_string
lt.client_hostname = client
if lt.save
if lt.save!
$LOG.debug("Login ticket '#{lt.ticket} has been created for '#{lt.client_hostname}'")
return lt
else
Expand All @@ -24,13 +24,19 @@ def self.generate_login_ticket(client)
# The optional 'extra_attributes' parameter takes a hash of additional attributes
# that will be sent along with the username in the CAS response to subsequent
# validation requests from clients.
def self.generate_ticket_granting_ticket(username, client, extra_attributes = {})
def self.generate_ticket_granting_ticket(
username,
client,
remember_me = false,
extra_attributes = {}
)
tgt = TicketGrantingTicket.new
tgt.ticket = "TGC-" + Util.random_string
tgt.username = username
tgt.extra_attributes = extra_attributes
tgt.remember_me = remember_me
tgt.extra_attributes = extra_attributes.to_s
tgt.client_hostname = client
if tgt.save
if tgt.save!
$LOG.debug("Generated ticket granting ticket '#{tgt.ticket}' for user" +
" '#{tgt.username}' at '#{tgt.client_hostname}'" +
(extra_attributes.empty? ? "" : " with extra attributes #{extra_attributes.inspect}"))
Expand All @@ -41,7 +47,7 @@ def self.generate_ticket_granting_ticket(username, client, extra_attributes = {}
end

def self.generate_service_ticket(service, username, tgt, client)
st = ServiceTicket.new
st = tgt.service_tickets.new
st.ticket = "ST-" + Util.random_string
st.service = service
st.username = username
Expand Down
15 changes: 12 additions & 3 deletions lib/rubycas-server-core/tickets/validations.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
require "rubycas-server-core/error"

module RubyCAS::Server::Core::Tickets
module Validations
include R18n::Helpers
include RubyCAS::Server::Core::Error

# Validate login ticket
#
Expand All @@ -17,11 +20,11 @@ def validate_login_ticket(ticket)
if lt.consumed?
error = t.error.login_ticket_already_used
$LOG.warn "Login ticket '#{ticket}' already consumed!"
elsif not lt.expired?(RubyCAS::Server::Core::Settings.maximum_unused_service_ticket_lifetime)
elsif not lt.expired?(RubyCAS::Server::Core::Settings.maximum_unused_login_ticket_lifetime)
$LOG.info "Login ticket '#{ticket}' successfully validated"
lt.consume!
success = true
elsif lt.expired?(RubyCAS::Server::Core::Settings.maximum_unused_service_ticket_lifetime)
elsif lt.expired?(RubyCAS::Server::Core::Settings.maximum_unused_login_ticket_lifetime)
error = t.error.login_timeout
$LOG.warn "Expired login ticket '#{ticket}'"
end
Expand All @@ -38,7 +41,13 @@ def validate_ticket_granting_ticket(ticket)
$LOG.debug "No ticket granting ticket given." if ticket.nil?

if tgt = TicketGrantingTicket.find_by_ticket(ticket)
if tgt.expired?(RubyCAS::Server::Core::Settings.maximum_session_lifetime)
if tgt.remember_me
max_lifetime = RubyCAS::Server::Core::Settings.maximum_session_lifetime
else
max_lifetime = RubyCAS::Server::Core::Settings.maximum_remember_me_lifetime
end

if tgt.expired?(max_lifetime)
tgt.destroy
error = "Your session has expired. Please log in again."
$LOG.info "Ticket granting ticket '#{ticket}' for user '#{tgt.username}' expired."
Expand Down
3 changes: 3 additions & 0 deletions rubycas-server-core.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ Gem::Specification.new do |gem|

gem.add_dependency "r18n-core"
gem.add_dependency "activesupport", ">= 3.0"

gem.add_development_dependency "rspec"
gem.add_development_dependency "bundler"
end
1 change: 1 addition & 0 deletions spec/config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ maximum_unused_login_ticket_lifetime: 300
maximum_unused_service_ticket_lifetime: 300

maximum_session_lifetime: 172800
maximum_remember_me_lifetime: 604800
downcase_username: true

default_locale: en
128 changes: 86 additions & 42 deletions spec/rubycas-server-core/tickets/validations_spec.rb
Original file line number Diff line number Diff line change
@@ -1,62 +1,106 @@
require "spec_helper"

describe RubyCAS::Server::Core::Tickets::Validations do
before(:all) do
Tickets = RubyCAS::Server::Core::Tickets
end

before do
RubyCAS::Server::Core.setup("spec/config/config.yml")
klass = Class.new {
RubyCAS::Server::Core.setup("spec/config/config.yml")
klass = Class.new {
include RubyCAS::Server::Core::Tickets
include RubyCAS::Server::Core::Tickets::Validations
}
@cas = klass.new
@client_hostname = "myhost.test"
Tickets = RubyCAS::Server::Core::Tickets
}
@cas = klass.new
@client_hostname = "myhost.test"
end

describe "validate login ticket" do
it "should validate login ticket" do
@lt = Tickets.generate_login_ticket(@client_hostname)
success, error = @cas.validate_login_ticket(@lt.ticket)
success.should be_true
error.should be_nil
end
end
describe "validations"

describe "validate ticket_granting_ticket(username, extra_attributes = {})" do
before do
@username = 'myuser'
@client_hostname = "myhost.test"
@tgt = Tickets.generate_ticket_granting_ticket(@username, @client_hostname)
end
describe "#validate_login_ticket" do
context "with valid ticket" do
it "should validate login ticket" do
@lt = Tickets.generate_login_ticket(@client_hostname)
success, error = @cas.validate_login_ticket(@lt.ticket)
success.should be_true
error.should be_nil
end
end

it "should validate ticket granting ticket" do
success, error = @cas.validate_ticket_granting_ticket(@tgt.ticket)
success.should be_true
error.should be_nil
context "with invalid ticket" do
it "should not validate login ticket" do
@lt = Tickets.generate_login_ticket(@client_hostname)
success, error = @cas.validate_login_ticket("#{@lt.ticket}random")
expect(success).to be false
expect(error).not_to be nil
end
end
end
end

describe "validate service_ticket(service, username, tgt)" do
before do
@username = 'testuser'
@client_hostname = "myhost.test"
@service = 'myservice.test'
@tgt = Tickets.generate_ticket_granting_ticket(@username, @client_hostname)
@st = Tickets.generate_service_ticket(@service, @username, @tgt, @client_hostname)
end
describe "#validate_ticket_granting_ticket(username, extra_attributes = {})" do
before do
@username = 'myuser'
@client_hostname = "myhost.test"
@tgt = Tickets.generate_ticket_granting_ticket(@username, @client_hostname)
end

context "with valid tgt" do
it "should validate ticket granting ticket" do
success, error = @cas.validate_ticket_granting_ticket(@tgt.ticket)
expect(success).to eq @tgt
expect(error).to eq nil
end
end

it "should validate service ticket" do
success, error = @cas.validate_service_ticket(@service, @st.ticket)
success.should be_true
error.should be_nil
context "with invalid gt" do
it "should not validate ticket granting ticket" do
success, error = @cas.validate_ticket_granting_ticket("#{@tgt.ticket}random")
expect(success).to eq nil
expect(error).not_to eq nil
end
end
end
end

describe "validate proxy_ticket(target_service, pgt)" do
describe "validate service_ticket(service, username, tgt)" do
context "with valid ticket" do
before do
@username = 'testuser'
@client_hostname = "myhost.test"
@service = 'myservice.test'
@tgt = Tickets.generate_ticket_granting_ticket(@username, @client_hostname)
@st = Tickets.generate_service_ticket(@service, @username, @tgt, @client_hostname)
end

it "should validate service ticket" do
success, error = @cas.validate_service_ticket(@service, @st.ticket)
expect(success).to eq @st
expect(error).to be nil
end
end

context "with invalid ticket" do
before do
@username = 'testuser'
@client_hostname = "myhost.test"
@service = 'myservice.test'
@tgt = Tickets.generate_ticket_granting_ticket(@username, @client_hostname)
@st = Tickets.generate_service_ticket(@service, @username, @tgt, @client_hostname)
end

it "does not validate service ticket (throws an error)" do
success, error = @cas.validate_service_ticket(@service, "#{@st.ticket}-random_string")
expect(error).not_to be nil
end
end

before do
pending("Proxy ticket is not yet implemented")
end

end
describe "validate proxy_ticket(target_service, pgt)" do

before do
pending("Proxy ticket is not yet implemented")
end

end

end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'bundler/setup'
require 'rubycas-server-core'
require 'rubycas-server-core/adapters/in_memory'

begin
require 'debugger'
rescue LoadError
Expand Down