hanko-ruby 0.1.1
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 +7 -0
- data/lib/hanko/api/admin/audit_logs.rb +19 -0
- data/lib/hanko/api/admin/emails.rb +30 -0
- data/lib/hanko/api/admin/metadata.rb +37 -0
- data/lib/hanko/api/admin/passwords.rb +54 -0
- data/lib/hanko/api/admin/sessions.rb +20 -0
- data/lib/hanko/api/admin/users.rb +77 -0
- data/lib/hanko/api/admin/webauthn_credentials.rb +20 -0
- data/lib/hanko/api/admin/webhooks.rb +19 -0
- data/lib/hanko/api/admin.rb +52 -0
- data/lib/hanko/api/base_resource.rb +79 -0
- data/lib/hanko/api/public/flow.rb +50 -0
- data/lib/hanko/api/public/sessions.rb +35 -0
- data/lib/hanko/api/public/well_known.rb +34 -0
- data/lib/hanko/api/public.rb +45 -0
- data/lib/hanko/client.rb +76 -0
- data/lib/hanko/configuration.rb +64 -0
- data/lib/hanko/connection.rb +92 -0
- data/lib/hanko/errors.rb +60 -0
- data/lib/hanko/flow_response.rb +56 -0
- data/lib/hanko/middleware/raise_error.rb +58 -0
- data/lib/hanko/resource.rb +77 -0
- data/lib/hanko/test_helper.rb +95 -0
- data/lib/hanko/version.rb +5 -0
- data/lib/hanko/webhook_verifier.rb +43 -0
- data/lib/hanko.rb +62 -0
- metadata +112 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 73c45486ef99cb5a9cabbdfaa4fa4900eb336f5cd96f9699c0f8e5cbff32d7f1
|
|
4
|
+
data.tar.gz: 46eacc55fd29afc575bd7bb4c829ab878c84c4d73d9e811087b124bcbbede268
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d929d9d4647418c5e4ff0aa947cedac5dced6b50cb26bb22c4746c0a09489cee4071a18ee748becfaea22d991a852ed9ee3a3686904968910ad1f89e1fca6f67
|
|
7
|
+
data.tar.gz: ef0ff26d1c4febd94375452e482e79b2758681bd1db83780f8ec46da11bb5a91e3d701f7d4be88450ffd8a5b0c241293ec539ceccf239f11bd27a2bb19173c3a
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for querying audit logs.
|
|
7
|
+
# Inherits list, get, create, update, delete from {BaseResource}.
|
|
8
|
+
class AuditLogs < BaseResource
|
|
9
|
+
# Initialize the audit logs resource.
|
|
10
|
+
#
|
|
11
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
12
|
+
# @return [AuditLogs] a new AuditLogs instance
|
|
13
|
+
def initialize(connection)
|
|
14
|
+
super(connection, "/audit_logs")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing a user's email addresses.
|
|
7
|
+
# Inherits list, get, create, update, delete from {BaseResource}.
|
|
8
|
+
class Emails < BaseResource
|
|
9
|
+
# Initialize the emails resource scoped to a user.
|
|
10
|
+
#
|
|
11
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
12
|
+
# @param user_base_path [String] the base path for the parent user (e.g. "/users/:id")
|
|
13
|
+
# @return [Emails] a new Emails instance
|
|
14
|
+
def initialize(connection, user_base_path)
|
|
15
|
+
super(connection, "#{user_base_path}/emails")
|
|
16
|
+
@connection = connection
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Set an email address as the primary email for the user.
|
|
20
|
+
#
|
|
21
|
+
# @param email_id [String] the unique identifier of the email to make primary
|
|
22
|
+
# @return [Resource] the updated email resource
|
|
23
|
+
def set_primary(email_id)
|
|
24
|
+
response = @connection.post("#{@base_path}/#{email_id}/set_primary")
|
|
25
|
+
parse_resource(response.body)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing a user's metadata.
|
|
7
|
+
class Metadata
|
|
8
|
+
# Initialize the metadata resource scoped to a user.
|
|
9
|
+
#
|
|
10
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
11
|
+
# @param user_base_path [String] the base path for the parent user (e.g. "/users/:id")
|
|
12
|
+
# @return [Metadata] a new Metadata instance
|
|
13
|
+
def initialize(connection, user_base_path)
|
|
14
|
+
@connection = connection
|
|
15
|
+
@base_path = "#{user_base_path}/metadata"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Fetch the user's metadata.
|
|
19
|
+
#
|
|
20
|
+
# @return [Resource] the metadata resource
|
|
21
|
+
def get
|
|
22
|
+
response = @connection.get(@base_path)
|
|
23
|
+
Resource.new(JSON.parse(response.body))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Update the user's metadata via PATCH.
|
|
27
|
+
#
|
|
28
|
+
# @param params [Hash] the metadata attributes to update
|
|
29
|
+
# @return [Resource] the updated metadata resource
|
|
30
|
+
def update(**params)
|
|
31
|
+
response = @connection.patch(@base_path, params)
|
|
32
|
+
Resource.new(JSON.parse(response.body))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing a user's password.
|
|
7
|
+
class Passwords
|
|
8
|
+
# Initialize the passwords resource scoped to a user.
|
|
9
|
+
#
|
|
10
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
11
|
+
# @param user_base_path [String] the base path for the parent user (e.g. "/users/:id")
|
|
12
|
+
# @return [Passwords] a new Passwords instance
|
|
13
|
+
def initialize(connection, user_base_path)
|
|
14
|
+
@connection = connection
|
|
15
|
+
@base_path = "#{user_base_path}/password"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Create a password for the user.
|
|
19
|
+
#
|
|
20
|
+
# @param params [Hash] the password attributes
|
|
21
|
+
# @return [Resource] the created password resource
|
|
22
|
+
def create(**params)
|
|
23
|
+
response = @connection.post(@base_path, params)
|
|
24
|
+
Resource.new(JSON.parse(response.body))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Fetch the user's password resource.
|
|
28
|
+
#
|
|
29
|
+
# @return [Resource] the password resource
|
|
30
|
+
def get
|
|
31
|
+
response = @connection.get(@base_path)
|
|
32
|
+
Resource.new(JSON.parse(response.body))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Update the user's password.
|
|
36
|
+
#
|
|
37
|
+
# @param params [Hash] the password attributes to update
|
|
38
|
+
# @return [Resource] the updated password resource
|
|
39
|
+
def update(**params)
|
|
40
|
+
response = @connection.put(@base_path, params)
|
|
41
|
+
Resource.new(JSON.parse(response.body))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Delete the user's password.
|
|
45
|
+
#
|
|
46
|
+
# @return [Boolean] true if deletion was successful
|
|
47
|
+
def delete
|
|
48
|
+
@connection.delete(@base_path)
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing a user's sessions.
|
|
7
|
+
# Inherits list, get, create, update, delete from {BaseResource}.
|
|
8
|
+
class Sessions < BaseResource
|
|
9
|
+
# Initialize the sessions resource scoped to a user.
|
|
10
|
+
#
|
|
11
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
12
|
+
# @param user_base_path [String] the base path for the parent user (e.g. "/users/:id")
|
|
13
|
+
# @return [Sessions] a new Sessions instance
|
|
14
|
+
def initialize(connection, user_base_path)
|
|
15
|
+
super(connection, "#{user_base_path}/sessions")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing users.
|
|
7
|
+
# Inherits list, get, create, update, delete from {BaseResource}.
|
|
8
|
+
class Users < BaseResource
|
|
9
|
+
# Initialize the users resource.
|
|
10
|
+
#
|
|
11
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
12
|
+
# @return [Users] a new Users instance
|
|
13
|
+
def initialize(connection)
|
|
14
|
+
super(connection, "/users")
|
|
15
|
+
@connection = connection
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Return a user-scoped context for accessing sub-resources.
|
|
19
|
+
#
|
|
20
|
+
# @param user_id [String] the unique identifier of the user
|
|
21
|
+
# @return [UserContext] a context scoped to the given user
|
|
22
|
+
def call(user_id)
|
|
23
|
+
UserContext.new(@connection, user_id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Provides access to sub-resources scoped to a specific user.
|
|
27
|
+
class UserContext
|
|
28
|
+
# Initialize a user-scoped context.
|
|
29
|
+
#
|
|
30
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
31
|
+
# @param user_id [String] the unique identifier of the user
|
|
32
|
+
# @return [UserContext] a new UserContext instance
|
|
33
|
+
def initialize(connection, user_id)
|
|
34
|
+
@connection = connection
|
|
35
|
+
@user_id = user_id
|
|
36
|
+
@base_path = "/users/#{user_id}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Access the emails sub-resource for this user.
|
|
40
|
+
#
|
|
41
|
+
# @return [Emails] the emails resource scoped to this user
|
|
42
|
+
def emails
|
|
43
|
+
Emails.new(@connection, @base_path)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Access the passwords sub-resource for this user.
|
|
47
|
+
#
|
|
48
|
+
# @return [Passwords] the passwords resource scoped to this user
|
|
49
|
+
def passwords
|
|
50
|
+
Passwords.new(@connection, @base_path)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Access the sessions sub-resource for this user.
|
|
54
|
+
#
|
|
55
|
+
# @return [Sessions] the sessions resource scoped to this user
|
|
56
|
+
def sessions
|
|
57
|
+
Sessions.new(@connection, @base_path)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Access the WebAuthn credentials sub-resource for this user.
|
|
61
|
+
#
|
|
62
|
+
# @return [WebauthnCredentials] the WebAuthn credentials resource scoped to this user
|
|
63
|
+
def webauthn_credentials
|
|
64
|
+
WebauthnCredentials.new(@connection, @base_path)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Access the metadata sub-resource for this user.
|
|
68
|
+
#
|
|
69
|
+
# @return [Metadata] the metadata resource scoped to this user
|
|
70
|
+
def metadata
|
|
71
|
+
Metadata.new(@connection, @base_path)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing a user's WebAuthn credentials.
|
|
7
|
+
# Inherits list, get, create, update, delete from {BaseResource}.
|
|
8
|
+
class WebauthnCredentials < BaseResource
|
|
9
|
+
# Initialize the WebAuthn credentials resource scoped to a user.
|
|
10
|
+
#
|
|
11
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
12
|
+
# @param user_base_path [String] the base path for the parent user (e.g. "/users/:id")
|
|
13
|
+
# @return [WebauthnCredentials] a new WebauthnCredentials instance
|
|
14
|
+
def initialize(connection, user_base_path)
|
|
15
|
+
super(connection, "#{user_base_path}/webauthn_credentials")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Admin
|
|
6
|
+
# Admin resource for managing webhooks.
|
|
7
|
+
# Inherits list, get, create, update, delete from {BaseResource}.
|
|
8
|
+
class Webhooks < BaseResource
|
|
9
|
+
# Initialize the webhooks resource.
|
|
10
|
+
#
|
|
11
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
12
|
+
# @return [Webhooks] a new Webhooks instance
|
|
13
|
+
def initialize(connection)
|
|
14
|
+
super(connection, "/webhooks")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "admin/users"
|
|
4
|
+
require_relative "admin/emails"
|
|
5
|
+
require_relative "admin/passwords"
|
|
6
|
+
require_relative "admin/sessions"
|
|
7
|
+
require_relative "admin/webauthn_credentials"
|
|
8
|
+
require_relative "admin/metadata"
|
|
9
|
+
require_relative "admin/webhooks"
|
|
10
|
+
require_relative "admin/audit_logs"
|
|
11
|
+
|
|
12
|
+
module Hanko
|
|
13
|
+
module Api
|
|
14
|
+
# Namespace module for Hanko Admin API resource classes.
|
|
15
|
+
module Admin
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Entry point for the Hanko Admin API, providing access to admin sub-resources.
|
|
19
|
+
class AdminNamespace
|
|
20
|
+
# Initialize the admin namespace.
|
|
21
|
+
#
|
|
22
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
23
|
+
# @return [AdminNamespace] a new AdminNamespace instance
|
|
24
|
+
def initialize(connection)
|
|
25
|
+
@connection = connection
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Access the users resource, optionally scoped to a specific user.
|
|
29
|
+
#
|
|
30
|
+
# @param user_id [String, nil] optional user ID to scope to a single user context
|
|
31
|
+
# @return [Admin::Users, Admin::Users::UserContext] the users resource or a user-scoped context
|
|
32
|
+
def users(user_id = nil)
|
|
33
|
+
users_resource = Admin::Users.new(@connection)
|
|
34
|
+
user_id ? users_resource.call(user_id) : users_resource
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Access the webhooks resource.
|
|
38
|
+
#
|
|
39
|
+
# @return [Admin::Webhooks] the webhooks resource
|
|
40
|
+
def webhooks
|
|
41
|
+
Admin::Webhooks.new(@connection)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Access the audit logs resource.
|
|
45
|
+
#
|
|
46
|
+
# @return [Admin::AuditLogs] the audit logs resource
|
|
47
|
+
def audit_logs
|
|
48
|
+
Admin::AuditLogs.new(@connection)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Hanko
|
|
6
|
+
module Api
|
|
7
|
+
# Base class for RESTful API resources providing standard CRUD operations.
|
|
8
|
+
# Subclasses inherit {#list}, {#get}, {#create}, {#update}, and {#delete}.
|
|
9
|
+
class BaseResource
|
|
10
|
+
# Initialize a new resource endpoint.
|
|
11
|
+
#
|
|
12
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
13
|
+
# @param base_path [String] the base API path for this resource
|
|
14
|
+
# @return [BaseResource] a new BaseResource instance
|
|
15
|
+
def initialize(connection, base_path)
|
|
16
|
+
@connection = connection
|
|
17
|
+
@base_path = base_path
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# List all resources, optionally filtered by query parameters.
|
|
21
|
+
#
|
|
22
|
+
# @param params [Hash] optional query parameters for filtering
|
|
23
|
+
# @return [Array<Resource>] an array of Resource objects
|
|
24
|
+
def list(params = {})
|
|
25
|
+
response = @connection.get(@base_path, params)
|
|
26
|
+
parse_array(response.body)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Fetch a single resource by its ID.
|
|
30
|
+
#
|
|
31
|
+
# @param id [String] the unique identifier of the resource
|
|
32
|
+
# @return [Resource] the requested resource
|
|
33
|
+
def get(id)
|
|
34
|
+
response = @connection.get("#{@base_path}/#{id}")
|
|
35
|
+
parse_resource(response.body)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Create a new resource with the given attributes.
|
|
39
|
+
#
|
|
40
|
+
# @param params [Hash] the attributes for the new resource
|
|
41
|
+
# @return [Resource] the newly created resource
|
|
42
|
+
def create(**params)
|
|
43
|
+
response = @connection.post(@base_path, params)
|
|
44
|
+
parse_resource(response.body)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Update an existing resource by its ID.
|
|
48
|
+
#
|
|
49
|
+
# @param id [String] the unique identifier of the resource
|
|
50
|
+
# @param params [Hash] the attributes to update
|
|
51
|
+
# @return [Resource] the updated resource
|
|
52
|
+
def update(id, **params)
|
|
53
|
+
response = @connection.put("#{@base_path}/#{id}", params)
|
|
54
|
+
parse_resource(response.body)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Delete a resource by its ID.
|
|
58
|
+
#
|
|
59
|
+
# @param id [String] the unique identifier of the resource
|
|
60
|
+
# @return [Boolean] true if deletion was successful
|
|
61
|
+
def delete(id)
|
|
62
|
+
@connection.delete("#{@base_path}/#{id}")
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def parse_resource(body)
|
|
69
|
+
data = body.is_a?(String) ? JSON.parse(body) : body
|
|
70
|
+
Resource.new(data)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def parse_array(body)
|
|
74
|
+
data = body.is_a?(String) ? JSON.parse(body) : body
|
|
75
|
+
Resource.from_array(data)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Public
|
|
6
|
+
# Public resource for initiating authentication and profile flows.
|
|
7
|
+
class Flow
|
|
8
|
+
# Initialize the flow resource.
|
|
9
|
+
#
|
|
10
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
11
|
+
# @return [Flow] a new Flow instance
|
|
12
|
+
def initialize(connection)
|
|
13
|
+
@connection = connection
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Initiate a login flow.
|
|
17
|
+
#
|
|
18
|
+
# @param params [Hash] optional parameters for the login flow
|
|
19
|
+
# @return [FlowResponse] the login flow response
|
|
20
|
+
def login(**params)
|
|
21
|
+
post_flow("/login", params)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Initiate a registration flow.
|
|
25
|
+
#
|
|
26
|
+
# @param params [Hash] optional parameters for the registration flow
|
|
27
|
+
# @return [FlowResponse] the registration flow response
|
|
28
|
+
def registration(**params)
|
|
29
|
+
post_flow("/registration", params)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Initiate a profile management flow.
|
|
33
|
+
#
|
|
34
|
+
# @param params [Hash] optional parameters for the profile flow
|
|
35
|
+
# @return [FlowResponse] the profile flow response
|
|
36
|
+
def profile(**params)
|
|
37
|
+
post_flow("/profile", params)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def post_flow(path, params)
|
|
43
|
+
body = params.empty? ? {} : params
|
|
44
|
+
response = @connection.post(path, body)
|
|
45
|
+
FlowResponse.new(JSON.parse(response.body))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Public
|
|
6
|
+
# Public resource for validating Hanko sessions.
|
|
7
|
+
class Sessions
|
|
8
|
+
# Initialize the public sessions resource.
|
|
9
|
+
#
|
|
10
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
11
|
+
# @return [Sessions] a new Sessions instance
|
|
12
|
+
def initialize(connection)
|
|
13
|
+
@connection = connection
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Validate the current session using cookies/headers from the connection.
|
|
17
|
+
#
|
|
18
|
+
# @return [Resource] the validated session resource
|
|
19
|
+
def validate
|
|
20
|
+
response = @connection.get("/sessions/validate")
|
|
21
|
+
Resource.new(JSON.parse(response.body))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Validate a session by providing an explicit session token.
|
|
25
|
+
#
|
|
26
|
+
# @param session_token [String] the session token to validate
|
|
27
|
+
# @return [Resource] the validated session resource
|
|
28
|
+
def validate_token(session_token)
|
|
29
|
+
response = @connection.post("/sessions/validate", session_token: session_token)
|
|
30
|
+
Resource.new(JSON.parse(response.body))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
module Api
|
|
5
|
+
module Public
|
|
6
|
+
# Public resource for accessing .well-known discovery endpoints.
|
|
7
|
+
class WellKnown
|
|
8
|
+
# Initialize the well-known resource.
|
|
9
|
+
#
|
|
10
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
11
|
+
# @return [WellKnown] a new WellKnown instance
|
|
12
|
+
def initialize(connection)
|
|
13
|
+
@connection = connection
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Fetch the JSON Web Key Set (JWKS) for token verification.
|
|
17
|
+
#
|
|
18
|
+
# @return [Resource] the JWKS resource
|
|
19
|
+
def jwks
|
|
20
|
+
response = @connection.get("/.well-known/jwks.json")
|
|
21
|
+
Resource.new(JSON.parse(response.body))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Fetch the Hanko server configuration.
|
|
25
|
+
#
|
|
26
|
+
# @return [Resource] the configuration resource
|
|
27
|
+
def config
|
|
28
|
+
response = @connection.get("/.well-known/config")
|
|
29
|
+
Resource.new(JSON.parse(response.body))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "public/sessions"
|
|
4
|
+
require_relative "public/well_known"
|
|
5
|
+
require_relative "public/flow"
|
|
6
|
+
|
|
7
|
+
module Hanko
|
|
8
|
+
module Api
|
|
9
|
+
# Namespace module for Hanko Public API resource classes.
|
|
10
|
+
module Public
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Entry point for the Hanko Public API, providing access to public sub-resources.
|
|
14
|
+
class PublicNamespace
|
|
15
|
+
# Initialize the public namespace.
|
|
16
|
+
#
|
|
17
|
+
# @param connection [Hanko::Connection] the HTTP connection to use
|
|
18
|
+
# @return [PublicNamespace] a new PublicNamespace instance
|
|
19
|
+
def initialize(connection)
|
|
20
|
+
@connection = connection
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Access the sessions resource for session validation.
|
|
24
|
+
#
|
|
25
|
+
# @return [Public::Sessions] the sessions resource
|
|
26
|
+
def sessions
|
|
27
|
+
Public::Sessions.new(@connection)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Access the .well-known resource for JWKS and configuration discovery.
|
|
31
|
+
#
|
|
32
|
+
# @return [Public::WellKnown] the well-known resource
|
|
33
|
+
def well_known
|
|
34
|
+
Public::WellKnown.new(@connection)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Access the flow resource for login, registration, and profile flows.
|
|
38
|
+
#
|
|
39
|
+
# @return [Public::Flow] the flow resource
|
|
40
|
+
def flow
|
|
41
|
+
Public::Flow.new(@connection)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/hanko/client.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hanko
|
|
4
|
+
# Main entry point for interacting with the Hanko API.
|
|
5
|
+
#
|
|
6
|
+
# A client merges any per-instance options with the global {Configuration},
|
|
7
|
+
# then exposes admin and public API namespaces.
|
|
8
|
+
#
|
|
9
|
+
# @example Create a client with inline options
|
|
10
|
+
# client = Hanko::Client.new(api_url: "https://example.hanko.io", api_key: "key")
|
|
11
|
+
# client.admin.users.list
|
|
12
|
+
#
|
|
13
|
+
# @example Create a client using global configuration
|
|
14
|
+
# Hanko.configure { |c| c.api_url = "https://example.hanko.io" }
|
|
15
|
+
# client = Hanko::Client.new
|
|
16
|
+
class Client
|
|
17
|
+
# @return [Configuration] the resolved configuration for this client
|
|
18
|
+
attr_reader :config
|
|
19
|
+
|
|
20
|
+
# Creates a new Hanko API client.
|
|
21
|
+
#
|
|
22
|
+
# Options override values from the global {Hanko.configuration}.
|
|
23
|
+
#
|
|
24
|
+
# @param options [Hash] configuration overrides
|
|
25
|
+
# @option options [String] :api_url the Hanko API base URL
|
|
26
|
+
# @option options [String] :api_key the API key for admin endpoints
|
|
27
|
+
# @option options [Integer] :timeout request timeout in seconds
|
|
28
|
+
# @option options [Integer] :open_timeout connection open timeout in seconds
|
|
29
|
+
# @option options [Integer] :retry_count number of retries on failure
|
|
30
|
+
# @option options [Array] :adapter Faraday adapter (for testing)
|
|
31
|
+
# @raise [ConfigurationError] if api_url is not set
|
|
32
|
+
def initialize(**options)
|
|
33
|
+
@adapter = options.delete(:adapter)
|
|
34
|
+
@config = build_config(options)
|
|
35
|
+
validate_config!
|
|
36
|
+
@connection = Connection.new(@config, adapter: @adapter)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns the admin API namespace for managing users, emails, etc.
|
|
40
|
+
#
|
|
41
|
+
# @return [Api::AdminNamespace]
|
|
42
|
+
def admin
|
|
43
|
+
@admin ||= Api::AdminNamespace.new(@connection)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns the public API namespace for flows, well-known endpoints, etc.
|
|
47
|
+
#
|
|
48
|
+
# @return [Api::PublicNamespace]
|
|
49
|
+
def public
|
|
50
|
+
@public ||= Api::PublicNamespace.new(@connection)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns a human-readable representation with the API key redacted.
|
|
54
|
+
#
|
|
55
|
+
# @return [String]
|
|
56
|
+
def inspect
|
|
57
|
+
"#<#{self.class} api_url=#{config.api_url.inspect} api_key=[REDACTED]>"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def build_config(options)
|
|
63
|
+
base = Hanko.configuration
|
|
64
|
+
Configuration.new.tap do |c|
|
|
65
|
+
Configuration::ATTRIBUTES.each do |attr|
|
|
66
|
+
value = options.fetch(attr, base.send(attr))
|
|
67
|
+
c.send(:"#{attr}=", value)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def validate_config!
|
|
73
|
+
raise ConfigurationError, 'api_url is required' unless config.api_url
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|