taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

main.rs (5347B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 
     17 use anyhow::bail;
     18 use clap::Parser;
     19 use taler_api::config::{ApiCfg, AuthCfg};
     20 use taler_build::long_version;
     21 use taler_common::{
     22     CommonArgs,
     23     cli::ConfigCmd,
     24     config::Config,
     25     db::{dbinit, pool},
     26     taler_main,
     27 };
     28 use taler_magnet_bank::{
     29     config::{ServeCfg, WorkerCfg, parse_account_payto, parse_db_cfg},
     30     constants::CONFIG_SOURCE,
     31     dev::{self, DevCmd},
     32     run_serve, run_worker, setup,
     33 };
     34 
     35 #[derive(clap::Parser, Debug)]
     36 #[command(long_version = long_version(), about, long_about = None)]
     37 struct Args {
     38     #[clap(flatten)]
     39     common: CommonArgs,
     40 
     41     #[command(subcommand)]
     42     cmd: Command,
     43 }
     44 
     45 #[derive(clap::Subcommand, Debug)]
     46 enum Command {
     47     /// Initialize taler-magnet-bank database
     48     Dbinit {
     49         /// Reset database (DANGEROUS: All existing data is lost)
     50         #[clap(long, short)]
     51         reset: bool,
     52     },
     53     /// Setup taler-magnet-bank auth token and account settings for Wire Gateway use
     54     Setup {
     55         /// Reset connection info and overwrite keys file
     56         #[clap(long, short)]
     57         reset: bool,
     58     },
     59     /// Run taler-magnet-bank worker
     60     Worker {
     61         /// Execute once and return
     62         #[clap(long, short)]
     63         transient: bool,
     64     },
     65     /// Run taler-magnet-bank HTTP server
     66     Serve {
     67         /// Check whether an API is in use (if it's useful to start the HTTP
     68         /// server). Exit with 0 if at least one API is enabled, otherwise 1
     69         #[clap(long)]
     70         check: bool,
     71     },
     72     #[command(subcommand)]
     73     TalerDeployment(TalerDeployment),
     74     /// Hidden dev commands
     75     #[command(subcommand, hide(true))]
     76     Dev(DevCmd),
     77     #[command(subcommand)]
     78     Config(ConfigCmd),
     79 }
     80 
     81 /// Helpers to integrate taler-magnet-bank with taler-exchange
     82 #[derive(clap::Subcommand, Debug)]
     83 enum TalerDeployment {
     84     /// Output the exchange payto
     85     ExchangePayto,
     86     /// Output the wire gateway credentials configuration
     87     WireGatewayCredentials,
     88 }
     89 
     90 async fn run(cmd: Command, cfg: &Config) -> anyhow::Result<()> {
     91     match cmd {
     92         Command::Dbinit { reset } => {
     93             let cfg = parse_db_cfg(cfg)?;
     94             let pool = pool(cfg.cfg, "magnet_bank").await?;
     95             let mut conn = pool.acquire().await?;
     96             dbinit(&mut conn, cfg.sql_dir.as_ref(), "magnet-bank", reset).await?;
     97         }
     98         Command::Setup { reset } => {
     99             let cfg = WorkerCfg::parse(cfg)?;
    100             setup::setup(cfg, reset).await?
    101         }
    102         Command::Serve { check } => {
    103             if check {
    104                 let cfg = ServeCfg::parse(cfg)?;
    105                 if cfg.revenue.is_none() && cfg.wire_gateway.is_none() {
    106                     std::process::exit(1);
    107                 }
    108             } else {
    109                 let db = parse_db_cfg(cfg)?;
    110                 let pool = pool(db.cfg, "magnet_bank").await?;
    111                 run_serve(cfg, pool).await?;
    112             }
    113         }
    114         Command::Worker { transient: _ } => {
    115             let db = parse_db_cfg(cfg)?;
    116             let pool = pool(db.cfg, "magnet_bank").await?;
    117             let client = reqwest::Client::new();
    118             run_worker(cfg, &pool, &client).await?;
    119         }
    120         Command::Config(cfg_cmd) => cfg_cmd.run(cfg)?,
    121         Command::Dev(dev_cmd) => dev::dev(cfg, dev_cmd).await?,
    122         Command::TalerDeployment(cmd) => match cmd {
    123             TalerDeployment::ExchangePayto => {
    124                 let payto = parse_account_payto(cfg)?;
    125                 println!("{payto}");
    126             }
    127             TalerDeployment::WireGatewayCredentials => {
    128                 let wire_gateway =
    129                     ApiCfg::parse(cfg.section("magnet-bank-httpd-wire-gateway-api"))?;
    130                 let Some(wire_gateway) = wire_gateway else {
    131                     bail!("Wire Gateway API is disabled");
    132                 };
    133 
    134                 match wire_gateway.auth {
    135                     AuthCfg::Basic { username, password } => {
    136                         println!("WIRE_GATEWAY_AUTH_METHOD = basic");
    137                         println!("USERNAME = {username}");
    138                         println!("PASSWORD = {password}");
    139                     }
    140                     AuthCfg::Bearer(token) => {
    141                         println!("WIRE_GATEWAY_AUTH_METHOD = bearer");
    142                         println!("AUTH_TOKEN = {token}");
    143                     }
    144                     AuthCfg::None => {
    145                         println!("WIRE_GATEWAY_AUTH_METHOD = none");
    146                     }
    147                 }
    148             }
    149         },
    150     }
    151     Ok(())
    152 }
    153 
    154 fn main() {
    155     let args = Args::parse();
    156     taler_main(CONFIG_SOURCE, args.common, |cfg| async move {
    157         run(args.cmd, &cfg).await
    158     });
    159 }