use crate::client::Client;
use crate::errors::Error;
use crate::KeygenResponseData;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ExpirationStrategy {
RestrictAccess,
RevokeAccess,
MaintainAccess,
AllowAccess,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum AuthenticationStrategy {
Token,
License,
Mixed,
None,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum OverageStrategy {
NoOverage,
AlwaysAllowOverage,
Allow125xOverage,
Allow15xOverage,
Allow2xOverage,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TransferStrategy {
KeepPolicy,
ResetPolicy,
KeepExpiry,
ResetExpiry,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum LeasingStrategy {
PerMachine,
PerLicense,
PerUser,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum UniquenessStrategy {
UniquePerAccount,
UniquePerProduct,
UniquePerPolicy,
UniquePerLicense,
UniquePerMachine,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum MatchingStrategy {
MatchAny,
MatchTwo,
MatchMost,
MatchAll,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Scheme {
#[serde(rename = "ED25519_SIGN")]
Ed25519Sign,
#[serde(rename = "ECDSA_P256_SIGN")]
EcdsaP256Sign,
#[serde(rename = "RSA_2048_PKCS1_PSS_SIGN_V2")]
Rsa2048Pkcs1PssSignV2,
#[serde(rename = "RSA_2048_PKCS1_SIGN_V2")]
Rsa2048Pkcs1SignV2,
#[serde(rename = "RSA_2048_PKCS1_ENCRYPT")]
Rsa2048Pkcs1Encrypt,
#[serde(rename = "RSA_2048_JWT_RS256")]
Rsa2048JwtRs256,
#[serde(rename = "LEGACY_ENCRYPT")]
LegacyEncrypt,
#[serde(rename = "RSA_2048_PKCS1_PSS_SIGN")]
Rsa2048Pkcs1PssSign, #[serde(rename = "RSA_2048_PKCS1_SIGN")]
Rsa2048Pkcs1Sign, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyAttributes {
pub name: String,
pub duration: Option<i64>, pub strict: bool,
pub floating: bool,
#[serde(rename = "requireHeartbeat")]
pub require_heartbeat: bool,
#[serde(rename = "heartbeatDuration")]
pub heartbeat_duration: Option<i64>,
#[serde(rename = "heartbeatCullStrategy")]
pub heartbeat_cull_strategy: Option<String>,
#[serde(rename = "heartbeatResurrectionStrategy")]
pub heartbeat_resurrection_strategy: Option<String>,
#[serde(rename = "heartbeatBasis")]
pub heartbeat_basis: Option<String>,
#[serde(rename = "machineUniquenessStrategy")]
pub machine_uniqueness_strategy: Option<UniquenessStrategy>,
#[serde(rename = "componentUniquenessStrategy")]
pub component_uniqueness_strategy: Option<UniquenessStrategy>,
#[serde(rename = "machineMatchingStrategy")]
pub machine_matching_strategy: Option<MatchingStrategy>,
#[serde(rename = "componentMatchingStrategy")]
pub component_matching_strategy: Option<MatchingStrategy>,
#[serde(rename = "expirationStrategy")]
pub expiration_strategy: ExpirationStrategy,
#[serde(rename = "expirationBasis")]
pub expiration_basis: Option<String>,
#[serde(rename = "renewalBasis")]
pub renewal_basis: Option<String>,
#[serde(rename = "authenticationStrategy")]
pub authentication_strategy: AuthenticationStrategy,
#[serde(rename = "machineLeasingStrategy")]
pub machine_leasing_strategy: LeasingStrategy,
#[serde(rename = "processLeasingStrategy")]
pub process_leasing_strategy: LeasingStrategy,
#[serde(rename = "overageStrategy")]
pub overage_strategy: OverageStrategy,
#[serde(rename = "transferStrategy")]
pub transfer_strategy: TransferStrategy,
#[serde(rename = "maxMachines")]
pub max_machines: Option<i32>,
#[serde(rename = "maxProcesses")]
pub max_processes: Option<i32>,
#[serde(rename = "maxCores")]
pub max_cores: Option<i32>,
#[serde(rename = "maxUses")]
pub max_uses: Option<i32>,
pub encrypted: bool,
pub protected: bool,
#[serde(rename = "requireCheckIn")]
pub require_check_in: bool,
#[serde(rename = "checkInInterval")]
pub check_in_interval: Option<String>,
#[serde(rename = "checkInIntervalCount")]
pub check_in_interval_count: Option<i32>,
#[serde(rename = "usePool")]
pub use_pool: bool,
#[serde(rename = "maxLicenses")]
pub max_licenses: Option<i32>,
#[serde(rename = "maxUsers")]
pub max_users: Option<i32>,
pub scheme: Option<Scheme>,
pub metadata: Option<HashMap<String, serde_json::Value>>,
pub created: String,
pub updated: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct PolicyResponse {
pub data: KeygenResponseData<PolicyAttributes>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct PoliciesResponse {
pub data: Vec<KeygenResponseData<PolicyAttributes>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreatePolicyRequest {
pub name: String,
pub duration: Option<i64>,
pub strict: Option<bool>,
pub floating: Option<bool>,
#[serde(rename = "requireHeartbeat")]
pub require_heartbeat: Option<bool>,
#[serde(rename = "heartbeatDuration")]
pub heartbeat_duration: Option<i64>,
#[serde(rename = "heartbeatCullStrategy")]
pub heartbeat_cull_strategy: Option<String>,
#[serde(rename = "heartbeatResurrectionStrategy")]
pub heartbeat_resurrection_strategy: Option<String>,
#[serde(rename = "heartbeatBasis")]
pub heartbeat_basis: Option<String>,
#[serde(rename = "machineUniquenessStrategy")]
pub machine_uniqueness_strategy: Option<UniquenessStrategy>,
#[serde(rename = "componentUniquenessStrategy")]
pub component_uniqueness_strategy: Option<UniquenessStrategy>,
#[serde(rename = "machineMatchingStrategy")]
pub machine_matching_strategy: Option<MatchingStrategy>,
#[serde(rename = "componentMatchingStrategy")]
pub component_matching_strategy: Option<MatchingStrategy>,
#[serde(rename = "expirationStrategy")]
pub expiration_strategy: Option<ExpirationStrategy>,
#[serde(rename = "expirationBasis")]
pub expiration_basis: Option<String>,
#[serde(rename = "renewalBasis")]
pub renewal_basis: Option<String>,
#[serde(rename = "authenticationStrategy")]
pub authentication_strategy: Option<AuthenticationStrategy>,
#[serde(rename = "machineLeasingStrategy")]
pub machine_leasing_strategy: Option<LeasingStrategy>,
#[serde(rename = "processLeasingStrategy")]
pub process_leasing_strategy: Option<LeasingStrategy>,
#[serde(rename = "overageStrategy")]
pub overage_strategy: Option<OverageStrategy>,
#[serde(rename = "transferStrategy")]
pub transfer_strategy: Option<TransferStrategy>,
#[serde(rename = "maxMachines")]
pub max_machines: Option<i32>,
#[serde(rename = "maxProcesses")]
pub max_processes: Option<i32>,
#[serde(rename = "maxCores")]
pub max_cores: Option<i32>,
#[serde(rename = "maxUses")]
pub max_uses: Option<i32>,
pub encrypted: Option<bool>,
pub protected: Option<bool>,
#[serde(rename = "requireCheckIn")]
pub require_check_in: Option<bool>,
#[serde(rename = "checkInInterval")]
pub check_in_interval: Option<String>,
#[serde(rename = "checkInIntervalCount")]
pub check_in_interval_count: Option<i32>,
#[serde(rename = "usePool")]
pub use_pool: Option<bool>,
#[serde(rename = "maxLicenses")]
pub max_licenses: Option<i32>,
#[serde(rename = "maxUsers")]
pub max_users: Option<i32>,
pub scheme: Option<Scheme>,
pub metadata: Option<HashMap<String, serde_json::Value>>,
pub product_id: String,
}
#[allow(clippy::derivable_impls)]
impl Default for CreatePolicyRequest {
fn default() -> Self {
Self {
name: String::new(),
duration: None,
strict: None,
floating: None,
require_heartbeat: None,
heartbeat_duration: None,
heartbeat_cull_strategy: None,
heartbeat_resurrection_strategy: None,
heartbeat_basis: None,
machine_uniqueness_strategy: None,
component_uniqueness_strategy: None,
machine_matching_strategy: None,
component_matching_strategy: None,
expiration_strategy: None,
expiration_basis: None,
renewal_basis: None,
authentication_strategy: None,
machine_leasing_strategy: None,
process_leasing_strategy: None,
overage_strategy: None,
transfer_strategy: None,
max_machines: None,
max_processes: None,
max_cores: None,
max_uses: None,
encrypted: None,
protected: None,
require_check_in: None,
check_in_interval: None,
check_in_interval_count: None,
use_pool: None,
max_licenses: None,
max_users: None,
scheme: None,
metadata: None,
product_id: String::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct UpdatePolicyRequest {
pub name: Option<String>,
pub duration: Option<i64>,
pub strict: Option<bool>,
pub floating: Option<bool>,
#[serde(rename = "requireHeartbeat")]
pub require_heartbeat: Option<bool>,
#[serde(rename = "heartbeatDuration")]
pub heartbeat_duration: Option<i64>,
#[serde(rename = "heartbeatCullStrategy")]
pub heartbeat_cull_strategy: Option<String>,
#[serde(rename = "heartbeatResurrectionStrategy")]
pub heartbeat_resurrection_strategy: Option<String>,
#[serde(rename = "heartbeatBasis")]
pub heartbeat_basis: Option<String>,
#[serde(rename = "machineUniquenessStrategy")]
pub machine_uniqueness_strategy: Option<UniquenessStrategy>,
#[serde(rename = "componentUniquenessStrategy")]
pub component_uniqueness_strategy: Option<UniquenessStrategy>,
#[serde(rename = "machineMatchingStrategy")]
pub machine_matching_strategy: Option<MatchingStrategy>,
#[serde(rename = "componentMatchingStrategy")]
pub component_matching_strategy: Option<MatchingStrategy>,
#[serde(rename = "expirationStrategy")]
pub expiration_strategy: Option<ExpirationStrategy>,
#[serde(rename = "expirationBasis")]
pub expiration_basis: Option<String>,
#[serde(rename = "renewalBasis")]
pub renewal_basis: Option<String>,
#[serde(rename = "authenticationStrategy")]
pub authentication_strategy: Option<AuthenticationStrategy>,
#[serde(rename = "machineLeasingStrategy")]
pub machine_leasing_strategy: Option<LeasingStrategy>,
#[serde(rename = "processLeasingStrategy")]
pub process_leasing_strategy: Option<LeasingStrategy>,
#[serde(rename = "overageStrategy")]
pub overage_strategy: Option<OverageStrategy>,
#[serde(rename = "transferStrategy")]
pub transfer_strategy: Option<TransferStrategy>,
#[serde(rename = "maxMachines")]
pub max_machines: Option<i32>,
#[serde(rename = "maxProcesses")]
pub max_processes: Option<i32>,
#[serde(rename = "maxCores")]
pub max_cores: Option<i32>,
#[serde(rename = "maxUses")]
pub max_uses: Option<i32>,
pub protected: Option<bool>,
#[serde(rename = "requireCheckIn")]
pub require_check_in: Option<bool>,
#[serde(rename = "checkInInterval")]
pub check_in_interval: Option<String>,
#[serde(rename = "checkInIntervalCount")]
pub check_in_interval_count: Option<i32>,
#[serde(rename = "maxUsers")]
pub max_users: Option<i32>,
pub scheme: Option<Scheme>,
pub metadata: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone)]
pub struct Policy {
pub id: String,
pub name: String,
pub duration: Option<i64>,
pub strict: bool,
pub floating: bool,
pub require_heartbeat: bool,
pub heartbeat_duration: Option<i64>,
pub heartbeat_cull_strategy: Option<String>,
pub heartbeat_resurrection_strategy: Option<String>,
pub heartbeat_basis: Option<String>,
pub machine_uniqueness_strategy: Option<UniquenessStrategy>,
pub component_uniqueness_strategy: Option<UniquenessStrategy>,
pub machine_matching_strategy: Option<MatchingStrategy>,
pub component_matching_strategy: Option<MatchingStrategy>,
pub expiration_strategy: ExpirationStrategy,
pub expiration_basis: Option<String>,
pub renewal_basis: Option<String>,
pub authentication_strategy: AuthenticationStrategy,
pub machine_leasing_strategy: LeasingStrategy,
pub process_leasing_strategy: LeasingStrategy,
pub overage_strategy: OverageStrategy,
pub transfer_strategy: TransferStrategy,
pub max_machines: Option<i32>,
pub max_processes: Option<i32>,
pub max_cores: Option<i32>,
pub max_uses: Option<i32>,
pub encrypted: bool,
pub protected: bool,
pub require_check_in: bool,
pub check_in_interval: Option<String>,
pub check_in_interval_count: Option<i32>,
pub use_pool: bool,
pub max_licenses: Option<i32>,
pub max_users: Option<i32>,
pub scheme: Option<Scheme>,
pub metadata: Option<HashMap<String, serde_json::Value>>,
pub created: String,
pub updated: String,
pub account_id: Option<String>,
pub product_id: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ListPoliciesOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[serde(rename = "page[size]", skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
#[serde(rename = "page[number]", skip_serializing_if = "Option::is_none")]
pub page_number: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub product: Option<String>,
}
impl Policy {
pub(crate) fn from(data: KeygenResponseData<PolicyAttributes>) -> Policy {
Policy {
id: data.id,
name: data.attributes.name,
duration: data.attributes.duration,
strict: data.attributes.strict,
floating: data.attributes.floating,
require_heartbeat: data.attributes.require_heartbeat,
heartbeat_duration: data.attributes.heartbeat_duration,
heartbeat_cull_strategy: data.attributes.heartbeat_cull_strategy,
heartbeat_resurrection_strategy: data.attributes.heartbeat_resurrection_strategy,
heartbeat_basis: data.attributes.heartbeat_basis,
machine_uniqueness_strategy: data.attributes.machine_uniqueness_strategy,
component_uniqueness_strategy: data.attributes.component_uniqueness_strategy,
machine_matching_strategy: data.attributes.machine_matching_strategy,
component_matching_strategy: data.attributes.component_matching_strategy,
expiration_strategy: data.attributes.expiration_strategy,
expiration_basis: data.attributes.expiration_basis,
renewal_basis: data.attributes.renewal_basis,
authentication_strategy: data.attributes.authentication_strategy,
machine_leasing_strategy: data.attributes.machine_leasing_strategy,
process_leasing_strategy: data.attributes.process_leasing_strategy,
overage_strategy: data.attributes.overage_strategy,
transfer_strategy: data.attributes.transfer_strategy,
max_machines: data.attributes.max_machines,
max_processes: data.attributes.max_processes,
max_cores: data.attributes.max_cores,
max_uses: data.attributes.max_uses,
encrypted: data.attributes.encrypted,
protected: data.attributes.protected,
require_check_in: data.attributes.require_check_in,
check_in_interval: data.attributes.check_in_interval,
check_in_interval_count: data.attributes.check_in_interval_count,
use_pool: data.attributes.use_pool,
max_licenses: data.attributes.max_licenses,
max_users: data.attributes.max_users,
scheme: data.attributes.scheme,
metadata: data.attributes.metadata,
created: data.attributes.created,
updated: data.attributes.updated,
account_id: data
.relationships
.account
.as_ref()
.and_then(|a| a.data.as_ref().map(|d| d.id.clone())),
product_id: data
.relationships
.product
.as_ref()
.and_then(|p| p.data.as_ref().map(|d| d.id.clone())),
}
}
pub async fn create(request: CreatePolicyRequest) -> Result<Policy, Error> {
let client = Client::from_global_config()?;
let mut attributes = serde_json::Map::new();
attributes.insert("name".to_string(), serde_json::Value::String(request.name));
if let Some(duration) = request.duration {
attributes.insert(
"duration".to_string(),
serde_json::Value::Number(duration.into()),
);
}
if let Some(strict) = request.strict {
attributes.insert("strict".to_string(), serde_json::Value::Bool(strict));
}
if let Some(floating) = request.floating {
attributes.insert("floating".to_string(), serde_json::Value::Bool(floating));
}
if let Some(require_heartbeat) = request.require_heartbeat {
attributes.insert(
"requireHeartbeat".to_string(),
serde_json::Value::Bool(require_heartbeat),
);
}
if let Some(heartbeat_duration) = request.heartbeat_duration {
attributes.insert(
"heartbeatDuration".to_string(),
serde_json::Value::Number(heartbeat_duration.into()),
);
}
if let Some(ref heartbeat_cull_strategy) = request.heartbeat_cull_strategy {
attributes.insert(
"heartbeatCullStrategy".to_string(),
serde_json::Value::String(heartbeat_cull_strategy.clone()),
);
}
if let Some(ref heartbeat_resurrection_strategy) = request.heartbeat_resurrection_strategy {
attributes.insert(
"heartbeatResurrectionStrategy".to_string(),
serde_json::Value::String(heartbeat_resurrection_strategy.clone()),
);
}
if let Some(ref heartbeat_basis) = request.heartbeat_basis {
attributes.insert(
"heartbeatBasis".to_string(),
serde_json::Value::String(heartbeat_basis.clone()),
);
}
if let Some(machine_uniqueness_strategy) = request.machine_uniqueness_strategy {
attributes.insert(
"machineUniquenessStrategy".to_string(),
serde_json::to_value(machine_uniqueness_strategy)?,
);
}
if let Some(component_uniqueness_strategy) = request.component_uniqueness_strategy {
attributes.insert(
"componentUniquenessStrategy".to_string(),
serde_json::to_value(component_uniqueness_strategy)?,
);
}
if let Some(machine_matching_strategy) = request.machine_matching_strategy {
attributes.insert(
"machineMatchingStrategy".to_string(),
serde_json::to_value(machine_matching_strategy)?,
);
}
if let Some(component_matching_strategy) = request.component_matching_strategy {
attributes.insert(
"componentMatchingStrategy".to_string(),
serde_json::to_value(component_matching_strategy)?,
);
}
if let Some(expiration_strategy) = request.expiration_strategy {
attributes.insert(
"expirationStrategy".to_string(),
serde_json::to_value(expiration_strategy)?,
);
}
if let Some(ref expiration_basis) = request.expiration_basis {
attributes.insert(
"expirationBasis".to_string(),
serde_json::Value::String(expiration_basis.clone()),
);
}
if let Some(ref renewal_basis) = request.renewal_basis {
attributes.insert(
"renewalBasis".to_string(),
serde_json::Value::String(renewal_basis.clone()),
);
}
if let Some(authentication_strategy) = request.authentication_strategy {
attributes.insert(
"authenticationStrategy".to_string(),
serde_json::to_value(authentication_strategy)?,
);
}
if let Some(machine_leasing_strategy) = request.machine_leasing_strategy {
attributes.insert(
"machineLeasingStrategy".to_string(),
serde_json::to_value(machine_leasing_strategy)?,
);
}
if let Some(process_leasing_strategy) = request.process_leasing_strategy {
attributes.insert(
"processLeasingStrategy".to_string(),
serde_json::to_value(process_leasing_strategy)?,
);
}
if let Some(overage_strategy) = request.overage_strategy {
attributes.insert(
"overageStrategy".to_string(),
serde_json::to_value(overage_strategy)?,
);
}
if let Some(transfer_strategy) = request.transfer_strategy {
attributes.insert(
"transferStrategy".to_string(),
serde_json::to_value(transfer_strategy)?,
);
}
if let Some(max_machines) = request.max_machines {
attributes.insert(
"maxMachines".to_string(),
serde_json::Value::Number(max_machines.into()),
);
}
if let Some(max_processes) = request.max_processes {
attributes.insert(
"maxProcesses".to_string(),
serde_json::Value::Number(max_processes.into()),
);
}
if let Some(max_cores) = request.max_cores {
attributes.insert(
"maxCores".to_string(),
serde_json::Value::Number(max_cores.into()),
);
}
if let Some(max_uses) = request.max_uses {
attributes.insert(
"maxUses".to_string(),
serde_json::Value::Number(max_uses.into()),
);
}
if let Some(encrypted) = request.encrypted {
attributes.insert("encrypted".to_string(), serde_json::Value::Bool(encrypted));
}
if let Some(protected) = request.protected {
attributes.insert("protected".to_string(), serde_json::Value::Bool(protected));
}
if let Some(require_check_in) = request.require_check_in {
attributes.insert(
"requireCheckIn".to_string(),
serde_json::Value::Bool(require_check_in),
);
}
if let Some(ref check_in_interval) = request.check_in_interval {
attributes.insert(
"checkInInterval".to_string(),
serde_json::Value::String(check_in_interval.clone()),
);
}
if let Some(check_in_interval_count) = request.check_in_interval_count {
attributes.insert(
"checkInIntervalCount".to_string(),
serde_json::Value::Number(check_in_interval_count.into()),
);
}
if let Some(use_pool) = request.use_pool {
attributes.insert("usePool".to_string(), serde_json::Value::Bool(use_pool));
}
if let Some(max_licenses) = request.max_licenses {
attributes.insert(
"maxLicenses".to_string(),
serde_json::Value::Number(max_licenses.into()),
);
}
if let Some(max_users) = request.max_users {
attributes.insert(
"maxUsers".to_string(),
serde_json::Value::Number(max_users.into()),
);
}
if let Some(scheme) = request.scheme {
attributes.insert("scheme".to_string(), serde_json::to_value(scheme)?);
}
if let Some(ref metadata) = request.metadata {
attributes.insert("metadata".to_string(), serde_json::to_value(metadata)?);
}
let body = serde_json::json!({
"data": {
"type": "policies",
"attributes": attributes,
"relationships": {
"product": {
"data": {
"type": "products",
"id": request.product_id
}
}
}
}
});
let response = client.post("policies", Some(&body), None::<&()>).await?;
let policy_response: PolicyResponse = serde_json::from_value(response.body)?;
Ok(Policy::from(policy_response.data))
}
pub async fn list(options: Option<ListPoliciesOptions>) -> Result<Vec<Policy>, Error> {
let client = Client::from_global_config()?;
let response = client.get("policies", options.as_ref()).await?;
let policies_response: PoliciesResponse = serde_json::from_value(response.body)?;
Ok(policies_response
.data
.into_iter()
.map(Policy::from)
.collect())
}
pub async fn get(id: &str) -> Result<Policy, Error> {
let client = Client::from_global_config()?;
let endpoint = format!("policies/{id}");
let response = client.get(&endpoint, None::<&()>).await?;
let policy_response: PolicyResponse = serde_json::from_value(response.body)?;
Ok(Policy::from(policy_response.data))
}
pub async fn update(&self, request: UpdatePolicyRequest) -> Result<Policy, Error> {
let client = Client::from_global_config()?;
let endpoint = format!("policies/{}", self.id);
let mut attributes = serde_json::Map::new();
if let Some(name) = request.name {
attributes.insert("name".to_string(), serde_json::Value::String(name));
}
if let Some(duration) = request.duration {
attributes.insert(
"duration".to_string(),
serde_json::Value::Number(duration.into()),
);
}
if let Some(strict) = request.strict {
attributes.insert("strict".to_string(), serde_json::Value::Bool(strict));
}
if let Some(floating) = request.floating {
attributes.insert("floating".to_string(), serde_json::Value::Bool(floating));
}
if let Some(require_heartbeat) = request.require_heartbeat {
attributes.insert(
"requireHeartbeat".to_string(),
serde_json::Value::Bool(require_heartbeat),
);
}
if let Some(heartbeat_duration) = request.heartbeat_duration {
attributes.insert(
"heartbeatDuration".to_string(),
serde_json::Value::Number(heartbeat_duration.into()),
);
}
if let Some(expiration_strategy) = request.expiration_strategy {
attributes.insert(
"expirationStrategy".to_string(),
serde_json::to_value(expiration_strategy)?,
);
}
if let Some(authentication_strategy) = request.authentication_strategy {
attributes.insert(
"authenticationStrategy".to_string(),
serde_json::to_value(authentication_strategy)?,
);
}
if let Some(machine_leasing_strategy) = request.machine_leasing_strategy {
attributes.insert(
"machineLeasingStrategy".to_string(),
serde_json::to_value(machine_leasing_strategy)?,
);
}
if let Some(process_leasing_strategy) = request.process_leasing_strategy {
attributes.insert(
"processLeasingStrategy".to_string(),
serde_json::to_value(process_leasing_strategy)?,
);
}
if let Some(overage_strategy) = request.overage_strategy {
attributes.insert(
"overageStrategy".to_string(),
serde_json::to_value(overage_strategy)?,
);
}
if let Some(transfer_strategy) = request.transfer_strategy {
attributes.insert(
"transferStrategy".to_string(),
serde_json::to_value(transfer_strategy)?,
);
}
if let Some(max_machines) = request.max_machines {
attributes.insert(
"maxMachines".to_string(),
serde_json::Value::Number(max_machines.into()),
);
}
if let Some(max_processes) = request.max_processes {
attributes.insert(
"maxProcesses".to_string(),
serde_json::Value::Number(max_processes.into()),
);
}
if let Some(max_cores) = request.max_cores {
attributes.insert(
"maxCores".to_string(),
serde_json::Value::Number(max_cores.into()),
);
}
if let Some(max_uses) = request.max_uses {
attributes.insert(
"maxUses".to_string(),
serde_json::Value::Number(max_uses.into()),
);
}
if let Some(protected) = request.protected {
attributes.insert("protected".to_string(), serde_json::Value::Bool(protected));
}
if let Some(require_check_in) = request.require_check_in {
attributes.insert(
"requireCheckIn".to_string(),
serde_json::Value::Bool(require_check_in),
);
}
if let Some(check_in_interval) = request.check_in_interval {
attributes.insert(
"checkInInterval".to_string(),
serde_json::Value::String(check_in_interval),
);
}
if let Some(check_in_interval_count) = request.check_in_interval_count {
attributes.insert(
"checkInIntervalCount".to_string(),
serde_json::Value::Number(check_in_interval_count.into()),
);
}
if let Some(max_users) = request.max_users {
attributes.insert(
"maxUsers".to_string(),
serde_json::Value::Number(max_users.into()),
);
}
if let Some(scheme) = request.scheme {
attributes.insert("scheme".to_string(), serde_json::to_value(scheme)?);
}
if let Some(metadata) = request.metadata {
attributes.insert("metadata".to_string(), serde_json::to_value(metadata)?);
}
let body = serde_json::json!({
"data": {
"type": "policies",
"attributes": attributes
}
});
let response = client.patch(&endpoint, Some(&body), None::<&()>).await?;
let policy_response: PolicyResponse = serde_json::from_value(response.body)?;
Ok(Policy::from(policy_response.data))
}
pub async fn delete(&self) -> Result<(), Error> {
let client = Client::from_global_config()?;
let endpoint = format!("policies/{}", self.id);
client.delete::<(), ()>(&endpoint, None::<&()>).await?;
Ok(())
}
pub async fn pop_key(&self) -> Result<String, Error> {
let client = Client::from_global_config()?;
let endpoint = format!("policies/{}/pool", self.id);
let response: crate::client::Response<serde_json::Value> =
client.delete(&endpoint, None::<&()>).await?;
let key_data = response.body["data"]["attributes"]["key"]
.as_str()
.ok_or_else(|| Error::KeygenApiError {
code: "INVALID_RESPONSE".to_string(),
detail: "Invalid key response format".to_string(),
body: response.body.clone(),
})?;
Ok(key_data.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_scheme_serialization() {
let scheme = Scheme::Ed25519Sign;
let json = serde_json::to_string(&scheme).unwrap();
assert_eq!(json, "\"ED25519_SIGN\"");
let scheme = Scheme::Rsa2048Pkcs1PssSignV2;
let json = serde_json::to_string(&scheme).unwrap();
assert_eq!(json, "\"RSA_2048_PKCS1_PSS_SIGN_V2\"");
let scheme = Scheme::Rsa2048JwtRs256;
let json = serde_json::to_string(&scheme).unwrap();
assert_eq!(json, "\"RSA_2048_JWT_RS256\"");
let scheme = Scheme::LegacyEncrypt;
let json = serde_json::to_string(&scheme).unwrap();
assert_eq!(json, "\"LEGACY_ENCRYPT\"");
}
#[test]
fn test_scheme_deserialization() {
let json = "\"ED25519_SIGN\"";
let scheme: Scheme = serde_json::from_str(json).unwrap();
assert_eq!(scheme, Scheme::Ed25519Sign);
let json = "\"RSA_2048_PKCS1_PSS_SIGN_V2\"";
let scheme: Scheme = serde_json::from_str(json).unwrap();
assert_eq!(scheme, Scheme::Rsa2048Pkcs1PssSignV2);
let json = "\"LEGACY_ENCRYPT\"";
let scheme: Scheme = serde_json::from_str(json).unwrap();
assert_eq!(scheme, Scheme::LegacyEncrypt);
}
#[test]
fn test_deprecated_schemes() {
let json = "\"RSA_2048_PKCS1_PSS_SIGN\"";
let scheme: Scheme = serde_json::from_str(json).unwrap();
assert_eq!(scheme, Scheme::Rsa2048Pkcs1PssSign);
let json = "\"RSA_2048_PKCS1_SIGN\"";
let scheme: Scheme = serde_json::from_str(json).unwrap();
assert_eq!(scheme, Scheme::Rsa2048Pkcs1Sign);
}
#[test]
fn test_policy_relationships() {
use crate::{
KeygenRelationship, KeygenRelationshipData, KeygenRelationships, KeygenResponseData,
};
let policy_data = KeygenResponseData {
id: "test-policy-id".to_string(),
r#type: "policies".to_string(),
attributes: PolicyAttributes {
name: "Test Policy".to_string(),
duration: Some(3600),
strict: false,
floating: false,
require_heartbeat: false,
heartbeat_duration: None,
heartbeat_cull_strategy: None,
heartbeat_resurrection_strategy: None,
heartbeat_basis: None,
machine_uniqueness_strategy: None,
component_uniqueness_strategy: None,
machine_matching_strategy: None,
component_matching_strategy: None,
expiration_strategy: ExpirationStrategy::RestrictAccess,
expiration_basis: None,
renewal_basis: None,
authentication_strategy: AuthenticationStrategy::Token,
machine_leasing_strategy: LeasingStrategy::PerMachine,
process_leasing_strategy: LeasingStrategy::PerMachine,
overage_strategy: OverageStrategy::NoOverage,
transfer_strategy: TransferStrategy::KeepPolicy,
max_machines: Some(5),
max_processes: None,
max_cores: None,
max_uses: None,
encrypted: false,
protected: false,
require_check_in: false,
check_in_interval: None,
check_in_interval_count: None,
use_pool: false,
max_licenses: None,
max_users: None,
scheme: None,
metadata: None,
created: "2023-01-01T00:00:00Z".to_string(),
updated: "2023-01-01T00:00:00Z".to_string(),
},
relationships: KeygenRelationships {
policy: None,
account: Some(KeygenRelationship {
data: Some(KeygenRelationshipData {
r#type: "accounts".to_string(),
id: "test-account-id".to_string(),
}),
links: None,
}),
product: Some(KeygenRelationship {
data: Some(KeygenRelationshipData {
r#type: "products".to_string(),
id: "test-product-id".to_string(),
}),
links: None,
}),
group: None,
owner: None,
users: None,
machines: None,
environment: None,
license: None,
release: None,
other: HashMap::new(),
},
};
let policy = Policy::from(policy_data);
assert_eq!(policy.account_id, Some("test-account-id".to_string()));
assert_eq!(policy.product_id, Some("test-product-id".to_string()));
}
#[test]
fn test_ecdsa_p256_sign_serialization() {
let scheme = Scheme::EcdsaP256Sign;
let json = serde_json::to_string(&scheme).unwrap();
assert_eq!(json, "\"ECDSA_P256_SIGN\"");
}
#[test]
fn test_ecdsa_p256_sign_deserialization() {
let json = "\"ECDSA_P256_SIGN\"";
let scheme: Scheme = serde_json::from_str(json).unwrap();
assert_eq!(scheme, Scheme::EcdsaP256Sign);
}
#[test]
fn test_transfer_strategy_serialization() {
assert_eq!(
serde_json::to_string(&TransferStrategy::KeepPolicy).unwrap(),
"\"KEEP_POLICY\""
);
assert_eq!(
serde_json::to_string(&TransferStrategy::ResetPolicy).unwrap(),
"\"RESET_POLICY\""
);
assert_eq!(
serde_json::to_string(&TransferStrategy::KeepExpiry).unwrap(),
"\"KEEP_EXPIRY\""
);
assert_eq!(
serde_json::to_string(&TransferStrategy::ResetExpiry).unwrap(),
"\"RESET_EXPIRY\""
);
}
#[test]
fn test_transfer_strategy_deserialization() {
assert_eq!(
serde_json::from_str::<TransferStrategy>("\"KEEP_POLICY\"").unwrap(),
TransferStrategy::KeepPolicy
);
assert_eq!(
serde_json::from_str::<TransferStrategy>("\"RESET_POLICY\"").unwrap(),
TransferStrategy::ResetPolicy
);
assert_eq!(
serde_json::from_str::<TransferStrategy>("\"KEEP_EXPIRY\"").unwrap(),
TransferStrategy::KeepExpiry
);
assert_eq!(
serde_json::from_str::<TransferStrategy>("\"RESET_EXPIRY\"").unwrap(),
TransferStrategy::ResetExpiry
);
}
}