tokens and more

This commit is contained in:
Mateusz Gruszczyński
2026-08-01 00:15:37 +02:00
parent 6c5232ccc5
commit 1401054c71
18 changed files with 1966 additions and 285 deletions
+24 -56
View File
@@ -14,6 +14,8 @@ pub struct CreatePadRequest {
name: String,
#[serde(default)]
password: Option<String>,
#[serde(default)]
content: Option<String>,
}
#[derive(Debug, Serialize)]
@@ -58,6 +60,7 @@ pub async fn create_pad(
) -> Result<(StatusCode, Json<CreatePadResponse>), ApiError> {
let title = validate_name(&payload.name, "Note name")?;
let password = validate_password(payload.password.as_deref())?;
let initial_content = validate_initial_content(payload.content.as_deref())?;
let base = slugify(title);
if base.is_empty() {
return Err(ApiError::bad_request(
@@ -68,26 +71,23 @@ pub async fn create_pad(
let account_user = crate::auth::optional_user(&state, &headers)
.await
.map_err(|e| ApiError::forbidden(&e.message))?;
let author = account_user.as_ref().map(|user| user.nickname.clone());
let created_by_guest_id = if account_user.is_none() {
requester_guest_id(&headers)
} else {
None
};
let pad = db::create_pad(
&state.db,
&slug,
title,
password,
created_by_guest_id,
)
.await?;
if let Some(user) = account_user {
let pad = db::create_pad(&state.db, &slug, title, password, created_by_guest_id).await?;
if let Some(user) = account_user.as_ref() {
sqlx::query(queries::get(state.db.kind(), queries::USER_ATTACH_PAD))
.bind(user.id)
.bind(&pad.slug)
.execute(state.db.pool())
.await?;
}
if let Some(content) = initial_content {
db::save_pad_revision(&state.db, pad.id, content, author.as_deref(), "[]").await?;
}
Ok((
StatusCode::CREATED,
Json(CreatePadResponse {
@@ -105,31 +105,17 @@ pub async fn pad_info(
let pad = db::find_pad(&state.db, &slug)
.await?
.ok_or_else(ApiError::not_found_note)?;
ensure_private_resource_access(
&state,
&headers,
"pad",
&pad.slug,
pad.is_private,
)
.await?;
ensure_private_resource_access(&state, &headers, "pad", &pad.slug, pad.is_private).await?;
let (global_color, note_color) = editor_colors(&state, &headers, "pad", &slug).await?;
let (editor_preferences, personal_editor_settings) = user_editor_preferences(
&state,
&headers,
db::EditorPreferenceResource::Pad(pad.id),
)
.await?;
let (editor_preferences, personal_editor_settings) =
user_editor_preferences(&state, &headers, db::EditorPreferenceResource::Pad(pad.id))
.await?;
let resource_editor_settings =
db::load_resource_editor_settings(&state.db, "pad", &slug).await?;
let account_owner = crate::auth::is_resource_owner(
&state,
"pad",
&slug,
user_session_token(&headers),
)
.await
.unwrap_or(false);
let account_owner =
crate::auth::is_resource_owner(&state, "pad", &slug, user_session_token(&headers))
.await
.unwrap_or(false);
let guest_owner = pad_creator_is_requester(&headers, &pad);
let password_write_access = has_password_write_access(&state, &headers, "pad", &slug).await?;
let can_manage_authorship = account_owner || guest_owner || password_write_access;
@@ -432,15 +418,8 @@ async fn ensure_public_page_access(
return Ok(());
}
let password_ok = db::verify_workspace_password(&workspace, password);
check_resource_password_attempt(
state,
headers,
"workspace",
&slug,
password,
password_ok,
)
.await?;
check_resource_password_attempt(state, headers, "workspace", &slug, password, password_ok)
.await?;
if password_ok {
return Ok(());
}
@@ -462,13 +441,8 @@ pub async fn public_page(
.await?
.ok_or_else(ApiError::not_found_note)?;
ensure_public_page_access(&state, &headers, &page).await?;
let files = markdown_file_references(
&state,
page.pad_id,
page.note_id,
Some(&page.content),
)
.await?;
let files =
markdown_file_references(&state, page.pad_id, page.note_id, Some(&page.content)).await?;
Ok(Json(PublicPageResponse {
title: page.title,
content: page.content,
@@ -496,13 +470,8 @@ pub async fn update_public_task(
let page = db::update_public_task(&state.db, &token, payload.source_line, payload.checked)
.await?
.ok_or_else(ApiError::not_found_note)?;
let files = markdown_file_references(
&state,
page.pad_id,
page.note_id,
Some(&page.content),
)
.await?;
let files =
markdown_file_references(&state, page.pad_id, page.note_id, Some(&page.content)).await?;
Ok(Json(PublicPageResponse {
title: page.title,
content: page.content,
@@ -614,8 +583,7 @@ pub(super) async fn authorized_pad(
}
if pad.password_hash.is_some() && token_level < AccessLevel::Write {
let password_ok = db::verify_pad_password(&pad, password);
check_resource_password_attempt(state, headers, "pad", slug, password, password_ok)
.await?;
check_resource_password_attempt(state, headers, "pad", slug, password, password_ok).await?;
if token_level == AccessLevel::None && !password_ok {
return Err(ApiError::forbidden("Password required or incorrect."));
}