mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-03 16:41:27 +01:00
Single-user diary served as one Rust binary with the Svelte frontend embedded. - axum 0.8 + SQLite (sqlx), migrations run at startup - stateless HMAC session cookie; credentials from .env, compared in constant time - FTS5 full-text search, user input rewritten into quoted prefix terms - media uploads linked to entries by scanning bodies for /api/media/<id>, which scopes share-token media access and entry deletion - unguessable share links (192-bit token) serving a public read-only page - vim keybindings via CodeMirror plus a modal browse layer and : command line; disabled on touch devices
51 lines
1.2 KiB
Rust
51 lines
1.2 KiB
Rust
use axum::{
|
|
extract::State,
|
|
http::{header, StatusCode},
|
|
response::IntoResponse,
|
|
Json,
|
|
};
|
|
use serde::Deserialize;
|
|
use serde_json::json;
|
|
|
|
use crate::{
|
|
auth::{self, Session},
|
|
error::{AppError, AppResult},
|
|
state::AppState,
|
|
};
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct LoginRequest {
|
|
pub username: String,
|
|
pub password: String,
|
|
}
|
|
|
|
pub async fn login(
|
|
State(state): State<AppState>,
|
|
Json(body): Json<LoginRequest>,
|
|
) -> AppResult<impl IntoResponse> {
|
|
if !auth::credentials_match(&state.config, &body.username, &body.password) {
|
|
return Err(AppError::BadRequest("invalid credentials".into()));
|
|
}
|
|
let token = auth::issue_token(&state.config);
|
|
Ok((
|
|
StatusCode::OK,
|
|
[(
|
|
header::SET_COOKIE,
|
|
auth::session_cookie(&state.config, &token),
|
|
)],
|
|
Json(json!({ "user": state.config.username })),
|
|
))
|
|
}
|
|
|
|
pub async fn logout(State(state): State<AppState>) -> impl IntoResponse {
|
|
(
|
|
StatusCode::OK,
|
|
[(header::SET_COOKIE, auth::clear_cookie(&state.config))],
|
|
Json(json!({ "ok": true })),
|
|
)
|
|
}
|
|
|
|
pub async fn me(_: Session, State(state): State<AppState>) -> impl IntoResponse {
|
|
Json(json!({ "user": state.config.username }))
|
|
}
|