identification 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c49ff5d80e197aa928760aa1193cb15fbe9b5917
4
+ data.tar.gz: 5335b98ae3ad61dd9e27a3ec98ebf807191a5bab
5
+ SHA512:
6
+ metadata.gz: c7e1f37bd66f8811ef89fce412c3e5ff9f265760ff8000610e1d3c857bca9f7a2d1ee74bb17f22bd35e7bf22b9cb8a6fe4fed90c2719307eca131d1911c35d4e
7
+ data.tar.gz: e537e3b1a55f025e65f02d7f2f6dca7a5dd741303daeb922d6d57acb021a8f2671962e57075f3886029d95edcb6d76788be7f78614d00c7ae52c785fa3486b0e
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ *.gem
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in identification.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Ruby Nealon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,109 @@
1
+ # Identification
2
+
3
+ A suite of tools for working with various identity documents. Allows verification of Passports and (coming very soon) UK Drivers Licenses. Generation tools coming soon.
4
+
5
+ ## Examples
6
+ Create a Passport instance with an MRZ Code.
7
+ ```ruby
8
+ passport = Identification::Passport.new mrz_line_1: "mrz_line_1", mrz_line_2: "mrz_line_2"
9
+ ```
10
+
11
+ and you're done! Use it like this:
12
+
13
+ ```ruby
14
+ passport.valid?
15
+ # => true
16
+ passport.last_name
17
+ # => LAST
18
+ passport.gender
19
+ # => M
20
+ ```
21
+
22
+ ## Installation
23
+
24
+ Add this line to your application's Gemfile:
25
+
26
+ ```ruby
27
+ gem 'identification'
28
+ ```
29
+
30
+ And then execute:
31
+
32
+ $ bundle
33
+
34
+ Or install it yourself as:
35
+
36
+ $ gem install identification
37
+
38
+ ## Usage
39
+
40
+ ### Passport
41
+
42
+ Setup your passport instance like so:
43
+ ```ruby
44
+ passport = Identification::Passport.new mrz_line_1: "mrz_line_1", mrz_line_1: "mrz_line_2"
45
+ ```
46
+
47
+ ```
48
+ mrz_line_1: The first line of a Passport MRZ (the long strip of text on the bottom). (string)
49
+ mrz_line_2: The second line of a Passport MRZ (the long strip of text on the bottom). (string)
50
+ ```
51
+
52
+ It then can be called using any of the folllowing methods/accessors:
53
+
54
+ ```
55
+ valid? : Returns true if it's a valid passport MRZ, false if it's not.
56
+ issuing_state : Issuing country of the passport
57
+ last_name : Last name on the passport
58
+ first_names : Array of first names on the passport (First and any middle names)
59
+ passport_number : Passport Number
60
+ nationality : Nationality of the person on the passport. Different from the issuing state (eg. Swedish person who is also a citizen of UK.)
61
+ date_of_birth : Date of Birth, given as a Ruby Date object.
62
+ gender : Gender, given as M, F or nil if not specified.
63
+ expiry_date : Expiry date of the passport, given as a Ruby Date object.
64
+ personal_number : Personal number, if chosen to be given by issuer. Nil if not specified.
65
+ ```
66
+
67
+ ### UK Drivers License
68
+
69
+ **Note:** *This does not verify check digits yet. I am currently in a 'legal argument' with the DVLA over whether it is in the public interest to release the check digit algorith as they're claiming it is a security threat... Feel free to follow the [FOI request on WhatDoTheyKnow](https://www.whatdotheyknow.com/request/what_check_digit_algorithm_is_us#incoming-670731) and I'll update the gem once I have a response.*
70
+
71
+ Setup your UK Drivers License (DVLA issued only) instance like so:
72
+ ```ruby
73
+ ukdl = Identification::DVLA.new driver_number: "your_driver_number"
74
+ ```
75
+
76
+ ```
77
+ driver_number: driver number from Section 5 of a license, 16 or 18 digit (if 16 digit license_numbers will be set to 00) (string)
78
+ ```
79
+
80
+ It then can be called using any of the folllowing methods/accessors:
81
+
82
+ ```
83
+ valid? : Returns true if it's a valid UK drivers license number, false if it's not.
84
+ last_name : First 5 letters of the last name of the license holder
85
+ first_initials : First initial(s) of the license holder
86
+ date_of_birth : Date of Birth, given as a Ruby Date object.
87
+ gender : Gender, given as M, F or nil if not specified.
88
+ license_numbers : License number (2 digit number at end of section 5)
89
+ ```
90
+
91
+ ## Development
92
+
93
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
94
+
95
+ To install the gem onto your local machine, run `bundle exec rake install`.
96
+
97
+ ## Contributing
98
+
99
+ Bug reports and pull requests are more than welcome on GitHub at https://github.com/rubymeow/identification! <3
100
+
101
+
102
+ ## License
103
+
104
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
105
+
106
+ MRZ parsing based on Document 9303 (Machine Readable Travel Documents - Part 1 - Machine Readable Passports. Volume 1 - Passports with Machine Readable Data Stored in Optical Character Recognition format) by the ICAO which can be found here:
107
+ http://www.icao.int/publications/pages/publication.aspx?docnum=9303
108
+
109
+ Warning: This is by no means a KYC solution on it's own. This merely parses and validates numbers/codes with their given algorithms to make sure they're not an edited forgery. It's not difficult to circumvent this, and this should only be used to validate input or expedite information checking.
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'identification'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'identification/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'identification'
8
+ spec.version = Identification::VERSION
9
+ spec.authors = ['Ruby']
10
+ spec.email = ['hi@ruby.sh']
11
+
12
+ spec.summary = 'A suite of tools for working with various identity documents.'
13
+ spec.description = 'A suite of tools for verifying and generating identity documents. Support is currently provided for parsing passports, and UK Drivers Liceneses are in development. Generation will be added in the near future.'
14
+ spec.homepage = 'https://github.com/rubymeow/identification'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.10'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'minitest'
25
+ end
@@ -0,0 +1,6 @@
1
+ require 'identification/version'
2
+ require 'identification/passport'
3
+ require 'identification/dvla'
4
+
5
+ module Identification
6
+ end
@@ -0,0 +1,81 @@
1
+ module Identification
2
+ # Represents an identity document.
3
+ # This class carries base methods that will appear in all document types.
4
+ #
5
+ # @abstract Subclass and implement a {#parse} method (setting the fields and @validity)
6
+ # and alter {#initialize} to implement a custom Document class. See other classes for examples.
7
+ class Document
8
+ attr_accessor :last_name, :date_of_birth, :gender
9
+
10
+ # Creates an instance of a documents.
11
+ # Will automatically parse if the drivers number is given, and will automatically generate if all necessary fields are set.
12
+ #
13
+ # @param [Hash] details of the paramaters
14
+ # @option opts [String] :last_name surname of the individual (only set for generating)
15
+ # @option opts [String] :date_of_birth date of birth of the individual (only set for generating)
16
+ # @option opts [String] :gender gender of the individual (only set for generating)
17
+ def initialize(params = {})
18
+ @last_name = params[:last_name]
19
+ @date_of_birth = params[:date_of_birth]
20
+ @gender = params[:gender]
21
+ end
22
+
23
+ # Returns true if the drivers license is valid.
24
+ # Requires the driver number to be parsed before it can be called.
25
+ #
26
+ # @return [Boolean] whether or not the passport is valid
27
+ # @raise [RuntimeError] if no mrz has been parsed yet.
28
+ def valid?
29
+ if defined? @validity
30
+ return @validity
31
+ else
32
+ fail 'No document number has been parsed.'
33
+ end
34
+ end
35
+
36
+ # Returns the age of the individual.
37
+ # Requires a date of birth to be set before it can be called.
38
+ #
39
+ # @return [Boolean] age of the individual
40
+ # @raise [RuntimeError] if no date of birth is set
41
+ def age
42
+ if !@date_of_birth.nil?
43
+ now = Time.now.utc.to_date
44
+ dob = @date_of_birth
45
+ return now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
46
+ else
47
+ fail 'No date of birth has been set.'
48
+ end
49
+ end
50
+
51
+ # Returns true if the individual is over 18 (18+)
52
+ # Requires a date of birth to be set before it can be called.
53
+ #
54
+ # @return [Boolean] whether or not the individual is over 18
55
+ # @raise [RuntimeError] if no date of birth is set
56
+ def over_18?
57
+ if !@date_of_birth.nil?
58
+ return true if age >= 18
59
+ else
60
+ fail 'No date of birth has been set.'
61
+ end
62
+
63
+ false
64
+ end
65
+
66
+ # Returns true if the individual is over 21 (21+)
67
+ # Requires a date of birth to be set before it can be called.
68
+ #
69
+ # @return [Boolean] whether or not the individual is over 21
70
+ # @raise [RuntimeError] if no date of birth is set
71
+ def over_21?
72
+ if !@date_of_birth.nil?
73
+ return true if age >= 21
74
+ else
75
+ fail 'No date of birth has been set.'
76
+ end
77
+
78
+ false
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,49 @@
1
+ require 'identification/document'
2
+ require 'identification/parser/dvla'
3
+
4
+ module Identification
5
+ # Represents a UK DVLA-issued Drivers License.
6
+ class DVLA < Document
7
+ attr_accessor :driver_number, :first_initials, :license_numbers
8
+
9
+ # Creates an instance of a drivers license.
10
+ # Will automatically parse if the drivers number is given, and will automatically generate if all necessary fields are set.
11
+ #
12
+ # @param [Hash] details of the paramaters
13
+ # @option opts [String] :driver_number 18 digit driver number, section 5 on a drivers license of the individual (only set for parsing)
14
+ # @option opts [String] :first_initials first initials of the individual (only set for generating)
15
+ # @option opts [String] :last_name surname of the individual - this will be abridged to the first 5 letters only (only set for generating)
16
+ # @option opts [String] :date_of_birth date of birth of the individual (only set for generating)
17
+ # @option opts [String] :gender gender of the individual stored as M or F (only set for generating)
18
+ # @option opts [String] :license_numbers license number of the passport (only set for generating)
19
+ def initialize(params = {})
20
+ super(params)
21
+ @driver_number = params[:driver_number]
22
+ @first_initials = params[:first_initials]
23
+ @license_numbers = params[:license_numbers]
24
+ parse if params.key?(:driver_number)
25
+ end
26
+
27
+ # Parses MRZs and updates the instance variables.
28
+ # Returns true if it was successfuly parsed, false if there was an issue.
29
+ #
30
+ # @return [Boolean] whether the passport is valid or not.
31
+ # @raise [RuntimeError] if there is no MRZ set in the instance.
32
+ def parse
33
+ if !@driver_number.nil?
34
+ result = Parser::DVLA.parse(@driver_number)
35
+ @last_name = result[:last_name] if result.key?(:last_name)
36
+ @first_initials = result[:first_initials] if result.key?(:first_initials)
37
+ @date_of_birth = result[:date_of_birth] if result.key?(:date_of_birth)
38
+ @license_numbers = result[:license_numbers] if result.key?(:license_numbers)
39
+ @gender = result[:gender] if result.key?(:gender)
40
+ @validity = result[:validity]
41
+ return true if @validity
42
+ else
43
+ fail 'No drivers number set to parse.'
44
+ end
45
+
46
+ false
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,75 @@
1
+ require "identification/parser/parser"
2
+
3
+ module Identification
4
+ module Parser
5
+ # Represents a DVLA parser.
6
+ #
7
+ # @private
8
+ class DVLA < Parser
9
+ def self.parse(driver_number)
10
+ # Remove whitespace
11
+ driver_number.gsub!(/\s+/, '')
12
+
13
+ return { validity: false } if driver_number.length != 18 && driver_number.length != 16
14
+
15
+ doc_data = Hash.new(6)
16
+
17
+ # Document will be valid unless an error occurs.
18
+ doc_data[:validity] = true
19
+
20
+ # Document may not be valid, but still, continue parsing.
21
+ doc_data[:validity] = false unless dvla_check_line_checksum(driver_number)
22
+
23
+ doc_data[:last_name] = driver_number[0...5].sub(/9+/, '')
24
+
25
+ doc_data[:first_initials] = driver_number[11...13].sub(/9+/, '')
26
+
27
+ if driver_number.length == 18
28
+ doc_data[:license_numbers] = driver_number[16...18]
29
+ else
30
+ doc_data[:license_numbers] = '00'
31
+ end
32
+
33
+ doc_data[:date_of_birth] = yymmdd_to_ruby_date(driver_number[5...11])
34
+
35
+ if driver_number[6] == '5' || driver_number == '6'
36
+ doc_data[:gender] = 'F'
37
+ else
38
+ doc_data[:gender] = 'M'
39
+ end
40
+
41
+ # In case of an invalid date...
42
+ doc_data[:validity] = false if doc_data[:date_of_birth] == false
43
+
44
+ return doc_data
45
+ end
46
+
47
+ def self.yymmdd_to_ruby_date(input_date)
48
+ # Change the month back (if gender is set to F)
49
+ input_date[1] = '0' if input_date[1] == '5'
50
+ input_date[1] = '1' if input_date[1] == '6'
51
+
52
+ # Put to YYMMDD format
53
+ new_date = String.new(input_date)
54
+ new_date[1] = input_date[5]
55
+ new_date[2] = input_date[1]
56
+ new_date[3] = input_date[2]
57
+ new_date[4] = input_date[3]
58
+ new_date[5] = input_date[4]
59
+ super(new_date)
60
+ end
61
+
62
+ def self.dvla_check_line_checksum(driver_number)
63
+ # Awaiting response from DVLA...
64
+ # Boilerplate content for now...
65
+
66
+ their_check_digit = driver_number[13...16]
67
+
68
+ # Returning true until I know how to calculate check digits
69
+ true
70
+ end
71
+
72
+ private_class_method :dvla_check_line_checksum
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,36 @@
1
+ require 'date'
2
+
3
+ module Identification
4
+ module Parser
5
+ # Represents a document parser.
6
+ # This class carries base methods that are required to process all documents.
7
+ #
8
+ # @private
9
+ # @abstract Subclass and implement a {#parse} method for the specific document type.
10
+ class Parser
11
+ def self.yymmdd_to_ruby_date(input_date)
12
+ # Only putting the last 2 digits of a date has the flaw of not knowing which century.
13
+ # So I use the current year as a cut off.
14
+ # Sorry to those over 100! :-(
15
+ current_year_yy = (Date.today.strftime('%Y'))[2..4]
16
+ input_year_yy = input_date[0..1]
17
+ input_month = input_date[2..3]
18
+ input_day = input_date[4..5]
19
+
20
+ begin
21
+ return Date.parse(input_day + '-' + input_month + '-' + '19' + input_year_yy) if input_year_yy >= current_year_yy
22
+ rescue
23
+ return false
24
+ end
25
+
26
+ begin
27
+ return Date.parse(input_day + '-' + input_month + '-' + '20' + input_year_yy)
28
+ rescue
29
+ return false
30
+ end
31
+ end
32
+
33
+ private_class_method :yymmdd_to_ruby_date
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,87 @@
1
+ require "identification/parser/parser"
2
+
3
+ module Identification
4
+ module Parser
5
+ # Represents a passport parser.
6
+ #
7
+ # @private
8
+ class Passport < Parser
9
+ def self.parse(mrz_line_1, mrz_line_2)
10
+ return { validity: false } if mrz_line_1.length != 44 || mrz_line_2.length != 44
11
+
12
+ doc_data = Hash.new(10)
13
+
14
+ # Document will be valid unless an error occurs.
15
+ doc_data[:validity] = true
16
+
17
+ # Document may not be valid, but still, continue parsing.
18
+ doc_data[:validity] = false unless mrz_check_line_checksum(mrz_line_2)
19
+
20
+ # Read the first line without chevrons
21
+ split = mrz_line_1.split(/<+/)
22
+
23
+ doc_data[:date_of_birth] = yymmdd_to_ruby_date(mrz_line_2[13...19])
24
+ doc_data[:expiry_date] = yymmdd_to_ruby_date(mrz_line_2[21...27])
25
+
26
+ # In case of an invalid date...
27
+ if doc_data['date_of_birth'] == false || doc_data['expiry_date'] == false
28
+ doc_data[:validity] = false
29
+ end
30
+
31
+ doc_data[:issuing_state] = mrz_line_1[2...5].sub(/<+/, '')
32
+ doc_data[:last_name] = split[1][3..-1]
33
+ doc_data[:first_names] = split[2..-1]
34
+ doc_data[:passport_number] = mrz_line_2[0...9]
35
+ doc_data[:nationality] = mrz_line_2[10...13].sub(/<+/, '')
36
+ doc_data[:gender] = mrz_line_2[20].sub(/<+/, '')
37
+ doc_data[:personal_number] = mrz_line_2[28...42].sub(/<+/, '')
38
+
39
+ doc_data
40
+ end
41
+
42
+ def self.mrz_check_digit_calculate(str)
43
+ str = str.strip.upcase
44
+ values = str.chars.map do |char|
45
+ case char
46
+ when '<'
47
+ 0
48
+ when 'A'..'Z'
49
+ char.ord - 65 + 10
50
+ when '0'..'9'
51
+ char.ord - 48
52
+ else
53
+ fail "Unexpected character '#{char}'"
54
+ end
55
+ end
56
+ (values.zip([7, 3, 1].cycle).map { |(v, w)| v * w }.reduce(:+) % 10).to_s
57
+ end
58
+
59
+ def self.mrz_check_line_checksum(mrz_line)
60
+ # Grabbing the MRZ's check digits
61
+ doc_check = []
62
+ doc_check[0] = mrz_line[9].to_s
63
+ doc_check[1] = mrz_line[19].to_s
64
+ doc_check[2] = mrz_line[27].to_s
65
+ doc_check[3] = mrz_line[42].to_s
66
+ doc_check[4] = mrz_line[43].to_s
67
+
68
+ # Calculating our own check digits...
69
+ our_check = []
70
+ our_check[0] = mrz_check_digit_calculate(mrz_line[0...9])
71
+ our_check[1] = mrz_check_digit_calculate(mrz_line[13...19])
72
+ our_check[2] = mrz_check_digit_calculate(mrz_line[21...27])
73
+ our_check[3] = mrz_check_digit_calculate(mrz_line[28...42])
74
+ our_check[4] = mrz_check_digit_calculate(mrz_line[0...10] + mrz_line[13...20] + mrz_line[21...43])
75
+
76
+ # The 4th check digit can be either > or 0, we always return 0 from our CheckDigit calc.
77
+ our_check[3] = '<' if our_check[3] == '0' && doc_check[3] == '<'
78
+
79
+ return true if doc_check.uniq.sort == our_check.uniq.sort
80
+
81
+ false
82
+ end
83
+
84
+ private_class_method :mrz_check_digit_calculate, :mrz_check_line_checksum
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,65 @@
1
+ require 'identification/document'
2
+ require 'identification/parser/passport'
3
+
4
+ module Identification
5
+ # Represents a passport with an MRZ or fields that create an MRZ.
6
+ class Passport < Document
7
+ attr_accessor :mrz_line_1, :mrz_line_2, :issuing_state, :first_names, :passport_number, :nationality, :expiry_date, :personal_number
8
+
9
+ # Creates an instance of a passport.
10
+ # Will automatically parse if both MRZ lines are given, and will automatically generate if all necessary fields are set.
11
+ # (all except personal number which is rarely used)
12
+ #
13
+ # @param [Hash] details of the paramaters
14
+ # @option opts [String] :mrz_line_1 first line of the machine readable zone (only set for parsing)
15
+ # @option opts [String] :mrz_line_2 second line of the machine readable zone (only set for parsing)
16
+ # @option opts [String] :issuing_state : issuing state of the individual's passport (only set for generating)
17
+ # @option opts [String] :first_names : array of first names on the passport (only set for generating)
18
+ # @option opts [String] :last_name surname of the individual (only set for generating)
19
+ # @option opts [String] :date_of_birth date of birth of the individual (only set for generating)
20
+ # @option opts [String] :gender gender of the individual (only set for generating)
21
+ # @option opts [String] :passport_number : passport number of the individual (only set for generating)
22
+ # @option opts [String] :nationality : nationality of the individual (only set for generating)
23
+ # @option opts [String] :expiry_date : expiry date of the passport, given as a date object (only set for generating)
24
+ # @option opts [String] :personal_number : personal number of the individual - optional (only set for generating)
25
+ def initialize(params = {})
26
+ super(params)
27
+ @mrz_line_1 = params[:mrz_line_1]
28
+ @mrz_line_2 = params[:mrz_line_2]
29
+ @issuing_state = params[:issuing_state]
30
+ @first_names = params[:first_names]
31
+ @passport_number = params[:passport_number]
32
+ @nationality = params[:nationality]
33
+ @expiry_date = params[:expiry_date]
34
+ @personal_number = params[:personal_number]
35
+
36
+ parse if params.key?(:mrz_line_1) && params.key?(:mrz_line_2)
37
+ end
38
+
39
+ # Parses MRZs and updates the instance variables.
40
+ # Returns true if it was successfuly parsed, false if there was an issue.
41
+ #
42
+ # @return [Boolean] whether the passport is valid or not.
43
+ # @raise [RuntimeError] if there is no MRZ set in the instance.
44
+ def parse
45
+ if !@mrz_line_1.nil? && !@mrz_line_2.nil?
46
+ result = Parser::Passport.parse(@mrz_line_1, @mrz_line_2)
47
+ @issuing_state = result[:issuing_state] if result.key?(:issuing_state)
48
+ @last_name = result[:last_name] if result.key?(:last_name)
49
+ @first_names = result[:first_names] if result.key?(:first_names)
50
+ @passport_number = result[:passport_number] if result.key?(:passport_number)
51
+ @nationality = result[:nationality] if result.key?(:nationality)
52
+ @date_of_birth = result[:date_of_birth] if result.key?(:date_of_birth)
53
+ @gender = result[:gender] if result.key?(:gender)
54
+ @expiry_date = result[:expiry_date] if result.key?(:expiry_date)
55
+ @personal_number = result[:personal_number] if result.key?(:personal_number)
56
+ @validity = result[:validity]
57
+ return true if @validity
58
+ else
59
+ fail 'No MRZ set to parse.'
60
+ end
61
+
62
+ false
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,4 @@
1
+ module Identification
2
+ # Stores the version of the gem.
3
+ VERSION = '0.1.0'
4
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: identification
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ruby
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-07-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A suite of tools for verifying and generating identity documents. Support
56
+ is currently provided for parsing passports, and UK Drivers Liceneses are in development.
57
+ Generation will be added in the near future.
58
+ email:
59
+ - hi@ruby.sh
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - bin/console
71
+ - bin/setup
72
+ - identification.gemspec
73
+ - lib/identification.rb
74
+ - lib/identification/document.rb
75
+ - lib/identification/dvla.rb
76
+ - lib/identification/parser/dvla.rb
77
+ - lib/identification/parser/parser.rb
78
+ - lib/identification/parser/passport.rb
79
+ - lib/identification/passport.rb
80
+ - lib/identification/version.rb
81
+ homepage: https://github.com/rubymeow/identification
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.4.8
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: A suite of tools for working with various identity documents.
105
+ test_files: []