use apiplant_abi::FunctionAccess;
use apiplant_core::Access;
use ntex::web::types::{Path, State};
use ntex::web::{HttpRequest, HttpResponse};
use serde_json::Value;
use crate::response::error;
use crate::state::AppState;
pub async fn publish(
req: HttpRequest,
state: State<AppState>,
topic: Path<String>,
body: ntex::util::Bytes,
) -> HttpResponse {
let access = state.app.config.queues.publish_access();
let missing = "this app does not accept published messages";
if let Err(response) =
crate::access::check(&state, &req, &to_function_access(&access), missing).await
{
return response;
}
let topic = topic.into_inner();
let message: Value = match body.is_empty() {
true => Value::Object(Default::default()),
false => match serde_json::from_slice(&body) {
Ok(value) => value,
Err(e) => return error(400, format!("the body is not valid JSON: {e}")),
},
};
let principal = state
.resolve_principal(&req)
.await
.map(|p| p.user_id.to_string())
.unwrap_or_default();
match state.queue.publish(&topic, &message, &principal).await {
Ok(publication) => HttpResponse::Accepted().json(&serde_json::json!({
"id": publication.id,
"topic": publication.topic,
"delivered": publication.delivered,
})),
Err(apiplant_queue::QueueError::Request(message)) => error(400, message),
Err(e) => {
crate::telemetry::record_error("queue_publish", &e);
tracing::error!(error = %e, %topic, "could not queue a published message");
error(500, "the message could not be queued")
}
}
}
fn to_function_access(access: &Access) -> FunctionAccess {
match access {
Access::Public => FunctionAccess::Public,
Access::Authenticated => FunctionAccess::Authenticated,
Access::Member => FunctionAccess::Member,
Access::Role(role) => FunctionAccess::Role(role.clone()),
Access::Owner | Access::Private => FunctionAccess::Private,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_two_access_grammars_line_up() {
assert_eq!(to_function_access(&Access::Public), FunctionAccess::Public);
assert_eq!(
to_function_access(&Access::Authenticated),
FunctionAccess::Authenticated
);
assert_eq!(to_function_access(&Access::Member), FunctionAccess::Member);
assert_eq!(
to_function_access(&Access::Role("admin".into())),
FunctionAccess::Role("admin".into())
);
assert_eq!(
to_function_access(&Access::Private),
FunctionAccess::Private
);
assert_eq!(to_function_access(&Access::Owner), FunctionAccess::Private);
}
}