refcode 0.1.0 → 0.1.1

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: 420403fbddbdbbfe612045ab19119651a54f8740
4
- data.tar.gz: 41307cc055dfbea7997fc7e66f20dffbcf94ff9a
3
+ metadata.gz: b45526e91ab90f8b69e43976b600a8bbfa1dbdc0
4
+ data.tar.gz: f580b982c0f61c0021f77b53f0f607047569ebdb
5
5
  SHA512:
6
- metadata.gz: b3fd63ca01f994071ac81ab8545f1880433a661806d73aa81797aeb83fa4763ea7f636777926f823b2df1115df90a3ab463c0c6a74424cceef958274d2095284
7
- data.tar.gz: 172f2f19bc9a3d6f02c75adc665bda99f4a12f5c6edbf825e4c4845cfd42de3fc88e9da06f215fbcfa862b54daa58a640bddf6eb4d50b291988e4a11dc2c270f
6
+ metadata.gz: 21d4ebf71a2fb58ebf43068289ae42b80646b78f8bb8fdbdd05be8ac0e0778f044d21bf466b04f0cd640cef75ae14cff2828dacfecbea19eec5d67180ab8e0fe
7
+ data.tar.gz: 25d0b08552e8e4f4c84080f084bd78d3ae89914aa380c9b81434b6993ee653f264b77961394d586615e213f6bbd262dab56f718cdf5f7d621020b8a5db527760
data/README.md CHANGED
@@ -1,13 +1,12 @@
1
1
  # Refcode
2
2
 
3
- Currently a standalone gem for converting arbitrary Ruby objects into encrypted,
4
- URL-safe strings. The strings can be simply decrypted later to be used by your
3
+ A ruby gem for converting arbitrary Ruby objects into encrypted,
4
+ URL-safe strings. The strings can be easily decrypted later for use in your
5
5
  application.
6
6
 
7
- Refcode was conceived as a way to attach referral data to tracking links. Encryption
7
+ RefCode was conceived as a way to attach referral data to tracking links. Encryption
8
8
  makes it unlikely that the links will be tampered with. Still, it is not recommended
9
- for critically sensitive applications! It was designed to power a simple referral
10
- link tracking system.
9
+ for critically sensitive data!
11
10
 
12
11
  ## Implementation
13
12
 
@@ -33,41 +32,50 @@ Or install it yourself as:
33
32
 
34
33
  ## Usage
35
34
 
36
- Refcode can be used in two ways. Most simply, you can use the `Refcode::Encoder` class directly.
35
+ RefCode can be used in two ways. Most simply, you can use the `Refcode::Encoder` class directly.
37
36
 
38
- encoder = Refcode::Encoder.new do |e|
39
- e.secret = "a long crunchy secret"
40
- e.salt = "some salt"
41
- end
37
+ ```ruby
38
+ encoder = Refcode::Encoder.new do |e|
39
+ e.secret = "a long crunchy secret"
40
+ e.salt = "some salt"
41
+ end
42
42
 
43
- something = OpenStruct.new(channel: 'facebook', action: 'message', user_id: 43765)
44
- encoded_param = encoder.encode something
43
+ something = OpenStruct.new(channel: 'facebook', action: 'message', user_id: 43765)
44
+ encoded_param = encoder.encode something
45
45
 
46
- # in some future request:
46
+ # in some future request:
47
47
 
48
- something = encoder.decode params[:encoded_param]
49
- puts something.channel # 'facebook'
48
+ something = encoder.decode params[:encoded_param]
49
+ puts something.channel #=> 'facebook'
50
+ ```
50
51
 
51
52
  For added convenience when using Refcode with an ORM such as ActiveRecord, a module called `Refcode::Encodable` is also provided.
52
53
 
53
- class Job < ActiveRecord::Base
54
- include Refcode::Encodable
55
- has_refcode secret: 'a long crunchy secret', salt: :id
56
- end
54
+ ```ruby
55
+ class Job < ActiveRecord::Base
56
+ include Refcode::Encodable
57
+ has_refcode secret: 'a long crunchy secret', salt: :id
58
+ end
57
59
 
58
- # the salt option of the has_refcode method can accept a proc/lambda, string
59
- # or a symbol representing an existing method on the class (id in this case)
60
+ # the salt option of the has_refcode method can accept a proc/lambda, string
61
+ # or a symbol representing an existing method on the class (id in this case)
60
62
 
61
- # in some controller code:
63
+ # in some controller code:
62
64
 
63
- @job = Job.find params[:id]
64
- referral_code = @job.generate_refcode channel: 'facebook', action: 'message', user_id: 43765
65
+ @job = Job.find params[:id]
66
+ referral_code = @job.generate_refcode channel: 'facebook', action: 'message', user_id: 43765
65
67
 
66
- # and in another action:
68
+ # and in another action:
67
69
 
68
- @job = Job.find params[:id]
69
- referral_data = @job.parse_refcode params[:encoded_param]
70
+ @job = Job.find params[:id]
71
+ referral_data = @job.parse_refcode params[:encoded_param]
72
+ ```
70
73
 
74
+ ## Features for 1.0
75
+
76
+ - ~~Encodable mixin~~
77
+ - ~~Better exception handling~~
78
+ - More complete tests against encoding non-core ruby class values
71
79
 
72
80
  ## Contributing
73
81
 
data/lib/refcode.rb CHANGED
@@ -3,5 +3,6 @@ require 'yaml'
3
3
  require 'base64url'
4
4
  require 'encryptor'
5
5
  require 'refcode/version'
6
+ require 'refcode/errors'
6
7
  require 'refcode/encoder'
7
8
  require 'refcode/encodable'
@@ -7,11 +7,12 @@ module Refcode
7
7
  end
8
8
 
9
9
  def generate_refcode val
10
- raise 'You must call the has_refcode method in your class definition' unless self.class.refcode_options
10
+ check_refcode_options!
11
11
  encoder.encode val
12
12
  end
13
13
 
14
14
  def parse_refcode code
15
+ check_refcode_options!
15
16
  encoder.decode code
16
17
  end
17
18
 
@@ -29,10 +30,11 @@ module Refcode
29
30
 
30
31
  def encoder
31
32
  Refcode::Encoder.new do |r|
33
+ check_refcode_options!
32
34
  r.secret = self.class.refcode_options[:secret]
33
35
  salt_option = self.class.refcode_options[:salt]
34
36
  if salt_option.respond_to? :call
35
- r.salt = salt_option.call
37
+ r.salt = salt_option.call self
36
38
  elsif salt_option.is_a? Symbol
37
39
  r.salt = self.send salt_option
38
40
  else
@@ -42,6 +44,10 @@ module Refcode
42
44
  end
43
45
  end
44
46
 
47
+ def check_refcode_options!
48
+ raise RefcodeInitException.new('You must call the has_refcode method in your class definition') unless self.class.refcode_options
49
+ end
50
+
45
51
  end
46
52
 
47
53
  end
@@ -23,7 +23,7 @@ module Refcode
23
23
  Encryptor.decrypt(:value => val, :key => @secret, :salt => @salt, :iv => iv)
24
24
  end
25
25
  def iv
26
- [@secret, @salt].join
26
+ [@secret, @salt, 42].join
27
27
  end
28
28
 
29
29
  end
@@ -0,0 +1,6 @@
1
+ module Refcode
2
+
3
+ class RefcodeInitException < Exception
4
+ end
5
+
6
+ end
@@ -1,3 +1,3 @@
1
1
  module Refcode
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,74 @@
1
+ require 'ostruct'
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__),"..","lib","refcode.rb")
4
+
5
+ class RefcodeEncodableTest < Test::Unit::TestCase
6
+
7
+ SECRET = "a short tidy secret, but not too short!"
8
+
9
+ class BareEncodableObject < OpenStruct
10
+ include Refcode::Encodable
11
+ end
12
+ class EncodableObjectSymbol < BareEncodableObject
13
+ has_refcode :secret => SECRET, :salt => :record_id
14
+ end
15
+ class EncodableObjectString < BareEncodableObject
16
+ has_refcode :secret => SECRET, :salt => "123 abc xyz"
17
+ end
18
+ class EncodableObjectSaltyLambda < BareEncodableObject
19
+ has_refcode :secret => SECRET, :salt => lambda { |me| "#{me.record_id}-42" }
20
+ end
21
+
22
+ def test_should_raise_argument_error_if_generate_refcode_called_without_val
23
+ assert_raise ArgumentError do
24
+ encodable_object.generate_refcode
25
+ end
26
+ end
27
+
28
+ def test_should_raise_error_if_refcode_methods_called_before_has_refcode
29
+ [:generate_refcode, :parse_refcode].each do |m|
30
+ assert_raise Refcode::RefcodeInitException do
31
+ obj = BareEncodableObject.new :some => 'value'
32
+ obj.send m, "bogus value"
33
+ end
34
+ end
35
+ end
36
+
37
+ def test_should_raise_argument_error_if_has_refcode_called_without_correct_options
38
+ assert_raise ArgumentError do
39
+ obj = BareEncodableObject.new :some => 'value'
40
+ obj.class.has_refcode :whatever => 'wrong'
41
+ end
42
+ end
43
+
44
+ def test_should_raise_an_error_if_salt_is_empty
45
+ encodable_object.record_id = nil
46
+ assert_raise RuntimeError do
47
+ referral_code_content = { :channel => 'email', :action => 'forward', :user_id => 14325 }
48
+ code = encodable_object.generate_refcode referral_code_content
49
+ assert_equal referral_code_content, encodable_object.parse_refcode(code)
50
+ end
51
+ end
52
+
53
+ def test_should_work_with_different_salt_options
54
+ [EncodableObjectSaltyLambda, EncodableObjectString].each do |klass|
55
+ referral_code_content = { :channel => 'email', :action => 'forward', :user_id => 14325 }
56
+ obj = klass.new referral_code_content
57
+ code = obj.generate_refcode referral_code_content
58
+ assert_equal referral_code_content, obj.parse_refcode(code)
59
+ end
60
+ end
61
+
62
+ def test_encodable_against_hash
63
+ referral_code_content = { :channel => 'email', :action => 'forward', :user_id => 14325 }
64
+ code = encodable_object.generate_refcode referral_code_content
65
+ assert_equal referral_code_content, encodable_object.parse_refcode(code)
66
+ end
67
+
68
+ private
69
+
70
+ def encodable_object
71
+ @encodable_object ||= EncodableObjectSymbol.new :name => 'Unimportant Value', :record_id => 381598
72
+ end
73
+
74
+ end
@@ -0,0 +1,42 @@
1
+ require 'ostruct'
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__),"..","lib","refcode.rb")
4
+
5
+ class RefcodeEncoderTest < Test::Unit::TestCase
6
+
7
+ SECRET = "686cb0461769ebed556f56bc88c956bfdf786646ab1920f58201723c557ccbaeb57112fd53302c06475e6e19a176ba617ee284b091d375858cb259e8578c620f"
8
+ SALT = "dcc74de5efdab0d80b5d763f8a63bef3d37c7453ee45446fbbccd26648af8ca6a112576dafbf5475f3cd7b968703cc9e0682ee45b8b622045cec287908f536e8"
9
+
10
+ def test_encoder_against_hash
11
+ test_hash = { :channel => 'email', :record_id => 49203, :action => 'forward' }
12
+ assert_equal test_hash, encode_and_decode(test_hash)
13
+ end
14
+
15
+ def test_encoder_against_string
16
+ test_string = "secret referral data"
17
+ assert_equal test_string, encode_and_decode(test_string)
18
+ end
19
+
20
+ def test_encoder_against_int
21
+ assert_equal 4857, encode_and_decode(4857)
22
+ end
23
+
24
+ def test_encoder_against_open_struct
25
+ test_struct = OpenStruct.new({:test => 42})
26
+ assert_equal test_struct, encode_and_decode(test_struct)
27
+ end
28
+
29
+ private
30
+
31
+ def encoder
32
+ @encoder ||= Refcode::Encoder.new do |e|
33
+ e.secret = SECRET
34
+ e.salt = SALT
35
+ end
36
+ end
37
+
38
+ def encode_and_decode val
39
+ encoder.decode(encoder.encode(val))
40
+ end
41
+
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refcode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Sitkin
@@ -81,9 +81,11 @@ files:
81
81
  - lib/refcode.rb
82
82
  - lib/refcode/encodable.rb
83
83
  - lib/refcode/encoder.rb
84
+ - lib/refcode/errors.rb
84
85
  - lib/refcode/version.rb
85
86
  - refcode.gemspec
86
- - test/refcode_test.rb
87
+ - test/refcode_encodable_test.rb
88
+ - test/refcode_encoder_test.rb
87
89
  homepage: http://github.com/dustMason/refcode
88
90
  licenses:
89
91
  - MIT
@@ -109,4 +111,5 @@ signing_key:
109
111
  specification_version: 4
110
112
  summary: Hide sensitive data in plain sight, right in your URL
111
113
  test_files:
112
- - test/refcode_test.rb
114
+ - test/refcode_encodable_test.rb
115
+ - test/refcode_encoder_test.rb
data/test/refcode_test.rb DELETED
@@ -1,81 +0,0 @@
1
- require 'ostruct'
2
- require 'test/unit'
3
- require File.join(File.dirname(__FILE__),"..","lib","refcode.rb")
4
-
5
- class RefcodeTest < Test::Unit::TestCase
6
-
7
- SECRET = "686cb0461769ebed556f56bc88c956bfdf786646ab1920f58201723c557ccbaeb57112fd53302c06475e6e19a176ba617ee284b091d375858cb259e8578c620f"
8
- SALT = "dcc74de5efdab0d80b5d763f8a63bef3d37c7453ee45446fbbccd26648af8ca6a112576dafbf5475f3cd7b968703cc9e0682ee45b8b622045cec287908f536e8"
9
-
10
- class BareEncodableObject < OpenStruct
11
- include Refcode::Encodable
12
- end
13
- class EncodableObject < BareEncodableObject
14
- has_refcode :secret => SECRET, :salt => :record_id
15
- end
16
-
17
- def test_encoder_against_hash
18
- test_hash = { :channel => 'email', :record_id => 49203, :action => 'forward' }
19
- assert_equal test_hash, encode_and_decode(test_hash)
20
- end
21
-
22
- def test_encoder_against_string
23
- test_string = "secret referral data"
24
- assert_equal test_string, encode_and_decode(test_string)
25
- end
26
-
27
- def test_encoder_against_int
28
- assert_equal 4857, encode_and_decode(4857)
29
- end
30
-
31
- def test_encoder_against_open_struct
32
- test_struct = OpenStruct.new({:test => 42})
33
- assert_equal test_struct, encode_and_decode(test_struct)
34
- end
35
-
36
- def test_should_raise_argument_error_if_generate_refcode_called_without_val
37
- assert_raise ArgumentError do
38
- encodable_object.generate_refcode
39
- end
40
- end
41
-
42
- def test_should_raise_error_if_generate_refcode_called_before_has_refcode
43
- assert_raise ArgumentError do
44
- obj = BareEncodableObject.new :some => 'value'
45
- obj.generate_refcode
46
- end
47
- end
48
-
49
- def test_should_raise_an_error_if_salt_is_empty
50
- encodable_object.record_id = nil
51
- assert_raise RuntimeError do
52
- referral_code_content = { :channel => 'email', :action => 'forward', :user_id => 14325 }
53
- code = encodable_object.generate_refcode referral_code_content
54
- assert_equal referral_code_content, encodable_object.parse_refcode(code)
55
- end
56
- end
57
-
58
- def test_encodable_against_hash
59
- referral_code_content = { :channel => 'email', :action => 'forward', :user_id => 14325 }
60
- code = encodable_object.generate_refcode referral_code_content
61
- assert_equal referral_code_content, encodable_object.parse_refcode(code)
62
- end
63
-
64
- private
65
-
66
- def encodable_object
67
- @encodable_object ||= EncodableObject.new :name => 'Unimportant Value', :record_id => 381598
68
- end
69
-
70
- def encoder
71
- @encoder ||= Refcode::Encoder.new do |e|
72
- e.secret = SECRET
73
- e.salt = SALT
74
- end
75
- end
76
-
77
- def encode_and_decode val
78
- encoder.decode(encoder.encode(val))
79
- end
80
-
81
- end