refile 0.5.5 → 0.6.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/lib/refile.rb +252 -27
- data/lib/refile/app.rb +55 -14
- data/lib/refile/attacher.rb +39 -40
- data/lib/refile/attachment.rb +28 -13
- data/lib/refile/attachment/active_record.rb +90 -1
- data/lib/refile/attachment_definition.rb +47 -0
- data/lib/refile/backend/s3.rb +1 -147
- data/lib/refile/backend_macros.rb +13 -5
- data/lib/refile/custom_logger.rb +3 -1
- data/lib/refile/file.rb +9 -0
- data/lib/refile/image_processing.rb +1 -143
- data/lib/refile/rails.rb +30 -0
- data/lib/refile/rails/attachment_helper.rb +27 -16
- data/lib/refile/signature.rb +5 -0
- data/lib/refile/simple_form.rb +17 -0
- data/lib/refile/version.rb +1 -1
- data/spec/refile/active_record_helper.rb +11 -0
- data/spec/refile/app_spec.rb +197 -20
- data/spec/refile/attachment/active_record_spec.rb +298 -1
- data/spec/refile/attachment_helper_spec.rb +39 -0
- data/spec/refile/attachment_spec.rb +53 -5
- data/spec/refile/backend_examples.rb +13 -2
- data/spec/refile/backend_macros_spec.rb +27 -6
- data/spec/refile/custom_logger_spec.rb +2 -3
- data/spec/refile/features/direct_upload_spec.rb +18 -0
- data/spec/refile/features/multiple_upload_spec.rb +122 -0
- data/spec/refile/features/normal_upload_spec.rb +5 -3
- data/spec/refile/features/presigned_upload_spec.rb +4 -0
- data/spec/refile/features/simple_form_spec.rb +8 -0
- data/spec/refile/fixtures/monkey.txt +1 -0
- data/spec/refile/fixtures/world.txt +1 -0
- data/spec/refile/spec_helper.rb +21 -11
- data/spec/refile_spec.rb +253 -24
- metadata +12 -303
- data/.gitignore +0 -27
- data/.rspec +0 -2
- data/.rubocop.yml +0 -68
- data/.travis.yml +0 -21
- data/.yardopts +0 -1
- data/CONTRIBUTING.md +0 -33
- data/Gemfile +0 -3
- data/History.md +0 -96
- data/LICENSE.txt +0 -22
- data/README.md +0 -651
- data/Rakefile +0 -19
- data/app/assets/javascripts/refile.js +0 -63
- data/config.ru +0 -8
- data/config/locales/en.yml +0 -8
- data/config/routes.rb +0 -5
- data/refile.gemspec +0 -42
- data/spec/refile/backend/s3_spec.rb +0 -11
- data/spec/refile/test_app.rb +0 -65
- data/spec/refile/test_app/app/assets/javascripts/application.js +0 -42
- data/spec/refile/test_app/app/controllers/application_controller.rb +0 -2
- data/spec/refile/test_app/app/controllers/direct_posts_controller.rb +0 -15
- data/spec/refile/test_app/app/controllers/home_controller.rb +0 -4
- data/spec/refile/test_app/app/controllers/normal_posts_controller.rb +0 -48
- data/spec/refile/test_app/app/controllers/presigned_posts_controller.rb +0 -31
- data/spec/refile/test_app/app/models/post.rb +0 -5
- data/spec/refile/test_app/app/views/direct_posts/new.html.erb +0 -20
- data/spec/refile/test_app/app/views/home/index.html.erb +0 -1
- data/spec/refile/test_app/app/views/layouts/application.html.erb +0 -14
- data/spec/refile/test_app/app/views/normal_posts/_form.html.erb +0 -28
- data/spec/refile/test_app/app/views/normal_posts/edit.html.erb +0 -1
- data/spec/refile/test_app/app/views/normal_posts/index.html +0 -5
- data/spec/refile/test_app/app/views/normal_posts/new.html.erb +0 -1
- data/spec/refile/test_app/app/views/normal_posts/show.html.erb +0 -19
- data/spec/refile/test_app/app/views/presigned_posts/new.html.erb +0 -16
- data/spec/refile/test_app/config/database.yml +0 -7
- data/spec/refile/test_app/config/routes.rb +0 -17
- data/spec/refile/test_app/public/favicon.ico +0 -0
@@ -5,8 +5,8 @@ RSpec.shared_examples_for :backend do
|
|
5
5
|
|
6
6
|
describe "#upload" do
|
7
7
|
it "raises ArgumentError when invalid object is uploaded" do
|
8
|
-
expect { backend.upload(double(size: 123)) }.to raise_error(
|
9
|
-
expect { backend.upload("hello") }.to raise_error(
|
8
|
+
expect { backend.upload(double(size: 123)) }.to raise_error(Refile::InvalidFile)
|
9
|
+
expect { backend.upload("hello") }.to raise_error(Refile::InvalidFile)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "raises Refile::Invalid when object is too large" do
|
@@ -177,6 +177,17 @@ RSpec.shared_examples_for :backend do
|
|
177
177
|
expect { file.read(1, buffer) }.to raise_error
|
178
178
|
end
|
179
179
|
|
180
|
+
describe "#rewind" do
|
181
|
+
it "rewinds file to beginning" do
|
182
|
+
file = backend.upload(uploadable)
|
183
|
+
|
184
|
+
expect(file.read(2)).to eq("he")
|
185
|
+
expect(file.read(2)).to eq("ll")
|
186
|
+
file.rewind
|
187
|
+
expect(file.read(2)).to eq("he")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
180
191
|
describe "#read" do
|
181
192
|
it "can read file contents" do
|
182
193
|
file = backend.upload(uploadable)
|
@@ -20,23 +20,27 @@ RSpec.describe Refile::BackendMacros do
|
|
20
20
|
let(:io) { StringIO.new("hello") }
|
21
21
|
|
22
22
|
it "works if it conforms to required API" do
|
23
|
-
expect(instance.upload(double(size: 444, read: io, eof?: true, close: nil))).to be_truthy
|
23
|
+
expect(instance.upload(double(size: 444, read: io, eof?: true, rewind: true, close: nil))).to be_truthy
|
24
24
|
end
|
25
25
|
|
26
26
|
it "raises ArgumentError if argument does not respond to `size`" do
|
27
|
-
expect { instance.upload(double(read: io, eof?: true, close: nil)) }.to raise_error(
|
27
|
+
expect { instance.upload(double(read: io, eof?: true, rewind: true, close: nil)) }.to raise_error(Refile::InvalidFile)
|
28
28
|
end
|
29
29
|
|
30
30
|
it "raises ArgumentError if argument does not respond to `read`" do
|
31
|
-
expect { instance.upload(double(size: 444, eof?: true, close: nil)) }.to raise_error(
|
31
|
+
expect { instance.upload(double(size: 444, eof?: true, rewind: true, close: nil)) }.to raise_error(Refile::InvalidFile)
|
32
32
|
end
|
33
33
|
|
34
34
|
it "raises ArgumentError if argument does not respond to `eof?`" do
|
35
|
-
expect { instance.upload(double(size: 444, read: true, close: nil)) }.to raise_error(
|
35
|
+
expect { instance.upload(double(size: 444, read: true, rewind: true, close: nil)) }.to raise_error(Refile::InvalidFile)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "raises ArgumentError if argument does not respond to `rewind`" do
|
39
|
+
expect { instance.upload(double(size: 444, read: true, eof?: true, close: nil)) }.to raise_error(Refile::InvalidFile)
|
36
40
|
end
|
37
41
|
|
38
42
|
it "raises ArgumentError if argument does not respond to `close`" do
|
39
|
-
expect { instance.upload(double(size: 444, read: true, eof?: true)) }.to raise_error(
|
43
|
+
expect { instance.upload(double(size: 444, read: true, rewind: true, eof?: true)) }.to raise_error(Refile::InvalidFile)
|
40
44
|
end
|
41
45
|
|
42
46
|
it "returns true if size is respeced" do
|
@@ -46,7 +50,7 @@ RSpec.describe Refile::BackendMacros do
|
|
46
50
|
|
47
51
|
it "raises Refile::Invalid if size is exceeded" do
|
48
52
|
instance.max_size = 8
|
49
|
-
expect { instance.upload(Refile::FileDouble.new("hello world")) }.to raise_error(Refile::
|
53
|
+
expect { instance.upload(Refile::FileDouble.new("hello world")) }.to raise_error(Refile::InvalidMaxSize)
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
@@ -59,4 +63,21 @@ RSpec.describe Refile::BackendMacros do
|
|
59
63
|
expect { instance.get("ev/il") }.to raise_error(Refile::InvalidID)
|
60
64
|
end
|
61
65
|
end
|
66
|
+
|
67
|
+
describe "#valid_id?" do
|
68
|
+
it "returns true for valid ID" do
|
69
|
+
expect(klass.valid_id?("1234aBCde123aee")).to be_truthy
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns false for invalid ID" do
|
73
|
+
expect(klass.valid_id?("ev/il")).to be_falsey
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#decode_id" do
|
78
|
+
it "returns to_s" do
|
79
|
+
expect(klass.decode_id("1234aBCde123aee")).to eq "1234aBCde123aee"
|
80
|
+
expect(klass.decode_id(1234)).to eq "1234"
|
81
|
+
end
|
82
|
+
end
|
62
83
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "active_support/logger"
|
2
1
|
require "refile/custom_logger"
|
3
2
|
|
4
3
|
describe Refile::CustomLogger do
|
@@ -12,10 +11,10 @@ describe Refile::CustomLogger do
|
|
12
11
|
"PATH_INFO" => "/" }
|
13
12
|
end
|
14
13
|
|
15
|
-
let(:expected_format) {
|
14
|
+
let(:expected_format) { %r{Prefix: \[[^\]]+\] POST "/" 200 \d+\.\d+ms\n\n$} }
|
16
15
|
|
17
16
|
it "uses a dynamic logger" do
|
18
|
-
_, _, body = described_class.new(rack_app, "Prefix", -> {
|
17
|
+
_, _, body = described_class.new(rack_app, "Prefix", -> { Logger.new(io) }).call(env)
|
19
18
|
body.close
|
20
19
|
expect(io.tap(&:rewind).read).to match(expected_format)
|
21
20
|
end
|
@@ -9,6 +9,7 @@ feature "Direct HTTP post file uploads", :js do
|
|
9
9
|
expect(page).to have_content("Upload started")
|
10
10
|
expect(page).to have_content("Upload success")
|
11
11
|
expect(page).to have_content("Upload complete")
|
12
|
+
expect(page).to have_content("All uploads complete")
|
12
13
|
|
13
14
|
click_button "Create"
|
14
15
|
|
@@ -28,6 +29,23 @@ feature "Direct HTTP post file uploads", :js do
|
|
28
29
|
expect(page).to have_content("Upload failure error")
|
29
30
|
end
|
30
31
|
|
32
|
+
scenario "Upload a file after validation failure" do
|
33
|
+
visit "/direct/posts/new"
|
34
|
+
fill_in "Title", with: "A cool post"
|
35
|
+
check "Requires document"
|
36
|
+
click_button "Create"
|
37
|
+
|
38
|
+
attach_file "Document", path("hello.txt")
|
39
|
+
|
40
|
+
expect(page).to have_content("Upload started")
|
41
|
+
expect(page).to have_content("Upload success")
|
42
|
+
expect(page).to have_content("Upload complete")
|
43
|
+
|
44
|
+
click_button "Create"
|
45
|
+
|
46
|
+
expect(download_link("Document")).to eq("hello")
|
47
|
+
end
|
48
|
+
|
31
49
|
scenario "Fail to upload a file that has wrong format" do
|
32
50
|
visit "/direct/posts/new"
|
33
51
|
fill_in "Title", with: "A cool post"
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "refile/test_app"
|
2
|
+
|
3
|
+
feature "Multiple file uploads", :js do
|
4
|
+
scenario "Upload multiple files" do
|
5
|
+
visit "/multiple/posts/new"
|
6
|
+
fill_in "Title", with: "A cool post"
|
7
|
+
attach_file "Documents", [path("hello.txt"), path("world.txt")]
|
8
|
+
click_button "Create"
|
9
|
+
|
10
|
+
expect(download_link("Document: hello.txt")).to eq("hello")
|
11
|
+
expect(download_link("Document: world.txt")).to eq("world")
|
12
|
+
end
|
13
|
+
|
14
|
+
scenario "Fail to upload a file that is too large" do
|
15
|
+
visit "/multiple/posts/new"
|
16
|
+
fill_in "Title", with: "A cool post"
|
17
|
+
attach_file "Documents", [path("hello.txt"), path("large.txt")]
|
18
|
+
click_button "Create"
|
19
|
+
|
20
|
+
expect(page).to have_content("Documents is invalid")
|
21
|
+
end
|
22
|
+
|
23
|
+
scenario "Fail to upload a file that has the wrong format then submit" do
|
24
|
+
visit "/multiple/posts/new"
|
25
|
+
fill_in "Title", with: "A cool post"
|
26
|
+
attach_file "Documents", [path("hello.txt"), path("image.jpg")]
|
27
|
+
click_button "Create"
|
28
|
+
|
29
|
+
expect(page).to have_content("Documents is invalid")
|
30
|
+
click_button "Create"
|
31
|
+
expect(page).to have_selector("h1", text: "A cool post")
|
32
|
+
expect(page).not_to have_link("Document")
|
33
|
+
end
|
34
|
+
|
35
|
+
scenario "Upload files via form redisplay", js: true do
|
36
|
+
visit "/multiple/posts/new"
|
37
|
+
attach_file "Documents", [path("hello.txt"), path("world.txt")]
|
38
|
+
click_button "Create"
|
39
|
+
fill_in "Title", with: "A cool post"
|
40
|
+
click_button "Create"
|
41
|
+
|
42
|
+
expect(download_link("Document: hello.txt")).to eq("hello")
|
43
|
+
expect(download_link("Document: world.txt")).to eq("world")
|
44
|
+
end
|
45
|
+
|
46
|
+
scenario "Edit with changes" do
|
47
|
+
visit "/multiple/posts/new"
|
48
|
+
fill_in "Title", with: "A cool post"
|
49
|
+
attach_file "Documents", [path("hello.txt"), path("world.txt")]
|
50
|
+
click_button "Create"
|
51
|
+
|
52
|
+
click_link "Edit multiple"
|
53
|
+
attach_file "Documents", [path("monkey.txt")]
|
54
|
+
click_button "Update"
|
55
|
+
|
56
|
+
expect(download_link("Document: monkey.txt")).to eq("monkey")
|
57
|
+
expect(page).not_to have_link("Document: hello.txt")
|
58
|
+
expect(page).not_to have_link("Document: world.txt")
|
59
|
+
end
|
60
|
+
|
61
|
+
scenario "Edit without changes" do
|
62
|
+
visit "/multiple/posts/new"
|
63
|
+
fill_in "Title", with: "A cool post"
|
64
|
+
attach_file "Documents", [path("hello.txt"), path("world.txt")]
|
65
|
+
click_button "Create"
|
66
|
+
|
67
|
+
click_link "Edit multiple"
|
68
|
+
click_button "Update"
|
69
|
+
|
70
|
+
expect(download_link("Document: hello.txt")).to eq("hello")
|
71
|
+
expect(download_link("Document: world.txt")).to eq("world")
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "with direct upload" do
|
75
|
+
scenario "Successfully upload a file" do
|
76
|
+
visit "/direct/posts/new"
|
77
|
+
fill_in "Title", with: "A cool post"
|
78
|
+
attach_file "Documents", [path("hello.txt"), path("world.txt")]
|
79
|
+
|
80
|
+
expect(page).to have_content("Upload started")
|
81
|
+
expect(page).to have_content("Upload success")
|
82
|
+
expect(page).to have_content("Upload complete")
|
83
|
+
expect(page).to have_content("All uploads complete")
|
84
|
+
|
85
|
+
click_button "Create"
|
86
|
+
|
87
|
+
expect(download_link("Document: hello.txt")).to eq("hello")
|
88
|
+
expect(download_link("Document: world.txt")).to eq("world")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "with presigned upload" do
|
93
|
+
scenario "Successfully upload a file" do
|
94
|
+
visit "/presigned/posts/new"
|
95
|
+
fill_in "Title", with: "A cool post"
|
96
|
+
attach_file "Documents", [path("hello.txt"), path("world.txt")]
|
97
|
+
|
98
|
+
expect(page).to have_content("Presign start")
|
99
|
+
expect(page).to have_content("Presign complete")
|
100
|
+
expect(page).to have_content("Upload started")
|
101
|
+
expect(page).to have_content("Upload complete token accepted")
|
102
|
+
expect(page).to have_content("Upload success token accepted")
|
103
|
+
|
104
|
+
click_button "Create"
|
105
|
+
|
106
|
+
expect(page).to have_selector("h1", text: "A cool post")
|
107
|
+
expect(download_link("Document: hello.txt")).to eq("hello")
|
108
|
+
expect(download_link("Document: world.txt")).to eq("world")
|
109
|
+
end
|
110
|
+
|
111
|
+
scenario "Fail to upload a file that is too large" do
|
112
|
+
visit "/presigned/posts/new"
|
113
|
+
fill_in "Title", with: "A cool post"
|
114
|
+
attach_file "Documents", [path("large.txt"), path("world.txt")]
|
115
|
+
|
116
|
+
expect(page).to have_content("Presign start")
|
117
|
+
expect(page).to have_content("Presign complete")
|
118
|
+
expect(page).to have_content("Upload started")
|
119
|
+
expect(page).to have_content("Upload failure too large")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -119,7 +119,9 @@ feature "Normal HTTP Post file uploads" do
|
|
119
119
|
end
|
120
120
|
|
121
121
|
scenario "Upload a file from a remote URL" do
|
122
|
-
|
122
|
+
url = "http://www.example.com/foo/bar/some_file.png?some-query-string=true"
|
123
|
+
|
124
|
+
stub_request(:get, url).to_return(
|
123
125
|
status: 200,
|
124
126
|
body: "abc",
|
125
127
|
headers: {
|
@@ -130,13 +132,13 @@ feature "Normal HTTP Post file uploads" do
|
|
130
132
|
|
131
133
|
visit "/normal/posts/new"
|
132
134
|
fill_in "Title", with: "A cool post"
|
133
|
-
fill_in "Remote document url", with:
|
135
|
+
fill_in "Remote document url", with: url
|
134
136
|
click_button "Create"
|
135
137
|
|
136
138
|
expect(page).to have_selector("h1", text: "A cool post")
|
137
139
|
expect(download_link("Document")).to eq("abc")
|
138
140
|
expect(page).to have_selector(".content-type", text: "image/png")
|
139
141
|
expect(page).to have_selector(".size", text: "3")
|
140
|
-
expect(page).to have_selector(".filename", text: "some_file")
|
142
|
+
expect(page).to have_selector(".filename", text: "some_file.png", exact: true)
|
141
143
|
end
|
142
144
|
end
|
@@ -6,6 +6,8 @@ feature "Direct HTTP post file uploads", :js do
|
|
6
6
|
fill_in "Title", with: "A cool post"
|
7
7
|
attach_file "Document", path("hello.txt")
|
8
8
|
|
9
|
+
expect(page).to have_content("Presign start")
|
10
|
+
expect(page).to have_content("Presign complete")
|
9
11
|
expect(page).to have_content("Upload started")
|
10
12
|
expect(page).to have_content("Upload complete token accepted")
|
11
13
|
expect(page).to have_content("Upload success token accepted")
|
@@ -21,6 +23,8 @@ feature "Direct HTTP post file uploads", :js do
|
|
21
23
|
fill_in "Title", with: "A cool post"
|
22
24
|
attach_file "Document", path("large.txt")
|
23
25
|
|
26
|
+
expect(page).to have_content("Presign start")
|
27
|
+
expect(page).to have_content("Presign complete")
|
24
28
|
expect(page).to have_content("Upload started")
|
25
29
|
expect(page).to have_content("Upload failure too large")
|
26
30
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
monkey
|
@@ -0,0 +1 @@
|
|
1
|
+
world
|
data/spec/refile/spec_helper.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
ENV["RACK_ENV"] = "test"
|
2
|
+
|
1
3
|
require "refile"
|
2
4
|
require "refile/backend_examples"
|
3
5
|
require "webmock/rspec"
|
4
6
|
|
5
7
|
tmp_path = Dir.mktmpdir
|
6
8
|
|
9
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
10
|
+
|
7
11
|
at_exit do
|
8
12
|
FileUtils.remove_entry_secure(tmp_path)
|
9
13
|
end
|
@@ -18,9 +22,15 @@ class FakePresignBackend < Refile::Backend::FileSystem
|
|
18
22
|
end
|
19
23
|
end
|
20
24
|
|
25
|
+
Refile.secret_key = "144c82de680afe5e8e91fc7cf13c22b2f8d2d4b1a4a0e92531979b12e2fa8b6dd6239c65be28517f27f442bfba11572a8bef80acf44a11f465ba85dde85488d5"
|
26
|
+
|
21
27
|
Refile.backends["limited_cache"] = FakePresignBackend.new(File.expand_path("default_cache", tmp_path), max_size: 100)
|
22
28
|
|
23
|
-
Refile.
|
29
|
+
Refile.allow_uploads_to = %w[cache limited_cache]
|
30
|
+
|
31
|
+
Refile.allow_origin = "*"
|
32
|
+
|
33
|
+
Refile.app_host = "http://localhost:56120"
|
24
34
|
|
25
35
|
Refile.processor(:reverse) do |file|
|
26
36
|
StringIO.new(file.read.reverse)
|
@@ -28,6 +38,8 @@ end
|
|
28
38
|
|
29
39
|
Refile.processor(:upcase, proc { |file| StringIO.new(file.read.upcase) })
|
30
40
|
|
41
|
+
Refile.logger = Logger.new(nil)
|
42
|
+
|
31
43
|
Refile.processor(:concat) do |file, *words|
|
32
44
|
tempfile = Tempfile.new("concat")
|
33
45
|
tempfile.write(file.read)
|
@@ -38,8 +50,8 @@ Refile.processor(:concat) do |file, *words|
|
|
38
50
|
File.open(tempfile.path, "r")
|
39
51
|
end
|
40
52
|
|
41
|
-
Refile.processor(:convert_case) do |file,
|
42
|
-
case format
|
53
|
+
Refile.processor(:convert_case) do |file, options = {}|
|
54
|
+
case options[:format]
|
43
55
|
when "up" then StringIO.new(file.read.upcase)
|
44
56
|
when "down" then StringIO.new(file.read.downcase)
|
45
57
|
else file
|
@@ -59,6 +71,10 @@ module Refile
|
|
59
71
|
@io.read(*args)
|
60
72
|
end
|
61
73
|
|
74
|
+
def rewind
|
75
|
+
@io.rewind
|
76
|
+
end
|
77
|
+
|
62
78
|
def size
|
63
79
|
@io.size
|
64
80
|
end
|
@@ -81,12 +97,6 @@ end
|
|
81
97
|
|
82
98
|
RSpec.configure do |config|
|
83
99
|
config.include PathHelper
|
84
|
-
config.before(:all) do
|
85
|
-
Refile.logger = Logger.new(nil)
|
86
|
-
if ENV["S3"]
|
87
|
-
WebMock.allow_net_connect!
|
88
|
-
else
|
89
|
-
WebMock.disable_net_connect!(allow_localhost: true)
|
90
|
-
end
|
91
|
-
end
|
92
100
|
end
|
101
|
+
|
102
|
+
RSpec::Expectations.configuration.warn_about_potential_false_positives = false
|
data/spec/refile_spec.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
require "refile"
|
2
2
|
|
3
3
|
RSpec.describe Refile do
|
4
|
+
before do
|
5
|
+
allow(Refile).to receive(:token).and_return("token")
|
6
|
+
allow(Refile).to receive(:app_host).and_return(nil)
|
7
|
+
allow(Refile).to receive(:mount_point).and_return(nil)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:klass) do
|
11
|
+
Class.new do
|
12
|
+
extend Refile::Attachment
|
13
|
+
attr_accessor :document_id
|
14
|
+
attachment :document
|
15
|
+
end
|
16
|
+
end
|
17
|
+
let(:instance) { klass.new }
|
18
|
+
|
4
19
|
describe ".extract_filename" do
|
5
20
|
it "extracts filename from original_filename" do
|
6
21
|
name = Refile.extract_filename(double(original_filename: "/foo/bar/baz.png"))
|
@@ -40,56 +55,126 @@ RSpec.describe Refile do
|
|
40
55
|
end
|
41
56
|
end
|
42
57
|
|
43
|
-
describe ".
|
44
|
-
|
45
|
-
|
46
|
-
extend Refile::Attachment
|
47
|
-
attachment :document
|
48
|
-
end
|
58
|
+
describe ".app_url" do
|
59
|
+
it "generates a root url when all options unset" do
|
60
|
+
expect(Refile.app_url).to eq("/")
|
49
61
|
end
|
50
|
-
let(:instance) { klass.new }
|
51
|
-
let(:id) { instance.document_attacher.cache_id }
|
52
62
|
|
53
|
-
|
54
|
-
|
55
|
-
|
63
|
+
it "uses supplied host option" do
|
64
|
+
expect(Refile.app_url(host: "http://example.org")).to eq("http://example.org/")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "falls back to Refile.app_host" do
|
68
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
69
|
+
|
70
|
+
expect(Refile.app_url).to eq("http://elabs.se/")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "adds a prefix" do
|
74
|
+
expect(Refile.app_url(prefix: "/moo")).to eq("/moo")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "takes prefix from Refile.mount_point" do
|
78
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
79
|
+
expect(Refile.app_url).to eq("/attachments")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe ".file_url" do
|
84
|
+
let(:file) { Refile.cache.upload(Refile::FileDouble.new("hello")) }
|
85
|
+
let(:id) { file.id }
|
86
|
+
|
87
|
+
it "generates a url from an attachment" do
|
88
|
+
expect(Refile.file_url(file, filename: "document")).to eq("/token/cache/#{id}/document")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "uses supplied host option" do
|
92
|
+
expect(Refile.file_url(file, host: "http://example.org", filename: "document")).to eq("http://example.org/token/cache/#{id}/document")
|
93
|
+
end
|
94
|
+
|
95
|
+
it "falls back to Refile.app_host" do
|
96
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
97
|
+
|
98
|
+
expect(Refile.file_url(file, filename: "document")).to eq("http://elabs.se/token/cache/#{id}/document")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "falls back to Refile.cdn_host" do
|
102
|
+
allow(Refile).to receive(:cdn_host).and_return("http://foo.cloudfront.com")
|
103
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
104
|
+
|
105
|
+
expect(Refile.file_url(file, filename: "document")).to eq("http://foo.cloudfront.com/token/cache/#{id}/document")
|
106
|
+
end
|
107
|
+
|
108
|
+
it "adds a prefix" do
|
109
|
+
expect(Refile.file_url(file, prefix: "/moo", filename: "document")).to eq("/moo/token/cache/#{id}/document")
|
56
110
|
end
|
57
111
|
|
112
|
+
it "takes prefix from Refile.mount_point" do
|
113
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
114
|
+
expect(Refile.file_url(file, filename: "document")).to eq("/attachments/token/cache/#{id}/document")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "adds an escaped filename" do
|
118
|
+
expect(Refile.file_url(file, filename: "test.png")).to eq("/token/cache/#{id}/test.png")
|
119
|
+
expect(Refile.file_url(file, filename: "tes/t.png")).to eq("/token/cache/#{id}/tes%2Ft.png")
|
120
|
+
end
|
121
|
+
|
122
|
+
it "adds a format" do
|
123
|
+
expect(Refile.file_url(file, format: "png", filename: "document")).to eq("/token/cache/#{id}/document.png")
|
124
|
+
end
|
125
|
+
|
126
|
+
context "with no file" do
|
127
|
+
it "returns nil" do
|
128
|
+
expect(Refile.file_url(nil, filename: "document")).to be_nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe ".attachment_url" do
|
134
|
+
let(:id) { instance.document_attacher.cache_id }
|
135
|
+
|
58
136
|
context "with file" do
|
59
137
|
before do
|
60
138
|
instance.document = Refile::FileDouble.new("hello")
|
61
139
|
end
|
62
140
|
|
63
141
|
it "generates a url from an attachment" do
|
64
|
-
expect(Refile.attachment_url(instance, :document)).to eq("/cache/#{id}/document")
|
142
|
+
expect(Refile.attachment_url(instance, :document)).to eq("/token/cache/#{id}/document")
|
65
143
|
end
|
66
144
|
|
67
145
|
it "uses supplied host option" do
|
68
|
-
expect(Refile.attachment_url(instance, :document, host: "http://example.org")).to eq("http://example.org/cache/#{id}/document")
|
146
|
+
expect(Refile.attachment_url(instance, :document, host: "http://example.org")).to eq("http://example.org/token/cache/#{id}/document")
|
69
147
|
end
|
70
148
|
|
71
|
-
it "falls back to Refile.
|
72
|
-
allow(Refile).to receive(:
|
149
|
+
it "falls back to Refile.app_host" do
|
150
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
73
151
|
|
74
|
-
expect(Refile.attachment_url(instance, :document)).to eq("http://elabs.se/cache/#{id}/document")
|
152
|
+
expect(Refile.attachment_url(instance, :document)).to eq("http://elabs.se/token/cache/#{id}/document")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "falls back to Refile.cdn_host" do
|
156
|
+
allow(Refile).to receive(:cdn_host).and_return("http://foo.cloudfront.com")
|
157
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
158
|
+
|
159
|
+
expect(Refile.attachment_url(instance, :document)).to eq("http://foo.cloudfront.com/token/cache/#{id}/document")
|
75
160
|
end
|
76
161
|
|
77
162
|
it "adds a prefix" do
|
78
|
-
expect(Refile.attachment_url(instance, :document, prefix: "moo")).to eq("/moo/cache/#{id}/document")
|
163
|
+
expect(Refile.attachment_url(instance, :document, prefix: "/moo")).to eq("/moo/token/cache/#{id}/document")
|
79
164
|
end
|
80
165
|
|
81
166
|
it "takes prefix from Refile.mount_point" do
|
82
|
-
allow(Refile).to receive(:mount_point).and_return("attachments")
|
83
|
-
expect(Refile.attachment_url(instance, :document)).to eq("/attachments/cache/#{id}/document")
|
167
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
168
|
+
expect(Refile.attachment_url(instance, :document)).to eq("/attachments/token/cache/#{id}/document")
|
84
169
|
end
|
85
170
|
|
86
171
|
it "adds an escaped filename" do
|
87
|
-
expect(Refile.attachment_url(instance, :document, filename: "test.png")).to eq("/cache/#{id}/test.png")
|
88
|
-
expect(Refile.attachment_url(instance, :document, filename: "tes/t.png")).to eq("/cache/#{id}/tes%2Ft.png")
|
172
|
+
expect(Refile.attachment_url(instance, :document, filename: "test.png")).to eq("/token/cache/#{id}/test.png")
|
173
|
+
expect(Refile.attachment_url(instance, :document, filename: "tes/t.png")).to eq("/token/cache/#{id}/tes%2Ft.png")
|
89
174
|
end
|
90
175
|
|
91
176
|
it "adds a format" do
|
92
|
-
expect(Refile.attachment_url(instance, :document, format: "png")).to eq("/cache/#{id}/document.png")
|
177
|
+
expect(Refile.attachment_url(instance, :document, format: "png")).to eq("/token/cache/#{id}/document.png")
|
93
178
|
end
|
94
179
|
end
|
95
180
|
|
@@ -99,7 +184,7 @@ RSpec.describe Refile do
|
|
99
184
|
end
|
100
185
|
|
101
186
|
it "adds format inferred from content type" do
|
102
|
-
expect(Refile.attachment_url(instance, :document)).to eq("/cache/#{id}/document.png")
|
187
|
+
expect(Refile.attachment_url(instance, :document)).to eq("/token/cache/#{id}/document.png")
|
103
188
|
end
|
104
189
|
end
|
105
190
|
|
@@ -109,7 +194,7 @@ RSpec.describe Refile do
|
|
109
194
|
end
|
110
195
|
|
111
196
|
it "adds filename" do
|
112
|
-
expect(Refile.attachment_url(instance, :document)).to eq("/cache/#{id}/hello.html")
|
197
|
+
expect(Refile.attachment_url(instance, :document)).to eq("/token/cache/#{id}/hello.html")
|
113
198
|
end
|
114
199
|
end
|
115
200
|
|
@@ -119,4 +204,148 @@ RSpec.describe Refile do
|
|
119
204
|
end
|
120
205
|
end
|
121
206
|
end
|
207
|
+
|
208
|
+
describe ".upload_url" do
|
209
|
+
it "generates an upload url" do
|
210
|
+
expect(Refile.upload_url(Refile.cache)).to eq("/cache")
|
211
|
+
end
|
212
|
+
|
213
|
+
it "uses supplied host option" do
|
214
|
+
expect(Refile.upload_url(Refile.cache, host: "http://example.org")).to eq("http://example.org/cache")
|
215
|
+
end
|
216
|
+
|
217
|
+
it "falls back to Refile.app_host" do
|
218
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
219
|
+
|
220
|
+
expect(Refile.upload_url(Refile.cache)).to eq("http://elabs.se/cache")
|
221
|
+
end
|
222
|
+
|
223
|
+
it "does not fall back to Refile.cdn_host" do
|
224
|
+
allow(Refile).to receive(:cdn_host).and_return("http://foo.cloudfront.com")
|
225
|
+
|
226
|
+
expect(Refile.upload_url(Refile.cache)).to eq("/cache")
|
227
|
+
end
|
228
|
+
|
229
|
+
it "adds a prefix" do
|
230
|
+
expect(Refile.upload_url(Refile.cache, prefix: "/moo")).to eq("/moo/cache")
|
231
|
+
end
|
232
|
+
|
233
|
+
it "takes prefix from Refile.mount_point" do
|
234
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
235
|
+
expect(Refile.upload_url(Refile.cache)).to eq("/attachments/cache")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe ".presign_url" do
|
240
|
+
it "generates an upload url" do
|
241
|
+
expect(Refile.presign_url(Refile.cache)).to eq("/cache/presign")
|
242
|
+
end
|
243
|
+
|
244
|
+
it "uses supplied host option" do
|
245
|
+
expect(Refile.presign_url(Refile.cache, host: "http://example.org")).to eq("http://example.org/cache/presign")
|
246
|
+
end
|
247
|
+
|
248
|
+
it "falls back to Refile.app_host" do
|
249
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
250
|
+
|
251
|
+
expect(Refile.presign_url(Refile.cache)).to eq("http://elabs.se/cache/presign")
|
252
|
+
end
|
253
|
+
|
254
|
+
it "does not fall back to Refile.cdn_host" do
|
255
|
+
allow(Refile).to receive(:cdn_host).and_return("http://foo.cloudfront.com")
|
256
|
+
|
257
|
+
expect(Refile.presign_url(Refile.cache)).to eq("/cache/presign")
|
258
|
+
end
|
259
|
+
|
260
|
+
it "adds a prefix" do
|
261
|
+
expect(Refile.presign_url(Refile.cache, prefix: "/moo")).to eq("/moo/cache/presign")
|
262
|
+
end
|
263
|
+
|
264
|
+
it "takes prefix from Refile.mount_point" do
|
265
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
266
|
+
expect(Refile.presign_url(Refile.cache)).to eq("/attachments/cache/presign")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe ".attachment_upload_url" do
|
271
|
+
it "generates an upload url" do
|
272
|
+
expect(Refile.attachment_upload_url(instance, :document)).to eq("/cache")
|
273
|
+
end
|
274
|
+
|
275
|
+
it "uses supplied host option" do
|
276
|
+
expect(Refile.attachment_upload_url(instance, :document, host: "http://example.org")).to eq("http://example.org/cache")
|
277
|
+
end
|
278
|
+
|
279
|
+
it "falls back to Refile.app_host" do
|
280
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
281
|
+
|
282
|
+
expect(Refile.attachment_upload_url(instance, :document)).to eq("http://elabs.se/cache")
|
283
|
+
end
|
284
|
+
|
285
|
+
it "does not fall back to Refile.cdn_host" do
|
286
|
+
allow(Refile).to receive(:cdn_host).and_return("http://foo.cloudfront.com")
|
287
|
+
|
288
|
+
expect(Refile.attachment_upload_url(instance, :document)).to eq("/cache")
|
289
|
+
end
|
290
|
+
|
291
|
+
it "adds a prefix" do
|
292
|
+
expect(Refile.attachment_upload_url(instance, :document, prefix: "/moo")).to eq("/moo/cache")
|
293
|
+
end
|
294
|
+
|
295
|
+
it "takes prefix from Refile.mount_point" do
|
296
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
297
|
+
expect(Refile.attachment_upload_url(instance, :document)).to eq("/attachments/cache")
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe ".attachment_presign_url" do
|
302
|
+
it "generates an upload url" do
|
303
|
+
expect(Refile.attachment_presign_url(instance, :document)).to eq("/cache/presign")
|
304
|
+
end
|
305
|
+
|
306
|
+
it "uses supplied host option" do
|
307
|
+
expect(Refile.attachment_presign_url(instance, :document, host: "http://example.org")).to eq("http://example.org/cache/presign")
|
308
|
+
end
|
309
|
+
|
310
|
+
it "falls back to Refile.app_host" do
|
311
|
+
allow(Refile).to receive(:app_host).and_return("http://elabs.se")
|
312
|
+
|
313
|
+
expect(Refile.attachment_presign_url(instance, :document)).to eq("http://elabs.se/cache/presign")
|
314
|
+
end
|
315
|
+
|
316
|
+
it "does not fall back to Refile.cdn_host" do
|
317
|
+
allow(Refile).to receive(:cdn_host).and_return("http://foo.cloudfront.com")
|
318
|
+
|
319
|
+
expect(Refile.attachment_presign_url(instance, :document)).to eq("/cache/presign")
|
320
|
+
end
|
321
|
+
|
322
|
+
it "adds a prefix" do
|
323
|
+
expect(Refile.attachment_presign_url(instance, :document, prefix: "/moo")).to eq("/moo/cache/presign")
|
324
|
+
end
|
325
|
+
|
326
|
+
it "takes prefix from Refile.mount_point" do
|
327
|
+
allow(Refile).to receive(:mount_point).and_return("/attachments")
|
328
|
+
expect(Refile.attachment_presign_url(instance, :document)).to eq("/attachments/cache/presign")
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
describe ".token" do
|
333
|
+
before do
|
334
|
+
allow(Refile).to receive(:token).and_call_original
|
335
|
+
end
|
336
|
+
|
337
|
+
it "returns digest of given path and secret token" do
|
338
|
+
allow(Refile).to receive(:secret_key).and_return("abcd1234")
|
339
|
+
|
340
|
+
path = "/store/f5f2e4/document.pdf"
|
341
|
+
token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), "abcd1234", path)
|
342
|
+
expect(Refile.token(path)).to eq(token)
|
343
|
+
end
|
344
|
+
|
345
|
+
it "returns raise error when secret token is nil" do
|
346
|
+
allow(Refile).to receive(:secret_key).and_return(nil)
|
347
|
+
|
348
|
+
expect { Refile.token("/store/f5f2e4/document.pdf") }.to raise_error(RuntimeError, /Refile\.secret_key was not set/)
|
349
|
+
end
|
350
|
+
end
|
122
351
|
end
|