grand_id_simple 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7326065dcdaba538729871712875f03f796e8628e544a5b76dbbcf4b0c2300c
4
- data.tar.gz: 5d80aba6c440c754924ccea8265695b0d6b61a22b9fdf9ceaf2e5f339d66984f
3
+ metadata.gz: 7fd425f3d614ca8058c8545052fffa7ed02a337edfd30e202683b93e3e110733
4
+ data.tar.gz: 6c14aa556412aadea0d3ac5ae7958f5f8f241dc6de28778e9364d845f22b128f
5
5
  SHA512:
6
- metadata.gz: 27465920d416071efedc6f3e7ca79127cc8202f5b55b1b111ddc882a106742aae1fe497751a28762b581ed315886a5fc298cefb2678dd75ba2ff9f649370a585
7
- data.tar.gz: d3925ede49d8018a52298e1e028772ed5927e639c13bf774312766ea7393657cfcebadd2803d3cc935033d711f56972618d8ead9b6ad9ee62bfb77ad45266f37
6
+ metadata.gz: dd88789c2f2fa1c78974ef9eefb9ba0dc721d7b8623d6b4798658ed26828bedb98bfb93e57eb52785647238aaa85dc388ff5a94bada9e5534e8d6cbb0b749d65
7
+ data.tar.gz: 873c900abe5df8f249c49f4fd33da1f22861d8645bacfdad2c788131ee0b56363ae06c5aaa9022413aef404bdadd47bb59663cc694e58d216a0f31a95dabc401
data/.rubocop.yml CHANGED
@@ -1,6 +1,3 @@
1
- require:
2
- rubocop-rake
3
-
4
1
  inherit_gem:
5
2
  rubocop_fonsan_style:
6
3
  - .rubocop.yml
data/Gemfile CHANGED
@@ -9,4 +9,6 @@ gem 'oj'
9
9
  gem 'rake', '~> 13.0'
10
10
  gem 'rspec', '~> 3.0'
11
11
  gem 'rubocop_fonsan_style'
12
+ gem 'sinatra'
12
13
  gem 'typhoeus'
14
+ gem 'webrick'
data/Gemfile.lock CHANGED
@@ -1,35 +1,68 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grand_id_simple (0.1.0)
4
+ grand_id_simple (0.2.0)
5
+ sinatra (~> 2.2)
6
+ typhoeus (~> 1.4)
7
+ webrick (~> 1.8)
5
8
 
6
9
  GEM
7
10
  remote: https://rubygems.org/
8
11
  specs:
9
- activesupport (7.0.4)
10
- concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ activesupport (8.0.0)
13
+ base64
14
+ benchmark (>= 0.3)
15
+ bigdecimal
16
+ concurrent-ruby (~> 1.0, >= 1.3.1)
17
+ connection_pool (>= 2.2.5)
18
+ drb
11
19
  i18n (>= 1.6, < 2)
20
+ logger (>= 1.4.2)
12
21
  minitest (>= 5.1)
13
- tzinfo (~> 2.0)
22
+ securerandom (>= 0.3)
23
+ tzinfo (~> 2.0, >= 2.0.5)
24
+ uri (>= 0.13.1)
14
25
  ast (2.4.2)
15
- concurrent-ruby (1.1.10)
26
+ base64 (0.2.0)
27
+ benchmark (0.4.0)
28
+ bigdecimal (3.1.8)
29
+ concurrent-ruby (1.3.4)
30
+ connection_pool (2.4.1)
16
31
  diff-lcs (1.5.0)
32
+ drb (2.2.1)
17
33
  ethon (0.16.0)
18
34
  ffi (>= 1.15.0)
19
35
  ffi (1.15.5)
20
- i18n (1.12.0)
36
+ haml (6.3.0)
37
+ temple (>= 0.8.2)
38
+ thor
39
+ tilt
40
+ haml_lint (0.59.0)
41
+ haml (>= 5.0)
42
+ parallel (~> 1.10)
43
+ rainbow
44
+ rubocop (>= 1.0)
45
+ sysexits (~> 1.1)
46
+ i18n (1.14.6)
21
47
  concurrent-ruby (~> 1.0)
22
- json (2.6.2)
23
- minitest (5.16.3)
48
+ json (2.8.2)
49
+ language_server-protocol (3.17.0.3)
50
+ logger (1.6.1)
51
+ minitest (5.25.2)
52
+ mustermann (2.0.2)
53
+ ruby2_keywords (~> 0.0.1)
24
54
  oj (3.13.23)
25
- parallel (1.22.1)
26
- parser (3.1.3.0)
55
+ parallel (1.26.3)
56
+ parser (3.3.6.0)
27
57
  ast (~> 2.4.1)
28
- rack (3.0.1)
58
+ racc
59
+ racc (1.8.1)
60
+ rack (2.2.10)
61
+ rack-protection (2.2.4)
62
+ rack
29
63
  rainbow (3.1.1)
30
64
  rake (13.0.6)
31
- regexp_parser (2.6.1)
32
- rexml (3.2.5)
65
+ regexp_parser (2.9.2)
33
66
  rspec (3.12.0)
34
67
  rspec-core (~> 3.12.0)
35
68
  rspec-expectations (~> 3.12.0)
@@ -43,47 +76,63 @@ GEM
43
76
  diff-lcs (>= 1.2.0, < 2.0)
44
77
  rspec-support (~> 3.12.0)
45
78
  rspec-support (3.12.0)
46
- rubocop (1.39.0)
79
+ rubocop (1.68.0)
47
80
  json (~> 2.3)
81
+ language_server-protocol (>= 3.17.0)
48
82
  parallel (~> 1.10)
49
- parser (>= 3.1.2.1)
83
+ parser (>= 3.3.0.2)
50
84
  rainbow (>= 2.2.2, < 4.0)
51
- regexp_parser (>= 1.8, < 3.0)
52
- rexml (>= 3.2.5, < 4.0)
53
- rubocop-ast (>= 1.23.0, < 2.0)
85
+ regexp_parser (>= 2.4, < 3.0)
86
+ rubocop-ast (>= 1.32.2, < 2.0)
54
87
  ruby-progressbar (~> 1.7)
55
- unicode-display_width (>= 1.4.0, < 3.0)
56
- rubocop-ast (1.23.0)
57
- parser (>= 3.1.1.0)
58
- rubocop-performance (1.15.1)
59
- rubocop (>= 1.7.0, < 2.0)
60
- rubocop-ast (>= 0.4.0)
61
- rubocop-rails (2.17.3)
88
+ unicode-display_width (>= 2.4.0, < 3.0)
89
+ rubocop-ast (1.36.1)
90
+ parser (>= 3.3.1.0)
91
+ rubocop-performance (1.23.0)
92
+ rubocop (>= 1.48.1, < 2.0)
93
+ rubocop-ast (>= 1.31.1, < 2.0)
94
+ rubocop-rails (2.27.0)
62
95
  activesupport (>= 4.2.0)
63
96
  rack (>= 1.1)
64
- rubocop (>= 1.33.0, < 2.0)
65
- rubocop-rake (0.6.0)
66
- rubocop (~> 1.0)
67
- rubocop-rspec (2.15.0)
68
- rubocop (~> 1.33)
97
+ rubocop (>= 1.52.0, < 2.0)
98
+ rubocop-ast (>= 1.31.1, < 2.0)
99
+ rubocop-rspec (3.2.0)
100
+ rubocop (~> 1.61)
69
101
  rubocop-rubycw (0.1.6)
70
102
  rubocop (~> 1.0)
71
- rubocop_fonsan_style (0.1.0)
72
- rubocop (~> 1.39)
73
- rubocop-performance (~> 1.15)
74
- rubocop-rails (~> 2.17)
75
- rubocop-rake (~> 0.6.0)
76
- rubocop-rspec (~> 2.15)
103
+ rubocop_fonsan_style (0.1.8)
104
+ haml_lint (~> 0.52)
105
+ rubocop (~> 1.68)
106
+ rubocop-performance (~> 1.22)
107
+ rubocop-rails (~> 2.27)
108
+ rubocop-rspec (~> 3.2)
77
109
  rubocop-rubycw (~> 0.1)
78
- ruby-progressbar (1.11.0)
110
+ ruby-progressbar (1.13.0)
111
+ ruby2_keywords (0.0.5)
112
+ securerandom (0.3.2)
113
+ sinatra (2.2.4)
114
+ mustermann (~> 2.0)
115
+ rack (~> 2.2)
116
+ rack-protection (= 2.2.4)
117
+ tilt (~> 2.0)
118
+ sysexits (1.2.0)
119
+ temple (0.10.3)
120
+ thor (1.3.2)
121
+ tilt (2.1.0)
79
122
  typhoeus (1.4.0)
80
123
  ethon (>= 0.9.0)
81
- tzinfo (2.0.5)
124
+ tzinfo (2.0.6)
82
125
  concurrent-ruby (~> 1.0)
83
- unicode-display_width (2.3.0)
126
+ unicode-display_width (2.6.0)
127
+ uri (1.0.2)
128
+ webrick (1.8.1)
84
129
 
85
130
  PLATFORMS
131
+ arm64-darwin-22
132
+ arm64-darwin-23
86
133
  x86_64-darwin-20
134
+ x86_64-darwin-22
135
+ x86_64-linux
87
136
 
88
137
  DEPENDENCIES
89
138
  grand_id_simple!
@@ -91,7 +140,9 @@ DEPENDENCIES
91
140
  rake (~> 13.0)
92
141
  rspec (~> 3.0)
93
142
  rubocop_fonsan_style
143
+ sinatra
94
144
  typhoeus
145
+ webrick
95
146
 
96
147
  BUNDLED WITH
97
- 2.4.0.dev
148
+ 2.3.26
data/README.md CHANGED
@@ -16,7 +16,28 @@ If bundler is not being used to manage dependencies, install the gem by executin
16
16
 
17
17
  ## Usage
18
18
 
19
- TODO: Write usage instructions here
19
+
20
+ ```bash
21
+ GRAND_ID_API_KEY='123' GRAND_ID_SERVICE_KEY='467' ruby some_app.rb
22
+ ```
23
+
24
+ ```ruby
25
+ api_key, service_key = ENV.values_at('GRAND_ID_API_KEY', 'GRAND_ID_SERVICE_KEY')
26
+
27
+ grand_id_simple = GrandIdSimple.new(api_key, service_key)
28
+
29
+ grand_id_simple.federated_login(your_callback_url)
30
+ # or if you know the personal number and would like to extend the courtesy of not having to scan qr code or manually fill
31
+ login = grand_id_simple.federated_login(your_callback_url, personal_number: '198801010101')
32
+ # => #<struct GrandIdSimple::Login session_id="123", redirect_url="https://grandid.se/redirect....">
33
+ # redirect your user
34
+ redirect_to(login.redirect_url)
35
+
36
+ # Then when you receive the callback:
37
+
38
+ person = grand_id_simple.get_session(params[:grandidsession])
39
+ # => #<struct GrandIdSimple::Person personal_number="198801010101", name="Greta Musk", given_name="Greta", surname="Musk", ip_address=...>
40
+ ```
20
41
 
21
42
  ## Development
22
43
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+ require 'webrick'
5
+ require 'grand_id_simple'
6
+ require 'sinatra/base'
7
+
8
+ class FakeGrandIdSimple < GrandIdSimple
9
+ class FakePerson < Person
10
+ def session_id
11
+ @session_id ||= Digest::SHA256.hexdigest(rand.to_s)
12
+ end
13
+
14
+ def name
15
+ "#{given_name} #{surname}"
16
+ end
17
+ end
18
+
19
+ def self.add_query_parameter(url, name, value)
20
+ uri = URI.parse(url)
21
+ new_query_ar = URI.decode_www_form(uri.query || '') << [name, value]
22
+ uri.query = URI.encode_www_form(new_query_ar)
23
+ uri.to_s
24
+ end
25
+
26
+ def initialize(&block)
27
+ super(nil, nil)
28
+ @block = block
29
+ @people = []
30
+ @server = WEBrick::HTTPServer.new(Port: 0)
31
+ @app = Sinatra.new do
32
+ get '/' do
33
+ return redirect params[:callback_url] if params[:session_id]
34
+
35
+ settings.people.map do |person|
36
+ %(<a href="#{FakeGrandIdSimple.add_query_parameter(params[:callback_url], 'grandidsession', person.session_id)}">#{person.name}</a><br/>)
37
+ end.join
38
+ end
39
+ end
40
+ @app.set :people, @people
41
+ @server.mount('/', Rack::Handler::WEBrick, @app)
42
+ @base_url = "http://localhost:#{@server.config[:Port]}"
43
+ end
44
+
45
+ def start!
46
+ @server_thread = Thread.start { @server.start }
47
+ end
48
+
49
+ def federated_login(callback_url, personal_number: nil)
50
+ @people.concat(@block.call) if @people.empty?
51
+ redirect_url = if personal_number && person = @people.find {|p| p.personal_number == personal_number }
52
+ FakeGrandIdSimple.add_query_parameter(callback_url, 'grandidsession', person.session_id)
53
+ else
54
+ FakeGrandIdSimple.add_query_parameter(@base_url, 'callback_url', callback_url)
55
+ end
56
+ Login.new(redirect_url: redirect_url)
57
+ end
58
+
59
+ def get_session(session_id)
60
+ @people.find {|person| person.session_id == session_id }
61
+ end
62
+
63
+ def logout(_session_id)
64
+ Logout.new(sessiondeleted: true)
65
+ end
66
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class GrandIdSimple
4
- VERSION = '0.1.0'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -5,7 +5,7 @@ require 'oj'
5
5
  require 'typhoeus'
6
6
 
7
7
  class GrandIdSimple
8
- DEFAULT_BASE_URL = 'client.grandid.com'
8
+ DEFAULT_BASE_URL = 'https://client.grandid.com'
9
9
 
10
10
  class Error < StandardError
11
11
  attr_reader :code
@@ -26,6 +26,8 @@ class GrandIdSimple
26
26
  :not_after,
27
27
  :signature,
28
28
  :ocsp_response,
29
+ :uhi,
30
+ :bank_id_issue_date,
29
31
  keyword_init: true,
30
32
  )
31
33
 
@@ -46,29 +48,40 @@ class GrandIdSimple
46
48
  @base_url = base_url
47
49
  end
48
50
 
49
- def federated_login(callback_url, personal_number: nil)
51
+ # callbackUrl string Optional Where to return end-user after completion.
52
+ # customerURL string Optional Where to return end-user if they press the back button.
53
+ # userVisibleData base64 Optional Visible data for the end-user to sign.
54
+ # userNonVisibleData base64 Optional Hidden data included in the signature.
55
+ # userVisibleDataFormat string Optional Used to format the visible signature data.
56
+ # authMessage base64 Optional Visible data for the end-user to auth.
57
+ # mobileBankId bool Optional Set to true to force usage of a Mobile BankID.
58
+ # desktopBankId bool Optional Set to true to force usage of a Desktop BankID.
59
+ # thisDevice bool Optional Set to true to allow usage of the end-users current device
60
+ # qr bool Optional Set to true to allow authentication/signing using a QR code
61
+ # allowFingerprintAuth string Optional Set whether usage of fingerprint biometrics is allowed with the authentication.
62
+ # allowFingerprintSign string Optional Set whether usage of fingerprint biometrics is allowed with the signature.
63
+ # gui string Optional Set to false to opt out of GrandID’s user interface and build your custom implementation.
64
+ # appRedirect string Optional Can be used to force a redirect to specific application from the BankID application.
65
+
66
+ def federated_login(**options)
50
67
  body = call_api(
51
68
  :FederatedLogin,
52
69
  method: :post,
53
70
  body: {
54
- thisDevice: false,
55
- askForSSN: !personal_number,
56
- personalNumber: personal_number,
57
- qr: true,
58
- callbackUrl: callback_url,
71
+ **options,
59
72
  },
60
73
  )
61
- Login.new(lower_keys(body))
74
+ Login.new(body)
62
75
  end
63
76
 
64
77
  def get_session(session_id)
65
78
  body = call_api(:GetSession, params: {sessionId: session_id})
66
- Person.new(lower_keys(body[:userAttributes]))
79
+ Person.new(body[:user_attributes])
67
80
  end
68
81
 
69
82
  def logout(session_id)
70
83
  body = call_api(:Logout, params: {sessionId: session_id})
71
- Logout.new(lower_keys(body))
84
+ Logout.new(body)
72
85
  end
73
86
 
74
87
  private
@@ -81,10 +94,10 @@ class GrandIdSimple
81
94
  body: body,
82
95
  )
83
96
  response = request.run
84
- body = Oj.load(response.body, symbol_keys: true)
97
+ body = json_load(response.body)
85
98
  raise StandardError, 'no body' unless body
86
- if error_object = body[:errorObject]
87
- raise Error.new(*lower_keys(error_object).values_at(:code, :message))
99
+ if error_object = body[:error_object]
100
+ raise Error.new(*error_object.values_at(:code, :message))
88
101
  end
89
102
 
90
103
  body
@@ -97,8 +110,26 @@ class GrandIdSimple
97
110
  }
98
111
  end
99
112
 
100
- def lower_keys(hash)
101
- hash.transform_keys {|k| k.to_s.gsub(/([a-z])([A-Z]+)/, '\1_\2').downcase.to_sym }
113
+ def json_load(body)
114
+ deep_underscore_keys(Oj.load(body, symbol_keys: true))
115
+ end
116
+
117
+ def deep_underscore_keys(hash)
118
+ deep_transform_keys(hash) {|key| key.to_s.gsub(/([a-z])([A-Z]+)/, '\1_\2').downcase.to_sym }
119
+ end
120
+
121
+ def deep_transform_keys(hash, &block)
122
+ hash.each_with_object({}) do |(key, value), result|
123
+ new_key = yield(key)
124
+ new_value = if value.is_a?(Hash)
125
+ deep_transform_keys(value, &block)
126
+ elsif value.is_a?(Array)
127
+ value.map {|item| item.is_a?(Hash) ? deep_transform_keys(item, &block) : item }
128
+ else
129
+ value
130
+ end
131
+ result[new_key] = new_value
132
+ end
102
133
  end
103
134
 
104
135
  def url(call)
metadata CHANGED
@@ -1,15 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grand_id_simple
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fonsan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-26 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-11-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: typhoeus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: webrick
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
13
55
  description: A simple wrapper around the grandid api
14
56
  email:
15
57
  - fonsan@gmail.com
@@ -26,7 +68,7 @@ files:
26
68
  - LICENSE.txt
27
69
  - README.md
28
70
  - Rakefile
29
- - grand_id_simple.gemspec
71
+ - lib/fake_grand_id_simple.rb
30
72
  - lib/grand_id_simple.rb
31
73
  - lib/grand_id_simple/version.rb
32
74
  - sig/grand_id_simple.rbs
@@ -46,14 +88,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
46
88
  requirements:
47
89
  - - ">="
48
90
  - !ruby/object:Gem::Version
49
- version: 2.6.0
91
+ version: 3.0.0
50
92
  required_rubygems_version: !ruby/object:Gem::Requirement
51
93
  requirements:
52
94
  - - ">="
53
95
  - !ruby/object:Gem::Version
54
96
  version: '0'
55
97
  requirements: []
56
- rubygems_version: 3.4.0.dev
98
+ rubygems_version: 3.5.23
57
99
  signing_key:
58
100
  specification_version: 4
59
101
  summary: grandid wrapper
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'lib/grand_id_simple/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'grand_id_simple'
7
- spec.version = GrandIdSimple::VERSION
8
- spec.authors = ['Fonsan']
9
- spec.email = ['fonsan@gmail.com']
10
-
11
- spec.summary = 'grandid wrapper'
12
- spec.description = 'A simple wrapper around the grandid api'
13
- spec.homepage = 'https://github.com/Fonsan/grand_id_simple'
14
- spec.license = 'MIT'
15
- spec.required_ruby_version = '>= 2.6.0'
16
-
17
- spec.metadata['homepage_uri'] = spec.homepage
18
- spec.metadata['source_code_uri'] = spec.homepage
19
- spec.metadata['changelog_uri'] = "#{spec.homepage}/CHANGELOG.md"
20
-
21
- # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
- `git ls-files -z`.split("\x0").reject do |f|
25
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
- end
27
- end
28
- spec.bindir = 'exe'
29
- spec.executables = spec.files.grep(%r{\Aexe/}) {|f| File.basename(f) }
30
- spec.require_paths = ['lib']
31
-
32
- # Uncomment to register a new dependency of your gem
33
- # spec.add_dependency "example-gem", "~> 1.0"
34
-
35
- # For more information and examples about making a new gem, check out our
36
- # guide at: https://bundler.io/guides/creating_gem.html
37
- spec.metadata['rubygems_mfa_required'] = 'true'
38
- end