refcode 0.0.1 → 0.1.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: e758644ad3263ebb08c54c505b606c310ba5a88a
4
- data.tar.gz: 5eef6a2ba89fa9dc55922ee1ea6fe54488155c72
3
+ metadata.gz: 420403fbddbdbbfe612045ab19119651a54f8740
4
+ data.tar.gz: 41307cc055dfbea7997fc7e66f20dffbcf94ff9a
5
5
  SHA512:
6
- metadata.gz: aa418e724d2bc68c26e7fb06ce6758d8ab2aa04d96aa5b3aaadaf5981750ab8e428706016d15d0c543ddd0f88b38807f8f91ab2fcd209839ee60263c853b36c5
7
- data.tar.gz: d098a3bd746a7f4afe3fb4db4240c7ec645b795f8e99e7296d91bd8677bd013203536cb79437a35e6a843947882727caa35c4be16f8b44a469e7c49197915d00
6
+ metadata.gz: b3fd63ca01f994071ac81ab8545f1880433a661806d73aa81797aeb83fa4763ea7f636777926f823b2df1115df90a3ab463c0c6a74424cceef958274d2095284
7
+ data.tar.gz: 172f2f19bc9a3d6f02c75adc665bda99f4a12f5c6edbf825e4c4845cfd42de3fc88e9da06f215fbcfa862b54daa58a640bddf6eb4d50b291988e4a11dc2c270f
data/README.md CHANGED
@@ -5,7 +5,9 @@ URL-safe strings. The strings can be simply decrypted later to be used by your
5
5
  application.
6
6
 
7
7
  Refcode was conceived as a way to attach referral data to tracking links. Encryption
8
- makes it unlikely that the links can be tampered with.
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
11
 
10
12
  ## Implementation
11
13
 
@@ -31,6 +33,8 @@ Or install it yourself as:
31
33
 
32
34
  ## Usage
33
35
 
36
+ Refcode can be used in two ways. Most simply, you can use the `Refcode::Encoder` class directly.
37
+
34
38
  encoder = Refcode::Encoder.new do |e|
35
39
  e.secret = "a long crunchy secret"
36
40
  e.salt = "some salt"
@@ -39,11 +43,32 @@ Or install it yourself as:
39
43
  something = OpenStruct.new(channel: 'facebook', action: 'message', user_id: 43765)
40
44
  encoded_param = encoder.encode something
41
45
 
42
- # in some future request...
46
+ # in some future request:
43
47
 
44
48
  something = encoder.decode params[:encoded_param]
45
49
  puts something.channel # 'facebook'
46
50
 
51
+ For added convenience when using Refcode with an ORM such as ActiveRecord, a module called `Refcode::Encodable` is also provided.
52
+
53
+ class Job < ActiveRecord::Base
54
+ include Refcode::Encodable
55
+ has_refcode secret: 'a long crunchy secret', salt: :id
56
+ end
57
+
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
+
61
+ # in some controller code:
62
+
63
+ @job = Job.find params[:id]
64
+ referral_code = @job.generate_refcode channel: 'facebook', action: 'message', user_id: 43765
65
+
66
+ # and in another action:
67
+
68
+ @job = Job.find params[:id]
69
+ referral_data = @job.parse_refcode params[:encoded_param]
70
+
71
+
47
72
  ## Contributing
48
73
 
49
74
  1. Fork it
data/lib/refcode.rb CHANGED
@@ -3,39 +3,5 @@ require 'yaml'
3
3
  require 'base64url'
4
4
  require 'encryptor'
5
5
  require 'refcode/version'
6
-
7
- module Refcode
8
-
9
- class Encoder
10
-
11
- attr_accessor :secret, :salt
12
-
13
- def initialize
14
- yield self if block_given?
15
- end
16
-
17
- def encode val
18
- Base64URL.encode(encrypt(YAML.dump(val)))
19
- end
20
-
21
- def decode val
22
- YAML.load(decrypt(Base64URL.decode(val)))
23
- end
24
-
25
- def encrypt val
26
- Encryptor.encrypt(:value => val, :key => @secret, :salt => @salt, :iv => iv)
27
- end
28
-
29
- def decrypt val
30
- Encryptor.decrypt(:value => val, :key => @secret, :salt => @salt, :iv => iv)
31
- end
32
-
33
- private
34
-
35
- def iv
36
- [@secret, @salt].join
37
- end
38
-
39
- end
40
-
41
- end
6
+ require 'refcode/encoder'
7
+ require 'refcode/encodable'
@@ -0,0 +1,47 @@
1
+ module Refcode
2
+
3
+ module Encodable
4
+
5
+ def self.included base
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ def generate_refcode val
10
+ raise 'You must call the has_refcode method in your class definition' unless self.class.refcode_options
11
+ encoder.encode val
12
+ end
13
+
14
+ def parse_refcode code
15
+ encoder.decode code
16
+ end
17
+
18
+ module ClassMethods
19
+ def has_refcode options
20
+ raise ArgumentError unless options[:secret] && options[:salt]
21
+ @refcode_options = options
22
+ end
23
+ def refcode_options
24
+ @refcode_options
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def encoder
31
+ Refcode::Encoder.new do |r|
32
+ r.secret = self.class.refcode_options[:secret]
33
+ salt_option = self.class.refcode_options[:salt]
34
+ if salt_option.respond_to? :call
35
+ r.salt = salt_option.call
36
+ elsif salt_option.is_a? Symbol
37
+ r.salt = self.send salt_option
38
+ else
39
+ r.salt = salt_option
40
+ end
41
+ raise "Value for salt is nil (#{salt_option} given)" if r.salt.nil?
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,31 @@
1
+ module Refcode
2
+
3
+ class Encoder
4
+
5
+ attr_accessor :secret, :salt
6
+
7
+ def initialize
8
+ yield self if block_given?
9
+ end
10
+ def encode val
11
+ Base64URL.encode(encrypt(YAML.dump(val)))
12
+ end
13
+ def decode val
14
+ YAML.load(decrypt(Base64URL.decode(val)))
15
+ end
16
+
17
+ private
18
+
19
+ def encrypt val
20
+ Encryptor.encrypt(:value => val, :key => @secret, :salt => @salt, :iv => iv)
21
+ end
22
+ def decrypt val
23
+ Encryptor.decrypt(:value => val, :key => @secret, :salt => @salt, :iv => iv)
24
+ end
25
+ def iv
26
+ [@secret, @salt].join
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -1,3 +1,3 @@
1
1
  module Refcode
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/test/refcode_test.rb CHANGED
@@ -7,6 +7,13 @@ class RefcodeTest < Test::Unit::TestCase
7
7
  SECRET = "686cb0461769ebed556f56bc88c956bfdf786646ab1920f58201723c557ccbaeb57112fd53302c06475e6e19a176ba617ee284b091d375858cb259e8578c620f"
8
8
  SALT = "dcc74de5efdab0d80b5d763f8a63bef3d37c7453ee45446fbbccd26648af8ca6a112576dafbf5475f3cd7b968703cc9e0682ee45b8b622045cec287908f536e8"
9
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
+
10
17
  def test_encoder_against_hash
11
18
  test_hash = { :channel => 'email', :record_id => 49203, :action => 'forward' }
12
19
  assert_equal test_hash, encode_and_decode(test_hash)
@@ -26,8 +33,40 @@ class RefcodeTest < Test::Unit::TestCase
26
33
  assert_equal test_struct, encode_and_decode(test_struct)
27
34
  end
28
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
+
29
64
  private
30
65
 
66
+ def encodable_object
67
+ @encodable_object ||= EncodableObject.new :name => 'Unimportant Value', :record_id => 381598
68
+ end
69
+
31
70
  def encoder
32
71
  @encoder ||= Refcode::Encoder.new do |e|
33
72
  e.secret = SECRET
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.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Sitkin
@@ -79,6 +79,8 @@ files:
79
79
  - README.md
80
80
  - Rakefile
81
81
  - lib/refcode.rb
82
+ - lib/refcode/encodable.rb
83
+ - lib/refcode/encoder.rb
82
84
  - lib/refcode/version.rb
83
85
  - refcode.gemspec
84
86
  - test/refcode_test.rb