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 }