coder_decorator 1.1.1 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0565842f5d3c837685232a7b349511616ad779b
4
- data.tar.gz: 9e87db8f9dc04ad0795ab0daaf1741e01ba34603
3
+ metadata.gz: 7155de757d7a11efebe6aaee8a3cdb785fde54cf
4
+ data.tar.gz: fa86ce84c8c168822da29def9df4b93786fbdc01
5
5
  SHA512:
6
- metadata.gz: 193e8eaff80c90c4db9633149461399f8782f0c7538fe3f5154e9ea23f9a543835b76c5e637950b45606dce99961e35bc758804b33e57eadbfb7a4d046060ea2
7
- data.tar.gz: 18e1e8afd7ba035dced6c5fc76f1f4c261110520a757333e493d616504b78666e84cebe1256658b106094d3fa3d74f726565dc93e464c4e088fad55b92514edc
6
+ metadata.gz: 77458a9ed211be9a4770bd7a91d3e88343ccfe7da701beb1e220b580db1a7689478a5666c8392ef7830af6244e1d6bd0d258ab3177a50df91cd537eb6e545f9d
7
+ data.tar.gz: b7fd8de88992caaa41dcd38ab35287f5d6e38b3dedf0304ea8c4beae84f09c202b183ee1029bb04b2ab7e4dcdb558d706041380e49fa809307590be8bb89e495
data/README.md CHANGED
@@ -15,8 +15,7 @@ gem install 'coder_decorator'
15
15
  Encode data with Marshal and Base64:
16
16
 
17
17
  ```ruby
18
- require 'coder_decorator/coders/base64'
19
- require 'coder_decorator/coders/marshal'
18
+ require 'coder_decorator'
20
19
  include CoderDecorator
21
20
  coder = Coders::Base64.new(Coders::Marshal.new)
22
21
  encoded_data = coder.encode(data)
@@ -26,52 +25,20 @@ coder.decode(encoded_data)
26
25
  Encode data with JSON and Zip:
27
26
 
28
27
  ```ruby
29
- require 'coder_decorator/coders/json'
30
- require 'coder_decorator/coders/zip'
28
+ require 'coder_decorator'
31
29
  include CoderDecorator
32
30
  coder = Coders::Zip.new(Coders::JSON.new)
33
31
  encoded_data = coder.encode(data)
34
32
  coder.decode(encoded_data)
35
33
  ```
36
34
 
37
- To load all coders and utilities, simply do:
38
-
39
- ```ruby
40
- require 'coder_decorator'
41
- ```
42
-
43
- All built-in coders are listed in [lib/coder_decorator/coders](lib/coder_decorator/coders).
44
-
45
- ## Use `CoderDecorator::Builder` to construct coders
46
-
47
- `CoderDecorator::Builder` provides a convenient interface to build a coder by passing arguments instead of tediously initializing and wrapping coders, for example:
48
-
49
- ```ruby
50
- require 'coder_decorator/builder'
51
- CoderDecorator::Builder.build(:marshal, :base64)
52
- ```
53
-
54
- is equivalent to:
55
-
56
- ```ruby
57
- require 'coder_decorator/coders/marshal'
58
- require 'coder_decorator/coders/base64'
59
- CoderDecorator::Coders::Marshal.new(CoderDecorator::Coders::Base64.new)
60
- ```
61
-
62
- Use array to pass arguments to the coder:
63
-
64
- ```ruby
65
- CoderDecorator::Builder.build(:marshal, [:base64, {strict: true}])
66
- ```
67
-
68
- Use `CoderDecorator.coder_names` to see all available coder names.
35
+ Coders are listed in [lib/coder_decorator/coders](lib/coder_decorator/coders).
69
36
 
70
37
  ## Integration with Rack
71
38
 
72
39
  ```ruby
73
40
  require 'rack'
74
- require 'coder_decorator/builder'
41
+ require 'coder_decorator'
75
42
 
76
43
  include CoderDecorator
77
44
 
@@ -82,11 +49,14 @@ app = lambda do |env|
82
49
  [200, {}, [session[:count].to_s]]
83
50
  end
84
51
 
85
- coder = CoderDecorator::Builder.build(
86
- :marshal,
87
- [:cipher, {secret: 'x' * 32}],
88
- [:hmac, {secret: 'y' * 32}],
89
- :rescue
52
+ coder = Coders::Rescue.new(
53
+ Coders::HMAC.new(
54
+ Coders::Cipher.new(
55
+ Coders::JSON.new,
56
+ secret: 'x' * 32
57
+ ),
58
+ secret: 'y' * 32
59
+ )
90
60
  )
91
61
 
92
62
  app = Rack::Builder.app(app) do
@@ -1,5 +1,18 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module CoderDecorator # :nodoc:
4
+ module Coders # :nodoc:
5
+ autoload :Base64, 'coder_decorator/coders/base64'
6
+ autoload :Cipher, 'coder_decorator/coders/cipher'
7
+ autoload :Coder, 'coder_decorator/coders/coder'
8
+ autoload :HMAC, 'coder_decorator/coders/hmac'
9
+ autoload :Identity, 'coder_decorator/coders/identity'
10
+ autoload :JSON, 'coder_decorator/coders/json'
11
+ autoload :Marshal, 'coder_decorator/coders/marshal'
12
+ autoload :Rescue, 'coder_decorator/coders/rescue'
13
+ autoload :Zip, 'coder_decorator/coders/zip'
14
+ end
15
+
3
16
  def self.coder_names
4
17
  @coder_names ||= begin
5
18
  coder_names = Dir["#{__dir__}/coder_decorator/coders/*"].map! { |name| File.basename(name, '.rb') }
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
4
  module CoderDecorator
4
5
  module Coders
@@ -14,8 +15,6 @@ module CoderDecorator
14
15
 
15
16
  def decode(str)
16
17
  coder.decode(str.unpack(@template_str).first)
17
- rescue ::ArgumentError
18
- raise InvalidEncoding
19
18
  end
20
19
  end
21
20
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
- require 'coder_decorator/coders/base64'
4
4
  require 'openssl'
5
5
 
6
6
  module CoderDecorator
@@ -14,8 +14,7 @@ module CoderDecorator
14
14
  super(coder)
15
15
  @secret = secret
16
16
  @old_secret = old_secret
17
- @cipher = ::OpenSSL::Cipher.new(cipher)
18
- @base64 = Coders::Base64.new
17
+ @cipher = OpenSSL::Cipher.new(cipher)
19
18
  end
20
19
 
21
20
  def encode(obj)
@@ -23,29 +22,23 @@ module CoderDecorator
23
22
  @cipher.key = @secret
24
23
  iv = @cipher.random_iv
25
24
  encrypted_data = @cipher.update(coder.encode(obj)) << @cipher.final
26
- blob = "#{@base64.encode(encrypted_data)}--#{@base64.encode(iv)}"
27
- @base64.encode(blob)
25
+ "#{[encrypted_data].pack('m0')}--#{[iv].pack('m0')}"
28
26
  end
29
27
 
30
- def decode(str)
31
- [@secret, @old_secret].each do |secret|
28
+ def decode(data)
29
+ secrets = [@old_secret, @secret]
30
+ until secrets.empty?
31
+ secret = secrets.pop
32
32
  begin
33
- return decrypt(secret, str)
34
- rescue ::OpenSSL::Cipher::CipherError, ::TypeError
35
- next
33
+ encrypted_data, iv = data.split('--').map! { |v| v.unpack('m0').first }
34
+ @cipher.decrypt
35
+ @cipher.key = secret
36
+ @cipher.iv = iv
37
+ return coder.decode(@cipher.update(encrypted_data) << @cipher.final)
38
+ rescue StandardError
39
+ secrets.empty? ? raise : next
36
40
  end
37
41
  end
38
- raise InvalidEncoding
39
- end
40
-
41
- private
42
-
43
- def decrypt(secret, data)
44
- encrypted_data, iv = @base64.decode(data).split('--').map! { |v| @base64.decode(v) }
45
- @cipher.decrypt
46
- @cipher.key = secret
47
- @cipher.iv = iv
48
- coder.decode(@cipher.update(encrypted_data) << @cipher.final)
49
42
  end
50
43
  end
51
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'coder_decorator/errors'
2
+
3
3
  module CoderDecorator
4
4
  module Coders
5
5
  # The abstract class of coder, must implement #encode and #decode.
@@ -24,41 +24,26 @@ module CoderDecorator
24
24
  # end
25
25
  # end
26
26
  #
27
- class Coder < BasicObject
28
- DELEGATE = %i(raise respond_to? respond_to_missing?).freeze
27
+ class Coder
28
+ attr_reader :coder
29
29
 
30
30
  # Can optionally pass a base coder which is going to be decorated.
31
31
  def initialize(coder = nil)
32
- @_coder = coder
33
- end
34
-
35
- def coder
36
- @_coder ||= Null.new
32
+ @coder = coder || Null.new
37
33
  end
38
34
 
39
35
  def encode(_obj)
40
- ::Kernel.raise ::NotImplementedError
36
+ raise NotImplementedError
41
37
  end
42
38
 
43
39
  # It decodes +_obj+, returning decoded data,
44
40
  # or +nil+ if it can't decode.
45
41
  def decode(_obj)
46
- ::Kernel.raise ::NotImplementedError
47
- end
48
-
49
- private
50
-
51
- def method_missing(name, *args, &block)
52
- super unless DELEGATE.include? name
53
- ::Kernel.send(name, *args, &block)
54
- end
55
-
56
- def respond_to_missing?(name, include_private = false)
57
- DELEGATE.include?(name) || super
42
+ raise NotImplementedError
58
43
  end
59
44
  end
60
45
 
61
- class Null < BasicObject # :nodoc:
46
+ class Null # :nodoc:
62
47
  def encode(obj)
63
48
  obj
64
49
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
4
  require 'openssl'
4
5
 
@@ -10,6 +11,8 @@ module CoderDecorator
10
11
  # "#{data}--#{hmac}"
11
12
  #
12
13
  class HMAC < Coder
14
+ class InvalidSignature < StandardError; end
15
+
13
16
  REGEXP = /\A(.*)--(.*)\z/
14
17
 
15
18
  def initialize(coder = nil, secret:, old_secret: nil, digest: 'SHA1')
@@ -27,9 +30,9 @@ module CoderDecorator
27
30
 
28
31
  def decode(str)
29
32
  match_data = REGEXP.match(str)
30
- data, hmac = match_data && match_data.captures
33
+ data, hmac = match_data.captures if match_data
31
34
  secrets = [@secret, @old_secret]
32
- raise InvalidEncoding unless data && hmac && secrets.any? { |secret| secure_compare(hmac, generate_hmac(secret, data)) }
35
+ raise InvalidSignature unless data && hmac && secrets.any? { |secret| secure_compare(hmac, generate_hmac(secret, data)) }
33
36
  coder.decode(data)
34
37
  end
35
38
 
@@ -39,7 +42,7 @@ module CoderDecorator
39
42
  ::OpenSSL::HMAC.hexdigest(@digest.new, secret, str)
40
43
  end
41
44
 
42
- def secure_compare(a, b)
45
+ def secure_compare(a, b) # rubocop:disable Naming/UncommunicativeMethodParamName
43
46
  return false unless a.bytesize == b.bytesize
44
47
  l = a.unpack('C*')
45
48
  r = 0
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
4
  module CoderDecorator
4
5
  module Coders
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
4
  require 'json'
4
5
  module CoderDecorator
@@ -10,8 +11,6 @@ module CoderDecorator
10
11
 
11
12
  def decode(str)
12
13
  coder.decode(::JSON.parse(str))
13
- rescue ::JSON::ParserError
14
- raise InvalidEncoding
15
14
  end
16
15
  end
17
16
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
4
+
3
5
  module CoderDecorator
4
6
  module Coders
5
7
  class Marshal < Coder # :nodoc:
@@ -9,8 +11,6 @@ module CoderDecorator
9
11
 
10
12
  def decode(str)
11
13
  coder.decode(::Marshal.load(str))
12
- rescue ::TypeError
13
- raise InvalidEncoding
14
14
  end
15
15
  end
16
16
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
4
  module CoderDecorator
4
5
  module Coders
@@ -10,7 +11,7 @@ module CoderDecorator
10
11
 
11
12
  def decode(obj)
12
13
  coder.decode(obj)
13
- rescue
14
+ rescue StandardError
14
15
  nil
15
16
  end
16
17
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'coder_decorator/coders/coder'
3
4
  require 'zlib'
4
5
  module CoderDecorator
@@ -10,8 +11,6 @@ module CoderDecorator
10
11
 
11
12
  def decode(str)
12
13
  coder.decode(::Zlib::Inflate.inflate(str))
13
- rescue ::Zlib::DataError
14
- raise InvalidEncoding
15
14
  end
16
15
  end
17
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coder_decorator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jian Weihang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-11 00:00:00.000000000 Z
11
+ date: 2018-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.47.1
47
+ version: 0.53.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.47.1
54
+ version: 0.53.0
55
55
  description: An encoding/decoding library with decorator pattern.
56
56
  email: tonytonyjan@gmail.com
57
57
  executables: []
@@ -60,7 +60,6 @@ extra_rdoc_files: []
60
60
  files:
61
61
  - README.md
62
62
  - lib/coder_decorator.rb
63
- - lib/coder_decorator/builder.rb
64
63
  - lib/coder_decorator/coders/base64.rb
65
64
  - lib/coder_decorator/coders/cipher.rb
66
65
  - lib/coder_decorator/coders/coder.rb
@@ -70,8 +69,6 @@ files:
70
69
  - lib/coder_decorator/coders/marshal.rb
71
70
  - lib/coder_decorator/coders/rescue.rb
72
71
  - lib/coder_decorator/coders/zip.rb
73
- - lib/coder_decorator/errors.rb
74
- - lib/coder_decorator/name_converter.rb
75
72
  homepage: https://github.com/tonytonyjan/coder_decorator
76
73
  licenses:
77
74
  - MIT
@@ -92,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
89
  version: '0'
93
90
  requirements: []
94
91
  rubyforge_project:
95
- rubygems_version: 2.6.10
92
+ rubygems_version: 2.4.5
96
93
  signing_key:
97
94
  specification_version: 4
98
95
  summary: An encoding/decoding library with decorator pattern.
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'coder_decorator/name_converter'
3
- module CoderDecorator
4
- # It provides a convenient interface to build a coder by passing arguments
5
- # instead of tediously initializing and wrapping, for example:
6
- #
7
- # require 'coder_decorator/builder'
8
- # CoderDecorator::Builder.build(:marshal, :base64)
9
- #
10
- # is equivalent to:
11
- #
12
- # require 'coder_decorator/coders/marshal'
13
- # require 'coder_decorator/coders/base64'
14
- # CoderDecorator::Coders::Marshal.new(CoderDecorator::Coders::Base64.new)
15
- #
16
- # To pass arguments to a coder, use array:
17
- #
18
- # CoderDecorator::Builder.build(:marshal, [:base64, {strict: true}])
19
- #
20
- class Builder
21
- # equivalent to +new(*coder_names).build+
22
- def self.build(*coder_names)
23
- new(*coder_names).build
24
- end
25
-
26
- # all coder names are listed as filenames under +lib/coder_decorator/coders+,
27
- def initialize(*coder_names)
28
- @coder_names = coder_names
29
- end
30
-
31
- def build
32
- coder = nil
33
- @coder_names.each do |coder_name|
34
- case coder_name
35
- when String, Symbol, Array
36
- name, *arguments = Array(coder_name)
37
- coder_class = NameConverter.new(name).constantize
38
- coder = coder_class.new(coder, *arguments)
39
- else
40
- raise ArgumentError, "Each argument should be one of Symbol, String or Array instance, but #{coder_name.inspect} was given."
41
- end
42
- end
43
- coder
44
- end
45
- end
46
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
- module CoderDecorator
3
- class Error < RuntimeError; end
4
- class InvalidEncoding < Error; end
5
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- module CoderDecorator
3
- # It converts coder names into class name or constant, for example:
4
- #
5
- # NameConverter.new('base64').to_class_name # => 'Base64'
6
- # NameConverter.new('base64').constantize # => Coders::Base64
7
- # NameConverter.new('json').to_class_name # => 'JSON'
8
- # NameConverter.new('json').to_class_name # => Coders::JSON
9
- #
10
- class NameConverter
11
- def initialize(coder_name)
12
- @coder_name = coder_name.to_s
13
- end
14
-
15
- def constantize
16
- @constantize ||= begin
17
- require_relative "coders/#{@coder_name}"
18
- CoderDecorator.const_get("Coders::#{to_class_name}")
19
- rescue LoadError
20
- raise "The coder \"#{@coder_name}\" doesn't exist, use `CoderDecorator.coder_names` to see all available coders."
21
- end
22
- end
23
-
24
- def to_class_name
25
- case @coder_name
26
- when 'hmac', 'json' then @coder_name.upcase
27
- else @coder_name.to_s.split('_').map!(&:capitalize!).join
28
- end
29
- end
30
- end
31
- end