this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 147 lines 5.2 kB view raw
1use crate::session::{AxumSessionStore, FlashMessage, get_flash_message, set_flash_message}; 2use crate::templates::{HtmlTemplate, login::LoginTemplate}; 3use crate::{error_response, oauth_scopes}; 4use atrium_api::agent::Agent; 5use atrium_oauth::{AuthorizeOptions, CallbackParams}; 6use axum::{ 7 extract::{Query, State}, 8 http::StatusCode, 9 response::{IntoResponse, Redirect, Response}, 10}; 11use shared::OAuthClientType; 12 13pub async fn login_page_handler( 14 mut session: AxumSessionStore, 15) -> Result<impl IntoResponse, Response> { 16 let possible_error = match get_flash_message(&mut session, "error").await? { 17 Some(FlashMessage::Error(msg)) => Some(msg), 18 _ => None, 19 }; 20 let is_logged_in = session.logged_in(); 21 22 Ok(HtmlTemplate(LoginTemplate { 23 title: "at://advent - Login", 24 error: possible_error, 25 is_logged_in, 26 })) 27} 28 29#[derive(serde::Deserialize)] 30pub struct LoginParams { 31 pub handle: String, 32} 33 34pub async fn login_handle( 35 Query(params): Query<LoginParams>, 36 State(oauth_client): State<OAuthClientType>, 37 mut session: AxumSessionStore, 38) -> Result<impl IntoResponse, Response> { 39 match atrium_api::types::string::Handle::new(params.handle.to_ascii_lowercase()) { 40 Ok(handle) => { 41 match oauth_client 42 .authorize( 43 &handle, 44 AuthorizeOptions { 45 scopes: oauth_scopes(), 46 ..Default::default() 47 }, 48 ) 49 .await 50 { 51 Ok(url) => Ok(Redirect::to(url.as_str())), 52 Err(err) => { 53 log::error!("Error generating OAuth URL: {err}"); 54 set_flash_message( 55 &mut session, 56 "error", 57 FlashMessage::Error("Error creating login URL".to_string()), 58 ) 59 .await?; 60 Err(error_response( 61 StatusCode::INTERNAL_SERVER_ERROR, 62 "Error creating login URL", 63 )) 64 } 65 } 66 } 67 Err(err) => { 68 log::error!("Error parsing the handle: {err}"); 69 set_flash_message( 70 &mut session, 71 "error", 72 FlashMessage::Error("Error parsing the handle".to_string()), 73 ) 74 .await?; 75 76 Ok(Redirect::to("/login")) 77 } 78 } 79} 80 81///End point that takes back the OAuth call back and creates a session 82pub async fn oauth_callback_handler( 83 params: Query<CallbackParams>, 84 State(oauth_client): State<OAuthClientType>, 85 mut session: AxumSessionStore, 86) -> Response { 87 let call_back_params = CallbackParams { 88 code: params.code.clone(), 89 state: params.state.clone(), 90 iss: params.iss.clone(), 91 }; 92 match oauth_client.callback(call_back_params).await { 93 Ok((bsky_session, _)) => { 94 let agent = Agent::new(bsky_session); 95 match agent.did().await { 96 Some(did) => { 97 if let Err(err) = session.set_did(did.clone().to_string()).await { 98 log::error!("Failed to write session: {err}"); 99 return error_response( 100 StatusCode::INTERNAL_SERVER_ERROR, 101 "Failed to create session", 102 ); 103 } 104 105 Redirect::permanent("/day/1").into_response() 106 } 107 None => error_response(StatusCode::INTERNAL_SERVER_ERROR, "No DID found"), 108 } 109 } 110 Err(err) => { 111 log::error!("OAuth callback error: {err}"); 112 error_response(StatusCode::INTERNAL_SERVER_ERROR, "OAuth callback failed") 113 } 114 } 115} 116 117/// Logout handler - clears session and redirects to home 118pub async fn logout_handler( 119 mut session: AxumSessionStore, 120 State(oauth_client): State<OAuthClientType>, 121) -> Result<impl IntoResponse, Response> { 122 //TODO test this and move the shared variables to a shared struct for templates like is logged in and title 123 124 match session.get_did() { 125 None => {} 126 Some(did) => { 127 //TODO lots of unwraps 128 let did = atrium_api::types::string::Did::new(did.clone()).map_err(|err| { 129 log::error!("Failed to parse DID: {err}"); 130 error_response(StatusCode::INTERNAL_SERVER_ERROR, "Failed to log out") 131 })?; 132 let client = oauth_client.restore(&did).await.map_err(|err| { 133 log::error!("Failed to restore OAuth client: {err}"); 134 error_response(StatusCode::INTERNAL_SERVER_ERROR, "Failed to log out") 135 })?; 136 let agent = Agent::new(client); 137 let _ = agent.api.com.atproto.server.delete_session().await; 138 } 139 } 140 141 session.clear_session().await.map_err(|err| { 142 log::error!("Failed to clear session: {err}"); 143 error_response(StatusCode::INTERNAL_SERVER_ERROR, "Failed to log out") 144 })?; 145 146 Ok(Redirect::to("/")) 147}