infopark_cloud_connector 7.0.2 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
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