global_session 1.0.10 → 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,8 +7,8 @@ spec = Gem::Specification.new do |s|
7
7
  s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
8
8
 
9
9
  s.name = 'global_session'
10
- s.version = '1.0.10'
11
- s.date = '2012-03-07'
10
+ s.version = '1.0.13'
11
+ s.date = '2012-09-26'
12
12
 
13
13
  s.authors = ['Tony Spataro']
14
14
  s.email = 'support@rightscale.com'
@@ -17,7 +17,7 @@ spec = Gem::Specification.new do |s|
17
17
  s.summary = %q{Secure single-domain session sharing plugin for Rails.}
18
18
  s.description = %q{This plugin for Rails allows several web apps in an authentication domain to share session state, facilitating single sign-on in a distributed web app. It only provides session sharing and does not concern itself with authentication or replication of the user database.}
19
19
 
20
- s.add_runtime_dependency('uuidtools', ["~> 2.1"])
20
+ s.add_runtime_dependency('uuidtools', [">= 1.0"])
21
21
  s.add_runtime_dependency('json', ["~> 1.4"])
22
22
  s.add_runtime_dependency('rack-contrib', ["~> 1.0"])
23
23
 
@@ -73,6 +73,11 @@ module GlobalSession
73
73
  # you are integrating; see GlobalSession::Rails for more information.
74
74
  #
75
75
  class Configuration
76
+ # @return a representation of the object suitable for printing to the console
77
+ def inspect
78
+ "<#{self.class.name} @environment=#{@environment.inspect}>"
79
+ end
80
+
76
81
  # Create a new Configuration object
77
82
  #
78
83
  # === Parameters
@@ -54,12 +54,17 @@ module GlobalSession
54
54
  class Directory
55
55
  attr_reader :configuration, :authorities, :private_key
56
56
 
57
+ # @return a representation of the object suitable for printing to the console
58
+ def inspect
59
+ "<#{self.class.name} @configuration=#{@configuration.inspect}>"
60
+ end
61
+
57
62
  # Create a new Directory.
58
63
  #
59
64
  # === Parameters
60
65
  # keystore_directory(String):: Absolute path to authority keystore
61
66
  #
62
- # ===Raise
67
+ # === Raise
63
68
  # ConfigurationError:: if too many or too few keys are found, or if *.key/*.pub files are malformatted
64
69
  def initialize(configuration, keystore_directory)
65
70
  @configuration = configuration
@@ -84,6 +89,26 @@ module GlobalSession
84
89
  @invalid_sessions = Set.new
85
90
  end
86
91
 
92
+ # Create a new Session, initialized against this directory and ready to
93
+ # be used by the app.
94
+ #
95
+ # === Parameters
96
+ # directory(Directory):: directory implementation that the session should use for various operations
97
+ # cookie(String):: Optional, serialized global session cookie. If none is supplied, a new session is created.
98
+ # valid_signature_digest(String):: Optional, already-trusted signature. If supplied, the expensive RSA-verify operation will be skipped if the cookie's signature matches the value supplied.
99
+ #
100
+ # === Return
101
+ # session(Session):: the newly-initialized session
102
+ #
103
+ # ===Raise
104
+ # InvalidSession:: if the session contained in the cookie has been invalidated
105
+ # ExpiredSession:: if the session contained in the cookie has expired
106
+ # MalformedCookie:: if the cookie was corrupt or malformed
107
+ # SecurityError:: if signature is invalid or cookie is not signed by a trusted authority
108
+ def create_session(*params)
109
+ Session.new(self, *params)
110
+ end
111
+
87
112
  def local_authority_name
88
113
  @configuration['authority']
89
114
  end
@@ -128,5 +153,18 @@ module GlobalSession
128
153
  def report_invalid_session(uuid, expired_at)
129
154
  @invalid_sessions << uuid
130
155
  end
156
+
157
+ # Callback used by GlobalSession::Rack::Middleware when the application invalidated
158
+ # current global_session object. This callback could help application to get data related
159
+ # to the previous global session (old_global_session_id), and put it to new global session
160
+ # (new_global_sesion_id)
161
+
162
+ # invalidated_uuid(String):: Invalidated Global session UUID
163
+ # new_uuid(String):: Newly created Global session UUID
164
+ # === Return
165
+ # true: Always returns true
166
+ def session_invalidated(invalidated_uuid, new_uuid)
167
+ true
168
+ end
131
169
  end
132
170
  end
@@ -88,7 +88,7 @@ module GlobalSession
88
88
  begin
89
89
  read_cookie(env)
90
90
  rescue Exception => e
91
- env['global_session'] = Session.new(@directory)
91
+ env['global_session'] = @directory.create_session
92
92
  handle_error('reading session cookie', env, e)
93
93
  end
94
94
 
@@ -114,12 +114,11 @@ module GlobalSession
114
114
  # env(Hash): Rack environment.
115
115
  def read_cookie(env)
116
116
  if env['rack.cookies'].has_key?(@cookie_name)
117
- env['global_session'] = Session.new(@directory,
118
- env['rack.cookies'][@cookie_name])
117
+ env['global_session'] = @directory.create_session(env['rack.cookies'][@cookie_name])
119
118
  elsif @cookie_retrieval && cookie = @cookie_retrieval.call(env)
120
- env['global_session'] = Session.new(@directory, cookie)
119
+ env['global_session'] = @directory.create_session(cookie)
121
120
  else
122
- env['global_session'] = Session.new(@directory)
121
+ env['global_session'] = @directory.create_session
123
122
  end
124
123
 
125
124
  true
@@ -149,9 +148,15 @@ module GlobalSession
149
148
 
150
149
  begin
151
150
  domain = @configuration['cookie']['domain'] || env['SERVER_NAME']
152
- if env['global_session'] && env['global_session'].valid?
153
- value = env['global_session'].to_s
154
- expires = @configuration['ephemeral'] ? nil : env['global_session'].expired_at
151
+ if env['global_session']
152
+ global_session = env['global_session']
153
+ unless global_session.valid?
154
+ invalidated_uuid = global_session.id
155
+ global_session = @directory.create_session
156
+ @directory.session_invalidated(invalidated_uuid, global_session.id)
157
+ end
158
+ value = global_session.to_s
159
+ expires = @configuration['ephemeral'] ? nil : global_session.expired_at
155
160
  unless env['rack.cookies'].has_key?(@cookie_name) && env['rack.cookies'][@cookie_name] == value
156
161
  env['rack.cookies'][@cookie_name] =
157
162
  {:value => value, :domain => domain, :expires => expires, :httponly=>true}
@@ -25,24 +25,23 @@ module GlobalSession
25
25
  # app-wide data such as the configuration object, and implements the DSL used to
26
26
  # configure controllers' use of the global session.
27
27
  module ActionControllerClassMethods
28
- def global_session_config
29
- unless @global_session_config
30
- config_file = File.join(::Rails.root, 'config', 'global_session.yml')
31
- @global_session_config = GlobalSession::Configuration.new(config_file, RAILS_ENV)
32
- end
33
-
34
- return @global_session_config
35
- end
36
-
37
- def global_session_config=(config)
38
- @global_session_config = config
39
- end
28
+ VALID_OPTIONS = [:raise, :renew, :only, :except]
29
+ DEFAULT_OPTIONS = {
30
+ :raise=>true,
31
+ :renew=>true
32
+ }
40
33
 
41
34
  def has_global_session(options={})
42
- odefault = {:integrated=>false, :raise=>true}
43
- obase = self.superclass.global_session_options if self.superclass.respond_to?(:global_session_options)
44
- obase ||= {}
45
- options = odefault.merge(obase).merge(options)
35
+ #validate our options
36
+ options.assert_valid_keys(VALID_OPTIONS)
37
+ if options.key?(:only) && options.key?(:except)
38
+ raise ArgumentError, "Must specify :only OR :except, you specified both"
39
+ end
40
+
41
+ #start with default options; merge any options inherited from our base class;
42
+ #merge any options provided by the caller.
43
+ obase = self.superclass.global_session_options
44
+ options = DEFAULT_OPTIONS.merge(obase).merge(options)
46
45
 
47
46
  #ensure derived-class options don't conflict with mutually exclusive base-class options
48
47
  options.delete(:only) if obase.has_key?(:only) && options.has_key?(:except)
@@ -51,20 +50,23 @@ module GlobalSession
51
50
  #mark the global session as enabled (a hidden option) and store our
52
51
  #calculated, merged options
53
52
  options[:enabled] = true
54
- self.global_session_options = options
55
53
 
56
- before_filter :global_session_initialize
54
+ self.global_session_options = options
57
55
  end
58
56
 
59
57
  def no_global_session
60
- @global_session_options[:enabled] = false if @global_session_options
61
- skip_before_filter :global_session_initialize
58
+ #mark the global session as not-enabled (a hidden option)
59
+ self.global_session_options={:enabled=>false}
62
60
  end
63
61
 
64
62
  def global_session_options
65
- obase = self.superclass.global_session_options if self.superclass.respond_to?(:global_session_options)
66
- obase ||= {}
67
- @global_session_options || obase
63
+ if @global_session_options
64
+ @global_session_options
65
+ elsif self.superclass.respond_to?(:global_session_options)
66
+ self.superclass.global_session_options
67
+ else
68
+ {}
69
+ end
68
70
  end
69
71
 
70
72
  def global_session_options=(options)
@@ -43,6 +43,8 @@ module GlobalSession
43
43
  unless base.instance_methods.include?("log_processing_without_global_session")
44
44
  base.alias_method_chain :log_processing, :global_session
45
45
  end
46
+
47
+ base.before_filter :global_session_initialize
46
48
  end
47
49
 
48
50
  # Shortcut accessor for global session configuration object.
@@ -41,14 +41,40 @@ end
41
41
 
42
42
  module GlobalSession
43
43
  module Rails
44
- def self.activate(config)
45
- authorities = File.join(::Rails.root, 'config', 'authorities')
46
- hgs_config = ActionController::Base.global_session_config
47
- hgs_dir = GlobalSession::Directory.new(hgs_config, authorities)
44
+ class <<self
45
+ # Single Configuration object used by entire Rails app
46
+ attr_accessor :configuration
47
+
48
+ # Single Directory object used by entire Rails app
49
+ attr_accessor :directory
50
+ end
51
+
52
+ def self.activate(rails_config, &block)
53
+ config_file = File.join(::Rails.root, 'config', 'global_session.yml')
54
+ self.configuration = GlobalSession::Configuration.new(config_file, ::Rails.env)
55
+
56
+ dir_name = self.configuration['directory'] || 'GlobalSession::Directory'
57
+ begin
58
+ dir_klass = dir_name.constantize
59
+ rescue NameError => e
60
+ raise GlobalSession::ConfigurationError,
61
+ "Unknown/malformed directory class '#{dir_name}' in config file: #{e.message}"
62
+ end
63
+
64
+ unless dir_klass.ancestors.include?(GlobalSession::Directory)
65
+ raise GlobalSession::ConfigurationError,
66
+ "Specified directory class '#{dir_name}' does not inherit from GlobalSession::Directory"
67
+ end
68
+
69
+ authorities_dir = File.join(::Rails.root, 'config', 'authorities')
70
+ self.directory = dir_klass.new(self.configuration, authorities_dir)
48
71
 
49
72
  # Add our middleware to the stack.
50
- config.middleware.use ::Rack::Cookies
51
- config.middleware.use ::Rack::GlobalSession, hgs_config, hgs_dir
73
+ rails_config.middleware.insert_before(ActionController::Base.session_store, ::Rack::Cookies)
74
+ rails_config.middleware.insert_before(ActionController::Base.session_store, ::Rack::GlobalSession,
75
+ self.configuration,
76
+ self.directory,
77
+ &block)
52
78
 
53
79
  return true
54
80
  end
@@ -48,6 +48,11 @@ module GlobalSession
48
48
  return Encoding::JSON.load(json)
49
49
  end
50
50
 
51
+ # @return a representation of the object suitable for printing to the console
52
+ def inspect
53
+ "<#{self.class.name} @id=#{@id.inspect}>"
54
+ end
55
+
51
56
  # Create a new global session object.
52
57
  #
53
58
  # === Parameters
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: global_session
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 10
10
- version: 1.0.10
9
+ - 13
10
+ version: 1.0.13
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tony Spataro
@@ -15,20 +15,20 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-07 00:00:00 -08:00
18
+ date: 2012-09-26 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  version_requirements: &id001 !ruby/object:Gem::Requirement
23
23
  none: false
24
24
  requirements:
25
- - - ~>
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
- hash: 1
27
+ hash: 15
28
28
  segments:
29
- - 2
30
29
  - 1
31
- version: "2.1"
30
+ - 0
31
+ version: "1.0"
32
32
  requirement: *id001
33
33
  name: uuidtools
34
34
  prerelease: false