infopark_cloud_connector 6.8.3.174.51542603 → 6.9.0.3.197272233

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 (29) hide show
  1. data/app/controllers/rails_connector/objs_controller.rb +44 -9
  2. data/app/helpers/rails_connector/cms_tag_helper.rb +45 -8
  3. data/app/helpers/rails_connector/editing_helper.rb +1 -6
  4. data/app/helpers/rails_connector/widget_helper.rb +13 -0
  5. data/app/views/rails_connector/_editing_javascript.html.erb +9 -0
  6. data/app/views/rails_connector/objs/create_widget.html.erb +1 -0
  7. data/config/routes.rb +6 -1
  8. data/lib/assets/fonts/infopark_icons-webfont.eot +0 -0
  9. data/lib/assets/fonts/infopark_icons-webfont.ttf +0 -0
  10. data/lib/assets/fonts/infopark_icons-webfont.woff +0 -0
  11. data/lib/assets/images/180x120.gif +0 -0
  12. data/lib/assets/images/irongrip.png +0 -0
  13. data/lib/assets/javascripts/infopark_editing.js +11267 -3387
  14. data/lib/assets/stylesheets/infopark_editing.css +1362 -12
  15. data/lib/generators/cms/migration/migration_generator.rb +7 -1
  16. data/lib/rails_connector/backend_not_available.rb +4 -0
  17. data/lib/rails_connector/basic_obj.rb +27 -1
  18. data/lib/rails_connector/cloud_engine.rb +13 -1
  19. data/lib/rails_connector/cms_api_search_request.rb +0 -3
  20. data/lib/rails_connector/cms_backend.rb +25 -7
  21. data/lib/rails_connector/cms_cache_storage.rb +4 -4
  22. data/lib/rails_connector/content_service.rb +36 -12
  23. data/lib/rails_connector/content_state_caching.rb +0 -18
  24. data/lib/rails_connector/default_search_request.rb +0 -1
  25. data/lib/rails_connector/migrations/migrator.rb +4 -1
  26. data/lib/rails_connector/widget_renderer.rb +41 -0
  27. data/lib/rails_connector/workspace.rb +4 -0
  28. data/lib/rails_connector/workspace_data_from_service.rb +35 -0
  29. metadata +9 -3
@@ -4,12 +4,18 @@ module Cms
4
4
 
5
5
  source_root File.expand_path('../templates', __FILE__)
6
6
 
7
+ class_option :path,
8
+ type: :string,
9
+ default: 'cms/migrate',
10
+ desc: 'Relative path to Rails.root where to place the migration file. Defaults to "cms/migrate".',
11
+ banner: 'PATH'
12
+
7
13
  def self.next_migration_number(dirname)
8
14
  Time.now.utc.strftime('%Y%m%d%H%M%S')
9
15
  end
10
16
 
11
17
  def create_migration_file
12
- migration_template('migration.rb', "cms/migrate/#{file_name}")
18
+ migration_template('migration.rb', "#{options[:path]}/#{file_name}")
13
19
  end
14
20
  end
15
21
  end
@@ -3,6 +3,10 @@ module RailsConnector
3
3
  class BackendNotAvailable < StandardError
4
4
  attr_reader :http_code
5
5
 
6
+ def self.from_socket_error(socket_error)
7
+ new(socket_error.message, 503)
8
+ end
9
+
6
10
  def initialize(message, http_code)
7
11
  @http_code = http_code
8
12
  super(message)
@@ -666,6 +666,29 @@ module RailsConnector
666
666
  data_from_cms.has_custom_attribute?(name.to_s)
667
667
  end
668
668
 
669
+ def widgets(attribute_name)
670
+ unless (type_of_attribute(attribute_name) == 'widget')
671
+ raise "Not a widget field: #{attribute_name}."
672
+ end
673
+
674
+ widgets = read_attribute(attribute_name.to_s, false)
675
+
676
+ return [] unless widgets.present?
677
+
678
+ output_objs = []
679
+ (widgets['layout'] || []).each do |widget_hash|
680
+ begin
681
+ widget_obj = self.class.find(widget_hash['widget'])
682
+ rescue RailsConnector::ResourceNotFound => e
683
+ end
684
+ if widget_obj.present? && widget_obj.path.start_with?("/_widgets/#{id}/")
685
+ output_objs << widget_obj
686
+ end
687
+ end
688
+
689
+ output_objs
690
+ end
691
+
669
692
  private
670
693
 
671
694
  attr_accessor :data_from_cms
@@ -675,7 +698,10 @@ module RailsConnector
675
698
  @attribute_cache = {}
676
699
  end
677
700
 
678
- def read_attribute(attribute_name)
701
+ def read_attribute(attribute_name, skip_widgets = true)
702
+ if skip_widgets && (type_of_attribute(attribute_name) == 'widget')
703
+ raise "Field #{attribute_name} not (yet) available, since it's a widget"
704
+ end
679
705
  @attribute_cache.fetch(attribute_name) do
680
706
  (raw_value, attribute_type) = data_from_cms.value_and_type_of(attribute_name)
681
707
  @attribute_cache[attribute_name] =
@@ -4,6 +4,18 @@ module ::RailsConnector
4
4
  # Specify which file should be precompiled for packaging
5
5
  app.config.assets.precompile += %w( infopark_editing.js infopark_editing.css )
6
6
  end
7
+
8
+ initializer "rails issue 4911 workaround" do
9
+ if Rails.version < '4'
10
+ max_size = [ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE, 228].min
11
+ silence_warnings { ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE = max_size }
12
+ end
13
+ end
14
+
15
+ initializer "widgets.attach_router" do |app|
16
+ ::RailsConnector::WidgetRenderer.class_eval do
17
+ include app.routes.url_helpers
18
+ end
19
+ end
7
20
  end
8
21
  end
9
-
@@ -3,7 +3,6 @@ module RailsConnector
3
3
  # This class provides a basic implementation for accessing the search using the cms api.
4
4
  # It can be activated by making it the superclass of SearchRequest.
5
5
  # It should be customized by subclassing.
6
- # @api public
7
6
  class CmsApiSearchRequest
8
7
 
9
8
  # Takes +query_string+ and +options+ for accessing Cms Api Search.
@@ -12,14 +11,12 @@ module RailsConnector
12
11
  #
13
12
  # <tt>:limit</tt>:: The maximum number of hits
14
13
  # <tt>:offset</tt>:: The search offset
15
- # @api public
16
14
  def initialize(query_string, options = {})
17
15
  @query_string = query_string
18
16
  @options = options
19
17
  end
20
18
 
21
19
  # Accesses Cms Api Search using #query and fetches search hits.
22
- # @api public
23
20
  def fetch_hits
24
21
  search_enum = search_results
25
22
 
@@ -82,17 +82,26 @@ module RailsConnector
82
82
  end
83
83
 
84
84
  def find_workspace_data_by_id(id)
85
- from_content_state_id = ContentStateCaching.find_content_state_id(id)
85
+ workspace_data_from_cache = WorkspaceDataFromService.find_from_cache(id)
86
+ from_content_state_id = workspace_data_from_cache.try(:content_state_id)
87
+
86
88
  request_params = {:workspace_id => id}
87
89
  request_params[:content_state_id] = from_content_state_id if from_content_state_id
88
- raw_data = ContentService.query('workspaces/query', request_params)
90
+
91
+ raw_data = if id == 'published' && workspace_data_from_cache
92
+ begin
93
+ ContentService.query('workspaces/query', request_params, timeout: 1)
94
+ rescue BackendNotAvailable => e
95
+ warn_backend_not_available(id, from_content_state_id, e.message)
96
+ return workspace_data_from_cache
97
+ end
98
+ else
99
+ ContentService.query('workspaces/query', request_params)
100
+ end
101
+
89
102
  if raw_workspace_data = raw_data['workspace']
90
103
  workspace_data = WorkspaceDataFromService.new(raw_workspace_data)
91
- if from_content_state_id != workspace_data.content_state_id
92
- ContentStateCaching.store_content_state(workspace_data)
93
- ContentStateCaching.store_content_state_id(workspace_data.id,
94
- workspace_data.content_state_id)
95
- end
104
+ workspace_data.store_in_cache if from_content_state_id != workspace_data.content_state_id
96
105
  workspace_data
97
106
  end
98
107
  end
@@ -198,6 +207,15 @@ module RailsConnector
198
207
  raise ArgumentError, "invalid index name '#{index}'" unless VALID_INDEX_NAMES.include?(index)
199
208
  end
200
209
 
210
+ def warn_backend_not_available(workspace_id, content_state_id, error_message)
211
+ message = <<-EOS
212
+ Couldn't connect to content service for workspace with id=#{workspace_id} and content_state_id=#{content_state_id}.
213
+ #{error_message}
214
+ Serving from cache.
215
+ EOS
216
+ Rails.logger.warn(message)
217
+ end
218
+
201
219
  end
202
220
 
203
221
  end
@@ -15,12 +15,12 @@ module CmsCacheStorage
15
15
  end
16
16
  end
17
17
 
18
- def read_workspace_content_state_id(workspace_id)
19
- cache.read("workspace/#{workspace_id}/content_state")
18
+ def read_workspace_data(workspace_id)
19
+ cache.read("workspace/#{workspace_id}")
20
20
  end
21
21
 
22
- def write_workspace_content_state_id(workspace_id, content_state_id)
23
- cache.write("workspace/#{workspace_id}/content_state", content_state_id)
22
+ def write_workspace_data(workspace_id, workspace_data)
23
+ cache.write("workspace/#{workspace_id}", workspace_data)
24
24
  end
25
25
 
26
26
  def read_content_state(content_state_id)
@@ -1,8 +1,20 @@
1
1
  module RailsConnector
2
2
  class ContentService
3
3
  DEFAULT_PROTOCOL = 'https'.freeze
4
- SOCKET_ERRORS = [EOFError, IOError, Errno::ECONNABORTED, Errno::ECONNRESET,
5
- Errno::EPIPE, Errno::EINVAL].freeze
4
+ DEFAULT_TIMEOUT = 10.freeze
5
+
6
+ SOCKET_ERRORS = [
7
+ EOFError,
8
+ Errno::ECONNABORTED,
9
+ Errno::ECONNREFUSED,
10
+ Errno::ECONNRESET,
11
+ Errno::EINVAL,
12
+ Errno::EPIPE,
13
+ Errno::ETIMEDOUT,
14
+ IOError,
15
+ SocketError,
16
+ Timeout::Error,
17
+ ].freeze
6
18
 
7
19
  class RateLimitExceeded < StandardError
8
20
  def initialize(retry_after)
@@ -33,15 +45,16 @@ class ContentService
33
45
  class << self
34
46
  @next_request_not_before = nil
35
47
 
36
- def query(path, payload)
48
+ def query(path, payload, options={})
49
+ timeout = options.fetch(:timeout, DEFAULT_TIMEOUT)
37
50
  retry_once_on_socket_error do
38
51
  retry_until_timeout_on_rate_limit_exceeded do
39
- ConnectionManager.ensure_started(uri)
52
+ ConnectionManager.ensure_started(uri, timeout)
40
53
  request = build_request(path, payload)
41
54
  if @next_request_not_before && @next_request_not_before > (now = Time.now)
42
55
  sleep @next_request_not_before - now
43
56
  end
44
- handle_response(ConnectionManager.connection.request(request))
57
+ handle_response(ConnectionManager.connection(timeout).request(request))
45
58
  end
46
59
  end
47
60
  end
@@ -57,8 +70,8 @@ class ContentService
57
70
  retried = false
58
71
  begin
59
72
  yield
60
- rescue *SOCKET_ERRORS
61
- raise if retried
73
+ rescue *SOCKET_ERRORS => e
74
+ raise BackendNotAvailable.from_socket_error(e) if retried
62
75
  ConnectionManager.ensure_finished
63
76
  retried = true
64
77
  retry
@@ -129,7 +142,8 @@ class ContentService
129
142
  end
130
143
 
131
144
  module ConnectionManager
132
- def self.connection
145
+ def self.connection(timeout=DEFAULT_TIMEOUT)
146
+ configure_timeout(@connection, timeout) if @connection
133
147
  @connection
134
148
  end
135
149
 
@@ -137,7 +151,7 @@ class ContentService
137
151
  @connection = conn
138
152
  end
139
153
 
140
- def self.ensure_started(uri)
154
+ def self.ensure_started(uri, timeout=DEFAULT_TIMEOUT)
141
155
  return if @connection && @connection.started?
142
156
  conn = Net::HTTP.new(uri.host, uri.port)
143
157
  if uri.scheme == 'https'
@@ -145,7 +159,10 @@ class ContentService
145
159
  conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
146
160
  conn.ca_file = RailsConnector::Configuration.ca_file
147
161
  end
148
- retry_twice_on_socket_error { conn.start }
162
+ configure_timeout(conn, timeout)
163
+ retry_twice_on_socket_error do
164
+ conn.start
165
+ end
149
166
  @connection = conn
150
167
  end
151
168
 
@@ -161,12 +178,19 @@ class ContentService
161
178
  attempt = 0
162
179
  begin
163
180
  yield
164
- rescue *ContentService::SOCKET_ERRORS
165
- raise if attempt == 2
181
+ rescue *ContentService::SOCKET_ERRORS => e
182
+ raise BackendNotAvailable.from_socket_error(e) if attempt == 2
166
183
  attempt += 1
167
184
  retry
168
185
  end
169
186
  end
187
+
188
+ def configure_timeout(connection, timeout)
189
+ connection.open_timeout = timeout
190
+ connection.read_timeout = timeout
191
+ connection.ssl_timeout = timeout
192
+ end
193
+
170
194
  end
171
195
  end
172
196
  end
@@ -14,24 +14,6 @@ module ContentStateCaching
14
14
  # to the current content state's cache. Default depth is 5.
15
15
  attr_accessor :cache_replication_depth
16
16
 
17
- # Creates a new content state for given workspace with given ancetor and returns it.
18
- def store_content_state(workspace_data)
19
- ContentState.create(content_state_id: workspace_data.to_content_state_id,
20
- changes: workspace_data.changes,
21
- from_content_state_id: workspace_data.from_content_state_id)
22
- end
23
-
24
- # Fetches last known content state id for a given workspace id.
25
- # Returns nil if there is no content state for that workspace.
26
- def find_content_state_id(workspace_id)
27
- CmsCacheStorage.read_workspace_content_state_id(workspace_id)
28
- end
29
-
30
- # Stores current content state id for workspace with given id.
31
- def store_content_state_id(workspace_id, content_state_id)
32
- CmsCacheStorage.write_workspace_content_state_id(workspace_id, content_state_id)
33
- end
34
-
35
17
  # Updates caches with data from given workspace.
36
18
  # Should be called every time a new OBJ data has been fetched.
37
19
  def store_obj_data(workspace_data, index, key, data)
@@ -1,7 +1,6 @@
1
1
  module RailsConnector
2
2
  # This class provides a default implementation for accessing the search server.
3
3
  # It is used by {DefaultSearchController}.
4
- # @api public
5
4
  class DefaultSearchRequest < CmsApiSearchRequest
6
5
  end
7
6
  end
@@ -92,7 +92,10 @@ module RailsConnector
92
92
  end
93
93
 
94
94
  def migrations_paths
95
- ["#{Rails.root}/cms/migrate"]
95
+ Dir.glob([
96
+ Rails.root + 'cms/migrate',
97
+ Rails.root + 'app/widgets/**/migrate/',
98
+ ])
96
99
  end
97
100
 
98
101
  def runnable
@@ -0,0 +1,41 @@
1
+ module RailsConnector
2
+
3
+ class WidgetRenderer < AbstractController::Base
4
+ include AbstractController::Rendering
5
+ include AbstractController::Helpers
6
+
7
+ helper :cms, "rails_connector/widget"
8
+
9
+ self.view_paths = [File.join('app', 'widgets')]
10
+
11
+ def initialize(request)
12
+ @_request = request
13
+ end
14
+
15
+ def show(widget, obj, widget_field_name, container)
16
+ @widget = widget
17
+ @obj = obj
18
+ @widget_field_name = widget_field_name
19
+ @container = container
20
+
21
+ render_to_string "#{widget.obj_class.underscore}/show"
22
+ end
23
+
24
+ def thumbnail(widget_dir)
25
+ begin
26
+ render_to_string "#{widget_dir}/thumbnail"
27
+ rescue ActionView::MissingTemplate => e
28
+ view_context.widget_thumbnail(
29
+ widget_dir.titleize,
30
+ 'thumbnail.html.erb does not existing. Please provide one.',
31
+ view_context.image_tag('180x120.gif')
32
+ )
33
+ end
34
+ end
35
+
36
+ def request
37
+ @_request
38
+ end
39
+ end
40
+
41
+ end # module RailsConnector
@@ -41,6 +41,10 @@ class Workspace
41
41
  @workspace_data.revision_id
42
42
  end
43
43
 
44
+ def title
45
+ @workspace_data.title
46
+ end
47
+
44
48
  def data
45
49
  @workspace_data
46
50
  end
@@ -1,6 +1,14 @@
1
1
  module RailsConnector
2
2
 
3
3
  class WorkspaceDataFromService
4
+ # Fetches a workspace data previously store in cache storage.
5
+ # Returns nil if not found.
6
+ def self.find_from_cache(id)
7
+ if data = CmsCacheStorage.read_workspace_data(id)
8
+ new(data)
9
+ end
10
+ end
11
+
4
12
  def initialize(data)
5
13
  @data = data
6
14
  end
@@ -13,6 +21,10 @@ class WorkspaceDataFromService
13
21
  @data["id"]
14
22
  end
15
23
 
24
+ def title
25
+ @data["title"]
26
+ end
27
+
16
28
  # remove this method after DynamoCmsBackend has been removed from the Cloud Connector
17
29
  def content_cache_id=(id)
18
30
  # ignore, since not using content caches
@@ -41,6 +53,29 @@ class WorkspaceDataFromService
41
53
  def to_content_state_id
42
54
  diff && diff['to_content_state_id']
43
55
  end
56
+
57
+ # Serializes and stores a workspace data in cache storage.
58
+ # Also creates an appropriate content state if needed.
59
+ def store_in_cache
60
+ create_content_state if content_state_id
61
+ CmsCacheStorage.write_workspace_data(id, to_hash)
62
+ end
63
+
64
+ private
65
+
66
+ def to_hash
67
+ {
68
+ 'id' => id,
69
+ 'revision_id' => revision_id,
70
+ 'title' => title,
71
+ 'content_state_id' => content_state_id,
72
+ }
73
+ end
74
+
75
+ def create_content_state
76
+ ContentState.create(content_state_id: to_content_state_id, changes: changes,
77
+ from_content_state_id: from_content_state_id)
78
+ end
44
79
  end
45
80
 
46
81
  end # module RailsConnector
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: infopark_cloud_connector
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.8.3.174.51542603
4
+ version: 6.9.0.3.197272233
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-05 00:00:00.000000000 Z
12
+ date: 2013-04-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client
@@ -73,10 +73,15 @@ files:
73
73
  - app/helpers/rails_connector/cms_tag_helper.rb
74
74
  - app/helpers/rails_connector/editing_helper.rb
75
75
  - app/helpers/rails_connector/marker_helper.rb
76
+ - app/helpers/rails_connector/widget_helper.rb
77
+ - app/views/rails_connector/_editing_javascript.html.erb
78
+ - app/views/rails_connector/objs/create_widget.html.erb
76
79
  - config/routes.rb
77
80
  - lib/assets/fonts/infopark_icons-webfont.eot
78
81
  - lib/assets/fonts/infopark_icons-webfont.ttf
79
82
  - lib/assets/fonts/infopark_icons-webfont.woff
83
+ - lib/assets/images/180x120.gif
84
+ - lib/assets/images/irongrip.png
80
85
  - lib/assets/javascripts/infopark_editing.js
81
86
  - lib/assets/stylesheets/infopark_editing.css
82
87
  - lib/generators/cms/migration/USAGE
@@ -122,6 +127,7 @@ files:
122
127
  - lib/rails_connector/obj_data_from_service.rb
123
128
  - lib/rails_connector/obj_search_enumerator.rb
124
129
  - lib/rails_connector/rack_middlewares.rb
130
+ - lib/rails_connector/widget_renderer.rb
125
131
  - lib/rails_connector/workspace.rb
126
132
  - lib/rails_connector/workspace_data_from_service.rb
127
133
  - lib/rails_connector/workspace_selection_middleware.rb
@@ -140,7 +146,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
146
  version: '0'
141
147
  segments:
142
148
  - 0
143
- hash: 676465587
149
+ hash: 779053553
144
150
  required_rubygems_version: !ruby/object:Gem::Requirement
145
151
  none: false
146
152
  requirements: