11use axum:: extract:: State ;
2- use axum:: response:: { Html , IntoResponse , Redirect } ;
2+ use axum:: response:: { Html , IntoResponse } ;
33use axum:: routing:: get;
44use axum:: { Form , Router } ;
55use radicle:: crypto:: { PublicKey , Signature } ;
@@ -35,41 +35,13 @@ async fn oauth_page_handler(
3535 State ( ctx) : State < Context > ,
3636 Query ( prms) : Query < OauthPageParams > ,
3737) -> impl IntoResponse {
38- let alias = & ctx. profile . config . node . alias . to_string ( ) ;
39- let nid = & ctx. profile . public_key . to_string ( ) ;
4038 if prms. callback_url . is_none ( ) {
4139 return Html ( String :: from ( "Invalid callback URL" ) ) ;
4240 }
41+ let alias = & ctx. profile . config . node . alias . to_string ( ) ;
42+ let nid = & ctx. profile . public_key . to_string ( ) ;
4343 let cb = prms. callback_url . unwrap_or_default ( ) ;
44- Html ( String :: from (
45- "<!DOCTYPE html><html lang=\" en\" >
46- <head>
47- <title>$alias Radicle HTTP API OAuth Page</title>
48- </head>
49- <body style=\" background-color:#0a0d10;margin:0;\" >
50- <form method=\" POST\" >
51- <div style=\" background-image:url('https://app.radicle.xyz/images/default-seed-header.png');border-bottom:1px solid;height:18rem;background-position:center;background-size:cover;\" ></div>
52- <div style=\" max-width:500px;margin-left:auto;margin-right:auto;margin-top:25px;\" >
53- <div style=\" height:12rem;border:1px solid #2e2f38;border-radius:4px;background-color:#14151a;padding:.75rem 1rem;position:relative;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;\" >
54- <div class=\" title\" style=\" display:flex;flex-direction:column;gap:.125rem;position:relative;\" >
55- <div class=\" headline-and-badges\" style=\" display:flex;justify-content:space-between;gap:.5rem;\" >
56- <h4 style=\" margin:0;color:rgb(249,249,251);line-clamp:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;\" >Radicle HTTP API</h4>
57- <img width=\" 24\" height=\" 24\" class=\" logo\" alt=\" Radicle logo\" src=\" https://app.radicle.xyz/radicle.svg\" style=\" margin:0px 0.5rem;\" >
58- </div>
59- <p class=\" txt-small\" style=\" margin:0;color:#9b9bb1;\" >Running on $alias</p>
60- <p class=\" txt-small\" style=\" margin:0;color:#9b9bb1;\" >$nid</p>
61- </div>
62- <div class=\" wrapper\" style=\" display:flex;flex-direction:column;margin:25px 0 0 0;position:relative;flex:1;align-items:start;height:2.5rem;\" >
63- <label for=\" session_id\" class=\" txt-small\" style=\" margin:0;color:#9b9bb1;\" >Fill in your session ID</label>
64- <input type=\" text\" id=\" session_id\" name=\" session_id\" placeholder=\" Your session ID...\" autocomplete=\" off\" required spellcheck=\" false\" style=\" background:#000;font-family:inherit;font-size:0.857rem;color:#f9f9fb;border:1px solid #24252d;border-radius:2px;line-height:1.6;outline:none;text-overflow:ellipsis;width:95%;height:auto;margin:10px 0 0 0;padding:0 10px;\" />
65- <input type=\" hidden\" id=\" callback_url\" name=\" callback_url\" value=\" $cb\" />
66- <input type=\" submit\" value=\" Submit\" style=\" margin-top:10px;\" />
67- </div>
68- </div>
69- </div>
70- </form>
71- </body>
72- </html>" ) . replace ( "$alias" , alias) . replace ( "$nid" , nid) . replace ( "$cb" , & cb) )
44+ Html ( oauth_page_html ( alias. to_owned ( ) , nid. to_owned ( ) , cb, None ) )
7345}
7446
7547#[ derive( Debug , Serialize , Deserialize ) ]
@@ -83,16 +55,80 @@ struct OauthSubmitParams {
8355
8456/// Submit oauth page and redirect back to original
8557/// `POST /oauth`
86- async fn oauth_submit_handler ( Form ( form) : Form < OauthSubmitParams > ) -> impl IntoResponse {
87- let mut redir_url = form. callback_url ;
88- if redir_url. contains ( "?" ) {
89- redir_url. push ( '^' ) ;
58+ async fn oauth_submit_handler (
59+ State ( ctx) : State < Context > ,
60+ Form ( form) : Form < OauthSubmitParams > ,
61+ ) -> impl IntoResponse {
62+ let res = crate :: api:: auth:: validate ( & ctx, & form. session_id ) . await ;
63+ if res. is_err ( ) {
64+ let alias = & ctx. profile . config . node . alias . to_string ( ) ;
65+ let nid = & ctx. profile . public_key . to_string ( ) ;
66+ Html ( oauth_page_html (
67+ alias. to_owned ( ) ,
68+ nid. to_owned ( ) ,
69+ form. callback_url ,
70+ Some ( "The Session ID you entered was invalid" . to_string ( ) ) ,
71+ ) )
9072 } else {
91- redir_url . push ( '?' ) ;
73+ Html ( oauth_auto_submit_form ( form . callback_url , form . session_id ) )
9274 }
93- redir_url. push_str ( "session_id=" ) ;
94- redir_url. push_str ( & form. session_id ) ;
95- Redirect :: temporary ( & redir_url)
75+ }
76+
77+ fn oauth_page_html ( alias : String , nid : String , cb : String , err : Option < String > ) -> String {
78+ let err_msg = err. unwrap_or ( "" . to_string ( ) ) ;
79+ format ! (
80+ r#"
81+ <!DOCTYPE html><html lang="en">
82+ <head>
83+ <title>{alias} Radicle HTTP API OAuth Page</title>
84+ </head>
85+ <body style="background-color:#0a0d10;margin:0;">
86+ <form method="POST">
87+ <div style="background-image:url('https://app.radicle.xyz/images/default-seed-header.png');border-bottom:1px solid;height:18rem;background-position:center;background-size:cover;"></div>
88+ <div style="max-width:500px;margin-left:auto;margin-right:auto;margin-top:25px;">
89+ <div style="/*height:12rem;*/border:1px solid #2e2f38;border-radius:4px;background-color:#14151a;padding:.75rem 1rem;position:relative;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;">
90+ <div class="title" style="display:flex;flex-direction:column;gap:.125rem;position:relative;">
91+ <div class="headline-and-badges" style="display:flex;justify-content:space-between;gap:.5rem;">
92+ <h4 style="margin:0;color:rgb(249,249,251);line-clamp:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">Radicle HTTP API</h4>
93+ <img width="24" height="24" class="logo" alt="Radicle logo" src="https://app.radicle.xyz/radicle.svg" style="margin:0px 0.5rem;">
94+ </div>
95+ <p class="txt-small" style="margin:0;color:#9b9bb1;">Running on {alias}</p>
96+ <p class="txt-small" style="margin:0;color:#9b9bb1;">{nid}</p>
97+ </div>
98+ <div class="err" style="margin:25px 0 0 0;color:#Fb9b91;">
99+ {err_msg}
100+ </div>
101+ <div class="wrapper" style="display:flex;flex-direction:column;margin:25px 0 0 0;position:relative;flex:1;align-items:start;height:2.5rem;">
102+ <label for="session_id" class="txt-small" style="margin:0;color:#9b9bb1;">Fill in your session ID</label>
103+ <input type="text" id="session_id" name="session_id" placeholder="Your session ID..." autocomplete="off" required spellcheck="false" style="background:#000;font-family:inherit;font-size:0.857rem;color:#f9f9fb;border:1px solid #24252d;border-radius:2px;line-height:1.6;outline:none;text-overflow:ellipsis;width:95%;height:auto;margin:10px 0 0 0;padding:0 10px;">
104+ <input type="hidden" id="callback_url" name="callback_url" value="{cb}" />
105+ <input type="submit" value="Submit" style="margin-top:10px;">
106+ </div>
107+ </div>
108+ </div>
109+ </form>
110+ </body>
111+ </html>
112+ "# ,
113+ )
114+ }
115+
116+ fn oauth_auto_submit_form ( cb : String , session_id : String ) -> String {
117+ format ! (
118+ r#"
119+ <html>
120+ <head>
121+ <title>Radicle HTTP API OAuth</title>
122+ <meta http-equiv="refresh" content="0; URL=#" />
123+ </head>
124+ <body onload="document.frm.submit()">
125+ <form name="frm" action="{cb}" method="POST" style="display:none;">
126+ <input type="hidden" name="code" value="{session_id}" />
127+ </form>
128+ </body>
129+ </html>
130+ "# ,
131+ )
96132}
97133
98134#[ cfg( test) ]
0 commit comments