ssn_validation 0.1.2
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 +7 -0
- data/Rakefile +10 -0
- data/lib/ssn_validation.rb +2 -0
- data/lib/ssn_validation/ssn.rb +56 -0
- data/lib/ssn_validation/ssn_validation.rb +18 -0
- data/lib/validators/social_security_number_validator.rb +13 -0
- data/lib/version.rb +3 -0
- data/ssn_validation.gemspec +22 -0
- data/test/lib/ssn_validation/ssn_test.rb +111 -0
- data/test/lib/ssn_validation_test.rb +10 -0
- data/test/lib/validators/social_security_number_validator_test.rb +18 -0
- metadata +84 -0
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,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,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,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
|