use crate::api::api_error;
use crate::api::authorize_request;
use crate::api::parse_json_payload;
use crate::api::BearerToken;
use crate::core::behavior_bio::BehaviorInput;
use crate::AppState;
use actix_web::http::StatusCode;
use actix_web::{post, web, HttpRequest, HttpResponse, Responder};
#[derive(serde::Deserialize, Clone)]
pub struct SmartAccessRequest {
pub geo_input: Option<(std::net::IpAddr, (f64, f64, u8, f64))>,
pub behavior_input: BehaviorInput,
pub os_info: String,
pub device_details: String,
pub env_context: String,
}
#[post("/smart_access/verify")]
pub async fn smart_access_verify(
data: web::Data<AppState>,
req: HttpRequest,
bearer: BearerToken,
payload_bytes: web::Bytes,
) -> impl Responder {
if let Err(resp) = authorize_request(&data, &req, &bearer, &payload_bytes).await {
return resp;
}
let payload: SmartAccessRequest = match parse_json_payload(&payload_bytes) {
Ok(v) => v,
Err(resp) => return resp,
};
let allowed_zones = vec!["Riyadh".to_string(), "Jeddah".to_string()];
let allowed_hours = Some((6, 18));
let result = data
.composite_verifier
.verify_smart_access(
payload.geo_input,
payload.behavior_input.clone(),
(
&payload.os_info,
&payload.device_details,
&payload.env_context,
),
&allowed_zones,
allowed_hours,
)
.await;
match result {
Ok(true) => HttpResponse::Ok().body("Access granted"),
Ok(false) => api_error(
StatusCode::FORBIDDEN,
"SMART_ACCESS_DENIED",
"Access denied",
),
Err(_) => api_error(
StatusCode::FORBIDDEN,
"SMART_ACCESS_POLICY_DENIED",
"Access denied by policy",
),
}
}