coder_decorator 1.1.1 → 2.0.0

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
  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