This commit is contained in:
despiegk 2025-04-20 09:34:18 +02:00
parent 59c9b445bb
commit 616d3247b6
8 changed files with 48 additions and 56 deletions

View File

@ -25,7 +25,7 @@ pub struct RpcResponse {
} }
/// ACL update request parameters /// ACL update request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct AclUpdateParams { pub struct AclUpdateParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,
@ -40,7 +40,7 @@ pub struct AclUpdateParams {
} }
/// ACL remove request parameters /// ACL remove request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct AclRemoveParams { pub struct AclRemoveParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,
@ -53,7 +53,7 @@ pub struct AclRemoveParams {
} }
/// ACL delete request parameters /// ACL delete request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct AclDelParams { pub struct AclDelParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,
@ -64,7 +64,7 @@ pub struct AclDelParams {
} }
/// Set request parameters /// Set request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct SetParams { pub struct SetParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,
@ -83,7 +83,7 @@ pub struct SetParams {
} }
/// Delete request parameters /// Delete request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct DelParams { pub struct DelParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,
@ -98,7 +98,7 @@ pub struct DelParams {
} }
/// Get request parameters /// Get request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct GetParams { pub struct GetParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,
@ -113,7 +113,7 @@ pub struct GetParams {
} }
/// Prefix request parameters /// Prefix request parameters
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize, ToSchema)]
pub struct PrefixParams { pub struct PrefixParams {
/// Public key of the requesting user /// Public key of the requesting user
pub caller_pubkey: String, pub caller_pubkey: String,

View File

@ -7,7 +7,7 @@ use std::future;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
use serde_json::json; use serde_json::json;
use log::{error}; use log::{error, info};
use utoipa::OpenApi; use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi; use utoipa_swagger_ui::SwaggerUi;
@ -158,20 +158,25 @@ impl Server {
/// Starts the server /// Starts the server
pub async fn start(&self) -> std::io::Result<()> { pub async fn start(&self) -> std::io::Result<()> {
let server_data = web::Data::new(self.clone()); let server = self.clone();
// Register RPC handlers
self.register_handlers();
info!("Starting ACLDB server on {}:{}", self.config.host, self.config.port);
info!("Swagger UI available at: http://{}:{}/swagger-ui/", self.config.host, self.config.port);
// Start the HTTP server // Start the HTTP server
HttpServer::new(move || { HttpServer::new(move || {
App::new() App::new()
.app_data(web::Data::new(server.clone()))
.wrap(Logger::default()) .wrap(Logger::default())
.wrap( .wrap(
Cors::default() Cors::default()
.allow_any_origin() .allow_any_origin()
.allow_any_method() .allow_any_method()
.allow_any_header() .allow_any_header()
.max_age(3600)
) )
.app_data(web::Data::clone(&server_data))
.route("/rpc", web::post().to(handle_rpc)) .route("/rpc", web::post().to(handle_rpc))
.route("/health", web::get().to(health_check)) .route("/health", web::get().to(health_check))
.service( .service(
@ -179,7 +184,7 @@ impl Server {
.url("/api-docs/openapi.json", ApiDoc::openapi()) .url("/api-docs/openapi.json", ApiDoc::openapi())
) )
}) })
.bind(format!("{}:{}", self.config.host, self.config.port))? .bind(format!("{0}:{1}", self.config.host, self.config.port))?
.run() .run()
.await .await
} }
@ -256,31 +261,25 @@ fn extract_circle_id(request: &web::Json<RpcRequest>) -> Result<String, Error> {
/// API documentation schema /// API documentation schema
#[derive(OpenApi)] #[derive(OpenApi)]
#[openapi( #[openapi(
paths(
health_check,
handle_rpc
),
components( components(
schemas(RpcRequest, RpcResponse) schemas(RpcRequest, RpcResponse)
), ),
tags( tags(
(name = "acldb", description = "ACLDB API") (name = "acldb", description = "ACLDB API - Access Control Database")
),
info(
title = "ACLDB API",
version = "1.0.0",
description = "API for managing access control lists and data operations in HeroDB",
contact(
name = "HeroDB Team",
url = "https://ourworld.tf"
)
) )
)] )]
struct ApiDoc; struct ApiDoc;
/// Handler for RPC requests with OpenAPI documentation /// Handler for RPC requests
#[utoipa::path(
post,
path = "/rpc",
request_body = RpcRequest,
responses(
(status = 200, description = "RPC request processed successfully", body = RpcResponse),
(status = 400, description = "Bad request", body = RpcResponse),
(status = 500, description = "Internal server error", body = RpcResponse)
),
tag = "acldb"
)]
async fn handle_rpc( async fn handle_rpc(
server: web::Data<Server>, server: web::Data<Server>,
request: web::Json<RpcRequest>, request: web::Json<RpcRequest>,
@ -470,19 +469,13 @@ async fn process_request(
} }
} }
/// Handler for health check with OpenAPI documentation /// Handler for health check
#[utoipa::path(
get,
path = "/health",
responses(
(status = 200, description = "Server is healthy", body = String)
),
tag = "acldb"
)]
async fn health_check() -> impl Responder { async fn health_check() -> impl Responder {
HttpResponse::Ok().json(json!({"status": "ok"})) HttpResponse::Ok().json(json!({"status": "ok"}))
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
// Tests will be added here // Tests will be added here

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBResult}; use crate::db::{Model, Storable, DB, DbError, DbResult};
use crate::models::mcc::event::Event; use crate::models::mcc::event::Event;
/// Calendar represents a calendar container for events /// Calendar represents a calendar container for events
@ -51,13 +51,12 @@ impl Calendar {
} }
} }
// Implement Storable trait (provides default dump/load)
impl Storable for Calendar{} impl Storable for Calendar{}
// Implement SledModel trait // Implement Model trait
impl SledModel for Calendar { impl Model for Calendar {
fn get_id(&self) -> String { fn get_id(&self) -> u32 {
self.id.to_string() self.id
} }
fn db_prefix() -> &'static str { fn db_prefix() -> &'static str {

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBResult}; use crate::db::{Model, Storable, DB, DbError, DbResult};
use crate::models::mcc::event::Event; use crate::models::mcc::event::Event;
use chrono::Utc; use chrono::Utc;
@ -63,8 +63,8 @@ impl Contact {
} }
/// Get events where this contact is an attendee /// Get events where this contact is an attendee
pub fn get_events(&self, db: &SledDB<Event>) -> SledDBResult<Vec<Event>> { pub fn get_events(&self, db: &DB) -> DbResult<Vec<Event>> {
let all_events = db.list()?; let all_events = db.list::<Event>()?;
let contact_events = all_events let contact_events = all_events
.into_iter() .into_iter()
.filter(|event| event.attendees.contains(&self.email)) .filter(|event| event.attendees.contains(&self.email))
@ -110,9 +110,9 @@ impl Contact {
impl Storable for Contact {} impl Storable for Contact {}
// Implement SledModel trait // Implement SledModel trait
impl SledModel for Contact { impl Model for Contact {
fn get_id(&self) -> String { fn get_id(&self) -> u32 {
self.id.to_string() self.id
} }
fn db_prefix() -> &'static str { fn db_prefix() -> &'static str {

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBResult}; use crate::db::{Model, Storable, DB, DbError, DbResult};
use crate::models::mcc::calendar::Calendar; use crate::models::mcc::calendar::Calendar;
use crate::models::mcc::contacts::Contact; use crate::models::mcc::contacts::Contact;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDBResult, SledDB}; use crate::db::{Model, Storable, DB, DbError, DbResult};
use chrono::Utc; use chrono::Utc;
/// Email represents an email message with all its metadata and content /// Email represents an email message with all its metadata and content

View File

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBResult}; use crate::db::{Model, Storable, DB, DbError, DbResult};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
/// MessageStatus represents the status of a message /// MessageStatus represents the status of a message

View File

@ -12,4 +12,4 @@ pub use contacts::Contact;
pub use message::{Message, MessageMeta, MessageStatus}; pub use message::{Message, MessageMeta, MessageStatus};
// Re-export database components from db module // Re-export database components from db module
pub use crate::db::{SledDB, SledDBError, SledDBResult, Storable, SledModel, DB}; pub use crate::db::{DB, DBBuilder, Model, Storable, DbError, DbResult};