infopark_fiona7 0.71.0.7 → 0.71.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07728fd57fdb01877b58ba69bde489bc1e5e2508
4
- data.tar.gz: bb716b43bd3cf4f5a2939f794386126315e488cc
3
+ metadata.gz: 3aaff7962c5f0c2bdce5d3856198cdab579fd8ac
4
+ data.tar.gz: cd04d39d77dc5bf489ff07becaff1e2c1ab20eb1
5
5
  SHA512:
6
- metadata.gz: eb53ab8dd8c92567f7939801f61cc715fe299273346294d801a81dabdf54d5387ab4899fb3978fabec66f0d4b9c266163d1d04c2742d69fa7d7511c187348125
7
- data.tar.gz: 328d9ac70b382b59fdb1632859ae0a4f00f338f7aa25d33d5c0ace84346c5828298c20841cd8eaa57e6b34becc454a00f9a5b2ed94595ffbc10ae70c7f17e8f9
6
+ metadata.gz: abe935f615d9b6b4bdd548c3f3f9e194ece6f54531bc1c425e81b608cc1cca8bedcc6dc6f3e64cbfdab30dc9d49394f095a27f8c98dba1f38bbc99672a5a28d4
7
+ data.tar.gz: e8879992375f4b647a9a0b60ed6140a3d351f1c5bfc3591e796c77645756786ba8052ccbe877a70f7538095f317d0f79a33b3105b53b6ef3f05feaff0edfb3ea
@@ -149,7 +149,7 @@
149
149
  actions = ["release"];
150
150
 
151
151
  scrivito.gui.on('document', function(cms_document) {
152
- console.log('adding release button');
152
+ //console.log('adding release button');
153
153
  var obj = cms_document.page();
154
154
 
155
155
  _.each(actions, function(action,idx) {
@@ -202,7 +202,7 @@
202
202
 
203
203
  create: function(attrs) {
204
204
  return prepare_attrs(scrivito.random_id(), attrs).then(function(prepared_attrs) {
205
- provide_default_path(prepared_attrs, prepared_attrs._obj_class);
205
+ provide_default_path(prepared_attrs, provide_default_name(prepared_attrs));
206
206
  return persist_obj_data(prepared_attrs).then(function (data) {
207
207
  scrivito.obj_class_selection.store(prepared_attrs._obj_class);
208
208
  return scrivito.obj.create_instance(data);
@@ -220,6 +220,27 @@
220
220
  }
221
221
  });
222
222
 
223
+ var provide_default_name = function (attrs) {
224
+ var default_name = null;
225
+
226
+ $.each(attrs, function (key, value) {
227
+ if (value && value.is_uploaded_binary && value.filename) {
228
+ default_name = value.filename;
229
+ } else if (instance_of_anywhere(value, 'File')) {
230
+ default_name = value.name;
231
+ }
232
+ });
233
+
234
+ if (default_name === null) {
235
+ default_name = attrs._obj_class;
236
+ } else {
237
+ // this removes file extension if present
238
+ default_name = default_name.replace(/\.[^\.]+$/, '');
239
+ }
240
+
241
+ return default_name;
242
+ };
243
+
223
244
  var provide_default_path = function (attrs, default_name) {
224
245
  if (!(attrs._path)) {
225
246
  var current_page = scrivito.application_document().page();
@@ -318,14 +339,7 @@
318
339
  };
319
340
 
320
341
  var instance_of_anywhere = function (object, ctor_name) {
321
- var i, val=false, possible_ctor;
322
- for (i=0; i < window.frames.length; ++i) {
323
- possible_ctor = window.frames[i][ctor_name];
324
- if ((typeof possible_ctor === 'function') && (object instanceof possible_ctor)) {
325
- val = true;
326
- }
327
- }
328
- return val;
342
+ return (object && (typeof object === 'object') && object.constructor && object.constructor.name === ctor_name);
329
343
  };
330
344
 
331
345
  var format_date_number = function(number) {
@@ -2,28 +2,61 @@ module Fiona7
2
2
  class ReleaseController < ActionController::Base
3
3
  def release
4
4
  @releasable = Set.new
5
+ @errors = []
5
6
 
6
7
  @obj = WriteObj.find(params[:id])
7
8
 
8
-
9
- @releasable.merge(referenced_objects(@obj))
10
- @releasable.merge(widgets(@obj))
11
- @releasable << @obj
9
+ recursively_find_objects(@releasable, @obj, Set.new)
12
10
 
13
11
  @releasable.each do |obj|
14
12
  if obj.really_edited?
15
- obj.take
16
- obj.release!
13
+ carefully_release(@errors, obj)
17
14
  end
18
15
  end
19
16
 
17
+ # TODO: display errors
20
18
  render json: {}
21
19
  end
22
20
 
23
21
  protected
22
+
23
+ def carefully_release(errors, obj)
24
+ obj.take
25
+ obj.release!
26
+ rescue => e
27
+ Rails.logger.error("Error occured when releasing #{@obj.id}: unable to release Object with ID #{obj.id} (#{obj.path} because: #{e.inspect}")
28
+
29
+ # TODO: translate
30
+ error = "Unable to release Object with ID #{obj.id} because: #{e.message}"
31
+ errors << error
32
+ end
33
+
34
+ def recursively_find_objects(set, obj, already_encountered)
35
+ # already_encountered prevents loops
36
+ widgets_of_this_object = widgets(obj) - already_encountered
37
+ referenced_objects_of_this_object = referenced_objects(obj) - already_encountered
38
+
39
+ already_encountered.merge(widgets_of_this_object)
40
+ already_encountered.merge(referenced_objects_from_widgets)
41
+
42
+ widgets_of_this_object.each do |widget|
43
+ recursively_find_objects(set, widget, already_encountered)
44
+ end
45
+
46
+ referenced_objects_of_this_object.each do |referenced|
47
+ recursively_find_objects(set, referenced, already_encountered)
48
+ end
49
+
50
+ set.merge(widgets_of_this_object)
51
+ set.merge(referenced_objects_of_this_object)
52
+ set << obj
53
+
54
+ set
55
+ end
56
+
24
57
  def widgets(obj)
25
58
  links = @obj[:X_widget_pool] || []
26
- WriteObj.where(obj_id: links.map {|l| l.destination_object_id }).to_a
59
+ WriteObj.where(obj_id: links.map {|l| l.destination_object_id }).to_a.to_set
27
60
  end
28
61
 
29
62
  def referenced_objects(obj)
@@ -109,7 +109,11 @@ module Fiona7
109
109
  end
110
110
 
111
111
  def find_by_permalink(permalink)
112
- @klass.where(permalink: permalink).limit(1).to_a
112
+ if permalink
113
+ @klass.where(permalink: permalink).limit(1).to_a
114
+ else
115
+ []
116
+ end
113
117
  end
114
118
  end
115
119
  end
@@ -6,6 +6,7 @@ require 'fiona7/builder/obj_builder'
6
6
  require 'fiona7/builder/obj_updater'
7
7
 
8
8
  require 'fiona7/naive_search_engine'
9
+ require 'fiona7/verity_search_engine'
9
10
 
10
11
  require 'fiona7/assert'
11
12
 
@@ -97,8 +98,15 @@ module Fiona7
97
98
  query = (params[:query] || []).dup
98
99
  order = (params[:sort_order] || :asc).to_sym
99
100
  sort = (params[:sort_by] || :id).to_sym
100
-
101
- search = NaiveSearchEngine.new(klass, query, offset, size, sort, order)
101
+
102
+ #puts "SEARCH: #{query}"
103
+ if use_naive_search_engine?(query)
104
+ #puts "NAIVE"
105
+ search = NaiveSearchEngine.new(klass, query, offset, size, sort, order)
106
+ else
107
+ #puts "VERITY"
108
+ search = VeritySearchEngine.new(klass, query, offset, size, sort, order)
109
+ end
102
110
  result = search.results.map {|o| {id: o.id} }
103
111
  total = search.total
104
112
 
@@ -181,6 +189,17 @@ module Fiona7
181
189
  "Workspace #{workspace_id} is not writable, only workspace rtc is writable"
182
190
  )
183
191
  end
192
+
193
+ def use_naive_search_engine?(query)
194
+ false ||
195
+ query.empty? ||
196
+ query.any? {|q| q[:field].to_sym == :_path && (q[:operator].to_sym == :equal || query.length == 1)} ||
197
+ (query.length == 1 && query.first[:field].to_sym == :_modification) ||
198
+ (query.length == 1 && query.first[:field].to_sym == :_obj_class) ||
199
+ (query.length == 1 && query.first[:field].to_sym == :id) ||
200
+ (query.length == 1 && query.first[:field].to_sym == :_permalink) ||
201
+ false
202
+ end
184
203
  end
185
204
  end
186
205
  end
@@ -2,7 +2,9 @@ module Fiona7
2
2
  module CurrentUserMapHelper
3
3
  def self.groups_for_user(user)
4
4
  user_name = user.id rescue ""
5
- Reactor::Cache::User.instance.get(user_name).groups
5
+ Reactor::Sudo.su(Fiona7.root) do
6
+ Reactor::Cache::User.instance.get(user_name).groups
7
+ end
6
8
  rescue => e
7
9
  Rails.logger.error "Error occured reading user groups of #{user_name} (#{e.message})"
8
10
  []
@@ -0,0 +1,122 @@
1
+ require "rails_connector/ses"
2
+ require "builder"
3
+
4
+ module Fiona7
5
+ class CustomVerityAccessor < ::RailsConnector::SES::VerityAccessor
6
+ require 'net/http'
7
+ require 'uri'
8
+ require "rexml/document"
9
+
10
+ #--
11
+ # Options: see VeritySearchRequest
12
+ #++
13
+ def initialize(query, options = {})
14
+ @query = query
15
+ @options = {
16
+ :host => 'localhost',
17
+ :port => 3011,
18
+ :offset => 0,
19
+ :limit => 10,
20
+ :min_relevance => 50,
21
+ :max_docs => 'unlimited',
22
+ :parser => 'simple',
23
+ :sort_order => [["score", "desc"], ["name", "asc"]],
24
+ :collections => ['cm-contents'],
25
+ :base_query => nil
26
+ }.merge(options)
27
+ @options[:collections] = Array(options[:collection]).flatten if options.has_key?(:collection)
28
+ end
29
+
30
+ # Queries the SES and returns a SearchResult.
31
+ #
32
+ # Exceptions:
33
+ # * SearchError - SES reported an error.
34
+ #
35
+ def search
36
+ parse_response_payload(send_to_ses(build_request_payload))
37
+ end
38
+
39
+ private
40
+
41
+ def build_request_payload
42
+ x = ::Builder::XmlMarkup.new
43
+ x.instruct!
44
+ x.tag!('ses-payload', 'payload-id' => 'd-1f6a64dec16aa328-00000020-i', 'timestamp' => Time.now.to_iso, 'version' => '6') {
45
+ x.tag!('ses-header') {
46
+ x.tag!('ses-sender', 'sender-id' => '42', 'name' => 'infopark-rails-connector')
47
+ }
48
+ x.tag!('ses-request', 'request-id' => 'd-1f6a64dec16aa328-00000021-j-1', 'preclusive' => 'false') {
49
+ x.tag!('ses-search') {
50
+ x.query @query, :parser => @options[:parser]
51
+ x.resultRecord {
52
+ x.resultField 'objId'
53
+ x.resultField 'score'
54
+ }
55
+ x.offset {
56
+ x.start @options[:offset].to_i + 1
57
+ x.length @options[:limit]
58
+ }
59
+ x.minRelevance @options[:min_relevance]
60
+ x.maxDocs @options[:max_docs]
61
+
62
+ unless @options[:sort_order].blank?
63
+ x.sortOrder {
64
+ @options[:sort_order].each do |attribute, direction|
65
+ x.sortField attribute, :direction => direction
66
+ end
67
+ }
68
+ end
69
+
70
+ x.searchBase {
71
+ @options[:collections].each {|item| x.collection item }
72
+ x.query @options[:base_query], :parser => @options[:parser] if @options[:base_query]
73
+ }
74
+ }
75
+ }
76
+ }
77
+ end
78
+
79
+ def send_to_ses(payload)
80
+ res = Net::HTTP.new(@options[:host], @options[:port].to_i).start do |http|
81
+ req = Net::HTTP::Post.new('/xml')
82
+ req.body = payload
83
+ http.request(req)
84
+ end
85
+ res.body
86
+ end
87
+
88
+ def parse_response_payload(response)
89
+ xml = REXML::Document.new(response)
90
+ if xml.elements['/ses-payload/ses-response/ses-code'].attributes['numeric'] == "200"
91
+ build_successful_result(xml)
92
+ else
93
+ handle_error(xml)
94
+ end
95
+ end
96
+
97
+ def build_successful_result(response)
98
+ result = RailsConnector::SES::SearchResult.new(response.elements['/ses-payload/ses-response/ses-code/searchResults'].attributes['hits'].to_i)
99
+ response.elements.to_a('/ses-payload/ses-response/ses-code/searchResults/record').each do |record|
100
+ hit = RailsConnector::SES::Hit.new(record.elements['objId'].text.to_i, record.elements['score'].text.to_f)
101
+ result << hit
102
+ end
103
+ result
104
+ end
105
+
106
+ # SES raises these errors:
107
+ # 100171: ERROR_SYSTEM_SES_INTERNALVERITYERROR_DS
108
+ # 100230: ERROR_SYSTEM_SES_VERITYERROR_DS
109
+ # 100099: ERROR_SYSTEM_SES_DUPLICATECOLLETION_S
110
+ # 100173: ERROR_SYSTEM_SES_OPENCOLLECTIONFAILED
111
+ # 100103: ERROR_SYSTEM_SEARCHENGINE_SESSIONNEWFAILED
112
+ # 100177: ERROR_SYSTEM_SEARCHENGINE_BULKSUBMITFAILED
113
+ def handle_error(response)
114
+ msg = ""
115
+ response.elements.each('/ses-payload/ses-response/ses-code/errorStack/error') do |error|
116
+ msg << error.elements['phrase'].text
117
+ msg << "\n"
118
+ end
119
+ raise RailsConnector::SES::SearchError, msg
120
+ end
121
+ end
122
+ end
data/lib/fiona7/engine.rb CHANGED
@@ -89,6 +89,9 @@ module Fiona7
89
89
  secret: config.secret
90
90
  }
91
91
 
92
+ Fiona7::VeritySearchEngine::VeritySearchRequest.configured_host = config.host
93
+ Fiona7::VeritySearchEngine::VeritySearchRequest.configured_port = config.port.to_i + 3
94
+
92
95
  Fiona7.root = config.username
93
96
 
94
97
  Fiona7.mode = config.mode
@@ -0,0 +1,215 @@
1
+ require "fiona7/search_engine"
2
+ require "rails_connector/verity_search_request"
3
+ require "fiona7/custom_verity_accessor"
4
+
5
+ module Fiona7
6
+ class VeritySearchEngine < SearchEngine
7
+ def results
8
+ # scrivito sdk likes to send a query with limit 0
9
+ # just to fetch the total count of results
10
+ # but verity does not like limit 0 very much
11
+ if @limit == 0
12
+ @limit = 1
13
+ end
14
+
15
+ construct_search_request
16
+ fetch_results
17
+ fetch_objects
18
+ end
19
+
20
+ protected
21
+ def construct_search_request
22
+ # TODO: sort order!
23
+ options = {}
24
+ options[:sort_order] = [["score", "desc"], ["lastChanged", "desc"]]
25
+ options[:limit] = @limit.to_i if @limit
26
+ options[:offset] = @offset.to_i if @offset.to_i > 0
27
+ @search_request = VeritySearchRequest.new(@query, options, @klass == Fiona7::ReleasedObj)
28
+ end
29
+
30
+ def fetch_results
31
+ @results = @search_request.fetch_hits
32
+ @count = @results.total_hits
33
+ end
34
+
35
+ def fetch_objects
36
+ unordered_objects = @klass.where(obj_id: @results.map(&:id)).to_a
37
+ ordered_objects = @results.map {|r| unordered_objects.find {|o| o.id.to_i == r.id } }.compact
38
+ end
39
+
40
+ class VeritySearchRequest < ::RailsConnector::VeritySearchRequest
41
+ def initialize(query, options={}, use_released=false)
42
+ @query_string = build_query_string(query)
43
+ @options = default_search_options.merge(options)
44
+ @use_released ||= use_released
45
+ end
46
+
47
+ def fetch_hits
48
+ Fiona7::CustomVerityAccessor.new(@query_string, {:base_query => base_query}.merge(@options)).search
49
+ end
50
+
51
+ protected
52
+
53
+ class << self
54
+ attr_accessor :configured_host, :configured_port
55
+ end
56
+
57
+ def default_search_options
58
+ {
59
+ :host => self.class.configured_host,
60
+ :port => self.class.configured_port,
61
+ :collection => 'cm-contents'
62
+ }
63
+ end
64
+
65
+ def build_query_string(query)
66
+ query = normalize_query(query)
67
+ if full_text_query?(query)
68
+ full_text_query_string(extract_words(query))
69
+ else
70
+ complex_query_string(query)
71
+ end
72
+ end
73
+
74
+ def full_text_query?(query)
75
+ query.any? {|q| q[:field] == :'*' && (q[:operator] == :prefix_search || q[:operator] == :search)}
76
+ end
77
+
78
+ def complex_query_string(query)
79
+ conditions = query.map do |q|
80
+ if q[:field] == :'*'
81
+ Rails.logger.error("Unexpected field * when processing search request: #{q.inspect}")
82
+ next
83
+ end
84
+
85
+ resolved_field = resolve_field_name(q[:field])
86
+
87
+ # paths are sadly not in the search index.
88
+ next if resolved_field == :visiblePath
89
+
90
+ case q[:operator]
91
+ when :equal
92
+ if q[:field] == :_modification
93
+ '("edited" <#IN> state)'
94
+ else
95
+ field_operator_value(resolved_field, "=", q[:value])
96
+ end
97
+ when :search
98
+ field_operator_value(resolved_field, "<#CONTAINS>", q[:value])
99
+ when :greater_than
100
+ field_operator_value(resolved_field, ">", q[:value])
101
+ when :less_than
102
+ field_operator_value(resolved_field, "<", q[:value])
103
+ when :prefix, :prefix_search
104
+ values = q[:value]
105
+ values = [values] unless values.kind_of?(Array)
106
+ values.map {|v| "#{v}*" }
107
+ values_operator_field(values, "<#IN>", resolved_field)
108
+ else
109
+ raise "Operator: #{q[:operator]} not supported"
110
+ end
111
+ end.compact
112
+
113
+ if conditions.empty?
114
+ query_string = ""
115
+ else
116
+ query_string = "<#AND> (" + conditions.join(", ") + ")"
117
+ end
118
+ end
119
+
120
+ def field_operator_value(field, operator, values)
121
+ values = [values] unless values.kind_of?(Array)
122
+
123
+ condition = values.map do |value|
124
+ %|(#{field} #{operator} "#{self.class.sanitize(value)}")|
125
+ end.join(", ")
126
+
127
+ %|(<#OR> #{condition})|
128
+ end
129
+
130
+ def values_operator_field(values, operator, field)
131
+ values = [values] unless values.kind_of?(Array)
132
+
133
+ condition = values.map do |value|
134
+ %|("#{self.class.sanitize(value)}" #{operator} #{field})|
135
+ end.join(", ")
136
+
137
+ %|(<#OR> #{condition})|
138
+ end
139
+
140
+ def resolve_field_name(field)
141
+ if Fiona7.mode != :legacy
142
+ Rails.logger.error("This method is not compatible with modes other than legacy")
143
+ end
144
+
145
+ case field
146
+ when :_obj_class
147
+ :objClass
148
+ when :_path
149
+ :visiblePath
150
+ when :_modification
151
+ :__dummy__
152
+ when :id
153
+ :obj_id
154
+ when :_permalink
155
+ :permalink
156
+ when :_last_changed
157
+ :lastChanged
158
+ when :_name
159
+ :name
160
+ else
161
+ field
162
+ end
163
+ end
164
+
165
+ def normalize_query(query)
166
+ query = query.map do |q|
167
+ q.symbolize_keys
168
+ q[:operator] = q[:operator].to_sym
169
+ q[:field] = q[:field].to_sym
170
+ q
171
+ end
172
+ end
173
+
174
+ def extract_words(query)
175
+ q = query.find {|q| q[:field] == :'*' && (q[:operator] == :prefix_search || q[:operator] == :search) }
176
+ if q[:value].kind_of?(Array)
177
+ q[:value]
178
+ else
179
+ [q[:value]]
180
+ end
181
+ end
182
+
183
+ def full_text_query_string(words)
184
+ words = words.map do |word|
185
+ word = self.class.sanitize(word)
186
+ word unless %w(and or not).include?(word.downcase)
187
+ end.compact.join(", ")
188
+ "<#AND> (#{words})"
189
+ end
190
+
191
+ def base_query_conditions
192
+ conditions = {}
193
+ conditions[:objTypes] = '<#ANY> (
194
+ ("generic" <#IN> objType),
195
+ ("document" <#IN> objType),
196
+ ("publication" <#IN> objType)
197
+ )'
198
+ if @use_released
199
+ conditions[:content] = '("released" <#IN> state)'
200
+ conditions[:suppressExport] = '("0" <#IN> suppressExport)'
201
+ conditions[:validFrom] = "(validFrom < #{Time.now.to_iso})"
202
+ conditions[:validUntil] = %!<#OR> (
203
+ (validUntil = ""),
204
+ (validUntil > #{Time.now.to_iso})
205
+ )!
206
+ else
207
+ conditions[:suppressExport] = '("0" <#IN> suppressExport)'
208
+ end
209
+ #conditions[:notWidget] = '("Widget" <#IN/NOT> objClass)'
210
+ conditions[:notWidget] = '(objClass <#ENDS/NOT> "Widget")'
211
+ conditions
212
+ end
213
+ end
214
+ end
215
+ end
@@ -1,3 +1,3 @@
1
1
  module Fiona7
2
- VERSION = "0.71.0.7"
2
+ VERSION = "0.71.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: infopark_fiona7
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.71.0.7
4
+ version: 0.71.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Przedmojski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-03 00:00:00.000000000 Z
11
+ date: 2015-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -183,6 +183,7 @@ files:
183
183
  - lib/fiona7/controllers/rest_api/obj_controller.rb
184
184
  - lib/fiona7/controllers/rest_api/workspace_controller.rb
185
185
  - lib/fiona7/current_user_map.rb
186
+ - lib/fiona7/custom_verity_accessor.rb
186
187
  - lib/fiona7/editing_env_check.rb
187
188
  - lib/fiona7/engine.rb
188
189
  - lib/fiona7/fiona_connector_patches/basic_obj.rb
@@ -239,6 +240,7 @@ files:
239
240
  - lib/fiona7/type_loader.rb
240
241
  - lib/fiona7/type_register.rb
241
242
  - lib/fiona7/type_synchronizer.rb
243
+ - lib/fiona7/verity_search_engine.rb
242
244
  - lib/fiona7/version.rb
243
245
  - lib/fiona7/version_helper.rb
244
246
  - lib/fiona7/widget_resolver.rb