taler-rust

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

commit 57befcb34e1562f2c8cdde4856b2af3445faa7a9
parent 23824a4cff08725f0ac6683df8a373d771ce9365
Author: Antoine A <>
Date:   Thu, 15 Jan 2026 13:04:28 +0100

cyclos: check root url during setup

Diffstat:
Mcommon/http-client/src/lib.rs | 4++--
Mtaler-cyclos/src/config.rs | 2++
Mtaler-cyclos/src/cyclos_api/client.rs | 9++++++++-
Mtaler-cyclos/src/cyclos_api/types.rs | 13++++++++++++-
Mtaler-cyclos/src/setup.rs | 17+++++++++++++++++
5 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/common/http-client/src/lib.rs b/common/http-client/src/lib.rs @@ -100,9 +100,9 @@ impl Display for Ctx { method, status, } = self; - write!(f, "{path} {method} ")?; + write!(f, "{path} {method}")?; if let Some(status) = status { - write!(f, "{status}")?; + write!(f, " {status}")?; } Ok(()) } diff --git a/taler-cyclos/src/config.rs b/taler-cyclos/src/config.rs @@ -128,6 +128,7 @@ impl ServeCfg { /// taler-cyclos setup config pub struct SetupCfg { pub currency: Currency, + pub root: Url, pub host: HostCfg, pub id: Option<CyclosId>, pub name: Option<String>, @@ -151,6 +152,7 @@ impl SetupCfg { name: main_s.str("NAME").opt()?, host: HostCfg::parse(cfg, &main)?, currency: main.currency, + root: main.url, }) } } diff --git a/taler-cyclos/src/cyclos_api/client.rs b/taler-cyclos/src/cyclos_api/client.rs @@ -25,7 +25,8 @@ use url::Url; use crate::cyclos_api::{ api::{ApiResult, CyclosAuth, CyclosRequest}, types::{ - Account, DataForTransaction, HistoryItem, OrderBy, Pagination, Transaction, Transfer, User, + Account, DataForTransaction, DataForUi, HistoryItem, OrderBy, Pagination, Transaction, + Transfer, User, }, }; @@ -40,6 +41,12 @@ impl Client<'_> { CyclosRequest::new(self.client, method, self.api_url, path, self.auth) } + pub async fn data_for_ui(&self) -> ApiResult<DataForUi> { + self.request(Method::GET, "ui/data-for-ui") + .parse_json() + .await + } + pub async fn whoami(&self) -> ApiResult<User> { self.request(Method::GET, "users/self").parse_json().await } diff --git a/taler-cyclos/src/cyclos_api/types.rs b/taler-cyclos/src/cyclos_api/types.rs @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2025 Taler Systems SA + Copyright (C) 2025, 2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -20,6 +20,7 @@ use compact_str::CompactString; use jiff::Timestamp; use serde::{Deserialize, Serialize}; use taler_common::types::{amount::Decimal, payto::FullPayto}; +use url::Url; use crate::{CyclosAccount, CyclosId, FullCyclosPayto}; @@ -247,6 +248,16 @@ pub struct Notification { #[derive(Debug, serde::Deserialize)] #[serde(rename_all = "camelCase")] +pub struct DataForUi { + pub cyclos_version: String, + pub cyclos_revision: String, + pub root_url: Url, + pub api_url: Url, + pub application_name: String, +} + +#[derive(Debug, serde::Deserialize)] +#[serde(rename_all = "camelCase")] pub enum UserStatus { Active, Blocked, diff --git a/taler-cyclos/src/setup.rs b/taler-cyclos/src/setup.rs @@ -38,6 +38,23 @@ pub async fn setup(cfg: &Config, _reset: bool, client: &http_client::Client) -> info!(target: "setup", "Check API access and configuration"); let mut ready = true; + let data = Client { + auth: &CyclosAuth::None, + ..client + } + .data_for_ui() + .await?; + + info!(target: "setup", "Connecting to '{}' v{}-{}", data.application_name, data.cyclos_version, &data.cyclos_revision[..8]); + + // Check root URL + if cfg.root != data.root_url { + warn!(target: "setup", + "Expected CYCLOS_URL '{}' from config got '{}' from server", + cfg.root, data.root_url + ); + } + let whoami = client.whoami().await?; if let Some(id) = cfg.id { if whoami.id != id {