scrivito_sdk 0.18.1 → 0.30.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/scrivito/blobs_controller.rb +1 -2
- data/app/controllers/scrivito/default_cms_controller.rb +9 -75
- data/app/controllers/scrivito/objs_controller.rb +107 -119
- data/app/controllers/scrivito/tasks_controller.rb +1 -1
- data/app/controllers/scrivito/users_controller.rb +1 -1
- data/app/controllers/scrivito/webservice_controller.rb +6 -2
- data/app/controllers/scrivito/workspaces_controller.rb +57 -17
- data/app/helpers/scrivito_helper.rb +285 -0
- data/app/views/google_maps_widget/show.html.erb +1 -0
- data/app/views/scrivito/_editing_auth_warning.html.erb +43 -0
- data/app/views/scrivito/blobs/upload_permission.json.jbuilder +1 -0
- data/app/views/scrivito/objs/copy.json.jbuilder +1 -0
- data/app/views/scrivito/objs/copy_widget.html.erb +1 -1
- data/app/views/scrivito/objs/create.json.jbuilder +1 -0
- data/app/views/scrivito/objs/create_widget.html.erb +1 -1
- data/app/views/scrivito/objs/details.json.jbuilder +1 -0
- data/app/views/scrivito/objs/format_missing_error.json.jbuilder +1 -0
- data/app/views/scrivito/objs/modification.json.jbuilder +1 -0
- data/app/views/scrivito/objs/page_class_selection.json.jbuilder +1 -0
- data/app/views/scrivito/objs/search.json.jbuilder +6 -0
- data/app/views/scrivito/objs/search_only_size.json.jbuilder +1 -0
- data/app/views/scrivito/objs/update.json.jbuilder +1 -0
- data/app/views/scrivito/objs/widget_class_selection.json.jbuilder +1 -0
- data/app/views/scrivito/objs/widget_modification.json.jbuilder +1 -0
- data/app/views/scrivito/tasks/show.json.jbuilder +3 -0
- data/app/views/scrivito/users/suggest.json.jbuilder +1 -0
- data/app/views/scrivito/webservice/empty.json +1 -0
- data/app/views/scrivito/webservice/error.json.jbuilder +2 -0
- data/app/views/scrivito/workspaces/_workspace.json.jbuilder +5 -0
- data/app/views/scrivito/workspaces/check.json.jbuilder +1 -0
- data/app/views/scrivito/workspaces/create.json.jbuilder +1 -0
- data/app/views/scrivito/workspaces/index.json.jbuilder +1 -0
- data/app/views/scrivito/workspaces/show.json.jbuilder +1 -0
- data/app/views/scrivito/workspaces/task.json.jbuilder +5 -0
- data/config/ca-bundle.crt +259 -234
- data/config/cms_routes.rb +2 -2
- data/config/routes.rb +3 -0
- data/lib/assets/javascripts/{scrivito_editing.js → scrivito_sdk.js} +1662 -1180
- data/lib/assets/stylesheets/{scrivito_editing.css → scrivito_sdk.css} +242 -6
- data/lib/generators/scrivito/install/install_generator.rb +62 -0
- data/lib/generators/scrivito/install/templates/app/controllers/cms_controller.rb +3 -0
- data/lib/generators/scrivito/install/templates/app/controllers/page_controller.rb +2 -0
- data/lib/generators/scrivito/install/templates/app/models/headline_widget.rb +7 -0
- data/lib/generators/scrivito/install/templates/app/models/image.rb +5 -0
- data/lib/generators/scrivito/install/templates/app/models/image_widget.rb +7 -0
- data/lib/generators/scrivito/install/templates/app/models/obj.rb +2 -0
- data/lib/generators/scrivito/install/templates/app/models/page.rb +8 -0
- data/lib/generators/scrivito/install/templates/app/models/text_widget.rb +7 -0
- data/lib/generators/scrivito/install/templates/app/models/widget.rb +2 -0
- data/lib/generators/scrivito/install/templates/app/views/headline_widget/show.html.erb +1 -0
- data/lib/generators/scrivito/install/templates/app/views/headline_widget/thumbnail.html.erb +3 -0
- data/lib/generators/scrivito/install/templates/app/views/image_widget/show.html.erb +1 -0
- data/lib/generators/scrivito/install/templates/app/views/image_widget/thumbnail.html.erb +3 -0
- data/lib/generators/scrivito/install/templates/app/views/page/details.html.erb +1 -0
- data/lib/generators/scrivito/install/templates/app/views/page/index.html.erb +16 -0
- data/lib/generators/scrivito/install/templates/app/views/page/thumbnail.html.erb +3 -0
- data/lib/generators/scrivito/install/templates/app/views/text_widget/show.html.erb +1 -0
- data/lib/generators/scrivito/install/templates/app/views/text_widget/thumbnail.html.erb +3 -0
- data/lib/generators/scrivito/install/templates/config/initializers/scrivito.rb +10 -0
- data/lib/generators/scrivito/install/templates/scrivito/migrate/install_scrivito.rb +49 -0
- data/lib/generators/scrivito/migration/USAGE +9 -0
- data/lib/generators/{cms → scrivito}/migration/migration_generator.rb +4 -9
- data/lib/generators/{cms → scrivito}/migration/templates/migration.erb +3 -3
- data/lib/generators/{cms → scrivito}/widget/templates/details.html.erb +0 -0
- data/lib/generators/{cms → scrivito}/widget/templates/migration.erb +0 -0
- data/lib/generators/{cms → scrivito}/widget/templates/model.erb +0 -0
- data/lib/generators/{cms → scrivito}/widget/templates/show.html.erb +0 -0
- data/lib/generators/scrivito/widget/templates/thumbnail.html.erb +3 -0
- data/lib/generators/{cms → scrivito}/widget/widget_generator.rb +3 -2
- data/lib/obj.rb +17 -3
- data/lib/scrivito/attribute_collection.rb +7 -12
- data/lib/scrivito/attribute_content.rb +31 -12
- data/lib/scrivito/basic_obj.rb +186 -96
- data/lib/scrivito/basic_widget.rb +25 -10
- data/lib/scrivito/binary.rb +75 -0
- data/lib/scrivito/cache_garbage_collector.rb +19 -4
- data/lib/scrivito/child_list_tag.rb +108 -0
- data/lib/scrivito/client_config.rb +2 -1
- data/lib/scrivito/client_error.rb +3 -2
- data/lib/scrivito/cms_backend.rb +81 -16
- data/lib/scrivito/cms_dispatch_controller.rb +7 -0
- data/lib/scrivito/cms_env.rb +0 -2
- data/lib/scrivito/cms_field_tag.rb +44 -35
- data/lib/scrivito/cms_rest_api.rb +23 -6
- data/lib/scrivito/cms_rest_api/attribute_serializer.rb +1 -1
- data/lib/scrivito/cms_routing.rb +120 -0
- data/lib/scrivito/configuration.rb +69 -58
- data/lib/scrivito/connection_manager.rb +30 -1
- data/lib/scrivito/content_service.rb +10 -7
- data/lib/scrivito/controller_actions.rb +108 -0
- data/lib/scrivito/diff.rb +30 -15
- data/lib/scrivito/editing_context.rb +4 -0
- data/lib/scrivito/editing_context_helper.rb +19 -0
- data/lib/scrivito/editing_context_middleware.rb +20 -1
- data/lib/scrivito/image_tag_helper.rb +44 -0
- data/lib/scrivito/layout_tags.rb +33 -0
- data/lib/scrivito/link.rb +4 -2
- data/lib/scrivito/membership.rb +0 -8
- data/lib/scrivito/migrations.rb +0 -1
- data/lib/scrivito/migrations/installer.rb +1 -1
- data/lib/scrivito/migrations/migration.rb +0 -2
- data/lib/scrivito/migrations/migrator.rb +2 -3
- data/lib/scrivito/obj_class.rb +64 -16
- data/lib/scrivito/obj_class_data.rb +4 -0
- data/lib/scrivito/obj_search_enumerator.rb +1 -1
- data/lib/scrivito/routing_helper.rb +42 -0
- data/lib/scrivito/{engine.rb → sdk_engine.rb} +15 -29
- data/lib/scrivito/tag_renderer.rb +40 -0
- data/lib/scrivito/test_request.rb +40 -0
- data/lib/scrivito/type_computer.rb +1 -6
- data/lib/scrivito/user.rb +33 -15
- data/lib/scrivito/user_definition.rb +34 -6
- data/lib/scrivito/widget_tag.rb +67 -0
- data/lib/scrivito/workspace.rb +12 -24
- data/lib/scrivito_sdk.rb +17 -1
- data/lib/tasks/cache.rake +4 -5
- data/lib/tasks/migration.rake +1 -1
- data/lib/widget.rb +21 -3
- metadata +119 -70
- data/README +0 -6
- data/app/controllers/cms_controller.rb +0 -7
- data/app/helpers/cms_helper.rb +0 -7
- data/app/helpers/cms_routing_helper.rb +0 -7
- data/app/helpers/scrivito/cms_asset_helper.rb +0 -110
- data/app/helpers/scrivito/cms_tag_helper.rb +0 -232
- data/app/helpers/scrivito/default_cms_helper.rb +0 -21
- data/app/helpers/scrivito/default_cms_routing_helper.rb +0 -128
- data/app/helpers/scrivito/display_helper.rb +0 -64
- data/app/helpers/scrivito/editing_helper.rb +0 -32
- data/app/helpers/scrivito/layout_helper.rb +0 -21
- data/app/models/named_link.rb +0 -2
- data/app/views/cms/_index.html.erb +0 -7
- data/app/views/cms/index.html.erb +0 -1
- data/app/views/scrivito/_editing_javascript.html.erb +0 -7
- data/app/views/scrivito/default_cms/show_widget.html.erb +0 -1
- data/lib/assets/stylesheets/scrivito.css +0 -199
- data/lib/generators/cms/migration/USAGE +0 -9
- data/lib/generators/cms/widget/templates/thumbnail.html.erb +0 -2
- data/lib/scrivito/blob.rb +0 -48
- data/lib/scrivito/cms_accessible.rb +0 -30
- data/lib/scrivito/cms_rest_api/blob_uploader.rb +0 -18
- data/lib/scrivito/cms_test_request.rb +0 -23
- data/lib/scrivito/migrations/migration_dsl.rb +0 -180
@@ -25,7 +25,7 @@ class BasicWidget
|
|
25
25
|
# The new Widget must be stored inside a container (i.e. an Obj or another Widget)
|
26
26
|
# before it can be used.
|
27
27
|
#
|
28
|
-
# See {BasicObj.create Obj.create} for a detailed overview of how to set attributes.
|
28
|
+
# See {Scrivito::BasicObj.create Obj.create} for a detailed overview of how to set attributes.
|
29
29
|
# @api public
|
30
30
|
# @param [Hash] attributes
|
31
31
|
#
|
@@ -51,7 +51,7 @@ class BasicWidget
|
|
51
51
|
|
52
52
|
# Update the attributes of this Widget
|
53
53
|
#
|
54
|
-
# See {BasicObj.create Obj.create} for a detailed overview of how to set attributes
|
54
|
+
# See {Scrivito::BasicObj.create Obj.create} for a detailed overview of how to set attributes
|
55
55
|
# @api public
|
56
56
|
# @param [Hash] attributes
|
57
57
|
def update(attributes)
|
@@ -59,16 +59,16 @@ class BasicWidget
|
|
59
59
|
reload
|
60
60
|
end
|
61
61
|
|
62
|
-
# Destroys the {BasicWidget Widget} in the current {Workspace}
|
62
|
+
# Destroys the {Scrivito::BasicWidget Widget} in the current {Workspace}
|
63
63
|
# @api public
|
64
64
|
def destroy
|
65
65
|
new_widget_list = container[container_field_name] - [self]
|
66
66
|
container.update(container_field_name => new_widget_list)
|
67
67
|
end
|
68
68
|
|
69
|
-
# Clones the {BasicWidget Widget}. The clone gets all
|
69
|
+
# Clones the {Scrivito::BasicWidget Widget}. The clone gets all
|
70
70
|
# attributes of the original widget except nested widget attributes.
|
71
|
-
# The clone is not attached to an {BasicObj Obj} initially.
|
71
|
+
# The clone is not attached to an {Scrivito::BasicObj Obj} initially.
|
72
72
|
# It only becomes usable by assigning it to a widget attribute of an Obj.
|
73
73
|
#
|
74
74
|
# @example
|
@@ -107,10 +107,21 @@ class BasicWidget
|
|
107
107
|
self == other
|
108
108
|
end
|
109
109
|
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
110
|
+
#
|
111
|
+
# Reverts all changes made to the +Widget+ in the current workspace.
|
112
|
+
#
|
113
|
+
# @api public
|
114
|
+
#
|
115
|
+
# @note This method does not support +Widget+s, which are +new+.
|
116
|
+
# Please use {Scrivito::BasicWidget#destroy Widget#destroy} to destroy them.
|
117
|
+
# @note This method does not support +Widget+s, which are +deleted+.
|
118
|
+
# Please use {Scrivito::BasicObj#revert Obj#revert} to restore them.
|
119
|
+
#
|
120
|
+
# @raise [ScrivitoError] If the current workspace is +published+.
|
121
|
+
# @raise [ScrivitoError] If the current workspace is the +rtc+ workspace.
|
122
|
+
# @raise [ScrivitoError] If the +Widget+ is +new+.
|
123
|
+
# @raise [ScrivitoError] If the +Widget+ is +deleted+.
|
124
|
+
#
|
114
125
|
def revert
|
115
126
|
workspace.assert_revertable
|
116
127
|
|
@@ -170,7 +181,7 @@ class BasicWidget
|
|
170
181
|
end
|
171
182
|
end
|
172
183
|
|
173
|
-
# returns the entity ({BasicObj} or {BasicWidget}) that references this widget
|
184
|
+
# returns the entity ({Scrivito::BasicObj} or {Scrivito::BasicWidget}) that references this widget
|
174
185
|
# @api public
|
175
186
|
def container
|
176
187
|
@container || cache_container_and_field_name_for_widget.first
|
@@ -182,6 +193,10 @@ class BasicWidget
|
|
182
193
|
@container_field_name || cache_container_and_field_name_for_widget.second
|
183
194
|
end
|
184
195
|
|
196
|
+
def has_attribute?(key)
|
197
|
+
key.to_s == '_obj_class' || super
|
198
|
+
end
|
199
|
+
|
185
200
|
def inspect
|
186
201
|
if @id
|
187
202
|
if @obj
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Scrivito
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# The Binary class represents the data stored in a binary attribute of an Obj
|
5
|
+
# or Widget
|
6
|
+
class Binary
|
7
|
+
def initialize(id, public_content)
|
8
|
+
@id = id
|
9
|
+
@public_content = public_content
|
10
|
+
end
|
11
|
+
|
12
|
+
# @api public
|
13
|
+
# Some Scrivito data is considered private, i.e. it is not currently intended
|
14
|
+
# for the general public, for example content in a workspace that has not
|
15
|
+
# been published yet.
|
16
|
+
# @return [Boolean]
|
17
|
+
def private?
|
18
|
+
!public_content?
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api public
|
22
|
+
# The URL where this binary data is accessible and can be downloaded using an
|
23
|
+
# HTTP GET request. Note that urls for private content will have an
|
24
|
+
# expiration time in order to protect them.
|
25
|
+
# Therefore the url returned here should be accessed immediately after it has been returned (i.e. within a couple of minutes).
|
26
|
+
# When accessed after they have expired, an error will occur.
|
27
|
+
# The urls should not be used for long-term-storage (i.e. they are no longer accessible hours or days after they have been generated).
|
28
|
+
# @return [String] the URL under which this content is available
|
29
|
+
def url
|
30
|
+
find_url('get')
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api public
|
34
|
+
# the filename of this binary data, for example "my_image.jpg"
|
35
|
+
# @return [String] the filename of binary
|
36
|
+
def filename
|
37
|
+
File.basename(URI(url).path)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api public
|
41
|
+
# the content type of this binary data, for example "image/jpeg"
|
42
|
+
# @return [String] content type
|
43
|
+
def content_type
|
44
|
+
headers[:content_type]
|
45
|
+
end
|
46
|
+
|
47
|
+
# @api public
|
48
|
+
# the length of this binary data, in bytes.
|
49
|
+
# @return [Integer] number of bytes
|
50
|
+
def content_length
|
51
|
+
headers[:content_length].to_i
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
attr_reader :id
|
57
|
+
|
58
|
+
def public_content?
|
59
|
+
!!@public_content
|
60
|
+
end
|
61
|
+
|
62
|
+
def headers
|
63
|
+
CmsBackend.instance.find_blob_metadata(id, find_url('head'))
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_url(verb)
|
67
|
+
CmsBackend.instance.find_blob_data(@id, access_type, verb)['url']
|
68
|
+
end
|
69
|
+
|
70
|
+
def access_type
|
71
|
+
public_content? ? 'public_access' : 'private_access'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module Scrivito
|
2
|
-
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
2
|
+
#
|
3
|
+
# The CacheGarbageCollector allows to remove old cache files from the Scrivito cache storage path.
|
4
|
+
# By default, a maximum of {Scrivito::CacheGarbageCollector::DEFAULT_MAX_FILE_INODES} file inodes
|
5
|
+
# that were accessed lately are kept in the cache directory.
|
6
|
+
# All other files and empty directories are removed.
|
7
|
+
# Log output is written to the Rails environment log file.
|
8
|
+
#
|
9
|
+
# @api public
|
6
10
|
#
|
7
11
|
# @example Running the garbage collector with default settings
|
8
12
|
#
|
@@ -11,7 +15,13 @@ module Scrivito
|
|
11
15
|
# @example Changing the maximum number of file inodes
|
12
16
|
#
|
13
17
|
# bundle exec rake scrivito:cache:gc MAX_FILE_INODES=5000
|
18
|
+
#
|
14
19
|
class CacheGarbageCollector
|
20
|
+
#
|
21
|
+
# Default maximum number of file inodes that are kept in the cache directory.
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
#
|
15
25
|
DEFAULT_MAX_FILE_INODES = 100000
|
16
26
|
|
17
27
|
attr_accessor :max_file_inodes
|
@@ -20,6 +30,9 @@ module Scrivito
|
|
20
30
|
@max_file_inodes = (max_file_inodes || DEFAULT_MAX_FILE_INODES).to_i
|
21
31
|
end
|
22
32
|
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
#
|
23
36
|
def run_gc
|
24
37
|
announce "Cap number of cache file inodes at #{max_file_inodes} in #{cache_path}."
|
25
38
|
|
@@ -58,6 +71,8 @@ module Scrivito
|
|
58
71
|
announce "Done. Removed #{delta_count} entries. Saved at least #{delta_disk_space} Bytes."
|
59
72
|
end
|
60
73
|
|
74
|
+
private
|
75
|
+
|
61
76
|
def cache_path
|
62
77
|
CmsCacheStorage.backend_cache.cache_path
|
63
78
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Scrivito
|
2
|
+
|
3
|
+
class ChildListTag < Struct.new(:tag_name, :obj, :field_name, :view)
|
4
|
+
include TagRenderer
|
5
|
+
|
6
|
+
def initialize(tag_name, obj, field_name, view)
|
7
|
+
unless field_name == 'toclist'
|
8
|
+
raise "#{field_name} is not (yet) supported. Currently only toclist is supported."
|
9
|
+
end
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def options
|
14
|
+
return {} unless user_present?
|
15
|
+
|
16
|
+
options = {
|
17
|
+
'private-child-list-allowed-classes' => Obj.valid_page_classes_beneath(obj.path).to_json,
|
18
|
+
'private-child-list-path' => obj.path,
|
19
|
+
'private-obj-description-for-editor' => obj.description_for_editor,
|
20
|
+
}
|
21
|
+
|
22
|
+
if obj.has_attribute?(:child_order)
|
23
|
+
options['private-child-list-order-obj-id'] = obj.id
|
24
|
+
modification = comparison.modification_for_attribute(obj, :child_order)
|
25
|
+
if modification == Modification::EDITED
|
26
|
+
options['private-child-list-modification'] = modification
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
options
|
31
|
+
end
|
32
|
+
|
33
|
+
def content(&block)
|
34
|
+
return unless block_given?
|
35
|
+
|
36
|
+
is_sortable = obj.has_attribute?(:child_order) && user_present?
|
37
|
+
rendered_children = sorted_children.map do |child|
|
38
|
+
obj_tag = ObjTag.new(child, is_sortable, comparison.modification(child), view)
|
39
|
+
yield obj_tag, child
|
40
|
+
obj_tag.rendered
|
41
|
+
end
|
42
|
+
view.safe_join(rendered_children)
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# This is a helper class for {ScrivitoHelper#scrivito_tag_list}.
|
47
|
+
# @api public
|
48
|
+
#
|
49
|
+
class ObjTag < Struct.new(:obj, :is_sortable, :modification, :view)
|
50
|
+
include TagRenderer
|
51
|
+
|
52
|
+
attr_reader :tag_name, :rendered
|
53
|
+
|
54
|
+
#
|
55
|
+
# @api public
|
56
|
+
#
|
57
|
+
# @param tag_name [String, Symbol] Name of the html tag (e.g. +:div+ or +:span+).
|
58
|
+
# @param html_options [Hash] Additional options, which are passed to +content_tag+.
|
59
|
+
# Use them to add HTML attributes to the tag.
|
60
|
+
#
|
61
|
+
# @return [String] The rendered html tag
|
62
|
+
#
|
63
|
+
# @example Render a <div> tag containing the text "random content" and assigns the tag a css class called +very_important+.
|
64
|
+
# <%= list.tag :div, class: "very_important" do %>
|
65
|
+
# random content
|
66
|
+
# <% end %>
|
67
|
+
#
|
68
|
+
def tag(tag_name, html_options = {}, &block)
|
69
|
+
raise '"list.tag" can only be called once per iteration!' if @rendered
|
70
|
+
@tag_name = tag_name
|
71
|
+
@rendered = render(html_options, &block)
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def options
|
76
|
+
return {} unless is_sortable
|
77
|
+
options = {
|
78
|
+
'private-obj-id' => obj.id,
|
79
|
+
'private-obj-description-for-editor' => obj.description_for_editor,
|
80
|
+
}
|
81
|
+
if modification == Modification::NEW || modification == Modification::DELETED
|
82
|
+
options['private-obj-modification'] = modification
|
83
|
+
end
|
84
|
+
options
|
85
|
+
end
|
86
|
+
|
87
|
+
def content(&block)
|
88
|
+
view.capture { yield } if block_given?
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def user_present?
|
95
|
+
view.scrivito_user.present?
|
96
|
+
end
|
97
|
+
|
98
|
+
def comparison
|
99
|
+
EditingContextMiddleware.from_request(view.request).comparison
|
100
|
+
end
|
101
|
+
|
102
|
+
def sorted_children
|
103
|
+
children = obj.toclist
|
104
|
+
obj.has_attribute?(:child_order) ? Obj.sort_by_list(children, obj.child_order) : children
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -24,7 +24,8 @@ class ClientConfig < Struct.new(:obj, :editing_context, :lookup_context, :resour
|
|
24
24
|
|
25
25
|
selected_workspace: {
|
26
26
|
id: selected_workspace.id,
|
27
|
-
title: selected_workspace.title
|
27
|
+
title: selected_workspace.title,
|
28
|
+
outdated: selected_workspace.outdated?
|
28
29
|
},
|
29
30
|
|
30
31
|
visible_workspace: {
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Scrivito
|
2
2
|
|
3
3
|
class ClientError < StandardError
|
4
|
-
attr_reader :http_code
|
4
|
+
attr_reader :http_code, :error_code
|
5
5
|
|
6
|
-
def initialize(message, http_code)
|
6
|
+
def initialize(message, http_code, error_code=nil)
|
7
7
|
@http_code = http_code
|
8
|
+
@error_code = error_code
|
8
9
|
super(message)
|
9
10
|
end
|
10
11
|
end
|
data/lib/scrivito/cms_backend.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'addressable/uri'
|
2
2
|
|
3
3
|
module Scrivito
|
4
4
|
|
@@ -47,7 +47,6 @@ module Scrivito
|
|
47
47
|
end
|
48
48
|
|
49
49
|
class CmsBackend
|
50
|
-
BLOB_DATA_CACHE_PREFIX = 'blob_data'.freeze
|
51
50
|
VALID_INDEX_NAMES = %w[id path ppath permalink].freeze
|
52
51
|
|
53
52
|
class << self
|
@@ -77,6 +76,11 @@ module Scrivito
|
|
77
76
|
@query_counter
|
78
77
|
end
|
79
78
|
|
79
|
+
# For test purpose only.
|
80
|
+
def reset_query_counter!
|
81
|
+
@query_counter = 0
|
82
|
+
end
|
83
|
+
|
80
84
|
def find_workspace_data_by_id(id)
|
81
85
|
workspace_data_from_cache = WorkspaceDataFromService.find_from_cache(id)
|
82
86
|
from_content_state_id = workspace_data_from_cache.try(:content_state_id)
|
@@ -110,16 +114,24 @@ module Scrivito
|
|
110
114
|
find_obj_data_filtering_deleted_by(revision, index, keys, true)
|
111
115
|
end
|
112
116
|
|
113
|
-
def
|
114
|
-
|
115
|
-
if
|
116
|
-
|
117
|
+
def find_blob_data(id, access, verb)
|
118
|
+
id = Addressable::URI.normalize_component(id, Addressable::URI::CharacterClasses::UNRESERVED)
|
119
|
+
if blob_data = fetch_blob_data_from_cache(id, access, verb)
|
120
|
+
blob_data
|
117
121
|
else
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
122
|
+
blob_datas = request_blob_datas_from_backend(id)
|
123
|
+
store_blob_datas_in_cache(id, blob_datas)
|
124
|
+
blob_datas[access][verb]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def find_blob_metadata(id, url)
|
129
|
+
if blob_metadata = fetch_blob_metadata_from_cache(id)
|
130
|
+
blob_metadata
|
131
|
+
else
|
132
|
+
blob_metadata = request_blob_metadata_from_s3(url)
|
133
|
+
store_blob_metadata_in_cache(id, blob_metadata)
|
134
|
+
blob_metadata
|
123
135
|
end
|
124
136
|
end
|
125
137
|
|
@@ -179,6 +191,64 @@ module Scrivito
|
|
179
191
|
content_state.save_obj_data(cache_index, cache_key, result) if caching?
|
180
192
|
end
|
181
193
|
|
194
|
+
def fetch_blob_data_from_cache(id, access, verb)
|
195
|
+
CmsCacheStorage.cache.read(blob_data_cache_key(id, access, verb))
|
196
|
+
end
|
197
|
+
|
198
|
+
def request_blob_datas_from_backend(id)
|
199
|
+
@query_counter += 1
|
200
|
+
CmsRestApi.get("blobs/#{id}")
|
201
|
+
end
|
202
|
+
|
203
|
+
def store_blob_datas_in_cache(id, blob_datas)
|
204
|
+
%w[public_access private_access].each do |access|
|
205
|
+
%w[get head].each do |verb|
|
206
|
+
blob_data = blob_datas[access][verb]
|
207
|
+
CmsCacheStorage.cache.write(blob_data_cache_key(id, access, verb),
|
208
|
+
blob_data, expires_in: blob_data['maxage'])
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def blob_data_cache_key(id, access, verb)
|
214
|
+
"blob_data/#{id}/#{access}/#{verb}"
|
215
|
+
end
|
216
|
+
|
217
|
+
def fetch_blob_metadata_from_cache(id)
|
218
|
+
CmsCacheStorage.cache.read(blob_metadata_cache_key(id))
|
219
|
+
end
|
220
|
+
|
221
|
+
def request_blob_metadata_from_s3(url)
|
222
|
+
uri = URI.parse(url)
|
223
|
+
retried = false
|
224
|
+
begin
|
225
|
+
response = ConnectionManager.request(uri, Net::HTTP::Head.new(uri.path))
|
226
|
+
@query_counter += 1
|
227
|
+
rescue NetworkError
|
228
|
+
raise if retried
|
229
|
+
retried = true
|
230
|
+
retry
|
231
|
+
end
|
232
|
+
|
233
|
+
raise ScrivitoError, "S3 responded with #{reponse.code}" unless response.code == '200'
|
234
|
+
|
235
|
+
{
|
236
|
+
content_length: response['content-length'],
|
237
|
+
content_type: response['content-type'],
|
238
|
+
cache_control: response['cache-control'],
|
239
|
+
}
|
240
|
+
end
|
241
|
+
|
242
|
+
def store_blob_metadata_in_cache(id, blob_metadata)
|
243
|
+
max_age = blob_metadata.delete(:cache_control) =~ /max-age=(.*),/ && $1
|
244
|
+
max_age = max_age.to_i if max_age
|
245
|
+
CmsCacheStorage.cache.write(blob_metadata_cache_key(id), blob_metadata, expires_in: max_age)
|
246
|
+
end
|
247
|
+
|
248
|
+
def blob_metadata_cache_key(id)
|
249
|
+
"blob_metadata/#{Digest::SHA1.hexdigest(id)}" # id of a blob is a URI.
|
250
|
+
end
|
251
|
+
|
182
252
|
def find_obj_data_filtering_deleted_by(revision, index, keys, include_deleted)
|
183
253
|
index = index.to_s
|
184
254
|
assert_valid_index_name(index)
|
@@ -269,11 +339,6 @@ module Scrivito
|
|
269
339
|
ContentStateCaching.store_obj_data(revision.content_state, index, key, item)
|
270
340
|
end
|
271
341
|
|
272
|
-
def find_blob_data_from_database_by(id)
|
273
|
-
@query_counter += 1
|
274
|
-
ContentService.query('blobs/query', :blob_ids => [id])['blobs'][id]
|
275
|
-
end
|
276
|
-
|
277
342
|
def assert_valid_index_name(index)
|
278
343
|
raise ArgumentError, "invalid index name '#{index}'" unless VALID_INDEX_NAMES.include?(index)
|
279
344
|
end
|