cpr-client 0.0.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
+ 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: