mini_paperclip 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +40 -0
  3. data/.gitignore +14 -0
  4. data/.rspec +3 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +12 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +175 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/gemfiles/rails_52.gemfile +10 -0
  13. data/gemfiles/rails_52.gemfile.lock +98 -0
  14. data/gemfiles/rails_60.gemfile +10 -0
  15. data/gemfiles/rails_60.gemfile.lock +98 -0
  16. data/lib/mini_paperclip.rb +41 -0
  17. data/lib/mini_paperclip/attachment.rb +190 -0
  18. data/lib/mini_paperclip/class_methods.rb +62 -0
  19. data/lib/mini_paperclip/config.rb +32 -0
  20. data/lib/mini_paperclip/interpolator.rb +41 -0
  21. data/lib/mini_paperclip/shoulda/matchers.rb +7 -0
  22. data/lib/mini_paperclip/shoulda/matchers/have_attached_file_matcher.rb +46 -0
  23. data/lib/mini_paperclip/shoulda/matchers/validate_attachment_content_type_matcher.rb +84 -0
  24. data/lib/mini_paperclip/shoulda/matchers/validate_attachment_geometry_matcher.rb +111 -0
  25. data/lib/mini_paperclip/shoulda/matchers/validate_attachment_presence_matcher.rb +52 -0
  26. data/lib/mini_paperclip/shoulda/matchers/validate_attachment_size_matcher.rb +62 -0
  27. data/lib/mini_paperclip/storage.rb +5 -0
  28. data/lib/mini_paperclip/storage/base.rb +39 -0
  29. data/lib/mini_paperclip/storage/filesystem.rb +34 -0
  30. data/lib/mini_paperclip/storage/s3.rb +49 -0
  31. data/lib/mini_paperclip/validators.rb +7 -0
  32. data/lib/mini_paperclip/validators/content_type_validator.rb +17 -0
  33. data/lib/mini_paperclip/validators/file_size_validator.rb +21 -0
  34. data/lib/mini_paperclip/validators/geometry_validator.rb +46 -0
  35. data/lib/mini_paperclip/validators/media_type_spoof_validator.rb +25 -0
  36. data/lib/mini_paperclip/validators/presence_validator.rb +13 -0
  37. data/lib/mini_paperclip/version.rb +5 -0
  38. data/mini_paperclip.gemspec +32 -0
  39. metadata +152 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ module Storage
5
+ class S3 < Base
6
+ def write(style, file)
7
+ debug("writing by S3 to bucket:#{@config.s3_bucket_name},key:#{s3_object_key(style)}")
8
+ Aws::S3::Client.new.put_object(
9
+ acl: @config.s3_acl,
10
+ cache_control: @config.s3_cache_control,
11
+ content_type: @record.read_attribute("#{@attachment_name}_content_type"),
12
+ body: file.tap(&:rewind),
13
+ bucket: @config.s3_bucket_name,
14
+ key: s3_object_key(style),
15
+ )
16
+ end
17
+
18
+ def copy(style, from_attachment)
19
+ raise "not supported yet" unless from_attachment.storage.instance_of?(S3)
20
+ debug("copying by S3 to bucket:#{@config.s3_bucket_name},key:#{s3_object_key(style)}")
21
+ Aws::S3::Client.new.copy_object(
22
+ acl: @config.s3_acl,
23
+ cache_control: @config.s3_cache_control,
24
+ content_type: @record.read_attribute("#{@attachment_name}_content_type"),
25
+ copy_source: from_attachment.storage.object_key(style),
26
+ bucket: @config.s3_bucket_name,
27
+ key: s3_object_key(style),
28
+ )
29
+ end
30
+
31
+ def s3_object_key(style)
32
+ interpolate(@config.url_path, style)
33
+ end
34
+
35
+ def host
36
+ # AWS CloudFront origin should be attached bucket name
37
+ @config.s3_host_alias || "#{@config.s3_bucket_name}.#{@config.url_host}"
38
+ end
39
+
40
+ def exists?(style)
41
+ res = Aws::S3::Client.new.head_object(
42
+ bucket: @config.s3_bucket_name,
43
+ key: s3_object_key(style),
44
+ )
45
+ res.content_length.to_i != 0
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mini_paperclip/validators/content_type_validator"
4
+ require "mini_paperclip/validators/file_size_validator"
5
+ require "mini_paperclip/validators/geometry_validator"
6
+ require "mini_paperclip/validators/media_type_spoof_validator"
7
+ require "mini_paperclip/validators/presence_validator"
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ module Validators
5
+ class ContentTypeValidator < ActiveModel::EachValidator
6
+ def validate_each(record, attribute, value)
7
+ allows = Array(options[:content_type])
8
+ attachment_content_type_name = "#{attribute}_content_type"
9
+ attachment_content_type = record.read_attribute_for_validation(attachment_content_type_name)
10
+ if attachment_content_type && !allows.include?(attachment_content_type)
11
+ record.errors.add(attribute, :invalid)
12
+ record.errors.add(attachment_content_type_name, :invalid)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ module Validators
5
+ class FileSizeValidator < ActiveModel::EachValidator
6
+ def validate_each(record, attribute, value)
7
+ attachment_file_size_name = "#{attribute}_file_size"
8
+ attachment_file_size = record.read_attribute_for_validation(attachment_file_size_name)
9
+ if attachment_file_size
10
+ if check_value = options[:less_than]
11
+ unless attachment_file_size < check_value
12
+ count = ActiveSupport::NumberHelper.number_to_human_size(check_value)
13
+ record.errors.add(attribute, :less_than, { count: count })
14
+ record.errors.add(attachment_file_size_name, :less_than, { count: count })
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ module Validators
5
+ class GeometryValidator < ActiveModel::EachValidator
6
+ Error = Class.new(StandardError)
7
+ ALLOW_OPTIONS = [:less_than_or_equal_to]
8
+
9
+ def check_validity!
10
+ [:width, :height].each do |key|
11
+ if options[key]
12
+ keys = ALLOW_OPTIONS & options[key].keys
13
+ if keys.empty?
14
+ raise ArgumentError, ":#{key} option should specify the :less_than_or_equal_to ."
15
+ end
16
+ end
17
+ end
18
+ end
19
+ # validate_attachment :image,
20
+ # geometry: {
21
+ # width: { less_than_or_equal_to: 3000 },
22
+ # height: { less_than_or_equal_to: 3000 } }
23
+ def validate_each(record, attribute, value)
24
+ return unless value.waiting_write_file
25
+ geometry_string = MiniMagick::Tool::Identify.new do |identify|
26
+ identify.format "%w,%h"
27
+ identify << value.waiting_write_file.path
28
+ end
29
+ return unless !geometry_string.empty?
30
+ width, height = geometry_string.split(',').map(&:to_i)
31
+
32
+ expected_width_less_than_or_equal_to = options.dig(:width, :less_than_or_equal_to)
33
+ expected_height_less_than_or_equal_to = options.dig(:height, :less_than_or_equal_to)
34
+ unless (!expected_width_less_than_or_equal_to || width <= expected_width_less_than_or_equal_to) &&
35
+ (!expected_height_less_than_or_equal_to || height <= expected_height_less_than_or_equal_to)
36
+ record.errors.add(attribute, :geometry, {
37
+ actual_width: width,
38
+ actual_height: height,
39
+ expected_width_less_than_or_equal_to: expected_width_less_than_or_equal_to,
40
+ expected_height_less_than_or_equal_to: expected_height_less_than_or_equal_to,
41
+ })
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ module Validators
5
+ class MediaTypeSpoofValidator < ActiveModel::EachValidator
6
+ def validate_each(record, attribute, attachment)
7
+ return unless attachment.meta_content_type
8
+
9
+ attachment_content_type = record.read_attribute_for_validation("#{attribute}_content_type")
10
+ unless normalize(attachment.meta_content_type) == normalize(attachment_content_type)
11
+ record.errors.add(attribute, :spoofed_media_type)
12
+ end
13
+ end
14
+
15
+ def normalize(content_type)
16
+ case content_type
17
+ when "image/jpg"
18
+ "image/jpeg"
19
+ else
20
+ content_type
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ module Validators
5
+ class PresenceValidator < ActiveModel::EachValidator
6
+ def validate_each(record, attribute, value)
7
+ if record.read_attribute_for_validation("#{attribute}_file_name").blank?
8
+ record.errors.add(attribute, :blank)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniPaperclip
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'lib/mini_paperclip/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "mini_paperclip"
5
+ spec.version = MiniPaperclip::VERSION
6
+ spec.authors = ["ksss"]
7
+ spec.email = ["co000ri@gmail.com"]
8
+
9
+ spec.summary = %q{MiniPaperclip is a mini paperclip}
10
+ spec.description = %q{Subset from paperclip because paperclip has deprecated}
11
+ spec.homepage = "https://github.com/reproio/mini_paperclip"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ spec.add_runtime_dependency "mini_magick"
16
+ spec.add_runtime_dependency "mimemagic"
17
+ spec.add_runtime_dependency "activemodel"
18
+ spec.add_runtime_dependency "activesupport"
19
+ spec.add_runtime_dependency "aws-sdk-s3"
20
+
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = spec.homepage
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
27
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_paperclip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ksss
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-11-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mini_magick
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mimemagic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activemodel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk-s3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Subset from paperclip because paperclip has deprecated
84
+ email:
85
+ - co000ri@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".github/workflows/ruby.yml"
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - CODE_OF_CONDUCT.md
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - gemfiles/rails_52.gemfile
101
+ - gemfiles/rails_52.gemfile.lock
102
+ - gemfiles/rails_60.gemfile
103
+ - gemfiles/rails_60.gemfile.lock
104
+ - lib/mini_paperclip.rb
105
+ - lib/mini_paperclip/attachment.rb
106
+ - lib/mini_paperclip/class_methods.rb
107
+ - lib/mini_paperclip/config.rb
108
+ - lib/mini_paperclip/interpolator.rb
109
+ - lib/mini_paperclip/shoulda/matchers.rb
110
+ - lib/mini_paperclip/shoulda/matchers/have_attached_file_matcher.rb
111
+ - lib/mini_paperclip/shoulda/matchers/validate_attachment_content_type_matcher.rb
112
+ - lib/mini_paperclip/shoulda/matchers/validate_attachment_geometry_matcher.rb
113
+ - lib/mini_paperclip/shoulda/matchers/validate_attachment_presence_matcher.rb
114
+ - lib/mini_paperclip/shoulda/matchers/validate_attachment_size_matcher.rb
115
+ - lib/mini_paperclip/storage.rb
116
+ - lib/mini_paperclip/storage/base.rb
117
+ - lib/mini_paperclip/storage/filesystem.rb
118
+ - lib/mini_paperclip/storage/s3.rb
119
+ - lib/mini_paperclip/validators.rb
120
+ - lib/mini_paperclip/validators/content_type_validator.rb
121
+ - lib/mini_paperclip/validators/file_size_validator.rb
122
+ - lib/mini_paperclip/validators/geometry_validator.rb
123
+ - lib/mini_paperclip/validators/media_type_spoof_validator.rb
124
+ - lib/mini_paperclip/validators/presence_validator.rb
125
+ - lib/mini_paperclip/version.rb
126
+ - mini_paperclip.gemspec
127
+ homepage: https://github.com/reproio/mini_paperclip
128
+ licenses:
129
+ - MIT
130
+ metadata:
131
+ homepage_uri: https://github.com/reproio/mini_paperclip
132
+ source_code_uri: https://github.com/reproio/mini_paperclip
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 2.3.0
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 3.1.2
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: MiniPaperclip is a mini paperclip
152
+ test_files: []