heldar_kernel/routes/
recording_control.rs1use axum::extract::{Path, State};
9use axum::routing::post;
10use axum::{Json, Router};
11use chrono::{DateTime, Utc};
12use serde::Serialize;
13use serde_json::json;
14
15use crate::auth::{self, Principal};
16use crate::error::{AppError, AppResult};
17use crate::routes::cameras::load_camera;
18use crate::state::AppState;
19
20pub fn router() -> Router<AppState> {
21 Router::new().route("/api/v1/cameras/{id}/record-trigger", post(record_trigger))
22}
23
24#[derive(Debug, Serialize)]
26pub struct TriggerResult {
27 pub camera_id: String,
28 pub triggered: bool,
29 pub window_end: DateTime<Utc>,
32 pub pre_roll_seconds: i64,
33 pub post_roll_seconds: i64,
34}
35
36async fn record_trigger(
37 State(st): State<AppState>,
38 Path(id): Path<String>,
39 principal: Principal,
40) -> AppResult<Json<TriggerResult>> {
41 principal.require(principal.can_manage_registry(), "trigger event recording")?;
42 let cam = load_camera(&st.pool, &id).await?;
43 let window_end = st.recorder.trigger(&id, "manual").await.ok_or_else(|| {
44 AppError::BadRequest(
45 "camera is not in an event recording mode (`event` or `scheduled_event`), or recording is disabled".into(),
46 )
47 })?;
48 auth::audit(
49 &st.pool,
50 &principal,
51 "record_trigger",
52 "camera",
53 &id,
54 json!({ "window_end": window_end, "post_roll_seconds": cam.post_roll_seconds }),
55 )
56 .await;
57 Ok(Json(TriggerResult {
58 camera_id: id,
59 triggered: true,
60 window_end,
61 pre_roll_seconds: cam.pre_roll_seconds,
62 post_roll_seconds: cam.post_roll_seconds,
63 }))
64}