128 lines
3.3 KiB
Rust
128 lines
3.3 KiB
Rust
![]() |
pub mod images;
|
||
|
|
||
|
use super::AuthProps;
|
||
|
use crate::{
|
||
|
State, get_user_from_token,
|
||
|
model::{ApiReturn, Error, auth::User},
|
||
|
};
|
||
|
use axum::{
|
||
|
Extension, Json,
|
||
|
http::{HeaderMap, HeaderValue},
|
||
|
response::IntoResponse,
|
||
|
};
|
||
|
use axum_extra::extract::CookieJar;
|
||
|
|
||
|
/// `/api/v1/auth/register`
|
||
|
pub async fn register_request(
|
||
|
headers: HeaderMap,
|
||
|
jar: CookieJar,
|
||
|
Extension(data): Extension<State>,
|
||
|
Json(props): Json<AuthProps>,
|
||
|
) -> impl IntoResponse {
|
||
|
let data = &(data.read().await).0;
|
||
|
let user = get_user_from_token!((jar, data) <optional>);
|
||
|
|
||
|
if user.is_some() {
|
||
|
return (
|
||
|
None,
|
||
|
Json(ApiReturn {
|
||
|
ok: false,
|
||
|
message: Error::AlreadyAuthenticated.to_string(),
|
||
|
payload: (),
|
||
|
}),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// get real ip
|
||
|
let real_ip = headers
|
||
|
.get(data.0.security.real_ip_header.to_owned())
|
||
|
.unwrap_or(&HeaderValue::from_static(""))
|
||
|
.to_str()
|
||
|
.unwrap_or("")
|
||
|
.to_string();
|
||
|
|
||
|
// ...
|
||
|
let mut user = User::new(props.username, props.password);
|
||
|
let (initial_token, t) = User::create_token(&real_ip);
|
||
|
user.tokens.push(t);
|
||
|
|
||
|
// return
|
||
|
match data.create_user(user).await {
|
||
|
Ok(_) => (
|
||
|
Some([(
|
||
|
"Set-Cookie",
|
||
|
format!(
|
||
|
"__Secure-atto-token={}; SameSite=Lax; Secure; Path=/; HostOnly=true; HttpOnly=true; Max-Age={}",
|
||
|
initial_token,
|
||
|
60 * 60 * 24 * 365
|
||
|
),
|
||
|
)]),
|
||
|
Json(ApiReturn {
|
||
|
ok: true,
|
||
|
message: "User created".to_string(),
|
||
|
payload: (),
|
||
|
}),
|
||
|
),
|
||
|
Err(e) => (None, Json(e.into())),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// `/api/v1/auth/login`
|
||
|
pub async fn login_request(
|
||
|
headers: HeaderMap,
|
||
|
jar: CookieJar,
|
||
|
Extension(data): Extension<State>,
|
||
|
Json(props): Json<AuthProps>,
|
||
|
) -> impl IntoResponse {
|
||
|
let data = &(data.read().await).0;
|
||
|
let user = get_user_from_token!((jar, data) <optional>);
|
||
|
|
||
|
if user.is_some() {
|
||
|
return (None, Json(Error::AlreadyAuthenticated.into()));
|
||
|
}
|
||
|
|
||
|
// get real ip
|
||
|
let real_ip = headers
|
||
|
.get(data.0.security.real_ip_header.to_owned())
|
||
|
.unwrap_or(&HeaderValue::from_static(""))
|
||
|
.to_str()
|
||
|
.unwrap_or("")
|
||
|
.to_string();
|
||
|
|
||
|
// verify password
|
||
|
let user = match data.get_user_by_username(&props.username).await {
|
||
|
Ok(ua) => ua,
|
||
|
Err(_) => return (None, Json(Error::IncorrectPassword.into())),
|
||
|
};
|
||
|
|
||
|
if !user.check_password(props.password) {
|
||
|
return (None, Json(Error::IncorrectPassword.into()));
|
||
|
}
|
||
|
|
||
|
// update tokens
|
||
|
let mut new_tokens = user.tokens.clone();
|
||
|
let (unhashed_token_id, token) = User::create_token(&real_ip);
|
||
|
new_tokens.push(token);
|
||
|
|
||
|
if let Err(e) = data.update_user_tokens(user.id, new_tokens).await {
|
||
|
return (None, Json(e.into()));
|
||
|
}
|
||
|
|
||
|
// ...
|
||
|
(
|
||
|
Some([(
|
||
|
"Set-Cookie",
|
||
|
format!(
|
||
|
"__Secure-atto-token={}; SameSite=Lax; Secure; Path=/; HostOnly=true; HttpOnly=true; Max-Age={}",
|
||
|
unhashed_token_id,
|
||
|
60 * 60 * 24 * 365
|
||
|
),
|
||
|
)]),
|
||
|
Json(ApiReturn {
|
||
|
ok: true,
|
||
|
message: unhashed_token_id,
|
||
|
payload: (),
|
||
|
}),
|
||
|
)
|
||
|
}
|