openidauthzen 0.1.0-alpha.1

OpenID AuthZEN Authorization API 1.0 — Policy Decision and Enforcement Points for Rust
Documentation
//! Search endpoints for discovering authorized subjects, resources, and
//! actions ([AuthZEN §8]).
//!
//! | Endpoint | Request | Response |
//! |----------|---------|----------|
//! | `POST /access/v1/search/subject` | [`SubjectSearchRequest`] | [`SubjectSearchResponse`] |
//! | `POST /access/v1/search/resource` | [`ResourceSearchRequest`] | [`ResourceSearchResponse`] |
//! | `POST /access/v1/search/action` | [`ActionSearchRequest`] | [`ActionSearchResponse`] |
//!
//! All search endpoints support pagination via [`Page`] (request) and
//! [`PageResponse`] (response).
//!
//! [AuthZEN §8]: https://openid.net/specs/authorization-api-1_0.html#section-8

use serde::{Deserialize, Serialize};

use crate::model::{Action, Context, Resource, Subject};

/// Pagination parameters for a search request ([AuthZEN §8]).
///
/// [AuthZEN §8]: https://openid.net/specs/authorization-api-1_0.html#section-8
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Page {
    /// An opaque continuation token from a previous [`PageResponse`].
    #[serde(skip_serializing_if = "Option::is_none")]
    pub token: Option<String>,
    /// Maximum number of results to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u32>,
    /// Additional pagination parameters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub properties: Option<serde_json::Value>,
}

/// Pagination metadata in a search response ([AuthZEN §8]).
///
/// [AuthZEN §8]: https://openid.net/specs/authorization-api-1_0.html#section-8
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PageResponse {
    /// Continuation token for fetching the next page. An empty string
    /// indicates no more results.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub next_token: Option<String>,
    /// Number of results in this page.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub count: Option<u32>,
    /// Total number of results across all pages, if known.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub total: Option<u32>,
    /// Additional pagination metadata.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub properties: Option<serde_json::Value>,
}

/// Find subjects authorized to perform an action on a resource
/// (`POST /access/v1/search/subject`, [AuthZEN §8.4]).
///
/// The `subject` field should include `type` but omit `id`, since
/// the search is discovering which subjects are authorized.
///
/// [AuthZEN §8.4]: https://openid.net/specs/authorization-api-1_0.html#section-8.4
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SubjectSearchRequest {
    /// Subject filter — set `type` to constrain results; omit `id`.
    pub subject: Subject,
    /// The action to evaluate against. Required.
    pub action: Action,
    /// The resource to evaluate against. Required.
    pub resource: Resource,
    /// Environmental context for the evaluation.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<Context>,
    /// Pagination parameters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<Page>,
}

/// Response to a subject search request ([AuthZEN §8.4]).
///
/// [AuthZEN §8.4]: https://openid.net/specs/authorization-api-1_0.html#section-8.4
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SubjectSearchResponse {
    /// Authorized subjects matching the search criteria.
    pub results: Vec<Subject>,
    /// Pagination metadata.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<PageResponse>,
    /// Additional response context.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<serde_json::Value>,
}

/// Find resources a subject is authorized to access
/// (`POST /access/v1/search/resource`, [AuthZEN §8.5]).
///
/// The `resource` field should include `type` but omit `id`, since
/// the search is discovering which resources are accessible.
///
/// [AuthZEN §8.5]: https://openid.net/specs/authorization-api-1_0.html#section-8.5
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResourceSearchRequest {
    /// The subject performing the action. Required.
    pub subject: Subject,
    /// The action to evaluate against. Required.
    pub action: Action,
    /// Resource filter — set `type` to constrain results; omit `id`.
    pub resource: Resource,
    /// Environmental context for the evaluation.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<Context>,
    /// Pagination parameters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<Page>,
}

/// Response to a resource search request ([AuthZEN §8.5]).
///
/// [AuthZEN §8.5]: https://openid.net/specs/authorization-api-1_0.html#section-8.5
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResourceSearchResponse {
    /// Accessible resources matching the search criteria.
    pub results: Vec<Resource>,
    /// Pagination metadata.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<PageResponse>,
    /// Additional response context.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<serde_json::Value>,
}

/// Find actions a subject is permitted to perform on a resource
/// (`POST /access/v1/search/action`, [AuthZEN §8.6]).
///
/// Note: unlike other search requests, this one does not include
/// an `action` field — the purpose is to discover which actions
/// are permitted.
///
/// [AuthZEN §8.6]: https://openid.net/specs/authorization-api-1_0.html#section-8.6
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ActionSearchRequest {
    /// The subject performing the action. Required.
    pub subject: Subject,
    /// The resource to evaluate against. Required.
    pub resource: Resource,
    /// Environmental context for the evaluation.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<Context>,
    /// Pagination parameters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<Page>,
}

/// Response to an action search request ([AuthZEN §8.6]).
///
/// [AuthZEN §8.6]: https://openid.net/specs/authorization-api-1_0.html#section-8.6
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ActionSearchResponse {
    /// Permitted actions matching the search criteria.
    pub results: Vec<Action>,
    /// Pagination metadata.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub page: Option<PageResponse>,
    /// Additional response context.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub context: Option<serde_json::Value>,
}