110 lines
3.3 KiB
Rust
110 lines
3.3 KiB
Rust
use axum::{Extension, Json, extract::State, http::StatusCode, response::IntoResponse};
|
|
use axum_extra::extract::cookie::CookieJar;
|
|
use serde_json::json;
|
|
|
|
use crate::{
|
|
auth::{AuthenticatedSession, cleared_session_cookie, extract_session_token, session_cookie},
|
|
error::ApiError,
|
|
service::{
|
|
ChangePasswordPayload, LoginPayload, UpdateCurrentWorkspacePayload, UpdateProfilePayload,
|
|
},
|
|
state::AppState,
|
|
};
|
|
|
|
pub async fn login(
|
|
State(state): State<AppState>,
|
|
jar: CookieJar,
|
|
Json(payload): Json<LoginPayload>,
|
|
) -> Result<impl IntoResponse, ApiError> {
|
|
let (session_data, session) = state.service.login(payload).await?;
|
|
let cookie_value = format!(
|
|
"{}.{}",
|
|
session_data.session_id.as_str(),
|
|
session_data.value
|
|
);
|
|
let jar = jar.add(session_cookie(state.service.auth_settings(), &cookie_value));
|
|
|
|
Ok((jar, Json(serde_json::json!(session))))
|
|
}
|
|
|
|
pub async fn logout(
|
|
State(state): State<AppState>,
|
|
jar: CookieJar,
|
|
) -> Result<impl IntoResponse, ApiError> {
|
|
if let Some((session_id, session_value)) = extract_session_token(&jar) {
|
|
state.service.logout(&session_id, &session_value).await?;
|
|
}
|
|
|
|
let jar = jar.remove(cleared_session_cookie(state.service.auth_settings()));
|
|
Ok((jar, StatusCode::NO_CONTENT))
|
|
}
|
|
|
|
pub async fn get_session(
|
|
State(state): State<AppState>,
|
|
jar: CookieJar,
|
|
) -> Result<Json<serde_json::Value>, ApiError> {
|
|
let (session_id, session_value) = extract_session_token(&jar)
|
|
.ok_or_else(|| ApiError::unauthorized("authentication required"))?;
|
|
let session = state
|
|
.service
|
|
.session_response(&session_id, &session_value)
|
|
.await?
|
|
.ok_or_else(|| ApiError::unauthorized("session is invalid or expired"))?;
|
|
|
|
Ok(Json(serde_json::json!(session)))
|
|
}
|
|
|
|
pub async fn get_profile(
|
|
Extension(session): Extension<AuthenticatedSession>,
|
|
) -> Result<Json<serde_json::Value>, ApiError> {
|
|
Ok(Json(json!({
|
|
"user": session.user,
|
|
"memberships": session.memberships,
|
|
"current_workspace_id": session.current_workspace_id
|
|
})))
|
|
}
|
|
|
|
pub async fn update_profile(
|
|
State(state): State<AppState>,
|
|
Extension(session): Extension<AuthenticatedSession>,
|
|
Json(payload): Json<UpdateProfilePayload>,
|
|
) -> Result<Json<serde_json::Value>, ApiError> {
|
|
let updated = state
|
|
.service
|
|
.update_profile(
|
|
&session.user.id,
|
|
session.current_workspace_id.as_ref(),
|
|
payload,
|
|
)
|
|
.await?;
|
|
Ok(Json(json!(updated)))
|
|
}
|
|
|
|
pub async fn update_current_workspace(
|
|
State(state): State<AppState>,
|
|
Extension(session): Extension<AuthenticatedSession>,
|
|
Json(payload): Json<UpdateCurrentWorkspacePayload>,
|
|
) -> Result<Json<serde_json::Value>, ApiError> {
|
|
let updated = state
|
|
.service
|
|
.set_current_workspace(
|
|
&session.session_id,
|
|
&session.user.id,
|
|
&payload.workspace_id.as_str().into(),
|
|
)
|
|
.await?;
|
|
Ok(Json(json!(updated)))
|
|
}
|
|
|
|
pub async fn change_password(
|
|
State(state): State<AppState>,
|
|
Extension(session): Extension<AuthenticatedSession>,
|
|
Json(payload): Json<ChangePasswordPayload>,
|
|
) -> Result<StatusCode, ApiError> {
|
|
state
|
|
.service
|
|
.change_password(&session.user.id, payload)
|
|
.await?;
|
|
Ok(StatusCode::NO_CONTENT)
|
|
}
|