clowk 0.1.0 → 0.3.3
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/README.md +2 -2
- data/clowk.gemspec +17 -16
- data/config/routes.rb +4 -4
- data/lib/clowk/authenticable.rb +85 -15
- data/lib/clowk/configuration.rb +43 -10
- data/lib/clowk/controllers/base_controller.rb +10 -10
- data/lib/clowk/controllers/callbacks_controller.rb +5 -4
- data/lib/clowk/current.rb +19 -1
- data/lib/clowk/engine.rb +1 -1
- data/lib/clowk/helpers/url_helpers.rb +7 -9
- data/lib/clowk/http/client.rb +9 -9
- data/lib/clowk/http/logger_middleware.rb +3 -2
- data/lib/clowk/http/response.rb +5 -5
- data/lib/clowk/http/retry_middleware.rb +2 -2
- data/lib/clowk/http/timeout_middleware.rb +1 -1
- data/lib/clowk/jwt_verifier.rb +4 -4
- data/lib/clowk/middleware/token_extractor.rb +3 -3
- data/lib/clowk/sdk/client.rb +5 -5
- data/lib/clowk/sdk/resource.rb +6 -6
- data/lib/clowk/sdk/session.rb +18 -1
- data/lib/clowk/sdk/session_config.rb +17 -0
- data/lib/clowk/sdk/subdomain.rb +1 -1
- data/lib/clowk/sdk/token.rb +14 -2
- data/lib/clowk/sdk/user.rb +1 -1
- data/lib/clowk/subdomain.rb +36 -25
- data/lib/clowk/version.rb +1 -1
- data/lib/clowk.rb +32 -30
- metadata +19 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b02c176f355917aa070a2b183a5844911e769b49ff7906cc40c13bbcd68cbf6
|
|
4
|
+
data.tar.gz: 7ba591ce54755e2ff3d6a586ef7942ae96442efa6ae93caff5c64e0ac313cbd1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f33e323f94c88fc064d12d0caa0cbc87bf9fad301ba0e29fc89d51ec0f40e81658e7dc67f485e437281705b0cdd10c6157b927500d0afd255f151d48485188ad
|
|
7
|
+
data.tar.gz: 9c6e02049ac043a85e293ad4ac8ec060d4f90e2b1231931cb593a6287a73b1400bdb6c4c01e18cf20fe090cf5be43336eeade52bb495c8d24074878b0a4c688f
|
data/README.md
CHANGED
|
@@ -86,7 +86,7 @@ Clowk.configure do |config|
|
|
|
86
86
|
config.after_sign_in_path = '/'
|
|
87
87
|
config.after_sign_out_path = '/'
|
|
88
88
|
|
|
89
|
-
config.api_base_url = 'https://api.clowk.dev/
|
|
89
|
+
config.api_base_url = 'https://api.clowk.dev/api/v1'
|
|
90
90
|
config.callback_path = '/clowk/oauth/callback'
|
|
91
91
|
config.mount_path = '/clowk'
|
|
92
92
|
|
|
@@ -362,4 +362,4 @@ Its job is to make the Rails side of Clowk integration predictable:
|
|
|
362
362
|
|
|
363
363
|
## License
|
|
364
364
|
|
|
365
|
-
|
|
365
|
+
AGPL-3.0. See `LICENSE`.
|
data/clowk.gemspec
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "lib/clowk/version"
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name =
|
|
6
|
+
spec.name = "clowk"
|
|
7
7
|
spec.version = Clowk::VERSION
|
|
8
|
-
spec.authors = [
|
|
9
|
-
spec.email = [
|
|
8
|
+
spec.authors = ["Clowk"]
|
|
9
|
+
spec.email = ["support@clowk.in"]
|
|
10
10
|
|
|
11
|
-
spec.summary =
|
|
12
|
-
spec.description =
|
|
13
|
-
spec.homepage =
|
|
14
|
-
spec.license =
|
|
15
|
-
spec.required_ruby_version =
|
|
11
|
+
spec.summary = "Rails SDK for Clowk authentication"
|
|
12
|
+
spec.description = "Clowk Authentication, JWT verification, and future API access"
|
|
13
|
+
spec.homepage = "https://clowk.in"
|
|
14
|
+
spec.license = "AGPL-3.0-only"
|
|
15
|
+
spec.required_ruby_version = ">= 3.3"
|
|
16
16
|
spec.metadata = {
|
|
17
|
-
|
|
17
|
+
"rubygems_mfa_required" => "true"
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
spec.files = Dir.chdir(__dir__) do
|
|
21
|
-
Dir[
|
|
21
|
+
Dir["README.md", "clowk.gemspec", "config/routes.rb", "lib/**/*.rb"]
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
spec.require_paths = [
|
|
24
|
+
spec.require_paths = ["lib"]
|
|
25
25
|
|
|
26
|
-
spec.add_dependency
|
|
27
|
-
spec.add_dependency
|
|
28
|
-
spec.add_dependency
|
|
26
|
+
spec.add_dependency "activesupport", ">= 7.0"
|
|
27
|
+
spec.add_dependency "jwt", ">= 2.7", "< 3.0"
|
|
28
|
+
spec.add_dependency "railties", ">= 7.0"
|
|
29
29
|
|
|
30
|
-
spec.add_development_dependency
|
|
30
|
+
spec.add_development_dependency "rspec", ">= 3.13", "< 4.0"
|
|
31
|
+
spec.add_development_dependency "standard", ">= 1.0"
|
|
31
32
|
end
|
data/config/routes.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
Clowk::Engine.routes.draw do
|
|
4
|
-
get
|
|
5
|
-
get
|
|
6
|
-
match
|
|
7
|
-
get
|
|
4
|
+
get "/sign_in", to: "sessions#new", as: :sign_in
|
|
5
|
+
get "/sign_up", to: "sessions#sign_up", as: :sign_up
|
|
6
|
+
match "/sign_out", to: "sessions#destroy", via: %i[get delete], as: :sign_out
|
|
7
|
+
get "/oauth/callback", to: "callbacks#show", as: :auth_callback
|
|
8
8
|
end
|
data/lib/clowk/authenticable.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "active_support/concern"
|
|
4
4
|
|
|
5
5
|
module Clowk
|
|
6
6
|
module Authenticable
|
|
@@ -12,17 +12,31 @@ module Clowk
|
|
|
12
12
|
authenticate_method = :"authenticate_#{scope}!"
|
|
13
13
|
signed_in_method = :"#{scope}_signed_in?"
|
|
14
14
|
|
|
15
|
+
enforce_session_method = :"#{scope}_enforce_session!"
|
|
16
|
+
|
|
15
17
|
base.class_eval do
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
unless current_method == :clowk_current_resource
|
|
19
|
+
define_method(current_method) do
|
|
20
|
+
clowk_current_resource
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
unless authenticate_method == :clowk_authenticate!
|
|
25
|
+
define_method(authenticate_method) do
|
|
26
|
+
clowk_authenticate!
|
|
27
|
+
end
|
|
18
28
|
end
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
unless signed_in_method == :clowk_signed_in?
|
|
31
|
+
define_method(signed_in_method) do
|
|
32
|
+
clowk_signed_in?
|
|
33
|
+
end
|
|
22
34
|
end
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
unless enforce_session_method == :clowk_enforce_session!
|
|
37
|
+
define_method(enforce_session_method) do
|
|
38
|
+
clowk_enforce_session!
|
|
39
|
+
end
|
|
26
40
|
end
|
|
27
41
|
|
|
28
42
|
helper_method current_method, authenticate_method, signed_in_method, :current_token if respond_to?(:helper_method)
|
|
@@ -41,21 +55,40 @@ module Clowk
|
|
|
41
55
|
end
|
|
42
56
|
|
|
43
57
|
def current_token
|
|
44
|
-
stored_session&.dig(
|
|
58
|
+
stored_session&.dig("token") || extracted_token
|
|
45
59
|
end
|
|
46
60
|
|
|
47
61
|
def clowk_signed_in?
|
|
48
62
|
clowk_current_resource.present?
|
|
49
63
|
end
|
|
50
64
|
|
|
65
|
+
def clowk_session_status
|
|
66
|
+
@clowk_session_status ||= resolve_session_status
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def clowk_session_active?
|
|
70
|
+
clowk_session_status&.dig(:status) == "active"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def clowk_enforce_session!
|
|
74
|
+
return if clowk_session_active?
|
|
75
|
+
|
|
76
|
+
session_info = clowk_session_status
|
|
77
|
+
callback = Clowk.config.on_session_expired
|
|
78
|
+
|
|
79
|
+
if callback.respond_to?(:call)
|
|
80
|
+
callback.call(self, session_info)
|
|
81
|
+
|
|
82
|
+
return
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
clowk_handle_expired_session(session_info)
|
|
86
|
+
end
|
|
87
|
+
|
|
51
88
|
def clowk_authenticate!
|
|
52
89
|
return clowk_current_resource if clowk_signed_in?
|
|
53
90
|
|
|
54
|
-
|
|
55
|
-
render json: { error: 'Unauthorized' }, status: :unauthorized
|
|
56
|
-
else
|
|
57
|
-
redirect_to clowk_sign_in_path(return_to: request.fullpath)
|
|
58
|
-
end
|
|
91
|
+
clowk_handle_unauthenticated
|
|
59
92
|
end
|
|
60
93
|
|
|
61
94
|
def clowk_sign_out!
|
|
@@ -67,6 +100,22 @@ module Clowk
|
|
|
67
100
|
|
|
68
101
|
private
|
|
69
102
|
|
|
103
|
+
def clowk_handle_unauthenticated
|
|
104
|
+
if request.format.json?
|
|
105
|
+
render json: {error: "Unauthorized"}, status: :unauthorized
|
|
106
|
+
else
|
|
107
|
+
redirect_to clowk_sign_in_path(return_to: request.fullpath)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def clowk_handle_expired_session(_session_info)
|
|
112
|
+
if request.format.json?
|
|
113
|
+
render json: {error: "Session expired or inactive"}, status: :unauthorized
|
|
114
|
+
else
|
|
115
|
+
redirect_to clowk_sign_in_path(return_to: request.fullpath)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
70
119
|
def verified_request_payload
|
|
71
120
|
return unless extracted_token
|
|
72
121
|
|
|
@@ -90,13 +139,13 @@ module Clowk
|
|
|
90
139
|
end
|
|
91
140
|
|
|
92
141
|
def stored_user_payload
|
|
93
|
-
payload = stored_session&.dig(
|
|
142
|
+
payload = stored_session&.dig("user") || stored_session&.dig(:user)
|
|
94
143
|
payload&.deep_symbolize_keys
|
|
95
144
|
end
|
|
96
145
|
|
|
97
146
|
def persist_clowk_session(token, payload)
|
|
98
147
|
session[Clowk.config.session_key] = {
|
|
99
|
-
token
|
|
148
|
+
token:,
|
|
100
149
|
user: payload,
|
|
101
150
|
signed_in_at: Time.now.to_i
|
|
102
151
|
}
|
|
@@ -108,5 +157,26 @@ module Clowk
|
|
|
108
157
|
secure: request.ssl?
|
|
109
158
|
}
|
|
110
159
|
end
|
|
160
|
+
|
|
161
|
+
def resolve_session_status
|
|
162
|
+
cached = stored_session&.dig("session_status") || stored_session&.dig(:session_status)
|
|
163
|
+
|
|
164
|
+
return cached&.deep_symbolize_keys if cached
|
|
165
|
+
|
|
166
|
+
resource = clowk_current_resource
|
|
167
|
+
|
|
168
|
+
return unless resource&.session_id
|
|
169
|
+
return unless Clowk.config.secret_key.present?
|
|
170
|
+
|
|
171
|
+
client = Clowk::SDK::Client.new(secret_key: Clowk.config.secret_key)
|
|
172
|
+
result = client.tokens.verify_with_session(token: current_token)
|
|
173
|
+
status = result&.dig(:session)
|
|
174
|
+
|
|
175
|
+
session[Clowk.config.session_key] = stored_session.merge("session_status" => status) if status && stored_session
|
|
176
|
+
|
|
177
|
+
status
|
|
178
|
+
rescue Clowk::InvalidTokenError
|
|
179
|
+
nil
|
|
180
|
+
end
|
|
111
181
|
end
|
|
112
182
|
end
|
data/lib/clowk/configuration.rb
CHANGED
|
@@ -4,8 +4,6 @@ module Clowk
|
|
|
4
4
|
class Configuration
|
|
5
5
|
attr_accessor :api_base_url
|
|
6
6
|
attr_accessor :app_base_url
|
|
7
|
-
attr_accessor :after_sign_in_path
|
|
8
|
-
attr_accessor :after_sign_out_path
|
|
9
7
|
attr_accessor :callback_path
|
|
10
8
|
attr_accessor :cookie_key
|
|
11
9
|
attr_accessor :http_logger
|
|
@@ -22,25 +20,60 @@ module Clowk
|
|
|
22
20
|
attr_accessor :session_key
|
|
23
21
|
attr_accessor :subdomain_url
|
|
24
22
|
attr_accessor :token_param
|
|
23
|
+
attr_accessor :enforce_active_session
|
|
24
|
+
attr_accessor :on_session_expired
|
|
25
25
|
|
|
26
26
|
def initialize
|
|
27
|
-
@api_base_url =
|
|
28
|
-
@app_base_url =
|
|
29
|
-
@after_sign_in_path =
|
|
30
|
-
@after_sign_out_path =
|
|
31
|
-
@mount_path =
|
|
32
|
-
@callback_path =
|
|
33
|
-
@cookie_key =
|
|
27
|
+
@api_base_url = "https://api.clowk.dev/api/v1"
|
|
28
|
+
@app_base_url = "https://app.clowk.in"
|
|
29
|
+
@after_sign_in_path = "/"
|
|
30
|
+
@after_sign_out_path = "/"
|
|
31
|
+
@mount_path = "/clowk"
|
|
32
|
+
@callback_path = "/clowk/oauth/callback"
|
|
33
|
+
@cookie_key = "clowk_token"
|
|
34
34
|
@http_logger = nil
|
|
35
35
|
@http_open_timeout = 5
|
|
36
36
|
@http_read_timeout = 10
|
|
37
37
|
@http_retry_attempts = 2
|
|
38
38
|
@http_retry_interval = 0.05
|
|
39
39
|
@http_write_timeout = 10
|
|
40
|
-
@issuer =
|
|
40
|
+
@issuer = "clowk"
|
|
41
41
|
@session_key = :clowk
|
|
42
42
|
@prefix_by = :clowk
|
|
43
43
|
@token_param = :token
|
|
44
|
+
@enforce_active_session = false
|
|
45
|
+
@on_session_expired = nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def after_sign_in_path
|
|
49
|
+
resolve_path(@after_sign_in_path)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def after_sign_out_path
|
|
53
|
+
resolve_path(@after_sign_out_path)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
attr_writer :after_sign_in_path
|
|
57
|
+
|
|
58
|
+
attr_writer :after_sign_out_path
|
|
59
|
+
|
|
60
|
+
def validate!
|
|
61
|
+
errors = []
|
|
62
|
+
errors << "secret_key must be a String" unless @secret_key.is_a?(String) || @secret_key.nil?
|
|
63
|
+
errors << "http_open_timeout must be Numeric" unless @http_open_timeout.is_a?(Numeric)
|
|
64
|
+
errors << "http_read_timeout must be Numeric" unless @http_read_timeout.is_a?(Numeric)
|
|
65
|
+
errors << "http_write_timeout must be Numeric" unless @http_write_timeout.is_a?(Numeric)
|
|
66
|
+
errors << "http_retry_attempts must be a non-negative Integer" unless @http_retry_attempts.is_a?(Integer) && @http_retry_attempts >= 0
|
|
67
|
+
|
|
68
|
+
raise ConfigurationError, errors.join(", ") if errors.any?
|
|
69
|
+
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def resolve_path(path_or_callable)
|
|
76
|
+
path_or_callable.respond_to?(:call) ? path_or_callable.call : path_or_callable
|
|
44
77
|
end
|
|
45
78
|
end
|
|
46
79
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require "securerandom"
|
|
4
|
+
require "uri"
|
|
5
5
|
|
|
6
6
|
module Clowk
|
|
7
7
|
class BaseController < ActionController::Base
|
|
@@ -13,18 +13,18 @@ module Clowk
|
|
|
13
13
|
private
|
|
14
14
|
|
|
15
15
|
def redirect_back_or(default, return_to: params[:return_to])
|
|
16
|
-
redirect_target = safe_redirect_path(return_to) || safe_redirect_path(default) ||
|
|
16
|
+
redirect_target = safe_redirect_path(return_to) || safe_redirect_path(default) || "/"
|
|
17
17
|
|
|
18
18
|
redirect_to redirect_target
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def start_clowk_auth_flow!(return_to: nil)
|
|
22
|
-
sanitized_return_to = safe_redirect_path(return_to) || safe_redirect_path(Clowk.config.after_sign_in_path) ||
|
|
22
|
+
sanitized_return_to = safe_redirect_path(return_to) || safe_redirect_path(Clowk.config.after_sign_in_path) || "/"
|
|
23
23
|
state = SecureRandom.hex(32)
|
|
24
24
|
|
|
25
25
|
session[:clowk_auth_flow] = {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
"state" => state,
|
|
27
|
+
"return_to" => sanitized_return_to
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
state
|
|
@@ -38,9 +38,9 @@ module Clowk
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def validate_clowk_state!(expected_state, actual_state)
|
|
41
|
-
raise Clowk::InvalidStateError,
|
|
42
|
-
raise Clowk::InvalidStateError,
|
|
43
|
-
raise Clowk::InvalidStateError,
|
|
41
|
+
raise Clowk::InvalidStateError, "missing state" if actual_state.blank?
|
|
42
|
+
raise Clowk::InvalidStateError, "missing state" if expected_state.blank?
|
|
43
|
+
raise Clowk::InvalidStateError, "invalid state" unless state_matches?(expected_state, actual_state)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def state_matches?(expected_state, actual_state)
|
|
@@ -53,7 +53,7 @@ module Clowk
|
|
|
53
53
|
value = candidate.to_s
|
|
54
54
|
return if value.empty?
|
|
55
55
|
|
|
56
|
-
return value if value.start_with?(
|
|
56
|
+
return value if value.start_with?("/") && !value.start_with?("//")
|
|
57
57
|
|
|
58
58
|
uri = URI.parse(value)
|
|
59
59
|
return unless uri.host == request.host && uri.scheme == request.scheme
|
|
@@ -4,20 +4,21 @@ module Clowk
|
|
|
4
4
|
class CallbacksController < BaseController
|
|
5
5
|
def show
|
|
6
6
|
flow = consume_clowk_auth_flow!
|
|
7
|
-
validate_clowk_state!(flow[
|
|
7
|
+
validate_clowk_state!(flow["state"], params[:state])
|
|
8
8
|
|
|
9
9
|
token = params[Clowk.config.token_param]
|
|
10
|
-
raise Clowk::InvalidTokenError,
|
|
10
|
+
raise Clowk::InvalidTokenError, "missing token" if token.blank?
|
|
11
11
|
|
|
12
12
|
payload = Clowk::JwtVerifier.new.verify(token)
|
|
13
|
-
return_to = flow[
|
|
13
|
+
return_to = flow["return_to"]
|
|
14
14
|
|
|
15
15
|
reset_clowk_session!
|
|
16
16
|
persist_clowk_session(token, payload)
|
|
17
17
|
|
|
18
18
|
redirect_back_or(Clowk.config.after_sign_in_path, return_to:)
|
|
19
19
|
rescue Clowk::InvalidTokenError, Clowk::InvalidStateError => e
|
|
20
|
-
|
|
20
|
+
Rails.logger.error("[Clowk] Authentication failed: #{e.class} - #{e.message}")
|
|
21
|
+
flash[:alert] = "Authentication failed. Please try again."
|
|
21
22
|
|
|
22
23
|
redirect_back_or(Clowk.config.after_sign_out_path, return_to: nil)
|
|
23
24
|
end
|
data/lib/clowk/current.rb
CHANGED
|
@@ -36,6 +36,10 @@ module Clowk
|
|
|
36
36
|
attributes[:app_id]
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
def session_id
|
|
40
|
+
attributes[:session_id]
|
|
41
|
+
end
|
|
42
|
+
|
|
39
43
|
def [](key)
|
|
40
44
|
attributes[key.to_sym]
|
|
41
45
|
end
|
|
@@ -43,5 +47,19 @@ module Clowk
|
|
|
43
47
|
def to_h
|
|
44
48
|
attributes.merge(id: id)
|
|
45
49
|
end
|
|
50
|
+
|
|
51
|
+
def ==(other)
|
|
52
|
+
return false unless other.is_a?(Current)
|
|
53
|
+
|
|
54
|
+
to_h == other.to_h
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def eql?(other)
|
|
58
|
+
self == other
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def hash
|
|
62
|
+
to_h.hash
|
|
63
|
+
end
|
|
46
64
|
end
|
|
47
|
-
end
|
|
65
|
+
end
|
data/lib/clowk/engine.rb
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'cgi'
|
|
4
|
-
|
|
5
3
|
module Clowk
|
|
6
4
|
module Helpers
|
|
7
5
|
module UrlHelpers
|
|
8
6
|
def clowk_sign_in_path(return_to: nil)
|
|
9
|
-
append_query(clowk_local_path(
|
|
7
|
+
append_query(clowk_local_path("/sign_in"), return_to:)
|
|
10
8
|
end
|
|
11
9
|
|
|
12
10
|
def clowk_sign_up_path(return_to: nil)
|
|
13
|
-
append_query(clowk_local_path(
|
|
11
|
+
append_query(clowk_local_path("/sign_up"), return_to:)
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def clowk_sign_out_path(return_to: nil)
|
|
17
|
-
append_query(clowk_local_path(
|
|
15
|
+
append_query(clowk_local_path("/sign_out"), return_to:)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def clowk_callback_url(return_to: nil, state: nil)
|
|
@@ -22,18 +20,18 @@ module Clowk
|
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
def clowk_sign_in_url(redirect_to: nil, return_to: nil, state: nil)
|
|
25
|
-
clowk_remote_auth_url(
|
|
23
|
+
clowk_remote_auth_url("sign-in", redirect_to:, return_to:, state:)
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
def clowk_sign_up_url(redirect_to: nil, return_to: nil, state: nil)
|
|
29
|
-
clowk_remote_auth_url(
|
|
27
|
+
clowk_remote_auth_url("sign-up", redirect_to:, return_to:, state:)
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
private
|
|
33
31
|
|
|
34
32
|
def clowk_remote_auth_url(action, redirect_to:, return_to:, state:)
|
|
35
33
|
callback_url = clowk_callback_url(return_to: redirect_to || return_to, state:)
|
|
36
|
-
query = {
|
|
34
|
+
query = {redirect_uri: callback_url}
|
|
37
35
|
|
|
38
36
|
append_query("#{clowk_instance_base_url}/#{action}", query)
|
|
39
37
|
end
|
|
@@ -50,7 +48,7 @@ module Clowk
|
|
|
50
48
|
filtered = params.compact.reject { |_key, value| value.respond_to?(:empty?) && value.empty? }
|
|
51
49
|
return url if filtered.empty?
|
|
52
50
|
|
|
53
|
-
separator = url.include?(
|
|
51
|
+
separator = url.include?("?") ? "&" : "?"
|
|
54
52
|
"#{url}#{separator}#{Rack::Utils.build_query(filtered)}"
|
|
55
53
|
end
|
|
56
54
|
end
|
data/lib/clowk/http/client.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
6
|
|
|
7
7
|
module Clowk
|
|
8
8
|
class Http
|
|
@@ -121,7 +121,7 @@ module Clowk
|
|
|
121
121
|
|
|
122
122
|
request.body = JSON.generate(env[:body]) unless env[:body].nil?
|
|
123
123
|
|
|
124
|
-
raw_response = Net::HTTP.start(env[:uri].host, env[:uri].port, use_ssl: env[:uri].scheme ==
|
|
124
|
+
raw_response = Net::HTTP.start(env[:uri].host, env[:uri].port, use_ssl: env[:uri].scheme == "https") do |http|
|
|
125
125
|
apply_timeouts(http, env[:timeouts])
|
|
126
126
|
http.request(request)
|
|
127
127
|
end
|
|
@@ -144,12 +144,12 @@ module Clowk
|
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
def normalize_path(path)
|
|
147
|
-
path.to_s.start_with?(
|
|
147
|
+
path.to_s.start_with?("/") ? path : "/#{path}"
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def join_paths(base_path, extra_path)
|
|
151
|
-
segments = [base_path.to_s, extra_path.to_s].map { |segment| segment.gsub(%r{^/+|/+$},
|
|
152
|
-
"/#{segments.join(
|
|
151
|
+
segments = [base_path.to_s, extra_path.to_s].map { |segment| segment.gsub(%r{^/+|/+$}, "") }.reject(&:empty?)
|
|
152
|
+
"/#{segments.join("/")}"
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
def apply_headers(request, request_headers)
|
|
@@ -167,8 +167,8 @@ module Clowk
|
|
|
167
167
|
|
|
168
168
|
def default_headers
|
|
169
169
|
{
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
"Accept" => "application/json",
|
|
171
|
+
"Content-Type" => "application/json"
|
|
172
172
|
}
|
|
173
173
|
end
|
|
174
174
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "logger"
|
|
4
4
|
|
|
5
5
|
module Clowk
|
|
6
6
|
class Http
|
|
@@ -22,7 +22,8 @@ module Clowk
|
|
|
22
22
|
attr_reader :app, :logger
|
|
23
23
|
|
|
24
24
|
class NullLogger
|
|
25
|
-
def info(*)
|
|
25
|
+
def info(*)
|
|
26
|
+
end
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
end
|
data/lib/clowk/http/response.rb
CHANGED
|
@@ -27,17 +27,17 @@ module Clowk
|
|
|
27
27
|
body: body,
|
|
28
28
|
body_parsed: body_parsed,
|
|
29
29
|
headers: headers,
|
|
30
|
-
success
|
|
30
|
+
success: success?
|
|
31
31
|
}
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def ==(other)
|
|
35
|
-
if other.respond_to?(:to_h)
|
|
36
|
-
|
|
35
|
+
to_h == if other.respond_to?(:to_h)
|
|
36
|
+
other.to_h
|
|
37
37
|
else
|
|
38
|
-
|
|
38
|
+
other
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
-
end
|
|
43
|
+
end
|
data/lib/clowk/jwt_verifier.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "jwt"
|
|
4
4
|
|
|
5
5
|
module Clowk
|
|
6
6
|
class JwtVerifier
|
|
7
|
-
ALGORITHM =
|
|
7
|
+
ALGORITHM = "HS256"
|
|
8
8
|
|
|
9
9
|
def initialize(secret_key: Clowk.config.secret_key, issuer: Clowk.config.issuer)
|
|
10
10
|
@secret_key = secret_key
|
|
@@ -12,9 +12,9 @@ module Clowk
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def verify(token)
|
|
15
|
-
raise ConfigurationError,
|
|
15
|
+
raise ConfigurationError, "missing Clowk secret_key" if @secret_key.to_s.empty?
|
|
16
16
|
|
|
17
|
-
options = {
|
|
17
|
+
options = {algorithm: ALGORITHM}
|
|
18
18
|
options[:iss] = @issuer if @issuer
|
|
19
19
|
options[:verify_iss] = @issuer.present?
|
|
20
20
|
|
|
@@ -18,7 +18,7 @@ module Clowk
|
|
|
18
18
|
attr_reader :request, :token_param, :cookie_key
|
|
19
19
|
|
|
20
20
|
def token_from_params
|
|
21
|
-
params = request.respond_to?(:params) && request.params ? request.params : {}
|
|
21
|
+
params = (request.respond_to?(:params) && request.params) ? request.params : {}
|
|
22
22
|
params[token_param.to_s].presence
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -26,8 +26,8 @@ module Clowk
|
|
|
26
26
|
header = request.authorization.to_s
|
|
27
27
|
return if header.empty?
|
|
28
28
|
|
|
29
|
-
scheme, token = header.split(
|
|
30
|
-
return unless scheme.to_s.casecmp(
|
|
29
|
+
scheme, token = header.split(" ", 2)
|
|
30
|
+
return unless scheme.to_s.casecmp("Bearer").zero?
|
|
31
31
|
|
|
32
32
|
token.presence
|
|
33
33
|
end
|
data/lib/clowk/sdk/client.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "active_support/inflector"
|
|
4
4
|
|
|
5
5
|
module Clowk
|
|
6
6
|
module SDK
|
|
7
7
|
class Client
|
|
8
8
|
def initialize(options = {})
|
|
9
|
-
@api_base_url = options.fetch(:api_base_url, Clowk.config.api_base_url
|
|
9
|
+
@api_base_url = options.fetch(:api_base_url, nil).presence || Clowk.config.api_base_url
|
|
10
10
|
@secret_key = options.fetch(:secret_key, Clowk.config.secret_key)
|
|
11
11
|
@publishable_key = options.fetch(:publishable_key, Clowk.config.publishable_key)
|
|
12
12
|
end
|
|
@@ -18,7 +18,7 @@ module Clowk
|
|
|
18
18
|
|
|
19
19
|
return super unless Clowk::SDK.const_defined?(resource_class_name)
|
|
20
20
|
|
|
21
|
-
resource_ivar = "@#{
|
|
21
|
+
resource_ivar = :"@#{resource_class_name}"
|
|
22
22
|
return instance_variable_get(resource_ivar) if instance_variable_defined?(resource_ivar)
|
|
23
23
|
|
|
24
24
|
resource_class = Clowk::SDK.const_get(resource_class_name)
|
|
@@ -80,8 +80,8 @@ module Clowk
|
|
|
80
80
|
|
|
81
81
|
def default_headers
|
|
82
82
|
{}.tap do |headers|
|
|
83
|
-
headers[
|
|
84
|
-
headers[
|
|
83
|
+
headers["X-Clowk-Secret-Key"] = secret_key if secret_key.present?
|
|
84
|
+
headers["X-Clowk-Publishable-Key"] = publishable_key if publishable_key.present?
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
data/lib/clowk/sdk/resource.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "erb"
|
|
4
4
|
|
|
5
5
|
module Clowk
|
|
6
6
|
module SDK
|
|
7
7
|
class Resource
|
|
8
8
|
def self.resource_path
|
|
9
|
-
raise NotImplementedError,
|
|
9
|
+
raise NotImplementedError, "resource_path must be implemented"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def initialize(client)
|
|
@@ -31,10 +31,10 @@ module Clowk
|
|
|
31
31
|
# @return [Clowk::Http::Response]
|
|
32
32
|
def search(raw_query = nil, **filters)
|
|
33
33
|
query = if raw_query.is_a?(String)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
raw_query
|
|
35
|
+
else
|
|
36
|
+
filters.map { |k, v| "#{k}:#{v}" }.join(" ")
|
|
37
|
+
end
|
|
38
38
|
|
|
39
39
|
client.get("#{self.class.resource_path}/search?query=#{ERB::Util.url_encode(query)}")
|
|
40
40
|
end
|
data/lib/clowk/sdk/session.rb
CHANGED
|
@@ -4,7 +4,24 @@ module Clowk
|
|
|
4
4
|
module SDK
|
|
5
5
|
class Session < Resource
|
|
6
6
|
def self.resource_path
|
|
7
|
-
|
|
7
|
+
"sessions"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @param raw_query [String, nil] Raw query string (forwarded to the base search)
|
|
11
|
+
# @param email [String, nil] Email to search for via the legacy ILIKE endpoint
|
|
12
|
+
# @param filters [Hash] Keyword filters (forwarded to the base search)
|
|
13
|
+
# @return [Clowk::Http::Response]
|
|
14
|
+
def search(raw_query = nil, email: nil, **filters)
|
|
15
|
+
return super(raw_query, **filters) unless email
|
|
16
|
+
|
|
17
|
+
client.get("#{self.class.resource_path}/search?email=#{ERB::Util.url_encode(email)}")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Revokes a session by its session_id (clk_session_UUID)
|
|
21
|
+
# @param session_id [String]
|
|
22
|
+
# @return [Clowk::Http::Response]
|
|
23
|
+
def revoke(session_id)
|
|
24
|
+
destroy(session_id)
|
|
8
25
|
end
|
|
9
26
|
end
|
|
10
27
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Clowk
|
|
4
|
+
module SDK
|
|
5
|
+
class SessionConfig < Resource
|
|
6
|
+
def self.resource_path
|
|
7
|
+
"session_config"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def fetch
|
|
11
|
+
response = client.get(self.class.resource_path)
|
|
12
|
+
|
|
13
|
+
response.body_parsed&.deep_symbolize_keys
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/clowk/sdk/subdomain.rb
CHANGED
data/lib/clowk/sdk/token.rb
CHANGED
|
@@ -4,11 +4,23 @@ module Clowk
|
|
|
4
4
|
module SDK
|
|
5
5
|
class Token < Resource
|
|
6
6
|
def self.resource_path
|
|
7
|
-
|
|
7
|
+
"tokens"
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def verify(token:)
|
|
11
|
-
client.post("#{self.class.resource_path}/verify", {
|
|
11
|
+
client.post("#{self.class.resource_path}/verify", {token: token})
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def verify_with_session(token:)
|
|
15
|
+
response = verify(token:)
|
|
16
|
+
|
|
17
|
+
unless response.success?
|
|
18
|
+
raise Clowk::InvalidTokenError, response.body_parsed&.dig("error") || "token verification failed"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
data = response.body_parsed&.dig("data") || response.body_parsed
|
|
22
|
+
|
|
23
|
+
data&.deep_symbolize_keys
|
|
12
24
|
end
|
|
13
25
|
end
|
|
14
26
|
end
|
data/lib/clowk/sdk/user.rb
CHANGED
data/lib/clowk/subdomain.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "uri"
|
|
4
4
|
|
|
5
5
|
module Clowk
|
|
6
6
|
class Subdomain
|
|
7
7
|
CACHE_TTL = 60
|
|
8
|
-
DEFAULT_SUBDOMAIN_BASE =
|
|
8
|
+
DEFAULT_SUBDOMAIN_BASE = "clowk.dev"
|
|
9
|
+
|
|
10
|
+
@cache_mutex = Mutex.new
|
|
9
11
|
|
|
10
12
|
class << self
|
|
11
13
|
def resolve_url!(...)
|
|
@@ -13,24 +15,28 @@ module Clowk
|
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
def clear_cache!
|
|
16
|
-
@cache = {}
|
|
18
|
+
@cache_mutex.synchronize { @cache = {} }
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def read_cache(key)
|
|
20
|
-
|
|
22
|
+
@cache_mutex.synchronize do
|
|
23
|
+
entry = cache[key]
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
return unless entry
|
|
26
|
+
return entry[:value] if entry[:expires_at] > Time.now
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
cache.delete(key)
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
def write_cache(key, value, ttl:)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
@cache_mutex.synchronize do
|
|
35
|
+
cache[key] = {
|
|
36
|
+
value: value,
|
|
37
|
+
expires_at: Time.now + ttl
|
|
38
|
+
}
|
|
39
|
+
end
|
|
34
40
|
end
|
|
35
41
|
|
|
36
42
|
private
|
|
@@ -42,7 +48,6 @@ module Clowk
|
|
|
42
48
|
|
|
43
49
|
def initialize(options = {})
|
|
44
50
|
@publishable_key = options.fetch(:publishable_key, Clowk.config.publishable_key)
|
|
45
|
-
@api_base_url = options.fetch(:api_base_url, Clowk.config.api_base_url)
|
|
46
51
|
@subdomain_url = options.fetch(:subdomain_url, Clowk.config.subdomain_url)
|
|
47
52
|
end
|
|
48
53
|
|
|
@@ -50,12 +55,12 @@ module Clowk
|
|
|
50
55
|
return resolve_from_key if publishable_key.present?
|
|
51
56
|
return normalize_url(subdomain_url) if subdomain_url.present?
|
|
52
57
|
|
|
53
|
-
raise ConfigurationError,
|
|
58
|
+
raise ConfigurationError, "set publishable_key or subdomain_url to build Clowk URLs"
|
|
54
59
|
end
|
|
55
60
|
|
|
56
61
|
private
|
|
57
62
|
|
|
58
|
-
attr_reader :
|
|
63
|
+
attr_reader :publishable_key, :subdomain_url
|
|
59
64
|
|
|
60
65
|
def resolve_from_key
|
|
61
66
|
cached = self.class.read_cache(cache_key)
|
|
@@ -64,7 +69,7 @@ module Clowk
|
|
|
64
69
|
response = client.subdomains.find_by_pk(publishable_key)
|
|
65
70
|
resolved = extract_url_from_instance(response.body_parsed)
|
|
66
71
|
|
|
67
|
-
raise ConfigurationError,
|
|
72
|
+
raise ConfigurationError, "could not resolve subdomain_url from publishable_key" if resolved.blank?
|
|
68
73
|
|
|
69
74
|
self.class.write_cache(cache_key, resolved, ttl: CACHE_TTL)
|
|
70
75
|
resolved
|
|
@@ -77,22 +82,28 @@ module Clowk
|
|
|
77
82
|
def extract_url_from_instance(payload)
|
|
78
83
|
return if payload.blank?
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
instance_data =
|
|
85
|
+
root = payload.is_a?(Hash) ? payload : {}
|
|
86
|
+
instance_data = if root["instance"].is_a?(Hash)
|
|
87
|
+
root["instance"]
|
|
88
|
+
elsif root["data"].is_a?(Hash)
|
|
89
|
+
root["data"]
|
|
90
|
+
else
|
|
91
|
+
root
|
|
92
|
+
end
|
|
82
93
|
|
|
83
|
-
explicit_url = instance_data[
|
|
94
|
+
explicit_url = instance_data["url"] || instance_data["subdomain_url"] || instance_data["instance_url"]
|
|
84
95
|
return normalize_url(explicit_url) if explicit_url.present?
|
|
85
96
|
|
|
86
|
-
host = instance_data[
|
|
97
|
+
host = instance_data["host"] || instance_data["domain"] || instance_data["hostname"]
|
|
87
98
|
return normalize_url(host_to_url(host)) if host.present?
|
|
88
99
|
|
|
89
|
-
subdomain = instance_data[
|
|
100
|
+
subdomain = instance_data["subdomain"]
|
|
90
101
|
normalize_url("https://#{subdomain}.#{default_subdomain_base}") if subdomain.present?
|
|
91
102
|
end
|
|
92
103
|
|
|
93
104
|
def host_to_url(host)
|
|
94
105
|
value = host.to_s
|
|
95
|
-
return value if value.start_with?(
|
|
106
|
+
return value if value.start_with?("http://", "https://")
|
|
96
107
|
|
|
97
108
|
"https://#{value}"
|
|
98
109
|
end
|
|
@@ -104,17 +115,17 @@ module Clowk
|
|
|
104
115
|
uri = URI.parse(configured)
|
|
105
116
|
return DEFAULT_SUBDOMAIN_BASE if uri.host.blank?
|
|
106
117
|
|
|
107
|
-
uri.host.split(
|
|
118
|
+
uri.host.split(".").drop(1).join(".")
|
|
108
119
|
rescue URI::InvalidURIError
|
|
109
120
|
DEFAULT_SUBDOMAIN_BASE
|
|
110
121
|
end
|
|
111
122
|
|
|
112
123
|
def normalize_url(value)
|
|
113
|
-
value.to_s.sub(%r{/$},
|
|
124
|
+
value.to_s.sub(%r{/$}, "")
|
|
114
125
|
end
|
|
115
126
|
|
|
116
127
|
def client
|
|
117
|
-
@client ||= Clowk::SDK::Client.new
|
|
128
|
+
@client ||= Clowk::SDK::Client.new(api_base_url: Clowk.config.api_base_url)
|
|
118
129
|
end
|
|
119
130
|
end
|
|
120
131
|
end
|
data/lib/clowk/version.rb
CHANGED
data/lib/clowk.rb
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
3
|
+
require "rails"
|
|
4
|
+
require "rails/engine"
|
|
5
|
+
require "action_controller/railtie"
|
|
6
|
+
require "active_support"
|
|
7
|
+
require "active_support/core_ext/hash"
|
|
8
|
+
require "active_support/core_ext/object/blank"
|
|
9
|
+
require "rack"
|
|
10
10
|
|
|
11
|
-
require_relative
|
|
12
|
-
require_relative
|
|
11
|
+
require_relative "clowk/version"
|
|
12
|
+
require_relative "clowk/configuration"
|
|
13
13
|
|
|
14
14
|
module Clowk
|
|
15
15
|
class Error < StandardError; end
|
|
@@ -24,6 +24,7 @@ module Clowk
|
|
|
24
24
|
|
|
25
25
|
def configure
|
|
26
26
|
yield(config)
|
|
27
|
+
config.validate!
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def reset!
|
|
@@ -33,24 +34,25 @@ module Clowk
|
|
|
33
34
|
end
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
require_relative
|
|
37
|
-
require_relative
|
|
38
|
-
require_relative
|
|
39
|
-
require_relative
|
|
40
|
-
require_relative
|
|
41
|
-
require_relative
|
|
42
|
-
require_relative
|
|
43
|
-
require_relative
|
|
44
|
-
require_relative
|
|
45
|
-
require_relative
|
|
46
|
-
require_relative
|
|
47
|
-
require_relative
|
|
48
|
-
require_relative
|
|
49
|
-
require_relative
|
|
50
|
-
require_relative
|
|
51
|
-
require_relative
|
|
52
|
-
require_relative
|
|
53
|
-
require_relative
|
|
54
|
-
require_relative
|
|
55
|
-
require_relative
|
|
56
|
-
require_relative
|
|
37
|
+
require_relative "clowk/current"
|
|
38
|
+
require_relative "clowk/http/response"
|
|
39
|
+
require_relative "clowk/http/logger_middleware"
|
|
40
|
+
require_relative "clowk/http/retry_middleware"
|
|
41
|
+
require_relative "clowk/http/timeout_middleware"
|
|
42
|
+
require_relative "clowk/http/client"
|
|
43
|
+
require_relative "clowk/sdk/resource"
|
|
44
|
+
require_relative "clowk/sdk/user"
|
|
45
|
+
require_relative "clowk/sdk/session"
|
|
46
|
+
require_relative "clowk/sdk/subdomain"
|
|
47
|
+
require_relative "clowk/sdk/token"
|
|
48
|
+
require_relative "clowk/sdk/session_config"
|
|
49
|
+
require_relative "clowk/sdk/client"
|
|
50
|
+
require_relative "clowk/subdomain"
|
|
51
|
+
require_relative "clowk/jwt_verifier"
|
|
52
|
+
require_relative "clowk/helpers/url_helpers"
|
|
53
|
+
require_relative "clowk/middleware/token_extractor"
|
|
54
|
+
require_relative "clowk/authenticable"
|
|
55
|
+
require_relative "clowk/controllers/base_controller"
|
|
56
|
+
require_relative "clowk/controllers/callbacks_controller"
|
|
57
|
+
require_relative "clowk/controllers/sessions_controller"
|
|
58
|
+
require_relative "clowk/engine"
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: clowk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Clowk
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: activesupport
|
|
@@ -77,6 +77,20 @@ dependencies:
|
|
|
77
77
|
- - "<"
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
79
|
version: '4.0'
|
|
80
|
+
- !ruby/object:Gem::Dependency
|
|
81
|
+
name: standard
|
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
84
|
+
- - ">="
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: '1.0'
|
|
87
|
+
type: :development
|
|
88
|
+
prerelease: false
|
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
90
|
+
requirements:
|
|
91
|
+
- - ">="
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '1.0'
|
|
80
94
|
description: Clowk Authentication, JWT verification, and future API access
|
|
81
95
|
email:
|
|
82
96
|
- support@clowk.in
|
|
@@ -106,6 +120,7 @@ files:
|
|
|
106
120
|
- lib/clowk/sdk/client.rb
|
|
107
121
|
- lib/clowk/sdk/resource.rb
|
|
108
122
|
- lib/clowk/sdk/session.rb
|
|
123
|
+
- lib/clowk/sdk/session_config.rb
|
|
109
124
|
- lib/clowk/sdk/subdomain.rb
|
|
110
125
|
- lib/clowk/sdk/token.rb
|
|
111
126
|
- lib/clowk/sdk/user.rb
|
|
@@ -113,7 +128,7 @@ files:
|
|
|
113
128
|
- lib/clowk/version.rb
|
|
114
129
|
homepage: https://clowk.in
|
|
115
130
|
licenses:
|
|
116
|
-
- AGPL-3.0
|
|
131
|
+
- AGPL-3.0-only
|
|
117
132
|
metadata:
|
|
118
133
|
rubygems_mfa_required: 'true'
|
|
119
134
|
rdoc_options: []
|
|
@@ -130,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
130
145
|
- !ruby/object:Gem::Version
|
|
131
146
|
version: '0'
|
|
132
147
|
requirements: []
|
|
133
|
-
rubygems_version: 3.6.
|
|
148
|
+
rubygems_version: 3.6.9
|
|
134
149
|
specification_version: 4
|
|
135
150
|
summary: Rails SDK for Clowk authentication
|
|
136
151
|
test_files: []
|