snapimage 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +3 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/snapimage_generate_config +63 -0
- data/bin/snapimage_server +55 -0
- data/lib/snapimage.rb +24 -0
- data/lib/snapimage/config.rb +51 -0
- data/lib/snapimage/exceptions.rb +25 -0
- data/lib/snapimage/image/image.rb +96 -0
- data/lib/snapimage/image/image_name_utils.rb +131 -0
- data/lib/snapimage/middleware.rb +27 -0
- data/lib/snapimage/rack/request.rb +19 -0
- data/lib/snapimage/rack/request_file.rb +26 -0
- data/lib/snapimage/rack/response.rb +51 -0
- data/lib/snapimage/server.rb +50 -0
- data/lib/snapimage/server_actions/server_actions.authorize.rb +69 -0
- data/lib/snapimage/server_actions/server_actions.delete_resource_images.rb +23 -0
- data/lib/snapimage/server_actions/server_actions.generate_image.rb +167 -0
- data/lib/snapimage/server_actions/server_actions.list_resource_images.rb +23 -0
- data/lib/snapimage/server_actions/server_actions.sync_resource.rb +78 -0
- data/lib/snapimage/storage/storage.rb +120 -0
- data/lib/snapimage/storage/storage_server.local.rb +120 -0
- data/lib/snapimage/storage/storage_server.rb +110 -0
- data/lib/snapimage/version.rb +3 -0
- data/snapimage.gemspec +27 -0
- data/spec/acceptance/delete_resource_images_spec.rb +166 -0
- data/spec/acceptance/list_resource_images_spec.rb +158 -0
- data/spec/acceptance/modify_spec.rb +165 -0
- data/spec/acceptance/sync_spec.rb +260 -0
- data/spec/acceptance/upload_spec.rb +235 -0
- data/spec/snapimage/config_spec.rb +56 -0
- data/spec/snapimage/image/image_name_utils_spec.rb +127 -0
- data/spec/snapimage/image/image_spec.rb +71 -0
- data/spec/snapimage/middleware_spec.rb +27 -0
- data/spec/snapimage/rack/request_file_spec.rb +15 -0
- data/spec/snapimage/rack/request_spec.rb +52 -0
- data/spec/snapimage/rack/response_spec.rb +33 -0
- data/spec/snapimage/server_actions/server_actions.authorize_spec.rb +67 -0
- data/spec/snapimage/server_actions/server_actions.generate_image_spec.rb +146 -0
- data/spec/snapimage/server_actions/server_actions.sync_resource_spec.rb +91 -0
- data/spec/snapimage/server_spec.rb +55 -0
- data/spec/snapimage/storage/assets/local/resource_1/12345678-1x1-0x0x1x1-1x1-1.gif +0 -0
- data/spec/snapimage/storage/assets/local/resource_1/12345678-1x1-0x0x1x1-300x200-0.jpg +0 -0
- data/spec/snapimage/storage/assets/local/resource_1/12345678-1x1.png +0 -0
- data/spec/snapimage/storage/assets/local/resource_2/12345678-1x1-0x0x1x1-1x1-1.gif +0 -0
- data/spec/snapimage/storage/assets/local/resource_2/12345678-1x1-0x0x1x1-300x200-0.jpg +0 -0
- data/spec/snapimage/storage/assets/local/resource_2/12345678-1x1.png +0 -0
- data/spec/snapimage/storage/storage_server.local_spec.rb +150 -0
- data/spec/snapimage/storage/storage_server_spec.rb +97 -0
- data/spec/snapimage/storage/storage_spec.rb +49 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/assets/config.json +8 -0
- data/spec/support/assets/config.yml +9 -0
- data/spec/support/assets/stub-1x1.png +0 -0
- data/spec/support/assets/stub-2048x100.png +0 -0
- data/spec/support/assets/stub-300x200.png +0 -0
- metadata +272 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module SnapImage
|
2
|
+
# SnapImage API Rack Middleware to handle all SnapImage API calls.
|
3
|
+
class Middleware
|
4
|
+
# Arguments:
|
5
|
+
# * app:: Rack application
|
6
|
+
# * path:: The URL path to access the SnapImage API (defaults to "/snapimage_api")
|
7
|
+
# * config:: Filename of the YAML or JSON config file or a config Hash
|
8
|
+
def initialize(app, options = {})
|
9
|
+
@app = app
|
10
|
+
@path = options[:path] || "/snapimage_api"
|
11
|
+
# TODO: If no config is given, set defaults.
|
12
|
+
# For example, if it's a Rails app, set the filename to
|
13
|
+
# config/snapimage.yml.
|
14
|
+
raise SnapImage::MissingConfig, "Missing config." if options[:config].nil?
|
15
|
+
@config = SnapImage::Config.new(options[:config])
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
request = SnapImage::Request.new(env)
|
20
|
+
if request.path_info == @path
|
21
|
+
SnapImage::Server.new(request, @config).call
|
22
|
+
else
|
23
|
+
@app.call(env)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SnapImage
|
2
|
+
class Request < Rack::Request
|
3
|
+
def bad_request?
|
4
|
+
!(self.post? && self.POST["json"] && self.json["action"] && self.json["resource_identifier"])
|
5
|
+
end
|
6
|
+
|
7
|
+
# NOTE: Call bad_request? first to make sure there is json to parse.
|
8
|
+
def json
|
9
|
+
@json ||= JSON.parse(self.POST["json"])
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a SnapImage::RequestFile which encapsulates the file that Rack
|
13
|
+
# provides. Returns nil if there is no file.
|
14
|
+
def file
|
15
|
+
return nil unless self.POST["file"]
|
16
|
+
@file ||= SnapImage::RequestFile.new(self.POST["file"])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SnapImage
|
2
|
+
class RequestFile
|
3
|
+
# The file comes through Rack's request's POST like this:
|
4
|
+
# {
|
5
|
+
# :filename=>"jpeg.jpeg",
|
6
|
+
# :type=>"image/jpeg",
|
7
|
+
# :name=>"file",
|
8
|
+
# :tempfile=>#<File:/tmp/RackMultipart20120628-19317-1w4ouxp>,
|
9
|
+
# :head=>"Content-Disposition: form-data; name=\"file\"; filename=\"jpeg.jpeg\"\r\nContent-Type: image/jpeg\r\n"}
|
10
|
+
# }
|
11
|
+
def initialize(file)
|
12
|
+
@file = file
|
13
|
+
end
|
14
|
+
|
15
|
+
def file
|
16
|
+
@file[:tempfile]
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
return @type if @type
|
21
|
+
@type = File.extname(@file[:filename])[1..-1]
|
22
|
+
@type = "jpg" if type == "jpeg"
|
23
|
+
@type
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SnapImage
|
2
|
+
class Response < Rack::Response
|
3
|
+
attr_accessor :content_type, :template, :json
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@content_type = options[:content_type] || "text/json"
|
7
|
+
@template = options[:template] || "{{json}}"
|
8
|
+
@json = {}
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_success(info = {})
|
13
|
+
info[:message] ||= "Success"
|
14
|
+
@json = { status_code: 200 }.merge(info)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_bad_request
|
18
|
+
@json = { status_code: 400, message: "Bad Request" }
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_authorization_required
|
22
|
+
@json = { status_code: 401, message: "Authorization Required" }
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_authorization_failed
|
26
|
+
@json = { status_code: 402, message: "Authorization Failed" }
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_invalid_image_identifier
|
30
|
+
@json = { status_code: 403, message: "Invalid Image Identifier" }
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_invalid_resource_identifier
|
34
|
+
@json = { status_code: 404, message: "Invalid Resource Identifier" }
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_internal_server_error
|
38
|
+
@json = { status_code: 500, message: "Internal Server Error" }
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_not_implemented
|
42
|
+
@json = { status_code: 501, message: "Not Implemented" }
|
43
|
+
end
|
44
|
+
|
45
|
+
def finish
|
46
|
+
self.body = [@template.gsub(/{{json}}/, @json.to_json)]
|
47
|
+
self["Content-Type"] = @content_type
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module SnapImage
|
2
|
+
class Server
|
3
|
+
ACTIONS = ["generate_image", "sync_resource", "delete_resource_images", "list_resource_images"]
|
4
|
+
RESOURCE_ID_REGEXP = /^[a-z0-9_-]+(\/[a-z0-9_-]+)*$/
|
5
|
+
|
6
|
+
# Arguments:
|
7
|
+
# * request:: Rack::Request
|
8
|
+
def initialize(request, config)
|
9
|
+
@request = request
|
10
|
+
@config = config
|
11
|
+
@storage = @config.storage
|
12
|
+
end
|
13
|
+
|
14
|
+
# Handles the request and returns a Rack::Response.
|
15
|
+
def call
|
16
|
+
@response = SnapImage::Response.new
|
17
|
+
begin
|
18
|
+
raise SnapImage::BadRequest if @request.bad_request?
|
19
|
+
raise SnapImage::InvalidResourceIdentifier unless !!@request.json["resource_identifier"].match(SnapImage::Server::RESOURCE_ID_REGEXP)
|
20
|
+
@response.content_type = @request.json["response_content_type"] if @request.json["response_content_type"]
|
21
|
+
@response.template = @request.json["response_template"] if @request.json["response_template"]
|
22
|
+
action = @request.json["action"]
|
23
|
+
raise SnapImage::ActionNotImplemented unless ACTIONS.include?(action)
|
24
|
+
@response = get_action_class(action).new(@config, @request, @response).call
|
25
|
+
rescue SnapImage::BadRequest
|
26
|
+
@response.set_bad_request
|
27
|
+
rescue SnapImage::ActionNotImplemented
|
28
|
+
@response.set_not_implemented
|
29
|
+
rescue SnapImage::AuthorizationRequired
|
30
|
+
@response.set_authorization_required
|
31
|
+
rescue SnapImage::AuthorizationFailed
|
32
|
+
@response.set_authorization_failed
|
33
|
+
rescue SnapImage::InvalidImageIdentifier
|
34
|
+
@response.set_invalid_image_identifier
|
35
|
+
rescue SnapImage::InvalidResourceIdentifier
|
36
|
+
@response.set_invalid_resource_identifier
|
37
|
+
#rescue
|
38
|
+
#@response.set_internal_server_error
|
39
|
+
end
|
40
|
+
@response.finish
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def get_action_class(action)
|
46
|
+
klassname = action.split("_").map { |t| t.capitalize }.join("")
|
47
|
+
SnapImage::ServerActions.const_get(klassname)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module SnapImage
|
2
|
+
module ServerActions
|
3
|
+
module Authorize
|
4
|
+
def get_token(role)
|
5
|
+
@request.json["#{role}_security_token"]
|
6
|
+
end
|
7
|
+
|
8
|
+
# Arguments:
|
9
|
+
# * role:: Can be either :client or :server
|
10
|
+
def token_available?(role)
|
11
|
+
!!get_token(role)
|
12
|
+
end
|
13
|
+
|
14
|
+
# A string is generated using
|
15
|
+
# * role:: "client" or "server"
|
16
|
+
# * date:: Date in the format "YYYY-MM-DD"
|
17
|
+
# * salt:: A shared salt
|
18
|
+
# * resource_id:: The resource's identifier
|
19
|
+
# and concatenated as "role:date:salt:resource_id".
|
20
|
+
#
|
21
|
+
# A SHA1 digest is generated off of the string to create a token.
|
22
|
+
#
|
23
|
+
# 3 tokens are generated: [yesterday, today, tomorrow].
|
24
|
+
def generate_tokens(role)
|
25
|
+
salt = @config["security_salt"]
|
26
|
+
now = Time.now
|
27
|
+
yesterday = (now - 24*60*60).strftime("%Y-%m-%d")
|
28
|
+
today = now.strftime("%Y-%m-%d")
|
29
|
+
tomorrow = (now + 24*60*60).strftime("%Y-%m-%d")
|
30
|
+
resource_id = @request.json["resource_identifier"]
|
31
|
+
[
|
32
|
+
Digest::SHA1.hexdigest("#{role}:#{yesterday}:#{salt}:#{resource_id}"),
|
33
|
+
Digest::SHA1.hexdigest("#{role}:#{today}:#{salt}:#{resource_id}"),
|
34
|
+
Digest::SHA1.hexdigest("#{role}:#{tomorrow}:#{salt}:#{resource_id}")
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
# If "security_salt" is set in the config, authorization is performed.
|
39
|
+
#
|
40
|
+
# A string is generated using
|
41
|
+
# * role:: "client" or "server"
|
42
|
+
# * date:: Date in the format "YYYY-MM-DD"
|
43
|
+
# * salt:: A shared salt
|
44
|
+
# * resource_id:: The resource's identifier
|
45
|
+
# and concatenated as "role:date:salt:resource_id".
|
46
|
+
#
|
47
|
+
# A SHA1 digest is generated off of the string to create a token. A token
|
48
|
+
# for yesterday, today, and tomorrow are generated and used to compare
|
49
|
+
# with the security token.
|
50
|
+
#
|
51
|
+
# When authorization fails, an error is raised. Authorization can fail in
|
52
|
+
# 2 ways.
|
53
|
+
# * AuthorizationRequired:: The role's security token is missing
|
54
|
+
# * AuthorizationFailed:: The security token did not match the generated token
|
55
|
+
#
|
56
|
+
# If authorization is successful, true is returned.
|
57
|
+
#
|
58
|
+
# Arguments:
|
59
|
+
# * role:: Can be either :client or :server
|
60
|
+
def authorize(role)
|
61
|
+
if @config["security_salt"]
|
62
|
+
raise SnapImage::AuthorizationRequired unless token_available?(role)
|
63
|
+
raise SnapImage::AuthorizationFailed unless generate_tokens(role).include?(get_token(role))
|
64
|
+
end
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SnapImage
|
2
|
+
module ServerActions
|
3
|
+
class DeleteResourceImages
|
4
|
+
include SnapImage::ServerActions::Authorize
|
5
|
+
|
6
|
+
def initialize(config, request, response)
|
7
|
+
@config = config
|
8
|
+
@storage = config.storage
|
9
|
+
@request = request
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
authorize(:server)
|
15
|
+
@response.set_success(
|
16
|
+
message: "Delete Resource Images Successful",
|
17
|
+
deleted_image_urls: @storage.delete_resource_images(@request.json["resource_identifier"])
|
18
|
+
)
|
19
|
+
@response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
module SnapImage
|
2
|
+
module ServerActions
|
3
|
+
class GenerateImage
|
4
|
+
include SnapImage::ServerActions::Authorize
|
5
|
+
|
6
|
+
def initialize(config, request, response)
|
7
|
+
@config = config
|
8
|
+
@storage = config.storage
|
9
|
+
@request = request
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
authorize(:client)
|
15
|
+
if request_valid?
|
16
|
+
image = get_image_for_modification
|
17
|
+
parts = SnapImage::ImageNameUtils.get_image_name_parts(image.public_url)
|
18
|
+
result = modify_image(image)
|
19
|
+
modified_image = result[:image]
|
20
|
+
modified_image_name = result[:name]
|
21
|
+
stored_image = @storage.add_image(modified_image, modified_image_name, @request.json["resource_identifier"])
|
22
|
+
@response.set_success(
|
23
|
+
message: "Get Modified Image Successful",
|
24
|
+
image_url: stored_image.public_url,
|
25
|
+
image_width: stored_image.width,
|
26
|
+
image_height: stored_image.height
|
27
|
+
)
|
28
|
+
else
|
29
|
+
@response.set_bad_request
|
30
|
+
end
|
31
|
+
@response
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Returns true if the request is valid. False otherwise.
|
37
|
+
def request_valid?
|
38
|
+
source_image_defined?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns true if either "file" or JSON "url" is defined.
|
42
|
+
def source_image_defined?
|
43
|
+
!!(@request.file || @request.json["url"])
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns true if the image is being uploaded. False otherwise.
|
47
|
+
def upload?
|
48
|
+
@request.file || !@storage.local?(@request.json["url"])
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns true if cropping is required. False otherwise.
|
52
|
+
def crop?
|
53
|
+
@request.json["crop_x"] || @request.json["crop_y"] || @request.json["crop_width"] || @request.json["crop_height"]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns true if all the cropping values are defined. False otherwise.
|
57
|
+
def crop_valid?
|
58
|
+
@request.json["crop_x"] && @request.json["crop_y"] && @request.json["crop_width"] && @request.json["crop_height"]
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns true if resizing is required. False otherwise.
|
62
|
+
def resize?
|
63
|
+
@request.json["width"] || @request.json["height"]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns true if the image is too large and needs to be resized to fit.
|
67
|
+
# False otherwise.
|
68
|
+
def resize_to_fit?(image)
|
69
|
+
image.width > get_max_width || image.height > get_max_height
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns true if sharpening is required. False otherwise
|
73
|
+
def sharpen?
|
74
|
+
@request.json["sharpen"]
|
75
|
+
end
|
76
|
+
|
77
|
+
# Gets the max width. Takes the lesser of the JSON "max_width" or the
|
78
|
+
# server max width.
|
79
|
+
def get_max_width
|
80
|
+
server_max_width = @config["max_width"]
|
81
|
+
[(@request.json["max_width"] && @request.json["max_width"].to_i || server_max_width), server_max_width].min
|
82
|
+
end
|
83
|
+
|
84
|
+
# Gets the max height. Takes the lesser of the JSON "max_height" or the
|
85
|
+
# server max height.
|
86
|
+
def get_max_height
|
87
|
+
server_max_height = @config["max_height"]
|
88
|
+
[(@request.json["max_height"] && @request.json["max_height"].to_i || server_max_height), server_max_height].min
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_image_for_modification
|
92
|
+
if upload?
|
93
|
+
# Add the image to the storage.
|
94
|
+
if @request.file
|
95
|
+
image = @storage.add_upload(@request.file, @request.json["resource_identifier"])
|
96
|
+
else
|
97
|
+
image = @storage.add_url(@request.json["url"], @request.json["resource_identifier"])
|
98
|
+
end
|
99
|
+
else
|
100
|
+
# Get the base image.
|
101
|
+
raise SnapImage::InvalidImageIdentifier unless SnapImage::ImageNameUtils.valid?(@request.json["url"])
|
102
|
+
image = @storage.get(SnapImage::ImageNameUtils.get_base_image_path(@request.json["url"]))
|
103
|
+
end
|
104
|
+
image
|
105
|
+
end
|
106
|
+
|
107
|
+
# Arguments:
|
108
|
+
# * image:: SnapImage::Image object that represents the base image
|
109
|
+
def modify_image(image)
|
110
|
+
parts = SnapImage::ImageNameUtils.get_image_name_parts(image.public_url)
|
111
|
+
|
112
|
+
# Crop.
|
113
|
+
cropped = crop?
|
114
|
+
crop = nil
|
115
|
+
if cropped
|
116
|
+
raise SnapImage::BadRequest, "Missing crop values." unless crop_valid?
|
117
|
+
crop = {
|
118
|
+
x: @request.json["crop_x"],
|
119
|
+
y: @request.json["crop_y"],
|
120
|
+
width: @request.json["crop_width"],
|
121
|
+
height: @request.json["crop_height"]
|
122
|
+
}
|
123
|
+
image = image.crop(crop[:x], crop[:y], crop[:width], crop[:height])
|
124
|
+
end
|
125
|
+
|
126
|
+
# Resize.
|
127
|
+
resized = resize?
|
128
|
+
if resized
|
129
|
+
width = @request.json["width"] && @request.json["width"].to_i
|
130
|
+
height = @request.json["height"] && @request.json["height"].to_i
|
131
|
+
if width && height
|
132
|
+
# When both width and height are specified, resize without
|
133
|
+
# maintaining the aspect ratio.
|
134
|
+
image = image.resize(width, height, false)
|
135
|
+
else
|
136
|
+
# When only one of width/height is specified, set the other to the
|
137
|
+
# max and maintain the aspect ratio.
|
138
|
+
image = image.resize(width || @config["max_width"], height || @config["max_height"])
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Resize to fit.
|
143
|
+
resized_to_fit = resize_to_fit?(image)
|
144
|
+
image = image.resize(get_max_width, get_max_height) if resized_to_fit
|
145
|
+
|
146
|
+
# Sharpen.
|
147
|
+
sharpened = sharpen?
|
148
|
+
image = image.sharpen if sharpened
|
149
|
+
|
150
|
+
# Get the dimensions at the end.
|
151
|
+
if cropped || resized || resized_to_fit || sharpened
|
152
|
+
modifications = {
|
153
|
+
crop: crop || { x: 0, y: 0, width: parts[:original_dimensions][0], height: parts[:original_dimensions][1] },
|
154
|
+
width: image.width,
|
155
|
+
height: image.height,
|
156
|
+
sharpen: sharpened
|
157
|
+
}
|
158
|
+
name = SnapImage::ImageNameUtils.generate_image_name(parts[:original_dimensions][0], parts[:original_dimensions][1], parts[:extname], {basename: parts[:basename]}.merge(modifications))
|
159
|
+
else
|
160
|
+
name = parts[:filename]
|
161
|
+
end
|
162
|
+
|
163
|
+
{ image: image, name: name }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SnapImage
|
2
|
+
module ServerActions
|
3
|
+
class ListResourceImages
|
4
|
+
include SnapImage::ServerActions::Authorize
|
5
|
+
|
6
|
+
def initialize(config, request, response)
|
7
|
+
@config = config
|
8
|
+
@storage = config.storage
|
9
|
+
@request = request
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
authorize(:server)
|
15
|
+
@response.set_success(
|
16
|
+
message: "List Resource Images Successful",
|
17
|
+
image_urls: @storage.get_resource_urls(@request.json["resource_identifier"])
|
18
|
+
)
|
19
|
+
@response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|