Replaces actix with axum for web, allows us to use socket.io and gives us access to the tower ecosystem of middleware breaks compatibility with our current websocket implementation, needs to be reimplemented for socket.io
97 lines
2.3 KiB
Rust
97 lines
2.3 KiB
Rust
//! `/api/v1/auth/reset-password` Endpoints for resetting user password
|
|
|
|
use std::sync::Arc;
|
|
|
|
use axum::{
|
|
Json,
|
|
extract::{Query, State},
|
|
http::StatusCode,
|
|
response::IntoResponse,
|
|
};
|
|
use chrono::{Duration, Utc};
|
|
use serde::Deserialize;
|
|
|
|
use crate::{AppState, error::Error, objects::PasswordResetToken};
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct QueryParams {
|
|
identifier: String,
|
|
}
|
|
|
|
/// `GET /api/v1/auth/reset-password` Sends password reset email to user
|
|
///
|
|
/// requires auth? no
|
|
///
|
|
/// ### Query Parameters
|
|
/// identifier: Email or username
|
|
///
|
|
/// ### Responses
|
|
/// 200 Email sent
|
|
///
|
|
/// 429 Too Many Requests
|
|
///
|
|
/// 404 Not found
|
|
///
|
|
/// 400 Bad request
|
|
///
|
|
pub async fn get(
|
|
State(app_state): State<Arc<AppState>>,
|
|
query: Query<QueryParams>,
|
|
) -> Result<impl IntoResponse, Error> {
|
|
if let Ok(password_reset_token) =
|
|
PasswordResetToken::get_with_identifier(&app_state, query.identifier.clone()).await
|
|
{
|
|
if Utc::now().signed_duration_since(password_reset_token.created_at) > Duration::hours(1) {
|
|
password_reset_token.delete(&app_state).await?;
|
|
} else {
|
|
return Err(Error::TooManyRequests(
|
|
"Please allow 1 hour before sending a new email".to_string(),
|
|
));
|
|
}
|
|
}
|
|
|
|
PasswordResetToken::new(&app_state, query.identifier.clone()).await?;
|
|
|
|
Ok(StatusCode::OK)
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct ResetPassword {
|
|
password: String,
|
|
token: String,
|
|
}
|
|
|
|
/// `POST /api/v1/auth/reset-password` Resets user password
|
|
///
|
|
/// requires auth? no
|
|
///
|
|
/// ### Request Example:
|
|
/// ```
|
|
/// json!({
|
|
/// "password": "1608c17a27f6ae3891c23d680c73ae91528f20a54dcf4973e2c3126b9734f48b7253047f2395b51bb8a44a6daa188003",
|
|
/// "token": "a3f7e29c1b8d0456e2c9f83b7a1d6e4f5028c3b9a7e1f2d5c6b8a0d3e7f4a2b"
|
|
/// });
|
|
/// ```
|
|
///
|
|
/// ### Responses
|
|
/// 200 Success
|
|
///
|
|
/// 410 Token Expired
|
|
///
|
|
/// 404 Not Found
|
|
///
|
|
/// 400 Bad Request
|
|
///
|
|
pub async fn post(
|
|
State(app_state): State<Arc<AppState>>,
|
|
reset_password: Json<ResetPassword>,
|
|
) -> Result<impl IntoResponse, Error> {
|
|
let password_reset_token =
|
|
PasswordResetToken::get(&app_state, reset_password.token.clone()).await?;
|
|
|
|
password_reset_token
|
|
.set_password(&app_state, reset_password.password.clone())
|
|
.await?;
|
|
|
|
Ok(StatusCode::OK)
|
|
}
|