hanami-utils 1.3.6 → 1.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e6573938b28f1b4f3b8f46aebec53e487d0af4e85087a65d5e081c4fdc2f030
4
- data.tar.gz: e2d13a7d2a675633a7b984882d7c01c5963b3933f1d9339b871ed20838b630c9
3
+ metadata.gz: '02818d90409ea03d89ca587c97fe418bbf17a8694662a2313609c0710466b0f9'
4
+ data.tar.gz: 973ef420992dd9ea30ab880d43e8cc70eee59cae6fb7b1ba17038c5ce8d536a4
5
5
  SHA512:
6
- metadata.gz: f8255168597fd310d075400c0a926b28f7bea6dd2025b1572d065e8df7e7ecfa76f991dc88afa1be37b3dfa57b06e70332015018e724ad7731184329a1cab559
7
- data.tar.gz: 4ff3e862379db3b02d1fecace8336ed0f44df2b98c9588f807f46883b3b0e7a862beac8119da7428b07484802842b09aca509e1d01ee9dc25360438847d94f63
6
+ metadata.gz: d49d6ad21aa25f285c9165c4619d6b2d7fe348513481bf30b8f231211d4e270f7502e2e3594f082789fdf32e9170a33e038329394ae5f43170ab778ebe01892f
7
+ data.tar.gz: 8b8832a39855525d6818de385212fb1c9d7c5c0f79874f60ead95ee1c592377f6bfec0ade5701a4340b87fe920c495889a9586d81fe2091d8691b52b14f297fa
@@ -1,6 +1,14 @@
1
1
  # Hanami::Utils
2
2
  Ruby core extentions and class utilities for Hanami
3
3
 
4
+ ## v1.3.7 - 2021-01-04
5
+ ### Added
6
+ - [Luca Guidi] Official support for Ruby: MRI 3.0
7
+ - [Khai Le] Allow `Hanami::Logger` to filter sensitive data for an array of hashes
8
+
9
+ ### Fixed
10
+ - [Hiếu Nguyễn] Ensure `Hanami::Logger` to not mutate `Hash` input when filtering sensitive data
11
+
4
12
  ## v1.3.6 - 2020-01-07
5
13
  ### Added
6
14
  - [Luca Guidi] Official support for Ruby: MRI 2.7
data/README.md CHANGED
@@ -5,8 +5,7 @@ Ruby core extensions and class utilities for [Hanami](http://hanamirb.org)
5
5
  ## Status
6
6
 
7
7
  [![Gem Version](https://badge.fury.io/rb/hanami-utils.svg)](https://badge.fury.io/rb/hanami-utils)
8
- [![Build Status](https://ci.hanamirb.org/api/badges/hanami/utils/status.svg)](https://ci.hanamirb.org/hanami/utils)
9
- [![CircleCI](https://circleci.com/gh/hanami/utils/tree/master.svg?style=svg)](https://circleci.com/gh/hanami/utils/tree/master)
8
+ [![CI](https://github.com/hanami/utils/workflows/ci/badge.svg?branch=master)](https://github.com/hanami/utils/actions?query=workflow%3Aci+branch%3Amaster)
10
9
  [![Test Coverage](https://codecov.io/gh/hanami/utils/branch/master/graph/badge.svg)](https://codecov.io/gh/hanami/utils)
11
10
  [![Depfu](https://badges.depfu.com/badges/a8545fb67cf32a2c75b6227bc0821027/overview.svg)](https://depfu.com/github/hanami/utils?project=Bundler)
12
11
  [![Inline Docs](http://inch-ci.org/github/hanami/utils.svg)](http://inch-ci.org/github/hanami/utils)
@@ -150,6 +149,6 @@ __Hanami::Utils__ uses [Semantic Versioning 2.0.0](http://semver.org)
150
149
 
151
150
  ## Copyright
152
151
 
153
- Copyright © 2014-2017 Luca Guidi – Released under MIT License
152
+ Copyright © 2014-2021 Luca Guidi – Released under MIT License
154
153
 
155
154
  This project was formerly known as Lotus (`lotus-utils`).
@@ -1,27 +1,30 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'hanami/utils/version'
5
+ require "hanami/utils/version"
4
6
 
5
7
  Gem::Specification.new do |spec|
6
- spec.name = 'hanami-utils'
8
+ spec.name = "hanami-utils"
7
9
  spec.version = Hanami::Utils::VERSION
8
- spec.authors = ['Luca Guidi']
9
- spec.email = ['me@lucaguidi.com']
10
- spec.description = 'Hanami utilities'
11
- spec.summary = 'Ruby core extentions and Hanami utilities'
12
- spec.homepage = 'http://hanamirb.org'
13
- spec.license = 'MIT'
10
+ spec.authors = ["Luca Guidi"]
11
+ spec.email = ["me@lucaguidi.com"]
12
+ spec.description = "Hanami utilities"
13
+ spec.summary = "Ruby core extentions and Hanami utilities"
14
+ spec.homepage = "http://hanamirb.org"
15
+ spec.license = "MIT"
14
16
 
15
17
  spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-utils.gemspec`.split($/)
16
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
- spec.require_paths = ['lib']
19
- spec.required_ruby_version = '>= 2.3.0'
20
+ spec.require_paths = ["lib"]
21
+ spec.required_ruby_version = ">= 2.3.0"
20
22
 
21
- spec.add_dependency 'transproc', '~> 1.0'
22
- spec.add_dependency 'concurrent-ruby', '~> 1.0'
23
+ spec.add_dependency "transproc", "~> 1.0"
24
+ spec.add_dependency "concurrent-ruby", "~> 1.0"
23
25
 
24
- spec.add_development_dependency 'bundler', '>= 1.6', '< 3'
25
- spec.add_development_dependency 'rake', '~> 13'
26
- spec.add_development_dependency 'rspec', '~> 3.7'
26
+ spec.add_development_dependency "bundler", ">= 1.6", "< 3"
27
+ spec.add_development_dependency "rake", "~> 13"
28
+ spec.add_development_dependency "rspec", "~> 3.9"
29
+ spec.add_development_dependency "rubocop", "0.81" # rubocop 0.81+ removed support for Ruby 2.3
27
30
  end
@@ -1 +1,3 @@
1
- require 'hanami/utils'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils"
@@ -1,6 +1,8 @@
1
- require 'hanami/utils/basic_object'
2
- require 'hanami/utils/class_attribute'
3
- require 'hanami/utils/hash'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils/basic_object"
4
+ require "hanami/utils/class_attribute"
5
+ require "hanami/utils/hash"
4
6
 
5
7
  module Hanami
6
8
  # Hanami Interactor
@@ -17,14 +19,14 @@ module Hanami
17
19
  # @api private
18
20
  #
19
21
  # @see Hanami::Interactor::Result#respond_to_missing?
20
- METHODS = ::Hash[initialize: true,
21
- success?: true,
22
+ METHODS = ::Hash[initialize: true,
23
+ success?: true,
22
24
  successful?: true,
23
- failure?: true,
24
- fail!: true,
25
- prepare!: true,
26
- errors: true,
27
- error: true].freeze
25
+ failure?: true,
26
+ fail!: true,
27
+ prepare!: true,
28
+ errors: true,
29
+ error: true].freeze
28
30
 
29
31
  # Initialize a new result
30
32
  #
@@ -50,7 +52,7 @@ module Hanami
50
52
  end
51
53
 
52
54
  # @since 0.3.5
53
- alias success? successful?
55
+ alias_method :success?, :successful?
54
56
 
55
57
  # Checks if the current status is not successful
56
58
  #
@@ -351,27 +353,51 @@ module Hanami
351
353
  # end
352
354
  #
353
355
  # Signup.new.call # => NoMethodError
354
- def call(*args)
355
- @__result = ::Hanami::Interactor::Result.new
356
- _call(*args) { super }
356
+ if RUBY_VERSION >= "3.0"
357
+ def call(*args, **kwargs)
358
+ @__result = ::Hanami::Interactor::Result.new
359
+ _call(*args, **kwargs) { super }
360
+ end
361
+ else
362
+ def call(*args)
363
+ @__result = ::Hanami::Interactor::Result.new
364
+ _call(*args) { super }
365
+ end
357
366
  end
358
367
 
359
368
  private
360
369
 
361
370
  # @api private
362
371
  # @since 1.1.0
363
- def _call(*args)
364
- catch :fail do
365
- validate!(*args)
366
- yield
372
+ if RUBY_VERSION >= "3.0"
373
+ def _call(*args, **kwargs)
374
+ catch :fail do
375
+ validate!(*args, **kwargs)
376
+ yield
377
+ end
378
+
379
+ _prepare!
367
380
  end
381
+ else
382
+ def _call(*args)
383
+ catch :fail do
384
+ validate!(*args)
385
+ yield
386
+ end
368
387
 
369
- _prepare!
388
+ _prepare!
389
+ end
370
390
  end
371
391
 
372
392
  # @since 1.1.0
373
- def validate!(*args)
374
- fail! unless valid?(*args)
393
+ if RUBY_VERSION >= "3.0"
394
+ def validate!(*args, **kwargs)
395
+ fail! unless valid?(*args, **kwargs)
396
+ end
397
+ else
398
+ def validate!(*args)
399
+ fail! unless valid?(*args)
400
+ end
375
401
  end
376
402
  end
377
403
 
@@ -132,11 +132,11 @@ module Hanami
132
132
  # @since 0.8.0
133
133
  # @api private
134
134
  LEVELS = ::Hash[
135
- "debug" => DEBUG,
136
- "info" => INFO,
137
- "warn" => WARN,
138
- "error" => ERROR,
139
- "fatal" => FATAL,
135
+ "debug" => DEBUG,
136
+ "info" => INFO,
137
+ "warn" => WARN,
138
+ "error" => ERROR,
139
+ "fatal" => FATAL,
140
140
  "unknown" => UNKNOWN
141
141
  ].freeze
142
142
 
@@ -281,7 +281,7 @@ module Hanami
281
281
  # # => {"app":"Hanami","severity":"DEBUG","time":"2017-03-30T13:57:59Z","message":"Hello World"}
282
282
  # rubocop:disable Lint/SuppressedException
283
283
  # rubocop:disable Metrics/ParameterLists
284
- def initialize(application_name = nil, *args, stream: $stdout, level: DEBUG, formatter: nil, filter: [], colorizer: nil)
284
+ def initialize(application_name = nil, *args, stream: $stdout, level: DEBUG, formatter: nil, filter: [], colorizer: nil) # rubocop:disable Layout/LineLength
285
285
  begin
286
286
  Utils::Files.mkdir_p(stream)
287
287
  rescue TypeError
@@ -14,9 +14,9 @@ module Hanami
14
14
  # @api private
15
15
  def call(app, severity, datetime, _progname)
16
16
  ::Hash[
17
- app: app,
17
+ app: app,
18
18
  severity: severity,
19
- time: datetime,
19
+ time: datetime,
20
20
  ]
21
21
  end
22
22
  end
@@ -44,9 +44,9 @@ module Hanami
44
44
  # @return [::Hash] an Hash containing the keys `:app`, `:severity`, and `:time`
45
45
  def call(app, severity, datetime, _progname)
46
46
  ::Hash[
47
- app: app(app),
47
+ app: app(app),
48
48
  severity: severity(severity),
49
- time: datetime(datetime),
49
+ time: datetime(datetime),
50
50
  ]
51
51
  end
52
52
 
@@ -57,18 +57,18 @@ module Hanami
57
57
  # @since 1.2.0
58
58
  # @api private
59
59
  COLORS = ::Hash[
60
- app: :blue,
60
+ app: :blue,
61
61
  datetime: :cyan,
62
62
  ].freeze
63
63
 
64
64
  # @since 1.2.0
65
65
  # @api private
66
66
  LEVELS = ::Hash[
67
- Hanami::Logger::DEBUG => :cyan,
68
- Hanami::Logger::INFO => :magenta,
69
- Hanami::Logger::WARN => :yellow,
70
- Hanami::Logger::ERROR => :red,
71
- Hanami::Logger::FATAL => :red,
67
+ Hanami::Logger::DEBUG => :cyan,
68
+ Hanami::Logger::INFO => :magenta,
69
+ Hanami::Logger::WARN => :yellow,
70
+ Hanami::Logger::ERROR => :red,
71
+ Hanami::Logger::FATAL => :red,
72
72
  Hanami::Logger::UNKNOWN => :blue,
73
73
  ].freeze
74
74
 
@@ -9,21 +9,19 @@ module Hanami
9
9
  # @since 1.1.0
10
10
  # @api private
11
11
  class Filter
12
- # @since 1.1.0
12
+ # @since 1.3.7
13
13
  # @api private
14
- def initialize(filters = [])
14
+ FILTERED_VALUE = "[FILTERED]"
15
+
16
+ def initialize(filters = [], mask: FILTERED_VALUE)
15
17
  @filters = filters
18
+ @mask = mask
16
19
  end
17
20
 
18
21
  # @since 1.1.0
19
22
  # @api private
20
- def call(hash)
21
- _filtered_keys(hash).each do |key|
22
- *keys, last = _actual_keys(hash, key.split("."))
23
- keys.inject(hash, :fetch)[last] = "[FILTERED]"
24
- end
25
-
26
- hash
23
+ def call(params)
24
+ _filter(_copy_params(params))
27
25
  end
28
26
 
29
27
  private
@@ -32,6 +30,29 @@ module Hanami
32
30
  # @api private
33
31
  attr_reader :filters
34
32
 
33
+ # @since 1.3.7
34
+ # @api private
35
+ attr_reader :mask
36
+
37
+ # This is a simple deep merge to merge the original input
38
+ # with the filtered hash which contains '[FILTERED]' string.
39
+ #
40
+ # It only deep-merges if the conflict values are both hashes.
41
+ #
42
+ # @since 1.3.7
43
+ # @api private
44
+ def _deep_merge(original_hash, filtered_hash)
45
+ original_hash.merge(filtered_hash) do |_key, original_item, filtered_item|
46
+ if original_item.is_a?(Hash) && filtered_item.is_a?(Hash)
47
+ _deep_merge(original_item, filtered_item)
48
+ elsif filtered_item == FILTERED_VALUE
49
+ filtered_item
50
+ else
51
+ original_item
52
+ end
53
+ end
54
+ end
55
+
35
56
  # @since 1.1.0
36
57
  # @api private
37
58
  def _filtered_keys(hash)
@@ -74,6 +95,53 @@ module Hanami
74
95
  def _key_paths?(value)
75
96
  value.is_a?(Enumerable) && !value.is_a?(File)
76
97
  end
98
+
99
+ # @since 1.3.7
100
+ # @api private
101
+ def _deep_dup(hash)
102
+ hash.map do |key, value|
103
+ [
104
+ key,
105
+ if value.is_a?(Hash)
106
+ _deep_dup(value)
107
+ else
108
+ _key_paths?(value) ? value.dup : value
109
+ end
110
+ ]
111
+ end.to_h
112
+ end
113
+
114
+ # @since 1.3.7
115
+ # @api private
116
+ def _copy_params(params)
117
+ case params
118
+ when Hash
119
+ _deep_dup(params)
120
+ when Array
121
+ params.map { |hash| _deep_dup(hash) }
122
+ end
123
+ end
124
+
125
+ # @since 1.3.7
126
+ # @api private
127
+ def _filter_hash(hash)
128
+ _filtered_keys(hash).each do |key|
129
+ *keys, last = _actual_keys(hash, key.split("."))
130
+ keys.inject(hash, :fetch)[last] = mask
131
+ end
132
+ hash
133
+ end
134
+
135
+ # @since 1.3.7
136
+ # @api private
137
+ def _filter(params)
138
+ case params
139
+ when Hash
140
+ _filter_hash(params)
141
+ when Array
142
+ params.map { |hash| _filter_hash(hash) }
143
+ end
144
+ end
77
145
  end
78
146
  end
79
147
  end
@@ -103,15 +103,15 @@ module Hanami
103
103
 
104
104
  # @since 0.8.0
105
105
  # @api private
106
- def _message_hash(message) # rubocop:disable Metrics/MethodLength
106
+ def _message_hash(message)
107
107
  case message
108
108
  when Hash
109
109
  @filter.call(message)
110
110
  when Exception
111
111
  Hash[
112
- message: message.message,
112
+ message: message.message,
113
113
  backtrace: message.backtrace || [],
114
- error: message.class
114
+ error: message.class
115
115
  ]
116
116
  else
117
117
  Hash[message: message]
@@ -121,7 +121,7 @@ module Hanami
121
121
  # @since 0.8.0
122
122
  # @api private
123
123
  def _format(hash)
124
- "#{_line_front_matter(hash.delete(:app), hash.delete(:severity), hash.delete(:time))}#{SEPARATOR}#{_format_message(hash)}"
124
+ "#{_line_front_matter(hash.delete(:app), hash.delete(:severity), hash.delete(:time))}#{SEPARATOR}#{_format_message(hash)}" # rubocop:disable Layout/LineLength
125
125
  end
126
126
 
127
127
  # @since 1.2.0
@@ -1,11 +1,13 @@
1
- require 'pathname'
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
2
4
 
3
5
  # Hanami - The web, with simplicity
4
6
  #
5
7
  # @since 0.1.0
6
8
  module Hanami
7
- require 'hanami/utils/version'
8
- require 'hanami/utils/file_list'
9
+ require "hanami/utils/version"
10
+ require "hanami/utils/file_list"
9
11
 
10
12
  # Ruby core extentions and Hanami utilities
11
13
  #
@@ -13,11 +15,11 @@ module Hanami
13
15
  module Utils
14
16
  # @since 0.3.1
15
17
  # @api private
16
- HANAMI_JRUBY = 'java'.freeze
18
+ HANAMI_JRUBY = "java"
17
19
 
18
20
  # @since 0.3.1
19
21
  # @api private
20
- HANAMI_RUBINIUS = 'rbx'.freeze
22
+ HANAMI_RUBINIUS = "rbx"
21
23
 
22
24
  # Checks if the current VM is JRuby
23
25
  #
@@ -87,7 +89,7 @@ module Hanami
87
89
  def self.for_each_file_in(directory, &blk)
88
90
  directory = directory.to_s.gsub(%r{(\/|\\)}, File::SEPARATOR)
89
91
  directory = Pathname.new(Dir.pwd).join(directory).to_s
90
- directory = File.join(directory, '**', '*.rb') unless directory =~ /(\*\*)/
92
+ directory = File.join(directory, "**", "*.rb") unless directory =~ /(\*\*)/
91
93
 
92
94
  FileList[directory].each(&blk)
93
95
  end