From f17fa877651a28456b1feab8ee79abd9952c4c2e Mon Sep 17 00:00:00 2001 From: Kim Altintop Date: Tue, 28 Oct 2025 20:30:04 +0100 Subject: [PATCH] Identity routes --- crates/client-api/src/routes/identity.rs | 52 +++++++++++++++++----- crates/client-api/src/routes/mod.rs | 11 +++-- crates/standalone/src/subcommands/start.rs | 3 +- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/crates/client-api/src/routes/identity.rs b/crates/client-api/src/routes/identity.rs index be9adde55f9..c8dc44d2964 100644 --- a/crates/client-api/src/routes/identity.rs +++ b/crates/client-api/src/routes/identity.rs @@ -2,6 +2,7 @@ use std::time::Duration; use axum::extract::{Path, State}; use axum::response::IntoResponse; +use axum::routing::MethodRouter; use http::header::CONTENT_TYPE; use http::StatusCode; use serde::{Deserialize, Serialize}; @@ -64,12 +65,12 @@ impl<'de> serde::Deserialize<'de> for IdentityForUrl { #[derive(Deserialize)] pub struct GetDatabasesParams { - identity: IdentityForUrl, + pub identity: IdentityForUrl, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GetDatabasesResponse { - identities: Vec, + pub identities: Vec, } pub async fn get_databases( @@ -135,15 +136,46 @@ pub async fn get_public_key(State(ctx): State) -> axum::resp )) } -pub fn router() -> axum::Router +/// A struct to allow customization of the `/identity` routes. +pub struct IdentityRoutes { + /// POST /identity + pub create_post: MethodRouter, + /// GET /identity/public-key + pub public_key_get: MethodRouter, + /// POST /identity/websocket-tocken + pub websocket_token_post: MethodRouter, + /// GET /identity/:identity/verify + pub verify_get: MethodRouter, + /// GET /identity/:identity/databases + pub databases_get: MethodRouter, +} + +impl Default for IdentityRoutes +where + S: NodeDelegate + ControlStateDelegate + Clone + 'static, +{ + fn default() -> Self { + use axum::routing::{get, post}; + Self { + create_post: post(create_identity::), + public_key_get: get(get_public_key::), + websocket_token_post: post(create_websocket_token::), + verify_get: get(validate_token), + databases_get: get(get_databases::), + } + } +} + +impl IdentityRoutes where S: NodeDelegate + ControlStateDelegate + Clone + 'static, { - use axum::routing::{get, post}; - axum::Router::new() - .route("/", post(create_identity::)) - .route("/public-key", get(get_public_key::)) - .route("/websocket-token", post(create_websocket_token::)) - .route("/:identity/verify", get(validate_token)) - .route("/:identity/databases", get(get_databases::)) + pub fn into_router(self) -> axum::Router { + axum::Router::new() + .route("/", self.create_post) + .route("/public-key", self.public_key_get) + .route("/websocket-token", self.websocket_token_post) + .route("/:identity/verify", self.verify_get) + .route("/:identity/databases", self.databases_get) + } } diff --git a/crates/client-api/src/routes/mod.rs b/crates/client-api/src/routes/mod.rs index 4fe1de67f41..08e1e73cb77 100644 --- a/crates/client-api/src/routes/mod.rs +++ b/crates/client-api/src/routes/mod.rs @@ -12,21 +12,26 @@ pub mod metrics; pub mod prometheus; pub mod subscribe; -use self::database::DatabaseRoutes; +use self::{database::DatabaseRoutes, identity::IdentityRoutes}; /// This API call is just designed to allow clients to determine whether or not they can /// establish a connection to SpacetimeDB. This API call doesn't actually do anything. pub async fn ping(_auth: crate::auth::SpacetimeAuthHeader) {} #[allow(clippy::let_and_return)] -pub fn router(ctx: &S, database_routes: DatabaseRoutes, extra: axum::Router) -> axum::Router +pub fn router( + ctx: &S, + database_routes: DatabaseRoutes, + identity_routes: IdentityRoutes, + extra: axum::Router, +) -> axum::Router where S: NodeDelegate + ControlStateDelegate + Authorization + Clone + 'static, { use axum::routing::get; let router = axum::Router::new() .nest("/database", database_routes.into_router(ctx.clone())) - .nest("/identity", identity::router()) + .nest("/identity", identity_routes.into_router()) .nest("/energy", energy::router()) .nest("/prometheus", prometheus::router()) .nest("/metrics", metrics::router()) diff --git a/crates/standalone/src/subcommands/start.rs b/crates/standalone/src/subcommands/start.rs index 3d9cc44af4f..811c3538117 100644 --- a/crates/standalone/src/subcommands/start.rs +++ b/crates/standalone/src/subcommands/start.rs @@ -1,3 +1,4 @@ +use spacetimedb_client_api::routes::identity::IdentityRoutes; use spacetimedb_pg::pg_server; use std::sync::Arc; @@ -185,7 +186,7 @@ pub async fn exec(args: &ArgMatches, db_cores: JobCores) -> anyhow::Result<()> { db_routes.db_put = db_routes.db_put.layer(DefaultBodyLimit::disable()); db_routes.pre_publish = db_routes.pre_publish.layer(DefaultBodyLimit::disable()); let extra = axum::Router::new().nest("/health", spacetimedb_client_api::routes::health::router()); - let service = router(&ctx, db_routes, extra).with_state(ctx.clone()); + let service = router(&ctx, db_routes, IdentityRoutes::default(), extra).with_state(ctx.clone()); let tcp = TcpListener::bind(listen_addr).await.context(format!( "failed to bind the SpacetimeDB server to '{listen_addr}', please check that the address is valid and not already in use"