11use anyhow:: Result ;
2+ use reqwest:: header:: { HeaderValue , AUTHORIZATION , CONTENT_TYPE } ;
3+ use serde_json:: Value ;
24
3- pub fn execute ( ) -> Result < ( ) > {
5+ use crate :: scopes;
6+
7+ pub async fn execute ( ) -> Result < ( ) > {
48 println ! ( "openapi-cli v{}" , env!( "CARGO_PKG_VERSION" ) ) ;
59 println ! ( ) ;
610
7- let username = std:: env:: var ( "OPENAPI_USERNAME" ) . ok ( ) ;
8- let key = std:: env:: var ( "OPENAPI_KEY" ) . ok ( ) ;
9- let sandbox_key = std:: env:: var ( "OPENAPI_SANDBOX_KEY" ) . ok ( ) ;
11+ let token = std:: env:: var ( "OPENAPI_TOKEN" ) . ok ( ) ;
12+ let sandbox_token = std:: env:: var ( "OPENAPI_SANDBOX_TOKEN" ) . ok ( ) ;
1013
11- let has_username = username. as_ref ( ) . is_some_and ( |v| !v. is_empty ( ) ) ;
12- let has_key = key. as_ref ( ) . is_some_and ( |v| !v. is_empty ( ) ) ;
13- let has_sandbox_key = sandbox_key. as_ref ( ) . is_some_and ( |v| !v. is_empty ( ) ) ;
14+ let has_token = token. as_ref ( ) . is_some_and ( |v| !v. is_empty ( ) ) ;
15+ let has_sandbox_token = sandbox_token. as_ref ( ) . is_some_and ( |v| !v. is_empty ( ) ) ;
1416
1517 // Show variable status
1618 println ! ( "Environment variables:" ) ;
17- print_var_status ( "OPENAPI_USERNAME" , has_username, & username) ;
18- print_var_status ( "OPENAPI_KEY" , has_key, & key) ;
19- print_var_status ( "OPENAPI_SANDBOX_KEY" , has_sandbox_key, & sandbox_key) ;
19+ print_var_status ( "OPENAPI_TOKEN" , has_token, & token) ;
20+ print_var_status ( "OPENAPI_SANDBOX_TOKEN" , has_sandbox_token, & sandbox_token) ;
2021 println ! ( ) ;
2122
2223 // Readiness assessment
23- if has_username && has_key && has_sandbox_key {
24+ if has_token && has_sandbox_token {
2425 println ! ( "Status: READY" ) ;
2526 println ! ( " Production and sandbox environments are both available." ) ;
26- } else if has_username && has_key {
27+ } else if has_token {
2728 println ! ( "Status: READY (production only)" ) ;
2829 println ! ( " Production environment is available." ) ;
29- println ! ( " Set OPENAPI_SANDBOX_KEY to enable sandbox mode (-S)." ) ;
30- } else if has_username && has_sandbox_key {
30+ println ! ( " Set OPENAPI_SANDBOX_TOKEN to enable sandbox mode (-S)." ) ;
31+ } else if has_sandbox_token {
3132 println ! ( "Status: SANDBOX ONLY" ) ;
3233 println ! ( " Only the sandbox environment is available (use -S flag)." ) ;
33- println ! ( " Set OPENAPI_KEY to enable production mode." ) ;
34+ println ! ( " Set OPENAPI_TOKEN to enable production mode." ) ;
3435 } else {
3536 println ! ( "Status: NOT CONFIGURED" ) ;
3637 println ! ( " The CLI cannot operate. Set the required environment variables:" ) ;
37- if !has_username {
38- println ! ( " export OPENAPI_USERNAME=\" your-username\" " ) ;
38+ println ! ( " export OPENAPI_TOKEN=\" your-api-token\" " ) ;
39+ println ! ( " export OPENAPI_SANDBOX_TOKEN=\" your-sandbox-token\" (optional)" ) ;
40+ }
41+
42+ // Show token scopes if tokens are available
43+ if has_token {
44+ println ! ( ) ;
45+ println ! ( "Production token scopes:" ) ;
46+ match fetch_token_scopes ( token. as_ref ( ) . unwrap ( ) , false ) . await {
47+ Ok ( token_scopes) if token_scopes. is_empty ( ) => {
48+ println ! ( " (no scopes)" ) ;
49+ }
50+ Ok ( token_scopes) => {
51+ print ! ( "{}" , scopes:: group_scopes_by_service( & token_scopes, false ) ) ;
52+ }
53+ Err ( e) => {
54+ println ! ( " Unable to retrieve ({})" , e) ;
55+ }
3956 }
40- if !has_key && !has_sandbox_key {
41- println ! ( " export OPENAPI_KEY=\" your-api-key\" " ) ;
42- println ! ( " export OPENAPI_SANDBOX_KEY=\" your-sandbox-key\" (optional)" ) ;
57+ }
58+
59+ if has_sandbox_token {
60+ println ! ( ) ;
61+ println ! ( "Sandbox token scopes:" ) ;
62+ match fetch_token_scopes ( sandbox_token. as_ref ( ) . unwrap ( ) , true ) . await {
63+ Ok ( token_scopes) if token_scopes. is_empty ( ) => {
64+ println ! ( " (no scopes)" ) ;
65+ }
66+ Ok ( token_scopes) => {
67+ print ! ( "{}" , scopes:: group_scopes_by_service( & token_scopes, true ) ) ;
68+ }
69+ Err ( e) => {
70+ println ! ( " Unable to retrieve ({})" , e) ;
71+ }
4372 }
4473 }
4574
4675 Ok ( ( ) )
4776}
4877
78+ async fn fetch_token_scopes ( token : & str , sandbox : bool ) -> Result < Vec < String > > {
79+ let base = if sandbox {
80+ "https://test.oauth.openapi.it"
81+ } else {
82+ "https://oauth.openapi.it"
83+ } ;
84+ let url = format ! ( "{}/token/{}" , base, token) ;
85+
86+ let mut headers = reqwest:: header:: HeaderMap :: new ( ) ;
87+ headers. insert ( CONTENT_TYPE , HeaderValue :: from_static ( "application/json" ) ) ;
88+ headers. insert (
89+ AUTHORIZATION ,
90+ HeaderValue :: from_str ( & format ! ( "Bearer {}" , token) ) ?,
91+ ) ;
92+
93+ let client = reqwest:: Client :: builder ( )
94+ . default_headers ( headers)
95+ . build ( ) ?;
96+
97+ let resp = client. get ( & url) . send ( ) . await ?;
98+ let status = resp. status ( ) ;
99+ let body: Value = resp. json ( ) . await ?;
100+
101+ if !status. is_success ( ) {
102+ let msg = body[ "message" ] . as_str ( ) . unwrap_or ( "unknown error" ) ;
103+ anyhow:: bail!( "{}" , msg) ;
104+ }
105+
106+ // Response: { "data": [{ "scopes": [...], "token": "...", "expire": ... }], "success": true }
107+ let scopes = body[ "data" ]
108+ . as_array ( )
109+ . and_then ( |arr| arr. first ( ) )
110+ . and_then ( |entry| entry[ "scopes" ] . as_array ( ) )
111+ . map ( |arr| {
112+ arr. iter ( )
113+ . filter_map ( |v| v. as_str ( ) . map ( String :: from) )
114+ . collect ( )
115+ } )
116+ . unwrap_or_default ( ) ;
117+
118+ Ok ( scopes)
119+ }
120+
49121fn print_var_status ( name : & str , is_set : bool , value : & Option < String > ) {
50122 if is_set {
51123 let v = value. as_ref ( ) . unwrap ( ) ;
@@ -54,8 +126,8 @@ fn print_var_status(name: &str, is_set: bool, value: &Option<String>) {
54126 } else {
55127 "*" . repeat ( v. len ( ) )
56128 } ;
57- println ! ( " {:<25 } SET ({})" , name, masked) ;
129+ println ! ( " {:<30 } SET ({})" , name, masked) ;
58130 } else {
59- println ! ( " {:<25 } NOT SET" , name) ;
131+ println ! ( " {:<30 } NOT SET" , name) ;
60132 }
61133}
0 commit comments