ratonvirus 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7fa55b1025e3d8099f86b8b9e9157cbd4473980441aac2c7acc98b92cf2c3ff6
4
- data.tar.gz: f219700545adb3593677af4fad1bb9d198892fc94bd128101a817169118254a0
3
+ metadata.gz: a0ee734de35bb79c99398afaf866f42c87e023aa4ab813ee8e582f4a1ea89597
4
+ data.tar.gz: 3d15112835af1745bf61d7d7a0d6017a31b4e1d638211d26e909564baa19e733
5
5
  SHA512:
6
- metadata.gz: 5fcd623e174c648393cc5489c27ce685ee0da9282a7289122a537daacff67950323123e7698da610af6a77b19b63753accb41ca22d06098dc95f4f8d41a109f9
7
- data.tar.gz: 85100d78a0e6a476cb4c4e3dde833381e7ac2219d4c9127cef4f07458b8ca56ba3a0977275f5d715f64cbab7989bbcb047c733dade35e6d6a95192b48005d0bd
6
+ metadata.gz: a663b2d27b3c98c8f4d83093cb87f4dc5f7ad87cdd8897358a923d1105ff69cfcd1bbb10831b657aad6d1bf1ef84a7b1ef42ed4817eccdb27782fbf081be3b7d
7
+ data.tar.gz: 5ba1e916ee109f4988c46c6bc325be84616af57f9a35b28390f55ea616b24a15de6a812d4dcbc58df11006b1d80b2636b4880c70abd45e517551392d64afc239
data/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ # v0.3.0
2
+
3
+ Changed:
4
+
5
+ - Minimum Ruby version is now set to 2.5
6
+
7
+ Fixed:
8
+
9
+ - Issue related with scanning files with CarrierWave storage engine using remote storage engines such as Fog. Related
10
+ to [#9](https://github.com/mainio/ratonvirus/pull/9)
11
+
12
+ # v0.2.0
13
+
14
+ Support for Rails 6
15
+
16
+ The ActiveStorage storage engine has been updated and partly rewritten due to changes in its API. The new API introduces
17
+ a changes concept in the library which this update takes in to account. In the new API, the blobs will not get uploaded
18
+ to the storage service before the validations have been successful, which led to rethinking how this storage engine
19
+ works in Ratonvirus.
20
+
21
+
1
22
  # v0.1.1
2
23
 
3
24
  Fixed:
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Rails antivirus made easy.
4
4
  Developed by [Mainio Tech](https://www.mainiotech.fi/).
5
5
 
6
- [![Build Status](https://travis-ci.org/mainio/ratonvirus.svg?branch=master)](https://travis-ci.org/mainio/ratonvirus)
6
+ [![Build Status](https://github.com/mainio/ratonvirus/actions/workflows/ci_ratonvirus.yml/badge.svg)](https://github.com/mainio/ratonvirus/actions)
7
7
  [![codecov](https://codecov.io/gh/mainio/ratonvirus/branch/master/graph/badge.svg)](https://codecov.io/gh/mainio/ratonvirus)
8
8
 
9
9
  Ratonvirus allows your Rails application to rat on the viruses that your users
data/lib/ratonvirus.rb CHANGED
@@ -12,6 +12,7 @@ require_relative "ratonvirus/scanner/support/callbacks"
12
12
  require_relative "ratonvirus/scanner/base"
13
13
  require_relative "ratonvirus/scanner/eicar"
14
14
  require_relative "ratonvirus/scanner/addon/remove_infected"
15
+ require_relative "ratonvirus/storage/support/io_handling"
15
16
  require_relative "ratonvirus/storage/base"
16
17
  require_relative "ratonvirus/storage/filepath"
17
18
  require_relative "ratonvirus/storage/active_storage"
@@ -4,6 +4,8 @@ module Ratonvirus
4
4
  class Error < StandardError; end
5
5
 
6
6
  class InvalidError < Error; end
7
+
7
8
  class NotDefinedError < Error; end
9
+
8
10
  class NotImplementedError < Error; end
9
11
  end
@@ -11,8 +11,8 @@ module Ratonvirus
11
11
  end
12
12
  end
13
13
 
14
- attr_reader :config
15
- attr_reader :errors # Only available after `virus?` has been called.
14
+ # :errors - Only available after `virus?` has been called.
15
+ attr_reader :config, :errors
16
16
 
17
17
  def initialize(configuration = {})
18
18
  @config = default_config.merge!(configuration)
@@ -19,11 +19,11 @@ module Ratonvirus
19
19
  protected
20
20
 
21
21
  def run_scan(path)
22
- if !File.file?(path)
23
- errors << :antivirus_file_not_found
24
- else
22
+ if File.file?(path)
25
23
  sha256 = Digest::SHA256.file path
26
24
  errors << :antivirus_virus_detected if sha256 == EICAR_SHA256
25
+ else
26
+ errors << :antivirus_file_not_found
27
27
  end
28
28
  rescue StandardError
29
29
  errors << :antivirus_client_error
@@ -3,6 +3,8 @@
3
3
  module Ratonvirus
4
4
  module Storage
5
5
  class ActiveStorage < Base
6
+ include Ratonvirus::Storage::Support::IoHandling
7
+
6
8
  def changed?(record, attribute)
7
9
  resource = record.public_send attribute
8
10
  !resource.record.attachment_changes[resource.name].nil?
@@ -20,9 +22,10 @@ module Ratonvirus
20
22
 
21
23
  change = resource.record.attachment_changes[resource.name]
22
24
 
23
- if change.is_a?(::ActiveStorage::Attached::Changes::CreateOne)
25
+ case change
26
+ when ::ActiveStorage::Attached::Changes::CreateOne
24
27
  handle_create_one(change, &block)
25
- elsif change.is_a?(::ActiveStorage::Attached::Changes::CreateMany)
28
+ when ::ActiveStorage::Attached::Changes::CreateMany
26
29
  handle_create_many(change, &block)
27
30
  end
28
31
  end
@@ -101,39 +104,6 @@ module Ratonvirus
101
104
 
102
105
  yield processable([change.attachment, attachable])
103
106
  end
104
-
105
- # This creates a local copy of the io contents for the scanning process. A
106
- # local copy is needed for processing because the io object may be a file
107
- # stream in the memory which may not have a path associated with it on the
108
- # filesystem.
109
- def io_path(io, extension)
110
- tempfile = Tempfile.open(
111
- ["Ratonvirus", extension],
112
- tempdir
113
- )
114
- # Important for the scanner to be able to access the file.
115
- prepare_for_scanner tempfile.path
116
-
117
- begin
118
- tempfile.binmode
119
- IO.copy_stream(io, tempfile)
120
- tempfile.flush
121
- tempfile.rewind
122
-
123
- yield tempfile.path
124
- ensure
125
- tempfile.close!
126
- end
127
- end
128
-
129
- def tempdir
130
- Dir.tmpdir
131
- end
132
-
133
- def prepare_for_scanner(filepath)
134
- # Important for the scanner to be able to access the file.
135
- File.chmod(0o644, filepath)
136
- end
137
107
  end
138
108
  end
139
109
  end
@@ -3,6 +3,8 @@
3
3
  module Ratonvirus
4
4
  module Storage
5
5
  class Carrierwave < Base
6
+ include Ratonvirus::Storage::Support::IoHandling
7
+
6
8
  def changed?(record, attribute)
7
9
  record.public_send :"#{attribute}_changed?"
8
10
  end
@@ -15,12 +17,22 @@ module Ratonvirus
15
17
  end
16
18
  end
17
19
 
18
- def asset_path(asset)
20
+ def asset_path(asset, &block)
19
21
  return unless block_given?
20
22
  return if asset.nil?
21
23
  return if asset.file.nil?
22
24
 
23
- yield asset.file.path
25
+ # If the file is a local SanitizedFile, it is faster to run the scan
26
+ # directly against that file instead of copying it to a tempfile first
27
+ # as below for external file storages.
28
+ return yield asset.file.path if asset.file.is_a?(::CarrierWave::SanitizedFile)
29
+
30
+ # The file could be externally stored, so we need to read it to memory
31
+ # in order to create a temporary file for the scanner to perform the
32
+ # scan on.
33
+ io = StringIO.new(asset.file.read)
34
+ ext = File.extname(asset.file.path)
35
+ io_path(io, ext, &block)
24
36
  end
25
37
 
26
38
  def asset_remove(asset)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
4
+
5
+ module Ratonvirus
6
+ module Storage
7
+ module Support
8
+ module IoHandling
9
+ private
10
+
11
+ # This creates a local copy of the io contents for the scanning process.
12
+ # A local copy is needed for processing because the io object may be a
13
+ # file stream in the memory which may not have a path associated with it
14
+ # on the filesystem.
15
+ def io_path(io, extension)
16
+ tempfile = Tempfile.open(
17
+ ["Ratonvirus", extension],
18
+ tempdir
19
+ )
20
+ # Important for the scanner to be able to access the file.
21
+ prepare_for_scanner tempfile.path
22
+
23
+ begin
24
+ tempfile.binmode
25
+ IO.copy_stream(io, tempfile)
26
+ tempfile.flush
27
+ tempfile.rewind
28
+
29
+ yield tempfile.path
30
+ ensure
31
+ tempfile.close!
32
+ end
33
+ end
34
+
35
+ def tempdir
36
+ Dir.tmpdir
37
+ end
38
+
39
+ def prepare_for_scanner(filepath)
40
+ # Important for the scanner to be able to access the file.
41
+ File.chmod(0o644, filepath)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -88,37 +88,37 @@ module Ratonvirus
88
88
  def define_backend(backend_type, backend_subclass)
89
89
  class_eval <<-CODE, __FILE__, __LINE__ + 1
90
90
  # Getter for #{backend_type}
91
- def self.#{backend_type}
92
- @#{backend_type} ||= create_#{backend_type}
93
- end
91
+ def self.#{backend_type} # def self.foo
92
+ @#{backend_type} ||= create_#{backend_type} # @foo ||= create_foo
93
+ end # end
94
94
 
95
95
  # Setter for #{backend_type}
96
- def self.#{backend_type}=(#{backend_type}_value)
97
- set_backend(
98
- :#{backend_type},
99
- "#{backend_subclass}",
100
- #{backend_type}_value
101
- )
102
- end
96
+ def self.#{backend_type}=(#{backend_type}_value) # def self.foo=(foo_value)
97
+ set_backend( # set_backend(
98
+ :#{backend_type}, # :foo
99
+ "#{backend_subclass}", # "Foo"
100
+ #{backend_type}_value # foo_value
101
+ ) # )
102
+ end # end
103
103
 
104
104
  # Destroys the currently active #{backend_type}.
105
105
  # The #{backend_type} is re-initialized when the getter is called.
106
- def self.destroy_#{backend_type}
107
- @#{backend_type} = nil
108
- end
106
+ def self.destroy_#{backend_type} # def self.destroy_foo
107
+ @#{backend_type} = nil # @foo = nil
108
+ end # end
109
109
 
110
110
  # Creates a new backend instance
111
111
  # private
112
- def self.create_#{backend_type}
113
- if @#{backend_type}_defs.nil?
114
- raise NotDefinedError.new("#{backend_subclass} not defined!")
115
- end
116
-
117
- @#{backend_type}_defs[:klass].new(
118
- @#{backend_type}_defs[:config]
119
- )
120
- end
121
- private_class_method :create_#{backend_type}
112
+ def self.create_#{backend_type} # def self.create_foo
113
+ if @#{backend_type}_defs.nil? # if @foo_defs.nil?
114
+ raise NotDefinedError.new("#{backend_subclass} not defined!") # raise NotDefinedError.new("Foo not defined")
115
+ end # end
116
+ #
117
+ @#{backend_type}_defs[:klass].new( # @foo_defs[:klass].new(
118
+ @#{backend_type}_defs[:config] # @foo_defs[:config]
119
+ ) # )
120
+ end # end
121
+ private_class_method :create_#{backend_type} # private_class_method :create_foo
122
122
  CODE
123
123
  end
124
124
 
@@ -154,12 +154,13 @@ module Ratonvirus
154
154
  subtype = backend_value.class
155
155
  config = backend_value.config
156
156
  else
157
- if backend_value.is_a?(Array)
157
+ case backend_value
158
+ when Array
158
159
  subtype = backend_value.shift
159
160
  config = backend_value.shift || {}
160
161
 
161
162
  raise InvalidError, "Invalid #{backend_type} type: #{subtype}" unless subtype.is_a?(Symbol)
162
- elsif backend_value.is_a?(Symbol)
163
+ when Symbol
163
164
  subtype = backend_value
164
165
  config = {}
165
166
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ratonvirus
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ratonvirus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Antti Hukkanen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-27 00:00:00.000000000 Z
11
+ date: 2021-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -128,28 +128,28 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.86.0
131
+ version: 1.11.0
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 0.86.0
138
+ version: 1.11.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rubocop-rspec
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '1.40'
145
+ version: 2.2.0
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '1.40'
152
+ version: 2.2.0
153
153
  description: Adds antivirus check capability for Rails applications.
154
154
  email:
155
155
  - antti.hukkanen@mainiotech.fi
@@ -177,6 +177,7 @@ files:
177
177
  - lib/ratonvirus/storage/carrierwave.rb
178
178
  - lib/ratonvirus/storage/filepath.rb
179
179
  - lib/ratonvirus/storage/multi.rb
180
+ - lib/ratonvirus/storage/support/io_handling.rb
180
181
  - lib/ratonvirus/support/backend.rb
181
182
  - lib/ratonvirus/version.rb
182
183
  - lib/tasks/ratonvirus.rake
@@ -192,7 +193,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
193
  requirements:
193
194
  - - ">="
194
195
  - !ruby/object:Gem::Version
195
- version: '0'
196
+ version: '2.5'
196
197
  required_rubygems_version: !ruby/object:Gem::Requirement
197
198
  requirements:
198
199
  - - ">="