scrivito_sdk 0.17.0 → 0.18.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.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/app/controllers/scrivito/default_cms_controller.rb +15 -3
- data/app/controllers/scrivito/objs_controller.rb +61 -25
- data/app/controllers/scrivito/users_controller.rb +7 -0
- data/app/controllers/scrivito/webservice_controller.rb +17 -7
- data/app/controllers/scrivito/workspaces_controller.rb +85 -17
- data/app/helpers/scrivito/default_cms_routing_helper.rb +3 -3
- data/config/routes.rb +4 -1
- data/lib/assets/javascripts/scrivito_editing.js +4182 -508
- data/lib/assets/stylesheets/scrivito_editing.css +489 -13
- data/lib/generators/cms/migration/templates/migration.erb +4 -4
- data/lib/scrivito/attribute_collection.rb +1 -6
- data/lib/scrivito/attribute_content.rb +29 -7
- data/lib/scrivito/basic_obj.rb +91 -61
- data/lib/scrivito/basic_widget.rb +0 -11
- data/lib/scrivito/client_config.rb +40 -25
- data/lib/scrivito/cms_backend.rb +54 -0
- data/lib/scrivito/cms_cache_storage.rb +8 -0
- data/lib/scrivito/cms_field_tag.rb +2 -1
- data/lib/scrivito/cms_rest_api.rb +9 -0
- data/lib/scrivito/configuration.rb +4 -2
- data/lib/scrivito/content_state.rb +8 -0
- data/lib/scrivito/content_state_caching.rb +20 -0
- data/lib/scrivito/editing_context.rb +35 -34
- data/lib/scrivito/membership.rb +22 -3
- data/lib/scrivito/memberships_collection.rb +8 -4
- data/lib/scrivito/obj_class.rb +45 -100
- data/lib/scrivito/obj_class_collection.rb +53 -0
- data/lib/scrivito/obj_class_data.rb +33 -0
- data/lib/scrivito/obj_data.rb +26 -48
- data/lib/scrivito/obj_data_from_hash.rb +5 -5
- data/lib/scrivito/obj_data_from_service.rb +9 -3
- data/lib/scrivito/obj_search_builder.rb +0 -5
- data/lib/scrivito/obj_search_enumerator.rb +3 -20
- data/lib/scrivito/objs_collection.rb +7 -0
- data/lib/scrivito/restriction_set.rb +2 -2
- data/lib/scrivito/user.rb +89 -23
- data/lib/scrivito/user_definition.rb +73 -70
- data/lib/scrivito/workspace.rb +52 -8
- data/lib/scrivito/workspace/publish_checker.rb +126 -0
- metadata +6 -2
@@ -1,63 +1,67 @@
|
|
1
1
|
module Scrivito
|
2
|
-
# @api
|
3
|
-
class UserDefinition
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# Allows user to do everything.
|
9
|
-
# @api beta
|
10
|
-
ADMINISTRATE_CMS_ABILITY = 'administrate_cms'
|
11
|
-
|
12
|
-
# @api beta
|
13
|
-
ABILITY_NAMES = [
|
14
|
-
ADMINISTRATE_CMS_ABILITY,
|
15
|
-
PUBLISH_WORKSPACE_ABILITY,
|
16
|
-
]
|
2
|
+
# @api public
|
3
|
+
class UserDefinition
|
4
|
+
def initialize(user_id)
|
5
|
+
@user_id = user_id
|
6
|
+
@explicit_rules = {}
|
7
|
+
end
|
17
8
|
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# @
|
21
|
-
# @param [
|
22
|
-
# @
|
23
|
-
# @
|
24
|
-
# @
|
25
|
-
# @
|
26
|
-
#
|
27
|
-
# @
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
9
|
+
# Adds an explicit rule, that allows the user to _always_ execute an action.
|
10
|
+
# A rule consists of a verb of the action, the subject of the action and an optional message.
|
11
|
+
# @api public
|
12
|
+
# @param [Symbol] verb the verb of the action (see {Scrivito::User::VERBS}).
|
13
|
+
# @param [Symbol] subject the subject of the action. At the moment only +:workspace+ is supported.
|
14
|
+
# @param [String] message optional message to be displayed in the UI.
|
15
|
+
# @raise [Scrivito::ScrivitoError] if the given verb is invalid
|
16
|
+
# @raise [Scrivito::ScrivitoError] if the specified rule conflicts with a rule specified with
|
17
|
+
# {Scrivito::UserDefinition#can_never}.
|
18
|
+
# @note Normally the memberships of a workspace decide whether a user is allowed or not to
|
19
|
+
# execute a specific action. This method allows to add an exception to this logic and thus
|
20
|
+
# should be used carefully.
|
21
|
+
# @see Scrivito::User::VERBS
|
22
|
+
# @see Scrivito::UserDefinition#can_never
|
23
|
+
# @example User can _always_ read, write and publish a workspace, ignoring the memberships.
|
24
|
+
# Scrivito::User.define('alice') do |user|
|
25
|
+
# user.can_always(:read, :workspace)
|
26
|
+
# user.can_always(:write, :workspace)
|
27
|
+
# user.can_always(:publish, :workspace, 'You can always publish a workspace.)
|
33
28
|
# end
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
def can_always(verb, subject, message = nil)
|
30
|
+
assert_no_conflict(:can_never, verb, subject)
|
31
|
+
@explicit_rules[[:can_always, verb, subject]] = message
|
32
|
+
end
|
33
|
+
|
34
|
+
# Adds an explicit rule, that forbids the user to execute an action.
|
35
|
+
# A rule consists of a verb of the action, the subject of the action and an optional message.
|
36
|
+
# @api public
|
37
|
+
# @param [Symbol] verb the verb of the action (see {Scrivito::User::VERBS}).
|
38
|
+
# @param [Symbol] subject the subject of the action. At the moment only +:workspace+ is supported.
|
39
|
+
# @param [String] message optional message to be displayed in the UI.
|
40
|
+
# @raise [Scrivito::ScrivitoError] if the given verb is invalid
|
41
|
+
# @raise [Scrivito::ScrivitoError] if the specified rule conflicts with a rule specified with
|
42
|
+
# {Scrivito::UserDefinition#can_always}.
|
43
|
+
# @note Normally the memberships of a workspace decide whether a user is allowed or not to
|
44
|
+
# execute a specific action. This method allows to add an exception to this logic and thus
|
45
|
+
# should be used carefully.
|
46
|
+
# @see Scrivito::User::VERBS
|
47
|
+
# @see Scrivito::UserDefinition#can_always
|
48
|
+
# @example User can _never_ publish a workspace, even if she's a workspace owner.
|
49
|
+
# Scrivito::User.define('alice') do |user|
|
50
|
+
# user.can_never(:publish, :workspace, 'You can not publish workspaces.')
|
37
51
|
# end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# allowed_user = 'alice'
|
42
|
-
# # The user `alice` will now be allowed to publish workspace,
|
43
|
-
# # but the user `bob` will still be not allowed.
|
44
|
-
#
|
45
|
-
# allowed_user = 'bob'
|
46
|
-
# # The user `bob` will now be allowed to publish workspace,
|
47
|
-
# # but the user `alice` will be not allowed again.
|
48
|
-
def can(ability_name, &ability_proc)
|
49
|
-
assert_valid_ability(ability_name, ability_proc)
|
50
|
-
abilities[ability_name] = ability_proc
|
52
|
+
def can_never(verb, subject, message = nil)
|
53
|
+
assert_no_conflict(:can_always, verb, subject)
|
54
|
+
@explicit_rules[[:can_never, verb, subject]] = message
|
51
55
|
end
|
52
56
|
|
53
57
|
# Defines the user description to be displayed, when the user is shown in the in-place GUI.
|
54
|
-
# @api
|
58
|
+
# @api public
|
55
59
|
# @param [Proc] description_proc proc to calculate the description. Defaults to the the user id.
|
56
60
|
# @note The description is calculated "lazy".
|
57
61
|
# @note The calculated description will be cached.
|
58
62
|
# @see Scrivito::User.define
|
59
63
|
# @example
|
60
|
-
# alice = Scrivito::User.define('alice')
|
64
|
+
# alice = Scrivito::User.define('alice')
|
61
65
|
# # User `alice` will be displayed as "alice" in the in-place GUI.
|
62
66
|
#
|
63
67
|
# bob = Scrivito::User.define('bob') do |user|
|
@@ -70,7 +74,9 @@ module Scrivito
|
|
70
74
|
|
71
75
|
# Defines the proc for fetching users for the user autocompletion of the in-place GUI.
|
72
76
|
# The user autocompletion is for example used in the details dialog of a workspace.
|
73
|
-
#
|
77
|
+
# If the proc is not set, then {Scrivito::User.find} will be used to fetch the suggested users with input
|
78
|
+
# as the user id.
|
79
|
+
# @api public
|
74
80
|
# @param [Proc] suggest_users_proc proc for fetching users to be suggested in the in-place GUI
|
75
81
|
# @yieldparam [String] input an arbitrary string from the input field of a user autocompletion,
|
76
82
|
# e.g. the first letters of a user name
|
@@ -91,25 +97,25 @@ module Scrivito
|
|
91
97
|
@suggest_users_proc = suggest_users_proc
|
92
98
|
end
|
93
99
|
|
94
|
-
# Lets you restrict the
|
100
|
+
# Lets you restrict the rule of a user to publish a certain object. Each
|
95
101
|
# registered callback can access a certain attribute of an object. Multiple
|
96
102
|
# callbacks are possible
|
97
103
|
#
|
98
|
-
# @api
|
104
|
+
# @api public
|
99
105
|
# @param [Hash] options
|
100
|
-
# @option options [Symbol] :
|
106
|
+
# @option options [Symbol] :using the attribute you need in the callback
|
101
107
|
# @yield [attribute] the value of the specified attribute
|
102
108
|
# @yieldreturn [String, false] either return a message for the user or false if
|
103
109
|
# no restriction is needed
|
104
110
|
#
|
105
111
|
# @note the callback is only called with {BasicObj Objs} that have the attribute
|
106
|
-
# specified by the :
|
112
|
+
# specified by the :using option and if it is not a {BasicWidget Widget}-attribute
|
107
113
|
#
|
108
114
|
# @example
|
109
115
|
# class MyUserModel
|
110
116
|
# def to_scrivito_user
|
111
117
|
# Scrivito::User.define(id) do |user|
|
112
|
-
# user.restrict_obj_publish(
|
118
|
+
# user.restrict_obj_publish(using: :_path) do |path|
|
113
119
|
# if path.start_with?("/en")
|
114
120
|
# false
|
115
121
|
# else
|
@@ -117,11 +123,11 @@ module Scrivito
|
|
117
123
|
# end
|
118
124
|
# end
|
119
125
|
#
|
120
|
-
# user.restrict_obj_publish(
|
121
|
-
# if obj_class ==
|
126
|
+
# user.restrict_obj_publish(using: :_obj_class) do |obj_class|
|
127
|
+
# if obj_class.name == 'BlogPost'
|
122
128
|
# false
|
123
129
|
# else
|
124
|
-
#
|
130
|
+
# 'You are only allowed to edit Blog Posts'
|
125
131
|
# end
|
126
132
|
# end
|
127
133
|
# end
|
@@ -132,8 +138,13 @@ module Scrivito
|
|
132
138
|
end
|
133
139
|
|
134
140
|
def user
|
135
|
-
User.new(
|
136
|
-
|
141
|
+
User.new(
|
142
|
+
id: @user_id,
|
143
|
+
explicit_rules: @explicit_rules,
|
144
|
+
description_proc: @description_proc,
|
145
|
+
suggest_users_proc: @suggest_users_proc,
|
146
|
+
restriction_set: restriction_set
|
147
|
+
)
|
137
148
|
end
|
138
149
|
|
139
150
|
private
|
@@ -142,17 +153,9 @@ module Scrivito
|
|
142
153
|
@restriction_set ||= RestrictionSet.new
|
143
154
|
end
|
144
155
|
|
145
|
-
def
|
146
|
-
@
|
147
|
-
|
148
|
-
|
149
|
-
def assert_valid_ability(ability_name, ability_proc)
|
150
|
-
unless ABILITY_NAMES.include?(ability_name.to_s)
|
151
|
-
raise ScrivitoError.new("'#{ability_name}' is not a valid ability name")
|
152
|
-
end
|
153
|
-
|
154
|
-
unless ability_proc
|
155
|
-
raise ScrivitoError.new("No proc given for ability '#{ability_name}'")
|
156
|
+
def assert_no_conflict(type, verb, subject)
|
157
|
+
if @explicit_rules.has_key?([type, verb, subject])
|
158
|
+
raise ScrivitoError.new("Conflicting rules for verb '#{verb}' and subject '#{subject}'")
|
156
159
|
end
|
157
160
|
end
|
158
161
|
end
|
data/lib/scrivito/workspace.rb
CHANGED
@@ -9,6 +9,8 @@ class Workspace
|
|
9
9
|
|
10
10
|
include ModelIdentity
|
11
11
|
|
12
|
+
PublishPreventedDueToContentChange = Class.new(ScrivitoError)
|
13
|
+
|
12
14
|
# Set the currently used workspace
|
13
15
|
# @api public
|
14
16
|
# @param [Scrivito::Workspace] workspace
|
@@ -108,7 +110,17 @@ class Workspace
|
|
108
110
|
# @api public
|
109
111
|
def reload
|
110
112
|
@workspace_data = CmsBackend.instance.find_workspace_data_by_id(self.id)
|
111
|
-
|
113
|
+
|
114
|
+
# Clear all cached instance variables.
|
115
|
+
@base_revision = nil
|
116
|
+
@memberships = nil
|
117
|
+
@revision = nil
|
118
|
+
end
|
119
|
+
|
120
|
+
def api_request(verb, path, payload = nil)
|
121
|
+
response = CmsRestApi.public_send(verb, "#{backend_url}#{path}", payload)
|
122
|
+
reload if [:post, :put, :delete].include?(verb)
|
123
|
+
response
|
112
124
|
end
|
113
125
|
|
114
126
|
# Updates this workspace's attributes
|
@@ -117,8 +129,7 @@ class Workspace
|
|
117
129
|
# @return [Scrivito::Workspace]
|
118
130
|
def update(attributes)
|
119
131
|
CmsRestApi.put(backend_url, workspace: attributes)
|
120
|
-
|
121
|
-
self.reload
|
132
|
+
reload
|
122
133
|
end
|
123
134
|
|
124
135
|
# Destroy this workspace
|
@@ -131,17 +142,24 @@ class Workspace
|
|
131
142
|
# Publish the changes of this workspace
|
132
143
|
# @api public
|
133
144
|
def publish
|
134
|
-
|
145
|
+
internal_publish
|
146
|
+
end
|
135
147
|
|
136
|
-
|
148
|
+
def conditional_publish
|
149
|
+
internal_publish(if_content_state_id_equals: content_state.content_state_id)
|
150
|
+
rescue Scrivito::ClientError => e
|
151
|
+
if e.message.starts_with?('The specified condition for content_state_id')
|
152
|
+
raise PublishPreventedDueToContentChange.new(e.message)
|
153
|
+
else
|
154
|
+
raise e
|
155
|
+
end
|
137
156
|
end
|
138
157
|
|
139
158
|
# Rebases the current workspace on the published content
|
140
159
|
# @api public
|
141
160
|
def rebase
|
142
161
|
CmsRestApi.put("#{backend_url}/rebase", {})
|
143
|
-
|
144
|
-
self.reload
|
162
|
+
reload
|
145
163
|
end
|
146
164
|
|
147
165
|
# Returns the id of the workspace
|
@@ -162,7 +180,7 @@ class Workspace
|
|
162
180
|
@workspace_data.title
|
163
181
|
end
|
164
182
|
|
165
|
-
# @api
|
183
|
+
# @api public
|
166
184
|
# Returns the members of this workspace and their roles
|
167
185
|
#
|
168
186
|
# @return [MembershipsCollection]
|
@@ -216,12 +234,38 @@ class Workspace
|
|
216
234
|
@objs ||= ObjsCollection.new(self)
|
217
235
|
end
|
218
236
|
|
237
|
+
# Returns all obj classes of this working copy.
|
238
|
+
#
|
239
|
+
# @api public
|
240
|
+
#
|
241
|
+
# @example Find the obj class named "Homepage" in the "rtc" {Workspace}.
|
242
|
+
# Workspace.find('rtc').obj_classes['Homepage']
|
243
|
+
#
|
244
|
+
# @return {ObjClassCollection}
|
245
|
+
def obj_classes
|
246
|
+
@obj_classes ||= ObjClassCollection.new(self)
|
247
|
+
end
|
248
|
+
|
219
249
|
def inspect
|
220
250
|
"<#{self.class} id=\"#{id}\" title=\"#{title}\">"
|
221
251
|
end
|
222
252
|
|
253
|
+
def as_json(options = {})
|
254
|
+
{
|
255
|
+
id: id,
|
256
|
+
title: title,
|
257
|
+
memberships: memberships,
|
258
|
+
}
|
259
|
+
end
|
260
|
+
|
223
261
|
private
|
224
262
|
|
263
|
+
def internal_publish(data={})
|
264
|
+
CmsRestApi.put("#{backend_url}/publish", data)
|
265
|
+
|
266
|
+
reset_workspace_if_current
|
267
|
+
end
|
268
|
+
|
225
269
|
def backend_url
|
226
270
|
"/workspaces/#{id}"
|
227
271
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Scrivito
|
2
|
+
class Workspace
|
3
|
+
class PublishChecker < Struct.new(:workspace, :user)
|
4
|
+
MAX_EXECUTION_TIME = (0.5).second
|
5
|
+
|
6
|
+
def passing_certificates?(certificates)
|
7
|
+
begin
|
8
|
+
responses = decrypt_responses(certificates).map do |response|
|
9
|
+
response.with_indifferent_access
|
10
|
+
end
|
11
|
+
|
12
|
+
return false unless responses.all? do |response|
|
13
|
+
raise_invalid_certificates_error if response[:content_state_id].nil?
|
14
|
+
|
15
|
+
response[:content_state_id] == workspace.content_state.content_state_id
|
16
|
+
end
|
17
|
+
|
18
|
+
assert_passing_result(responses)
|
19
|
+
true
|
20
|
+
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
21
|
+
raise_invalid_certificates_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def call(offset)
|
26
|
+
batch_size = Configuration.check_batch_size
|
27
|
+
objs, changed_obj_count = fetch_objs_and_count(offset, batch_size)
|
28
|
+
passed, objs = compute_publishable(objs)
|
29
|
+
|
30
|
+
if passed
|
31
|
+
passing_result(objs, changed_obj_count, offset)
|
32
|
+
else
|
33
|
+
failing_result
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def decrypt_responses(certificates)
|
40
|
+
certificates.map(&message_verifier.method(:verify))
|
41
|
+
end
|
42
|
+
|
43
|
+
def fetch_objs_and_count(offset, batch_size)
|
44
|
+
enumerator = workspace.objs.changes(offset, batch_size)
|
45
|
+
[enumerator.take(batch_size), enumerator.size]
|
46
|
+
end
|
47
|
+
|
48
|
+
def passing_result(objs, changed_obj_count, offset)
|
49
|
+
until_element = offset + objs.size - 1
|
50
|
+
until_element = 'END' if until_element >= (changed_obj_count - 1)
|
51
|
+
|
52
|
+
pass_sub_hash = {
|
53
|
+
workspace_id: workspace.id,
|
54
|
+
content_state_id: workspace.content_state.content_state_id,
|
55
|
+
from: offset,
|
56
|
+
until: until_element,
|
57
|
+
}
|
58
|
+
|
59
|
+
{ result: 'pass', pass: pass_sub_hash, certificate: sign(pass_sub_hash) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def compute_publishable(objs)
|
63
|
+
start_time = Time.now
|
64
|
+
result = []
|
65
|
+
|
66
|
+
objs.each do |obj|
|
67
|
+
if publishable?(obj)
|
68
|
+
result << obj
|
69
|
+
else
|
70
|
+
return false, []
|
71
|
+
end
|
72
|
+
|
73
|
+
break if (Time.now - start_time) > MAX_EXECUTION_TIME
|
74
|
+
end
|
75
|
+
|
76
|
+
return true, result
|
77
|
+
end
|
78
|
+
|
79
|
+
def failing_result
|
80
|
+
{result: 'fail' }
|
81
|
+
end
|
82
|
+
|
83
|
+
def publishable?(obj)
|
84
|
+
obj.publishable? && user.can_publish?(obj)
|
85
|
+
end
|
86
|
+
|
87
|
+
def sign(object)
|
88
|
+
message_verifier.generate(object)
|
89
|
+
end
|
90
|
+
|
91
|
+
def message_verifier
|
92
|
+
@message_verifier ||= ActiveSupport::MessageVerifier.new(
|
93
|
+
Rails.application.secrets.secret_key_base, serializer: JSON
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
def assert_passing_result(responses)
|
98
|
+
sorted_responses = responses.sort_by do |response|
|
99
|
+
response[:from].to_i
|
100
|
+
end
|
101
|
+
|
102
|
+
last_until = sorted_responses.inject(-1) do |last_until, response|
|
103
|
+
if last_until == 'END'
|
104
|
+
raise_invalid_certificates_error
|
105
|
+
elsif (last_until + 1) == response[:from].to_i
|
106
|
+
if response[:until] == 'END'
|
107
|
+
'END'
|
108
|
+
else
|
109
|
+
response[:until].to_i
|
110
|
+
end
|
111
|
+
else
|
112
|
+
raise_invalid_certificates_error
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
if last_until != 'END'
|
117
|
+
raise_invalid_certificates_error
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def raise_invalid_certificates_error
|
122
|
+
raise ScrivitoError, 'Invalid certificates'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scrivito_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Infopark AG
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -149,6 +149,7 @@ files:
|
|
149
149
|
- app/controllers/scrivito/default_cms_controller.rb
|
150
150
|
- app/controllers/scrivito/objs_controller.rb
|
151
151
|
- app/controllers/scrivito/tasks_controller.rb
|
152
|
+
- app/controllers/scrivito/users_controller.rb
|
152
153
|
- app/controllers/scrivito/webservice_controller.rb
|
153
154
|
- app/controllers/scrivito/workspaces_controller.rb
|
154
155
|
- app/helpers/cms_helper.rb
|
@@ -254,6 +255,8 @@ files:
|
|
254
255
|
- lib/scrivito/named_link.rb
|
255
256
|
- lib/scrivito/network_error.rb
|
256
257
|
- lib/scrivito/obj_class.rb
|
258
|
+
- lib/scrivito/obj_class_collection.rb
|
259
|
+
- lib/scrivito/obj_class_data.rb
|
257
260
|
- lib/scrivito/obj_data.rb
|
258
261
|
- lib/scrivito/obj_data_from_hash.rb
|
259
262
|
- lib/scrivito/obj_data_from_service.rb
|
@@ -273,6 +276,7 @@ files:
|
|
273
276
|
- lib/scrivito/widget_field_params.rb
|
274
277
|
- lib/scrivito/widget_garbage_collection.rb
|
275
278
|
- lib/scrivito/workspace.rb
|
279
|
+
- lib/scrivito/workspace/publish_checker.rb
|
276
280
|
- lib/scrivito/workspace_data_from_service.rb
|
277
281
|
- lib/scrivito/workspace_selection_middleware.rb
|
278
282
|
- lib/scrivito_sdk.rb
|