feat: Endpoint for server info (#835)

* feat: provide endpoint so that client can detect server information

* feat: add server info endpoint
This commit is contained in:
Khor Shu Heng 2024-09-29 11:01:22 +08:00 committed by GitHub
parent bbe459a323
commit 47a1aae75c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 79 additions and 3 deletions

View file

@ -1,6 +1,8 @@
use crate::notify::{ClientToken, TokenStateReceiver};
use app_error::AppError;
use app_error::ErrorCode;
use client_api_entity::auth_dto::DeleteUserQuery;
use client_api_entity::server_info_dto::ServerInfoResponseItem;
use client_api_entity::workspace_dto::FolderView;
use client_api_entity::workspace_dto::QueryWorkspaceFolder;
use client_api_entity::workspace_dto::QueryWorkspaceParam;
@ -11,6 +13,7 @@ use gotrue::grant::PasswordGrant;
use gotrue::grant::{Grant, RefreshTokenGrant};
use gotrue::params::MagicLinkParams;
use gotrue::params::{AdminUserParams, GenerateLinkParams};
use reqwest::StatusCode;
use shared_entity::dto::workspace_dto::{CreateWorkspaceParam, PatchWorkspaceParam};
use std::fmt::{Display, Formatter};
#[cfg(feature = "enable_brotli")]
@ -967,6 +970,26 @@ impl Client {
.into_data()
}
#[instrument(level = "info", skip_all)]
pub async fn get_server_info(&self) -> Result<ServerInfoResponseItem, AppResponseError> {
let url = format!("{}/api/server", self.base_url);
let resp = self
.http_client_with_auth(Method::GET, &url)
.await?
.send()
.await?;
if resp.status() == StatusCode::NOT_FOUND {
Err(AppResponseError::new(
ErrorCode::Unhandled,
"server info not implemented",
))
} else {
AppResponse::<ServerInfoResponseItem>::from_response(resp)
.await?
.into_data()
}
}
// Refresh token if given timestamp is close to the token expiration time
pub async fn refresh_if_expired(&self, ts: i64, reason: &str) -> Result<(), AppResponseError> {
let expires_at = self.token_expires_at()?;

View file

@ -20,11 +20,18 @@ database-entity.workspace = true
collab-entity = { workspace = true }
app-error = { workspace = true }
chrono = "0.4.31"
appflowy-ai-client = { workspace = true, default-features = false, features = ["dto"] }
appflowy-ai-client = { workspace = true, default-features = false, features = [
"dto",
] }
pin-project = "1.1.5"
actix-web = { version = "4.4.1", default-features = false, features = ["http2"], optional = true }
validator = { version = "0.16", features = ["validator_derive", "derive"], optional = true }
actix-web = { version = "4.4.1", default-features = false, features = [
"http2",
], optional = true }
validator = { version = "0.16", features = [
"validator_derive",
"derive",
], optional = true }
futures = "0.3.30"
bytes = "1.6.0"
log = "0.4.21"

View file

@ -5,4 +5,5 @@ pub mod billing_dto;
pub mod history_dto;
pub mod publish_dto;
pub mod search_dto;
pub mod server_info_dto;
pub mod workspace_dto;

View file

@ -0,0 +1,13 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum SupportedClientFeatures {
// Supports Collab Params serialization using Protobuf
CollabParamsProtobuf,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ServerInfoResponseItem {
pub supported_client_features: Vec<SupportedClientFeatures>,
pub minimum_supported_client_version: Option<String>,
}

View file

@ -6,6 +6,7 @@ pub mod access_request;
pub mod history;
pub mod metrics;
pub mod search;
pub mod server_info;
pub mod template;
pub mod user;
pub mod util;

18
src/api/server_info.rs Normal file
View file

@ -0,0 +1,18 @@
use actix_web::{web, Scope};
use shared_entity::dto::server_info_dto::ServerInfoResponseItem;
use shared_entity::response::{AppResponse, JsonAppResponse};
pub fn server_info_scope() -> Scope {
web::scope("/api/server").service(web::resource("").route(web::get().to(server_info_handler)))
}
async fn server_info_handler() -> actix_web::Result<JsonAppResponse<ServerInfoResponseItem>> {
Ok(
AppResponse::Ok()
.with_data(ServerInfoResponseItem {
supported_client_features: vec![],
minimum_supported_client_version: None,
})
.into(),
)
}

View file

@ -49,6 +49,7 @@ use crate::api::file_storage::file_storage_scope;
use crate::api::history::history_scope;
use crate::api::metrics::metrics_scope;
use crate::api::search::search_scope;
use crate::api::server_info::server_info_scope;
use crate::api::template::template_scope;
use crate::api::user::user_scope;
use crate::api::workspace::{collab_scope, workspace_scope};
@ -159,6 +160,7 @@ pub async fn run_actix_server(
// .wrap(DecryptPayloadMiddleware)
.wrap(access_control.clone())
.wrap(RequestIdMiddleware)
.service(server_info_scope())
.service(user_scope())
.service(workspace_scope())
.service(collab_scope())

View file

@ -4,6 +4,7 @@ mod collab_history;
mod file_test;
mod gotrue;
mod search;
mod server_info;
mod sql_test;
mod user;
mod websocket;

View file

@ -0,0 +1,9 @@
use client_api_test::generate_unique_registered_user_client;
#[tokio::test]
async fn test_get_server_info() {
let (c, _) = generate_unique_registered_user_client().await;
c.get_server_info()
.await
.expect("Failed to get server info");
}

1
tests/server_info/mod.rs Normal file
View file

@ -0,0 +1 @@
mod info;