passageidentity 0.0.4 → 0.0.5
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 +4 -4
- data/.github/workflows/deploy.yml +30 -0
- data/.github/workflows/on_pr.yml +34 -0
- data/.gitignore +1 -2
- data/CONTRIBUTING.md +11 -16
- data/lib/passageidentity/auth.rb +19 -19
- data/lib/passageidentity/client.rb +39 -38
- data/lib/passageidentity/user_api.rb +101 -101
- data/lib/passageidentity.rb +2 -2
- data/passageidentity.gemspec +2 -1
- data/tests/all.rb +3 -2
- data/tests/auth_test.rb +8 -7
- data/tests/magic_link_test.rb +8 -7
- data/tests/user_api_test.rb +17 -16
- metadata +22 -7
- data/passage-ruby +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dfa34c812dd0c803c77a375095960299d732b8d0ce07eacdefca3aec3aa4f8a
|
4
|
+
data.tar.gz: cf34eeee8ec89edbeab4249f2f579a735e2a0a867edb646ee12432ade01758dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18af9cbfe8169d5065365d4f4db14cc428720554e014c46c814e9b34a5198198099978f9a7b9ebdaae38f6fae933edb689fdff694c3782cf89e2cc7ed592fde9
|
7
|
+
data.tar.gz: c76ad6cfc72baebdb6d55da7d454ec3e1b8077b9a81fa69a8779a6b420a9b728f84bf78800b58ffa839c546e161cf5c57129594b20e4a4f0b8a8b2372ec37aa3
|
@@ -0,0 +1,30 @@
|
|
1
|
+
name: Deploy Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [main]
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
build:
|
9
|
+
name: Build + Publish
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
permissions:
|
12
|
+
contents: read
|
13
|
+
packages: write
|
14
|
+
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v2
|
17
|
+
- uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: '3.0'
|
20
|
+
|
21
|
+
- name: Publish to RubyGems
|
22
|
+
run: |
|
23
|
+
mkdir -p $HOME/.gem
|
24
|
+
touch $HOME/.gem/credentials
|
25
|
+
chmod 0600 $HOME/.gem/credentials
|
26
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
27
|
+
gem build *.gemspec
|
28
|
+
gem push *.gem
|
29
|
+
env:
|
30
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: PR Checks
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
branches: [ main ]
|
6
|
+
|
7
|
+
env:
|
8
|
+
API_KEY: ${{ secrets.API_KEY }}
|
9
|
+
APP_ID: ${{ secrets.APP_ID }}
|
10
|
+
PSG_JWT: ${{ secrets.PSG_JWT }}
|
11
|
+
TEST_USER_ID: ${{ secrets.TEST_USER_ID }}
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
build:
|
15
|
+
name: Test and Lint
|
16
|
+
runs-on: ubuntu-latest
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
- uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: '3.0'
|
23
|
+
|
24
|
+
- name: Run Tests
|
25
|
+
run: |
|
26
|
+
gem build passageidentity.gemspec -o test.gem
|
27
|
+
gem install test.gem
|
28
|
+
rm test.gem
|
29
|
+
ruby tests/all.rb
|
30
|
+
- name: Run Linting
|
31
|
+
run: |
|
32
|
+
npm install -g prettier @prettier/plugin-ruby
|
33
|
+
gem install bundler prettier_print syntax_tree syntax_tree-haml syntax_tree-rbs
|
34
|
+
prettier --check '**/*.rb'
|
data/.gitignore
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
Install the gem
|
6
6
|
|
7
7
|
```
|
8
|
-
gem build passageidentity.gemspec
|
9
|
-
gem install ./
|
8
|
+
gem build passageidentity.gemspec -o {$FILE_NAME}.gem
|
9
|
+
gem install ./{$FILE_NAME}.gem
|
10
10
|
```
|
11
11
|
|
12
12
|
Test it out:
|
@@ -27,6 +27,15 @@ ruby tests/all.rb
|
|
27
27
|
ruby tests/*_test.rb
|
28
28
|
```
|
29
29
|
|
30
|
+
Run Linter:
|
31
|
+
|
32
|
+
```
|
33
|
+
npm install -g prettier @prettier/plugin-ruby
|
34
|
+
gem install bundler prettier_print syntax_tree syntax_tree-haml syntax_tree-rbs
|
35
|
+
prettier --fix '**/*.rb'
|
36
|
+
```
|
37
|
+
|
38
|
+
|
30
39
|
To test in the example app, change the Gemfile to include this path:
|
31
40
|
|
32
41
|
```
|
@@ -45,7 +54,6 @@ Enter host password for user '<username>':
|
|
45
54
|
```
|
46
55
|
|
47
56
|
```
|
48
|
-
<<<<<<< HEAD
|
49
57
|
gem push passage-0.0.0.gem
|
50
58
|
```
|
51
59
|
|
@@ -55,17 +63,4 @@ You can check for the gem here:
|
|
55
63
|
gem list -r passage
|
56
64
|
```
|
57
65
|
|
58
|
-
=======
|
59
|
-
gem push passageidentity-0.0.0.gem
|
60
|
-
|
61
|
-
```
|
62
|
-
|
63
|
-
You can check for the gem here:
|
64
|
-
|
65
|
-
```
|
66
|
-
|
67
|
-
gem list -r passageidentity
|
68
|
-
|
69
|
-
```
|
70
|
-
>>>>>>> 2d0e3f6dc3b40c621c8d16506fa6ab43b0fba673
|
71
66
|
```
|
data/lib/passageidentity/auth.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require_relative
|
1
|
+
require "openssl"
|
2
|
+
require "base64"
|
3
|
+
require "jwt"
|
4
|
+
require_relative "client"
|
5
5
|
|
6
6
|
module Passage
|
7
7
|
class Auth
|
@@ -17,10 +17,10 @@ module Passage
|
|
17
17
|
def fetch_app()
|
18
18
|
begin
|
19
19
|
response = @connection.get("/v1/apps/#{@app_id}")
|
20
|
-
return response.body[
|
20
|
+
return response.body["app"]
|
21
21
|
rescue Faraday::Error => e
|
22
22
|
raise PassageError,
|
23
|
-
"failed to get Passage
|
23
|
+
"failed to get Passage App. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -30,7 +30,7 @@ module Passage
|
|
30
30
|
else
|
31
31
|
app = fetch_app
|
32
32
|
auth_gw_connection =
|
33
|
-
Faraday.new(url:
|
33
|
+
Faraday.new(url: "https://auth.passage.id") do |f|
|
34
34
|
f.request :json
|
35
35
|
f.request :retry
|
36
36
|
f.response :raise_error
|
@@ -40,7 +40,7 @@ module Passage
|
|
40
40
|
|
41
41
|
# fetch the public key if not in cache
|
42
42
|
app = fetch_app
|
43
|
-
@auth_origin = app[
|
43
|
+
@auth_origin = app["auth_origin"]
|
44
44
|
response =
|
45
45
|
auth_gw_connection.get("/v1/apps/#{@app_id}/.well-known/jwks.json")
|
46
46
|
@jwks = response.body
|
@@ -51,33 +51,33 @@ module Passage
|
|
51
51
|
def authenticate_request(request)
|
52
52
|
# Get the token based on the strategy
|
53
53
|
if @auth_strategy === Passage::COOKIE_STRATEGY
|
54
|
-
unless request.cookies[
|
54
|
+
unless request.cookies["psg_auth_token"].present?
|
55
55
|
raise PassageError,
|
56
56
|
`missing authentication token: expected "psg_auth_token" cookie`
|
57
57
|
end
|
58
|
-
@token = request.cookies[
|
58
|
+
@token = request.cookies["psg_auth_token"]
|
59
59
|
else
|
60
60
|
headers = request.headers
|
61
|
-
unless headers[
|
62
|
-
raise PassageError,
|
61
|
+
unless headers["Authorization"].present?
|
62
|
+
raise PassageError, "no authentication token in header"
|
63
63
|
end
|
64
|
-
@token = headers[
|
64
|
+
@token = headers["Authorization"].split(" ").last
|
65
65
|
end
|
66
66
|
|
67
67
|
# authenticate the token
|
68
68
|
if @token
|
69
69
|
return authenticate_token(@token)
|
70
70
|
else
|
71
|
-
raise PassageError,
|
71
|
+
raise PassageError, "no authentication token"
|
72
72
|
end
|
73
73
|
nil
|
74
74
|
end
|
75
75
|
|
76
76
|
def authenticate_token(token)
|
77
|
-
kid = JWT.decode(token, nil, false)[1][
|
77
|
+
kid = JWT.decode(token, nil, false)[1]["kid"]
|
78
78
|
exists = false
|
79
|
-
for jwk in @jwks[
|
80
|
-
if jwk[
|
79
|
+
for jwk in @jwks["keys"]
|
80
|
+
if jwk["kid"] == kid
|
81
81
|
exists = true
|
82
82
|
break
|
83
83
|
end
|
@@ -94,11 +94,11 @@ module Passage
|
|
94
94
|
verify_iss: true,
|
95
95
|
aud: @auth_origin,
|
96
96
|
verify_aud: true,
|
97
|
-
algorithms: [
|
97
|
+
algorithms: ["RS256"],
|
98
98
|
jwks: @jwks
|
99
99
|
}
|
100
100
|
)
|
101
|
-
return claims[0][
|
101
|
+
return claims[0]["sub"]
|
102
102
|
rescue JWT::InvalidIssuerError => e
|
103
103
|
raise Passage::PassageError, e.message
|
104
104
|
rescue JWT::InvalidAudError => e
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative "auth"
|
4
|
+
require_relative "user_api"
|
5
|
+
require_relative "error"
|
6
6
|
|
7
7
|
module Passage
|
8
8
|
User =
|
@@ -43,21 +43,21 @@ module Passage
|
|
43
43
|
COOKIE_STRATEGY = 0
|
44
44
|
HEADER_STRATEGY = 1
|
45
45
|
|
46
|
-
EMAIL_CHANNEL =
|
47
|
-
PHONE_CHANNEL =
|
46
|
+
EMAIL_CHANNEL = "email"
|
47
|
+
PHONE_CHANNEL = "phone"
|
48
48
|
|
49
49
|
class Client
|
50
50
|
attr_reader :auth
|
51
51
|
attr_reader :user
|
52
52
|
|
53
|
-
def initialize(app_id:, api_key:
|
54
|
-
@api_url =
|
53
|
+
def initialize(app_id:, api_key: "", auth_strategy: COOKIE_STRATEGY)
|
54
|
+
@api_url = "https://api.passage.id"
|
55
55
|
@app_id = app_id
|
56
56
|
@api_key = api_key
|
57
57
|
|
58
58
|
# check for valid auth strategy
|
59
59
|
unless [COOKIE_STRATEGY, HEADER_STRATEGY].include? auth_strategy
|
60
|
-
raise PassageError,
|
60
|
+
raise PassageError, "invalid auth strategy."
|
61
61
|
end
|
62
62
|
@auth_strategy = auth_strategy
|
63
63
|
|
@@ -72,7 +72,7 @@ module Passage
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def get_connection
|
75
|
-
if @api_key ==
|
75
|
+
if @api_key == ""
|
76
76
|
@connection =
|
77
77
|
Faraday.new(url: @api_url) do |f|
|
78
78
|
f.request :json
|
@@ -86,7 +86,7 @@ module Passage
|
|
86
86
|
Faraday.new(
|
87
87
|
url: @api_url,
|
88
88
|
headers: {
|
89
|
-
|
89
|
+
"Authorization" => "Bearer #{@api_key}"
|
90
90
|
}
|
91
91
|
) do |f|
|
92
92
|
f.request :json
|
@@ -99,53 +99,54 @@ module Passage
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def create_magic_link(
|
102
|
-
user_id:
|
103
|
-
email:
|
104
|
-
phone:
|
105
|
-
channel:
|
102
|
+
user_id: "",
|
103
|
+
email: "",
|
104
|
+
phone: "",
|
105
|
+
channel: "",
|
106
106
|
send: false,
|
107
|
-
magic_link_path:
|
108
|
-
redirect_url:
|
107
|
+
magic_link_path: "",
|
108
|
+
redirect_url: "",
|
109
109
|
ttl: 60
|
110
110
|
)
|
111
111
|
magic_link_req = {}
|
112
|
-
magic_link_req[
|
113
|
-
magic_link_req[
|
114
|
-
magic_link_req[
|
112
|
+
magic_link_req["user_id"] = user_id unless user_id.empty?
|
113
|
+
magic_link_req["email"] = email unless email.empty?
|
114
|
+
magic_link_req["phone"] = phone unless phone.empty?
|
115
115
|
|
116
116
|
# check to see if the channel specified is valid before sending it off to the server
|
117
117
|
unless [PHONE_CHANNEL, EMAIL_CHANNEL].include? channel
|
118
118
|
raise PassageError,
|
119
|
-
|
119
|
+
"channel: must be either Passage::EMAIL_CHANNEL or Passage::PHONE_CHANNEL"
|
120
120
|
end
|
121
|
-
magic_link_req[
|
122
|
-
magic_link_req[
|
123
|
-
magic_link_req[
|
124
|
-
|
125
|
-
|
126
|
-
magic_link_req[
|
121
|
+
magic_link_req["channel"] = channel unless channel.empty?
|
122
|
+
magic_link_req["send"] = send
|
123
|
+
magic_link_req[
|
124
|
+
"magic_link_path"
|
125
|
+
] = magic_link_path unless magic_link_path.empty?
|
126
|
+
magic_link_req["redirect_url"] = redirect_url unless redirect_url.empty?
|
127
|
+
magic_link_req["ttl"] = ttl unless ttl == 0
|
127
128
|
|
128
129
|
begin
|
129
130
|
response =
|
130
131
|
@connection.post("/v1/apps/#{@app_id}/magic-links", magic_link_req)
|
131
|
-
magic_link = response.body[
|
132
|
+
magic_link = response.body["magic_link"]
|
132
133
|
return(
|
133
134
|
Passage::MagicLink.new(
|
134
|
-
id: magic_link[
|
135
|
-
secret: magic_link[
|
136
|
-
activated: magic_link[
|
137
|
-
user_id: magic_link[
|
138
|
-
app_id: magic_link[
|
139
|
-
identifier: magic_link[
|
140
|
-
type: magic_link[
|
141
|
-
redirect_url: magic_link[
|
142
|
-
ttl: magic_link[
|
143
|
-
url: magic_link[
|
135
|
+
id: magic_link["id"],
|
136
|
+
secret: magic_link["secret"],
|
137
|
+
activated: magic_link["activated"],
|
138
|
+
user_id: magic_link["user_id"],
|
139
|
+
app_id: magic_link["app_id"],
|
140
|
+
identifier: magic_link["identifier"],
|
141
|
+
type: magic_link["type"],
|
142
|
+
redirect_url: magic_link["redirect_url"],
|
143
|
+
ttl: magic_link["ttl"],
|
144
|
+
url: magic_link["url"]
|
144
145
|
)
|
145
146
|
)
|
146
147
|
rescue Faraday::Error => e
|
147
148
|
raise PassageError,
|
148
|
-
"failed to create Passage Magic Link. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
149
|
+
"failed to create Passage Magic Link. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
149
150
|
end
|
150
151
|
end
|
151
152
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative "client"
|
2
2
|
|
3
3
|
module Passage
|
4
4
|
class UserAPI
|
@@ -10,26 +10,26 @@ module Passage
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def get(user_id:)
|
13
|
-
raise PassageError,
|
13
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
14
14
|
begin
|
15
15
|
response = @connection.get("/v1/apps/#{@app_id}/users/#{user_id}")
|
16
|
-
user = response.body[
|
16
|
+
user = response.body["user"]
|
17
17
|
user.transform_keys(&:to_sym)
|
18
18
|
return(
|
19
19
|
Passage::User.new(
|
20
|
-
id: user[
|
21
|
-
status: user[
|
22
|
-
email: user[
|
23
|
-
phone: user[
|
24
|
-
email_verified: user[
|
25
|
-
created_at: user[
|
26
|
-
updated_at: user[
|
27
|
-
last_login_at: user[
|
28
|
-
login_count: user[
|
29
|
-
webauthn: user[
|
30
|
-
webauthn_devices: user[
|
31
|
-
recent_events: user[
|
32
|
-
user_metadata: user[
|
20
|
+
id: user["id"],
|
21
|
+
status: user["status"],
|
22
|
+
email: user["email"],
|
23
|
+
phone: user["phone"],
|
24
|
+
email_verified: user["email_verified"],
|
25
|
+
created_at: user["created_at"],
|
26
|
+
updated_at: user["updated_at"],
|
27
|
+
last_login_at: user["last_login_at"],
|
28
|
+
login_count: user["login_count"],
|
29
|
+
webauthn: user["webauthn"],
|
30
|
+
webauthn_devices: user["webauthn_devices"],
|
31
|
+
recent_events: user["recent_events"],
|
32
|
+
user_metadata: user["user_metadata"]
|
33
33
|
)
|
34
34
|
)
|
35
35
|
rescue Faraday::Error => e
|
@@ -38,32 +38,32 @@ module Passage
|
|
38
38
|
"passage User with ID \"#{user_id}\" does not exist"
|
39
39
|
else
|
40
40
|
raise PassageError,
|
41
|
-
"failed to get Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
41
|
+
"failed to get Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
def activate(user_id:)
|
47
|
-
raise PassageError,
|
47
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
48
48
|
begin
|
49
49
|
response =
|
50
50
|
@connection.patch("/v1/apps/#{@app_id}/users/#{user_id}/activate")
|
51
|
-
user = response.body[
|
51
|
+
user = response.body["user"]
|
52
52
|
return(
|
53
53
|
Passage::User.new(
|
54
|
-
id: user[
|
55
|
-
status: user[
|
56
|
-
email: user[
|
57
|
-
phone: user[
|
58
|
-
email_verified: user[
|
59
|
-
created_at: user[
|
60
|
-
updated_at: user[
|
61
|
-
last_login_at: user[
|
62
|
-
login_count: user[
|
63
|
-
webauthn: user[
|
64
|
-
webauthn_devices: user[
|
65
|
-
recent_events: user[
|
66
|
-
user_metadata: user[
|
54
|
+
id: user["id"],
|
55
|
+
status: user["status"],
|
56
|
+
email: user["email"],
|
57
|
+
phone: user["phone"],
|
58
|
+
email_verified: user["email_verified"],
|
59
|
+
created_at: user["created_at"],
|
60
|
+
updated_at: user["updated_at"],
|
61
|
+
last_login_at: user["last_login_at"],
|
62
|
+
login_count: user["login_count"],
|
63
|
+
webauthn: user["webauthn"],
|
64
|
+
webauthn_devices: user["webauthn_devices"],
|
65
|
+
recent_events: user["recent_events"],
|
66
|
+
user_metadata: user["user_metadata"]
|
67
67
|
)
|
68
68
|
)
|
69
69
|
rescue Faraday::Error => e
|
@@ -72,32 +72,32 @@ module Passage
|
|
72
72
|
"passage User with ID \"#{user_id}\" does not exist"
|
73
73
|
else
|
74
74
|
raise PassageError,
|
75
|
-
"failed to activate Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
75
|
+
"failed to activate Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
80
|
def deactivate(user_id:)
|
81
|
-
raise PassageError,
|
81
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
82
82
|
begin
|
83
83
|
response =
|
84
84
|
@connection.patch("/v1/apps/#{@app_id}/users/#{user_id}/deactivate")
|
85
|
-
user = response.body[
|
85
|
+
user = response.body["user"]
|
86
86
|
return(
|
87
87
|
Passage::User.new(
|
88
|
-
id: user[
|
89
|
-
status: user[
|
90
|
-
email: user[
|
91
|
-
phone: user[
|
92
|
-
email_verified: user[
|
93
|
-
created_at: user[
|
94
|
-
updated_at: user[
|
95
|
-
last_login_at: user[
|
96
|
-
login_count: user[
|
97
|
-
webauthn: user[
|
98
|
-
webauthn_devices: user[
|
99
|
-
recent_events: user[
|
100
|
-
user_metadata: user[
|
88
|
+
id: user["id"],
|
89
|
+
status: user["status"],
|
90
|
+
email: user["email"],
|
91
|
+
phone: user["phone"],
|
92
|
+
email_verified: user["email_verified"],
|
93
|
+
created_at: user["created_at"],
|
94
|
+
updated_at: user["updated_at"],
|
95
|
+
last_login_at: user["last_login_at"],
|
96
|
+
login_count: user["login_count"],
|
97
|
+
webauthn: user["webauthn"],
|
98
|
+
webauthn_devices: user["webauthn_devices"],
|
99
|
+
recent_events: user["recent_events"],
|
100
|
+
user_metadata: user["user_metadata"]
|
101
101
|
)
|
102
102
|
)
|
103
103
|
rescue Faraday::Error => e
|
@@ -106,36 +106,36 @@ module Passage
|
|
106
106
|
"passage User with ID \"#{user_id}\" does not exist"
|
107
107
|
else
|
108
108
|
raise PassageError,
|
109
|
-
"failed to deactivate Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
109
|
+
"failed to deactivate Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
110
110
|
end
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
def update(user_id:, email:
|
115
|
-
raise PassageError,
|
114
|
+
def update(user_id:, email: "", phone: "", user_metadata: {})
|
115
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
116
116
|
updates = {}
|
117
|
-
updates[
|
118
|
-
updates[
|
119
|
-
updates[
|
117
|
+
updates["email"] = email unless email.empty?
|
118
|
+
updates["phone"] = phone unless phone.empty?
|
119
|
+
updates["user_metadata"] = user_metadata unless user_metadata.empty?
|
120
120
|
begin
|
121
121
|
response =
|
122
122
|
@connection.patch("/v1/apps/#{@app_id}/users/#{user_id}", updates)
|
123
|
-
user = response.body[
|
123
|
+
user = response.body["user"]
|
124
124
|
return(
|
125
125
|
Passage::User.new(
|
126
|
-
id: user[
|
127
|
-
status: user[
|
128
|
-
email: user[
|
129
|
-
phone: user[
|
130
|
-
email_verified: user[
|
131
|
-
created_at: user[
|
132
|
-
updated_at: user[
|
133
|
-
last_login_at: user[
|
134
|
-
login_count: user[
|
135
|
-
webauthn: user[
|
136
|
-
webauthn_devices: user[
|
137
|
-
recent_events: user[
|
138
|
-
user_metadata: user[
|
126
|
+
id: user["id"],
|
127
|
+
status: user["status"],
|
128
|
+
email: user["email"],
|
129
|
+
phone: user["phone"],
|
130
|
+
email_verified: user["email_verified"],
|
131
|
+
created_at: user["created_at"],
|
132
|
+
updated_at: user["updated_at"],
|
133
|
+
last_login_at: user["last_login_at"],
|
134
|
+
login_count: user["login_count"],
|
135
|
+
webauthn: user["webauthn"],
|
136
|
+
webauthn_devices: user["webauthn_devices"],
|
137
|
+
recent_events: user["recent_events"],
|
138
|
+
user_metadata: user["user_metadata"]
|
139
139
|
)
|
140
140
|
)
|
141
141
|
rescue Faraday::Error => e
|
@@ -144,44 +144,44 @@ module Passage
|
|
144
144
|
"passage User with ID \"#{user_id}\" does not exist"
|
145
145
|
else
|
146
146
|
raise PassageError,
|
147
|
-
"failed to update Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
147
|
+
"failed to update Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
148
148
|
end
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
-
def create(email:
|
152
|
+
def create(email: "", phone: "", user_metadata: {})
|
153
153
|
create = {}
|
154
|
-
create[
|
155
|
-
create[
|
156
|
-
create[
|
154
|
+
create["email"] = email unless email.empty?
|
155
|
+
create["phone"] = phone unless phone.empty?
|
156
|
+
create["user_metadata"] = user_metadata unless user_metadata.empty?
|
157
157
|
begin
|
158
158
|
response = @connection.post("/v1/apps/#{@app_id}/users", create)
|
159
|
-
user = response.body[
|
159
|
+
user = response.body["user"]
|
160
160
|
return(
|
161
161
|
Passage::User.new(
|
162
|
-
id: user[
|
163
|
-
status: user[
|
164
|
-
email: user[
|
165
|
-
phone: user[
|
166
|
-
email_verified: user[
|
167
|
-
created_at: user[
|
168
|
-
updated_at: user[
|
169
|
-
last_login_at: user[
|
170
|
-
login_count: user[
|
171
|
-
webauthn: user[
|
172
|
-
webauthn_devices: user[
|
173
|
-
recent_events: user[
|
174
|
-
user_metadata: user[
|
162
|
+
id: user["id"],
|
163
|
+
status: user["status"],
|
164
|
+
email: user["email"],
|
165
|
+
phone: user["phone"],
|
166
|
+
email_verified: user["email_verified"],
|
167
|
+
created_at: user["created_at"],
|
168
|
+
updated_at: user["updated_at"],
|
169
|
+
last_login_at: user["last_login_at"],
|
170
|
+
login_count: user["login_count"],
|
171
|
+
webauthn: user["webauthn"],
|
172
|
+
webauthn_devices: user["webauthn_devices"],
|
173
|
+
recent_events: user["recent_events"],
|
174
|
+
user_metadata: user["user_metadata"]
|
175
175
|
)
|
176
176
|
)
|
177
177
|
rescue Faraday::Error => e
|
178
178
|
raise PassageError,
|
179
|
-
"failed to create Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
179
|
+
"failed to create Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
180
180
|
end
|
181
181
|
end
|
182
182
|
|
183
183
|
def delete(user_id:)
|
184
|
-
raise PassageError,
|
184
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
185
185
|
begin
|
186
186
|
response = @connection.delete("/v1/apps/#{@app_id}/users/#{user_id}")
|
187
187
|
return true
|
@@ -191,15 +191,15 @@ module Passage
|
|
191
191
|
"passage User with ID \"#{user_id}\" does not exist"
|
192
192
|
else
|
193
193
|
raise PassageError,
|
194
|
-
"failed to delete Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
194
|
+
"failed to delete Passage User. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
195
195
|
end
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
199
|
def delete_device(user_id:, device_id:)
|
200
|
-
raise PassageError,
|
200
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
201
201
|
if device_id.to_s.empty?
|
202
|
-
raise PassageError,
|
202
|
+
raise PassageError, "must supply a valid device_id"
|
203
203
|
end
|
204
204
|
begin
|
205
205
|
response =
|
@@ -209,32 +209,32 @@ module Passage
|
|
209
209
|
return true
|
210
210
|
rescue Faraday::Error => e
|
211
211
|
raise PassageError,
|
212
|
-
"failed to delete Passage User Device. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
212
|
+
"failed to delete Passage User Device. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
216
216
|
def list_devices(user_id:)
|
217
|
-
raise PassageError,
|
217
|
+
raise PassageError, "must supply a valid user_id" if user_id.to_s.empty?
|
218
218
|
begin
|
219
219
|
response =
|
220
220
|
@connection.get("/v1/apps/#{@app_id}/users/#{user_id}/devices")
|
221
|
-
devicesResp = response.body[
|
221
|
+
devicesResp = response.body["devices"]
|
222
222
|
devices = Array.new
|
223
223
|
devicesResp.each do |device|
|
224
224
|
devices.append(
|
225
225
|
Passage::Device.new(
|
226
|
-
id: device[
|
227
|
-
cred_id: device[
|
228
|
-
friendly_name: device[
|
229
|
-
usage_count: device[
|
230
|
-
last_used: device[
|
226
|
+
id: device["id"],
|
227
|
+
cred_id: device["cred_id"],
|
228
|
+
friendly_name: device["friendly_name"],
|
229
|
+
usage_count: device["usage_count"],
|
230
|
+
last_used: device["last_used"]
|
231
231
|
)
|
232
232
|
)
|
233
233
|
end
|
234
234
|
return devices
|
235
235
|
rescue Faraday::Error => e
|
236
236
|
raise PassageError,
|
237
|
-
"failed to delete Passage User Device. Http Status: #{e.response[:status]}. Response: #{e.response[:body][
|
237
|
+
"failed to delete Passage User Device. Http Status: #{e.response[:status]}. Response: #{e.response[:body]["error"]}"
|
238
238
|
end
|
239
239
|
end
|
240
240
|
end
|
data/lib/passageidentity.rb
CHANGED
data/passageidentity.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'passageidentity'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.5'
|
4
4
|
s.summary = 'Passage SDK for biometric authentication'
|
5
5
|
s.description =
|
6
6
|
'Enables verification of server-side authentication and user management for applications using Passage'
|
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_dependency 'faraday', '>= 0.17.0', '< 2.0'
|
28
28
|
s.add_dependency 'jwt', '>= 2.3.0'
|
29
29
|
s.add_dependency 'openssl', '>= 3.0.0'
|
30
|
+
s.add_dependency 'dotenv', '>= 2.7.6'
|
30
31
|
end
|
data/tests/all.rb
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
Dir[File.dirname(File.absolute_path(__FILE__)) +
|
2
|
-
|
1
|
+
Dir[File.dirname(File.absolute_path(__FILE__)) + "/**/*_test.rb"].each do |file|
|
2
|
+
require file
|
3
|
+
end
|
data/tests/auth_test.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
-
require_relative
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require_relative "../lib/passageidentity/client"
|
2
|
+
require "dotenv"
|
3
|
+
require "faraday"
|
4
|
+
require "test/unit"
|
5
5
|
|
6
|
+
Dotenv.load(".env")
|
6
7
|
class TestUserAPI < Test::Unit::TestCase
|
7
8
|
PassageClient =
|
8
|
-
Passage::Client.new(app_id: ENV[
|
9
|
+
Passage::Client.new(app_id: ENV["APP_ID"], api_key: ENV["API_KEY"])
|
9
10
|
|
10
11
|
def test_authenticate_token
|
11
|
-
user_id = PassageClient.auth.authenticate_token(ENV[
|
12
|
-
assert_equal ENV[
|
12
|
+
user_id = PassageClient.auth.authenticate_token(ENV["PSG_JWT"])
|
13
|
+
assert_equal ENV["TEST_USER_ID"], user_id
|
13
14
|
end
|
14
15
|
end
|
data/tests/magic_link_test.rb
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
-
require_relative
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require_relative "../lib/passageidentity/client"
|
2
|
+
require "dotenv"
|
3
|
+
require "faraday"
|
4
|
+
require "test/unit"
|
5
5
|
|
6
|
+
Dotenv.load(".env")
|
6
7
|
class TestUserAPI < Test::Unit::TestCase
|
7
8
|
PassageClient =
|
8
|
-
Passage::Client.new(app_id: ENV[
|
9
|
+
Passage::Client.new(app_id: ENV["APP_ID"], api_key: ENV["API_KEY"])
|
9
10
|
|
10
11
|
def test_create_magi_link()
|
11
12
|
magic_link =
|
12
13
|
PassageClient.create_magic_link(
|
13
|
-
email:
|
14
|
+
email: "chris@passage.id",
|
14
15
|
channel: Passage::EMAIL_CHANNEL,
|
15
16
|
ttl: 12
|
16
17
|
)
|
17
18
|
assert_equal 12, magic_link.ttl
|
18
|
-
assert_equal
|
19
|
+
assert_equal "chris@passage.id", magic_link.identifier
|
19
20
|
end
|
20
21
|
end
|
data/tests/user_api_test.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
-
require_relative
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require_relative "../lib/passageidentity/client"
|
2
|
+
require "dotenv"
|
3
|
+
require "faraday"
|
4
|
+
require "test/unit"
|
5
5
|
|
6
|
+
Dotenv.load(".env")
|
6
7
|
class TestUserAPI < Test::Unit::TestCase
|
7
8
|
PassageClient =
|
8
|
-
Passage::Client.new(app_id: ENV[
|
9
|
+
Passage::Client.new(app_id: ENV["APP_ID"], api_key: ENV["API_KEY"])
|
9
10
|
|
10
11
|
def setup()
|
11
12
|
$global_test_user =
|
12
13
|
PassageClient.user.create(
|
13
|
-
email:
|
14
|
+
email: "chris+test-ruby@passage.id",
|
14
15
|
user_metadata: {
|
15
|
-
|
16
|
+
example1: "cool"
|
16
17
|
}
|
17
18
|
)
|
18
19
|
end
|
@@ -20,13 +21,13 @@ class TestUserAPI < Test::Unit::TestCase
|
|
20
21
|
def test_create_delete_user()
|
21
22
|
user =
|
22
23
|
PassageClient.user.create(
|
23
|
-
email:
|
24
|
+
email: "chris+test-create-delete@passage.id",
|
24
25
|
user_metadata: {
|
25
|
-
|
26
|
+
example1: "cool"
|
26
27
|
}
|
27
28
|
)
|
28
|
-
assert_equal
|
29
|
-
assert_equal
|
29
|
+
assert_equal "chris+test-create-delete@passage.id", user.email
|
30
|
+
assert_equal "cool", user.user_metadata["example1"]
|
30
31
|
deleted = PassageClient.user.delete(user_id: user.id)
|
31
32
|
assert_equal true, deleted
|
32
33
|
end
|
@@ -39,28 +40,28 @@ class TestUserAPI < Test::Unit::TestCase
|
|
39
40
|
def test_deactivate_user()
|
40
41
|
user = PassageClient.user.deactivate(user_id: $global_test_user.id)
|
41
42
|
assert_equal $global_test_user.id, user.id
|
42
|
-
assert_equal
|
43
|
+
assert_equal "inactive", user.status
|
43
44
|
end
|
44
45
|
|
45
46
|
def test_activate_user()
|
46
47
|
user = PassageClient.user.activate(user_id: $global_test_user.id)
|
47
48
|
assert_equal $global_test_user.id, user.id
|
48
|
-
assert_equal
|
49
|
+
assert_equal "active", user.status
|
49
50
|
end
|
50
51
|
|
51
52
|
def test_update_user()
|
52
|
-
new_email =
|
53
|
+
new_email = "chris+update_test-ruby@passage.id"
|
53
54
|
user =
|
54
55
|
PassageClient.user.update(
|
55
56
|
user_id: $global_test_user.id,
|
56
57
|
email: new_email,
|
57
58
|
user_metadata: {
|
58
|
-
|
59
|
+
example1: "lame"
|
59
60
|
}
|
60
61
|
)
|
61
62
|
assert_equal $global_test_user.id, user.id
|
62
63
|
assert_equal new_email, user.email
|
63
|
-
assert_equal
|
64
|
+
assert_equal "lame", user.user_metadata["example1"]
|
64
65
|
end
|
65
66
|
|
66
67
|
def test_list_devices()
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passageidentity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Passage Identity
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-05-
|
11
|
+
date: 2022-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 3.0.0
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: dotenv
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 2.7.6
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 2.7.6
|
61
75
|
description: Enables verification of server-side authentication and user management
|
62
76
|
for applications using Passage
|
63
77
|
email: support@passage.id
|
@@ -65,6 +79,8 @@ executables: []
|
|
65
79
|
extensions: []
|
66
80
|
extra_rdoc_files: []
|
67
81
|
files:
|
82
|
+
- ".github/workflows/deploy.yml"
|
83
|
+
- ".github/workflows/on_pr.yml"
|
68
84
|
- ".gitignore"
|
69
85
|
- CONTRIBUTING.md
|
70
86
|
- LICENSE
|
@@ -74,7 +90,6 @@ files:
|
|
74
90
|
- lib/passageidentity/client.rb
|
75
91
|
- lib/passageidentity/error.rb
|
76
92
|
- lib/passageidentity/user_api.rb
|
77
|
-
- passage-ruby
|
78
93
|
- passageidentity.gemspec
|
79
94
|
- tests/all.rb
|
80
95
|
- tests/auth_test.rb
|
@@ -85,7 +100,7 @@ licenses:
|
|
85
100
|
- MIT
|
86
101
|
metadata:
|
87
102
|
source_code_uri: https://github.com/passage-identity/passage-ruby
|
88
|
-
post_install_message:
|
103
|
+
post_install_message:
|
89
104
|
rdoc_options: []
|
90
105
|
require_paths:
|
91
106
|
- lib
|
@@ -100,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
115
|
- !ruby/object:Gem::Version
|
101
116
|
version: '0'
|
102
117
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
104
|
-
signing_key:
|
118
|
+
rubygems_version: 3.2.33
|
119
|
+
signing_key:
|
105
120
|
specification_version: 4
|
106
121
|
summary: Passage SDK for biometric authentication
|
107
122
|
test_files: []
|
data/passage-ruby
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
passage-ruby
|