infopark_fiona7 1.1.0.0.10 → 1.2.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/fiona7_ui.js +96 -50
  3. data/app/assets/javascripts/scrivito_patches/models/blob.js +21 -0
  4. data/app/assets/javascripts/scrivito_patches/models/obj.js +1 -1
  5. data/app/controllers/fiona7/release_controller.rb +6 -2
  6. data/app/controllers/fiona7/sessions_controller.rb +3 -0
  7. data/app/controllers/fiona7/workflow_controller.rb +46 -0
  8. data/app/helpers/fiona7_login_helper.rb +16 -0
  9. data/app/helpers/fiona7_override_helper.rb +1 -1
  10. data/config/delayed_routes.rb +1 -0
  11. data/config/precedence_routes.rb +92 -0
  12. data/infopark_fiona7.gemspec +2 -2
  13. data/lib/fiona7/blob_id_generator.rb +13 -0
  14. data/lib/fiona7/builder/indirect_blob_builder.rb +71 -0
  15. data/lib/fiona7/builder/lazy_blob_copier.rb +207 -0
  16. data/lib/fiona7/builder/obj_builder.rb +29 -50
  17. data/lib/fiona7/builder/obj_class_builder.rb +20 -0
  18. data/lib/fiona7/controllers/rest_api/blob_controller.rb +19 -0
  19. data/lib/fiona7/controllers/rest_api/obj_controller.rb +8 -4
  20. data/lib/fiona7/controllers/rest_api/workspace_controller.rb +2 -1
  21. data/lib/fiona7/engine.rb +56 -2
  22. data/lib/fiona7/json/obj_decorator.rb +4 -1
  23. data/lib/fiona7/link_converter/fiona_to_scrivito.rb +3 -1
  24. data/lib/fiona7/link_converter/scrivito_to_fiona.rb +12 -1
  25. data/lib/fiona7/mode_switch/cms_routes/scrivito_sdk.rb +1 -71
  26. data/lib/fiona7/mode_switch/cms_routes/scrivito_sdk_slave.rb +1 -71
  27. data/lib/fiona7/recursive_object_finder.rb +32 -8
  28. data/lib/fiona7/routers/rest_api.rb +6 -7
  29. data/lib/fiona7/scrivito_patches/attribute_content.rb +1 -1
  30. data/lib/fiona7/scrivito_patches/attribute_serializer.rb +22 -1
  31. data/lib/fiona7/scrivito_patches/basic_obj.rb +27 -5
  32. data/lib/fiona7/scrivito_patches/cms_backend.rb +3 -22
  33. data/lib/fiona7/scrivito_patches/cms_rest_api.rb +2 -1
  34. data/lib/fiona7/scrivito_patches/cms_routing.rb +2 -2
  35. data/lib/fiona7/scrivito_patches/model_library.rb +3 -3
  36. data/lib/fiona7/scrivito_patches/page_config.rb +21 -1
  37. data/lib/fiona7/scrivito_patches/preset_routes.rb +15 -2
  38. data/lib/fiona7/scrivito_patches/routing_extensions.rb +33 -20
  39. data/lib/fiona7/scrivito_patches/workspace.rb +3 -1
  40. data/lib/fiona7/super_object_finder.rb +63 -0
  41. data/lib/fiona7/type_register.rb +35 -9
  42. data/lib/fiona7/verity_search_engine.rb +1 -1
  43. data/lib/fiona7/version.rb +1 -1
  44. metadata +13 -7
  45. data/config/routes.rb +0 -13
@@ -17,7 +17,7 @@ module Scrivito
17
17
 
18
18
  # support shadow classes
19
19
  def description_for_editor
20
- to_s
20
+ to_s.titleize
21
21
  end
22
22
 
23
23
  def register_attribute_definitions(obj_class)
@@ -5,12 +5,33 @@ module Scrivito
5
5
  def serialize_binary_value(attribute_value, attribute_definition)
6
6
  case attribute_value
7
7
  when File then attribute_value
8
- when FutureBinary then attribute_value.file_to_upload
8
+ when FutureBinary then special_handling_of_future_binary(attribute_value, attribute_definition)
9
9
  when UploadedBinary then attribute_value.params
10
10
  else
11
11
  raise_validation_error(attribute_definition.name,
12
12
  'an instance of File, Scrivito::UploadedBinary or nil', attribute_value)
13
13
  end
14
14
  end
15
+
16
+ protected
17
+ def special_handling_of_future_binary(future_binary, attribute_definition)
18
+ if future_binary.file_to_upload
19
+ # The easy case: just upload the file directly, it works
20
+ future_binary.file_to_upload
21
+ elsif future_binary.id_to_copy
22
+ # The hard case: magic blob copy/rename needs to happen
23
+ {
24
+ obj_id: obj_id,
25
+ attr_name: attribute_definition.name.to_s,
26
+ id_to_copy: future_binary.id_to_copy,
27
+ filename: future_binary.filename,
28
+ content_type: future_binary.content_type
29
+ }
30
+ else
31
+ # The unknown case: ???
32
+ Rails.logger.error("Unsure how to proceed with an upload of #{future_binary.inspect}")
33
+ nil
34
+ end
35
+ end
15
36
  end
16
37
  end
@@ -21,11 +21,6 @@ module Scrivito
21
21
  "Already modified in workspace #{target_workspace.id}"
22
22
  end
23
23
 
24
- def copy_binaries(attributes)
25
- # TODO: what to do?
26
- attributes
27
- end
28
-
29
24
  # Originally this method checks for conflicts
30
25
  # which are impossible here, hence the method is stubbed out
31
26
  def publishable?
@@ -45,6 +40,33 @@ module Scrivito
45
40
  end
46
41
  end
47
42
 
43
+ # Original implementation mishandles attribute => [type, value]
44
+ def copy_binaries(attributes)
45
+ attribute_defintions = self.class.find_attribute_definitions(obj_class)
46
+ destination_obj_id = attributes.fetch(:_id)
47
+
48
+ Hash[attributes.map do |name, value|
49
+ # Here is the change
50
+ if value && attribute_defintions[name].try(:type) == 'binary' && (binary = self[name])
51
+ [name, ['binary', copy_binary(destination_obj_id, binary)]]
52
+ else
53
+ [name, value]
54
+ end
55
+ end]
56
+ end
57
+
58
+ # Original implmentation uses the blob copy API
59
+ # This is completely unneccessary, as the required
60
+ # logic is already possible implemented similar to FutureBinary
61
+ def copy_binary(destination_obj_id, binary)
62
+ {
63
+ obj_id: destination_obj_id,
64
+ id_to_copy: binary.id,
65
+ filename: binary.filename,
66
+ content_type: binary.content_type
67
+ }.stringify_keys
68
+ end
69
+
48
70
  def fiona_obj
49
71
  @fiona_obj ||= ::RailsConnector::BasicObj.find(self.id)
50
72
  end
@@ -1,11 +1,11 @@
1
1
  require 'scrivito/cms_backend'
2
2
 
3
3
  module Scrivito
4
- class CmsBackend
4
+ module CmsBackend
5
5
  # prevent the use of local URLs (localhost:7104) from cache
6
6
  # when running under a server
7
- def find_blob_data_from_cache(id, access, verb, transformation_definition)
8
- cache_key = blob_data_cache_key(normalize_blob_id(id), access, verb, transformation_definition)
7
+ def self.find_blob_data_from_cache(id, access, verb, options)
8
+ cache_key = blob_data_cache_key(normalize_blob_id(id), access, verb, options)
9
9
  data = CmsDataCache.cache.read(cache_key)
10
10
 
11
11
  if !data.nil? && Fiona7::Middleware::ServerDetectionMiddleware.server_detected?
@@ -20,24 +20,5 @@ module Scrivito
20
20
  data
21
21
  end
22
22
  end
23
-
24
- # prevent real get requests since we run everything locally
25
- # def request_blob_metadata_from_s3(url)
26
- # @query_counter += 1
27
-
28
- # blob_id = /\/_b\/([0-9]+)/.match(url)[1]
29
-
30
- # raise ScrivitoError, "Unexpected 's3' url: #{url}" unless blob_id.present?
31
-
32
- # rest_api_meta_data = Fiona7::Controllers::RestAPI::BlobController.new.metadata(blob_id)
33
-
34
- # meta_data = {}
35
- # meta_data[:content_type] = rest_api_meta_data['meta_data']['content_type'].last
36
- # meta_data[:content_length] = rest_api_meta_data['meta_data']['content_length'].last
37
- # meta_data[:cache_control] = 'no-transform,public,max-age=300,s-maxage=900'
38
-
39
- # meta_data
40
- # end
41
-
42
23
  end
43
24
  end
@@ -1,4 +1,5 @@
1
1
  require 'scrivito/cms_rest_api.rb'
2
+ require 'fiona7/blob_id_generator'
2
3
 
3
4
  module Scrivito
4
5
  class CmsRestApi
@@ -18,7 +19,7 @@ module Scrivito
18
19
  raise Scrivito::ScrivitoError.new("File extension of uploaded file cannot be identified", 422) if ext.nil?
19
20
 
20
21
  upload = Fiona7::WriteObj.upload(file, ext, {name: name, parent: parent, obj_class: obj_class}).tap(&:release!)
21
- encoded_id = '%032d' % upload.id
22
+ encoded_id = Fiona7::BlobIdGenerator.new(upload.id, upload.last_changed).call
22
23
  {'id' => encoded_id}
23
24
  end
24
25
 
@@ -53,7 +53,7 @@ module Scrivito
53
53
  # Use fiona connector permalinks in legacy mode
54
54
  def path_or_url_for_objs(obj, path_or_url, options)
55
55
  permalink = obj.permalink
56
- if permalink && route_defined?(:permalink)
56
+ if permalink && route_defined?(:permalink) && permalink.split('/').first != 'scrivito'
57
57
 
58
58
  if Fiona7.mode == :legacy
59
59
  context.public_send("cms_permalink_#{path_or_url}", options.merge(:permalink => permalink))
@@ -64,7 +64,7 @@ module Scrivito
64
64
  use_route(:homepage, path_or_url, options)
65
65
  elsif obj.binary?
66
66
  # use fiona connector routes when possible
67
- if Fiona7.mode == :legacy
67
+ if Fiona7.mode == :legacy && self.image_options.blank?
68
68
  if binary = obj.binary
69
69
  params = {
70
70
  id: obj.id,
@@ -10,10 +10,10 @@ module Scrivito
10
10
  return model_class if model_class.ancestors.include?(base_class)
11
11
 
12
12
  if Fiona7.mode == :legacy && model_class.respond_to?(:shadow_class)
13
- model_class = model_class.shadow_class
14
- model_class if model_class.ancestors.include?(base_class)
13
+ model_class = model_class.shadow_class rescue nil
14
+ model_class if model_class && model_class.ancestors.include?(base_class)
15
15
  end
16
- rescue NameError
16
+ rescue LoadError
17
17
  end
18
18
  end
19
19
  end
@@ -5,7 +5,7 @@ module Scrivito
5
5
  def current_page_config
6
6
  # TODO: add permission info
7
7
  return {} unless obj
8
- {
8
+ config = {
9
9
  id: obj.id,
10
10
  path: obj.path,
11
11
  obj_class: obj.obj_class,
@@ -16,6 +16,26 @@ module Scrivito
16
16
  parent_path: obj.parent_path,
17
17
  restriction_messages: editor.restriction_messages_for(obj),
18
18
  }
19
+ if ::Fiona7.workflows_enabled?
20
+ fiona_obj = obj.fiona_obj
21
+ if fiona_obj.workflow.present?
22
+ # without a workflow or with workflows disabled this will be falsy
23
+ config[:workflow] = true
24
+ # this just the returns the currently set editor
25
+ config[:editor] = fiona_obj.editor
26
+ # this is the most important bit: when to disable the editing
27
+ # altough simple this implementation handles the following cases:
28
+ # 1. someone outside the workflow visits the page
29
+ # 2. a current editor within the workflow visits the page
30
+ # 3. someone within the workflow visits the page
31
+ config[:editing_disabled] = fiona_obj.editor != editor.id
32
+ # this contains validActionKeys from cms
33
+ # TODO: this should be implemented in reactor
34
+ config[:buttons] = fiona_obj.send(:crul_obj).valid_actions
35
+ end
36
+ end
37
+
38
+ config
19
39
  end
20
40
  end
21
41
  end
@@ -1,6 +1,18 @@
1
+ require "scrivito/preset_routes"
2
+
1
3
  module Scrivito
2
4
  module PresetRoutes
3
- def self.install_into(route_set)
5
+ mattr_accessor :delayed
6
+ self.delayed ||= {}
7
+
8
+ def self.install_delayed(route_set=nil)
9
+ delayed.each do |route, delayed_lambda|
10
+ delayed_lambda.call(route_set)
11
+ end
12
+ end
13
+
14
+ def self.install_into(route_set, do_the_install=false)
15
+ return unless do_the_install
4
16
  return if Scrivito::Configuration.scrivito_route_enabled?
5
17
 
6
18
  Scrivito::Configuration.with_scrivito_route_enabled do
@@ -22,7 +34,8 @@ module Scrivito
22
34
  end
23
35
  end
24
36
 
25
- def self.install_slave_into(route_set)
37
+ def self.install_slave_into(route_set, do_the_install=false)
38
+ return unless do_the_install
26
39
  return if Scrivito::Configuration.scrivito_route_enabled?
27
40
 
28
41
  Scrivito::Configuration.with_scrivito_route_enabled do
@@ -1,3 +1,5 @@
1
+ require "scrivito/routing_extensions"
2
+
1
3
  module Scrivito
2
4
 
3
5
  module RoutingExtensions
@@ -6,32 +8,43 @@ module RoutingExtensions
6
8
  assert_scrivito_route_enabled
7
9
  # @set is a ActionDispatch::Routing::RouteSet
8
10
  # see: http://git.io/v4UYF and http://git.io/v4UOI
9
- route_set = @set
11
+ original_route_set = @set
10
12
 
11
13
  route_name = using.to_sym
12
14
 
13
- route = Route.register(route_set, route_name)
14
-
15
- options = {
16
- to: 'scrivito/cms_dispatch#index',
17
- via: via,
18
- format: format,
19
- as: route.helper_name,
20
- }
21
-
22
- # removed fixed length constraint on ids
23
- options[:constraints] = {id: /[0-9]{4,}/} if route_name == :slug_id
24
-
25
- begin
26
- match(path, options)
27
- rescue ArgumentError => error
28
- if error.message.include?(route.helper_name)
29
- raise ScrivitoError,
15
+ # route_set is actually an optional parameter
16
+ # and should only be used in test scenarios
17
+ delayed = proc do |route_set|
18
+ route_set ||= original_route_set
19
+ route = Route.register(route_set, route_name)
20
+
21
+ options = {
22
+ to: 'scrivito/cms_dispatch#index',
23
+ via: via,
24
+ format: format,
25
+ as: route.helper_name,
26
+ }
27
+
28
+ # removed fixed length constraint on ids
29
+ options[:constraints] = {id: /[0-9]{4,}/} if route_name == :slug_id
30
+
31
+ begin
32
+ match(path, options)
33
+ rescue ArgumentError => error
34
+ if error.message.include?(route.helper_name)
35
+ raise ScrivitoError,
30
36
  %(You have already defined a Scrivito route with the name "#{route_name}".)
31
- else
32
- raise error
37
+ else
38
+ raise error
39
+ end
33
40
  end
34
41
  end
42
+
43
+ if route_name == :permalink && false
44
+ PresetRoutes.delayed[route_name] = delayed
45
+ else
46
+ delayed.call(original_route_set)
47
+ end
35
48
  end
36
49
 
37
50
  private
@@ -12,7 +12,7 @@ module Scrivito
12
12
  false
13
13
  end
14
14
 
15
- # fix silly assumptions
15
+ # properly handle the only two workspaces
16
16
  def self.use(id_or_title)
17
17
  self.current = if id_or_title =~ /(published|rtc)/
18
18
  find(id_or_title)
@@ -20,6 +20,8 @@ module Scrivito
20
20
  find_by_title(id_or_title) or
21
21
  raise ResourceNotFound, "Could not find #{self} with title #{id_or_title}"
22
22
  end
23
+ rescue ResourceNotFound
24
+ raise ResourceNotFound, %{Could not find #{self} with title or ID "#{id_or_title}"}
23
25
  end
24
26
  end
25
27
  end
@@ -0,0 +1,63 @@
1
+ # This class allows to access objects linking to
2
+ # given object, i.e. super objects
3
+ #
4
+ # It provides two modes of searching: preview nad live
5
+ module Fiona7
6
+ class SuperObjectFinder
7
+ def initialize(model=::Fiona7::WriteObj, connection=nil, instance_name=RailsConnector::CmsBaseModel.instance_name)
8
+ @instance_name = instance_name
9
+ @conn = connection || model.connection
10
+ @model = model
11
+ end
12
+
13
+ def find(type=:preview, obj)
14
+ case type
15
+ when :preview
16
+ preview(obj)
17
+ when :live
18
+ live(obj)
19
+ else
20
+ raise ArgumentError, "Uknown type #{type.inspect} expected :preview or :ive"
21
+ end
22
+ end
23
+
24
+ # This method returns the results of search for objects
25
+ # in preview mode.
26
+ #
27
+ # This means that all objects that are reachable in preview
28
+ # are returned (unreleased, commited etc.)
29
+ def preview(obj)
30
+ query = "SELECT #{objects_table}.object_id FROM #{links_table} INNER JOIN #{objects_table} ON #{links_table}.content_id = #{objects_table}.edited_content_id WHERE #{links_table}.sub_object_id = #{obj.obj_id.to_i} #{self.obj_class_condition} UNION SELECT #{objects_table}.object_id FROM #{links_table} INNER JOIN #{objects_table} ON #{links_table}.content_id = #{objects_table}.committed_cont_id WHERE #{links_table}.sub_object_id = #{obj.obj_id.to_i} #{self.obj_class_condition} UNION SELECT #{objects_table}.object_id FROM #{links_table} INNER JOIN #{objects_table} ON #{links_table}.content_id = #{objects_table}.released_cont_id WHERE #{links_table}.sub_object_id = #{obj.obj_id.to_i} AND #{objects_table}.committed_cont_id IS NULL AND #{objects_table}.edited_content_id IS NULL #{self.obj_class_condition}"
31
+ ids = self.sql_query(query).to_a.flatten
32
+ @model.find(ids).select(&:exportable?)
33
+ end
34
+
35
+ # This method returns the results of search for objects
36
+ # in live mode.
37
+ #
38
+ # This means that only the objects that are reachable in
39
+ # live are returned, i.e. avaiable for outside world
40
+ def live(obj)
41
+ query = "SELECT #{objects_table}.object_id FROM #{links_table} INNER JOIN #{objects_table} ON #{links_table}.content_id = #{objects_table}.released_cont_id WHERE #{links_table}.sub_object_id = #{obj.obj_id.to_i} #{self.obj_class_condition}"
42
+ ids = self.sql_query(query).to_a.flatten
43
+ @model.find(ids).select(&:exportable?)
44
+ end
45
+
46
+ protected
47
+ def links_table
48
+ "#{@instance_name}_links"
49
+ end
50
+
51
+ def obj_class_condition
52
+ ""
53
+ end
54
+
55
+ def objects_table
56
+ "#{@instance_name}_objects"
57
+ end
58
+
59
+ def sql_query(query, *args)
60
+ @conn.execute(query, *args)
61
+ end
62
+ end
63
+ end
@@ -8,6 +8,9 @@ require "fiona7/attribute_name_mangler"
8
8
 
9
9
 
10
10
  module Fiona7
11
+ class TypeSystemError < ::ArgumentError
12
+ end
13
+
11
14
  class TypeRegister
12
15
  include Singleton
13
16
 
@@ -17,24 +20,35 @@ module Fiona7
17
20
  referencelist: :linklist,
18
21
  widgetlist: :linklist,
19
22
  binary: :linklist,
23
+ number: :string,
20
24
  stringlist: :text
21
25
  }.freeze
22
26
 
23
27
  class TypeDefinition
24
28
  class Attribute < Struct.new(:name, :type, :real_name, :real_type, :values)
25
- class Core < Struct.new(:name, :type)
26
- end
27
-
28
29
  def eql?(other)
29
30
  other.kind_of?(self.class) &&
30
31
  self.name.eql?(other.name)
31
- #Core.new(self.name, self.type).eql?(Core.new(other.name, other.type))
32
32
  end
33
33
 
34
34
  def hash
35
35
  return self.name.hash
36
- #Core.new(self.name, self.type).hash
37
36
  end
37
+
38
+ def values_set
39
+ return @values_set if defined?(@values_set)
40
+
41
+ if self.values.present?
42
+ @values_set = self.values.to_set
43
+ else
44
+ @values_set = Set[]
45
+ end
46
+
47
+ return @values_set
48
+ end
49
+
50
+ protected
51
+ attr_writer :name, :type, :real_name, :real_type, :values
38
52
  end
39
53
 
40
54
  attr_accessor :name
@@ -143,7 +157,6 @@ module Fiona7
143
157
  end
144
158
 
145
159
  def ad_hoc_synchronize(type_definition)
146
- #puts "Ad hoc synchronize of #{type_definition.name}"
147
160
  obj_class = type_definition.name
148
161
 
149
162
  existing_definition = self.usr_defs[obj_class]
@@ -157,7 +170,7 @@ module Fiona7
157
170
  self.cms_def_present?(obj_class) &&
158
171
  defs_compatible?(self.cms_defs[obj_class], type_definition)
159
172
 
160
- puts "Ad hoc synchronization required of #{type_definition.name}"
173
+ Rails.logger.warn "Ad hoc synchronization required of #{type_definition.name}"
161
174
 
162
175
  self.synchronize(obj_class)
163
176
  self.load(obj_class)
@@ -196,13 +209,25 @@ module Fiona7
196
209
  # has a proper definition
197
210
  true
198
211
  else
199
- #raise "Attribute types for #{attr_name} incompatible: CMS uses #{cms_type} but the application provided #{usr_type}"
200
- puts "Attribute types for #{attr_name} incompatible: CMS uses #{cms_type} but the application provided #{usr_type}"
212
+ message = "Attribute types for #{attr_name} incompatible: CMS uses #{cms_type} but the application provided #{usr_type}"
213
+ if ::Fiona7.config.dont_yell_at_me_for_abusing_attributes
214
+ Rails.logger.error("TYPE SYNCHRONIZATION: " + message)
215
+ else
216
+ raise TypeSystemError, message
217
+ end
218
+
201
219
  false
202
220
  end
203
221
  end
204
222
  end
205
223
 
224
+ def value_lists_compatabile?(usr_attr, cms_attr)
225
+ return true unless [:multienum, :enum].include?(usr_attr.type)
226
+ return true unless [:multienum, :enum].include?(cms_attr.type)
227
+
228
+ return cms_attr.values_set.superset?(usr_attr.values_set)
229
+ end
230
+
206
231
  def defs_compatible?(cms_def, usr_def)
207
232
  cms_attr_map = {}
208
233
  cms_def.attrs.each do |attr|
@@ -212,6 +237,7 @@ module Fiona7
212
237
  usr_def.attrs.each do |attr|
213
238
  return false if !cms_attr_map[attr.name]
214
239
  return false if !type_compatible?(attr.name, cms_attr_map[attr.name].type, attr.type)
240
+ return false if !value_lists_compatabile?(attr, cms_attr_map[attr.name])
215
241
  end
216
242
 
217
243
  return true