sanitization 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 380311ca85432700d4426ddb1a6a6e42daa861206d22954a686b4453ef385bff
4
+ data.tar.gz: 8cf63d1d494492d6859a3d97b1e61cfa6921941f4527d0acb7a0ef3b364d5060
5
+ SHA512:
6
+ metadata.gz: f30635f856767f472f4761ffa213043fdcaed98b80129c27862f2bd5295fa7402a87e178b2dfbaffae5848d8ebf27ea5fd2211dd044cc269ceb66b40c2342ac5
7
+ data.tar.gz: 331210228d4cca1c382b7ffd0719735d3e65d42b50480ea51448de466bc9c9d2498bdbb42a980648d0b15abbfef36b2d9c3db4c3502b80c1c6c04e0f19adb6be
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sanitization.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
8
+ gem "temping", "~> 3.0"
9
+ gem "sqlite3"
10
+ gem "byebug"
data/Gemfile.lock ADDED
@@ -0,0 +1,63 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sanitization (1.0.0)
5
+ activerecord
6
+ activesupport
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (6.0.3.2)
12
+ activesupport (= 6.0.3.2)
13
+ activerecord (6.0.3.2)
14
+ activemodel (= 6.0.3.2)
15
+ activesupport (= 6.0.3.2)
16
+ activesupport (6.0.3.2)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (>= 0.7, < 2)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ zeitwerk (~> 2.2, >= 2.2.2)
22
+ byebug (11.1.3)
23
+ concurrent-ruby (1.1.8)
24
+ diff-lcs (1.4.4)
25
+ i18n (1.8.10)
26
+ concurrent-ruby (~> 1.0)
27
+ minitest (5.14.4)
28
+ rake (12.3.3)
29
+ rspec (3.10.0)
30
+ rspec-core (~> 3.10.0)
31
+ rspec-expectations (~> 3.10.0)
32
+ rspec-mocks (~> 3.10.0)
33
+ rspec-core (3.10.1)
34
+ rspec-support (~> 3.10.0)
35
+ rspec-expectations (3.10.1)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.10.0)
38
+ rspec-mocks (3.10.2)
39
+ diff-lcs (>= 1.2.0, < 2.0)
40
+ rspec-support (~> 3.10.0)
41
+ rspec-support (3.10.2)
42
+ sqlite3 (1.4.2)
43
+ temping (3.10.0)
44
+ activerecord (>= 4.2)
45
+ activesupport (>= 4.2)
46
+ thread_safe (0.3.6)
47
+ tzinfo (1.2.8)
48
+ thread_safe (~> 0.1)
49
+ zeitwerk (2.4.2)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ byebug
56
+ rake (~> 12.0)
57
+ rspec (~> 3.0)
58
+ sanitization!
59
+ sqlite3
60
+ temping (~> 3.0)
61
+
62
+ BUNDLED WITH
63
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Carl Mercier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Sanitization
2
+
3
+ Sanitization makes it easy to store slightly cleaner strings to your database.
4
+
5
+ ### Features (all optional):
6
+
7
+ - White space stripping
8
+ - White space collapsing (multiple consecutive spaces combined into one)
9
+ - Empty string to nil (if database column supports it)
10
+ - Change casing (ie. upcase, downcase, titlecase, etc)
11
+
12
+ ### Defaults
13
+
14
+ - Leading & training white spaces are stripped (`strip: true`)
15
+ - All spaces are collapsed (`collapse: true`)
16
+ - All String columns are sanitized (`only: nil, except: nil`)
17
+ - Columns of type `text` are not sanitized (`include_text_type: false`)
18
+ - Casing remains unchanged (`case: nil`)
19
+
20
+
21
+ ## Installation
22
+
23
+ ```sh
24
+ bundle add sanitization
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ # Default settings for all strings
31
+ class Person < ApplicationModel
32
+ sanitization
33
+ # is equivalent to:
34
+ sanitization strip: true, collapse: true, include_text_type: false
35
+ end
36
+
37
+ # Default settings for all strings, except a specific column
38
+ class Person < ApplicationModel
39
+ sanitization except: :alias
40
+ end
41
+
42
+ # Default settings + titlecase for specific columns
43
+ class Person < ApplicationModel
44
+ sanitization only: [:first_name, :last_name], case: :title
45
+ end
46
+
47
+ # Complex example. All these lines could be used in combination.
48
+ class Person
49
+ # Apply default settings and `titlecase` to all string columns, except `description`.
50
+ sanitization case: :title, except: :description
51
+
52
+ # Keep previous settings, but specify `upcase` for 2 columns.
53
+ sanitization only: [:first_name, :last_name], case: :up
54
+
55
+ # Keep previous settings, but specify `downcase` for a single column.
56
+ sanitization only: :email, case: :downcase
57
+
58
+ # Apply default settings to column `description`, of type `text`. By default, `text` type is NOT sanitized.
59
+ sanitization only: :description, include_text_type: true
60
+
61
+ # Disable collapsing for `do_not_collapse`.
62
+ sanitization only: :do_not_collapse, collapse: false
63
+
64
+ # Sanitize with a custom casing method named `leetcase` for the `133t` column.
65
+ sanitization only: '1337', case: :leet
66
+ end
67
+
68
+ ```
69
+
70
+ ## Development
71
+
72
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
73
+
74
+ ## License
75
+
76
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sanitization"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,120 @@
1
+ require 'active_record'
2
+
3
+ module ActiveRecord
4
+ module Sanitization
5
+ def self.append_features(base)
6
+ super
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ attr_accessor :sanitization__store
12
+
13
+ private
14
+ def sanitization(options = {})
15
+ self.sanitization__store ||= {}
16
+
17
+ options[:only] = Array.wrap(options[:only])
18
+ options[:except] = Array.wrap(options[:except])
19
+ options[:strip] = !!(options[:strip].nil? ? true : options[:strip])
20
+ options[:collapse] = !!(options[:collapse].nil? ? true : options[:collapse])
21
+ options[:nullify] = !!(options[:nullify].nil? ? true : options[:nullify])
22
+
23
+ unless options[:case].nil?
24
+ raise ArgumentError.new("Invalid type for `case`: #{options[:case].class}") \
25
+ unless [String, Symbol].include?(options[:case].class)
26
+ options[:case] = options[:case].downcase.to_s
27
+ options[:case] = options[:case] + "case" unless options[:case] =~ /case$/
28
+ end
29
+
30
+ columns_to_format = self.columns.select { |c| c.type == :string }
31
+ columns_to_format = columns_to_format.concat(self.columns.select { |c| c.type == :text }) \
32
+ if options[:include_text_type]
33
+
34
+ columns_to_format = options[:only].map do |col|
35
+ columns_to_format.detect { |c| c.name == col.to_s }
36
+ end.compact if options[:only].present?
37
+
38
+ options[:except].each do |col|
39
+ columns_to_format.delete_if { |c| c.name == col.to_s }
40
+ end
41
+
42
+ if options[:case]
43
+ raise ArgumentError.new("Method not found: `:#{options[:case]}`. Valid methods are: :#{valid_case_methods.join(', :')}") \
44
+ unless valid_case_methods.include?(options[:case])
45
+ end
46
+
47
+ columns_to_format.each do |col|
48
+ self.sanitization__store[col.name] ||= {}
49
+ self.sanitization__store[col.name].merge!(options.slice(:case, :strip, :collapse, :nullify))
50
+ end
51
+
52
+ class_eval <<-EOV
53
+ include ActiveRecord::Sanitization::InstanceMethods
54
+ before_save :sanitization__format_strings
55
+ EOV
56
+ end
57
+
58
+ def valid_case_methods
59
+ String.new.methods.map { |m|
60
+ m.to_s if m.to_s =~ /case$/
61
+ }.compact
62
+ end
63
+ end # module ClassMethods
64
+
65
+ module InstanceMethods
66
+ # Taken from `strip_attributes`: https://github.com/rmm5t/strip_attributes/blob/master/lib/strip_attributes.rb
67
+ # Unicode invisible and whitespace characters. The POSIX character class
68
+ # [:space:] corresponds to the Unicode class Z ("separator"). We also
69
+ # include the following characters from Unicode class C ("control"), which
70
+ # are spaces or invisible characters that make no sense at the start or end
71
+ # of a string:
72
+ # U+180E MONGOLIAN VOWEL SEPARATOR
73
+ # U+200B ZERO WIDTH SPACE
74
+ # U+200C ZERO WIDTH NON-JOINER
75
+ # U+200D ZERO WIDTH JOINER
76
+ # U+2060 WORD JOINER
77
+ # U+FEFF ZERO WIDTH NO-BREAK SPACE
78
+ MULTIBYTE_WHITE = "\u180E\u200B\u200C\u200D\u2060\uFEFF".freeze
79
+ MULTIBYTE_SPACE = /[[:space:]#{MULTIBYTE_WHITE}]/.freeze
80
+ MULTIBYTE_BLANK = /[[:blank:]#{MULTIBYTE_WHITE}]/.freeze
81
+ MULTIBYTE_SUPPORTED = "\u0020" == " "
82
+
83
+ private
84
+
85
+ def sanitization__format_strings
86
+ return unless self.class.sanitization__store
87
+
88
+ class_formatting = self.class.sanitization__store
89
+ class_formatting.each_pair do |col_name, col_formatting|
90
+ sanitization__format_column(col_name, col_formatting)
91
+ end
92
+ end
93
+
94
+ def sanitization__format_column(col_name, col_formatting)
95
+ return unless self[col_name].is_a?(String)
96
+
97
+ self[col_name].strip! if col_formatting[:strip]
98
+
99
+ if col_formatting[:collapse]
100
+ if MULTIBYTE_SUPPORTED && Encoding.compatible?(self[col_name], MULTIBYTE_BLANK)
101
+ self[col_name].gsub!(/#{MULTIBYTE_BLANK}+/, " ")
102
+ else
103
+ self[col_name].squeeze!(" ")
104
+ end
105
+ end
106
+
107
+ if col_formatting[:nullify] && !self[col_name].nil? && self[col_name].to_s.empty? && \
108
+ self.class.columns.select { |c| c.name == col_name }.first.null
109
+ return self[col_name] = nil
110
+ end
111
+
112
+ self[col_name] = self[col_name].send(col_formatting[:case]) if col_formatting[:case]
113
+ self[col_name]
114
+ end
115
+
116
+
117
+ end # module InstanceMethods
118
+ end # module Sanitization
119
+ end # module ActiveRecord
120
+
@@ -0,0 +1,11 @@
1
+ require "sanitization/version"
2
+ require "active_record/sanitization"
3
+
4
+ module Sanitization
5
+ class Error < StandardError; end
6
+ end
7
+
8
+ ActiveRecord::Base.class_eval do
9
+ include ActiveRecord::Sanitization
10
+ end
11
+
@@ -0,0 +1,3 @@
1
+ module Sanitization
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'lib/sanitization/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sanitization"
5
+ spec.version = Sanitization::VERSION
6
+ spec.authors = ["Carl Mercier"]
7
+ spec.email = ["foss@carlmercier.com"]
8
+
9
+ spec.summary = %q{}
10
+ spec.description = %q{}
11
+ spec.homepage = "https://github.com/cmer/sanitization"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/cmer/sanitization"
19
+ spec.metadata["changelog_uri"] = "https://github.com/cmer/sanitization"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+ spec.add_runtime_dependency "activerecord"
30
+ spec.add_runtime_dependency "activesupport"
31
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sanitization
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Carl Mercier
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-05-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
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: activesupport
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
+ description: ''
42
+ email:
43
+ - foss@carlmercier.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - bin/console
56
+ - bin/setup
57
+ - lib/active_record/sanitization.rb
58
+ - lib/sanitization.rb
59
+ - lib/sanitization/version.rb
60
+ - sanitization.gemspec
61
+ homepage: https://github.com/cmer/sanitization
62
+ licenses:
63
+ - MIT
64
+ metadata:
65
+ allowed_push_host: https://rubygems.org
66
+ homepage_uri: https://github.com/cmer/sanitization
67
+ source_code_uri: https://github.com/cmer/sanitization
68
+ changelog_uri: https://github.com/cmer/sanitization
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.3.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.1.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: ''
88
+ test_files: []