use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use super::types::PolicyKind;
use super::{ManagementClient, Result};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyEnvelope {
pub id: String,
pub name: String,
pub kind: PolicyKind,
pub spec: serde_json::Value,
#[serde(default)]
pub disabled_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyListResponse {
pub data: Vec<PolicyEnvelope>,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct ListPoliciesQuery {
#[serde(skip_serializing_if = "Option::is_none")]
pub kind: Option<PolicyKind>,
}
#[derive(Debug, Clone, Serialize)]
pub struct CreatePolicyRequest {
pub name: String,
pub kind: PolicyKind,
pub spec: serde_json::Value,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct UpdatePolicyRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub spec: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeletePolicyResponse {
pub deleted: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct BindPolicyRequest {
pub principal_type: String,
pub principal_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BindPolicyResponse {
pub binding_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnbindPolicyResponse {
pub unbound: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToggleResponse {
pub disabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BindingEnvelope {
pub id: String,
pub policy_id: String,
pub principal_type: String,
pub principal_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BindingListResponse {
pub data: Vec<BindingEnvelope>,
}
#[derive(Debug, Clone, Serialize)]
pub struct EffectivePolicyQuery {
pub principal_type: String,
pub principal_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EffectivePolicy {
#[serde(default)]
pub budgets: Vec<serde_json::Value>,
#[serde(default)]
pub rate_limits: Vec<serde_json::Value>,
#[serde(default)]
pub guardrail: Option<serde_json::Value>,
}
impl ManagementClient {
pub async fn list_policies(&self, query: &ListPoliciesQuery) -> Result<PolicyListResponse> {
let path = self.namespaced("/policies")?;
self.get_with_query(&path, query).await
}
pub async fn get_policy(&self, id: &str) -> Result<PolicyEnvelope> {
let path = self.namespaced(&format!("/policies/{id}"))?;
self.get_json(&path).await
}
pub async fn create_policy(&self, body: &CreatePolicyRequest) -> Result<PolicyEnvelope> {
let path = self.namespaced("/policies")?;
self.post_json(&path, body).await
}
pub async fn update_policy(
&self,
id: &str,
body: &UpdatePolicyRequest,
) -> Result<PolicyEnvelope> {
let path = self.namespaced(&format!("/policies/{id}"))?;
self.put_json(&path, body).await
}
pub async fn delete_policy(&self, id: &str) -> Result<DeletePolicyResponse> {
let path = self.namespaced(&format!("/policies/{id}"))?;
self.delete_json(&path).await
}
pub async fn bind_policy(
&self,
id: &str,
body: &BindPolicyRequest,
) -> Result<BindPolicyResponse> {
let path = self.namespaced(&format!("/policies/{id}/bind"))?;
self.post_json(&path, body).await
}
pub async fn unbind_policy(&self, id: &str, binding_id: &str) -> Result<UnbindPolicyResponse> {
let path = self.namespaced(&format!("/policies/{id}/bind/{binding_id}"))?;
self.delete_json(&path).await
}
pub async fn list_policy_bindings(&self, id: &str) -> Result<BindingListResponse> {
let path = self.namespaced(&format!("/policies/{id}/bindings"))?;
self.get_json(&path).await
}
pub async fn disable_policy(&self, id: &str) -> Result<ToggleResponse> {
let path = self.namespaced(&format!("/policies/{id}/disable"))?;
self.post_empty(&path).await
}
pub async fn enable_policy(&self, id: &str) -> Result<ToggleResponse> {
let path = self.namespaced(&format!("/policies/{id}/enable"))?;
self.post_empty(&path).await
}
pub async fn list_principal_policies(
&self,
principal_type: &str,
principal_id: &str,
) -> Result<PolicyListResponse> {
let path = self.namespaced(&format!(
"/principals/{principal_type}/{principal_id}/policies"
))?;
self.get_json(&path).await
}
pub async fn effective_policy(&self, query: &EffectivePolicyQuery) -> Result<EffectivePolicy> {
let path = self.namespaced("/policies/effective")?;
self.get_with_query(&path, query).await
}
}