refcode 0.1.0 → 0.1.1

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