clowk 0.1.0

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.
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clowk
4
+ module SDK
5
+ class Session < Resource
6
+ def self.resource_path
7
+ 'sessions'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clowk
4
+ module SDK
5
+ class Subdomain < Resource
6
+ def self.resource_path
7
+ 'instances'
8
+ end
9
+
10
+ def find_by_pk(key = nil)
11
+ return if key.blank?
12
+
13
+ search(publishable_key: key)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clowk
4
+ module SDK
5
+ class Token < Resource
6
+ def self.resource_path
7
+ 'tokens'
8
+ end
9
+
10
+ def verify(token:)
11
+ client.post("#{self.class.resource_path}/verify", { token: token })
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clowk
4
+ module SDK
5
+ class User < Resource
6
+ def self.resource_path
7
+ 'users'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ module Clowk
6
+ class Subdomain
7
+ CACHE_TTL = 60
8
+ DEFAULT_SUBDOMAIN_BASE = 'clowk.dev'
9
+
10
+ class << self
11
+ def resolve_url!(...)
12
+ new(...).resolve_url!
13
+ end
14
+
15
+ def clear_cache!
16
+ @cache = {}
17
+ end
18
+
19
+ def read_cache(key)
20
+ entry = cache[key]
21
+
22
+ return unless entry
23
+ return entry[:value] if entry[:expires_at] > Time.now
24
+
25
+ cache.delete(key)
26
+ nil
27
+ end
28
+
29
+ def write_cache(key, value, ttl:)
30
+ cache[key] = {
31
+ value: value,
32
+ expires_at: Time.now + ttl
33
+ }
34
+ end
35
+
36
+ private
37
+
38
+ def cache
39
+ @cache ||= {}
40
+ end
41
+ end
42
+
43
+ def initialize(options = {})
44
+ @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
+ @subdomain_url = options.fetch(:subdomain_url, Clowk.config.subdomain_url)
47
+ end
48
+
49
+ def resolve_url!
50
+ return resolve_from_key if publishable_key.present?
51
+ return normalize_url(subdomain_url) if subdomain_url.present?
52
+
53
+ raise ConfigurationError, 'set publishable_key or subdomain_url to build Clowk URLs'
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :api_base_url, :publishable_key, :subdomain_url
59
+
60
+ def resolve_from_key
61
+ cached = self.class.read_cache(cache_key)
62
+ return cached if cached
63
+
64
+ response = client.subdomains.find_by_pk(publishable_key)
65
+ resolved = extract_url_from_instance(response.body_parsed)
66
+
67
+ raise ConfigurationError, 'could not resolve subdomain_url from publishable_key' if resolved.blank?
68
+
69
+ self.class.write_cache(cache_key, resolved, ttl: CACHE_TTL)
70
+ resolved
71
+ end
72
+
73
+ def cache_key
74
+ "instance-url:#{publishable_key}"
75
+ end
76
+
77
+ def extract_url_from_instance(payload)
78
+ return if payload.blank?
79
+
80
+ instance = payload.is_a?(Hash) ? payload : {}
81
+ instance_data = instance['instance'].is_a?(Hash) ? instance['instance'] : instance
82
+
83
+ explicit_url = instance_data['url'] || instance_data['subdomain_url'] || instance_data['instance_url']
84
+ return normalize_url(explicit_url) if explicit_url.present?
85
+
86
+ host = instance_data['host'] || instance_data['domain'] || instance_data['hostname']
87
+ return normalize_url(host_to_url(host)) if host.present?
88
+
89
+ subdomain = instance_data['subdomain']
90
+ normalize_url("https://#{subdomain}.#{default_subdomain_base}") if subdomain.present?
91
+ end
92
+
93
+ def host_to_url(host)
94
+ value = host.to_s
95
+ return value if value.start_with?('http://', 'https://')
96
+
97
+ "https://#{value}"
98
+ end
99
+
100
+ def default_subdomain_base
101
+ configured = subdomain_url.to_s.strip
102
+ return DEFAULT_SUBDOMAIN_BASE if configured.empty?
103
+
104
+ uri = URI.parse(configured)
105
+ return DEFAULT_SUBDOMAIN_BASE if uri.host.blank?
106
+
107
+ uri.host.split('.').drop(1).join('.')
108
+ rescue URI::InvalidURIError
109
+ DEFAULT_SUBDOMAIN_BASE
110
+ end
111
+
112
+ def normalize_url(value)
113
+ value.to_s.sub(%r{/$}, '')
114
+ end
115
+
116
+ def client
117
+ @client ||= Clowk::SDK::Client.new
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clowk
4
+ VERSION = '0.1.0'
5
+ end
data/lib/clowk.rb ADDED
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
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
+
11
+ require_relative 'clowk/version'
12
+ require_relative 'clowk/configuration'
13
+
14
+ module Clowk
15
+ class Error < StandardError; end
16
+ class ConfigurationError < Error; end
17
+ class InvalidStateError < Error; end
18
+ class InvalidTokenError < Error; end
19
+
20
+ class << self
21
+ def config
22
+ @config ||= Configuration.new
23
+ end
24
+
25
+ def configure
26
+ yield(config)
27
+ end
28
+
29
+ def reset!
30
+ Subdomain.clear_cache! if defined?(Subdomain)
31
+ @config = Configuration.new
32
+ end
33
+ end
34
+ end
35
+
36
+ require_relative 'clowk/current'
37
+ require_relative 'clowk/http/response'
38
+ require_relative 'clowk/http/logger_middleware'
39
+ require_relative 'clowk/http/retry_middleware'
40
+ require_relative 'clowk/http/timeout_middleware'
41
+ require_relative 'clowk/http/client'
42
+ require_relative 'clowk/sdk/resource'
43
+ require_relative 'clowk/sdk/user'
44
+ require_relative 'clowk/sdk/session'
45
+ require_relative 'clowk/sdk/subdomain'
46
+ require_relative 'clowk/sdk/token'
47
+ require_relative 'clowk/sdk/client'
48
+ require_relative 'clowk/subdomain'
49
+ require_relative 'clowk/jwt_verifier'
50
+ require_relative 'clowk/helpers/url_helpers'
51
+ require_relative 'clowk/middleware/token_extractor'
52
+ require_relative 'clowk/authenticable'
53
+ require_relative 'clowk/controllers/base_controller'
54
+ require_relative 'clowk/controllers/callbacks_controller'
55
+ require_relative 'clowk/controllers/sessions_controller'
56
+ require_relative 'clowk/engine'
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clowk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Clowk
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-03-23 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: activesupport
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: jwt
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.7'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '3.0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '2.7'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: railties
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '7.0'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '7.0'
60
+ - !ruby/object:Gem::Dependency
61
+ name: rspec
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '3.13'
67
+ - - "<"
68
+ - !ruby/object:Gem::Version
69
+ version: '4.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '3.13'
77
+ - - "<"
78
+ - !ruby/object:Gem::Version
79
+ version: '4.0'
80
+ description: Clowk Authentication, JWT verification, and future API access
81
+ email:
82
+ - support@clowk.in
83
+ executables: []
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - README.md
88
+ - clowk.gemspec
89
+ - config/routes.rb
90
+ - lib/clowk.rb
91
+ - lib/clowk/authenticable.rb
92
+ - lib/clowk/configuration.rb
93
+ - lib/clowk/controllers/base_controller.rb
94
+ - lib/clowk/controllers/callbacks_controller.rb
95
+ - lib/clowk/controllers/sessions_controller.rb
96
+ - lib/clowk/current.rb
97
+ - lib/clowk/engine.rb
98
+ - lib/clowk/helpers/url_helpers.rb
99
+ - lib/clowk/http/client.rb
100
+ - lib/clowk/http/logger_middleware.rb
101
+ - lib/clowk/http/response.rb
102
+ - lib/clowk/http/retry_middleware.rb
103
+ - lib/clowk/http/timeout_middleware.rb
104
+ - lib/clowk/jwt_verifier.rb
105
+ - lib/clowk/middleware/token_extractor.rb
106
+ - lib/clowk/sdk/client.rb
107
+ - lib/clowk/sdk/resource.rb
108
+ - lib/clowk/sdk/session.rb
109
+ - lib/clowk/sdk/subdomain.rb
110
+ - lib/clowk/sdk/token.rb
111
+ - lib/clowk/sdk/user.rb
112
+ - lib/clowk/subdomain.rb
113
+ - lib/clowk/version.rb
114
+ homepage: https://clowk.in
115
+ licenses:
116
+ - AGPL-3.0
117
+ metadata:
118
+ rubygems_mfa_required: 'true'
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '3.3'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.6.2
134
+ specification_version: 4
135
+ summary: Rails SDK for Clowk authentication
136
+ test_files: []