From cc390ee36cf02b02edbabc6a354c612608319cf7 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 11:25:31 +0800 Subject: [PATCH 01/13] add api Signed-off-by: xxs-wallace --- ee/tabby-schema/graphql/schema.graphql | 41 +++++++++++++ ee/tabby-schema/src/schema/mod.rs | 1 + ee/tabby-schema/src/schema/web_documents.rs | 64 +++++++++++++++++++++ ee/tabby-webserver/src/service/mod.rs | 1 - 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 ee/tabby-schema/src/schema/web_documents.rs diff --git a/ee/tabby-schema/graphql/schema.graphql b/ee/tabby-schema/graphql/schema.graphql index 667c3e145b9..76ce3d0d591 100644 --- a/ee/tabby-schema/graphql/schema.graphql +++ b/ee/tabby-schema/graphql/schema.graphql @@ -475,6 +475,10 @@ type Mutation { triggerJobRun(command: String!): ID! createWebCrawlerUrl(input: CreateWebCrawlerUrlInput!): ID! deleteWebCrawlerUrl(id: ID!): Boolean! + "requires admin" + setPresetDocumentActive(input: SetPresetDocumentActiveInput!): Boolean! + createCustomDocument(input: CreateCustomDocumentInput!): ID! + deleteCustomDocument(id: ID!): Boolean! } type NetworkSetting { @@ -566,6 +570,8 @@ type Query { Thread is public within an instance, so no need to check for ownership. """ threadMessages(threadId: ID!, after: String, before: String, first: Int, last: Int): MessageConnection! + presetWebDocument(active: Boolean!): [PresetWebDocument!]! + customWebDocument(after: String, before: String, first: Int, last: Int): CustomWebDocumentConnection! } type RefreshTokenResponse { @@ -710,3 +716,38 @@ type WebCrawlerUrlEdge { node: WebCrawlerUrl! cursor: String! } + +input CreateCustomDocumentInput { + url: String! + name: String! +} + +input SetPresetDocumentActiveInput { + name: String! + active: Boolean! +} + +type PresetWebDocument { + id: ID + name: String! + createdAt: DateTime! + jobInfo: JobInfo +} + +type CustomWebDocument { + id: ID! + name: String! + url: String! + createdAt: DateTime! + jobInfo: JobInfo! +} + +type CustomWebDocumentEdge { + node: CustomWebDocument! + cursor: String! +} + +type CustomWebDocumentConnection { + edges: [CustomWebDocumentEdge!]! + pageInfo: PageInfo! +} diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index 6d396d14be8..9b89b76954d 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -11,6 +11,7 @@ pub mod thread; pub mod user_event; pub mod web_crawler; pub mod worker; +mod web_documents; use std::sync::Arc; diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs new file mode 100644 index 00000000000..47ac94713a9 --- /dev/null +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -0,0 +1,64 @@ +use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use juniper::{GraphQLInputObject, GraphQLObject, ID}; +use validator::Validate; + +use crate::{job::JobInfo, juniper::relay::NodeType, Context, Result}; + +#[derive(GraphQLObject)] +#[graphql(context = Context)] +pub struct WebDocument { + pub url: String, + pub id: ID, + pub created_at: DateTime, + pub job_info: JobInfo, +} + +impl WebDocument { + pub fn source_id(&self) -> String { + Self::format_source_id(&self.id) + } + + pub fn format_source_id(id: &ID) -> String { + format!("web_crawler:{}", id) + } +} + +#[derive(Validate, GraphQLInputObject)] +pub struct CreateWebCrawlerUrlInput { + #[validate(url(code = "name", message = "Invalid URL"))] + pub name: String, + #[validate(url(code = "url", message = "Invalid URL"))] + pub url: String, +} + +impl NodeType for WebDocument { + type Cursor = String; + + fn cursor(&self) -> Self::Cursor { + self.id.to_string() + } + + fn connection_type_name() -> &'static str { + "WebCrawlerUrlConnection" + } + + fn edge_type_name() -> &'static str { + "WebCrawlerUrlEdge" + } +} + +#[async_trait] +pub trait WebDocumentService: Send + Sync { + async fn list_custom_web_documents( + &self, + after: Option, + before: Option, + first: Option, + last: Option, + ) -> Result>; + + async fn create_custom_web_document(&self, name: String, url: String) -> Result; + async fn delete_custom_web_document(&self, id: ID) -> Result<()>; + async fn list_preset_web_documents(&self, active: bool) -> Result<()>; +} diff --git a/ee/tabby-webserver/src/service/mod.rs b/ee/tabby-webserver/src/service/mod.rs index f9e5c10def3..a33786bd4a8 100644 --- a/ee/tabby-webserver/src/service/mod.rs +++ b/ee/tabby-webserver/src/service/mod.rs @@ -12,7 +12,6 @@ mod setting; mod thread; mod user_event; pub mod web_crawler; - use std::sync::Arc; use answer::AnswerService; From 4c5b1319244b7601439112529759febeb45a2472 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 11:26:29 +0800 Subject: [PATCH 02/13] fmt Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index 9b89b76954d..e0c9a7c95d8 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -10,8 +10,8 @@ pub mod setting; pub mod thread; pub mod user_event; pub mod web_crawler; -pub mod worker; mod web_documents; +pub mod worker; use std::sync::Arc; From f7071869b1e0fdad9121829870fbdf63f9c56752 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 11:29:11 +0800 Subject: [PATCH 03/13] refactor some name Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/web_documents.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 47ac94713a9..15c05e7bde1 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -20,7 +20,7 @@ impl WebDocument { } pub fn format_source_id(id: &ID) -> String { - format!("web_crawler:{}", id) + format!("web_document:{}", id) } } @@ -40,11 +40,11 @@ impl NodeType for WebDocument { } fn connection_type_name() -> &'static str { - "WebCrawlerUrlConnection" + "WebDocumentConnection" } fn edge_type_name() -> &'static str { - "WebCrawlerUrlEdge" + "WebDocumentEdge" } } From 45c21dcb3ca7a4833a29351df9cb0aae334521e2 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 12:21:45 +0800 Subject: [PATCH 04/13] fix generate example Signed-off-by: xxs-wallace --- ee/tabby-db/src/lib.rs | 1 + ee/tabby-schema/graphql/schema.graphql | 49 +++++------ ee/tabby-schema/src/schema/mod.rs | 81 ++++++++++++++++--- ee/tabby-schema/src/schema/web_documents.rs | 14 +++- ee/tabby-webserver/src/service/mod.rs | 13 +++ .../src/service/web_documents.rs | 46 +++++++++++ ee/tabby-webserver/src/webserver.rs | 13 +-- 7 files changed, 168 insertions(+), 49 deletions(-) create mode 100644 ee/tabby-webserver/src/service/web_documents.rs diff --git a/ee/tabby-db/src/lib.rs b/ee/tabby-db/src/lib.rs index fc91d0775ec..b4e10f9ceea 100644 --- a/ee/tabby-db/src/lib.rs +++ b/ee/tabby-db/src/lib.rs @@ -21,6 +21,7 @@ use user_completions::UserCompletionDailyStatsDAO; pub use user_events::UserEventDAO; pub use users::UserDAO; pub use web_crawler::WebCrawlerUrlDAO; +pub use web_documents::WebDocumentDAO; pub mod cache; mod email_setting; diff --git a/ee/tabby-schema/graphql/schema.graphql b/ee/tabby-schema/graphql/schema.graphql index 76ce3d0d591..67fdcafe771 100644 --- a/ee/tabby-schema/graphql/schema.graphql +++ b/ee/tabby-schema/graphql/schema.graphql @@ -99,6 +99,11 @@ input CodeSearchParamsOverrideInput { numToScore: Int } +input CreateCustomDocumentInput { + name: String! + url: String! +} + input CreateIntegrationInput { displayName: String! accessToken: String! @@ -182,6 +187,11 @@ input SecuritySettingInput { disableClientSideTelemetry: Boolean! } +input SetPresetDocumentActiveInput { + name: String! + active: Boolean! +} + input ThreadRunDebugOptionsInput { codeSearchParamsOverride: CodeSearchParamsOverrideInput = null } @@ -475,10 +485,9 @@ type Mutation { triggerJobRun(command: String!): ID! createWebCrawlerUrl(input: CreateWebCrawlerUrlInput!): ID! deleteWebCrawlerUrl(id: ID!): Boolean! - "requires admin" - setPresetDocumentActive(input: SetPresetDocumentActiveInput!): Boolean! createCustomDocument(input: CreateCustomDocumentInput!): ID! deleteCustomDocument(id: ID!): Boolean! + setPresetDocumentActive(input: SetPresetDocumentActiveInput!): ID! } type NetworkSetting { @@ -570,8 +579,8 @@ type Query { Thread is public within an instance, so no need to check for ownership. """ threadMessages(threadId: ID!, after: String, before: String, first: Int, last: Int): MessageConnection! - presetWebDocument(active: Boolean!): [PresetWebDocument!]! - customWebDocument(after: String, before: String, first: Int, last: Int): CustomWebDocumentConnection! + customWebDocuments(after: String, before: String, first: Int, last: Int): WebDocumentConnection! + presetWebDocuments(active: Boolean!): [WebDocument!]! } type RefreshTokenResponse { @@ -717,37 +726,19 @@ type WebCrawlerUrlEdge { cursor: String! } -input CreateCustomDocumentInput { +type WebDocument { url: String! - name: String! -} - -input SetPresetDocumentActiveInput { - name: String! - active: Boolean! -} - -type PresetWebDocument { - id: ID - name: String! - createdAt: DateTime! - jobInfo: JobInfo -} - -type CustomWebDocument { id: ID! - name: String! - url: String! createdAt: DateTime! jobInfo: JobInfo! } -type CustomWebDocumentEdge { - node: CustomWebDocument! - cursor: String! +type WebDocumentConnection { + edges: [WebDocumentEdge!]! + pageInfo: PageInfo! } -type CustomWebDocumentConnection { - edges: [CustomWebDocumentEdge!]! - pageInfo: PageInfo! +type WebDocumentEdge { + node: WebDocument! + cursor: String! } diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index e0c9a7c95d8..e8bb1a14418 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -10,7 +10,7 @@ pub mod setting; pub mod thread; pub mod user_event; pub mod web_crawler; -mod web_documents; +pub mod web_documents; pub mod worker; use std::sync::Arc; @@ -52,11 +52,13 @@ use self::{ }, user_event::{UserEvent, UserEventService}, web_crawler::{CreateWebCrawlerUrlInput, WebCrawlerService, WebCrawlerUrl}, + web_documents::{CreateCustomDocumentInput, WebDocumentService, WebDocument}, }; use crate::{ env, juniper::relay::{self, query_async, Connection}, }; +use crate::web_documents::SetPresetDocumentActiveInput; pub trait ServiceLocator: Send + Sync { fn auth(&self) -> Arc; @@ -72,6 +74,7 @@ pub trait ServiceLocator: Send + Sync { fn analytic(&self) -> Arc; fn user_event(&self) -> Arc; fn web_crawler(&self) -> Arc; + fn web_documents(&self) -> Arc; fn thread(&self) -> Arc; } @@ -190,7 +193,7 @@ impl Query { .await }, ) - .await + .await } async fn invitations( @@ -213,7 +216,7 @@ impl Query { .await }, ) - .await + .await } async fn job_runs( @@ -238,7 +241,7 @@ impl Query { .await }, ) - .await + .await } async fn job_run_stats(ctx: &Context, jobs: Option>) -> Result { @@ -282,7 +285,7 @@ impl Query { .await }, ) - .await + .await } /// Search files that matches the pattern in the repository. @@ -428,7 +431,7 @@ impl Query { .await }, ) - .await + .await } async fn disk_usage_stats(ctx: &Context) -> Result { @@ -463,7 +466,7 @@ impl Query { .await }, ) - .await + .await } async fn integrated_repositories( @@ -489,7 +492,7 @@ impl Query { .await }, ) - .await + .await } async fn web_crawler_urls( @@ -511,7 +514,7 @@ impl Query { .await }, ) - .await + .await } async fn threads( @@ -535,7 +538,7 @@ impl Query { .await }, ) - .await + .await } /// Read thread messages by thread ID. @@ -563,7 +566,38 @@ impl Query { .await }, ) - .await + .await + } + + async fn custom_web_documents( + ctx: &Context, + after: Option, + before: Option, + first: Option, + last: Option, + ) -> Result> { + query_async( + after, + before, + first, + last, + |after, before, first, last| async move { + ctx.locator + .web_documents() + .list_custom_web_documents(after, before, first, last) + .await + }, + ) + .await + } + async fn preset_web_documents( + ctx: &Context, + active: bool, + ) -> Result> { + ctx.locator + .web_documents() + .list_preset_web_documents(active) + .await } } @@ -917,6 +951,31 @@ impl Mutation { ctx.locator.web_crawler().delete_web_crawler_url(id).await?; Ok(true) } + + async fn create_custom_document(ctx: &Context, input: CreateCustomDocumentInput) -> Result { + input.validate()?; + let id = ctx + .locator + .web_documents() + .create_custom_web_document(input.name, input.url) + .await?; + Ok(id) + } + + async fn delete_custom_document(ctx: &Context, id: ID) -> Result { + ctx.locator.web_documents().delete_custom_web_document(id).await?; + Ok(true) + } + + async fn set_preset_document_active(ctx: &Context, input: SetPresetDocumentActiveInput) -> Result { + input.validate()?; + let id = ctx + .locator + .web_documents() + .set_preset_web_documents_active(input.name, input.active) + .await?; + Ok(id) + } } async fn check_analytic_access(ctx: &Context, users: &[ID]) -> Result<(), CoreError> { diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 15c05e7bde1..9ca4b540f83 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -25,13 +25,20 @@ impl WebDocument { } #[derive(Validate, GraphQLInputObject)] -pub struct CreateWebCrawlerUrlInput { - #[validate(url(code = "name", message = "Invalid URL"))] +pub struct CreateCustomDocumentInput { + #[validate(url(code = "name", message = "Invalid Name"))] pub name: String, #[validate(url(code = "url", message = "Invalid URL"))] pub url: String, } +#[derive(Validate, GraphQLInputObject)] +pub struct SetPresetDocumentActiveInput { + #[validate(url(code = "name", message = "Invalid Name"))] + pub name: String, + pub active: bool, +} + impl NodeType for WebDocument { type Cursor = String; @@ -60,5 +67,6 @@ pub trait WebDocumentService: Send + Sync { async fn create_custom_web_document(&self, name: String, url: String) -> Result; async fn delete_custom_web_document(&self, id: ID) -> Result<()>; - async fn list_preset_web_documents(&self, active: bool) -> Result<()>; + async fn list_preset_web_documents(&self, active: bool) -> Result>; + async fn set_preset_web_documents_active(&self, name: String, active: bool) -> Result; } diff --git a/ee/tabby-webserver/src/service/mod.rs b/ee/tabby-webserver/src/service/mod.rs index a33786bd4a8..cccd9107192 100644 --- a/ee/tabby-webserver/src/service/mod.rs +++ b/ee/tabby-webserver/src/service/mod.rs @@ -12,6 +12,8 @@ mod setting; mod thread; mod user_event; pub mod web_crawler; +pub mod web_documents; + use std::sync::Arc; use answer::AnswerService; @@ -42,6 +44,7 @@ use tabby_schema::{ thread::ThreadService, user_event::UserEventService, web_crawler::WebCrawlerService, + web_documents::WebDocumentService, worker::WorkerService, AsID, AsRowid, CoreError, Result, ServiceLocator, }; @@ -59,6 +62,7 @@ struct ServerContext { user_event: Arc, job: Arc, web_crawler: Arc, + web_documents: Arc, thread: Arc, logger: Arc, @@ -76,6 +80,7 @@ impl ServerContext { repository: Arc, integration: Arc, web_crawler: Arc, + web_documents: Arc, job: Arc, answer: Option>, db_conn: DbConn, @@ -104,6 +109,7 @@ impl ServerContext { setting.clone(), )), web_crawler, + web_documents, thread, license, repository, @@ -259,6 +265,11 @@ impl ServiceLocator for ArcServerContext { self.0.web_crawler.clone() } + + fn web_documents(&self) -> Arc { + self.0.web_documents.clone() + } + fn thread(&self) -> Arc { self.0.thread.clone() } @@ -270,6 +281,7 @@ pub async fn create_service_locator( repository: Arc, integration: Arc, web_crawler: Arc, + web_documents: Arc, job: Arc, answer: Option>, db: DbConn, @@ -282,6 +294,7 @@ pub async fn create_service_locator( repository, integration, web_crawler, + web_documents, job, answer, db, diff --git a/ee/tabby-webserver/src/service/web_documents.rs b/ee/tabby-webserver/src/service/web_documents.rs new file mode 100644 index 00000000000..0f88170729f --- /dev/null +++ b/ee/tabby-webserver/src/service/web_documents.rs @@ -0,0 +1,46 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use juniper::ID; +use tabby_db::{DbConn, WebDocumentDAO}; +use tabby_schema::{ + job::{JobInfo, JobService}, + web_documents::{WebDocumentService, WebDocument}, + AsID, AsRowid, Result, +}; + +use super::{background_job::BackgroundJobEvent, graphql_pagination_to_filter}; + +pub fn create(db: DbConn, job_service: Arc) -> impl WebDocumentService { + WebDocumentServiceImpl { db, job_service } +} + +struct WebDocumentServiceImpl { + db: DbConn, + job_service: Arc, +} + +#[async_trait] +impl WebDocumentService for WebDocumentServiceImpl { + async fn list_custom_web_documents(&self, after: Option, before: Option, first: Option, last: Option) -> Result> { + Ok(vec![]) + } + + async fn create_custom_web_document(&self, name: String, url: String) -> Result { + Ok(ID::new("0")) + } + + async fn delete_custom_web_document(&self, id: ID) -> Result<()> { + Ok(()) + } + + async fn list_preset_web_documents(&self, active: bool) -> Result> { + Ok(vec![]) + } + + + async fn set_preset_web_documents_active(&self, name: String, active: bool) -> Result { + Ok(ID::new("0")) + } +} + diff --git a/ee/tabby-webserver/src/webserver.rs b/ee/tabby-webserver/src/webserver.rs index 8fd3ae3739d..532f67fded0 100644 --- a/ee/tabby-webserver/src/webserver.rs +++ b/ee/tabby-webserver/src/webserver.rs @@ -11,17 +11,14 @@ use tabby_common::{ }; use tabby_db::DbConn; use tabby_inference::{ChatCompletionStream, Embedding}; -use tabby_schema::{ - integration::IntegrationService, job::JobService, repository::RepositoryService, - web_crawler::WebCrawlerService, -}; - +use tabby_schema::{integration::IntegrationService, job::JobService, repository::RepositoryService, web_crawler::WebCrawlerService}; +use tabby_schema::web_documents::WebDocumentService; use crate::{ path::db_file, routes, service::{ background_job, create_service_locator, event_logger::create_event_logger, integration, - job, repository, web_crawler, + job, repository, web_crawler, web_documents, }, }; @@ -31,6 +28,7 @@ pub struct Webserver { repository: Arc, integration: Arc, web_crawler: Arc, + web_documents: Arc, job: Arc, } @@ -61,6 +59,7 @@ impl Webserver { let repository = repository::create(db.clone(), integration.clone(), job.clone()); let web_crawler = Arc::new(web_crawler::create(db.clone(), job.clone())); + let web_documents = Arc::new(web_documents::create(db.clone(), job.clone())); let logger2 = create_event_logger(db.clone()); let logger = Arc::new(ComposedLogger::new(logger1, logger2)); @@ -70,6 +69,7 @@ impl Webserver { repository: repository.clone(), integration: integration.clone(), web_crawler: web_crawler.clone(), + web_documents: web_documents.clone(), job: job.clone(), }); @@ -121,6 +121,7 @@ impl Webserver { self.repository.clone(), self.integration.clone(), self.web_crawler.clone(), + self.web_documents.clone(), self.job.clone(), answer.clone(), self.db.clone(), From d5eae6acb6254570f6f219e457461051091c5c8a Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 12:30:13 +0800 Subject: [PATCH 05/13] fmt Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/mod.rs | 41 ++++++++++--------- ee/tabby-webserver/src/service/mod.rs | 1 - .../src/service/web_documents.rs | 12 ++++-- ee/tabby-webserver/src/webserver.rs | 19 +++++---- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index e8bb1a14418..dc459f51d18 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -52,13 +52,13 @@ use self::{ }, user_event::{UserEvent, UserEventService}, web_crawler::{CreateWebCrawlerUrlInput, WebCrawlerService, WebCrawlerUrl}, - web_documents::{CreateCustomDocumentInput, WebDocumentService, WebDocument}, + web_documents::{CreateCustomDocumentInput, WebDocument, WebDocumentService}, }; +use crate::web_documents::SetPresetDocumentActiveInput; use crate::{ env, juniper::relay::{self, query_async, Connection}, }; -use crate::web_documents::SetPresetDocumentActiveInput; pub trait ServiceLocator: Send + Sync { fn auth(&self) -> Arc; @@ -193,7 +193,7 @@ impl Query { .await }, ) - .await + .await } async fn invitations( @@ -216,7 +216,7 @@ impl Query { .await }, ) - .await + .await } async fn job_runs( @@ -241,7 +241,7 @@ impl Query { .await }, ) - .await + .await } async fn job_run_stats(ctx: &Context, jobs: Option>) -> Result { @@ -285,7 +285,7 @@ impl Query { .await }, ) - .await + .await } /// Search files that matches the pattern in the repository. @@ -431,7 +431,7 @@ impl Query { .await }, ) - .await + .await } async fn disk_usage_stats(ctx: &Context) -> Result { @@ -466,7 +466,7 @@ impl Query { .await }, ) - .await + .await } async fn integrated_repositories( @@ -492,7 +492,7 @@ impl Query { .await }, ) - .await + .await } async fn web_crawler_urls( @@ -514,7 +514,7 @@ impl Query { .await }, ) - .await + .await } async fn threads( @@ -538,7 +538,7 @@ impl Query { .await }, ) - .await + .await } /// Read thread messages by thread ID. @@ -566,7 +566,7 @@ impl Query { .await }, ) - .await + .await } async fn custom_web_documents( @@ -588,12 +588,9 @@ impl Query { .await }, ) - .await + .await } - async fn preset_web_documents( - ctx: &Context, - active: bool, - ) -> Result> { + async fn preset_web_documents(ctx: &Context, active: bool) -> Result> { ctx.locator .web_documents() .list_preset_web_documents(active) @@ -963,11 +960,17 @@ impl Mutation { } async fn delete_custom_document(ctx: &Context, id: ID) -> Result { - ctx.locator.web_documents().delete_custom_web_document(id).await?; + ctx.locator + .web_documents() + .delete_custom_web_document(id) + .await?; Ok(true) } - async fn set_preset_document_active(ctx: &Context, input: SetPresetDocumentActiveInput) -> Result { + async fn set_preset_document_active( + ctx: &Context, + input: SetPresetDocumentActiveInput, + ) -> Result { input.validate()?; let id = ctx .locator diff --git a/ee/tabby-webserver/src/service/mod.rs b/ee/tabby-webserver/src/service/mod.rs index cccd9107192..e36a8c33ca0 100644 --- a/ee/tabby-webserver/src/service/mod.rs +++ b/ee/tabby-webserver/src/service/mod.rs @@ -265,7 +265,6 @@ impl ServiceLocator for ArcServerContext { self.0.web_crawler.clone() } - fn web_documents(&self) -> Arc { self.0.web_documents.clone() } diff --git a/ee/tabby-webserver/src/service/web_documents.rs b/ee/tabby-webserver/src/service/web_documents.rs index 0f88170729f..ec8a6f6078a 100644 --- a/ee/tabby-webserver/src/service/web_documents.rs +++ b/ee/tabby-webserver/src/service/web_documents.rs @@ -5,7 +5,7 @@ use juniper::ID; use tabby_db::{DbConn, WebDocumentDAO}; use tabby_schema::{ job::{JobInfo, JobService}, - web_documents::{WebDocumentService, WebDocument}, + web_documents::{WebDocument, WebDocumentService}, AsID, AsRowid, Result, }; @@ -22,7 +22,13 @@ struct WebDocumentServiceImpl { #[async_trait] impl WebDocumentService for WebDocumentServiceImpl { - async fn list_custom_web_documents(&self, after: Option, before: Option, first: Option, last: Option) -> Result> { + async fn list_custom_web_documents( + &self, + after: Option, + before: Option, + first: Option, + last: Option, + ) -> Result> { Ok(vec![]) } @@ -38,9 +44,7 @@ impl WebDocumentService for WebDocumentServiceImpl { Ok(vec![]) } - async fn set_preset_web_documents_active(&self, name: String, active: bool) -> Result { Ok(ID::new("0")) } } - diff --git a/ee/tabby-webserver/src/webserver.rs b/ee/tabby-webserver/src/webserver.rs index 532f67fded0..3b1875f2b63 100644 --- a/ee/tabby-webserver/src/webserver.rs +++ b/ee/tabby-webserver/src/webserver.rs @@ -1,5 +1,13 @@ use std::sync::Arc; +use crate::{ + path::db_file, + routes, + service::{ + background_job, create_service_locator, event_logger::create_event_logger, integration, + job, repository, web_crawler, web_documents, + }, +}; use axum::Router; use tabby_common::{ api::{ @@ -11,15 +19,10 @@ use tabby_common::{ }; use tabby_db::DbConn; use tabby_inference::{ChatCompletionStream, Embedding}; -use tabby_schema::{integration::IntegrationService, job::JobService, repository::RepositoryService, web_crawler::WebCrawlerService}; use tabby_schema::web_documents::WebDocumentService; -use crate::{ - path::db_file, - routes, - service::{ - background_job, create_service_locator, event_logger::create_event_logger, integration, - job, repository, web_crawler, web_documents, - }, +use tabby_schema::{ + integration::IntegrationService, job::JobService, repository::RepositoryService, + web_crawler::WebCrawlerService, }; pub struct Webserver { From 24abcb7e00a016b24857b9fc8eddc578a38eb422 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 12:44:26 +0800 Subject: [PATCH 06/13] rename Signed-off-by: xxs-wallace --- ee/tabby-schema/graphql/schema.graphql | 25 ++++++++++++------- ee/tabby-schema/src/schema/mod.rs | 8 +++--- ee/tabby-schema/src/schema/web_documents.rs | 19 ++++++++++---- .../src/service/web_documents.rs | 10 ++++---- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/ee/tabby-schema/graphql/schema.graphql b/ee/tabby-schema/graphql/schema.graphql index 67fdcafe771..815b87d2c6e 100644 --- a/ee/tabby-schema/graphql/schema.graphql +++ b/ee/tabby-schema/graphql/schema.graphql @@ -242,6 +242,14 @@ type CompletionStats { selects: Int! } +type CustomWebDocument { + url: String! + name: String! + id: ID! + createdAt: DateTime! + jobInfo: JobInfo! +} + type DiskUsage { filepath: [String!]! "Size in kilobytes." @@ -508,6 +516,12 @@ type PageInfo { endCursor: String } +type PresetWebDocument { + name: String! + id: ID! + jobInfo: JobInfo! +} + type ProvidedRepository { id: ID! integrationId: ID! @@ -580,7 +594,7 @@ type Query { """ threadMessages(threadId: ID!, after: String, before: String, first: Int, last: Int): MessageConnection! customWebDocuments(after: String, before: String, first: Int, last: Int): WebDocumentConnection! - presetWebDocuments(active: Boolean!): [WebDocument!]! + presetWebDocuments(active: Boolean!): [PresetWebDocument!]! } type RefreshTokenResponse { @@ -726,19 +740,12 @@ type WebCrawlerUrlEdge { cursor: String! } -type WebDocument { - url: String! - id: ID! - createdAt: DateTime! - jobInfo: JobInfo! -} - type WebDocumentConnection { edges: [WebDocumentEdge!]! pageInfo: PageInfo! } type WebDocumentEdge { - node: WebDocument! + node: CustomWebDocument! cursor: String! } diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index dc459f51d18..a544b1a2cea 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -52,9 +52,9 @@ use self::{ }, user_event::{UserEvent, UserEventService}, web_crawler::{CreateWebCrawlerUrlInput, WebCrawlerService, WebCrawlerUrl}, - web_documents::{CreateCustomDocumentInput, WebDocument, WebDocumentService}, + web_documents::{CreateCustomDocumentInput, CustomWebDocument, WebDocumentService}, }; -use crate::web_documents::SetPresetDocumentActiveInput; +use crate::web_documents::{PresetWebDocument, SetPresetDocumentActiveInput}; use crate::{ env, juniper::relay::{self, query_async, Connection}, @@ -575,7 +575,7 @@ impl Query { before: Option, first: Option, last: Option, - ) -> Result> { + ) -> Result> { query_async( after, before, @@ -590,7 +590,7 @@ impl Query { ) .await } - async fn preset_web_documents(ctx: &Context, active: bool) -> Result> { + async fn preset_web_documents(ctx: &Context, active: bool) -> Result> { ctx.locator .web_documents() .list_preset_web_documents(active) diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 9ca4b540f83..bbc284ce3d7 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -7,14 +7,23 @@ use crate::{job::JobInfo, juniper::relay::NodeType, Context, Result}; #[derive(GraphQLObject)] #[graphql(context = Context)] -pub struct WebDocument { +pub struct CustomWebDocument { pub url: String, + pub name: String, pub id: ID, pub created_at: DateTime, pub job_info: JobInfo, } -impl WebDocument { +#[derive(GraphQLObject)] +#[graphql(context = Context)] +pub struct PresetWebDocument { + pub name: String, + pub id: ID, + pub job_info: JobInfo, +} + +impl CustomWebDocument { pub fn source_id(&self) -> String { Self::format_source_id(&self.id) } @@ -39,7 +48,7 @@ pub struct SetPresetDocumentActiveInput { pub active: bool, } -impl NodeType for WebDocument { +impl NodeType for CustomWebDocument { type Cursor = String; fn cursor(&self) -> Self::Cursor { @@ -63,10 +72,10 @@ pub trait WebDocumentService: Send + Sync { before: Option, first: Option, last: Option, - ) -> Result>; + ) -> Result>; async fn create_custom_web_document(&self, name: String, url: String) -> Result; async fn delete_custom_web_document(&self, id: ID) -> Result<()>; - async fn list_preset_web_documents(&self, active: bool) -> Result>; + async fn list_preset_web_documents(&self, active: bool) -> Result>; async fn set_preset_web_documents_active(&self, name: String, active: bool) -> Result; } diff --git a/ee/tabby-webserver/src/service/web_documents.rs b/ee/tabby-webserver/src/service/web_documents.rs index ec8a6f6078a..1a080969029 100644 --- a/ee/tabby-webserver/src/service/web_documents.rs +++ b/ee/tabby-webserver/src/service/web_documents.rs @@ -1,16 +1,16 @@ use std::sync::Arc; +use super::{background_job::BackgroundJobEvent, graphql_pagination_to_filter}; use async_trait::async_trait; use juniper::ID; use tabby_db::{DbConn, WebDocumentDAO}; +use tabby_schema::web_documents::PresetWebDocument; use tabby_schema::{ job::{JobInfo, JobService}, - web_documents::{WebDocument, WebDocumentService}, + web_documents::{CustomWebDocument, WebDocumentService}, AsID, AsRowid, Result, }; -use super::{background_job::BackgroundJobEvent, graphql_pagination_to_filter}; - pub fn create(db: DbConn, job_service: Arc) -> impl WebDocumentService { WebDocumentServiceImpl { db, job_service } } @@ -28,7 +28,7 @@ impl WebDocumentService for WebDocumentServiceImpl { before: Option, first: Option, last: Option, - ) -> Result> { + ) -> Result> { Ok(vec![]) } @@ -40,7 +40,7 @@ impl WebDocumentService for WebDocumentServiceImpl { Ok(()) } - async fn list_preset_web_documents(&self, active: bool) -> Result> { + async fn list_preset_web_documents(&self, active: bool) -> Result> { Ok(vec![]) } From 62566e4099403450f14b408ed85c91c493a751a5 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 13:38:01 +0800 Subject: [PATCH 07/13] fix method Signed-off-by: xxs-wallace --- ee/tabby-schema/graphql/schema.graphql | 37 ++++++++++------ ee/tabby-schema/src/schema/mod.rs | 22 +++++++--- ee/tabby-schema/src/schema/web_documents.rs | 42 ++++++++++++++++--- .../src/service/web_documents.rs | 7 +++- 4 files changed, 83 insertions(+), 25 deletions(-) diff --git a/ee/tabby-schema/graphql/schema.graphql b/ee/tabby-schema/graphql/schema.graphql index 815b87d2c6e..17bf94f8280 100644 --- a/ee/tabby-schema/graphql/schema.graphql +++ b/ee/tabby-schema/graphql/schema.graphql @@ -242,6 +242,16 @@ type CompletionStats { selects: Int! } +type CustomDocumentConnection { + edges: [CustomDocumentEdge!]! + pageInfo: PageInfo! +} + +type CustomDocumentEdge { + node: CustomWebDocument! + cursor: String! +} + type CustomWebDocument { url: String! name: String! @@ -516,10 +526,21 @@ type PageInfo { endCursor: String } +type PresetDocumentConnection { + edges: [PresetDocumentEdge!]! + pageInfo: PageInfo! +} + +type PresetDocumentEdge { + node: PresetWebDocument! + cursor: String! +} + type PresetWebDocument { name: String! id: ID! - jobInfo: JobInfo! + active: Boolean! + jobInfo: JobInfo } type ProvidedRepository { @@ -593,8 +614,8 @@ type Query { Thread is public within an instance, so no need to check for ownership. """ threadMessages(threadId: ID!, after: String, before: String, first: Int, last: Int): MessageConnection! - customWebDocuments(after: String, before: String, first: Int, last: Int): WebDocumentConnection! - presetWebDocuments(active: Boolean!): [PresetWebDocument!]! + customWebDocuments(after: String, before: String, first: Int, last: Int): CustomDocumentConnection! + presetWebDocuments(after: String, before: String, first: Int, last: Int, active: Boolean!): PresetDocumentConnection! } type RefreshTokenResponse { @@ -739,13 +760,3 @@ type WebCrawlerUrlEdge { node: WebCrawlerUrl! cursor: String! } - -type WebDocumentConnection { - edges: [WebDocumentEdge!]! - pageInfo: PageInfo! -} - -type WebDocumentEdge { - node: CustomWebDocument! - cursor: String! -} diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index a544b1a2cea..dec33516cd7 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -590,11 +590,23 @@ impl Query { ) .await } - async fn preset_web_documents(ctx: &Context, active: bool) -> Result> { - ctx.locator - .web_documents() - .list_preset_web_documents(active) - .await + async fn preset_web_documents(ctx: &Context, + after: Option, + before: Option, + first: Option, + last: Option, + active: bool) -> Result> { + query_async( + after, + before, + first, + last, + |after, before, first, last| async move { + ctx.locator + .web_documents() + .list_preset_web_documents(after, before, first, last, active) + .await + }).await } } diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index bbc284ce3d7..013c02b3987 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -20,7 +20,8 @@ pub struct CustomWebDocument { pub struct PresetWebDocument { pub name: String, pub id: ID, - pub job_info: JobInfo, + pub active: bool, + pub job_info: Option, } impl CustomWebDocument { @@ -35,7 +36,11 @@ impl CustomWebDocument { #[derive(Validate, GraphQLInputObject)] pub struct CreateCustomDocumentInput { - #[validate(url(code = "name", message = "Invalid Name"))] + #[validate(regex( + code = "name", + path = "*crate::schema::constants::USERNAME_REGEX", + message = "Invalid repository name" + ))] pub name: String, #[validate(url(code = "url", message = "Invalid URL"))] pub url: String, @@ -43,7 +48,11 @@ pub struct CreateCustomDocumentInput { #[derive(Validate, GraphQLInputObject)] pub struct SetPresetDocumentActiveInput { - #[validate(url(code = "name", message = "Invalid Name"))] + #[validate(regex( + code = "name", + path = "*crate::schema::constants::USERNAME_REGEX", + message = "Invalid repository name" + ))] pub name: String, pub active: bool, } @@ -56,11 +65,27 @@ impl NodeType for CustomWebDocument { } fn connection_type_name() -> &'static str { - "WebDocumentConnection" + "CustomDocumentConnection" + } + + fn edge_type_name() -> &'static str { + "CustomDocumentEdge" + } +} + +impl NodeType for PresetWebDocument { + type Cursor = String; + + fn cursor(&self) -> Self::Cursor { + self.name.clone() + } + + fn connection_type_name() -> &'static str { + "PresetDocumentConnection" } fn edge_type_name() -> &'static str { - "WebDocumentEdge" + "PresetDocumentEdge" } } @@ -76,6 +101,11 @@ pub trait WebDocumentService: Send + Sync { async fn create_custom_web_document(&self, name: String, url: String) -> Result; async fn delete_custom_web_document(&self, id: ID) -> Result<()>; - async fn list_preset_web_documents(&self, active: bool) -> Result>; + async fn list_preset_web_documents(&self, + after: Option, + before: Option, + first: Option, + last: Option, + active: bool) -> Result>; async fn set_preset_web_documents_active(&self, name: String, active: bool) -> Result; } diff --git a/ee/tabby-webserver/src/service/web_documents.rs b/ee/tabby-webserver/src/service/web_documents.rs index 1a080969029..5d4f5dfe9d8 100644 --- a/ee/tabby-webserver/src/service/web_documents.rs +++ b/ee/tabby-webserver/src/service/web_documents.rs @@ -40,7 +40,12 @@ impl WebDocumentService for WebDocumentServiceImpl { Ok(()) } - async fn list_preset_web_documents(&self, active: bool) -> Result> { + async fn list_preset_web_documents(&self, + after: Option, + before: Option, + first: Option, + last: Option, + active: bool) -> Result> { Ok(vec![]) } From e72ea16a8e1b7827d74654f6b9411cbc603945fb Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 13:40:23 +0800 Subject: [PATCH 08/13] add updated at field Signed-off-by: xxs-wallace --- ee/tabby-schema/graphql/schema.graphql | 1 + ee/tabby-schema/src/schema/web_documents.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/ee/tabby-schema/graphql/schema.graphql b/ee/tabby-schema/graphql/schema.graphql index 17bf94f8280..4c570ca87f3 100644 --- a/ee/tabby-schema/graphql/schema.graphql +++ b/ee/tabby-schema/graphql/schema.graphql @@ -540,6 +540,7 @@ type PresetWebDocument { name: String! id: ID! active: Boolean! + updatedAt: DateTime jobInfo: JobInfo } diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 013c02b3987..1252218bbb8 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -21,6 +21,7 @@ pub struct PresetWebDocument { pub name: String, pub id: ID, pub active: bool, + pub updated_at: Option>, pub job_info: Option, } From 5761a76b4f2bc98e56417c4cdf6d30ea02267127 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 13:48:54 +0800 Subject: [PATCH 09/13] add regex Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/constants.rs | 1 + ee/tabby-schema/src/schema/mod.rs | 18 +++++++++++------- ee/tabby-schema/src/schema/web_documents.rs | 18 ++++++++++-------- .../src/service/web_documents.rs | 14 ++++++++------ 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/ee/tabby-schema/src/schema/constants.rs b/ee/tabby-schema/src/schema/constants.rs index 66270f823e2..6116bf6aed5 100644 --- a/ee/tabby-schema/src/schema/constants.rs +++ b/ee/tabby-schema/src/schema/constants.rs @@ -5,6 +5,7 @@ lazy_static! { pub static ref REPOSITORY_NAME_REGEX: Regex = Regex::new("^[a-zA-Z][\\w.-]+$").unwrap(); pub static ref USERNAME_REGEX: Regex = Regex::new(r"^[^0-9±!@£$%^&*_+§¡€#¢¶•ªº«\\/<>?:;|=.,]{2,20}$").unwrap(); + pub static ref DOCUMENT_NAME_REGEX: Regex = Regex::new(r"^[A-Za-z][A-Za-z0-9]*$").unwrap(); } #[cfg(test)] diff --git a/ee/tabby-schema/src/schema/mod.rs b/ee/tabby-schema/src/schema/mod.rs index dec33516cd7..fe39b351ec3 100644 --- a/ee/tabby-schema/src/schema/mod.rs +++ b/ee/tabby-schema/src/schema/mod.rs @@ -590,12 +590,14 @@ impl Query { ) .await } - async fn preset_web_documents(ctx: &Context, - after: Option, - before: Option, - first: Option, - last: Option, - active: bool) -> Result> { + async fn preset_web_documents( + ctx: &Context, + after: Option, + before: Option, + first: Option, + last: Option, + active: bool, + ) -> Result> { query_async( after, before, @@ -606,7 +608,9 @@ impl Query { .web_documents() .list_preset_web_documents(after, before, first, last, active) .await - }).await + }, + ) + .await } } diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 1252218bbb8..b662fd8e1de 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -51,8 +51,8 @@ pub struct CreateCustomDocumentInput { pub struct SetPresetDocumentActiveInput { #[validate(regex( code = "name", - path = "*crate::schema::constants::USERNAME_REGEX", - message = "Invalid repository name" + path = "*crate::schema::constants::DOCUMENT_NAME_REGEX", + message = "Invalid document name" ))] pub name: String, pub active: bool, @@ -102,11 +102,13 @@ pub trait WebDocumentService: Send + Sync { async fn create_custom_web_document(&self, name: String, url: String) -> Result; async fn delete_custom_web_document(&self, id: ID) -> Result<()>; - async fn list_preset_web_documents(&self, - after: Option, - before: Option, - first: Option, - last: Option, - active: bool) -> Result>; + async fn list_preset_web_documents( + &self, + after: Option, + before: Option, + first: Option, + last: Option, + active: bool, + ) -> Result>; async fn set_preset_web_documents_active(&self, name: String, active: bool) -> Result; } diff --git a/ee/tabby-webserver/src/service/web_documents.rs b/ee/tabby-webserver/src/service/web_documents.rs index 5d4f5dfe9d8..8e1086e0f13 100644 --- a/ee/tabby-webserver/src/service/web_documents.rs +++ b/ee/tabby-webserver/src/service/web_documents.rs @@ -40,12 +40,14 @@ impl WebDocumentService for WebDocumentServiceImpl { Ok(()) } - async fn list_preset_web_documents(&self, - after: Option, - before: Option, - first: Option, - last: Option, - active: bool) -> Result> { + async fn list_preset_web_documents( + &self, + after: Option, + before: Option, + first: Option, + last: Option, + active: bool, + ) -> Result> { Ok(vec![]) } From dc5dc6e3c1c730dde94124df6cf6c1aab936ce91 Mon Sep 17 00:00:00 2001 From: Meng Zhang Date: Sun, 18 Aug 2024 22:50:56 -0700 Subject: [PATCH 10/13] Update ee/tabby-schema/src/schema/web_documents.rs --- ee/tabby-schema/src/schema/web_documents.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index b662fd8e1de..482a7f55cc5 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -21,6 +21,7 @@ pub struct PresetWebDocument { pub name: String, pub id: ID, pub active: bool, + /// `updated_at` is only filled when the preset is active. pub updated_at: Option>, pub job_info: Option, } From 4bb8c062761e641acbc6a3037a6bc4f9b75806bb Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 13:51:09 +0800 Subject: [PATCH 11/13] fix doc Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/web_documents.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 482a7f55cc5..3b3c42450d4 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -40,8 +40,8 @@ impl CustomWebDocument { pub struct CreateCustomDocumentInput { #[validate(regex( code = "name", - path = "*crate::schema::constants::USERNAME_REGEX", - message = "Invalid repository name" + path = "*crate::schema::constants::DOCUMENT_NAME_REGEX", + message = "Invalid document name" ))] pub name: String, #[validate(url(code = "url", message = "Invalid URL"))] From 7458beef7259c51b6b29022d7a1e0fc9eb262fe3 Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 14:00:17 +0800 Subject: [PATCH 12/13] add test Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/constants.rs | 19 ++++++++++++++++++- ee/tabby-schema/src/schema/web_documents.rs | 4 ++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/ee/tabby-schema/src/schema/constants.rs b/ee/tabby-schema/src/schema/constants.rs index 6116bf6aed5..e5d0d5504d8 100644 --- a/ee/tabby-schema/src/schema/constants.rs +++ b/ee/tabby-schema/src/schema/constants.rs @@ -5,7 +5,7 @@ lazy_static! { pub static ref REPOSITORY_NAME_REGEX: Regex = Regex::new("^[a-zA-Z][\\w.-]+$").unwrap(); pub static ref USERNAME_REGEX: Regex = Regex::new(r"^[^0-9±!@£$%^&*_+§¡€#¢¶•ªº«\\/<>?:;|=.,]{2,20}$").unwrap(); - pub static ref DOCUMENT_NAME_REGEX: Regex = Regex::new(r"^[A-Za-z][A-Za-z0-9]*$").unwrap(); + pub static ref WEB_DOCUMENT_NAME_REGEX: Regex = Regex::new(r"^[A-Za-z][A-Za-z0-9_]*$").unwrap(); } #[cfg(test)] @@ -41,4 +41,21 @@ mod tests { assert_eq!(result, expected, "Failed for name: {}", name); } } + + #[test] + fn test_web_document_name_regex() { + let test_cases = vec![ + ("John", true), // English name + ("Müller", false), // German name + ("abc123", true), + ("Abc_123", true), + ("_abc_123", false), + ("abc123*", false), + ]; + + for (name, expected) in test_cases { + let result = WEB_DOCUMENT_NAME_REGEX.is_match(name); + assert_eq!(result, expected, "Failed for name: {}", name); + } + } } diff --git a/ee/tabby-schema/src/schema/web_documents.rs b/ee/tabby-schema/src/schema/web_documents.rs index 3b3c42450d4..523016595d7 100644 --- a/ee/tabby-schema/src/schema/web_documents.rs +++ b/ee/tabby-schema/src/schema/web_documents.rs @@ -40,7 +40,7 @@ impl CustomWebDocument { pub struct CreateCustomDocumentInput { #[validate(regex( code = "name", - path = "*crate::schema::constants::DOCUMENT_NAME_REGEX", + path = "*crate::schema::constants::WEB_DOCUMENT_NAME_REGEX", message = "Invalid document name" ))] pub name: String, @@ -52,7 +52,7 @@ pub struct CreateCustomDocumentInput { pub struct SetPresetDocumentActiveInput { #[validate(regex( code = "name", - path = "*crate::schema::constants::DOCUMENT_NAME_REGEX", + path = "*crate::schema::constants::WEB_DOCUMENT_NAME_REGEX", message = "Invalid document name" ))] pub name: String, From d0857bb7cdcac222c9e2f810811ed7deed51e8ff Mon Sep 17 00:00:00 2001 From: xxs-wallace Date: Mon, 19 Aug 2024 14:01:39 +0800 Subject: [PATCH 13/13] fix space Signed-off-by: xxs-wallace --- ee/tabby-schema/src/schema/constants.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ee/tabby-schema/src/schema/constants.rs b/ee/tabby-schema/src/schema/constants.rs index e5d0d5504d8..98c9f227edb 100644 --- a/ee/tabby-schema/src/schema/constants.rs +++ b/ee/tabby-schema/src/schema/constants.rs @@ -5,7 +5,7 @@ lazy_static! { pub static ref REPOSITORY_NAME_REGEX: Regex = Regex::new("^[a-zA-Z][\\w.-]+$").unwrap(); pub static ref USERNAME_REGEX: Regex = Regex::new(r"^[^0-9±!@£$%^&*_+§¡€#¢¶•ªº«\\/<>?:;|=.,]{2,20}$").unwrap(); - pub static ref WEB_DOCUMENT_NAME_REGEX: Regex = Regex::new(r"^[A-Za-z][A-Za-z0-9_]*$").unwrap(); + pub static ref WEB_DOCUMENT_NAME_REGEX: Regex = Regex::new(r"^[A-Za-z][A-Za-z0-9\ ]*$").unwrap(); } #[cfg(test)] @@ -48,9 +48,10 @@ mod tests { ("John", true), // English name ("Müller", false), // German name ("abc123", true), - ("Abc_123", true), - ("_abc_123", false), + ("Abc 123", true), + (" abc 123", false), ("abc123*", false), + ("abc123_", false), ]; for (name, expected) in test_cases {