areev 0.2.0

Rust SDK for the Areev knowledge database — gRPC and HTTP transports
Documentation
//! `Consent` resource — per-user, per-purpose consent grants
//! (GDPR Art. 6/7).
//!
//! Mirrors the Python SDK's `client.consent.*` surface.

use serde_json::{json, Map, Value};

use crate::error::Result;
use crate::http::HttpClient;

/// Consent lifecycle.
///
/// Access via [`crate::Areev::consent`].
pub struct Consent<'a> {
    http: &'a HttpClient,
    memory_id: String,
}

impl<'a> Consent<'a> {
    /// Internal constructor — use [`crate::Areev::consent`].
    pub(crate) fn new(http: &'a HttpClient, memory_id: String) -> Self {
        Self { http, memory_id }
    }

    /// Check whether `user_id` has consented to `purpose`.
    ///
    /// All three parameters — `user_id`, `purpose`, and `disclosure_version`
    /// — are required by the server.
    pub async fn check(
        &self,
        user_id: &str,
        purpose: &str,
        disclosure_version: &str,
    ) -> Result<Value> {
        let query = json!({
            "user_id": user_id,
            "purpose": purpose,
            "disclosure_version": disclosure_version,
        });
        let path = format!("/memories/{}/consent/check", self.memory_id);
        self.http._get(&path, Some(&query)).await
    }

    /// Aggregate consent status for the memory.
    ///
    /// Pass `include_ids = Some(true)` to include the plaintext user-id list
    /// in the response (omitted by default for privacy).
    pub async fn status(&self, include_ids: Option<bool>) -> Result<Value> {
        let mut query = Map::new();
        if let Some(v) = include_ids {
            query.insert("include_ids".into(), Value::Bool(v));
        }
        let path = format!("/memories/{}/consent/status", self.memory_id);
        let q = Value::Object(query);
        self.http._get(&path, Some(&q)).await
    }

    /// Record a consent grant for `user_id` / `purpose`. Emits an audit
    /// event.
    pub async fn grant(
        &self,
        user_id: &str,
        purpose: &str,
        scope: Option<&[&str]>,
        disclosure_version: Option<&str>,
    ) -> Result<Value> {
        let mut body = Map::new();
        body.insert("user_id".into(), Value::String(user_id.to_string()));
        body.insert("purpose".into(), Value::String(purpose.to_string()));
        if let Some(s) = scope {
            body.insert(
                "scope".into(),
                Value::Array(s.iter().map(|x| Value::String(x.to_string())).collect()),
            );
        }
        if let Some(d) = disclosure_version {
            body.insert("disclosure_version".into(), Value::String(d.to_string()));
        }
        let path = format!("/memories/{}/consent/grant", self.memory_id);
        self.http._post(&path, Some(&Value::Object(body))).await
    }

    /// Record one consent grant per id in `user_ids` for `purpose`. Emits
    /// audit events.
    pub async fn grant_bulk(&self, user_ids: &[&str], purpose: Option<&str>) -> Result<Value> {
        let mut body = Map::new();
        body.insert(
            "user_ids".into(),
            Value::Array(
                user_ids
                    .iter()
                    .map(|x| Value::String(x.to_string()))
                    .collect(),
            ),
        );
        if let Some(p) = purpose {
            body.insert("purpose".into(), Value::String(p.to_string()));
        }
        let path = format!("/memories/{}/consent/grant-bulk", self.memory_id);
        self.http._post(&path, Some(&Value::Object(body))).await
    }

    /// Revoke a previously granted consent. Emits an audit event.
    pub async fn revoke(
        &self,
        user_id: &str,
        purpose: &str,
        scope: Option<&[&str]>,
    ) -> Result<Value> {
        let mut body = Map::new();
        body.insert("user_id".into(), Value::String(user_id.to_string()));
        body.insert("purpose".into(), Value::String(purpose.to_string()));
        if let Some(s) = scope {
            body.insert(
                "scope".into(),
                Value::Array(s.iter().map(|x| Value::String(x.to_string())).collect()),
            );
        }
        let path = format!("/memories/{}/consent/revoke", self.memory_id);
        self.http._post(&path, Some(&Value::Object(body))).await
    }
}