hydra-works 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hydra/works.rb +7 -0
- data/lib/hydra/works/services/virus_checker_service.rb +3 -36
- data/lib/hydra/works/version.rb +1 -1
- data/lib/hydra/works/virus_scanner.rb +56 -0
- data/spec/hydra/works/services/virus_checker_service_spec.rb +5 -48
- data/spec/hydra/works/virus_scanner_spec.rb +48 -0
- data/spec/hydra/works_spec.rb +5 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ab0358efa05c2000773dbf94f9fdce307613889
|
4
|
+
data.tar.gz: 15dddd5f77310395add9882e5cf2887135bf0721
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2063fa30e2d4f5d26cd34d8b6968bcb046b414375a3c704974f10678630f4d72bf4bc92cec360734b6119c539b30eb28c3143b544cf7d9026e7b75d5ee95d151
|
7
|
+
data.tar.gz: 9002fa2a214853d15d44ff95eb96009d8d78c0a3e6bc826309d0bb7475cc0de7b69c7c4a9d69a8c6d5aa27433d3d152a200ba246e56faa35c7986483d00ac8db
|
data/lib/hydra/works.rb
CHANGED
@@ -6,6 +6,13 @@ module Hydra
|
|
6
6
|
module Works
|
7
7
|
extend ActiveSupport::Autoload
|
8
8
|
|
9
|
+
autoload :VirusScanner
|
10
|
+
|
11
|
+
class << self
|
12
|
+
class_attribute :default_system_virus_scanner
|
13
|
+
self.default_system_virus_scanner = VirusScanner
|
14
|
+
end
|
15
|
+
|
9
16
|
module Vocab
|
10
17
|
extend ActiveSupport::Autoload
|
11
18
|
eager_autoload do
|
@@ -6,14 +6,12 @@ module Hydra::Works
|
|
6
6
|
|
7
7
|
# @api public
|
8
8
|
# @param original_file [String, #path]
|
9
|
-
# @return true
|
10
|
-
# @return true if anti-virus was not able to run
|
11
|
-
# @return false if the file was scanned and no viruses were found
|
9
|
+
# @return true or false result from system_virus_scanner
|
12
10
|
def self.file_has_virus?(original_file)
|
13
11
|
new(original_file).file_has_virus?
|
14
12
|
end
|
15
13
|
|
16
|
-
def initialize(original_file, system_virus_scanner = default_system_virus_scanner)
|
14
|
+
def initialize(original_file, system_virus_scanner = Hydra::Works.default_system_virus_scanner)
|
17
15
|
self.original_file = original_file
|
18
16
|
self.system_virus_scanner = system_virus_scanner
|
19
17
|
end
|
@@ -21,42 +19,11 @@ module Hydra::Works
|
|
21
19
|
# Default behavior is to raise a validation error and halt the save if a virus is found
|
22
20
|
def file_has_virus?
|
23
21
|
path = original_file.is_a?(String) ? original_file : local_path_for_file(original_file)
|
24
|
-
|
25
|
-
handle_virus_scan_results(path, scan_result)
|
22
|
+
system_virus_scanner.infected?(path)
|
26
23
|
end
|
27
24
|
|
28
25
|
private
|
29
26
|
|
30
|
-
# Stubbing out the behavior of "The Clam" was growing into a rather nasty
|
31
|
-
# challenge. So instead I'm injecting a system scanner. This allows me to
|
32
|
-
# now test the default system scanner in isolation from the general response
|
33
|
-
# to a system scan.
|
34
|
-
def default_system_virus_scanner
|
35
|
-
if defined?(ClamAV)
|
36
|
-
ClamAV.instance.method(:scanfile)
|
37
|
-
else
|
38
|
-
lambda do |_path|
|
39
|
-
:no_anti_virus_was_run
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def handle_virus_scan_results(path, scan_result)
|
45
|
-
case scan_result
|
46
|
-
when 0 then return false
|
47
|
-
when 1
|
48
|
-
warning("A virus was found in #{path}: #{scan_result}")
|
49
|
-
true
|
50
|
-
else
|
51
|
-
warning "Virus checking disabled, #{path} not checked"
|
52
|
-
true
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def warning(msg)
|
57
|
-
ActiveFedora::Base.logger.warn msg if ActiveFedora::Base.logger
|
58
|
-
end
|
59
|
-
|
60
27
|
# Returns a path for reading the content of +file+
|
61
28
|
# @param [File] file object to retrieve a path for
|
62
29
|
def local_path_for_file(file)
|
data/lib/hydra/works/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
# The default virus scanner for Hydra::Works
|
2
|
+
# If ClamAV is present, it will be used to check for the presence of a virus. If ClamAV is not
|
3
|
+
# installed or otherwise not available to your application, Hydra::Works does no virus checking
|
4
|
+
# add assumes files have no viruses.
|
5
|
+
#
|
6
|
+
# To use a virus checker other than ClamAV:
|
7
|
+
# class MyScanner < Hydra::Works::VirusScanner
|
8
|
+
# def infected?
|
9
|
+
# my_result = Scanner.check_for_viruses(file)
|
10
|
+
# [return true or false]
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# Then set Hydra::Works to use your scanner either in a config file or initializer:
|
15
|
+
# Hydra::Works.default_system_virus_scanner = MyScanner
|
16
|
+
module Hydra::Works
|
17
|
+
class VirusScanner
|
18
|
+
attr_reader :file
|
19
|
+
|
20
|
+
# @api public
|
21
|
+
# @param file [String]
|
22
|
+
def self.infected?(file)
|
23
|
+
new(file).infected?
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(file)
|
27
|
+
@file = file
|
28
|
+
end
|
29
|
+
|
30
|
+
# Override this method to use your own virus checking software
|
31
|
+
# @return [Boolean]
|
32
|
+
def infected?
|
33
|
+
defined?(ClamAV) ? clam_av_scanner : null_scanner
|
34
|
+
end
|
35
|
+
|
36
|
+
def clam_av_scanner
|
37
|
+
scan_result = ClamAV.instance.method(:scanfile).call(file)
|
38
|
+
return false if scan_result == 0
|
39
|
+
warning "A virus was found in #{file}: #{scan_result}"
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Always return zero if there's nothing available to check for viruses. This means that
|
44
|
+
# we assume all files have no viruses because we can't conclusively say if they have or not.
|
45
|
+
def null_scanner
|
46
|
+
warning "Unable to check #{file} for viruses because no virus scanner is defined"
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def warning(msg)
|
53
|
+
ActiveFedora::Base.logger.warn(msg) if ActiveFedora::Base.logger
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hydra::Works::VirusCheckerService do
|
4
|
-
let(:system_virus_scanner) { double
|
4
|
+
let(:system_virus_scanner) { double }
|
5
5
|
let(:file) { Hydra::PCDM::File.new { |f| f.content = File.new(File.join(fixture_path, 'sample-file.pdf')) } }
|
6
6
|
let(:virus_checker) { described_class.new(file, system_virus_scanner) }
|
7
7
|
|
@@ -14,27 +14,17 @@ describe Hydra::Works::VirusCheckerService do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
context 'with a system virus scanner that did not run' do
|
18
|
-
let(:virus_checker) { described_class.new(file) }
|
19
|
-
it 'will return false and set a system warning' do
|
20
|
-
expect(defined?(ClamAV)).to eq(nil) # A bit of a sanity test to make sure the default behaves
|
21
|
-
allow(file).to receive(:path).and_return('/tmp/file.pdf')
|
22
|
-
expect(virus_checker).to receive(:warning).with(kind_of(String))
|
23
|
-
expect(virus_checker.file_has_virus?).to eq(true)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
17
|
context 'with an infected file' do
|
28
18
|
context 'that responds to :path' do
|
29
19
|
it 'will return false' do
|
30
|
-
expect(system_virus_scanner).to receive(:
|
20
|
+
expect(system_virus_scanner).to receive(:infected?).with('/tmp/file.pdf').and_return(true)
|
31
21
|
allow(file).to receive(:path).and_return('/tmp/file.pdf')
|
32
22
|
expect(virus_checker.file_has_virus?).to eq(true)
|
33
23
|
end
|
34
24
|
end
|
35
25
|
context 'that does not respond to :path' do
|
36
26
|
it 'will return false' do
|
37
|
-
expect(system_virus_scanner).to receive(:
|
27
|
+
expect(system_virus_scanner).to receive(:infected?).with(kind_of(String)).and_return(true)
|
38
28
|
allow(file).to receive(:respond_to?).and_call_original
|
39
29
|
allow(file).to receive(:respond_to?).with(:path).and_return(false)
|
40
30
|
expect(virus_checker.file_has_virus?).to eq(true)
|
@@ -45,51 +35,18 @@ describe Hydra::Works::VirusCheckerService do
|
|
45
35
|
context 'with a clean file' do
|
46
36
|
context 'that responds to :path' do
|
47
37
|
it 'will return true' do
|
48
|
-
expect(system_virus_scanner).to receive(:
|
38
|
+
expect(system_virus_scanner).to receive(:infected?).with('/tmp/file.pdf').and_return(false)
|
49
39
|
allow(file).to receive(:path).and_return('/tmp/file.pdf')
|
50
40
|
expect(virus_checker.file_has_virus?).to eq(false)
|
51
41
|
end
|
52
42
|
end
|
53
43
|
context 'that does not respond to :path' do
|
54
44
|
it 'will return true' do
|
55
|
-
expect(system_virus_scanner).to receive(:
|
45
|
+
expect(system_virus_scanner).to receive(:infected?).with(kind_of(String)).and_return(false)
|
56
46
|
allow(file).to receive(:respond_to?).and_call_original
|
57
47
|
allow(file).to receive(:respond_to?).with(:path).and_return(false)
|
58
48
|
expect(virus_checker.file_has_virus?).to eq(false)
|
59
49
|
end
|
60
50
|
end
|
61
51
|
end
|
62
|
-
|
63
|
-
context '#default_system_virus_scanner' do
|
64
|
-
let(:virus_checker) { described_class.new(file) }
|
65
|
-
let(:system_virus_scanner) { virus_checker.send(:default_system_virus_scanner) }
|
66
|
-
it 'is callable' do
|
67
|
-
expect(system_virus_scanner).to respond_to(:call)
|
68
|
-
end
|
69
|
-
context 'when called and ClamAV is NOT defined' do
|
70
|
-
it 'will warn and return :no_anti_virus_was_run if ClamAV is not defined' do
|
71
|
-
expect(system_virus_scanner.call('/tmp/path')).to eq(:no_anti_virus_was_run)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
context 'when called and ClamAV is defined' do
|
75
|
-
before do
|
76
|
-
class ClamAV
|
77
|
-
def self.instance
|
78
|
-
@instance ||= ClamAV.new
|
79
|
-
end
|
80
|
-
|
81
|
-
def scanfile(path)
|
82
|
-
puts "scanfile: #{path}"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
after do
|
87
|
-
Object.send(:remove_const, :ClamAV)
|
88
|
-
end
|
89
|
-
it "will call the Clam's scanfile" do
|
90
|
-
expect(ClamAV.instance).to receive(:scanfile).with('/tmp/path')
|
91
|
-
system_virus_scanner.call('/tmp/path')
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
52
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::Works::VirusScanner do
|
4
|
+
let(:file) { '/tmp/path' }
|
5
|
+
let(:logger) { Logger.new(nil) }
|
6
|
+
|
7
|
+
before { allow(ActiveFedora::Base).to receive(:logger).and_return(logger) }
|
8
|
+
|
9
|
+
subject { described_class.new(file) }
|
10
|
+
|
11
|
+
context 'when ClamAV is defined' do
|
12
|
+
before do
|
13
|
+
class ClamAV
|
14
|
+
def self.instance
|
15
|
+
@instance ||= ClamAV.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def scanfile(path)
|
19
|
+
puts "scanfile: #{path}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
after do
|
24
|
+
Object.send(:remove_const, :ClamAV)
|
25
|
+
end
|
26
|
+
context 'with a clean file' do
|
27
|
+
before { allow(ClamAV.instance).to receive(:scanfile).with('/tmp/path').and_return(0) }
|
28
|
+
it 'returns false with no warning' do
|
29
|
+
expect(ActiveFedora::Base.logger).not_to receive(:warn)
|
30
|
+
is_expected.not_to be_infected
|
31
|
+
end
|
32
|
+
end
|
33
|
+
context 'with an infected file' do
|
34
|
+
before { allow(ClamAV.instance).to receive(:scanfile).with('/tmp/path').and_return(1) }
|
35
|
+
it 'returns true with a warning' do
|
36
|
+
expect(ActiveFedora::Base.logger).to receive(:warn).with(kind_of(String))
|
37
|
+
is_expected.to be_infected
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when ClamAV is not defined' do
|
43
|
+
it 'returns false with a warning' do
|
44
|
+
expect(ActiveFedora::Base.logger).to receive(:warn).with(kind_of(String))
|
45
|
+
is_expected.not_to be_infected
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/hydra/works_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hydra-works
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Coyne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hydra-pcdm
|
@@ -217,6 +217,7 @@ files:
|
|
217
217
|
- lib/hydra/works/services/upload_file_to_file_set.rb
|
218
218
|
- lib/hydra/works/services/virus_checker_service.rb
|
219
219
|
- lib/hydra/works/version.rb
|
220
|
+
- lib/hydra/works/virus_scanner.rb
|
220
221
|
- lib/hydra/works/vocab/works_terms.rb
|
221
222
|
- solr/config/_rest_managed.json
|
222
223
|
- solr/config/admin-extra.html
|
@@ -270,6 +271,7 @@ files:
|
|
270
271
|
- spec/hydra/works/services/persist_derivatives_spec.rb
|
271
272
|
- spec/hydra/works/services/upload_file_spec.rb
|
272
273
|
- spec/hydra/works/services/virus_checker_service_spec.rb
|
274
|
+
- spec/hydra/works/virus_scanner_spec.rb
|
273
275
|
- spec/hydra/works_spec.rb
|
274
276
|
- spec/spec_helper.rb
|
275
277
|
- spec/support/file_set_helper.rb
|
@@ -302,7 +304,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
302
304
|
version: '0'
|
303
305
|
requirements: []
|
304
306
|
rubyforge_project:
|
305
|
-
rubygems_version: 2.
|
307
|
+
rubygems_version: 2.4.8
|
306
308
|
signing_key:
|
307
309
|
specification_version: 4
|
308
310
|
summary: Fundamental repository data model for hydra
|
@@ -343,6 +345,7 @@ test_files:
|
|
343
345
|
- spec/hydra/works/services/persist_derivatives_spec.rb
|
344
346
|
- spec/hydra/works/services/upload_file_spec.rb
|
345
347
|
- spec/hydra/works/services/virus_checker_service_spec.rb
|
348
|
+
- spec/hydra/works/virus_scanner_spec.rb
|
346
349
|
- spec/hydra/works_spec.rb
|
347
350
|
- spec/spec_helper.rb
|
348
351
|
- spec/support/file_set_helper.rb
|