blob: b3e20a7e4d2adc20a1c9718d9caf90ba7b658199 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use super::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ConnectionCredentialKind {
Provider,
RequestHeaders,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum PasswordKind {
Password,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(
tag = "scope",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
pub enum CredentialLocator {
Connection {
connection_id: String,
kind: ConnectionCredentialKind,
},
NetworkProxy {
kind: PasswordKind,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CredentialIdentityBasis {
pub credential_id: String,
pub revision: u64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CredentialVersionBasis {
pub locator: CredentialLocator,
pub credential_id: String,
pub revision: u64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CredentialStatus {
pub locator: CredentialLocator,
pub state: CredentialState,
}
impl CredentialStatus {
pub fn basis(&self) -> Option<CredentialVersionBasis> {
let CredentialState::Configured {
credential_id,
revision,
..
} = &self.state
else {
return None;
};
Some(CredentialVersionBasis {
locator: self.locator.clone(),
credential_id: credential_id.clone(),
revision: *revision,
})
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum CredentialState {
Absent,
Configured {
credential_id: String,
revision: u64,
updated_at: u64,
},
}
impl Serialize for CredentialStatus {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let (configured, credential_id, revision, updated_at) = match &self.state {
CredentialState::Absent => (false, None, None, None),
CredentialState::Configured {
credential_id,
revision,
updated_at,
} => (true, Some(credential_id), Some(revision), Some(updated_at)),
};
let mut wire = serializer.serialize_struct("CredentialStatus", 5)?;
wire.serialize_field("locator", &self.locator)?;
wire.serialize_field("configured", &configured)?;
wire.serialize_field("credentialId", &credential_id)?;
wire.serialize_field("revision", &revision)?;
wire.serialize_field("updatedAt", &updated_at)?;
wire.end()
}
}
#[derive(Deserialize, schemars::JsonSchema)]
#[schemars(rename = "CredentialStatus")]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct CredentialStatusWire {
locator: CredentialLocator,
configured: bool,
// The wire requires these keys even when their values are null.
#[serde(deserialize_with = "Option::deserialize")]
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<String>")]
credential_id: Option<String>,
#[serde(deserialize_with = "Option::deserialize")]
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<u64>")]
revision: Option<u64>,
#[serde(deserialize_with = "Option::deserialize")]
#[schemars(with = "maka_plugin_core::wire_schema::RequiredNullable<u64>")]
updated_at: Option<u64>,
}
impl schemars::JsonSchema for CredentialStatus {
fn schema_name() -> std::borrow::Cow<'static, str> {
<CredentialStatusWire as schemars::JsonSchema>::schema_name()
}
fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
<CredentialStatusWire as schemars::JsonSchema>::json_schema(generator)
}
}
impl<'de> Deserialize<'de> for CredentialStatus {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let wire = CredentialStatusWire::deserialize(deserializer)?;
let state = match (
wire.configured,
wire.credential_id,
wire.revision,
wire.updated_at,
) {
(false, None, None, None) => CredentialState::Absent,
(true, Some(credential_id), Some(revision), Some(updated_at)) => {
CredentialState::Configured {
credential_id,
revision,
updated_at,
}
}
_ => {
return Err(serde::de::Error::custom(
"credential status metadata contradicts configured",
));
}
};
Ok(Self {
locator: wire.locator,
state,
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CredentialVaultSnapshot {
pub revision: u64,
pub entries: Vec<CredentialStatus>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CredentialVaultQueryInput {
pub locator: CredentialLocator,
}
/// Secret material deliberately has no Debug or public serialization.
#[derive(Clone, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SetCredentialInput {
pub locator: CredentialLocator,
pub expected: Option<CredentialIdentityBasis>,
pub expected_connection: Option<ConnectionCredentialTarget>,
pub secret: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct DeleteCredentialInput {
pub expected: CredentialVersionBasis,
/// Required for connection credentials; null for network credentials.
#[serde(deserialize_with = "Option::deserialize")]
#[schemars(
with = "maka_plugin_core::wire_schema::RequiredNullable<ConnectionCredentialTarget>"
)]
pub expected_connection: Option<ConnectionCredentialTarget>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
pub enum CredentialVaultQueryResult {
Status { status: CredentialStatus },
ConnectionNotFound,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(
tag = "kind",
rename_all = "snake_case",
rename_all_fields = "camelCase",
deny_unknown_fields
)]
pub enum CredentialMutationResult {
Rejected {
reason: super::ConfigurationRejection,
},
Committed {
vault_revision: u64,
status: CredentialStatus,
},
ConnectionNotFound,
ConnectionStale {
expected: ConnectionVersionBasis,
#[schemars(
with = "maka_plugin_core::wire_schema::RequiredNullable<ConnectionVersionBasis>"
)]
actual: Option<ConnectionVersionBasis>,
},
CredentialStale {
#[schemars(
with = "maka_plugin_core::wire_schema::RequiredNullable<CredentialVersionBasis>"
)]
expected: Option<CredentialVersionBasis>,
#[schemars(
with = "maka_plugin_core::wire_schema::RequiredNullable<CredentialVersionBasis>"
)]
actual: Option<CredentialVersionBasis>,
},
}
pub type SetCredentialResult = CredentialMutationResult;
pub type DeleteCredentialResult = CredentialMutationResult;