//! Common structures and functionality for the CLI. //! //! Note: Prefer placing CLI implementations next to the associated structures, if possible. use core::cell::RefCell; use std::rc::Rc;
use anyhow::bail; use clap::{Args, ValueEnum}; use tracing::trace;
/// Work / OnPrem credentials, i.e. `<username:password>`. #[arg(
long,
requires = "work",
value_parser = WorkCredentials::from_colon_separated_str,
)] pub credentials: Option<WorkCredentials>,
}
/// Common configuration for the CLI. pubstruct CommonConfig { /// Configuration. pub config: Rc<Config>,
/// General flavour of the application. pub flavor: Flavor,
} impl CommonConfig { /// Create a [`CommonConfig`] from [`CommonConfigOptions`]. /// /// Note: This is only an asynchronous process for an OnPrem configuration in which case the OPPF file /// will be downloaded and verified. /// /// # Errors /// /// Returns an error if the options are invalid, or in case of an OnPrem configuration in case the /// OPPF file could not be downloaded or verified. pubasyncfn from_options(
http_client: &reqwest::Client,
options: CommonConfigOptions,
) -> anyhow::Result<Self> { let config = match (
options.consumer,
options.work,
options.onprem,
options.credentials,
) {
(Some(consumer_config), None, None, None) => Self {
config: Rc::new(Config::from(ConfigEnvironment::from(consumer_config))),
flavor: Flavor::Consumer,
},
/// Minimal identity configuration for the CLI. pubstruct MinimalIdentityConfig { /// Common configuration. pub common: CommonConfig,
/// The user's identity. pub user_identity: ThreemaId,
/// Client key. pub client_key: RawClientKey,
} impl MinimalIdentityConfig { /// Create an [`MinimalIdentityConfig`] from [`MinimalIdentityConfigOptions`]. /// /// Note: This is only an asynchronous process for an OnPrem configuration in which case the OPPF file /// will be downloaded and verified. /// /// # Errors /// /// Returns an error if the options are invalid, or in case of an OnPrem configuration in case the /// OPPF file could not be downloaded or verified. pubasyncfn from_options(
http_client: &reqwest::Client,
options: MinimalIdentityConfigOptions,
) -> anyhow::Result<Self> {
Ok(Self {
common: CommonConfig::from_options(http_client, options.common).await?,
user_identity: options.threema_id,
client_key: options.client_key,
})
}
/// Generate a [`RemoteSecretSetupContext`] from the config. /// /// # Errors /// /// Returns an error if the configuration flavor is not Work (or OnPrem). pubfn remote_secret_setup_context(&self) -> anyhow::Result<RemoteSecretSetupContext> { let Flavor::Work(work_context) = &self.common.flavor else {
bail!("Remote secret context only available for 'Work' flavor");
};
Ok(RemoteSecretSetupContext {
client_info: ClientInfo::Libthreema,
work_server_url: self.common.config.work_server_url.clone(),
work_context: work_context.clone(),
user_identity: self.user_identity,
client_key: ClientKey::from(&self.client_key),
})
}
/// Generate a [`RemoteSecretMonitorContext`] from the config. /// /// # Errors /// /// Returns an error if the configuration flavor is not Work (or OnPrem). #[must_use] pubfn remote_secret_monitor_context(
&self,
remote_secret_authentication_token: RemoteSecretAuthenticationToken,
remote_secret_hash: RemoteSecretHash,
) -> RemoteSecretMonitorContext {
RemoteSecretMonitorContext {
client_info: ClientInfo::Libthreema,
work_server_url: self.common.config.work_server_url.clone(),
remote_secret_authentication_token,
remote_secret_verifier: RemoteSecretVerifier::RemoteSecretHash(remote_secret_hash),
}
}
}
/// D2X configuration for the CLI. pubstruct D2xConfig { /// The device's D2X ID. pub d2x_device_id: D2xDeviceId,
/// The device's CSP ID. pub csp_device_id: CspDeviceId,
/// The device group key. pub device_group_key: RawDeviceGroupKey,
/// Optional D2X configuration. pub d2x_config: Option<D2xConfig>,
} impl FullIdentityConfig { /// Create an [`FullIdentityConfig`] from [`FullIdentityConfigOptions`]. /// /// Note: This is only an asynchronous process for an OnPrem configuration in which case the OPPF file /// will be downloaded and verified. /// /// # Errors /// /// Returns an error if the options are invalid, or in case of an OnPrem configuration in case the /// OPPF file could not be downloaded or verified. pubasyncfn from_options(
http_client: &reqwest::Client,
options: FullIdentityConfigOptions,
) -> anyhow::Result<Self> { let minimal = MinimalIdentityConfig::from_options(http_client, options.minimal).await?; let d2x_config: Option<D2xConfig> = options.d2x_config.into();
Ok(Self {
minimal,
csp_server_group: options.csp_server_group,
csp_device_cookie: options.csp_device_cookie,
d2x_config,
})
}
/// Generate a [`CspProtocolContextInit`] from the config. /// /// # Errors /// /// Returns an error if the configuration is invalid. #[must_use] pubfn csp_context_init(&self) -> CspProtocolContextInit {
CspProtocolContextInit {
permanent_server_keys: self.minimal.common.config.chat_server_public_keys.clone(),
identity: self.minimal.user_identity,
client_key: ClientKey::from(&self.minimal.client_key),
client_info: ClientInfo::Libthreema,
device_cookie: self.csp_device_cookie,
csp_device_id: self
.d2x_config
.as_ref()
.map(|d2x_config| d2x_config.csp_device_id),
}
}
/// Generate a [`CspE2eContextInit`] from the config. #[must_use] pubfn csp_e2e_context_init(&self, nonce_storage: Box<RefCell<dyn NonceStorage>>) -> CspE2eContextInit {
CspE2eContextInit {
user_identity: self.minimal.user_identity,
client_key: ClientKey::from(&self.minimal.client_key),
flavor: self.minimal.common.flavor.clone(),
nonce_storage,
}
}
/// Generate a [`D2mContext`] from the config, if multi-device has been enabled by the config. #[must_use] pubfn d2m_context(&self) -> Option<D2mContext> { let mediator_server_url = self
.minimal
.common
.config
.multi_device
.as_ref()
.map(|config| config.mediator_server_url.clone())?;
/// Generate a [`D2xContextInit`] from the config, if multi-device has been enabled by the config. #[must_use] pubfn d2x_context_init(&self, nonce_storage: Box<RefCell<dyn NonceStorage>>) -> Option<D2xContextInit> { self.d2x_config.as_ref().map(|d2x_config| D2xContextInit {
device_id: d2x_config.d2x_device_id,
device_group_key: DeviceGroupKey::from(&d2x_config.device_group_key),
nonce_storage,
})
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-22)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.