infopark_cloud_connector 7.0.2 → 7.1.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 (61) hide show
  1. checksums.yaml +8 -8
  2. data/app/controllers/rails_connector/objs_controller.rb +29 -37
  3. data/app/helpers/rails_connector/cms_asset_helper.rb +1 -1
  4. data/app/helpers/rails_connector/cms_tag_helper.rb +1 -1
  5. data/app/helpers/rails_connector/default_cms_routing_helper.rb +1 -3
  6. data/app/helpers/rails_connector/display_helper.rb +5 -1
  7. data/app/views/rails_connector/_editing_javascript.html.erb +3 -2
  8. data/config/ca-bundle.crt +2 -2
  9. data/config/routes.rb +3 -0
  10. data/lib/assets/fonts/infopark_icons-webfont.eot +0 -0
  11. data/lib/assets/fonts/infopark_icons-webfont.ttf +0 -0
  12. data/lib/assets/fonts/infopark_icons-webfont.woff +0 -0
  13. data/lib/assets/images/apple-touch-icon.jpg +0 -0
  14. data/lib/assets/images/favicon.ico +0 -0
  15. data/lib/assets/images/ip_logo.svg +50 -0
  16. data/lib/assets/javascripts/infopark_editing.js +903 -164
  17. data/lib/assets/stylesheets/infopark_editing.css +222 -271
  18. data/lib/infopark_cloud_connector.rb +0 -1
  19. data/lib/rails_connector/attribute_content.rb +25 -74
  20. data/lib/rails_connector/backend_error.rb +4 -0
  21. data/lib/rails_connector/basic_obj.rb +173 -20
  22. data/lib/rails_connector/basic_widget.rb +42 -1
  23. data/lib/rails_connector/blob.rb +1 -1
  24. data/lib/rails_connector/cache_middleware.rb +2 -2
  25. data/lib/rails_connector/cms_backend.rb +51 -33
  26. data/lib/rails_connector/cms_rest_api.rb +13 -8
  27. data/lib/rails_connector/cms_rest_api/attribute_serializer.rb +62 -0
  28. data/lib/rails_connector/cms_rest_api/blob_uploader.rb +18 -0
  29. data/lib/rails_connector/communication_error.rb +17 -0
  30. data/lib/rails_connector/configuration.rb +28 -0
  31. data/lib/rails_connector/connection_manager.rb +2 -2
  32. data/lib/rails_connector/content_conversion.rb +16 -62
  33. data/lib/rails_connector/content_service.rb +2 -2
  34. data/lib/rails_connector/engine.rb +2 -1
  35. data/lib/rails_connector/html_string.rb +0 -1
  36. data/lib/rails_connector/link.rb +41 -33
  37. data/lib/rails_connector/link_parser.rb +72 -0
  38. data/lib/rails_connector/migrations/migration_dsl.rb +13 -0
  39. data/lib/rails_connector/{backend_not_available.rb → network_error.rb} +1 -6
  40. data/lib/rails_connector/obj_data.rb +4 -0
  41. data/lib/rails_connector/obj_data_from_hash.rb +6 -0
  42. data/lib/rails_connector/obj_data_from_service.rb +37 -3
  43. data/lib/rails_connector/obj_params_parser.rb +50 -0
  44. data/lib/rails_connector/obj_search_builder.rb +62 -0
  45. data/lib/rails_connector/obj_search_enumerator.rb +60 -5
  46. data/lib/rails_connector/rate_limit_exceeded.rb +5 -0
  47. data/lib/rails_connector/revision.rb +9 -0
  48. data/lib/rails_connector/string_tagging.rb +1 -12
  49. data/lib/rails_connector/text_link.rb +52 -0
  50. data/lib/rails_connector/text_link_conversion.rb +50 -0
  51. data/lib/rails_connector/workspace.rb +125 -3
  52. data/lib/rails_connector/workspace_data_from_service.rb +30 -31
  53. data/lib/rails_connector/workspace_selection_middleware.rb +62 -20
  54. data/lib/tasks/cache.rake +2 -0
  55. data/lib/tasks/rails_connector/cache_garbage_collector_task.rb +98 -0
  56. metadata +24 -17
  57. data/lib/assets/images/ip_logo_app.png +0 -0
  58. data/lib/assets/images/ip_logo_app2x.png +0 -0
  59. data/lib/assets/images/irongrip.png +0 -0
  60. data/lib/rails_connector/link_resolvable.rb +0 -9
  61. data/lib/rails_connector/rack_middlewares.rb +0 -6
@@ -37,7 +37,7 @@ class Blob
37
37
  private
38
38
 
39
39
  def raw_data
40
- @raw_data ||= CmsBackend.find_blob_data_by_id(id)
40
+ @raw_data ||= CmsBackend.instance.find_blob_data_by_id(id)
41
41
  end
42
42
 
43
43
  def meta_data
@@ -6,10 +6,10 @@ class CacheMiddleware
6
6
  end
7
7
 
8
8
  def call(env)
9
- CmsBackend.begin_caching
9
+ CmsBackend.instance.begin_caching
10
10
  @app.call(env)
11
11
  ensure
12
- CmsBackend.end_caching
12
+ CmsBackend.instance.end_caching
13
13
  end
14
14
  end
15
15
 
@@ -55,9 +55,6 @@ module RailsConnector
55
55
  def instance
56
56
  @instance ||= new
57
57
  end
58
-
59
- delegate :begin_caching, :end_caching, :caching?, :query_counter, :find_workspace_data_by_id,
60
- :find_obj_data_by, :find_blob_data_by_id, to: :instance
61
58
  end
62
59
 
63
60
  def initialize
@@ -91,7 +88,7 @@ module RailsConnector
91
88
  raw_data = if id == 'published' && workspace_data_from_cache
92
89
  begin
93
90
  ContentService.query('workspaces/query', request_params, timeout: 1)
94
- rescue BackendNotAvailable => e
91
+ rescue CommunicationError => e
95
92
  warn_backend_not_available(id, from_content_state_id, e.message)
96
93
  return workspace_data_from_cache
97
94
  end
@@ -106,15 +103,12 @@ module RailsConnector
106
103
  end
107
104
  end
108
105
 
109
- def find_obj_data_by(workspace_data, index, keys)
110
- index = index.to_s
111
- assert_valid_index_name(index)
112
- raw_data = find_raw_data_from_cache_or_database_by(workspace_data, index, keys)
113
- raw_data.map do |raw_list|
114
- raw_list.map do |raw_obj_data|
115
- ObjDataFromService.new(raw_obj_data)
116
- end
117
- end
106
+ def find_obj_data_by(revision, index, keys)
107
+ find_obj_data_filtering_deleted_by(revision, index, keys, false)
108
+ end
109
+
110
+ def find_obj_data_including_deleted_by(revision, index, keys)
111
+ find_obj_data_filtering_deleted_by(revision, index, keys, true)
118
112
  end
119
113
 
120
114
  def find_blob_data_by_id(id)
@@ -132,20 +126,33 @@ module RailsConnector
132
126
 
133
127
  private
134
128
 
135
- def find_raw_data_from_cache_or_database_by(workspace_data, index, keys)
129
+ def find_obj_data_filtering_deleted_by(revision, index, keys, include_deleted)
130
+ index = index.to_s
131
+ assert_valid_index_name(index)
132
+ raw_data = find_raw_data_from_cache_or_database_by(revision, index, keys)
133
+
134
+ raw_data.map do |raw_result|
135
+ raw_result.each_with_object([]) do |raw_data, result|
136
+ next if raw_data['_modification'] == ['deleted'] && !include_deleted
137
+ result << ObjDataFromService.new(raw_data)
138
+ end
139
+ end
140
+ end
141
+
142
+ def find_raw_data_from_cache_or_database_by(revision, index, keys)
136
143
  keys_from_database = []
137
144
  # load results from cache
138
145
  results_from_cache = keys.map do |key|
139
- find_raw_data_from_cache_by(workspace_data, index, key).tap do |objs|
146
+ find_raw_data_from_cache_by(revision, index, key).tap do |objs|
140
147
  keys_from_database << key unless objs
141
148
  end
142
149
  end
143
150
 
144
151
  # load cache misses from database and store them in cache
145
152
  results_from_database =
146
- find_raw_data_from_database_by(workspace_data, index, keys_from_database)
153
+ find_raw_data_from_database_by(revision, index, keys_from_database)
147
154
  keys_from_database.each_with_index do |key, key_number|
148
- store_raw_data_list_in_cache(workspace_data, index, key, results_from_database[key_number])
155
+ store_raw_data_list_in_cache(revision, index, key, results_from_database[key_number])
149
156
  end
150
157
 
151
158
  # combine the results
@@ -154,11 +161,11 @@ module RailsConnector
154
161
  end
155
162
  end
156
163
 
157
- def find_raw_data_from_cache_by(workspace_data, index, key)
158
- ContentStateCaching.find_obj_data(workspace_data.content_state, index, key) if caching?
164
+ def find_raw_data_from_cache_by(revision, index, key)
165
+ ContentStateCaching.find_obj_data(revision.content_state, index, key) if caching?
159
166
  end
160
167
 
161
- def find_raw_data_from_database_by(workspace_data, index, keys)
168
+ def find_raw_data_from_database_by(revision, index, keys)
162
169
  return [] if keys.blank?
163
170
  instrumenter = ActiveSupport::Notifications.instrumenter
164
171
  instrumenter.instrument(
@@ -166,36 +173,47 @@ module RailsConnector
166
173
  ) do
167
174
  @query_counter += 1
168
175
  queries = ContentServiceObjQueries.new(keys.map {|key| {:type => index, :param => key} })
169
- until queries.finished?
170
- queries.handle_response(ContentService.query(
171
- "objs/query",
172
- :queries => queries.open_queries,
173
- :workspace_id => workspace_data.id,
174
- :revision_id => workspace_data.revision_id
175
- ))
176
- end
176
+ queries.handle_response(request_content_service(queries, revision)) until queries.finished?
177
177
  queries.results
178
178
  end
179
179
  end
180
180
 
181
+ def request_content_service(queries, revision)
182
+ ContentService.query('objs/query', content_service_request_params(queries, revision))
183
+ end
184
+
185
+ def content_service_request_params(queries, revision)
186
+ params = {
187
+ queries: queries.open_queries,
188
+ revision_id: revision.id,
189
+ include_deleted: true
190
+ }
191
+
192
+ # Not every revision has a workspace,
193
+ # e.g. when requesting with the base revision of the current workspace.
194
+ params[:workspace_id] = revision.workspace.id if revision.workspace
195
+
196
+ params
197
+ end
198
+
181
199
  UNIQUE_INDICES = [:id, :path, :permalink].freeze
182
200
 
183
- def store_raw_data_list_in_cache(workspace_data, index, key, raw_data_list)
201
+ def store_raw_data_list_in_cache(revision, index, key, raw_data_list)
184
202
  raw_data_list.each do |values|
185
203
  UNIQUE_INDICES.each do |unique_index|
186
204
  unique_index_values = values["_#{unique_index}"]
187
205
  if unique_index_values.present?
188
- store_item_in_cache(workspace_data, unique_index, unique_index_values.first, [values])
206
+ store_item_in_cache(revision, unique_index, unique_index_values.first, [values])
189
207
  end
190
208
  end
191
209
  end
192
210
  unless UNIQUE_INDICES.include?(index)
193
- store_item_in_cache(workspace_data, index, key, raw_data_list)
211
+ store_item_in_cache(revision, index, key, raw_data_list)
194
212
  end
195
213
  end
196
214
 
197
- def store_item_in_cache(workspace_data, index, key, item)
198
- ContentStateCaching.store_obj_data(workspace_data.content_state, index, key, item)
215
+ def store_item_in_cache(revision, index, key, item)
216
+ ContentStateCaching.store_obj_data(revision.content_state, index, key, item)
199
217
  end
200
218
 
201
219
  def find_blob_data_from_database_by(id)
@@ -90,8 +90,6 @@ module RailsConnector
90
90
  private
91
91
 
92
92
  def request_cms_api(action, resource_path, payload, options)
93
- reset_connection_manager if connection_manager.uri != uri
94
-
95
93
  decoded = response_for_request_cms_api(action, resource_path, payload)
96
94
  return decoded unless Hash === decoded
97
95
  return decoded unless decoded.keys == ["task"]
@@ -102,6 +100,8 @@ module RailsConnector
102
100
  end
103
101
 
104
102
  def response_for_request_cms_api(method, resource_path, payload = nil)
103
+ reset_connection_manager if connection_manager.uri != uri
104
+
105
105
  request = method_to_net_http_class(method).new(path(resource_path))
106
106
  set_headers(request)
107
107
  request.body = MultiJson.encode(payload) if payload.present?
@@ -111,19 +111,24 @@ module RailsConnector
111
111
 
112
112
  def handle_response(response)
113
113
  code = response.code.to_i
114
- if code.to_s.start_with?('2')
114
+ if response.code.start_with?('2')
115
115
  MultiJson.load(response.body)
116
116
  elsif response.code == '403'
117
117
  raise AccessDenied.new(response.body)
118
- elsif (400...500).include?(code)
118
+ else
119
119
  begin
120
120
  specific_output = MultiJson.decode(response.body)['error']
121
- raise ClientError.new(specific_output, code)
121
+
122
+ if response.code.start_with?('4')
123
+ raise ClientError.new(specific_output, code)
124
+ elsif response.code == '500' && specific_output
125
+ raise BackendError.new(specific_output, code)
126
+ else # 3xx and >500 are treated as NetworkErrors
127
+ raise NetworkError.new(response.body, code)
128
+ end
122
129
  rescue MultiJson::DecodeError
123
- raise BackendNotAvailable.new(response.body, code)
130
+ raise NetworkError.new(response.body, code)
124
131
  end
125
- else
126
- raise BackendNotAvailable.new(response.body, code)
127
132
  end
128
133
  end
129
134
 
@@ -0,0 +1,62 @@
1
+ module RailsConnector
2
+ class CmsRestApi
3
+ module AttributeSerializer
4
+ class << self
5
+ def convert(attributes)
6
+ Hash[
7
+ attributes.map do |attribute_name, value|
8
+ converted_value = if link_array?(value)
9
+ convert_links(value)
10
+ elsif value.is_a?(BasicObj)
11
+ value.id
12
+ elsif obj_array?(value)
13
+ value.map(&:id)
14
+ elsif value.is_a?(Time) || value.is_a?(Date)
15
+ convert_time(value)
16
+ elsif value.is_a?(Array)
17
+ value.map(&:to_s)
18
+ elsif value.is_a?(File)
19
+ RailsConnector::CmsRestApi::BlobUploader.upload_file(value)
20
+ else
21
+ value.to_s
22
+ end
23
+
24
+ [attribute_name.to_s, converted_value]
25
+ end
26
+ ]
27
+ end
28
+
29
+ private
30
+
31
+ def link_array?(value)
32
+ value.is_a?(Array) && value.all? do |element|
33
+ element.is_a?(Link)
34
+ end
35
+ end
36
+
37
+ def obj_array?(value)
38
+ value.is_a?(Array) && value.all? do |element|
39
+ element.is_a?(BasicObj)
40
+ end
41
+ end
42
+
43
+ def convert_links(links)
44
+ links.map do |link|
45
+ link.to_cms_api_linklist_params
46
+ end
47
+ end
48
+
49
+ def convert_time(point_in_time)
50
+ time_object = if point_in_time.instance_of?(Date)
51
+ point_in_time.to_time
52
+ else
53
+ point_in_time.to_time.utc
54
+ end
55
+
56
+ time_object.strftime("%Y%m%d%H%M%S")
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,18 @@
1
+ module RailsConnector
2
+ class CmsRestApi
3
+ module BlobUploader
4
+ class << self
5
+ def upload_file(file)
6
+ upload_permission = CmsRestApi.get('blobs/upload_permission')
7
+
8
+ fields = upload_permission['fields'].to_a + [[:file, file]]
9
+
10
+ # Net/HTTP does not support multipart forms
11
+ RestClient.post(upload_permission['url'], fields)
12
+
13
+ upload_permission['blob']
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module RailsConnector
2
+
3
+ class CommunicationError < StandardError
4
+ attr_reader :http_code, :message
5
+
6
+ def initialize(message, http_code)
7
+ @http_code = http_code.to_i
8
+ @message = message
9
+ end
10
+
11
+ def to_s
12
+ "HTTP-Response-Code: #{self.http_code}, Body: \"#{self.message}\""
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -170,6 +170,30 @@ module RailsConnector
170
170
  ' config.action_dispatch.x_sendfile_header = "X-Sendfile"'
171
171
  end
172
172
 
173
+ def obj_formats
174
+ @obj_formats ||= {
175
+ '_changes_list' => proc do |obj|
176
+ {
177
+ id: obj.id,
178
+ modification: obj.modification,
179
+ deleted: obj.modification == 'deleted',
180
+ obj_class: obj.obj_class,
181
+ binary: obj.binary?,
182
+ title: obj.description_for_editor,
183
+ last_changed: obj.last_changed.strftime('%d.%m.%Y - %H:%M')
184
+ }
185
+ end
186
+ }
187
+ end
188
+
189
+ def register_obj_format(name, &block)
190
+ if name.start_with? '_'
191
+ raise InvalidFormatNameError.new('Format names starting with underscore are not allowed.')
192
+ else
193
+ obj_formats[name] = block
194
+ end
195
+ end
196
+
173
197
  private
174
198
 
175
199
  def content_service
@@ -188,4 +212,8 @@ module RailsConnector
188
212
 
189
213
  class ConfigurationError < StandardError
190
214
  end
215
+
216
+ class InvalidFormatNameError < StandardError; end
217
+
191
218
  end
219
+
@@ -62,7 +62,7 @@ module RailsConnector
62
62
  begin
63
63
  yield
64
64
  rescue *SOCKET_ERRORS => e
65
- raise BackendNotAvailable.from_socket_error(e) if retried
65
+ raise NetworkError.from_socket_error(e) if retried
66
66
  ensure_finished
67
67
  retried = true
68
68
  retry
@@ -74,7 +74,7 @@ module RailsConnector
74
74
  begin
75
75
  yield
76
76
  rescue *SOCKET_ERRORS => e
77
- raise BackendNotAvailable.from_socket_error(e) if attempt == 2
77
+ raise NetworkError.from_socket_error(e) if attempt == 2
78
78
  attempt += 1
79
79
  retry
80
80
  end
@@ -1,5 +1,4 @@
1
1
  require 'nokogiri'
2
- require 'addressable/uri'
3
2
 
4
3
  module RailsConnector
5
4
 
@@ -8,13 +7,17 @@ module RailsConnector
8
7
  doc = Nokogiri::HTML.parse("<div class='internal_jump_point'>#{input}</div>")
9
8
 
10
9
  doc.css('body a').each do |a_tag|
11
- item = a_tag.attributes['href']
12
- item.value = convert_link(item.value, request_host, request_port)
10
+ if href = a_tag.attributes['href']
11
+ link = Link.parse(href.value, request_host, request_port)
12
+ href.value = link.to_cms_api_html_url
13
+ end
13
14
  end
14
15
 
15
16
  doc.css('body img').each do |img_tag|
16
- item = img_tag.attributes['src']
17
- item.value = convert_link(item.value, request_host, request_port)
17
+ if src = img_tag.attributes['src']
18
+ link = Link.parse(src.value, request_host, request_port)
19
+ src.value = link.to_cms_api_html_url
20
+ end
18
21
  end
19
22
 
20
23
  new_html = doc.css('body div.internal_jump_point').inner_html
@@ -23,65 +26,16 @@ module RailsConnector
23
26
  new_html.gsub(nbsp, "&nbsp;")
24
27
  end
25
28
 
26
- private
27
-
28
- def self.convert_link(target, request_host, request_port)
29
- if target.present?
30
- uri = Addressable::URI.parse(target)
31
-
32
- if uri.absolute?
33
- if internal_url?(uri, request_host, request_port)
34
- target = convert_single_link(uri)
35
- end
36
- else
37
- if uri.path.present?
38
- target = convert_single_link(uri)
39
- end
29
+ def self.convert_linklist_urls(linklist, request_host, request_port)
30
+ linklist.map do |link_data|
31
+ if link_data.has_key?(:url)
32
+ link_data.delete(:obj_id)
33
+ url = link_data.delete(:url)
34
+ link = Link.parse(url, request_host, request_port)
35
+ link_data.merge!(link.to_cms_api_linklist_params)
40
36
  end
41
- end
42
37
 
43
- target
44
- end
45
-
46
- def self.internal_url?(uri, request_host, request_port)
47
- if request_host == uri.host
48
- if uri.port.present?
49
- uri.port == Integer(request_port)
50
- else
51
- true
52
- end
53
- else
54
- false
55
- end
56
- end
57
-
58
- def self.convert_single_link(uri)
59
- uri.path = '/' unless uri.path.present?
60
- uri.port = nil
61
- uri.host = nil
62
- uri.scheme = nil
63
-
64
- if obj_id = determine_obj_id(uri.to_s)
65
- uri.scheme = 'objid'
66
- uri.path = obj_id
67
- else
68
- uri.scheme = 'external'
69
- end
70
-
71
- uri.to_s
72
- end
73
-
74
- def self.determine_obj_id(target)
75
- route = Rails.application.routes.recognize_path(target, :method => :get)
76
- if route[:controller] == 'rails_connector/cms_dispatch'
77
- begin
78
- if id = route[:id]
79
- Obj.find(id).id
80
- elsif permalink = route[:permalink]
81
- CmsEnv.find_permalink_by_param(permalink).id
82
- end
83
- rescue RailsConnector::ResourceNotFound
84
- end
38
+ link_data
85
39
  end
86
40
  end
87
41
  end