snapimage 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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