cpr-client 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 370bb6e5adf2275a7517d5cd4e16a7a3238f6a8c
4
+ data.tar.gz: f343164a5508cfa3e94fd493fce9402c08c93de5
5
+ SHA512:
6
+ metadata.gz: 23fabf0b46d29328714286fc0679d44eca2389d1310123c81e851e49a2cdf7978d40cee6119d667972a1804ef982b0750d9b3a9611c31f60c8b037adeca36f5f
7
+ data.tar.gz: a6920f3334801db2193dd894ec4f11f2db0e975cdc4ea376121b0be11b4e4e07b1356d0bd627a4b31376992da62e6c9a748e3adbb3c2ea841d1d13454d0c0424
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ CPR Client
2
+ ===
3
+
4
+ A client for looking up people in the CPR registry (as a private company).
5
+ It is backed by HTTPClient.
6
+
7
+ ```ruby
8
+ # The client is connecting to the demo environment
9
+ client = CPRClient.new(username, password, true)
10
+ record = client.lookup('0707614285')
11
+
12
+ if record.nil?
13
+ puts "The record was not found"
14
+ elsif record.protected?
15
+ puts "The record has name and address protection"
16
+ else
17
+ puts record[:adrnvn]
18
+ puts record[:adrnvn, :t]
19
+ end
20
+ ```
data/lib/cpr_client.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'cpr_client/client'
2
+ require 'cpr_client/record'
3
+ require 'cpr_client/errors'
4
+ require 'cpr_client/version'
5
+
6
+ module CPRClient
7
+
8
+ ENDPOINT_DEMO = 'https://gctp-demo.cpr.dk/cpr-online-gctp/gctp'
9
+ ENDPOINT_PROD = 'https://gctp.cpr.dk/cpr-online-gctp/gctp'
10
+
11
+ # Returns a new Client.
12
+ #
13
+ # @param user your cpr username
14
+ # @param pass your current cpr password
15
+ # @param demo use demo endpoint
16
+ def self.new(user, pass, demo = false)
17
+ Client.new(user, pass, demo ? ENDPOINT_DEMO : ENDPOINT_PROD)
18
+ end
19
+
20
+ end
@@ -0,0 +1,131 @@
1
+ require 'httpclient'
2
+ require 'nokogiri'
3
+ require 'cpr_client/record'
4
+ require 'cpr_client/errors'
5
+ require 'cpr_client/version'
6
+
7
+ module CPRClient
8
+
9
+ class Client
10
+
11
+ # Returns a new Client.
12
+ #
13
+ # @param user your cpr username
14
+ # @param pass your current cpr password
15
+ # @param endpoint the full URI to the cpr gctp service
16
+ def initialize(user, pass, endpoint)
17
+ @user, @pass, @endpoint = user, pass, endpoint
18
+ @http = HTTPClient.new(
19
+ agent_name: "CPRClient/#{CPRClient::VERSION}",
20
+ default_header: { 'Content-Type' => 'text/xml' }
21
+ )
22
+ end
23
+
24
+ # Returns a Record object or nil if the record could not be found.
25
+ # If the client is not logged in, a login is performed before a retry.
26
+ #
27
+ # The cpr parameter is stripped of any non-digits.
28
+ #
29
+ # @param cpr a string
30
+ # @return a #Record or nil if no record was found
31
+ def lookup(cpr)
32
+ xml_doc = post_auto_login(stamp_body(digits(cpr)))
33
+ case receipt_code(xml_doc)
34
+ when 0
35
+ Record.new(xml_doc)
36
+ when 172, 52
37
+ nil
38
+ else
39
+ raise ClientError, "Unexpected STAMP resp: #{xml_doc}"
40
+ end
41
+ end
42
+
43
+ alias_method :stamp, :lookup
44
+
45
+ # Performs login for client.
46
+ #
47
+ # @return true
48
+ # @raise LoginError if login failed
49
+ def login
50
+ code = receipt_code(post(login_body))
51
+ code == 900 or raise LoginError, code
52
+ end
53
+
54
+ protected
55
+
56
+ # Returns the gctp status code of the given xml_doc.
57
+ #
58
+ # If a receipt is not preset then -1 is returned.
59
+ #
60
+ # @param xml_doc a Nokogiri::XML object
61
+ # @return a Fixnum gctp status code
62
+ def receipt_code(xml_doc)
63
+ node = xml_doc && xml_doc.at_css('Kvit')
64
+ node && node['v'] ? node['v'].to_i : -1
65
+ end
66
+
67
+ # Removes all non digit characters from string
68
+ def digits(arg)
69
+ arg.to_s.gsub(/\D+/,'')
70
+ end
71
+
72
+ # Posts xml to the server.
73
+ #
74
+ # A login is performed if the client is not logged in,
75
+ # or if the login is expired.
76
+ #
77
+ # @param body a string of xml
78
+ # @return a Nokogiri::XML object
79
+ # @raise ClientError if the response status was not 200
80
+ # @raise LoginError if login failed
81
+ def post_auto_login(body)
82
+ xml_doc = post(body)
83
+ xml_doc = login && post(body) if receipt_code(xml_doc) == 901
84
+ xml_doc
85
+ end
86
+
87
+ # Posts a request to the service with xml as content type.
88
+ #
89
+ # @param body a string of xml
90
+ # @return a Nokogiri::XML object
91
+ # @raise ClientError if the response status was not 200
92
+ def post(body)
93
+ resp = @http.post(@endpoint, body)
94
+ raise ClientError, 'Bad response' if resp.status != 200
95
+ Nokogiri::XML(resp.body)
96
+ end
97
+
98
+ private
99
+
100
+ def login_body
101
+ <<-DATA
102
+ <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
103
+ <root xmlns="http://www.cpr.dk">
104
+ <Gctp v=”1.0”>
105
+ <Sik function="signon" userid="#{@user}" password="#{@pass}"/>
106
+ </Gctp>
107
+ </root>
108
+ DATA
109
+ end
110
+
111
+ def stamp_body(cpr)
112
+ <<-DATA
113
+ <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
114
+ <root xmlns="http://www.cpr.dk">
115
+ <Gctp v="1.0">
116
+ <System r="CprSoeg">
117
+ <Service r="STAMP">
118
+ <CprServiceHeader r="STAMP">
119
+ <Key>
120
+ <Field r="PNR" v="#{cpr}"/>
121
+ </Key>
122
+ </CprServiceHeader>
123
+ </Service>
124
+ </System>
125
+ </Gctp>
126
+ </root>
127
+ DATA
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,19 @@
1
+ module CPRClient
2
+
3
+ class ClientError < StandardError; end
4
+
5
+ class LoginError < ClientError
6
+
7
+ attr_reader :code
8
+
9
+ # Returns a new instance of LoginError.
10
+ #
11
+ # @param code login error code
12
+ def initialize(code)
13
+ @code = code
14
+ super("CPRClient login failed [#{code}]")
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,63 @@
1
+ module CPRClient
2
+ class Record
3
+
4
+ attr_reader :timestamp, :fields
5
+
6
+ # Returns a new Response.
7
+ #
8
+ # @param xml_doc a Nokogiri::XML object
9
+ def initialize(xml_doc)
10
+ @timestamp = xml_doc.at_css("CprServiceHeader[r='STAMP']")['ts']
11
+ @fields = extract_fields(xml_doc)
12
+ end
13
+
14
+ # Gets the value of a field with the given name.
15
+ #
16
+ # @param name the name of the target field.
17
+ # @param value the name of the value attribute
18
+ def get(name, value = 'v')
19
+ field = @fields[name.to_s.upcase]
20
+ field[value.to_s.downcase] if field
21
+ end
22
+
23
+ alias_method :[], :get
24
+
25
+ # Returns true if the person has name/address protection.
26
+ #
27
+ # @return true if protected, false otherwise
28
+ def protected?
29
+ get(:beskyt) == '1'
30
+ end
31
+
32
+ # Returns the birthday as Date.
33
+ #
34
+ # @return Date with date of birth
35
+ def birthday
36
+ Date.parse(get(:foeddato))
37
+ end
38
+
39
+ # Returns the record's address if present.
40
+ #
41
+ # The address will be a string of the fields
42
+ # STADR, POSTNR and POSTNR's t attribute.
43
+ #
44
+ # Fx. Boulevarden 101,1 mf, 6800 Varde
45
+ #
46
+ # @return string with address or nil
47
+ def address
48
+ values = [ get(:stadr), get(:postnr), get(:postnr, :t) ]
49
+ '%s, %s %s' % values if values.all?
50
+ end
51
+
52
+ private
53
+
54
+ def extract_fields(xml_doc)
55
+ Hash[xml_doc.css("Praes[r='STAMPNR'] Field").reduce([]) { |a, f|
56
+ attrs = Hash[f.keys.zip(f.values)]
57
+ key = attrs.delete('r')
58
+ attrs.empty? ? a : a << [key, attrs]
59
+ }]
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module CPRClient
2
+ VERSION = '0.0.2'
3
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cpr-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Michael Andersen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-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: '10.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: httpclient
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.7'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.7'
69
+ description: Client for making requests to the CPR registry (as a private company)
70
+ email: michael@aion.dk
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - lib/cpr_client.rb
77
+ - lib/cpr_client/client.rb
78
+ - lib/cpr_client/errors.rb
79
+ - lib/cpr_client/record.rb
80
+ - lib/cpr_client/version.rb
81
+ homepage: http://assemblyvoting.dk
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.5.1
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: CPR Client
105
+ test_files: []
106
+ has_rdoc: