use crate::db::users::{Credentials, User}; use crate::db::{sessions, users}; use crate::DatabaseConnection; use axum::extract::{FromRequest, RequestParts, TypedHeader}; use axum::headers::authorization::Bearer; use axum::headers::Authorization; use axum::http::StatusCode; use axum::{async_trait, Json}; use serde::{Deserialize, Serialize}; type AuthorizationHeader = TypedHeader>; #[async_trait] impl FromRequest for User where B: Send, { type Rejection = (StatusCode, String); async fn from_request(req: &mut RequestParts) -> Result { let conn = DatabaseConnection::from_request(req).await?; let TypedHeader(Authorization(bearer)) = AuthorizationHeader::from_request(req) .await .map_err(|_| (StatusCode::UNAUTHORIZED, "".to_string()))?; let (_session, user) = sessions::find_user_by_session(bearer.token(), &conn) .map_err(|_| (StatusCode::UNAUTHORIZED, "".to_string()))?; Ok(user) } } #[derive(Serialize, Deserialize)] pub struct UserData { pub user_id: i32, pub username: String, } impl From for UserData { fn from(user: User) -> Self { UserData { user_id: user.id, username: user.username, } } } #[derive(Deserialize)] pub struct RegistrationParams { pub username: String, pub password: String, } pub async fn register( conn: DatabaseConnection, params: Json, ) -> Json { let credentials = Credentials { username: ¶ms.username, password: ¶ms.password, }; let user = users::create_user(&credentials, &conn).unwrap(); Json(user.into()) } #[derive(Deserialize)] pub struct LoginParams { pub username: String, pub password: String, } pub async fn login( conn: DatabaseConnection, params: Json, ) -> Result { let credentials = Credentials { username: ¶ms.username, password: ¶ms.password, }; // TODO: handle failures let authenticated = users::authenticate_user(&credentials, &conn); match authenticated { None => Err(StatusCode::FORBIDDEN), Some(user) => { let session = sessions::create_session(&user, &conn); Ok(session.token) } } } pub async fn current_user(user: User) -> Json { Json(user.into()) }