Implement session-owned first delivery and password reissue scenarios
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
//! Freshly authenticated publication of a saved client's configuration.
|
||||
|
||||
use super::{Application, ReissueDelivery, ReissueError, ReissueFailureKind, ReissueStage};
|
||||
use crate::delivery::files::{self, PreparedDestination};
|
||||
use crate::delivery::qr;
|
||||
use crate::delivery::{self, DeliverySettings};
|
||||
use crate::domain::PublicKey;
|
||||
use crate::vault::VaultBundle;
|
||||
use crate::wireguard::ConfigDocument;
|
||||
|
||||
impl Application {
|
||||
/// Reissue a saved client's configuration after freshly unlocking its
|
||||
/// installed vault record with this action's password. This operation reads
|
||||
/// only installed saved bytes, never uses a draft or retained source file,
|
||||
/// and publishes the required file before attempting optional QR encoding.
|
||||
pub fn reissue_client_file(
|
||||
&self,
|
||||
identity: PublicKey,
|
||||
password: &str,
|
||||
destination: PreparedDestination,
|
||||
include_qr: bool,
|
||||
) -> Result<ReissueDelivery, ReissueError> {
|
||||
let installed = self.store.read_saved().map_err(|_| ReissueError {
|
||||
stage: ReissueStage::SavedState,
|
||||
kind: ReissueFailureKind::SavedStateUnavailable,
|
||||
})?;
|
||||
let document =
|
||||
ConfigDocument::parse(&installed.server_config).map_err(|_| ReissueError {
|
||||
stage: ReissueStage::SavedState,
|
||||
kind: ReissueFailureKind::SavedStateUnavailable,
|
||||
})?;
|
||||
let encoded_vault = installed.vault.as_deref().ok_or(ReissueError {
|
||||
stage: ReissueStage::Authorization,
|
||||
kind: ReissueFailureKind::VaultUnavailable,
|
||||
})?;
|
||||
let vault_text = std::str::from_utf8(encoded_vault).map_err(|_| ReissueError {
|
||||
stage: ReissueStage::Authorization,
|
||||
kind: ReissueFailureKind::VaultUnavailable,
|
||||
})?;
|
||||
let vault = VaultBundle::from_toml(vault_text).map_err(|_| ReissueError {
|
||||
stage: ReissueStage::Authorization,
|
||||
kind: ReissueFailureKind::VaultUnavailable,
|
||||
})?;
|
||||
// Retrieval performs the password unlock and authenticated conflict
|
||||
// check on every invocation. The short-lived owner is dropped when
|
||||
// this method returns and is never kept in Application state.
|
||||
let record = vault
|
||||
.retrieve_client_record(identity, password)
|
||||
.map_err(|_| ReissueError {
|
||||
stage: ReissueStage::Authorization,
|
||||
kind: ReissueFailureKind::PasswordOrRecordRejected,
|
||||
})?;
|
||||
let resolved = self
|
||||
.store
|
||||
.resolved_settings_for(&installed)
|
||||
.map_err(|_| ReissueError {
|
||||
stage: ReissueStage::SavedState,
|
||||
kind: ReissueFailureKind::SavedStateUnavailable,
|
||||
})?;
|
||||
let delivery_settings = DeliverySettings {
|
||||
server_endpoint: &resolved.server_endpoint,
|
||||
dns_addresses: &resolved.dns_addresses,
|
||||
};
|
||||
let payload = if record.is_new_template() {
|
||||
delivery::render_new_client(
|
||||
identity,
|
||||
record.private_key().ok_or(ReissueError {
|
||||
stage: ReissueStage::Authorization,
|
||||
kind: ReissueFailureKind::PasswordOrRecordRejected,
|
||||
})?,
|
||||
&document,
|
||||
&delivery_settings,
|
||||
)
|
||||
} else {
|
||||
delivery::render_imported_client(identity, &record, &document, &delivery_settings)
|
||||
}
|
||||
.map_err(|_| ReissueError {
|
||||
stage: ReissueStage::Rendering,
|
||||
kind: ReissueFailureKind::ConfigurationRejected,
|
||||
})?;
|
||||
|
||||
files::publish(destination, &payload).map_err(|error| ReissueError {
|
||||
stage: ReissueStage::FilePublication,
|
||||
kind: ReissueFailureKind::FileOutput(error),
|
||||
})?;
|
||||
|
||||
// A historical timestamp is deliberately insufficient: after reopen,
|
||||
// the runtime observation is unknown. Warn unless this live session
|
||||
// has verified the exact saved peer snapshot currently on disk.
|
||||
let activation_warning = !self.saved_generation_is_verified_applied(&installed, &document);
|
||||
let qr = include_qr.then(|| qr::encode_payload(&payload));
|
||||
Ok(ReissueDelivery {
|
||||
activation_warning,
|
||||
qr,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user