fix in db and collaborate
This commit is contained in:
+68
-21
@@ -30,6 +30,7 @@ use sha2::{Digest, Sha256};
|
||||
use slug::slugify;
|
||||
|
||||
use crate::{
|
||||
collab::{self, AppliedOperation},
|
||||
db, queries,
|
||||
state::{NoteUpdate, RoomEvent, SharedState},
|
||||
};
|
||||
@@ -301,10 +302,17 @@ pub struct ListPaginationMeta {
|
||||
total_pages: usize,
|
||||
}
|
||||
|
||||
fn default_list_page() -> usize { 1 }
|
||||
fn default_list_per_page() -> usize { 25 }
|
||||
fn default_list_page() -> usize {
|
||||
1
|
||||
}
|
||||
fn default_list_per_page() -> usize {
|
||||
25
|
||||
}
|
||||
fn normalize_list_per_page(value: usize) -> usize {
|
||||
match value { 25 | 50 | 100 => value, _ => 25 }
|
||||
match value {
|
||||
25 | 50 | 100 => value,
|
||||
_ => 25,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@@ -614,7 +622,12 @@ pub async fn open_workspace(
|
||||
search.is_empty()
|
||||
|| note.title.to_lowercase().contains(&search)
|
||||
|| note.slug.to_lowercase().contains(&search)
|
||||
|| note.created_by.as_deref().unwrap_or_default().to_lowercase().contains(&search)
|
||||
|| note
|
||||
.created_by
|
||||
.as_deref()
|
||||
.unwrap_or_default()
|
||||
.to_lowercase()
|
||||
.contains(&search)
|
||||
})
|
||||
.map(|note| {
|
||||
let stats = stats.get(¬e.id);
|
||||
@@ -658,7 +671,12 @@ pub async fn open_workspace(
|
||||
Ok(Json(WorkspaceOpenResponse {
|
||||
workspace: workspace_info_from(&workspace, access_level),
|
||||
notes,
|
||||
pagination: ListPaginationMeta { page, per_page, total, total_pages },
|
||||
pagination: ListPaginationMeta {
|
||||
page,
|
||||
per_page,
|
||||
total,
|
||||
total_pages,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1053,26 +1071,62 @@ pub async fn restore(
|
||||
.fetch_optional(state.db.pool())
|
||||
.await?;
|
||||
let content = content.ok_or_else(ApiError::not_found_revision)?;
|
||||
let room_key = crate::state::AppState::note_room_key(&workspace_slug, ¬e_slug);
|
||||
let channel = state.note_channel(&workspace_slug, ¬e_slug).await;
|
||||
let collaboration_snapshot = db::note_collaboration_snapshot(&state.db, note.id).await?;
|
||||
let collaborative_document = state
|
||||
.collaborative_document(
|
||||
&room_key,
|
||||
collaboration_snapshot.content,
|
||||
collaboration_snapshot.owner_map,
|
||||
collaboration_snapshot.revision_id,
|
||||
)
|
||||
.await;
|
||||
let mut document = collaborative_document.lock().await;
|
||||
let base_revision_id = document.revision_id;
|
||||
let operation =
|
||||
collab::replace_operation(document.content.encode_utf16().count(), content, Vec::new());
|
||||
let (content, owner_map) = collab::apply_operation_to_document(
|
||||
&document.content,
|
||||
&document.owner_map,
|
||||
&operation,
|
||||
&[],
|
||||
)
|
||||
.map_err(|_| ApiError::bad_request("The selected revision could not be restored"))?;
|
||||
let (revision_id, updated_at) = db::save_revision(
|
||||
&state.db,
|
||||
note.id,
|
||||
workspace.id,
|
||||
&content,
|
||||
Some("restore"),
|
||||
"[]",
|
||||
&owner_map,
|
||||
)
|
||||
.await?;
|
||||
let update_id = u64::try_from(revision_id).unwrap_or_default().max(1);
|
||||
let applied = AppliedOperation {
|
||||
base_revision_id,
|
||||
revision_id,
|
||||
client_id: "server_restore".into(),
|
||||
update_id,
|
||||
operation: operation.clone(),
|
||||
owner_replacements: Vec::new(),
|
||||
};
|
||||
document.content.clone_from(&content);
|
||||
document.owner_map.clone_from(&owner_map);
|
||||
document.revision_id = revision_id;
|
||||
document.record(applied);
|
||||
let update = NoteUpdate {
|
||||
content,
|
||||
base_revision_id,
|
||||
revision_id,
|
||||
updated_at,
|
||||
author: Some("restore".into()),
|
||||
owner_map: "[]".into(),
|
||||
client_id: "server_restore".into(),
|
||||
update_id,
|
||||
operation,
|
||||
owner_replacements: Vec::new(),
|
||||
};
|
||||
let _ = state
|
||||
.note_channel(&workspace_slug, ¬e_slug)
|
||||
.await
|
||||
.send(RoomEvent::Document(update));
|
||||
let _ = channel.send(RoomEvent::Document(update));
|
||||
drop(document);
|
||||
Ok(Json(serde_json::json!({"ok": true})))
|
||||
}
|
||||
|
||||
@@ -1217,15 +1271,8 @@ async fn effective_header_access_level(
|
||||
is_private: i64,
|
||||
password_protected: bool,
|
||||
) -> Result<AccessLevel, ApiError> {
|
||||
let mut level = request_access_level(
|
||||
state,
|
||||
headers,
|
||||
kind,
|
||||
slug,
|
||||
None,
|
||||
bearer_token(headers),
|
||||
)
|
||||
.await?;
|
||||
let mut level =
|
||||
request_access_level(state, headers, kind, slug, None, bearer_token(headers)).await?;
|
||||
if is_private == 0 && !password_protected {
|
||||
level = std::cmp::max(level, AccessLevel::Write);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user