Skip to content

Commit

Permalink
Add credit card brand validation
Browse files Browse the repository at this point in the history
  • Loading branch information
jmortlock committed Dec 12, 2016
1 parent 35c3e39 commit ddfc2ab
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 35 deletions.
40 changes: 5 additions & 35 deletions lib/sensitive_data_filter/types/credit_card.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# frozen_string_literal: true
require 'credit_card_validations'

module SensitiveDataFilter
module Types
module CreditCard
Expand All @@ -21,7 +23,9 @@ module CreditCard
module_function def valid?(number)
return false unless number.is_a? String
return false unless number.match CARD
Luhn.new(number.gsub(SEPARATORS, '')).valid?
credit_number = number.gsub(SEPARATORS, '')
return false unless CreditCardValidations::Luhn.valid?(credit_number)
CreditCardValidations::Detector.new(credit_number).brand.present?
end

module_function def scan(value)
Expand All @@ -33,40 +37,6 @@ module CreditCard
return value unless value.is_a? String
scan(value).inject(value) { |acc, elem| acc.gsub(elem, FILTERED) }
end

# Adapted from https://github.com/rolfb/luhn-ruby/blob/master/lib/luhn.rb
class Luhn
def initialize(number)
@number = number
end

def valid?
numbers = split_digits(@number)
numbers.last == checksum(numbers[0..-2].join)
end

private

def checksum(number)
products = luhn_doubled(number)
sum = products.inject(0) { |acc, elem| acc + sum_of(elem) }
checksum = 10 - (sum % 10)
checksum == 10 ? 0 : checksum
end

def luhn_doubled(number)
numbers = split_digits(number).reverse
numbers.map.with_index { |n, i| i.even? ? n * 2 : n * 1 }.reverse
end

def sum_of(number)
split_digits(number).inject(:+)
end

def split_digits(number)
number.to_s.split(//).map(&:to_i)
end
end
end
end
end
6 changes: 6 additions & 0 deletions spec/sensitive_data/types/credit_card_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,11 @@ def validations(cards)
specify { expect(scan).to be_empty }
specify { expect(mask).to eq value }
end

context 'a luhn valid number but invalid credit card' do
let(:value) { '1234-5678-9012-3528' }
specify { expect(scan).to be_empty }
specify { expect(mask).to eq value }
end
end
end

0 comments on commit ddfc2ab

Please sign in to comment.