ssn_validation 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 055a5606a0f3628720394e6fadc9d7d031cccfd56ae1004184bc7e1c741881b2
4
+ data.tar.gz: 9fa6a0e907840f4b7e04981144e6d13930a1af4d53103d29ed0d61ad691a0c2b
5
+ SHA512:
6
+ metadata.gz: 77969a0983d95df462807ea033cf37aca5142e1122d28867e736fcf1515f53b3cf72ed8e8722b1c38603f07f162a225406702fb0ce7671d3510459c38faacffe
7
+ data.tar.gz: 58ec9cef29eed8d78060b14a3a7d006c746816ab1f6b37f9a3bb2111359b8ad9cd5ae3866fc4850207ed0620e21a44d372ba54cbe0b72c3ac342d18570396620
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new(:test) do |t|
4
+ t.pattern = 'test/**/*_test.rb'
5
+ t.verbose = true
6
+ t.warning = true
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -0,0 +1,2 @@
1
+ require 'ssn_validation/ssn_validation'
2
+ require 'ssn_validation/ssn'
@@ -0,0 +1,56 @@
1
+ module SsnValidation
2
+ module Ssn
3
+ DIGITS = %w[0 1 2 3 4 5 6 7 8 9].freeze
4
+ DIGITS_EX0 = DIGITS[1..-1]
5
+
6
+ # returns a hash of 0..n key/value pairs for ssn validation error codes and a default message for each
7
+ def self.validate(ssn)
8
+ ssn = ssn.to_s
9
+ errors = {}
10
+ return errors if test_ssn?(ssn)
11
+
12
+ (ssn.length != 9) && errors[:nine_digits] = "SSN value is not 9 digits"
13
+ (ssn.chars - DIGITS).any? && errors[:non_digits] = "SSN value contains non-digits"
14
+ return errors if errors.any? # return if basic conditions fail
15
+
16
+ (ssn[0..2] == "666") && errors[:excluded_666] = "SSN value contains excluded area 666-xx-xxxx"
17
+ (ssn.chars - [ssn[0]]).empty? && errors[:repeating] = "SSN value contains repeating digits"
18
+ (ssn[0..2] == "000") && errors[:zero_area] = "SSN value contains zeros in area number 000-xx-xxxx"
19
+ (ssn[3..4] == "00") && errors[:zero_group] = "SSN value contains zeros in group number xxx-00-xxxx"
20
+ (ssn[5..8] == "0000") && errors[:zero_serial] = "SSN value contains zeros in serial number xxx-xx-0000"
21
+ ascending?(ssn) && errors[:ascending] = "SSN value contains all ASCENDING digits"
22
+ descending?(ssn) && errors[:descending] = "SSN value contains all DESCENDING digits"
23
+ return errors if errors.any? # return if ssn conditions fail
24
+
25
+ # check valid ITIN format last
26
+ invalid_itin?(ssn) && errors[:invalid_itin] = "SSN value contains invalid ITIN format 9xx-[x]x-xxxx"
27
+ errors
28
+ end
29
+
30
+ def self.ascending?(ssn)
31
+ return true if ssn.chars == DIGITS.rotate(ssn[0].to_i)[0..8]
32
+ return true if ssn.chars == DIGITS_EX0.rotate(ssn[0].to_i - 1)
33
+
34
+ false
35
+ end
36
+
37
+ def self.descending?(ssn)
38
+ return true if ssn.chars == DIGITS.reverse.rotate(-(ssn[0].to_i + 1))[0..8]
39
+ return true if ssn.chars == DIGITS_EX0.reverse.rotate(-ssn[0].to_i)
40
+
41
+ false
42
+ end
43
+
44
+ def self.invalid_itin?(ssn)
45
+ ssn[0] == "9" && !%w[7 8].include?(ssn[3])
46
+ end
47
+
48
+ def self.test_ssn?(ssn)
49
+ SsnValidation.config.test_ssns.any? {|p| p.match(ssn)}
50
+ end
51
+ end
52
+
53
+ def self.validate(ssn)
54
+ Ssn.validate(ssn)
55
+ end
56
+ end
@@ -0,0 +1,18 @@
1
+ module SsnValidation
2
+ def self.config
3
+ @@config ||= Configuration.new
4
+ end
5
+
6
+ def self.configure
7
+ self.config ||= Configuration.new
8
+ yield(config)
9
+ end
10
+
11
+ class Configuration
12
+ attr_accessor :test_ssns
13
+
14
+ def initialize
15
+ @test_ssns = []
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module ActiveModel
2
+ module Validations
3
+ class SocialSecurityNumberValidator < EachValidator
4
+ def validate_each(record, attribute, value)
5
+ ssn_errors = Ssn.validate(value)
6
+ return if ssn_errors.blank?
7
+ ssn_errors.values.each {|error| record.errors[attribute] << error}
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module SsnValidation
2
+ VERSION = '0.1.2'
3
+ end
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ssn_validation"
8
+ spec.version = SsnValidation::VERSION
9
+ spec.authors = ["John Stewart"]
10
+ spec.summary = 'Social Security Number (SSN) Validation'
11
+ spec.license = 'Apache-2.0'
12
+ spec.homepage = 'https://github.com/johnsinco/ssn_validation'
13
+ spec.summary = 'Social Security Number (SSN) Validation'
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ spec.executables = `git ls-files -- bin/*`.split("\n").map {|f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+ spec.required_ruby_version = '>= 2.3'
19
+ spec.add_development_dependency "rake", '~> 12'
20
+ spec.add_development_dependency "activemodel", '~> 5'
21
+ end
22
+
@@ -0,0 +1,111 @@
1
+ require 'minitest/autorun'
2
+ require 'ssn_validation/ssn'
3
+
4
+ class SsnTest < Minitest::Test
5
+ include SsnValidation
6
+ describe Ssn do
7
+ describe 'valid formats' do
8
+ describe 'valid ITIN' do
9
+ it 'is valid' do
10
+ assert_equal({}, Ssn.validate('911781111'))
11
+ end
12
+ end
13
+ describe 'valid SSN' do
14
+ it 'is valid' do
15
+ assert_equal({}, Ssn.validate('123432100'))
16
+ end
17
+ end
18
+ describe 'valid repeating SSN' do
19
+ it 'is valid' do
20
+ assert_equal({}, Ssn.validate('123444444'))
21
+ end
22
+ end
23
+ end
24
+ describe 'invalid formats' do
25
+ describe '666 is invalid' do
26
+ it 'is valid' do
27
+ assert_equal({excluded_666: 'SSN value contains excluded area 666-xx-xxxx'}, Ssn.validate('666123210'))
28
+ end
29
+ end
30
+ describe 'zero area numbers invalid' do
31
+ it 'is invalid' do
32
+ assert_equal({zero_area: 'SSN value contains zeros in area number 000-xx-xxxx'}, Ssn.validate('000567890'))
33
+ end
34
+ end
35
+ describe 'zero group numbers invalid' do
36
+ it 'is invalid' do
37
+ assert_equal({zero_group: 'SSN value contains zeros in group number xxx-00-xxxx'}, Ssn.validate('567007890'))
38
+ end
39
+ end
40
+ describe 'zero serial numbers invalid' do
41
+ it 'is invalid' do
42
+ assert_equal({zero_serial: 'SSN value contains zeros in serial number xxx-xx-0000'}, Ssn.validate('567890000'))
43
+ end
44
+ end
45
+ describe 'non digits invalid' do
46
+ it 'is invalid' do
47
+ assert_equal({non_digits: 'SSN value contains non-digits'}, Ssn.validate('ABCDEFGHI'))
48
+ end
49
+ end
50
+ describe 'not 9 digits invalid' do
51
+ it 'is invalid' do
52
+ assert_equal({nine_digits: 'SSN value is not 9 digits'}, Ssn.validate('303'))
53
+ end
54
+ end
55
+ describe 'ascending digits invalid' do
56
+ it 'is invalid' do
57
+ assert_equal({ascending: 'SSN value contains all ASCENDING digits'}, Ssn.validate('123456789'))
58
+ assert_equal({ascending: 'SSN value contains all ASCENDING digits'}, Ssn.validate('567891234'))
59
+ end
60
+ end
61
+ describe 'ascending digits ex 0 invalid' do
62
+ it 'is invalid' do
63
+ assert_equal({ascending: 'SSN value contains all ASCENDING digits'}, Ssn.validate('678912345'))
64
+ assert_equal({ascending: 'SSN value contains all ASCENDING digits'}, Ssn.validate('123456789'))
65
+ assert_equal({ascending: 'SSN value contains all ASCENDING digits'}, Ssn.validate('234567891'))
66
+ end
67
+ end
68
+ describe 'descending digits invalid' do
69
+ it 'is invalid' do
70
+ assert_equal({descending: 'SSN value contains all DESCENDING digits'}, Ssn.validate('876543210'))
71
+ assert_equal({descending: 'SSN value contains all DESCENDING digits'}, Ssn.validate('321098765'))
72
+ assert_equal({descending: 'SSN value contains all DESCENDING digits'}, Ssn.validate('987654321'))
73
+ end
74
+ end
75
+ describe 'descending digits ex 0 invalid' do
76
+ it 'is invalid' do
77
+ assert_equal({descending: 'SSN value contains all DESCENDING digits'}, Ssn.validate('321987654'))
78
+ assert_equal({descending: 'SSN value contains all DESCENDING digits'}, Ssn.validate('765432198'))
79
+ end
80
+ end
81
+ describe 'repeating digits invalid' do
82
+ it 'is invalid' do
83
+ assert_equal({repeating: 'SSN value contains repeating digits'}, Ssn.validate('888888888'))
84
+ end
85
+ end
86
+ describe 'invalid ITIN' do
87
+ it 'is invalid' do
88
+ assert_equal({invalid_itin: 'SSN value contains invalid ITIN format 9xx-[x]x-xxxx'}, Ssn.validate('900991234'))
89
+ end
90
+ end
91
+ end
92
+ describe 'allowing dummy ssns' do
93
+ it 'allows 666xxxxx' do
94
+ SsnValidation.config.test_ssns = [/^666/]
95
+ assert_equal({}, Ssn.validate('666123456'))
96
+ SsnValidation.config.test_ssns = []
97
+ end
98
+ it 'allows random test ssns' do
99
+ SsnValidation.config.test_ssns = ['509421234']
100
+ assert_equal({}, Ssn.validate('509421234'))
101
+ SsnValidation.config.test_ssns = []
102
+ end
103
+ it 'allows multiple test ssns' do
104
+ SsnValidation.config.test_ssns = ['999999999', /^666/]
105
+ assert_equal({}, Ssn.validate('666123456'))
106
+ assert_equal({}, Ssn.validate('999999999'))
107
+ SsnValidation.config.test_ssns = []
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,10 @@
1
+ require 'minitest/autorun'
2
+ require 'ssn_validation'
3
+
4
+ class SsnTest < Minitest::Test
5
+ describe 'shortcut validator' do
6
+ it 'validates' do
7
+ assert_equal({}, SsnValidation.validate('123432100'))
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ # require 'minitest/autorun'
2
+ # require 'ssn_validation'
3
+ # require 'activemodel'
4
+
5
+ # class SsnTestModel
6
+ # include ActiveModel::Validations
7
+ # attr_accessor :ssn
8
+ # validates :ssn, social_security_number: true
9
+ # end
10
+
11
+ # class SocialSecurityNumberValidatorTest < Minitest::Test
12
+ # describe 'it uses the ssn validation rules' do
13
+ # it 'validates' do
14
+ # subject = SsnTestModel.new(ssn: '666000000')
15
+ # assert_equal({}, subject.errors)
16
+ # end
17
+ # end
18
+ # end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ssn_validation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - John Stewart
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ description:
42
+ email:
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - Rakefile
48
+ - lib/ssn_validation.rb
49
+ - lib/ssn_validation/ssn.rb
50
+ - lib/ssn_validation/ssn_validation.rb
51
+ - lib/validators/social_security_number_validator.rb
52
+ - lib/version.rb
53
+ - ssn_validation.gemspec
54
+ - test/lib/ssn_validation/ssn_test.rb
55
+ - test/lib/ssn_validation_test.rb
56
+ - test/lib/validators/social_security_number_validator_test.rb
57
+ homepage: https://github.com/johnsinco/ssn_validation
58
+ licenses:
59
+ - Apache-2.0
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '2.3'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.7.6.2
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Social Security Number (SSN) Validation
81
+ test_files:
82
+ - test/lib/ssn_validation/ssn_test.rb
83
+ - test/lib/ssn_validation_test.rb
84
+ - test/lib/validators/social_security_number_validator_test.rb