omf_web 0.9.9 → 1.0.0

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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +31 -0
  3. data/bin/omf_web_server.rb +157 -0
  4. data/doc/screenshot2.png +0 -0
  5. data/doc/widget_detail.png +0 -0
  6. data/example/demo/data_sources/downloads.rb +2 -1
  7. data/example/simple/README.md +12 -13
  8. data/example/simple/create_waveform.rb +29 -0
  9. data/example/simple/introduction.md +17 -0
  10. data/example/simple/sample.sq3 +0 -0
  11. data/example/simple/sample.sql +1008 -0
  12. data/example/simple/simple.yaml +62 -0
  13. data/example/simple/simple_dynamic.yaml +66 -0
  14. data/lib/irods4r/file.rb +15 -14
  15. data/lib/irods4r/icommands.rb +18 -18
  16. data/lib/irods4r.rb +9 -9
  17. data/lib/omf-web/config.ru +41 -16
  18. data/lib/omf-web/content/git_repository.rb +32 -31
  19. data/lib/omf-web/content/irods_repository.rb +34 -33
  20. data/lib/omf-web/content/repository.rb +48 -44
  21. data/lib/omf-web/data_source_proxy.rb +33 -22
  22. data/lib/omf-web/rack/session_authenticator.rb +48 -12
  23. data/lib/omf-web/rack/tab_mapper.rb +30 -36
  24. data/lib/omf-web/rack/websocket_handler.rb +26 -25
  25. data/lib/omf-web/session_store.rb +16 -13
  26. data/lib/omf-web/theme/abstract_page.rb +26 -22
  27. data/lib/omf-web/theme/bright/page.rb +84 -34
  28. data/lib/omf-web/theme/bright/stacked_renderer.rb +20 -19
  29. data/lib/omf-web/theme.rb +14 -9
  30. data/lib/omf-web/thin/runner.rb +38 -36
  31. data/lib/omf-web/thin/server.rb +255 -0
  32. data/lib/omf-web/version.rb +1 -1
  33. data/lib/omf-web/widget/data_widget.rb +6 -6
  34. data/lib/omf-web/widget/text/maruku/helpers.rb +33 -30
  35. data/lib/omf-web/widget/text/maruku/input/parse_block.rb +117 -117
  36. data/lib/omf-web/widget/text/maruku/output/to_html.rb +155 -154
  37. data/lib/omf-web/widget/text/maruku.rb +17 -16
  38. data/omf_web.gemspec +6 -2
  39. data/sample.sq3 +0 -0
  40. data/share/htdocs/graph/js/gauge.js +524 -0
  41. data/share/htdocs/vendor/VERSION_MAP.yaml +3 -3
  42. data/share/htdocs/vendor/backbone-1.0.0/backbone.js +1571 -0
  43. data/share/htdocs/vendor/d3-3.0/LICENSE.brewer.txt +38 -0
  44. data/share/htdocs/vendor/d3-3.0/colorbrewer.js +1 -0
  45. data/share/htdocs/vendor/d3-3.0/d3.js +8810 -0
  46. data/share/htdocs/vendor/d3-3.0/d3.min.js +5 -0
  47. data/share/htdocs/vendor/geo_json/Readme.txt +71 -0
  48. data/share/htdocs/vendor/geo_json/regions.json +41 -0
  49. data/share/htdocs/vendor/geo_json/switzerland.json +24 -0
  50. data/share/htdocs/vendor/geo_json/world.json +497 -0
  51. data/share/htdocs/vendor/nv_d3/js/nv.d3.js +8801 -4447
  52. data/share/htdocs/vendor/spin/jquery.spin.js +46 -0
  53. data/share/htdocs/vendor/spin/spin.js +349 -0
  54. data/share/htdocs/vendor/spin/spin.min.js +1 -0
  55. data/share/htdocs/vendor/underscore-1.4.4/underscore.js +1227 -0
  56. metadata +63 -48
  57. data/example/simple/data_sources/gimi31.sq3 +0 -0
  58. data/example/simple/data_sources/ping_source.rb +0 -56
  59. data/example/simple/simple_viz_server.rb +0 -39
  60. data/example/simple/widgets/charts_tab.yaml +0 -38
  61. data/share/.DS_Store +0 -0
  62. data/share/htdocs/.DS_Store +0 -0
  63. data/share/htdocs/vendor/backbone-0.5.3/backbone.js +0 -1158
  64. data/share/htdocs/vendor/underscore-1.2.1/underscore.js +0 -958
@@ -11,10 +11,10 @@ module OMF::Web
11
11
  # This class provides an interface to a directory based repository
12
12
  # It retrieves, archives and versions content.
13
13
  #
14
- class IRodsContentRepository < ContentRepository
15
-
14
+ class IRodsContentRepository < ContentRepository
15
+
16
16
  @@irods_repositories = {}
17
-
17
+
18
18
  # Return the repository which is referenced to by elements in 'opts'.
19
19
  #
20
20
  #
@@ -24,8 +24,8 @@ module OMF::Web
24
24
  end
25
25
  repo
26
26
  end
27
-
28
- # Register an existing directory to the system. It will be
27
+
28
+ # Register an existing directory to the system. It will be
29
29
  # consulted for all content url's starting with
30
30
  # 'irods:_top_dir_:'. If 'is_primary' is set to true, it will
31
31
  # become the default repo for all newly created content
@@ -42,17 +42,18 @@ module OMF::Web
42
42
  @@primary_repository = repo
43
43
  end
44
44
  end
45
-
45
+
46
46
  attr_reader :name, :top_dir
47
-
47
+
48
48
  def initialize(name, opts)
49
49
  super
50
50
  unless @top_dir
51
51
  raise "No top_dir defined (#{opts.keys.inspect})"
52
52
  end
53
53
  @url_prefix = "irods:#{name}:"
54
+ @ticket = opts[:ticket]
54
55
  end
55
-
56
+
56
57
  # Load content described by either a hash or a straightforward path
57
58
  # and return a 'ContentProxy' holding it.
58
59
  #
@@ -67,38 +68,38 @@ module OMF::Web
67
68
  descr = descr ? descr.dup : {}
68
69
  url = get_url_for_path(path)
69
70
  key = Digest::MD5.hexdigest(url)
70
- descr[:url] = url
71
+ descr[:url] = url
71
72
  descr[:url_key] = key
72
- descr[:path] = path
73
+ descr[:path] = path
73
74
  descr[:name] = url # Should be something human digestable
74
75
  if (descr[:strictly_new])
75
- return nil if IRODS4r.exists?(path)
76
+ return nil if IRODS4r.exists?(path, @ticket)
76
77
  end
77
78
  proxy = ContentProxy.create(descr, self)
78
79
  return proxy
79
80
  end
80
-
81
+
81
82
  def write(content_descr, content, message)
82
83
  path = _get_path(content_descr)
83
84
  #puts "WRITE PATHS>>> #{path}"
84
- f = IRODS4r::File.create(path, false)
85
+ f = IRODS4r::File.create(path, false, ticket: @ticket)
85
86
  f.write(content)
86
87
  end
87
-
88
+
88
89
  def read(content_descr)
89
90
  path = _get_path(content_descr)
90
91
  #puts "READ PATHS>>> #{path}"
91
- f = IRODS4r::File.create(path, false)
92
+ f = IRODS4r::File.create(path, false, ticket: @ticket)
92
93
  f.read()
93
- end
94
-
94
+ end
95
+
95
96
  #
96
97
  # Return an array of file names which are in the repository and
97
98
  # match 'search_pattern'
98
99
  #
99
100
  def find_files(search_pattern, opts = {})
100
101
  begin
101
- dir = IRODS4r.find(@top_dir)
102
+ dir = IRODS4r.find(@top_dir, {}, @ticket)
102
103
  rescue IRODS4r::IRODS4rException
103
104
  return []
104
105
  end
@@ -106,7 +107,7 @@ module OMF::Web
106
107
  _find_files(search_pattern, dir, res, opts[:mime_type])
107
108
  res
108
109
  end
109
-
110
+
110
111
  def _find_files(search_pattern, dir, res, mime_type)
111
112
  dir.list.each do |e|
112
113
  if e.directory?
@@ -115,7 +116,7 @@ module OMF::Web
115
116
  path = e.path
116
117
  if path.match(search_pattern)
117
118
  mt = mime_type_for_file(path)
118
- next if mime_type != nil && mime_type != mt
119
+ next if mime_type != nil && mime_type != mt
119
120
  res << {:url => get_url_for_path(path), :path => path, #:name => 'foo',
120
121
  :mime_type => mt}
121
122
  end
@@ -123,10 +124,10 @@ module OMF::Web
123
124
  end
124
125
  res
125
126
  end
126
-
127
-
127
+
128
+
128
129
  # Return a URL for a path in this repo
129
- #
130
+ #
130
131
  def get_url_for_path(path)
131
132
  puts "PATH>>>>> '#{path}:#{path.class}'-'#{@top_dir}:#{@top_dir.class}'"
132
133
  if m = path.match("#{@top_dir}(.*)")
@@ -134,12 +135,12 @@ module OMF::Web
134
135
  end
135
136
  url = @url_prefix + path
136
137
  end
137
-
138
+
138
139
  # HACK ALERT!!!
139
- #
140
+ #
140
141
  # This method may be called by an entity which wants to access the content
141
- # directly through the file system. In the absence of a FUSE mounted iRODS
142
- # repo, we 'iget' the resource to a temporary directory and return that
142
+ # directly through the file system. In the absence of a FUSE mounted iRODS
143
+ # repo, we 'iget' the resource to a temporary directory and return that
143
144
  # path. The calling entity needs to be aware that any changes to that file
144
145
  # will NOT show up in iRODS without an iput.
145
146
  #
@@ -147,19 +148,19 @@ module OMF::Web
147
148
  #
148
149
  def absolute_path(content_descr)
149
150
  path = _get_path(content_descr)
150
-
151
+
151
152
  require 'etc'
152
153
  tmp_dir = "#{Dir::tmpdir}/LabWiki-#{Etc.getlogin}"
153
154
  # unless Dir.exists? tmp_dir
154
155
  # Dir.mkdir tmp_dir, 0700
155
156
  # end
156
-
157
+
157
158
  target = File.join(tmp_dir, path)
158
- IRODS4r::ICommands.export(path, target)
159
+ IRODS4r::ICommands.export(path, target, true, @ticket)
159
160
  target
160
161
  end
161
162
 
162
-
163
+
163
164
  def _get_path(content_descr)
164
165
  #puts ">>>GET PATH #{content_descr.inspect}"
165
166
  if content_descr.is_a? String
@@ -186,6 +187,6 @@ module OMF::Web
186
187
  end
187
188
  return path
188
189
  end
189
-
190
+
190
191
  end # class
191
- end # module
192
+ end # module
@@ -12,48 +12,48 @@ module OMF::Web
12
12
  # It retrieves, archives and versions content.
13
13
  #
14
14
  class ContentRepository < OMF::Common::LObject
15
-
15
+
16
16
  MIME_TYPE = {
17
- :js => 'text/javascript',
17
+ :js => 'text/javascript',
18
18
  :md => 'text/markup',
19
- :rb => 'text/ruby',
20
- :r => 'text/r',
21
- :svg => 'text/svg',
22
- :txt => 'text'
19
+ :rb => 'text/ruby',
20
+ :r => 'text/r',
21
+ :svg => 'text/svg',
22
+ :txt => 'text'
23
23
  }
24
-
24
+
25
25
  REPO_PLUGINS = {
26
26
  git: lambda do |name, opts|
27
- require 'omf-web/content/git_repository'
27
+ require 'omf-web/content/git_repository'
28
28
  return GitContentRepository.new(name, opts)
29
29
  end,
30
30
  file: lambda do |name, opts|
31
- require 'omf-web/content/file_repository'
31
+ require 'omf-web/content/file_repository'
32
32
  return FileContentRepository.new(name, opts)
33
33
  end,
34
34
  irods: lambda do |name, opts|
35
- require 'omf-web/content/irods_repository'
35
+ require 'omf-web/content/irods_repository'
36
36
  return IRodsContentRepository.new(name, opts)
37
37
  end,
38
38
  static: lambda do |name, opts|
39
- require 'omf-web/content/static_repository'
39
+ require 'omf-web/content/static_repository'
40
40
  return StaticContentRepository.new(name, opts)
41
41
  end
42
42
  }
43
-
43
+
44
44
  # Repo to be used for all newly created content
45
45
  @@primary_repository = nil
46
46
  @@repositories = {}
47
-
47
+
48
48
  def self.register_repo(name, opts)
49
49
  raise "ArgumentMismatch: Expected Hash, but got #{opts}" unless opts.is_a? Hash
50
-
50
+
51
51
  name = name.to_sym
52
52
  if @@repositories[name]
53
53
  warn "Ignoring repeated registration of repo '#{name}'"
54
54
  return
55
55
  end
56
-
56
+
57
57
  unless type = opts[:type]
58
58
  raise "Missing type in repo opts (#{opts})"
59
59
  end
@@ -62,9 +62,10 @@ module OMF::Web
62
62
  end
63
63
  @@repositories[name] = r = repo_creator.call(name, opts)
64
64
  @@primary_repository = r if opts[:is_primary]
65
+ r
65
66
  end
66
-
67
-
67
+
68
+
68
69
  # Load content described by either a hash or a straightforward url
69
70
  # and return a 'ContentProxy' holding it.
70
71
  #
@@ -75,7 +76,7 @@ module OMF::Web
75
76
  if url_or_descr.is_a? ContentProxy
76
77
  return url_or_descr
77
78
  end
78
-
79
+
79
80
  if url_or_descr.is_a? String
80
81
  url = url_or_descr
81
82
  else
@@ -90,20 +91,20 @@ module OMF::Web
90
91
  unless url
91
92
  throw "Can't find url in '#{url_or_descr.inspect}"
92
93
  end
93
-
94
+
94
95
  repo = find_repo_for(url)
95
96
  repo.create_content_proxy_for(url_or_descr)
96
97
  end
97
-
98
-
98
+
99
+
99
100
  def self.absolute_path_for(url)
100
101
  find_repo_for(url).absolute_path(url)
101
102
  end
102
-
103
+
103
104
  def self.read_content(url, opts)
104
105
  find_repo_for(url).read(url)
105
106
  end
106
-
107
+
107
108
  def self.find_repo_for(url)
108
109
  parts = url.split(':')
109
110
  name = parts[1]
@@ -112,23 +113,26 @@ module OMF::Web
112
113
  end
113
114
  return repo
114
115
  end
115
-
116
-
117
- # Find files whose file name matches 'selector'.
118
- #
116
+
117
+
118
+ # Find files whose file name matches 'selector'.
119
+ #
119
120
  # Supported options:
120
121
  # * :max - Maximum numbers of matches to return
121
122
  # * :mime_type - Only return files with that specific mime type.
123
+ # * :repo_iterator [Iterator] - Iterator over repos to search
122
124
  #
123
125
  def self.find_files(selector, opts = {})
124
- # TODO: Search across ALL registered repos
125
- fs = @@primary_repository.find_files(selector, opts)
126
+ fsa = (opts[:repo_iterator] || [@@primary_repository]).map do |repo|
127
+ repo.find_files(selector, opts)
128
+ end
129
+ fs = fsa.flatten
126
130
  if (max = opts[:max])
127
131
  fs = fs[0, max]
128
132
  end
129
133
  fs
130
- end
131
-
134
+ end
135
+
132
136
  #
133
137
  # Create a URL for a file with 'path' in the user's primary repository.
134
138
  # If 'strictly_new' is true, returns nil if 'path' already exists.
@@ -137,17 +141,17 @@ module OMF::Web
137
141
  # TODO: Need to add code to select proper repository
138
142
  return GitContentRepository.create_url(path, strictly_new)
139
143
  end
140
-
141
-
144
+
145
+
142
146
  attr_reader :name, :top_dir
143
-
147
+
144
148
  def initialize(name, opts)
145
149
  @name = name
146
150
  if @top_dir = opts[:top_dir]
147
151
  @top_dir = File.expand_path(@top_dir)
148
152
  end
149
153
  end
150
-
154
+
151
155
  #
152
156
  # Return an array of file names which are in the repository and
153
157
  # match 'search_pattern'
@@ -155,8 +159,8 @@ module OMF::Web
155
159
  def find_files(search_pattern, opts = {})
156
160
  raise "Missing implementation"
157
161
  end
158
-
159
-
162
+
163
+
160
164
  def mime_type_for_file(content_descriptor)
161
165
  fname = content_descriptor
162
166
  if content_descriptor.is_a? Hash
@@ -165,7 +169,7 @@ module OMF::Web
165
169
  ext = fname.split('.')[-1]
166
170
  mt = MIME_TYPE[ext.to_sym] || 'text'
167
171
  end
168
-
172
+
169
173
  def read(content_descr)
170
174
  path = _get_path(content_descr)
171
175
  Dir.chdir(@top_dir) do
@@ -175,21 +179,21 @@ module OMF::Web
175
179
  content = File.open(path).read
176
180
  return content
177
181
  end
178
- end
179
-
182
+ end
183
+
180
184
  def absolute_path(content_descr)
181
185
  path = _get_path(content_descr)
182
186
  File.join(@top_dir, path)
183
187
  end
184
-
188
+
185
189
  def path(content_descr)
186
190
  path = _get_path(content_descr)
187
191
  end
188
-
192
+
189
193
  # Return a URL for a path in this repo
190
- #
194
+ #
191
195
  def get_url_for_path(path)
192
196
  raise "Missing implementation"
193
197
  end
194
198
  end # class
195
- end # module
199
+ end # module
@@ -4,20 +4,30 @@ require 'omf_common/lobject'
4
4
  require 'omf_oml/network'
5
5
 
6
6
  module OMF::Web
7
-
8
- # This object maintains synchronization between a JS DataSource object
7
+
8
+ # This object maintains synchronization between a JS DataSource object
9
9
  # in a web browser and the corresponding +OmlTable+ in this server.
10
10
  #
11
11
  #
12
12
  class DataSourceProxy < OMF::Common::LObject
13
-
13
+
14
14
  @@datasources = {}
15
-
15
+
16
16
  # Register a data source.
17
17
  #
18
18
  # params data_source - Data source to register
19
19
  # params opts:
20
20
  # name - Name to use instead of data source's native name
21
+
22
+ #
23
+ # A data_source needs to support eh following methods:
24
+ #
25
+ # * rows Returns an array of rows
26
+ # * on_content_changed(lambda{action, rows}) Call provided block with actions :added, :removed
27
+ # * create_sliced_table (optional)
28
+ # * release Not exactly sure when that is being used
29
+ # * schema Schema of row
30
+ # * offset
21
31
  #
22
32
  def self.register_datasource(data_source, opts = {})
23
33
  name = (opts[:name] || data_source.name).to_sym
@@ -32,9 +42,9 @@ module OMF::Web
32
42
  # else
33
43
  # @@datasources[name] = data_source
34
44
  # end
35
- @@datasources[name] = data_source
45
+ @@datasources[name] = data_source
36
46
  end
37
-
47
+
38
48
  def self.[](name)
39
49
  name = name.to_sym
40
50
  unless dsp = OMF::Web::SessionStore[name, :dsp]
@@ -46,7 +56,7 @@ module OMF::Web
46
56
  end
47
57
  dsp
48
58
  end
49
-
59
+
50
60
  # Return proxies for 'ds_name'. Note, there can be more then
51
61
  # one proxy be needed for a datasource, such as a network which
52
62
  # has one ds for the nodes and one for the links
@@ -69,8 +79,8 @@ module OMF::Web
69
79
  top = "#{ds_name}/"
70
80
  names = @@datasources.keys.find_all { |ds_name| ds_name.to_s.start_with? top }
71
81
  unless names.empty?
72
- return names.map do |ds_name|
73
- OMF::Web::SessionStore[ds_name, :dsp] ||= self.new(ds_name, @@datasources[ds_name])
82
+ return names.map do |ds_name|
83
+ OMF::Web::SessionStore[ds_name, :dsp] ||= self.new(ds_name, @@datasources[ds_name])
74
84
  end
75
85
  end
76
86
  # debug ">>>> #{dsa}"
@@ -93,25 +103,25 @@ module OMF::Web
93
103
  end
94
104
  return proxies
95
105
  end
96
-
106
+
97
107
  #debug ">>>>> DS: #{ds_descr.inspect} - #{ds}"
98
108
  proxy = OMF::Web::SessionStore[ds_name, :dsp] ||= self.new(ds_name, ds)
99
109
  return [proxy]
100
110
  end
101
-
111
+
102
112
  attr_reader :name
103
-
113
+
104
114
  def reset()
105
- # TODO: Figure out partial sending
115
+ # TODO: Figure out partial sending
106
116
  end
107
-
117
+
108
118
  def on_update(req)
109
119
  res = {:events => @data_source.rows}
110
120
  [res.to_json, "text/json"]
111
121
  end
112
-
122
+
113
123
  # Register callback to be informed of changes to the underlying data source.
114
- # Call block when new rows are becoming available. Block needs ot return
124
+ # Call block when new rows are becoming available. Block needs ot return
115
125
  # true if it wants to continue receiving updates.
116
126
  #
117
127
  # offset: Number of records already downloaded
@@ -128,7 +138,7 @@ module OMF::Web
128
138
  block.call action, rows
129
139
  end
130
140
  end
131
-
141
+
132
142
  # Create a new data source which only contains a slice of the underlying data source
133
143
  def create_slice(col_name, col_value)
134
144
  ds = @data_source.create_sliced_table(col_name, col_value)
@@ -136,7 +146,7 @@ module OMF::Web
136
146
  def dsp.release; @data_source.release end
137
147
  dsp
138
148
  end
139
-
149
+
140
150
  def to_javascript(opts = {})
141
151
  #puts "to_java>>>>> #{opts.inspect}"
142
152
  sid = Thread.current["sessionID"]
@@ -145,23 +155,24 @@ module OMF::Web
145
155
  opts[:schema] = @data_source.schema.describe
146
156
  opts[:update_url] = "/_update/#{@name}?sid=#{sid}"
147
157
  opts[:sid] = sid
158
+ #opts[:is_static] = (@data_source.respond_to? :static?) ? @data_source.static? : false
148
159
  unless opts[:slice] # don't send any data if this is a sliced one
149
160
  #opts[:rows] = @data_source.rows[0 .. 20]
150
161
  opts[:rows] = []
151
162
  opts[:offset] = @data_source.offset
152
163
  end
153
164
  #puts "to_java2>>>>> #{opts.inspect}"
154
-
165
+
155
166
  %{
156
167
  OML.data_sources.register(#{opts.to_json});
157
168
  }
158
-
169
+
159
170
  end
160
-
171
+
161
172
  def initialize(name, data_source)
162
173
  @name = name
163
174
  @data_source = data_source
164
175
  end
165
176
  end
166
-
177
+
167
178
  end
@@ -28,22 +28,61 @@ module OMF::Web::Rack
28
28
  # Return true if the session is authenticated
29
29
  #
30
30
  def self.authenticated?
31
- debug "AUTH: #{self[:authenticated] == true}"
32
- self[:authenticated] == true
31
+ auth = self[:authenticated] == true && self[:valid_until] > Time.now
32
+ #debug "AUTH: #{auth}"
33
+ auth
33
34
  end
34
35
 
35
36
  # Calling this method will authenticate the current session
36
37
  #
37
- def self.authenticate
38
+ def self.authenticate(expires = nil)
38
39
  self[:authenticated] = true
39
40
  self[:valid_until] = Time.now + @@expire_after
40
41
  end
41
42
 
43
+ # Information about the authenticated user
44
+ #
45
+ def self.user()
46
+ self[:user]
47
+ end
48
+
49
+ # Attempt to authenticate with the provided 'req'
50
+ def self.authenticate_with(req)
51
+ p = req.params
52
+ #puts ">>>>>>> AA(#{req.host_with_port}): #{p}"
53
+ case t = p['method']
54
+ when 'persona'
55
+ require 'net/http'
56
+ unless assertion = p['assertion']
57
+ raise AuthenticationFailedException.new("Missing assertion")
58
+ end
59
+
60
+ http = Net::HTTP.new('verifier.login.persona.org', 443)
61
+ http.use_ssl = true
62
+ data = "assertion=#{assertion}&audience=#{req.host_with_port}"
63
+ headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
64
+ reply = http.post('/verify', data, headers)
65
+ unless reply.code_type == Net::HTTPOK && reply.content_type == "application/json"
66
+ raise AuthenticationFailedException.new("Could not verify Persona - '#{reply.body}'")
67
+ end
68
+ debug "Persona reply: '#{reply.body}'"
69
+ r = JSON.load(reply.body)
70
+ unless ((email = r['email']) && (expires = r['expires']))
71
+ raise AuthenticationFailedException.new("Could not verify Persona - '#{r}'")
72
+ end
73
+ self[:user] = {name: email, email: email, method: 'persona'}
74
+ authenticate(Time.at(expires))
75
+ else
76
+ raise AuthenticationFailedException.new("Unsupported authentication type '#{t}'")
77
+ end
78
+ end
79
+
42
80
  # Logging out will un-authenticate this session
43
81
  #
44
82
  def self.logout
45
83
  debug "LOGOUT"
46
84
  self[:authenticated] = false
85
+ self[:user] = nil
47
86
  end
48
87
 
49
88
  # DO NOT CALL DIRECTLY
@@ -79,23 +118,20 @@ module OMF::Web::Rack
79
118
  end
80
119
 
81
120
  def check_authenticated
82
- authenticated = self.class[:authenticated] == true
83
- #puts "AUTHENTICATED: #{authenticated}"
121
+ authenticated = self.class.authenticated?
84
122
  raise AuthenticationFailedException.new unless authenticated
85
- #self.class[:valid_until] = Time.now + @@expire_after
86
-
87
123
  end
88
124
 
89
125
  def call(env)
90
- #puts env.keys.inspect
91
126
  req = ::Rack::Request.new(env)
92
127
  path_info = req.path_info
93
- unless sid = req.cookies['sid']
128
+ sid = req.cookies['sid']
129
+ unless sid
94
130
  sid = "s#{(rand * 10000000).to_i}_#{(rand * 10000000).to_i}"
95
131
  end
96
132
  Thread.current["sessionID"] = sid # needed for Session Store
133
+ debug "Request for '#{path_info}' - sid: #{sid} - #{self.class.authenticated?}"
97
134
  unless @opts[:no_session].find {|rx| rx.match(path_info) }
98
-
99
135
  # If 'login_page_url' is defined, check if this session is authenticated
100
136
  login_url = @opts[:login_page_url]
101
137
  if login_url && login_url != req.path_info
@@ -107,13 +143,13 @@ module OMF::Web::Rack
107
143
  end
108
144
  headers = {'Location' => login_url, "Content-Type" => ""}
109
145
  Rack::Utils.set_cookie_header!(headers, 'sid', sid)
110
- return [301, headers, ['Login first']]
146
+ return [307, headers, ['Login first']]
111
147
  end
112
148
  end
113
149
  end
114
150
 
115
151
  status, headers, body = @app.call(env)
116
- Rack::Utils.set_cookie_header!(headers, 'sid', sid) if sid
152
+ Rack::Utils.set_cookie_header!(headers, 'sid', sid) # if sid
117
153
  [status, headers, body]
118
154
  end
119
155
  end # class