snapimage 0.0.1

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.
Files changed (61) hide show
  1. data/.autotest +3 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +2 -0
  8. data/bin/snapimage_generate_config +63 -0
  9. data/bin/snapimage_server +55 -0
  10. data/lib/snapimage.rb +24 -0
  11. data/lib/snapimage/config.rb +51 -0
  12. data/lib/snapimage/exceptions.rb +25 -0
  13. data/lib/snapimage/image/image.rb +96 -0
  14. data/lib/snapimage/image/image_name_utils.rb +131 -0
  15. data/lib/snapimage/middleware.rb +27 -0
  16. data/lib/snapimage/rack/request.rb +19 -0
  17. data/lib/snapimage/rack/request_file.rb +26 -0
  18. data/lib/snapimage/rack/response.rb +51 -0
  19. data/lib/snapimage/server.rb +50 -0
  20. data/lib/snapimage/server_actions/server_actions.authorize.rb +69 -0
  21. data/lib/snapimage/server_actions/server_actions.delete_resource_images.rb +23 -0
  22. data/lib/snapimage/server_actions/server_actions.generate_image.rb +167 -0
  23. data/lib/snapimage/server_actions/server_actions.list_resource_images.rb +23 -0
  24. data/lib/snapimage/server_actions/server_actions.sync_resource.rb +78 -0
  25. data/lib/snapimage/storage/storage.rb +120 -0
  26. data/lib/snapimage/storage/storage_server.local.rb +120 -0
  27. data/lib/snapimage/storage/storage_server.rb +110 -0
  28. data/lib/snapimage/version.rb +3 -0
  29. data/snapimage.gemspec +27 -0
  30. data/spec/acceptance/delete_resource_images_spec.rb +166 -0
  31. data/spec/acceptance/list_resource_images_spec.rb +158 -0
  32. data/spec/acceptance/modify_spec.rb +165 -0
  33. data/spec/acceptance/sync_spec.rb +260 -0
  34. data/spec/acceptance/upload_spec.rb +235 -0
  35. data/spec/snapimage/config_spec.rb +56 -0
  36. data/spec/snapimage/image/image_name_utils_spec.rb +127 -0
  37. data/spec/snapimage/image/image_spec.rb +71 -0
  38. data/spec/snapimage/middleware_spec.rb +27 -0
  39. data/spec/snapimage/rack/request_file_spec.rb +15 -0
  40. data/spec/snapimage/rack/request_spec.rb +52 -0
  41. data/spec/snapimage/rack/response_spec.rb +33 -0
  42. data/spec/snapimage/server_actions/server_actions.authorize_spec.rb +67 -0
  43. data/spec/snapimage/server_actions/server_actions.generate_image_spec.rb +146 -0
  44. data/spec/snapimage/server_actions/server_actions.sync_resource_spec.rb +91 -0
  45. data/spec/snapimage/server_spec.rb +55 -0
  46. data/spec/snapimage/storage/assets/local/resource_1/12345678-1x1-0x0x1x1-1x1-1.gif +0 -0
  47. data/spec/snapimage/storage/assets/local/resource_1/12345678-1x1-0x0x1x1-300x200-0.jpg +0 -0
  48. data/spec/snapimage/storage/assets/local/resource_1/12345678-1x1.png +0 -0
  49. data/spec/snapimage/storage/assets/local/resource_2/12345678-1x1-0x0x1x1-1x1-1.gif +0 -0
  50. data/spec/snapimage/storage/assets/local/resource_2/12345678-1x1-0x0x1x1-300x200-0.jpg +0 -0
  51. data/spec/snapimage/storage/assets/local/resource_2/12345678-1x1.png +0 -0
  52. data/spec/snapimage/storage/storage_server.local_spec.rb +150 -0
  53. data/spec/snapimage/storage/storage_server_spec.rb +97 -0
  54. data/spec/snapimage/storage/storage_spec.rb +49 -0
  55. data/spec/spec_helper.rb +18 -0
  56. data/spec/support/assets/config.json +8 -0
  57. data/spec/support/assets/config.yml +9 -0
  58. data/spec/support/assets/stub-1x1.png +0 -0
  59. data/spec/support/assets/stub-2048x100.png +0 -0
  60. data/spec/support/assets/stub-300x200.png +0 -0
  61. metadata +272 -0
@@ -0,0 +1,166 @@
1
+ require "spec_helper"
2
+ require "rack/test"
3
+
4
+ describe "Delete Resource Images" do
5
+ include Rack::Test::Methods
6
+
7
+ before do
8
+ @local_root = File.join(RSpec.root, "storage")
9
+ @image_path = File.join(RSpec.root, "support/assets/stub-300x200.png")
10
+ @resource_id_1 = "abc/123"
11
+ @resource_id_2 = "abc/456"
12
+ end
13
+
14
+ after do
15
+ FileUtils.rm_rf(@local_root)
16
+ end
17
+
18
+ context "without security tokens" do
19
+ def app
20
+ app = Proc.new do |env|
21
+ [200, {}, ""]
22
+ end
23
+ SnapImage::Middleware.new(
24
+ app,
25
+ path: "/snapimage_api",
26
+ config: {
27
+ "primary_storage_server" => "local",
28
+ "storage_servers" => [
29
+ {
30
+ "name" => "local",
31
+ "type" => "LOCAL",
32
+ "local_root" => File.join(RSpec.root, "storage"),
33
+ "public_url" => "//example.com/images"
34
+ }
35
+ ]
36
+ }
37
+ )
38
+ end
39
+
40
+ before do
41
+ # Store some images.
42
+ json = { action: "generate_image", resource_identifier: @resource_id_1 }.to_json
43
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
44
+ @url_1 = JSON.parse(last_response.body)["image_url"]
45
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
46
+ @url_2 = JSON.parse(last_response.body)["image_url"]
47
+
48
+ json = { action: "generate_image", resource_identifier: @resource_id_2 }.to_json
49
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
50
+ @url_3 = JSON.parse(last_response.body)["image_url"]
51
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
52
+ @url_4 = JSON.parse(last_response.body)["image_url"]
53
+
54
+ json = {
55
+ action: "delete_resource_images",
56
+ resource_identifier: @resource_id_1
57
+ }.to_json
58
+ post "/snapimage_api", "json" => json
59
+ end
60
+
61
+ it "is successful" do
62
+ last_response.should be_successful
63
+ last_response["Content-Type"].should eq "text/json"
64
+ json = JSON.parse(last_response.body)
65
+ json["status_code"].should eq 200
66
+ json["message"].should eq "Delete Resource Images Successful"
67
+ json["deleted_image_urls"].size.should eq 2
68
+ json["deleted_image_urls"].include?(@url_1).should be_true
69
+ json["deleted_image_urls"].include?(@url_2).should be_true
70
+ end
71
+
72
+ it "deletes the resource" do
73
+ File.exists?(File.join(@local_root, @resource_id_1)).should be_false
74
+ end
75
+
76
+ it "does not delete other resources" do
77
+ File.exists?(File.join(@local_root, @resource_id_2)).should be_true
78
+ end
79
+ end
80
+
81
+ context "with security tokens" do
82
+ def app
83
+ app = Proc.new do |env|
84
+ [200, {}, ""]
85
+ end
86
+ SnapImage::Middleware.new(
87
+ app,
88
+ path: "/snapimage_api",
89
+ config: {
90
+ "security_salt" => "123456789",
91
+ "primary_storage_server" => "local",
92
+ "storage_servers" => [
93
+ {
94
+ "name" => "local",
95
+ "type" => "LOCAL",
96
+ "local_root" => File.join(RSpec.root, "storage"),
97
+ "public_url" => "//example.com/images"
98
+ }
99
+ ]
100
+ }
101
+ )
102
+ end
103
+
104
+ before do
105
+ @client_security_token_1 = Digest::SHA1.hexdigest("client:#{Time.now.strftime("%Y-%m-%d")}:123456789:#{@resource_id_1}")
106
+ @client_security_token_2 = Digest::SHA2.hexdigest("client:#{Time.now.strftime("%Y-%m-%d")}:223456789:#{@resource_id_2}")
107
+ @server_security_token = Digest::SHA1.hexdigest("server:#{Time.now.strftime("%Y-%m-%d")}:123456789:#{@resource_id_1}")
108
+
109
+ # Store some images.
110
+ json = {
111
+ action: "generate_image",
112
+ resource_identifier: @resource_id_1,
113
+ client_security_token: @client_security_token_1
114
+ }.to_json
115
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
116
+ @url_1 = JSON.parse(last_response.body)["image_url"]
117
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
118
+ @url_2 = JSON.parse(last_response.body)["image_url"]
119
+
120
+ json = {
121
+ action: "generate_image",
122
+ resource_identifier: @resource_id_2,
123
+ client_security_token: @client_security_token_2
124
+ }.to_json
125
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
126
+ @url_3 = JSON.parse(last_response.body)["image_url"]
127
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
128
+ @url_4 = JSON.parse(last_response.body)["image_url"]
129
+
130
+ @options = { action: "delete_resource_images", resource_identifier: @resource_id_1 }
131
+ end
132
+
133
+ it "requires authorization when no security token is provided" do
134
+ request_json = @options.to_json
135
+ post "/snapimage_api", "json" => request_json
136
+ last_response.should be_successful
137
+ last_response["content-type"].should eq "text/json"
138
+ json = JSON.parse(last_response.body)
139
+ json["status_code"].should eq 401
140
+ json["message"].should eq "Authorization Required"
141
+ end
142
+
143
+ it "fails authorization when the security token is invalid" do
144
+ request_json = @options.merge!({"server_security_token" => "abc"}).to_json
145
+ post "/snapimage_api", "json" => request_json
146
+ last_response.should be_successful
147
+ last_response["content-type"].should eq "text/json"
148
+ json = JSON.parse(last_response.body)
149
+ json["status_code"].should eq 402
150
+ json["message"].should eq "Authorization Failed"
151
+ end
152
+
153
+ it "deletes successfully" do
154
+ request_json = @options.merge!({"server_security_token" => @server_security_token}).to_json
155
+ post "/snapimage_api", "json" => request_json
156
+ last_response.should be_successful
157
+ last_response["Content-Type"].should eq "text/json"
158
+ json = JSON.parse(last_response.body)
159
+ json["status_code"].should eq 200
160
+ json["message"].should eq "Delete Resource Images Successful"
161
+ json["deleted_image_urls"].size.should eq 2
162
+ json["deleted_image_urls"].include?(@url_1).should be_true
163
+ json["deleted_image_urls"].include?(@url_2).should be_true
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,158 @@
1
+ require "spec_helper"
2
+ require "rack/test"
3
+
4
+ describe "List Resource Images" do
5
+ include Rack::Test::Methods
6
+
7
+ before do
8
+ @local_root = File.join(RSpec.root, "storage")
9
+ @image_path = File.join(RSpec.root, "support/assets/stub-300x200.png")
10
+ @resource_id_1 = "abc/123"
11
+ @resource_id_2 = "abc/456"
12
+ end
13
+
14
+ after do
15
+ FileUtils.rm_rf(@local_root)
16
+ end
17
+
18
+ context "without security tokens" do
19
+ def app
20
+ app = Proc.new do |env|
21
+ [200, {}, ""]
22
+ end
23
+ SnapImage::Middleware.new(
24
+ app,
25
+ path: "/snapimage_api",
26
+ config: {
27
+ "primary_storage_server" => "local",
28
+ "storage_servers" => [
29
+ {
30
+ "name" => "local",
31
+ "type" => "LOCAL",
32
+ "local_root" => File.join(RSpec.root, "storage"),
33
+ "public_url" => "//example.com/images"
34
+ }
35
+ ]
36
+ }
37
+ )
38
+ end
39
+
40
+ before do
41
+ # Store some images.
42
+ json = { action: "generate_image", resource_identifier: @resource_id_1 }.to_json
43
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
44
+ @url_1 = JSON.parse(last_response.body)["image_url"]
45
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
46
+ @url_2 = JSON.parse(last_response.body)["image_url"]
47
+
48
+ json = { action: "generate_image", resource_identifier: @resource_id_2 }.to_json
49
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
50
+ @url_3 = JSON.parse(last_response.body)["image_url"]
51
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
52
+ @url_4 = JSON.parse(last_response.body)["image_url"]
53
+
54
+ json = {
55
+ action: "list_resource_images",
56
+ resource_identifier: @resource_id_1
57
+ }.to_json
58
+ post "/snapimage_api", "json" => json
59
+ end
60
+
61
+ it "is successful" do
62
+ last_response.should be_successful
63
+ last_response["Content-Type"].should eq "text/json"
64
+ json = JSON.parse(last_response.body)
65
+ json["status_code"].should eq 200
66
+ json["message"].should eq "List Resource Images Successful"
67
+ json["image_urls"].size.should eq 2
68
+ json["image_urls"].include?(@url_1).should be_true
69
+ json["image_urls"].include?(@url_2).should be_true
70
+ end
71
+ end
72
+
73
+ context "with security tokens" do
74
+ def app
75
+ app = Proc.new do |env|
76
+ [200, {}, ""]
77
+ end
78
+ SnapImage::Middleware.new(
79
+ app,
80
+ path: "/snapimage_api",
81
+ config: {
82
+ "security_salt" => "123456789",
83
+ "primary_storage_server" => "local",
84
+ "storage_servers" => [
85
+ {
86
+ "name" => "local",
87
+ "type" => "LOCAL",
88
+ "local_root" => File.join(RSpec.root, "storage"),
89
+ "public_url" => "//example.com/images"
90
+ }
91
+ ]
92
+ }
93
+ )
94
+ end
95
+
96
+ before do
97
+ @client_security_token_1 = Digest::SHA1.hexdigest("client:#{Time.now.strftime("%Y-%m-%d")}:123456789:#{@resource_id_1}")
98
+ @client_security_token_2 = Digest::SHA1.hexdigest("client:#{Time.now.strftime("%Y-%m-%d")}:123456789:#{@resource_id_2}")
99
+ @server_security_token = Digest::SHA1.hexdigest("server:#{Time.now.strftime("%Y-%m-%d")}:123456789:#{@resource_id_1}")
100
+
101
+ # Store some images.
102
+ json = {
103
+ action: "generate_image",
104
+ resource_identifier: @resource_id_1,
105
+ client_security_token: @client_security_token_1
106
+ }.to_json
107
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
108
+ @url_1 = JSON.parse(last_response.body)["image_url"]
109
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
110
+ @url_2 = JSON.parse(last_response.body)["image_url"]
111
+
112
+ json = {
113
+ action: "generate_image",
114
+ resource_identifier: @resource_id_2,
115
+ client_security_token: @client_security_token_2
116
+ }.to_json
117
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
118
+ @url_3 = JSON.parse(last_response.body)["image_url"]
119
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
120
+ @url_4 = JSON.parse(last_response.body)["image_url"]
121
+
122
+ @options = { action: "list_resource_images", resource_identifier: @resource_id_1 }
123
+ end
124
+
125
+ it "requires authorization when no security token is provided" do
126
+ request_json = @options.to_json
127
+ post "/snapimage_api", "json" => request_json
128
+ last_response.should be_successful
129
+ last_response["content-type"].should eq "text/json"
130
+ json = JSON.parse(last_response.body)
131
+ json["status_code"].should eq 401
132
+ json["message"].should eq "Authorization Required"
133
+ end
134
+
135
+ it "fails authorization when the security token is invalid" do
136
+ request_json = @options.merge!({"server_security_token" => "abc"}).to_json
137
+ post "/snapimage_api", "json" => request_json
138
+ last_response.should be_successful
139
+ last_response["content-type"].should eq "text/json"
140
+ json = JSON.parse(last_response.body)
141
+ json["status_code"].should eq 402
142
+ json["message"].should eq "Authorization Failed"
143
+ end
144
+
145
+ it "lists successfully" do
146
+ request_json = @options.merge!({"server_security_token" => @server_security_token}).to_json
147
+ post "/snapimage_api", "json" => request_json
148
+ last_response.should be_successful
149
+ last_response["Content-Type"].should eq "text/json"
150
+ json = JSON.parse(last_response.body)
151
+ json["status_code"].should eq 200
152
+ json["message"].should eq "List Resource Images Successful"
153
+ json["image_urls"].size.should eq 2
154
+ json["image_urls"].include?(@url_1).should be_true
155
+ json["image_urls"].include?(@url_2).should be_true
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,165 @@
1
+ require "spec_helper"
2
+ require "rack/test"
3
+
4
+ describe "Modify" do
5
+ include Rack::Test::Methods
6
+
7
+ before do
8
+ @local_root = File.join(RSpec.root, "storage")
9
+ @image_path = File.join(RSpec.root, "support/assets/stub-300x200.png")
10
+ @large_image_path = File.join(RSpec.root, "support/assets/stub-2048x100.png")
11
+ @resource_id = "abc/123"
12
+ end
13
+
14
+ after do
15
+ FileUtils.rm_rf(@local_root)
16
+ end
17
+
18
+ context "without security tokens" do
19
+ def app
20
+ app = Proc.new do |env|
21
+ [200, {}, ""]
22
+ end
23
+ SnapImage::Middleware.new(
24
+ app,
25
+ path: "/snapimage_api",
26
+ config: {
27
+ "primary_storage_server" => "local",
28
+ "storage_servers" => [
29
+ {
30
+ "name" => "local",
31
+ "type" => "LOCAL",
32
+ "local_root" => File.join(RSpec.root, "storage"),
33
+ "public_url" => "//example.com/images"
34
+ }
35
+ ]
36
+ }
37
+ )
38
+ end
39
+
40
+ before do
41
+ # Store the image.
42
+ json = { action: "generate_image", resource_identifier: @resource_id }.to_json
43
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
44
+
45
+ json = {
46
+ action: "generate_image",
47
+ url: "http:#{JSON.parse(last_response.body)["image_url"]}",
48
+ resource_identifier: @resource_id,
49
+ crop_x: 10,
50
+ crop_y: 50,
51
+ crop_width: 40,
52
+ crop_height: 60,
53
+ width: 400,
54
+ height: 600,
55
+ sharpen: true
56
+ }.to_json
57
+ post "/snapimage_api", "json" => json
58
+ end
59
+
60
+ it "modifies successfully" do
61
+ last_response.should be_successful
62
+ last_response["Content-Type"].should eq "text/json"
63
+ json = JSON.parse(last_response.body)
64
+ json["status_code"].should eq 200
65
+ json["message"].should eq "Get Modified Image Successful"
66
+ json["image_url"].should match Regexp.new("^//example.com/images/abc/123/[a-z0-9]{8}-300x200-10x50x40x60-400x600-1.png$")
67
+ json["image_width"].should eq 400
68
+ json["image_height"].should eq 600
69
+ end
70
+
71
+ it "stores the image" do
72
+ json = JSON.parse(last_response.body)
73
+ path = File.join(@local_root, @resource_id, File.basename(json["image_url"]))
74
+ File.exist?(path).should be_true
75
+ end
76
+ end
77
+
78
+ context "with security tokens" do
79
+ def app
80
+ app = Proc.new do |env|
81
+ [200, {}, ""]
82
+ end
83
+ SnapImage::Middleware.new(
84
+ app,
85
+ path: "/snapimage_api",
86
+ config: {
87
+ "security_salt" => "123456789",
88
+ "primary_storage_server" => "local",
89
+ "storage_servers" => [
90
+ {
91
+ "name" => "local",
92
+ "type" => "LOCAL",
93
+ "local_root" => File.join(RSpec.root, "storage"),
94
+ "public_url" => "//example.com/images"
95
+ }
96
+ ]
97
+ }
98
+ )
99
+ end
100
+
101
+ before do
102
+ @security_token = Digest::SHA1.hexdigest("client:#{Time.now.strftime("%Y-%m-%d")}:123456789:#{@resource_id}")
103
+
104
+ # Store the image.
105
+ json = {
106
+ action: "generate_image",
107
+ resource_identifier: @resource_id,
108
+ client_security_token: @security_token
109
+ }.to_json
110
+ post "/snapimage_api", "file" => Rack::Test::UploadedFile.new(@image_path, "image/png"), "json" => json
111
+
112
+ @options = {
113
+ action: "generate_image",
114
+ url: "http:#{JSON.parse(last_response.body)["image_url"]}",
115
+ resource_identifier: @resource_id,
116
+ crop_x: 10,
117
+ crop_y: 50,
118
+ crop_width: 40,
119
+ crop_height: 60,
120
+ width: 400,
121
+ height: 600,
122
+ sharpen: true
123
+ }
124
+ end
125
+
126
+ it "requires authorization when no security token is provided" do
127
+ request_json = @options.to_json
128
+ post "/snapimage_api", "json" => request_json
129
+ last_response.should be_successful
130
+ last_response["content-type"].should eq "text/json"
131
+ json = JSON.parse(last_response.body)
132
+ json["status_code"].should eq 401
133
+ json["message"].should eq "Authorization Required"
134
+ end
135
+
136
+ it "fails authorization when the security token is invalid" do
137
+ request_json = @options.merge!({"client_security_token" => "abc"}).to_json
138
+ post "/snapimage_api", "json" => request_json
139
+ last_response.should be_successful
140
+ last_response["content-type"].should eq "text/json"
141
+ json = JSON.parse(last_response.body)
142
+ json["status_code"].should eq 402
143
+ json["message"].should eq "Authorization Failed"
144
+ end
145
+
146
+ it "modifies successfully" do
147
+ request_json = @options.merge!({"client_security_token" => @security_token}).to_json
148
+ post "/snapimage_api", "json" => request_json
149
+ last_response.should be_successful
150
+ last_response["Content-Type"].should eq "text/json"
151
+ json = JSON.parse(last_response.body)
152
+ json["status_code"].should eq 200
153
+ json["message"].should eq "Get Modified Image Successful"
154
+ json["image_url"].should match Regexp.new("^//example.com/images/abc/123/[a-z0-9]{8}-300x200-10x50x40x60-400x600-1.png$")
155
+ json["image_width"].should eq 400
156
+ json["image_height"].should eq 600
157
+ end
158
+
159
+ it "stores the image" do
160
+ json = JSON.parse(last_response.body)
161
+ path = File.join(@local_root, @resource_id, File.basename(json["image_url"]))
162
+ File.exist?(path).should be_true
163
+ end
164
+ end
165
+ end