Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Adds CurrentUser processor #16

Closed
wants to merge 2 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
12 changes: 1 addition & 11 deletions app/controllers/casino/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,12 @@
require 'http_accept_language'

class CASino::ApplicationController < ::ApplicationController
include ApplicationHelper
include CASino::ApplicationHelper

layout 'application'
before_filter :set_locale

def cookies
super
end

protected
def processor(processor_name, listener_name = nil)
listener_name ||= processor_name
listener = CASino.const_get(:"#{listener_name}Listener").new(self)
@processor = CASino.const_get(:"#{processor_name}Processor").new(listener)
end

def set_locale
I18n.locale = extract_locale_from_accept_language_header || I18n.default_locale
end
Expand Down
17 changes: 10 additions & 7 deletions app/controllers/casino/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
class CASino::SessionsController < CASino::ApplicationController
include CASino::SessionsHelper

skip_before_filter :set_current_user, only:[:create, :validate_otp]

def index
processor(:TwoFactorAuthenticatorOverview).process(cookies, request.user_agent)
processor(:SessionOverview).process(cookies, request.user_agent)
processor(:TwoFactorAuthenticatorOverview).process(current_user, request.user_agent)
processor(:SessionOverview).process(current_user, request.user_agent)
end

def new
processor(:LoginCredentialRequestor).process(params, cookies, request.user_agent)
processor(:LoginCredentialRequestor).process(params, current_user, request.user_agent)
end

def create
processor(:LoginCredentialAcceptor).process(params, request.user_agent)
end

def destroy
processor(:SessionDestroyer).process(params, cookies, request.user_agent)
processor(:SessionDestroyer).process(params, current_user, request.user_agent)
end

def destroy_others
processor(:OtherSessionsDestroyer).process(params, cookies, request.user_agent)
processor(:OtherSessionsDestroyer).process(params, current_user, request.user_agent)
end

def logout
processor(:Logout).process(params, cookies, request.user_agent)
processor(:Logout).process(params, current_user, request.user_agent)
end

def validate_otp
processor(:SecondFactorAuthenticationAcceptor).process(params, request.user_agent)
processor(:CurrentUser).process(params, request.user_agent, ignore_two_factor:true)
processor(:SecondFactorAuthenticationAcceptor).process(params, current_user, request.user_agent)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ class CASino::TwoFactorAuthenticatorsController < CASino::ApplicationController
include CASino::SessionsHelper

def new
processor(:TwoFactorAuthenticatorRegistrator).process(cookies, request.user_agent)
processor(:TwoFactorAuthenticatorRegistrator).process(current_user, request.user_agent)
end

def create
processor(:TwoFactorAuthenticatorActivator).process(params, cookies, request.user_agent)
processor(:TwoFactorAuthenticatorActivator).process(params, current_user, request.user_agent)
end

def destroy
processor(:TwoFactorAuthenticatorDestroyer).process(params, cookies, request.user_agent)
processor(:TwoFactorAuthenticatorDestroyer).process(params, current_user, request.user_agent)
end
end
2 changes: 0 additions & 2 deletions app/helpers/application_helper.rb

This file was deleted.

9 changes: 9 additions & 0 deletions app/helpers/casino/application_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module CASino
module ApplicationHelper
extend ActiveSupport::Concern

included do
include CASino::CurrentUserHelper
end
end
end
23 changes: 23 additions & 0 deletions app/helpers/casino/current_user_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module CASino::CurrentUserHelper
include CASino::ProcessorHelper

def self.included(base)
return unless base.ancestors.include? ActionController::Base

base.helper_method :current_user, :user_signed_in?
base.before_filter :set_current_user
end

def set_current_user
params[:tgt] ||= cookies[:tgt]
processor(:CurrentUser).process(params, request.user_agent)
end

def current_user
@current_user
end

def user_signed_in?
!!current_user
end
end
8 changes: 8 additions & 0 deletions app/helpers/casino/processor_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module CASino::ProcessorHelper
protected
def processor(processor_name, listener_name = nil)
listener_name ||= processor_name
listener = CASino.const_get(:"#{listener_name}Listener").new(self)
@processor = CASino.const_get(:"#{processor_name}Processor").new(listener)
end
end
13 changes: 13 additions & 0 deletions app/listeners/casino/current_user_listener.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CASino::CurrentUserListener < CASino::Listener
def user_not_logged_in
# NO-OP
end

def user_not_logged_in!
@controller.redirect_to login_path
end

def current_user_found(user)
assign(:current_user, user)
end
end
11 changes: 9 additions & 2 deletions app/listeners/casino/listener.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
module CASino
class Listener

# include helpers to have the route path methods (like sessions_path)
include CASino::Engine.routes.url_helpers

def initialize(controller)
@controller = controller
end

protected
def assign(name, value)
@controller.instance_variable_set("@#{name}", value)
end

def assigned(name)
@controller.instance_variable_get("@#{name}")
end

protected
def cookies
@controller.send(:cookies)
end
end
end
2 changes: 1 addition & 1 deletion app/listeners/casino/login_credential_acceptor_listener.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class CASino::LoginCredentialAcceptorListener < CASino::Listener
def user_logged_in(url, ticket_granting_ticket, cookie_expiry_time = nil)
@controller.cookies[:tgt] = { value: ticket_granting_ticket, expires: cookie_expiry_time }
cookies[:tgt] = { value: ticket_granting_ticket, expires: cookie_expiry_time }
if url.nil?
@controller.redirect_to sessions_path, status: :see_other
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class CASino::LoginCredentialRequestorListener < CASino::Listener
def user_not_logged_in(login_ticket)
assign(:login_ticket, login_ticket)
@controller.cookies.delete :tgt
cookies.delete :tgt
end

def service_not_allowed(service)
Expand Down
3 changes: 2 additions & 1 deletion app/listeners/casino/logout_listener.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

class CASino::LogoutListener < CASino::Listener
def user_logged_out(url, redirect_immediately = false)
assign(:current_user, nil)
if redirect_immediately
@controller.redirect_to url, status: :see_other
else
assign(:url, url)
end
@controller.cookies.delete :tgt
cookies.delete :tgt
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def user_not_logged_in
end

def user_logged_in(url, ticket_granting_ticket, cookie_expiry_time = nil)
@controller.cookies[:tgt] = { value: ticket_granting_ticket, expires: cookie_expiry_time }
cookies[:tgt] = { value: ticket_granting_ticket, expires: cookie_expiry_time }
if url.nil?
@controller.redirect_to sessions_path, status: :see_other
else
Expand Down
7 changes: 7 additions & 0 deletions app/models/casino/ticket_granting_ticket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ class CASino::TicketGrantingTicket < ActiveRecord::Base
belongs_to :user
has_many :service_tickets, dependent: :destroy

# Backport Rails 4's ActiveRecord::NullRelation
# From: http://stackoverflow.com/questions/4877931/how-to-return-an-empty-activerecord-relation
# See also: http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-none
if Rails.version.to_i < 4
scope :none, where('1=0')
end

def self.cleanup(user = nil)
if user.nil?
base = self
Expand Down
19 changes: 19 additions & 0 deletions app/models/casino/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,23 @@ class CASino::User < ActiveRecord::Base
def active_two_factor_authenticator
self.two_factor_authenticators.where(active: true).first
end

def ticket(params = {})
query = if params
params = params.delete_if{ |k,v| v.nil? }
ticket_granting_tickets.where(params)
else
ticket_granting_tickets
end

query.first
end

def other_tickets(user_agent = nil)
if primary = ticket(user_agent:user_agent)
ticket_granting_tickets.where('id != ?', primary.id)
else
ticket_granting_tickets.none
end
end
end
52 changes: 52 additions & 0 deletions app/processors/casino/current_user_processor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class CASino::CurrentUserProcessor < CASino::Processor
include CASino::ProcessorConcern::LoginTickets
include CASino::ProcessorConcern::TicketGrantingTickets

# This method will call `#user_not_logged_in` or `#current_user_found(User)` on the listener.
# @param [Hash] params A Hash delivered by the client used to located the User's Ticket Granting Ticket
# @param [String] user_agent user-agent delivered by the client
def process(params = nil, user_agent = nil, options = {})
options ||= {}
if user = handle_process(params, user_agent, options)
@listener.current_user_found(user)
else
@listener.user_not_logged_in
end
end

# This method will call `#user_not_logged_in!` or `#current_user_found(User)` on the listener.
# @param [Hash] params A Hash delivered by the client used to located the User's Ticket Granting Ticket
# @param [String] user_agent user-agent delivered by the client
def process!(params = nil, user_agent = nil, options = {})
options ||= {}
if handle_process(params, user_agent, options)
@listener.current_user_found
else
@listener.user_not_logged_in!
end
end

private
def handle_process(params, user_agent, options)
return current_user if user_signed_in?

@params, @user_agent = (params || {}), user_agent

ticket_granting_ticket(options).try(:user)
end

def current_user
@listener.assigned :current_user
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I don't like this. It introduces a circular dependency. I don't think it is really necessary, since the current user will be passed in as a parameter to all the processors.

end

def user_signed_in?
current_user
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be !!current_user to always return a boolean.

end

def ticket_granting_ticket(options)
@ticket_granting_ticket ||= begin
find_valid_ticket_granting_ticket(@params[:tgt], @user_agent, options[:ignore_two_factor])
end
end

end
17 changes: 11 additions & 6 deletions app/processors/casino/login_credential_requestor_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class CASino::LoginCredentialRequestorProcessor < CASino::Processor
include CASino::ProcessorConcern::Browser
include CASino::ProcessorConcern::LoginTickets
include CASino::ProcessorConcern::ServiceTickets
include CASino::ProcessorConcern::TicketGrantingTickets
include CASino::ProcessorConcern::CurrentUser

# Use this method to process the request.
#
Expand All @@ -13,20 +13,21 @@ class CASino::LoginCredentialRequestorProcessor < CASino::Processor
# * `#service_not_allowed`: The user tried to access a service that this CAS server is not allowed to serve.
#
# @param [Hash] params parameters supplied by user
# @param [Hash] cookies cookies supplied by user
# @param [Object] user A previously initializer User instance
# @param [String] user_agent user-agent delivered by the client
def process(params = nil, cookies = nil, user_agent = nil)
def process(params = nil, user = nil, user_agent = nil)
@params = params || {}
@cookies = cookies || {}
@user_agent = user_agent || {}
@user = user || current_user
@user_agent = user_agent

if check_service_allowed
handle_allowed_service
end
end

private
def handle_allowed_service
if !@params[:renew] && (@ticket_granting_ticket = find_valid_ticket_granting_ticket(@cookies[:tgt], @user_agent))
if !@params[:renew] && ticket_granting_ticket
handle_logged_in
else
handle_not_logged_in
Expand Down Expand Up @@ -63,4 +64,8 @@ def check_service_allowed
def gateway_request?
@params[:gateway] == 'true' && @params[:service]
end

def ticket_granting_ticket
@ticket_granting_ticket ||= @user.ticket(user_agent:@user_agent)
end
end
10 changes: 5 additions & 5 deletions app/processors/casino/logout_processor.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# The Logout processor should be used to process GET requests to /logout.
class CASino::LogoutProcessor < CASino::Processor
include CASino::ProcessorConcern::TicketGrantingTickets
include CASino::ProcessorConcern::CurrentUser

# This method will call `#user_logged_out` and may supply an URL that should be presented to the user.
# As per specification, the URL specified by "url" SHOULD be on the logout page with descriptive text.
# For example, "The application you just logged out of has provided a link it would like you to follow.
# Please click here to access http://www.go-back.edu/."
#
# @param [Hash] params parameters supplied by user
# @param [Hash] cookies cookies supplied by user
# @param [Object] user A previously initializer User instance
# @param [String] user_agent user-agent delivered by the client
def process(params = nil, cookies = nil, user_agent = nil)
def process(params = nil, user = nil, user_agent = nil)
params ||= {}
cookies ||= {}
remove_ticket_granting_ticket(cookies[:tgt], user_agent)
user ||= current_user
user.ticket(user_agent:user_agent).try(:destroy)
if params[:service] && CASino::ServiceRule.allowed?(params[:service])
@listener.user_logged_out(params[:service], true)
else
Expand Down
Loading