infopark_cloud_connector 6.9.1.3.22208381 → 6.9.2.1.125136549
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.
- data/app/controllers/rails_connector/blobs_controller.rb +1 -1
- data/app/controllers/rails_connector/objs_controller.rb +29 -9
- data/app/controllers/rails_connector/tasks_controller.rb +1 -1
- data/app/controllers/rails_connector/widget_renderer.rb +66 -0
- data/app/controllers/rails_connector/workspaces_controller.rb +9 -5
- data/app/helpers/rails_connector/cms_tag_helper.rb +40 -12
- data/app/views/rails_connector/objs/create_widget.html.erb +1 -1
- data/app/views/rails_connector/objs/show.html.erb +1 -0
- data/config/routes.rb +1 -1
- data/lib/assets/javascripts/infopark_editing.js +5598 -3254
- data/lib/assets/stylesheets/infopark_editing.css +366 -311
- data/lib/generators/cms/migration/templates/migration.rb +7 -9
- data/lib/rails_connector/backend_not_available.rb +1 -1
- data/lib/rails_connector/basic_obj.rb +10 -21
- data/lib/rails_connector/cache.rb +1 -1
- data/lib/rails_connector/cms_cache_storage.rb +10 -1
- data/lib/rails_connector/cms_rest_api.rb +80 -40
- data/lib/rails_connector/content_service.rb +1 -1
- data/lib/rails_connector/date_attribute.rb +1 -1
- data/lib/rails_connector/link.rb +0 -4
- data/lib/rails_connector/migrations/migration_dsl.rb +116 -12
- data/lib/rails_connector/migrations/migrator.rb +0 -1
- data/lib/rails_connector/workspace.rb +1 -1
- metadata +5 -7
- data/lib/rails_connector/cms_api_search_request.rb +0 -50
- data/lib/rails_connector/default_search_request.rb +0 -6
- data/lib/rails_connector/elasticsearch_request.rb +0 -78
- data/lib/rails_connector/widget_renderer.rb +0 -41
@@ -1,17 +1,15 @@
|
|
1
1
|
class <%= class_name %> < ::RailsConnector::Migration
|
2
2
|
def up
|
3
|
-
# get_attribute('test')
|
4
|
-
# create_attribute(:name => 'test', :type => :string)
|
5
|
-
# update_attribute('test', :title => 'Test Title')
|
6
|
-
# delete_attribute('test')
|
7
|
-
|
8
3
|
# get_obj_class('Test')
|
9
|
-
# create_obj_class(:
|
10
|
-
# update_obj_class('Test', :
|
4
|
+
# create_obj_class(name: 'Test', type: :publication, attributes: [])
|
5
|
+
# update_obj_class('Test', title: 'Test Title')
|
6
|
+
# add_attribute_to('Test', { name: 'test', type: 'string' })
|
7
|
+
# update_attribute_for('Test', 'test', { title: 'New Title' })
|
8
|
+
# delete_attribute_from('Test', 'test')
|
11
9
|
|
12
10
|
# get_obj('a1b2c3')
|
13
|
-
# create_obj(:
|
14
|
-
# update_obj('a1b2c3', :
|
11
|
+
# create_obj(_path: '/test', _obj_class: 'Test')
|
12
|
+
# update_obj('a1b2c3', title: 'Test Title')
|
15
13
|
# delete_obj('a1b2c3')
|
16
14
|
end
|
17
15
|
end
|
@@ -8,7 +8,6 @@ module RailsConnector
|
|
8
8
|
extend ActiveModel::Naming
|
9
9
|
|
10
10
|
include DateAttribute
|
11
|
-
include SEO
|
12
11
|
include ModelIdentity
|
13
12
|
|
14
13
|
# Create a new Obj instance with the given values and attributes.
|
@@ -343,12 +342,11 @@ module RailsConnector
|
|
343
342
|
object_type == :document
|
344
343
|
end
|
345
344
|
|
346
|
-
# Returns true if this object is active
|
345
|
+
# Returns true if this object is active.
|
347
346
|
# @api public
|
348
|
-
def active?
|
347
|
+
def active?
|
349
348
|
return false unless valid_from
|
350
|
-
|
351
|
-
valid_from <= time_then && (!valid_until || time_then <= valid_until)
|
349
|
+
valid_from <= Time.now && (!valid_until || Time.now <= valid_until)
|
352
350
|
end
|
353
351
|
|
354
352
|
# compatibility with legacy apps.
|
@@ -365,8 +363,8 @@ module RailsConnector
|
|
365
363
|
end
|
366
364
|
|
367
365
|
# Returns true if the export of the object is not suppressed and the content is active?
|
368
|
-
def exportable?
|
369
|
-
!suppressed? && active?
|
366
|
+
def exportable?
|
367
|
+
!suppressed? && active?
|
370
368
|
end
|
371
369
|
|
372
370
|
# Returns the file name to which the Content.file_extension has been appended.
|
@@ -404,8 +402,7 @@ module RailsConnector
|
|
404
402
|
# @api public
|
405
403
|
def toclist(*args)
|
406
404
|
return [] unless publication?
|
407
|
-
|
408
|
-
toclist = children.select{ |toc| toc.exportable?(time) }
|
405
|
+
toclist = children.select{ |toc| toc.exportable? }
|
409
406
|
toclist = toclist.reject { |toc| toc.binary? } unless args.include?(:all)
|
410
407
|
toclist
|
411
408
|
end
|
@@ -638,10 +635,6 @@ module RailsConnector
|
|
638
635
|
end
|
639
636
|
end
|
640
637
|
|
641
|
-
def to_liquid
|
642
|
-
LiquidSupport::ObjDrop.new(self)
|
643
|
-
end
|
644
|
-
|
645
638
|
def respond_to?(method_id, include_private=false)
|
646
639
|
if has_attribute?(method_id)
|
647
640
|
true
|
@@ -650,14 +643,6 @@ module RailsConnector
|
|
650
643
|
end
|
651
644
|
end
|
652
645
|
|
653
|
-
def self.preview_time=(t)
|
654
|
-
Thread.current[:preview_time] = t
|
655
|
-
end
|
656
|
-
|
657
|
-
def self.preview_time
|
658
|
-
Thread.current[:preview_time] || Time.now
|
659
|
-
end
|
660
|
-
|
661
646
|
def inspect
|
662
647
|
"<#{self.class} id=\"#{id}\" path=\"#{path}\">"
|
663
648
|
end
|
@@ -697,6 +682,10 @@ module RailsConnector
|
|
697
682
|
CmsRestApi.delete("revisions/#{Workspace.current.revision_id}/objs/#{id}")
|
698
683
|
end
|
699
684
|
|
685
|
+
def widget_container
|
686
|
+
@widget_container ||= self.class.find(parent_path.split('/').last)
|
687
|
+
end
|
688
|
+
|
700
689
|
private
|
701
690
|
|
702
691
|
attr_accessor :data_from_cms
|
@@ -11,10 +11,19 @@ module CmsCacheStorage
|
|
11
11
|
@cache ||= begin
|
12
12
|
prefix = VERSION.dup
|
13
13
|
prefix.concat('-utf8') if String.new.encoding_aware?
|
14
|
-
Cache.new(fallback_backend:
|
14
|
+
Cache.new(fallback_backend: backend_cache, cache_prefix: prefix)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def backend_cache=(new_cache)
|
19
|
+
@backend_cache = new_cache
|
20
|
+
@cache = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def backend_cache
|
24
|
+
@backend_cache || Rails.cache
|
25
|
+
end
|
26
|
+
|
18
27
|
def read_workspace_data(workspace_id)
|
19
28
|
cache.read("workspace/#{workspace_id}")
|
20
29
|
end
|
@@ -19,23 +19,38 @@ module RailsConnector
|
|
19
19
|
#
|
20
20
|
# @example Delete an Obj:
|
21
21
|
# RailsConnector::CmsRestApi.delete('revisions/001384beff9e5845/objs/f4123622ff07b70b')
|
22
|
+
#
|
23
|
+
# @example Specify a poll interval (in seconds; default: 2) to use in case the response
|
24
|
+
# is a task reference response and the final response is polled for:
|
25
|
+
# RailsConnector::CmsRestApi.put('workspace/rtc/publish', nil, :interval => 10)
|
26
|
+
#
|
27
|
+
# @example Return immediately with the first response (without polling in case it is a
|
28
|
+
# task reference response):
|
29
|
+
# RailsConnector::CmsRestApi.task_unaware_request(:put, 'workspace/rtc/publish', nil)
|
30
|
+
#
|
22
31
|
class CmsRestApi
|
32
|
+
|
23
33
|
cattr_accessor :credentials
|
24
34
|
|
25
|
-
def self.get(resource_path, payload = nil)
|
26
|
-
request_cms_api(:get, resource_path, payload)
|
35
|
+
def self.get(resource_path, payload = nil, options = nil)
|
36
|
+
request_cms_api(:get, resource_path, payload, options)
|
27
37
|
end
|
28
38
|
|
29
|
-
def self.put(resource_path, payload)
|
30
|
-
request_cms_api(:put, resource_path, payload)
|
39
|
+
def self.put(resource_path, payload, options = nil)
|
40
|
+
request_cms_api(:put, resource_path, payload, options)
|
31
41
|
end
|
32
42
|
|
33
|
-
def self.post(resource_path, payload)
|
34
|
-
request_cms_api(:post, resource_path, payload)
|
43
|
+
def self.post(resource_path, payload, options = nil)
|
44
|
+
request_cms_api(:post, resource_path, payload, options)
|
35
45
|
end
|
36
46
|
|
37
|
-
def self.delete(resource_path, payload = nil)
|
38
|
-
request_cms_api(:delete, resource_path, payload)
|
47
|
+
def self.delete(resource_path, payload = nil, options = nil)
|
48
|
+
request_cms_api(:delete, resource_path, payload, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.task_unaware_request(method, resource_path, payload = nil)
|
52
|
+
raise "Unexpected method #{method}" unless [:delete, :get, :post, :put].include?(method)
|
53
|
+
response_for_request_cms_api(method, resource_path, payload)
|
39
54
|
end
|
40
55
|
|
41
56
|
# @param [Hash] value
|
@@ -44,48 +59,73 @@ module RailsConnector
|
|
44
59
|
@@credentials = value.symbolize_keys
|
45
60
|
end
|
46
61
|
|
47
|
-
|
62
|
+
class << self
|
48
63
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
64
|
+
private
|
65
|
+
|
66
|
+
def request_cms_api(action, resource_path, payload, options)
|
67
|
+
decoded = response_for_request_cms_api(action, resource_path, payload)
|
68
|
+
return decoded unless Hash === decoded
|
69
|
+
return decoded unless decoded.keys == ["task"]
|
70
|
+
task_data = decoded["task"]
|
71
|
+
return decoded unless Hash === task_data
|
72
|
+
task_path = "tasks/#{task_data["id"]}"
|
73
|
+
final_response(task_path, options)
|
74
|
+
end
|
54
75
|
|
55
|
-
|
76
|
+
def response_for_request_cms_api(action, resource_path, payload)
|
77
|
+
request_params = basic_request_params
|
78
|
+
request_params[:method] = action
|
79
|
+
request_params[:url] = url(resource_path)
|
80
|
+
request_params[:payload] = MultiJson.encode(payload) if payload.present?
|
56
81
|
MultiJson.decode(RestClient::Request.execute(request_params))
|
57
82
|
rescue RestClient::ExceptionWithResponse => e
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
83
|
+
http_code = e.http_code
|
84
|
+
if http_code == 403
|
85
|
+
raise AccessDenied.new(e.http_body)
|
86
|
+
elsif 400 <= http_code && http_code < 500
|
87
|
+
begin
|
88
|
+
specific_output = MultiJson.decode(e.http_body)['error']
|
89
|
+
rescue MultiJson::DecodeError
|
90
|
+
# fall through
|
91
|
+
else
|
92
|
+
raise ClientError.new(specific_output, http_code)
|
64
93
|
end
|
65
|
-
rescue MultiJson::DecodeError
|
66
94
|
end
|
95
|
+
raise BackendNotAvailable.new(e.http_body, http_code)
|
96
|
+
end
|
67
97
|
|
68
|
-
|
98
|
+
def final_response(task_path, options)
|
99
|
+
options ||= {}
|
100
|
+
wait = options[:interval].presence.try(:to_f) || 2
|
101
|
+
task_data = response = nil
|
102
|
+
loop do
|
103
|
+
sleep wait
|
104
|
+
task_data = response_for_request_cms_api(:get, task_path, nil)
|
105
|
+
break unless task_data["status"] == "open"
|
106
|
+
end
|
107
|
+
return task_data["result"] if task_data["status"] == "success"
|
108
|
+
message = task_data["message"] || "Missing error message in task response #{task_data}"
|
109
|
+
raise ClientError.new(message, 400)
|
69
110
|
end
|
70
|
-
end
|
71
111
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
{
|
80
|
-
:user => credentials[:login],
|
81
|
-
:password => credentials[:api_key],
|
82
|
-
:headers => headers,
|
83
|
-
}
|
84
|
-
end
|
112
|
+
def basic_request_params
|
113
|
+
headers = {
|
114
|
+
:content_type => :json,
|
115
|
+
:accept => :json,
|
116
|
+
}
|
117
|
+
headers[:host] = credentials[:http_host] if credentials[:http_host].present?
|
85
118
|
|
86
|
-
|
87
|
-
|
119
|
+
{
|
120
|
+
:user => credentials[:login],
|
121
|
+
:password => credentials[:api_key],
|
122
|
+
:headers => headers,
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def url(resource_path)
|
127
|
+
"#{credentials[:url]}/#{resource_path}"
|
128
|
+
end
|
88
129
|
end
|
89
130
|
end
|
90
|
-
|
91
131
|
end
|
@@ -107,7 +107,7 @@ class ContentService
|
|
107
107
|
elsif response.code == "429"
|
108
108
|
raise RateLimitExceeded.new(response["Retry-After"])
|
109
109
|
else
|
110
|
-
raise "Server responded with status code #{response.code}"
|
110
|
+
raise BackendNotAvailable.new("Server responded with status code #{response.code}", response.code)
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
data/lib/rails_connector/link.rb
CHANGED
@@ -7,7 +7,7 @@ module RailsConnector
|
|
7
7
|
#
|
8
8
|
# @example Create "test" Attribute
|
9
9
|
#
|
10
|
-
# create_attribute(:
|
10
|
+
# create_attribute(name: 'test', type: 'string')
|
11
11
|
#
|
12
12
|
# @param attributes [Hash] The attributes and their values of the new
|
13
13
|
# CMS attribute.
|
@@ -20,14 +20,94 @@ module RailsConnector
|
|
20
20
|
warn_deprecated __callee__, 'create_obj_class', 'update_obj_class'
|
21
21
|
endpoint = "revisions/#{Workspace.current.revision_id}/attributes"
|
22
22
|
|
23
|
-
CmsRestApi.post(endpoint, :
|
23
|
+
CmsRestApi.post(endpoint, attribute: attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Adds an attribute to an object class.
|
27
|
+
#
|
28
|
+
# @example Add "test" attribute to object class "Foo.
|
29
|
+
#
|
30
|
+
# add_attribute_to('Foo', { name: 'test', type: 'string' })
|
31
|
+
#
|
32
|
+
# @param obj_class_name [String] The class name of the object class.
|
33
|
+
# @param params [Hash] The definition of the new attribute.
|
34
|
+
#
|
35
|
+
# @return nothing
|
36
|
+
def add_attribute_to(obj_class_name, params)
|
37
|
+
attributes = get_obj_class(obj_class_name)['attributes']
|
38
|
+
attributes << params
|
39
|
+
|
40
|
+
update_obj_class(obj_class_name, attributes: attributes)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Deletes an attribute from an object class.
|
44
|
+
#
|
45
|
+
# @example Delete "test" attribute from object class "Foo.
|
46
|
+
#
|
47
|
+
# delete_attribute_from('Foo', 'test')
|
48
|
+
#
|
49
|
+
# @param obj_class_name [String] The class name of the object class.
|
50
|
+
# @param attribute_name [String] The name of the attribute that should be
|
51
|
+
# deleted.
|
52
|
+
#
|
53
|
+
# @return nothing
|
54
|
+
def delete_attribute_from(obj_class_name, attribute_name)
|
55
|
+
attributes = get_obj_class(obj_class_name)['attributes']
|
56
|
+
attributes = attributes.delete_if do |attribute|
|
57
|
+
# handle global and local attributes
|
58
|
+
name = attribute.is_a?(String) ? attribute : attribute['name']
|
59
|
+
|
60
|
+
name == attribute_name.to_s
|
61
|
+
end
|
62
|
+
|
63
|
+
update_obj_class(obj_class_name, attributes: attributes)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Updates an attribute for an object class. Turns local into global
|
67
|
+
# attribute if found.
|
68
|
+
#
|
69
|
+
# @example Update "test" attribute for object class "Foo.
|
70
|
+
#
|
71
|
+
# update_attribute_for('Foo', 'test', { title: 'New Title' })
|
72
|
+
#
|
73
|
+
# @param obj_class_name [String] The class name of the object class.
|
74
|
+
# @param attribute_name [String] The name of the attribute that should be
|
75
|
+
# updated.
|
76
|
+
# @param params [Hash] Hash of updated attributes.
|
77
|
+
#
|
78
|
+
# @return nothing
|
79
|
+
def update_attribute_for(obj_class_name, attribute_name, params)
|
80
|
+
attribute_name = attribute_name.to_s
|
81
|
+
attributes = get_obj_class(obj_class_name)['attributes']
|
82
|
+
found = false
|
83
|
+
|
84
|
+
attributes.each_with_index do |attribute, index|
|
85
|
+
name = attribute.is_a?(String) ? attribute : attribute['name']
|
86
|
+
|
87
|
+
if name == attribute_name
|
88
|
+
if attribute.is_a?(String)
|
89
|
+
attribute = get_attribute(attribute)
|
90
|
+
end
|
91
|
+
|
92
|
+
attributes[index] = attribute.merge(params.stringify_keys)
|
93
|
+
update_obj_class(obj_class_name, attributes: attributes)
|
94
|
+
|
95
|
+
found = true
|
96
|
+
|
97
|
+
break
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
unless found
|
102
|
+
raise ArgumentError.new("Object class '#{obj_class_name}' does not have attribute '#{attribute_name}'.")
|
103
|
+
end
|
24
104
|
end
|
25
105
|
|
26
106
|
# Creates a CMS object.
|
27
107
|
#
|
28
108
|
# @example Create "/test" Object
|
29
109
|
#
|
30
|
-
# create_obj(:
|
110
|
+
# create_obj(_path: '/test', _obj_class: 'Test')
|
31
111
|
#
|
32
112
|
# @param attributes [Hash] The attributes and their values of the new
|
33
113
|
# CMS object.
|
@@ -37,14 +117,14 @@ module RailsConnector
|
|
37
117
|
def create_obj(attributes = {})
|
38
118
|
endpoint = "revisions/#{Workspace.current.revision_id}/objs"
|
39
119
|
|
40
|
-
CmsRestApi.post(endpoint, :
|
120
|
+
CmsRestApi.post(endpoint, obj: attributes)
|
41
121
|
end
|
42
122
|
|
43
123
|
# Creates a CMS object class.
|
44
124
|
#
|
45
125
|
# @example Create "Test" Object Class
|
46
126
|
#
|
47
|
-
# create_obj_class(:
|
127
|
+
# create_obj_class(name: 'Test', type: 'publication')
|
48
128
|
#
|
49
129
|
# @param attributes [Hash] The attributes and their values of the new
|
50
130
|
# CMS object class.
|
@@ -54,7 +134,7 @@ module RailsConnector
|
|
54
134
|
def create_obj_class(attributes = {})
|
55
135
|
endpoint = "revisions/#{Workspace.current.revision_id}/obj_classes"
|
56
136
|
|
57
|
-
CmsRestApi.post(endpoint, :
|
137
|
+
CmsRestApi.post(endpoint, obj_class: attributes)
|
58
138
|
end
|
59
139
|
|
60
140
|
# Deletes a CMS attribute.
|
@@ -145,7 +225,7 @@ module RailsConnector
|
|
145
225
|
#
|
146
226
|
# @example Update the title of the "test" Attribute
|
147
227
|
#
|
148
|
-
# update_attribute(:
|
228
|
+
# update_attribute(title: 'Test Title')
|
149
229
|
#
|
150
230
|
# @param id [String] The ID of the attribute.
|
151
231
|
# @param attributes [Hash] The updated attributes and their values.
|
@@ -157,14 +237,14 @@ module RailsConnector
|
|
157
237
|
warn_deprecated __callee__, 'update_obj_class'
|
158
238
|
endpoint = "revisions/#{Workspace.current.revision_id}/attributes/#{id}"
|
159
239
|
|
160
|
-
CmsRestApi.put(endpoint, :
|
240
|
+
CmsRestApi.put(endpoint, attribute: attributes)
|
161
241
|
end
|
162
242
|
|
163
243
|
# Updates a CMS object.
|
164
244
|
#
|
165
245
|
# @example Update the title of the "a1b2c3" Object
|
166
246
|
#
|
167
|
-
# update_attribute('a1b2c3', :
|
247
|
+
# update_attribute('a1b2c3', title: 'Test Title')
|
168
248
|
#
|
169
249
|
# @param id [String] The ID of the CMS object.
|
170
250
|
# @param attributes [Hash] The updated attributes and their values.
|
@@ -174,14 +254,14 @@ module RailsConnector
|
|
174
254
|
def update_obj(id, attributes = {})
|
175
255
|
endpoint = "revisions/#{Workspace.current.revision_id}/objs/#{id}"
|
176
256
|
|
177
|
-
CmsRestApi.put(endpoint, :
|
257
|
+
CmsRestApi.put(endpoint, obj: attributes)
|
178
258
|
end
|
179
259
|
|
180
260
|
# Updates a CMS object class.
|
181
261
|
#
|
182
262
|
# @example Update the title of the "Test" Object Class
|
183
263
|
#
|
184
|
-
# update_obj_class('Test', :
|
264
|
+
# update_obj_class('Test', title: 'Test Title')
|
185
265
|
#
|
186
266
|
# @param id [String] The ID of the CMS object class.
|
187
267
|
# @param attributes [Hash] The updated attributes and their values.
|
@@ -191,7 +271,31 @@ module RailsConnector
|
|
191
271
|
def update_obj_class(id, attributes = {})
|
192
272
|
endpoint = "revisions/#{Workspace.current.revision_id}/obj_classes/#{id}"
|
193
273
|
|
194
|
-
CmsRestApi.put(endpoint, :
|
274
|
+
CmsRestApi.put(endpoint, obj_class: attributes)
|
275
|
+
end
|
276
|
+
|
277
|
+
# Uploads a file to the content store.
|
278
|
+
#
|
279
|
+
# @example Upload "image.png" and store it in an "Image" CMS object.
|
280
|
+
#
|
281
|
+
# filename = 'image.png'
|
282
|
+
# file = File.new(filename)
|
283
|
+
# blob = upload_file(file)
|
284
|
+
# create_obj(_path: "/resources/images/#{filename}", _obj_class: 'Image', blob: blob)
|
285
|
+
#
|
286
|
+
# @param file [IO] The file IO object that gets uploaded.
|
287
|
+
#
|
288
|
+
# @return The blob of the uploaded file that can be stored on a CMS object.
|
289
|
+
# @api public
|
290
|
+
def upload_file(file)
|
291
|
+
upload_permission = RailsConnector::CmsRestApi.get('blobs/upload_permission')
|
292
|
+
|
293
|
+
fields = upload_permission['fields'].map { |name, value| [name, value] }
|
294
|
+
fields << [:file, file]
|
295
|
+
|
296
|
+
RestClient.post(upload_permission['url'], fields)
|
297
|
+
|
298
|
+
upload_permission['blob']
|
195
299
|
end
|
196
300
|
|
197
301
|
private
|