use crate::config::SmartIDConfig;
use crate::error::Result;
use crate::error::SmartIdClientError;
use crate::models::api::response::SmartIdAPIResponse;
use crate::models::common::{CertificateLevel, RequestProperties, VCCodeType};
use crate::models::interaction::{encode_interactions_base_64, Interaction};
use crate::models::signature::{
HashingAlgorithm, SignatureAlgorithm, SignatureProtocol, SignatureProtocolParameters,
};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
#[skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationDeviceLinkRequest {
#[serde(rename = "relyingPartyUUID")]
pub relying_party_uuid: String,
pub relying_party_name: String,
pub initial_callback_url: Option<String>,
pub certificate_level: AuthenticationCertificateLevel,
pub signature_protocol: SignatureProtocol,
pub signature_protocol_parameters: SignatureProtocolParameters,
pub interactions: String,
pub request_properties: Option<RequestProperties>,
pub capabilities: Option<Vec<String>>,
}
impl AuthenticationDeviceLinkRequest {
pub fn new(
cfg: &SmartIDConfig,
interactions: Vec<Interaction>,
signature_algorithm: SignatureAlgorithm,
authentication_certificate_level: AuthenticationCertificateLevel,
initial_callback_url: Option<String>,
hash_algorithm: HashingAlgorithm,
) -> Result<Self> {
if interactions.is_empty() {
return Err(SmartIdClientError::ConfigMissingException(
"Define at least 1 interaction for an authentication request",
));
};
for interaction in &interactions {
interaction.validate_text_length()?;
}
let encoded_interactions = encode_interactions_base_64(&interactions)?;
Ok(AuthenticationDeviceLinkRequest {
relying_party_uuid: cfg.relying_party_uuid.clone(),
relying_party_name: cfg.relying_party_name.clone(),
initial_callback_url,
certificate_level: authentication_certificate_level,
signature_protocol: SignatureProtocol::ACSP_V2,
signature_protocol_parameters: SignatureProtocolParameters::new_acsp_v2(
signature_algorithm,
hash_algorithm,
),
interactions: encoded_interactions,
request_properties: None,
capabilities: None,
})
}
}
pub(crate) type AuthenticationDeviceLinkResponse =
SmartIdAPIResponse<AuthenticationDeviceLinkSession>;
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationDeviceLinkSession {
#[serde(rename = "sessionID")]
pub session_id: String,
pub session_secret: String,
pub session_token: String,
pub device_link_base: String,
}
#[skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthenticationNotificationRequest {
#[serde(rename = "relyingPartyUUID")]
pub relying_party_uuid: String,
pub relying_party_name: String,
pub certificate_level: AuthenticationCertificateLevel,
pub signature_protocol: SignatureProtocol,
pub signature_protocol_parameters: SignatureProtocolParameters,
pub interactions: String,
pub request_properties: Option<RequestProperties>,
pub capabilities: Option<Vec<String>>,
pub vc_type: VCCodeType,
}
impl AuthenticationNotificationRequest {
pub fn new(
cfg: &SmartIDConfig,
interactions: Vec<Interaction>,
signature_algorithm: SignatureAlgorithm,
authentication_certificate_level: AuthenticationCertificateLevel,
hash_algorithm: HashingAlgorithm,
) -> Result<Self> {
if interactions.is_empty() {
return Err(SmartIdClientError::ConfigMissingException(
"Define at least 1 interaction for an authentication request",
));
};
for interaction in &interactions {
interaction.validate_text_length()?;
}
let encoded_interactions = encode_interactions_base_64(&interactions)?;
Ok(AuthenticationNotificationRequest {
relying_party_uuid: cfg.relying_party_uuid.clone(),
relying_party_name: cfg.relying_party_name.clone(),
certificate_level: authentication_certificate_level,
signature_protocol: SignatureProtocol::ACSP_V2,
signature_protocol_parameters: SignatureProtocolParameters::new_acsp_v2(
signature_algorithm,
hash_algorithm,
),
interactions: encoded_interactions,
request_properties: None,
capabilities: None,
vc_type: VCCodeType::numeric4,
})
}
}
pub(crate) type AuthenticationNotificationResponse =
SmartIdAPIResponse<AuthenticationNotificationSession>;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticationNotificationSession {
#[serde(rename = "sessionID")]
pub session_id: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
#[non_exhaustive]
pub enum AuthenticationCertificateLevel {
QUALIFIED,
ADVANCED,
}
impl From<AuthenticationCertificateLevel> for CertificateLevel {
fn from(val: AuthenticationCertificateLevel) -> Self {
match val {
AuthenticationCertificateLevel::QUALIFIED => CertificateLevel::QUALIFIED,
AuthenticationCertificateLevel::ADVANCED => CertificateLevel::ADVANCED,
}
}
}