Module: HubSsoLib::Core

Defined in:
lib/hub_sso_lib.rb

Overview

Module: Core #

Various authors                                            #
                                                           #

Purpose: The barely recognisable core of acts_as_authenticated’s #

AuthenticatedSystem module, modified to work with the      #
other parts of HubSsoLib. You should include this module   #
to use its facilities.                                     #
                                                           #

Author: Various; adaptation by A.D.Hodgkinson #

#

History: 20-Oct-2006 (ADH): Integrated into HubSsoLib. #

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Inclusion hook to make various methods available as ActionView helper methods.



853
854
855
856
857
858
859
860
861
862
863
864
# File 'lib/hub_sso_lib.rb', line 853

def self.included(base)
  base.send :helper_method,
            :hubssolib_current_user,
            :hubssolib_unique_name,
            :hubssolib_logged_in?,
            :hubssolib_authorized?,
            :hubssolib_privileged?,
            :hubssolib_flash_data
rescue
  # We're not always included in controllers...
  nil
end

Instance Method Details

#hubssolib_afterwardsObject

Main after_filter method to tidy up after running state changes.



714
715
716
717
718
719
720
721
# File 'lib/hub_sso_lib.rb', line 714

def hubssolib_afterwards
  begin
    DRb.current_server
    DRb.stop_service()
  rescue DRb::DRbServerNotFound
    # Nothing to do; no service is running.
  end
end

#hubssolib_authorized?(action = action_name, classname = self.class) ⇒ Boolean

Check if the user is authorized to perform the current action. If calling from a helper, pass the action name and class name; otherwise by default, the current action name and ‘self.class’ will be used.

Override this method in your controllers if you want to restrict access to a different set of actions. Presently, the current user’s roles are compared against the caller’s permissions hash and the action name.

Returns:

  • (Boolean)


529
530
531
532
533
534
535
536
537
538
539
# File 'lib/hub_sso_lib.rb', line 529

def hubssolib_authorized?(action = action_name, classname = self.class)

  # Classes with no permissions object always authorise everything.
  # Otherwise, ask the permissions object for its opinion.

  if (classname.respond_to? :hubssolib_permissions)
    return classname.hubssolib_permissions.permitted?(hubssolib_get_user_roles, action)
  else
    return true
  end
end

#hubssolib_beforehandObject

Main filter method to implement HubSsoLib permissions management, session expiry and so-on. Call from controllers only, always as a before_fitler.



644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
# File 'lib/hub_sso_lib.rb', line 644

def hubssolib_beforehand

  # Does this action require a logged in user?

  if (self.class.respond_to? :hubssolib_permissions)
     = !self.class.hubssolib_permissions.permitted?('', action_name)
  else
     = false
  end

  # If we require login but we're logged out, redirect to Hub login.

  logged_in = hubssolib_logged_in?

  if ( and logged_in == false)
    hubssolib_store_location
    return 
  end

  # If we reach here the user is either logged, or the method does
  # not require them to be. In the latter case, if we're not logged
  # in there is no more work to do - exit early.

  return true unless logged_in # true -> let action processing continue

  # So we reach here knowing we're logged in, but the action may or
  # may not require authorisation.

  if ()

    # Login *is* required for this action. If the session expires,
    # redirect to Hub's login page via its expiry action. Otherwise
    # check authorisation and allow action processing to continue
    # if OK, else indicate that access is denied.

    if (hubssolib_session_expired?)
      hubssolib_store_location
      hubssolib_log_out
      hubssolib_set_flash(:attention, 'Sorry, your session timed out; you need to log in again to continue.')

      # We mean this: redirect_to :controller => 'account', :action => 'login'
      # ...except for the Hub, rather than the current application (whatever
      # it may be).
      redirect_to HUB_PATH_PREFIX + '/account/login'
    else
      hubssolib_set_last_used(Time.now.utc)
      return hubssolib_authorized? ? true : hubssolib_access_denied
    end

  else

    # We have to update session expiry even for actions that don't
    # need us to be logged in, since we *are* logged in and need to
    # maintain that state. If, though, the session expires, we just
    # quietly log out and let action processing carry on.

    if (hubssolib_session_expired?)
      hubssolib_log_out
      hubssolib_set_flash(:attention, 'Your session timed out, so you are no longer logged in.')
    else
      hubssolib_set_last_used(Time.now.utc)
    end

    return true # true -> let action processing continue

  end
end

#hubssolib_clear_flashObject



791
792
793
794
# File 'lib/hub_sso_lib.rb', line 791

def hubssolib_clear_flash
  return unless self.hubssolib_current_session
  self.hubssolib_current_session.session_flash = {}
end

#hubssolib_current_sessionObject

Accesses the current session from the cookie. Creates a new session object if need be, but can return nil if e.g. attempting to access session cookie data without SSL.



568
569
570
# File 'lib/hub_sso_lib.rb', line 568

def hubssolib_current_session
  @hubssolib_current_session_proxy ||= hubssolib_get_session_proxy()
end

#hubssolib_current_userObject

Accesses the current user, via the DRb server if necessary.



574
575
576
577
578
579
580
581
582
583
# File 'lib/hub_sso_lib.rb', line 574

def hubssolib_current_user
  hub_session = self.hubssolib_current_session
  user        = hub_session.nil? ? nil : hub_session.session_user

  if (user && user.user_id)
    return user
  else
    return nil
  end
end

#hubssolib_current_user=(user) ⇒ Object

Store the given user data in the cookie



587
588
589
590
# File 'lib/hub_sso_lib.rb', line 587

def hubssolib_current_user=(user)
  hub_session = self.hubssolib_current_session
  hub_session.session_user = user unless hub_session.nil?
end

#hubssolib_ensure_httpsObject

Ensure the current request is carried out over HTTPS by redirecting back to the current URL with the HTTPS protocol if it isn’t. Returns ‘true’ if not redirected (already HTTPS), else ‘false’.



764
765
766
767
768
769
770
771
772
# File 'lib/hub_sso_lib.rb', line 764

def hubssolib_ensure_https
  if request.ssl? || hub_bypass_ssl?
    return true
  else
    # This isn't reliable: redirect_to({ :protocol => 'https://' })
    redirect_to( hubssolib_promote_uri_to_ssl( request.request_uri, request.host ) )
    return false
  end
end

#hubssolib_flash_dataObject

Return flash data for known keys, then all remaining keys, from both the cross-application and standard standard flash hashes. The returned Hash is of the form:

{ 'hub' => ...data..., 'standard' => ...data... }

…where “…data…” is itself a Hash of flash keys yielding flash values. This allows both the Hub and standard flashes to have values inside them under the same key. All keys are strings.



806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
# File 'lib/hub_sso_lib.rb', line 806

def hubssolib_flash_data

  # These known key values are used to guarantee an order in the output
  # for cases where multiple messages are defined.
  #
  compiled_data = { 'hub' => {}, 'standard' => {} }
  ordered_keys  = [
    'notice',
    'attention',
    'alert'
  ]

  # Get an array of keys for the Hub flash with the ordered key items
  # first and store data from that flash; same again for standard.

  hash = hubssolib_get_flash()
  keys = ordered_keys | hash.keys

  keys.each do | key |
    compiled_data['hub'][key] = hash[key] if hash.key?(key)
  end

  if defined?( flash )
    hash = flash.to_h()
    keys = ordered_keys | hash.keys

    keys.each do | key |
      compiled_data['standard'][key] = hash[key] if hash.key?(key)
    end
  end

  hubssolib_clear_flash()
  flash.discard()

  return compiled_data
end

#hubssolib_get_exception_message(id_data) ⇒ Object

Retrieve the message of an exception stored as an object in the given string.



846
847
848
# File 'lib/hub_sso_lib.rb', line 846

def hubssolib_get_exception_message(id_data)
  hubssolib_get_exception_data(CGI::unescape(id_data))
end

#hubssolib_get_flashObject

Public methods to set some data that would normally go in @session, but can’t because it needs to be accessed across applications. It is put in an insecure support cookie instead. There are some related private methods for things like session expiry too.



779
780
781
782
# File 'lib/hub_sso_lib.rb', line 779

def hubssolib_get_flash()
  f = self.hubssolib_current_session ? self.hubssolib_current_session.session_flash : nil
  return f || {}
end

#hubssolib_get_user_addressObject

Public read-only accessor methods for common user activities: return the current user’s e-mail address, or nil if there’s no user.



623
624
625
626
# File 'lib/hub_sso_lib.rb', line 623

def hubssolib_get_user_address
  user = self.hubssolib_current_user
  user ? user.user_email : nil
end

#hubssolib_get_user_idObject

Public read-only accessor methods for common user activities: return the Hub database ID of the current user account, or nil if there’s no user. See also hubssolib_unique_name.



614
615
616
617
# File 'lib/hub_sso_lib.rb', line 614

def hubssolib_get_user_id
  user = self.hubssolib_current_user
  user ? user.user_id : nil
end

#hubssolib_get_user_nameObject

Public read-only accessor methods for common user activities: return the current user’s name as a string, or nil if there’s no user. See also hubssolib_unique_name.



605
606
607
608
# File 'lib/hub_sso_lib.rb', line 605

def hubssolib_get_user_name
  user = self.hubssolib_current_user
  user ? user.user_real_name : nil
end

#hubssolib_get_user_rolesObject

Public read-only accessor methods for common user activities: return the current user’s roles as a Roles object, or nil if there’s no user.



596
597
598
599
# File 'lib/hub_sso_lib.rb', line 596

def hubssolib_get_user_roles
  user = self.hubssolib_current_user
  user ? user.user_roles.to_authenticated_roles : nil
end

#hubssolib_log_outObject

Log out the user. Very few applications should ever need to call this, though Hub certainly does and it gets used internally too.



557
558
559
560
561
562
# File 'lib/hub_sso_lib.rb', line 557

def hubssolib_log_out
  # Causes the "hubssolib_current_[foo]=" methods to run, which
  # deal with everything else.
  self.hubssolib_current_user = nil
  @hubssolib_current_session_proxy = nil
end

#hubssolib_logged_in?Boolean

Returns true or false if the user is logged in.

Preloads @hubssolib_current_user with user data if logged in.

Returns:

  • (Boolean)


517
518
519
# File 'lib/hub_sso_lib.rb', line 517

def hubssolib_logged_in?
  !!self.hubssolib_current_user
end

#hubssolib_privileged?Boolean

Is the current user privileged? Anything other than normal user privileges will suffice. Can be called if not logged in. Returns ‘false’ for logged out or normal user privileges only, else ‘true’.

Returns:

  • (Boolean)


545
546
547
548
549
550
551
552
# File 'lib/hub_sso_lib.rb', line 545

def hubssolib_privileged?
  return false unless hubssolib_logged_in?

  pnormal = HubSsoLib::Roles.new(false).to_s
  puser   = hubssolib_get_user_roles().to_s

  return (puser && !puser.empty? && puser != pnormal)
end

#hubssolib_promote_uri_to_ssl(uri_str, host = nil) ⇒ Object

Take a URI and pass an optional host parameter. Decomposes the URI, sets the host you provide (or leaves it alone if you omit the parameter), then forces the scheme to ‘https’. Returns the result as a flat string.



753
754
755
756
757
758
# File 'lib/hub_sso_lib.rb', line 753

def hubssolib_promote_uri_to_ssl(uri_str, host = nil)
  uri = URI.parse(uri_str)
  uri.host = host if host
  uri.scheme = hub_bypass_ssl? ? 'http' : 'https'
  return uri.to_s
end

#hubssolib_redirect_back_or_default(default) ⇒ Object

Redirect to the URI stored by the most recent store_location call or to the passed default.



741
742
743
744
745
746
# File 'lib/hub_sso_lib.rb', line 741

def hubssolib_redirect_back_or_default(default)
  url = hubssolib_get_return_to
  hubssolib_set_return_to(nil)

  redirect_to(url || default)
end

#hubssolib_set_flash(symbol, message) ⇒ Object



784
785
786
787
788
789
# File 'lib/hub_sso_lib.rb', line 784

def hubssolib_set_flash(symbol, message)
  return unless self.hubssolib_current_session
  f = hubssolib_get_flash
  f[symbol.to_s] = message
  self.hubssolib_current_session.session_flash = f
end

#hubssolib_store_location(uri_str = request.url) ⇒ Object

Store the URI of the current request in the session, or store the optional supplied specific URI.

We can return to this location by calling #redirect_back_or_default.



728
729
730
731
732
733
734
735
736
737
# File 'lib/hub_sso_lib.rb', line 728

def hubssolib_store_location(uri_str = request.url)

  if (uri_str && !uri_str.empty?)
    uri_str = hubssolib_promote_uri_to_ssl(uri_str, request.host) unless request.ssl?
    hubssolib_set_return_to(uri_str)
  else
    hubssolib_set_return_to(nil)
  end

end

#hubssolib_unique_nameObject

Return a human-readable unique ID for a user. We don’t want to have e-mail addresses all over the place, but don’t want to rely on real names as unique - they aren’t. Instead, produce a composite of the user’s account database ID (which must be unique by definition) and their real name. See also hubssolib_get_name.



635
636
637
638
# File 'lib/hub_sso_lib.rb', line 635

def hubssolib_unique_name
  user = hubssolib_current_user
  user ? "#{user.user_real_name} (#{user.user_id})" : 'Anonymous'
end