assay_workflow/api/
mod.rs1pub mod activities;
2pub mod api_keys;
3pub mod auth;
4pub mod dashboard;
5pub mod events;
6pub mod namespaces;
7pub mod openapi;
8pub mod public;
9pub mod queues;
10pub mod schedules;
11pub mod tasks;
12pub mod whitelabel;
13pub mod workers;
14pub mod workflow_tasks;
15pub mod workflows;
16
17use std::sync::Arc;
18
19use axum::middleware;
20use axum::Router;
21use tokio::sync::broadcast;
22use tracing::info;
23
24use crate::api::auth::AuthMode;
25use crate::engine::Engine;
26use crate::store::WorkflowStore;
27
28pub struct AppState<S: WorkflowStore> {
30 pub engine: Arc<Engine<S>>,
31 pub event_tx: broadcast::Sender<events::BroadcastEvent>,
32 pub auth_mode: AuthMode,
33 pub binary_version: Option<&'static str>,
39}
40
41pub fn router<S: WorkflowStore + 'static>(state: Arc<AppState<S>>) -> Router {
52 let needs_auth = state.auth_mode.is_enabled();
53
54 let authed_api = Router::new()
55 .nest("/api/v1", api_v1_router())
56 .nest("/api/v1", events::router());
57
58 let authed_api = if needs_auth {
59 authed_api.layer(middleware::from_fn_with_state(
60 Arc::clone(&state),
61 auth::auth_middleware,
62 ))
63 } else {
64 authed_api
65 };
66
67 let public_api = Router::new().nest("/api/v1", public::router());
69
70 let app = authed_api
71 .merge(public_api)
72 .merge(dashboard::router())
73 .merge(openapi::router());
74
75 app.with_state(state)
76}
77
78fn api_v1_router<S: WorkflowStore + 'static>() -> Router<Arc<AppState<S>>> {
79 Router::new()
80 .merge(workflows::router())
81 .merge(activities::router())
82 .merge(workflow_tasks::router())
83 .merge(tasks::router())
84 .merge(schedules::router())
85 .merge(workers::router())
86 .merge(namespaces::router())
87 .merge(queues::router())
88 .merge(api_keys::router())
89}
90
91pub async fn serve<S: WorkflowStore + 'static>(
93 engine: Engine<S>,
94 port: u16,
95 auth_mode: AuthMode,
96) -> anyhow::Result<()> {
97 serve_with_version(engine, port, auth_mode, None).await
98}
99
100pub async fn serve_with_version<S: WorkflowStore + 'static>(
106 engine: Engine<S>,
107 port: u16,
108 auth_mode: AuthMode,
109 binary_version: Option<&'static str>,
110) -> anyhow::Result<()> {
111 let (event_tx, _) = broadcast::channel(1024);
112
113 let mode_desc = auth_mode.describe();
114
115 let state = Arc::new(AppState {
116 engine: Arc::new(engine),
117 event_tx,
118 auth_mode,
119 binary_version,
120 });
121
122 let app = router(state);
123 let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}")).await?;
124 info!("Workflow API listening on 0.0.0.0:{port} (auth: {mode_desc})");
125
126 axum::serve(listener, app).await?;
127 Ok(())
128}