mirror of
https://github.com/perstarkse/minne.git
synced 2026-03-27 11:51:37 +01:00
working backend process for entity handling
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -3,32 +3,25 @@ use axum::{
|
|||||||
response::{IntoResponse, Redirect},
|
response::{IntoResponse, Redirect},
|
||||||
Form,
|
Form,
|
||||||
};
|
};
|
||||||
use axum_session::Session;
|
|
||||||
use axum_session_auth::AuthSession;
|
use axum_session_auth::AuthSession;
|
||||||
use axum_session_surreal::SessionSurrealPool;
|
use axum_session_surreal::SessionSurrealPool;
|
||||||
use futures::SinkExt;
|
|
||||||
use plotly::{
|
use plotly::{
|
||||||
common::{Line, Marker, Mode},
|
common::{Line, Marker, Mode},
|
||||||
layout::{Axis, Camera, LayoutScene, ProjectionType},
|
layout::{Axis, Camera, LayoutScene, ProjectionType},
|
||||||
Configuration, Layout, Plot, Scatter, Scatter3D,
|
Layout, Plot, Scatter3D,
|
||||||
};
|
};
|
||||||
use surrealdb::{engine::any::Any, Surreal};
|
use surrealdb::{engine::any::Any, Surreal};
|
||||||
use tokio::join;
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{AppError, HtmlError},
|
error::{AppError, HtmlError},
|
||||||
page_data,
|
page_data,
|
||||||
server::{
|
server::{routes::html::render_template, AppState},
|
||||||
routes::html::{render_block, render_template},
|
|
||||||
AppState,
|
|
||||||
},
|
|
||||||
storage::{
|
storage::{
|
||||||
db::{delete_item, get_item},
|
db::delete_item,
|
||||||
types::{
|
types::{
|
||||||
file_info::FileInfo, job::Job, knowledge_entity::KnowledgeEntity,
|
knowledge_entity::KnowledgeEntity, knowledge_relationship::KnowledgeRelationship,
|
||||||
knowledge_relationship::KnowledgeRelationship, text_chunk::TextChunk,
|
user::User,
|
||||||
text_content::TextContent, user::User,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -167,17 +160,14 @@ pub async fn show_edit_knowledge_entity_form(
|
|||||||
None => return Ok(Redirect::to("/signin").into_response()),
|
None => return Ok(Redirect::to("/signin").into_response()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// SORT OUT ERROR HANDLING AND VALIDATE INPUT
|
// Get the entity and validate ownership
|
||||||
let entity = get_item(&state.surreal_db_client, &id)
|
let entity = User::get_and_validate_knowledge_entity(&id, &user.id, &state.surreal_db_client)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| HtmlError::new(AppError::from(e), state.templates.clone()))?;
|
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||||
|
|
||||||
let output = render_template(
|
let output = render_template(
|
||||||
"knowledge/edit_knowledge_entity_modal.html",
|
"knowledge/edit_knowledge_entity_modal.html",
|
||||||
EntityData {
|
EntityData { entity, user },
|
||||||
entity: entity.unwrap(),
|
|
||||||
user,
|
|
||||||
},
|
|
||||||
state.templates,
|
state.templates,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -192,6 +182,7 @@ pub struct EntityListData {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct PatchKnowledgeEntityParams {
|
pub struct PatchKnowledgeEntityParams {
|
||||||
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
}
|
}
|
||||||
@@ -207,12 +198,27 @@ pub async fn patch_knowledge_entity(
|
|||||||
None => return Ok(Redirect::to("/signin").into_response()),
|
None => return Ok(Redirect::to("/signin").into_response()),
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("{:#?}", form);
|
// Get the existing entity and validate that the user is allowed
|
||||||
|
User::get_and_validate_knowledge_entity(&form.id, &user.id, &state.surreal_db_client)
|
||||||
|
.await
|
||||||
|
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||||
|
|
||||||
|
// Update the entity
|
||||||
|
KnowledgeEntity::patch(
|
||||||
|
&form.id,
|
||||||
|
&form.name,
|
||||||
|
&form.description,
|
||||||
|
&state.surreal_db_client,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| HtmlError::new(AppError::from(e), state.templates.clone()))?;
|
||||||
|
|
||||||
|
// Get updated list of entities
|
||||||
let entities = User::get_knowledge_entities(&user.id, &state.surreal_db_client)
|
let entities = User::get_knowledge_entities(&user.id, &state.surreal_db_client)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||||
|
|
||||||
|
// Render updated list
|
||||||
let output = render_template(
|
let output = render_template(
|
||||||
"knowledge/entity_list.html",
|
"knowledge/entity_list.html",
|
||||||
EntityListData { entities, user },
|
EntityListData { entities, user },
|
||||||
@@ -225,11 +231,35 @@ pub async fn patch_knowledge_entity(
|
|||||||
pub async fn delete_knowledge_entity(
|
pub async fn delete_knowledge_entity(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||||
|
Path(id): Path<String>,
|
||||||
) -> Result<impl IntoResponse, HtmlError> {
|
) -> Result<impl IntoResponse, HtmlError> {
|
||||||
// Early return if the user is not authenticated
|
// Early return if the user is not authenticated
|
||||||
let user = match auth.current_user {
|
let user = match auth.current_user {
|
||||||
Some(user) => user,
|
Some(user) => user,
|
||||||
None => return Ok(Redirect::to("/signin").into_response()),
|
None => return Ok(Redirect::to("/signin").into_response()),
|
||||||
};
|
};
|
||||||
Ok("Thanks".into_response())
|
|
||||||
|
// Get the existing entity and validate that the user is allowed
|
||||||
|
User::get_and_validate_knowledge_entity(&id, &user.id, &state.surreal_db_client)
|
||||||
|
.await
|
||||||
|
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||||
|
|
||||||
|
// Delete the entity
|
||||||
|
delete_item::<KnowledgeEntity>(&state.surreal_db_client, &id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| HtmlError::new(AppError::from(e), state.templates.clone()))?;
|
||||||
|
|
||||||
|
// Get updated list of entities
|
||||||
|
let entities = User::get_knowledge_entities(&user.id, &state.surreal_db_client)
|
||||||
|
.await
|
||||||
|
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||||
|
|
||||||
|
// Render updated list
|
||||||
|
let output = render_template(
|
||||||
|
"knowledge/entity_list.html",
|
||||||
|
EntityListData { entities, user },
|
||||||
|
state.templates,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(output.into_response())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,4 +72,29 @@ impl KnowledgeEntity {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn patch(
|
||||||
|
id: &str,
|
||||||
|
name: &str,
|
||||||
|
description: &str,
|
||||||
|
db_client: &SurrealDbClient,
|
||||||
|
) -> Result<(), AppError> {
|
||||||
|
db_client
|
||||||
|
.client
|
||||||
|
.query(
|
||||||
|
"UPDATE type::thing($table, $id)
|
||||||
|
SET name = $name,
|
||||||
|
description = $description,
|
||||||
|
updated_at = $updated_at
|
||||||
|
RETURN AFTER",
|
||||||
|
)
|
||||||
|
.bind(("table", Self::table_name()))
|
||||||
|
.bind(("id", id.to_string()))
|
||||||
|
.bind(("name", name.to_string()))
|
||||||
|
.bind(("updated_at", Utc::now()))
|
||||||
|
.bind(("description", description.to_string()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use crate::storage::types::file_info::deserialize_flexible_id;
|
|||||||
use crate::{error::AppError, storage::db::SurrealDbClient};
|
use crate::{error::AppError, storage::db::SurrealDbClient};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use surrealdb::{engine::any::Any, Surreal};
|
use surrealdb::{engine::any::Any, Surreal};
|
||||||
use tracing::{debug, info};
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use axum_session_auth::Authentication;
|
use axum_session_auth::Authentication;
|
||||||
use surrealdb::{engine::any::Any, Surreal};
|
use surrealdb::{engine::any::Any, Surreal};
|
||||||
use tracing::info;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -259,7 +258,7 @@ impl User {
|
|||||||
pub async fn update_timezone(
|
pub async fn update_timezone(
|
||||||
user_id: &str,
|
user_id: &str,
|
||||||
timezone: &str,
|
timezone: &str,
|
||||||
db: &Surreal<Any>,
|
db: &SurrealDbClient,
|
||||||
) -> Result<(), AppError> {
|
) -> Result<(), AppError> {
|
||||||
db.query("UPDATE type::thing('user', $user_id) SET timezone = $timezone")
|
db.query("UPDATE type::thing('user', $user_id) SET timezone = $timezone")
|
||||||
.bind(("table_name", User::table_name()))
|
.bind(("table_name", User::table_name()))
|
||||||
@@ -287,4 +286,19 @@ impl User {
|
|||||||
|
|
||||||
Ok(categories)
|
Ok(categories)
|
||||||
}
|
}
|
||||||
|
pub async fn get_and_validate_knowledge_entity(
|
||||||
|
id: &str,
|
||||||
|
user_id: &str,
|
||||||
|
db: &SurrealDbClient,
|
||||||
|
) -> Result<KnowledgeEntity, AppError> {
|
||||||
|
let entity: KnowledgeEntity = get_item(db, &id)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| AppError::NotFound("Entity not found".into()))?;
|
||||||
|
|
||||||
|
if entity.user_id != user_id {
|
||||||
|
return Err(AppError::Auth("Access denied".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(entity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ hx-swap="outerHTML"
|
|||||||
<input type="text" name="name" value="{{ entity.name }}" class="input input-bordered">
|
<input type="text" name="name" value="{{ entity.name }}" class="input input-bordered">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<input type="text" name="id" value="{{ entity.id }}" class="hidden">
|
||||||
|
|
||||||
<div class="form-control mt-4">
|
<div class="form-control mt-4">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text">Description</span>
|
<span class="label-text">Description</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user