oauth-tool 1.0.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.
- checksums.yaml +7 -0
- data/bin/oauth-tool +3 -0
- data/lib/oauth_tool.rb +295 -0
- data/oauth-tool.gemspec +21 -0
- metadata +42 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9886d33c495d6518949769d978c9473d7d7daeb2967064628011677934c6f048
|
|
4
|
+
data.tar.gz: a4583d59e5ee705f2a3ada3c3d1401cf35f3c253d4d14f8e72bbdcd5bae1f086
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7e494e7eed47442de0d76acd43d89a54ad08f8696843b0e6fbe767bdcff5eb4f345b76c1ac1580e1a6c3bde2224c4b4d5a7de6e2d4d64f44f4bf73e34dafea82
|
|
7
|
+
data.tar.gz: 4718488f6debce1e33df8593c857af29a90fe6278d6798173fd562076bff0714b73af181eabd9c6b20c9d025a980c6b791a52ac0b198aad6ff6d94e0f5eb064f
|
data/bin/oauth-tool
ADDED
data/lib/oauth_tool.rb
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "uri"
|
|
5
|
+
require "json"
|
|
6
|
+
require "fileutils"
|
|
7
|
+
|
|
8
|
+
BASE = "https://probable-octo-winner.fly.dev"
|
|
9
|
+
TOKEN_FILE = File.join(Dir.home, ".oauth_access_token")
|
|
10
|
+
VERSION = "1.0.0"
|
|
11
|
+
|
|
12
|
+
def request(method, path, body = nil, token = nil)
|
|
13
|
+
uri = URI("#{BASE}#{path}")
|
|
14
|
+
|
|
15
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
16
|
+
http.use_ssl = true
|
|
17
|
+
|
|
18
|
+
klass = {
|
|
19
|
+
"GET" => Net::HTTP::Get,
|
|
20
|
+
"POST" => Net::HTTP::Post
|
|
21
|
+
}[method]
|
|
22
|
+
|
|
23
|
+
raise "Unsupported HTTP method: #{method}" unless klass
|
|
24
|
+
|
|
25
|
+
req = klass.new(uri)
|
|
26
|
+
req["Content-Type"] = "application/json"
|
|
27
|
+
req["Authorization"] = "Bearer #{token}" if token
|
|
28
|
+
req.body = JSON.generate(body) if body
|
|
29
|
+
|
|
30
|
+
response = http.request(req)
|
|
31
|
+
|
|
32
|
+
begin
|
|
33
|
+
JSON.parse(response.body)
|
|
34
|
+
rescue JSON::ParserError
|
|
35
|
+
{
|
|
36
|
+
"raw" => response.body,
|
|
37
|
+
"status" => response.code.to_i
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def save_token(token)
|
|
43
|
+
File.write(TOKEN_FILE, "#{token}\n")
|
|
44
|
+
File.chmod(0600, TOKEN_FILE)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def load_token
|
|
48
|
+
return nil unless File.file?(TOKEN_FILE)
|
|
49
|
+
|
|
50
|
+
token = File.read(TOKEN_FILE).strip
|
|
51
|
+
token.empty? ? nil : token
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def help
|
|
55
|
+
puts <<~HELP
|
|
56
|
+
OAuth Tool #{VERSION}
|
|
57
|
+
|
|
58
|
+
Usage:
|
|
59
|
+
oauth-tool [command] [options]
|
|
60
|
+
|
|
61
|
+
Commands:
|
|
62
|
+
help Show this help
|
|
63
|
+
health Check API health
|
|
64
|
+
auth register Create an account
|
|
65
|
+
auth login Start OAuth device login
|
|
66
|
+
auth status Check authentication
|
|
67
|
+
auth logout Remove saved token
|
|
68
|
+
auth help Show authentication help
|
|
69
|
+
get Get protected RAM information
|
|
70
|
+
|
|
71
|
+
Options:
|
|
72
|
+
-h, --help Show help
|
|
73
|
+
-v, --version Show version
|
|
74
|
+
HELP
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def auth_help
|
|
78
|
+
puts <<~HELP
|
|
79
|
+
OAuth authentication commands:
|
|
80
|
+
|
|
81
|
+
oauth-tool auth register
|
|
82
|
+
oauth-tool auth login
|
|
83
|
+
oauth-tool auth status
|
|
84
|
+
oauth-tool auth logout
|
|
85
|
+
oauth-tool auth help
|
|
86
|
+
HELP
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def register
|
|
90
|
+
print "Username: "
|
|
91
|
+
username = STDIN.gets&.strip
|
|
92
|
+
|
|
93
|
+
if username.nil? || username.empty?
|
|
94
|
+
puts "Username is required."
|
|
95
|
+
return
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
print "Password: "
|
|
99
|
+
|
|
100
|
+
if STDIN.tty?
|
|
101
|
+
system("stty -echo")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
password = STDIN.gets&.strip
|
|
105
|
+
|
|
106
|
+
if STDIN.tty?
|
|
107
|
+
system("stty echo")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
puts
|
|
111
|
+
|
|
112
|
+
if password.nil? || password.empty?
|
|
113
|
+
puts "Password is required."
|
|
114
|
+
return
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
result = request(
|
|
118
|
+
"POST",
|
|
119
|
+
"/api/auth/register",
|
|
120
|
+
{
|
|
121
|
+
username: username,
|
|
122
|
+
password: password
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
puts JSON.pretty_generate(result)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def login
|
|
130
|
+
puts "Generating OAuth device code..."
|
|
131
|
+
|
|
132
|
+
data = request("POST", "/oauth/device/code", {})
|
|
133
|
+
|
|
134
|
+
unless data["device_code"]
|
|
135
|
+
puts JSON.pretty_generate(data)
|
|
136
|
+
return
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
device_code = data["device_code"]
|
|
140
|
+
user_code = data["user_code"]
|
|
141
|
+
verify_url =
|
|
142
|
+
data["verification_uri_complete"] ||
|
|
143
|
+
data["verification_uri"]
|
|
144
|
+
|
|
145
|
+
interval = (data["interval"] || 5).to_i
|
|
146
|
+
|
|
147
|
+
puts
|
|
148
|
+
puts "======================================"
|
|
149
|
+
puts " OAuth Device Authorization"
|
|
150
|
+
puts "======================================"
|
|
151
|
+
puts
|
|
152
|
+
puts "User code: #{user_code}"
|
|
153
|
+
puts
|
|
154
|
+
puts "Verification URL: #{verify_url}"
|
|
155
|
+
puts
|
|
156
|
+
puts "Open the URL and authorize the device."
|
|
157
|
+
puts "Waiting for authorization..."
|
|
158
|
+
|
|
159
|
+
loop do
|
|
160
|
+
token_data = request(
|
|
161
|
+
"POST",
|
|
162
|
+
"/oauth2/token",
|
|
163
|
+
{ device_code: device_code }
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if token_data["access_token"]
|
|
167
|
+
save_token(token_data["access_token"])
|
|
168
|
+
|
|
169
|
+
puts
|
|
170
|
+
puts "Authorization completed."
|
|
171
|
+
puts "Access token saved:"
|
|
172
|
+
puts TOKEN_FILE
|
|
173
|
+
return
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
if token_data["error"] == "authorization_pending"
|
|
177
|
+
print "."
|
|
178
|
+
sleep interval
|
|
179
|
+
next
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
puts
|
|
183
|
+
puts "OAuth token request failed:"
|
|
184
|
+
puts JSON.pretty_generate(token_data)
|
|
185
|
+
return
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def status
|
|
190
|
+
token = load_token
|
|
191
|
+
|
|
192
|
+
unless token
|
|
193
|
+
puts '{"authenticated":false}'
|
|
194
|
+
return
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
result = request(
|
|
198
|
+
"GET",
|
|
199
|
+
"/api/oauth/status",
|
|
200
|
+
nil,
|
|
201
|
+
token
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
puts JSON.pretty_generate(result)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def logout
|
|
208
|
+
token = load_token
|
|
209
|
+
|
|
210
|
+
unless token
|
|
211
|
+
puts "Not authenticated."
|
|
212
|
+
return
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
result = request(
|
|
216
|
+
"POST",
|
|
217
|
+
"/api/auth/logout",
|
|
218
|
+
{},
|
|
219
|
+
token
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
File.delete(TOKEN_FILE) if File.exist?(TOKEN_FILE)
|
|
223
|
+
|
|
224
|
+
puts JSON.pretty_generate(result)
|
|
225
|
+
puts "Local access token removed."
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def get_ram
|
|
229
|
+
token = load_token
|
|
230
|
+
|
|
231
|
+
unless token
|
|
232
|
+
puts "Not authenticated."
|
|
233
|
+
puts "Run: oauth-tool auth login"
|
|
234
|
+
return
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
result = request(
|
|
238
|
+
"GET",
|
|
239
|
+
"/api/get-ram",
|
|
240
|
+
nil,
|
|
241
|
+
token
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
puts JSON.pretty_generate(result)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
args = ARGV.dup
|
|
248
|
+
|
|
249
|
+
if args.empty? ||
|
|
250
|
+
args[0] == "help" ||
|
|
251
|
+
args[0] == "-h" ||
|
|
252
|
+
args[0] == "--help"
|
|
253
|
+
|
|
254
|
+
help
|
|
255
|
+
exit
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
if args[0] == "-v" || args[0] == "--version"
|
|
259
|
+
puts VERSION
|
|
260
|
+
exit
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
case args[0]
|
|
264
|
+
when "health"
|
|
265
|
+
puts JSON.pretty_generate(
|
|
266
|
+
request("GET", "/api/health")
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
when "get"
|
|
270
|
+
get_ram
|
|
271
|
+
|
|
272
|
+
when "auth"
|
|
273
|
+
case args[1]
|
|
274
|
+
when "register"
|
|
275
|
+
register
|
|
276
|
+
when "login"
|
|
277
|
+
login
|
|
278
|
+
when "status"
|
|
279
|
+
status
|
|
280
|
+
when "logout"
|
|
281
|
+
logout
|
|
282
|
+
when "help", nil
|
|
283
|
+
auth_help
|
|
284
|
+
else
|
|
285
|
+
warn "Unknown auth command: #{args[1]}"
|
|
286
|
+
auth_help
|
|
287
|
+
exit 1
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
else
|
|
291
|
+
warn "Unknown command: #{args[0]}"
|
|
292
|
+
puts
|
|
293
|
+
help
|
|
294
|
+
exit 1
|
|
295
|
+
end
|
data/oauth-tool.gemspec
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Gem::Specification.new do |spec|
|
|
2
|
+
spec.name = "oauth-tool"
|
|
3
|
+
spec.version = "1.0.0"
|
|
4
|
+
spec.authors = ["Jjjm"]
|
|
5
|
+
spec.summary = "OAuth device authorization CLI"
|
|
6
|
+
spec.description = "CLI for OAuth device authentication and protected API access."
|
|
7
|
+
spec.homepage = "https://probable-octo-winner.fly.dev"
|
|
8
|
+
spec.license = "MIT"
|
|
9
|
+
|
|
10
|
+
spec.required_ruby_version = ">= 3.0"
|
|
11
|
+
|
|
12
|
+
spec.files = [
|
|
13
|
+
"bin/oauth-tool",
|
|
14
|
+
"lib/oauth_tool.rb",
|
|
15
|
+
"oauth-tool.gemspec"
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
spec.bindir = "bin"
|
|
19
|
+
spec.executables = ["oauth-tool"]
|
|
20
|
+
spec.require_paths = ["lib"]
|
|
21
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: oauth-tool
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jjjm
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-08-13 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: CLI for OAuth device authentication and protected API access.
|
|
13
|
+
executables:
|
|
14
|
+
- oauth-tool
|
|
15
|
+
extensions: []
|
|
16
|
+
extra_rdoc_files: []
|
|
17
|
+
files:
|
|
18
|
+
- bin/oauth-tool
|
|
19
|
+
- lib/oauth_tool.rb
|
|
20
|
+
- oauth-tool.gemspec
|
|
21
|
+
homepage: https://probable-octo-winner.fly.dev
|
|
22
|
+
licenses:
|
|
23
|
+
- MIT
|
|
24
|
+
metadata: {}
|
|
25
|
+
rdoc_options: []
|
|
26
|
+
require_paths:
|
|
27
|
+
- lib
|
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '3.0'
|
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
requirements: []
|
|
39
|
+
rubygems_version: 3.6.2
|
|
40
|
+
specification_version: 4
|
|
41
|
+
summary: OAuth device authorization CLI
|
|
42
|
+
test_files: []
|