2021-12-29 16:11:27 +01:00
|
|
|
use crate::db::users::{Credentials, User};
|
2021-12-13 22:41:20 +01:00
|
|
|
use crate::db::{sessions, users};
|
2021-12-29 16:11:27 +01:00
|
|
|
use crate::DatabaseConnection;
|
|
|
|
use axum::extract::{FromRequest, RequestParts, TypedHeader};
|
|
|
|
use axum::headers::authorization::Bearer;
|
|
|
|
use axum::headers::Authorization;
|
|
|
|
use axum::http::StatusCode;
|
2022-01-04 23:24:31 +01:00
|
|
|
use axum::response::{Headers, IntoResponse, Response};
|
2021-12-29 16:11:27 +01:00
|
|
|
use axum::{async_trait, Json};
|
2021-12-13 22:41:20 +01:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
type AuthorizationHeader = TypedHeader<Authorization<Bearer>>;
|
2021-12-13 22:41:20 +01:00
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
#[async_trait]
|
|
|
|
impl<B> FromRequest<B> for User
|
|
|
|
where
|
|
|
|
B: Send,
|
|
|
|
{
|
|
|
|
type Rejection = (StatusCode, String);
|
2021-12-13 22:41:20 +01:00
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
|
|
|
let conn = DatabaseConnection::from_request(req).await?;
|
2021-12-30 23:40:37 +01:00
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
let TypedHeader(Authorization(bearer)) = AuthorizationHeader::from_request(req)
|
|
|
|
.await
|
|
|
|
.map_err(|_| (StatusCode::UNAUTHORIZED, "".to_string()))?;
|
2021-12-15 22:40:55 +01:00
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
let (_session, user) = sessions::find_user_by_session(bearer.token(), &conn)
|
|
|
|
.map_err(|_| (StatusCode::UNAUTHORIZED, "".to_string()))?;
|
2021-12-15 22:40:55 +01:00
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
Ok(user)
|
2021-12-13 22:41:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
pub struct UserData {
|
|
|
|
pub user_id: i32,
|
|
|
|
pub username: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<User> for UserData {
|
|
|
|
fn from(user: User) -> Self {
|
|
|
|
UserData {
|
2021-12-19 00:16:46 +01:00
|
|
|
user_id: user.id,
|
2021-12-13 22:41:20 +01:00
|
|
|
username: user.username,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct RegistrationParams {
|
|
|
|
pub username: String,
|
|
|
|
pub password: String,
|
|
|
|
}
|
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
pub async fn register(
|
|
|
|
conn: DatabaseConnection,
|
|
|
|
params: Json<RegistrationParams>,
|
|
|
|
) -> Json<UserData> {
|
|
|
|
let credentials = Credentials {
|
|
|
|
username: ¶ms.username,
|
|
|
|
password: ¶ms.password,
|
|
|
|
};
|
|
|
|
let user = users::create_user(&credentials, &conn).unwrap();
|
|
|
|
Json(user.into())
|
2021-12-13 22:41:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct LoginParams {
|
|
|
|
pub username: String,
|
|
|
|
pub password: String,
|
|
|
|
}
|
|
|
|
|
2022-01-04 23:24:31 +01:00
|
|
|
pub async fn login(conn: DatabaseConnection, params: Json<LoginParams>) -> Response {
|
2021-12-29 16:11:27 +01:00
|
|
|
let credentials = Credentials {
|
|
|
|
username: ¶ms.username,
|
|
|
|
password: ¶ms.password,
|
|
|
|
};
|
|
|
|
// TODO: handle failures
|
|
|
|
let authenticated = users::authenticate_user(&credentials, &conn);
|
2021-12-15 22:40:55 +01:00
|
|
|
|
2021-12-29 16:11:27 +01:00
|
|
|
match authenticated {
|
2022-01-04 23:24:31 +01:00
|
|
|
None => StatusCode::FORBIDDEN.into_response(),
|
2021-12-29 16:11:27 +01:00
|
|
|
Some(user) => {
|
|
|
|
let session = sessions::create_session(&user, &conn);
|
2022-01-04 23:24:31 +01:00
|
|
|
let user_data: UserData = user.into();
|
|
|
|
let headers = Headers(vec![("Token", &session.token)]);
|
|
|
|
|
|
|
|
(headers, Json(user_data)).into_response()
|
2021-12-29 16:11:27 +01:00
|
|
|
}
|
|
|
|
}
|
2021-12-13 22:41:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn current_user(user: User) -> Json<UserData> {
|
|
|
|
Json(user.into())
|
|
|
|
}
|