global_session 1.0.10 → 1.0.13
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.
- data/global_session.gemspec +3 -3
- data/lib/global_session/configuration.rb +5 -0
- data/lib/global_session/directory.rb +39 -1
- data/lib/global_session/rack.rb +13 -8
- data/lib/global_session/rails/action_controller_class_methods.rb +25 -23
- data/lib/global_session/rails/action_controller_instance_methods.rb +2 -0
- data/lib/global_session/rails.rb +32 -6
- data/lib/global_session/session.rb +5 -0
- metadata +8 -8
data/global_session.gemspec
CHANGED
@@ -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.
|
11
|
-
s.date = '2012-
|
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', ["
|
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
|
data/lib/global_session/rack.rb
CHANGED
@@ -88,7 +88,7 @@ module GlobalSession
|
|
88
88
|
begin
|
89
89
|
read_cookie(env)
|
90
90
|
rescue Exception => e
|
91
|
-
env['global_session'] =
|
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'] =
|
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'] =
|
119
|
+
env['global_session'] = @directory.create_session(cookie)
|
121
120
|
else
|
122
|
-
env['global_session'] =
|
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']
|
153
|
-
|
154
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
54
|
+
self.global_session_options = options
|
57
55
|
end
|
58
56
|
|
59
57
|
def no_global_session
|
60
|
-
|
61
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
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.
|
data/lib/global_session/rails.rb
CHANGED
@@ -41,14 +41,40 @@ end
|
|
41
41
|
|
42
42
|
module GlobalSession
|
43
43
|
module Rails
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
51
|
-
|
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:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
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-
|
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:
|
27
|
+
hash: 15
|
28
28
|
segments:
|
29
|
-
- 2
|
30
29
|
- 1
|
31
|
-
|
30
|
+
- 0
|
31
|
+
version: "1.0"
|
32
32
|
requirement: *id001
|
33
33
|
name: uuidtools
|
34
34
|
prerelease: false
|