@@ -12,88 +12,23 @@ use crate::state::State;
12
12
const WEB_AUTH_URL : & str = "https://console.hop.io/cli-auth" ;
13
13
const PAT_FALLBACK_URL : & str = "https://console.hop.io/settings/pats" ;
14
14
15
- #[ derive( Debug , Parser ) ]
15
+ #[ derive( Debug , Parser , PartialEq , Default ) ]
16
16
#[ clap( about = "Login to Hop" ) ]
17
17
pub struct LoginOptions {
18
- #[ clap( name = "pat" , help = "Personal Access Token" ) ]
18
+ #[ clap( long = "pat" , help = "Personal Access Token" ) ]
19
19
pub pat : Option < String > ,
20
- }
21
-
22
- async fn request_handler (
23
- req : Request < Body > ,
24
- sender : Sender < String > ,
25
- ) -> Result < Response < Body > , Infallible > {
26
- let query = req. uri ( ) . query ( ) ;
27
-
28
- // only send if it's an actual token
29
- if let Some ( query) = query {
30
- // parse the query
31
- // since pat should be a URL safe string we can just split on '='
32
- let query: Vec < ( String , String ) > = query
33
- . split ( "&" )
34
- . map ( |s| parse_key_val ( s) . unwrap ( ) )
35
- . collect :: < Vec < _ > > ( ) ;
36
-
37
- // if query has a key called "token"
38
- if let Some ( token) = query. iter ( ) . find ( |( k, _) | k. to_owned ( ) == "token" ) {
39
- // send it to the main thread
40
- sender. send ( token. 1 . to_string ( ) ) . await . unwrap ( ) ;
41
- return Ok ( Response :: new ( "You've been authorized" . into ( ) ) ) ;
42
- }
43
- }
44
-
45
- return Ok ( Response :: builder ( )
46
- . status ( 400 )
47
- . body ( "You're not authorized" . into ( ) )
48
- . unwrap ( ) ) ;
49
- }
50
-
51
- async fn web_auth ( port : u16 ) -> Result < String , std:: io:: Error > {
52
- let ( sender, mut receiver) = channel :: < String > ( 1 ) ;
53
-
54
- let timeouter = sender. clone ( ) ;
55
-
56
- let timeout = task:: spawn ( async move {
57
- tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 120 ) ) . await ;
58
- timeouter. send ( "timeout" . to_string ( ) ) . await . unwrap ( ) ;
59
- } ) ;
60
-
61
- let service = make_service_fn ( move |_| {
62
- let sender = sender. clone ( ) ;
63
-
64
- async move {
65
- Ok :: < _ , Infallible > ( service_fn ( move |req : Request < Body > | {
66
- request_handler ( req, sender. clone ( ) )
67
- } ) )
68
- }
69
- } ) ;
70
-
71
- let address = ( [ 127 , 0 , 0 , 1 ] , port) . into ( ) ;
72
-
73
- let server = Server :: bind ( & address) . serve ( service) ;
74
-
75
- let runtime = task:: spawn ( async move {
76
- if let Err ( error) = server. await {
77
- eprintln ! ( "Server error: {}" , error) ;
78
- }
79
- timeout. abort ( ) ;
80
- } ) ;
81
-
82
- let response = receiver. recv ( ) . await ;
83
-
84
- runtime. abort ( ) ;
85
-
86
- if Some ( "timeout" . to_string ( ) ) == response {
87
- panic ! ( "Reached the 2 minute timeout" ) ;
88
- }
89
-
90
- Ok ( response. unwrap ( ) )
20
+ #[ clap( short = 'u' , long = "username" , help = "Username" ) ]
21
+ pub username : Option < String > ,
22
+ #[ clap( short = 'p' , long = "password" , help = "Password" ) ]
23
+ pub password : Option < String > ,
91
24
}
92
25
93
26
pub async fn handle_login ( options : LoginOptions , mut state : State ) -> Result < ( ) , std:: io:: Error > {
94
- let token = match options. pat {
95
- Some ( pat) => pat,
96
- None => browser_login ( ) . await ,
27
+ let token = if LoginOptions :: default ( ) == options {
28
+ browser_login ( ) . await
29
+ } else {
30
+ todo ! ( ) ;
31
+ // flags_login(options).await
97
32
} ;
98
33
99
34
// update the token assuming it's a valid PAT
@@ -143,6 +78,78 @@ async fn browser_login() -> String {
143
78
dialoguer:: Password :: new ( )
144
79
. with_prompt ( "Enter your token" )
145
80
. interact ( )
146
- . unwrap ( )
81
+ . ok ( )
82
+ . expect ( "Failed to get token" )
147
83
}
148
84
}
85
+
86
+ async fn web_auth ( port : u16 ) -> Result < String , std:: io:: Error > {
87
+ let ( sender, mut receiver) = channel :: < String > ( 1 ) ;
88
+
89
+ let timeouter = sender. clone ( ) ;
90
+
91
+ let timeout = task:: spawn ( async move {
92
+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 120 ) ) . await ;
93
+ timeouter. send ( "timeout" . to_string ( ) ) . await . unwrap ( ) ;
94
+ } ) ;
95
+
96
+ let service = make_service_fn ( move |_| {
97
+ let sender = sender. clone ( ) ;
98
+
99
+ async move {
100
+ Ok :: < _ , Infallible > ( service_fn ( move |req : Request < Body > | {
101
+ request_handler ( req, sender. clone ( ) )
102
+ } ) )
103
+ }
104
+ } ) ;
105
+
106
+ let address = ( [ 127 , 0 , 0 , 1 ] , port) . into ( ) ;
107
+
108
+ let server = Server :: bind ( & address) . serve ( service) ;
109
+
110
+ let runtime = task:: spawn ( async move {
111
+ if let Err ( error) = server. await {
112
+ eprintln ! ( "Server error: {}" , error) ;
113
+ }
114
+ timeout. abort ( ) ;
115
+ } ) ;
116
+
117
+ let response = receiver. recv ( ) . await ;
118
+
119
+ runtime. abort ( ) ;
120
+
121
+ if Some ( "timeout" . to_string ( ) ) == response {
122
+ panic ! ( "Reached the 2 minute timeout" ) ;
123
+ }
124
+
125
+ Ok ( response. unwrap ( ) )
126
+ }
127
+
128
+ async fn request_handler (
129
+ req : Request < Body > ,
130
+ sender : Sender < String > ,
131
+ ) -> Result < Response < Body > , Infallible > {
132
+ let query = req. uri ( ) . query ( ) ;
133
+
134
+ // only send if it's an actual token
135
+ if let Some ( query) = query {
136
+ // parse the query
137
+ // since pat should be a URL safe string we can just split on '='
138
+ let query: Vec < ( String , String ) > = query
139
+ . split ( "&" )
140
+ . map ( |s| parse_key_val ( s) . unwrap ( ) )
141
+ . collect :: < Vec < _ > > ( ) ;
142
+
143
+ // if query has a key called "token"
144
+ if let Some ( token) = query. iter ( ) . find ( |( k, _) | k. to_owned ( ) == "token" ) {
145
+ // send it to the main thread
146
+ sender. send ( token. 1 . to_string ( ) ) . await . unwrap ( ) ;
147
+ return Ok ( Response :: new ( "You've been authorized" . into ( ) ) ) ;
148
+ }
149
+ }
150
+
151
+ return Ok ( Response :: builder ( )
152
+ . status ( 400 )
153
+ . body ( "You're not authorized" . into ( ) )
154
+ . unwrap ( ) ) ;
155
+ }
0 commit comments