global_session 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.0'
11
- s.date = '2011-01-01'
10
+ s.version = '1.0.2'
11
+ s.date = '2011-01-15'
12
12
 
13
13
  s.authors = ['Tony Spataro']
14
14
  s.email = 'code@tracker.xeger.net'
@@ -21,11 +21,11 @@ spec = Gem::Specification.new do |s|
21
21
  s.add_runtime_dependency('json', [">= 1.1.7"])
22
22
  s.add_runtime_dependency('rack-contrib', [">= 1.0"])
23
23
 
24
- s.add_development_dependency('rake', ["~> 0.8.7"])
25
- s.add_development_dependency('ruby-debug', ["~> 0.10.3"])
26
- s.add_development_dependency('rspec', [">= 1.3.0"])
27
- s.add_development_dependency('flexmock', [">= 0.8.6"])
28
- s.add_development_dependency('actionpack', [">= 2.1.2"])
24
+ s.add_development_dependency('rake', [">= 0.8.7"])
25
+ s.add_development_dependency('ruby-debug', [">= 0.10.3"])
26
+ s.add_development_dependency('rspec', ["~> 1.3"])
27
+ s.add_development_dependency('flexmock', ["~> 0.8"])
28
+ s.add_development_dependency('actionpack', ["~> 2.3"])
29
29
 
30
30
  basedir = File.dirname(__FILE__)
31
31
  candidates = ['global_session.gemspec', 'init.rb', 'MIT-LICENSE', 'README.rdoc'] +
@@ -1,3 +1,5 @@
1
+ require 'set'
2
+
1
3
  module GlobalSession
2
4
  # The global session directory, which provides some lookup and decision services
3
5
  # to instances of Session.
@@ -29,7 +31,7 @@ module GlobalSession
29
31
  # at initialization time.
30
32
  #
31
33
  class Directory
32
- attr_reader :configuration, :authorities, :private_key, :local_authority_name
34
+ attr_reader :configuration, :authorities, :private_key
33
35
 
34
36
  # Create a new Directory.
35
37
  #
@@ -52,15 +54,20 @@ module GlobalSession
52
54
  raise ConfigurationError, "Expected #{basename} to contain an RSA public key" unless @authorities[authority].public?
53
55
  end
54
56
 
55
- if (authority_name = @configuration['authority'])
56
- key_file = keys.detect { |kf| kf =~ /#{authority_name}.key$/ }
57
- raise ConfigurationError, "Key file #{authority_name}.key not found" unless key_file
57
+ if local_authority_name
58
+ key_file = keys.detect { |kf| kf =~ /#{local_authority_name}.key$/ }
59
+ raise ConfigurationError, "Key file #{local_authority_name}.key not found" unless key_file
58
60
  @private_key = OpenSSL::PKey::RSA.new(File.read(key_file))
59
61
  raise ConfigurationError, "Expected #{key_file} to contain an RSA private key" unless @private_key.private?
60
- @local_authority_name = authority_name
61
62
  end
63
+
64
+ @invalid_sessions = Set.new
62
65
  end
63
66
 
67
+ def local_authority_name
68
+ @configuration['authority']
69
+ end
70
+
64
71
  # Determine whether this system trusts a particular authority based on
65
72
  # the trust settings specified in Configuration.
66
73
  #
@@ -85,11 +92,13 @@ module GlobalSession
85
92
  # === Return
86
93
  # valid(true|false):: whether the specified session is valid
87
94
  def valid_session?(uuid, expired_at)
88
- expired_at > Time.now
95
+ (expired_at > Time.now) && !@invalid_sessions.include?(uuid)
89
96
  end
90
97
 
91
98
  # Callback used by Session objects to report when the application code calls
92
- # #invalidate! on them. The default implementation of this method does nothing.
99
+ # #invalidate! on them. The default implementation of this method records
100
+ # invalid session IDs using an in-memory data structure, which is not ideal
101
+ # for most implementations.
93
102
  #
94
103
  # uuid(String):: Global session UUID
95
104
  # expired_at(Time):: When the session expired
@@ -97,7 +106,7 @@ module GlobalSession
97
106
  # === Return
98
107
  # true:: Always returns true
99
108
  def report_invalid_session(uuid, expired_at)
100
- true
109
+ @invalid_sessions << uuid
101
110
  end
102
111
  end
103
112
  end
@@ -1,4 +1,4 @@
1
- basedir = File.dirname(__FILE__)
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "global_session"))
2
2
 
3
3
  # Make sure the namespace exists, to satisfy Rails auto-loading
4
4
  module GlobalSession
@@ -37,8 +37,20 @@ module GlobalSession
37
37
  @configuration = configuration
38
38
  end
39
39
 
40
+ begin
41
+ klass_name = @configuration['directory'] || 'GlobalSession::Directory'
42
+
43
+ #Constantize the type name that was given as a string
44
+ parts = klass_name.split('::')
45
+ namespace = Object
46
+ namespace = namespace.const_get(parts.shift.to_sym) until parts.empty?
47
+ directory_klass = namespace
48
+ rescue Exception => e
49
+ raise ConfigurationError, "Invalid/unknown directory class name #{@configuration['directory']}"
50
+ end
51
+
40
52
  if directory.instance_of?(String)
41
- @directory = Directory.new(@configuration, directory)
53
+ @directory = directory_klass.new(@configuration, directory)
42
54
  else
43
55
  @directory = directory
44
56
  end
@@ -47,6 +59,34 @@ module GlobalSession
47
59
  @cookie_name = @configuration['cookie']['name']
48
60
  end
49
61
 
62
+ # Rack request chain. Sets up the global session ticket from
63
+ # the environment and passes it up the chain.
64
+ def call(env)
65
+ env['rack.cookies'] = {} unless env['rack.cookies']
66
+
67
+ begin
68
+ read_cookie(env)
69
+ rescue Exception => e
70
+ env['global_session'] = Session.new(@directory)
71
+ handle_error('reading session cookie', env, e)
72
+ end
73
+
74
+ tuple = nil
75
+
76
+ begin
77
+ tuple = @app.call(env)
78
+ rescue Exception => e
79
+ handle_error('processing request', env, e)
80
+ return tuple
81
+ else
82
+ renew_cookie(env)
83
+ update_cookie(env)
84
+ return tuple
85
+ end
86
+ end
87
+
88
+ protected
89
+
50
90
  # Read a cookie from the Rack environment.
51
91
  #
52
92
  # === Parameters
@@ -71,7 +111,7 @@ module GlobalSession
71
111
  def renew_cookie(env)
72
112
  return unless env['global_session'].directory.local_authority_name
73
113
  return if env['global_session.req.renew'] == false
74
-
114
+
75
115
  if (renew = @configuration['renew']) && env['global_session'] &&
76
116
  env['global_session'].expired_at < Time.at(Time.now.utc + 60 * renew.to_i)
77
117
  env['global_session'].renew!
@@ -110,6 +150,9 @@ module GlobalSession
110
150
  # === Parameters
111
151
  # env(Hash): Rack environment
112
152
  def wipe_cookie(env)
153
+ return unless env['global_session'].directory.local_authority_name
154
+ return if env['global_session.req.update'] == false
155
+
113
156
  domain = @configuration['cookie']['domain'] || env['SERVER_NAME']
114
157
  env['rack.cookies'][@cookie_name] = {:value => nil, :domain => domain, :expires => Time.at(0)}
115
158
  end
@@ -123,42 +166,17 @@ module GlobalSession
123
166
  # env(Hash): Rack environment
124
167
  # e(Exception): error that happened
125
168
  def handle_error(activity, env, e)
126
- if e.is_a? ClientError
169
+ env['rack.logger'].error("#{e.class} while #{activity}: #{e} #{e.backtrace}") if env['rack.logger']
170
+
171
+ if e.is_a?(ClientError) || e.is_a?(SecurityError)
127
172
  env['global_session.error'] = e
128
173
  wipe_cookie(env)
129
174
  elsif e.is_a? ConfigurationError
130
- env['rack.logger'].error("#{e.class} while #{activity}: #{e} #{e.backtrace}") if env['rack.logger']
131
175
  env['global_session.error'] = e
132
176
  else
133
177
  raise e
134
178
  end
135
179
  end
136
-
137
- # Rack request chain. Sets up the global session ticket from
138
- # the environment and passes it up the chain.
139
- def call(env)
140
- env['rack.cookies'] = {} unless env['rack.cookies']
141
-
142
- begin
143
- read_cookie(env)
144
- rescue Exception => e
145
- env['global_session'] = Session.new(@directory)
146
- handle_error('reading session cookie', env, e)
147
- end
148
-
149
- tuple = nil
150
-
151
- begin
152
- tuple = @app.call(env)
153
- rescue Exception => e
154
- handle_error('processing request', env, e)
155
- return tuple
156
- else
157
- renew_cookie(env)
158
- update_cookie(env)
159
- return tuple
160
- end
161
- end
162
180
  end
163
181
  end
164
182
  end
@@ -19,6 +19,9 @@ module GlobalSession
19
19
  unless base.instance_methods.include?("session_without_global_session")
20
20
  base.alias_method_chain :session, :global_session
21
21
  end
22
+ unless base.instance_methods.include?("log_processing_without_global_session")
23
+ base.alias_method_chain :log_processing, :global_session
24
+ end
22
25
  end
23
26
 
24
27
  # Shortcut accessor for global session configuration object.
@@ -115,16 +118,13 @@ module GlobalSession
115
118
  #
116
119
  # === Return
117
120
  # name(Type):: Description
118
- def log_processing
119
- if logger && logger.info?
120
- log_processing_for_request_id
121
- log_processing_for_parameters
122
- end
123
- end
121
+ def log_processing_with_global_session
122
+ return unless logger && logger.info?
124
123
 
125
- def log_processing_for_request_id # :nodoc:
126
- if global_session && global_session.id
127
- session_id = global_session.id + " (#{session[:session_id]})"
124
+ gs = request.env['global_session']
125
+
126
+ if gs && gs.id
127
+ session_id = gs.id + " (#{session[:session_id] || request.session_options[:id]})"
128
128
  elsif session[:session_id]
129
129
  session_id = session[:session_id]
130
130
  elsif request.session_options[:id]
@@ -137,9 +137,7 @@ module GlobalSession
137
137
  request_id << "\n Session ID: #{session_id}" if session_id
138
138
 
139
139
  logger.info(request_id)
140
- end
141
140
 
142
- def log_processing_for_parameters # :nodoc:
143
141
  parameters = respond_to?(:filter_parameters) ? filter_parameters(params) : params.dup
144
142
  parameters = parameters.except!(:controller, :action, :format, :_method)
145
143
 
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: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 0
10
- version: 1.0.0
9
+ - 2
10
+ version: 1.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tony Spataro
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-01 00:00:00 -08:00
18
+ date: 2011-01-15 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -71,7 +71,7 @@ dependencies:
71
71
  requirement: &id004 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
- - - ~>
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  hash: 49
77
77
  segments:
@@ -87,7 +87,7 @@ dependencies:
87
87
  requirement: &id005 !ruby/object:Gem::Requirement
88
88
  none: false
89
89
  requirements:
90
- - - ~>
90
+ - - ">="
91
91
  - !ruby/object:Gem::Version
92
92
  hash: 49
93
93
  segments:
@@ -103,14 +103,13 @@ dependencies:
103
103
  requirement: &id006 !ruby/object:Gem::Requirement
104
104
  none: false
105
105
  requirements:
106
- - - ">="
106
+ - - ~>
107
107
  - !ruby/object:Gem::Version
108
- hash: 27
108
+ hash: 9
109
109
  segments:
110
110
  - 1
111
111
  - 3
112
- - 0
113
- version: 1.3.0
112
+ version: "1.3"
114
113
  type: :development
115
114
  version_requirements: *id006
116
115
  - !ruby/object:Gem::Dependency
@@ -119,14 +118,13 @@ dependencies:
119
118
  requirement: &id007 !ruby/object:Gem::Requirement
120
119
  none: false
121
120
  requirements:
122
- - - ">="
121
+ - - ~>
123
122
  - !ruby/object:Gem::Version
124
- hash: 51
123
+ hash: 27
125
124
  segments:
126
125
  - 0
127
126
  - 8
128
- - 6
129
- version: 0.8.6
127
+ version: "0.8"
130
128
  type: :development
131
129
  version_requirements: *id007
132
130
  - !ruby/object:Gem::Dependency
@@ -135,14 +133,13 @@ dependencies:
135
133
  requirement: &id008 !ruby/object:Gem::Requirement
136
134
  none: false
137
135
  requirements:
138
- - - ">="
136
+ - - ~>
139
137
  - !ruby/object:Gem::Version
140
- hash: 15
138
+ hash: 5
141
139
  segments:
142
140
  - 2
143
- - 1
144
- - 2
145
- version: 2.1.2
141
+ - 3
142
+ version: "2.3"
146
143
  type: :development
147
144
  version_requirements: *id008
148
145
  description: 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.