| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- //! Example for creating a new Threema ID.
- #![expect(unused_crate_dependencies, reason = "Example triggered false positive")]
- #![expect(clippy::print_stdout, reason = "Examples are allowed to print")]
- use clap::{Parser, Subcommand};
- use data_encoding::HEXLOWER;
- use libthreema::{
- cli::{MinimalIdentityConfig, MinimalIdentityConfigOptions},
- common::keys::{RemoteSecretAuthenticationToken, RemoteSecretHash},
- https::cli::https_client_builder,
- remote_secret::{
- monitor::{
- RemoteSecretMonitorContext, RemoteSecretMonitorInstruction, RemoteSecretMonitorProtocol,
- RemoteSecretMonitorResponse,
- },
- setup::{
- RemoteSecretSetupContext, RemoteSecretSetupResponse,
- create::{RemoteSecretCreateLoop, RemoteSecretCreateResult, RemoteSecretCreateTask},
- delete::{RemoteSecretDeleteLoop, RemoteSecretDeleteTask},
- },
- },
- utils::logging::init_stderr_logging,
- };
- use tokio::time;
- use tracing::{Level, debug, info};
- #[derive(Parser)]
- #[command()]
- struct RemoteSecretCommand {
- #[command(flatten)]
- config: MinimalIdentityConfigOptions,
- #[command(subcommand)]
- command: Commands,
- }
- #[derive(Subcommand)]
- enum Commands {
- Create,
- Delete {
- #[arg(long, value_parser = RemoteSecretAuthenticationToken::from_hex)]
- remote_secret_authentication_token: RemoteSecretAuthenticationToken,
- },
- Monitor {
- #[arg(long, value_parser = RemoteSecretAuthenticationToken::from_hex)]
- remote_secret_authentication_token: RemoteSecretAuthenticationToken,
- #[arg(long, value_parser = RemoteSecretHash::from_hex)]
- remote_secret_hash: RemoteSecretHash,
- },
- }
- async fn run_create_remote_secret(
- http_client: reqwest::Client,
- context: RemoteSecretSetupContext,
- ) -> anyhow::Result<RemoteSecretCreateResult> {
- let mut task = RemoteSecretCreateTask::new(context);
- loop {
- match task.poll()? {
- RemoteSecretCreateLoop::Instruction(instruction) => {
- let result = instruction.request.send(&http_client).await;
- task.response(RemoteSecretSetupResponse { result })?;
- },
- RemoteSecretCreateLoop::Done(result) => return Ok(result),
- }
- }
- }
- async fn run_delete_remote_secret(
- http_client: reqwest::Client,
- context: RemoteSecretSetupContext,
- remote_secret_authentication_token: RemoteSecretAuthenticationToken,
- ) -> anyhow::Result<()> {
- let mut task = RemoteSecretDeleteTask::new(context, remote_secret_authentication_token);
- loop {
- match task.poll()? {
- RemoteSecretDeleteLoop::Instruction(instruction) => {
- let result = instruction.request.send(&http_client).await;
- task.response(RemoteSecretSetupResponse { result })?;
- },
- RemoteSecretDeleteLoop::Done(()) => return Ok(()),
- }
- }
- }
- async fn run_monitor_remote_secret(
- http_client: reqwest::Client,
- context: RemoteSecretMonitorContext,
- ) -> anyhow::Result<()> {
- let mut protocol = RemoteSecretMonitorProtocol::new(context);
- loop {
- match protocol.poll()? {
- RemoteSecretMonitorInstruction::Request(https_request) => {
- let result = https_request.send(&http_client).await;
- protocol.response(RemoteSecretMonitorResponse { result })?;
- },
- RemoteSecretMonitorInstruction::Schedule {
- timeout,
- remote_secret,
- } => {
- if let Some(remote_secret) = remote_secret {
- info!(
- remote_secret = HEXLOWER.encode(&remote_secret.0),
- remote_secret_hash = ?remote_secret.derive_hash(),
- "Retrieved remote secret",
- );
- }
- debug!(?timeout, "Scheduling another poll");
- time::sleep(timeout).await;
- },
- }
- }
- }
- #[tokio::main]
- async fn main() -> anyhow::Result<()> {
- // Configure logging
- init_stderr_logging(Level::TRACE);
- // Create HTTP client
- let http_client = https_client_builder().build()?;
- // Parse arguments for command
- let arguments = RemoteSecretCommand::parse();
- let config = MinimalIdentityConfig::from_options(&http_client, arguments.config).await?;
- match arguments.command {
- Commands::Create => {
- let context = config.remote_secret_setup_context()?;
- let result = run_create_remote_secret(http_client, context).await?;
- println!(
- "--remote-secret-authentication-token {}",
- HEXLOWER.encode(&result.remote_secret_authentication_token.0)
- );
- println!(
- "--remote-secret-hash {}",
- HEXLOWER.encode(&result.remote_secret.derive_hash().0)
- );
- },
- Commands::Delete {
- remote_secret_authentication_token,
- } => {
- let context = config.remote_secret_setup_context()?;
- run_delete_remote_secret(http_client, context, remote_secret_authentication_token).await?;
- },
- Commands::Monitor {
- remote_secret_authentication_token,
- remote_secret_hash,
- } => {
- let context =
- config.remote_secret_monitor_context(remote_secret_authentication_token, remote_secret_hash);
- run_monitor_remote_secret(http_client, context).await?;
- },
- }
- Ok(())
- }
- #[test]
- fn verify_cli() {
- use clap::CommandFactory;
- RemoteSecretCommand::command().debug_assert();
- }
|