commit e5c3c0d1d2561d43829200321f4fd326174987ce
parent 23acdbd445d2a9a8f22eecc2459cc4e962d4a4f1
Author: Antoine A <>
Date: Fri, 4 Sep 2026 13:08:51 +0200
bank: fix token API
Diffstat:
15 files changed, 195 insertions(+), 78 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -170,9 +170,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "aws-lc-rs"
-version = "1.18.0"
+version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e"
+checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
dependencies = [
"aws-lc-sys",
"untrusted 0.7.1",
@@ -181,9 +181,9 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
-version = "0.44.0"
+version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483"
+checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
dependencies = [
"cc",
"cmake",
@@ -390,9 +390,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.4.4"
+version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273"
+checksum = "005ec2760ca554fae18df7a11195552ec576cd665632a881bc011d5bb2fd4d80"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -1005,9 +1005,9 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
-version = "0.1.11"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
+checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d"
[[package]]
name = "flate2"
@@ -1349,7 +1349,7 @@ dependencies = [
[[package]]
name = "http-client"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
+source = "git+git://git.taler.net/taler-rust.git/#14f571a7e85caf215a7e9995914026f064f488fe"
dependencies = [
"compact_str",
"futures-util",
@@ -1917,9 +1917,9 @@ dependencies = [
[[package]]
name = "libredox"
-version = "0.1.21"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7955dfc218a8afb29dfeffd540e3a6e96baeb94fe7138228dd7cc6937fbbf96"
+checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed"
dependencies = [
"bitflags 2.13.1",
"libc",
@@ -2042,9 +2042,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "mio"
-version = "1.2.2"
+version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
+checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8"
dependencies = [
"libc",
"log",
@@ -3090,9 +3090,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
-version = "1.15.2"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
+checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f"
dependencies = [
"serde",
]
@@ -3451,7 +3451,7 @@ dependencies = [
[[package]]
name = "taler-api"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
+source = "git+git://git.taler.net/taler-rust.git/#14f571a7e85caf215a7e9995914026f064f488fe"
dependencies = [
"aws-lc-rs",
"axum",
@@ -3479,12 +3479,12 @@ dependencies = [
[[package]]
name = "taler-build"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
+source = "git+git://git.taler.net/taler-rust.git/#14f571a7e85caf215a7e9995914026f064f488fe"
[[package]]
name = "taler-common"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
+source = "git+git://git.taler.net/taler-rust.git/#14f571a7e85caf215a7e9995914026f064f488fe"
dependencies = [
"anyhow",
"aws-lc-rs",
@@ -3514,7 +3514,7 @@ dependencies = [
[[package]]
name = "taler-macros"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
+source = "git+git://git.taler.net/taler-rust.git/#14f571a7e85caf215a7e9995914026f064f488fe"
dependencies = [
"proc-macro2",
"quote",
@@ -3524,7 +3524,7 @@ dependencies = [
[[package]]
name = "taler-test-utils"
version = "1.5.0"
-source = "git+git://git.taler.net/taler-rust.git/#48c40c365ac671cbbe1ac2fb359e1a5cf7e165a3"
+source = "git+git://git.taler.net/taler-rust.git/#14f571a7e85caf215a7e9995914026f064f488fe"
dependencies = [
"aws-lc-rs",
"axum",
@@ -3661,9 +3661,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.12.0"
+version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
+checksum = "4cf0ded5c4e56918d8f8a339e1bb67d038d3bc6d144ac407904015ba2e4cde9b"
dependencies = [
"tinyvec_macros",
]
@@ -3703,9 +3703,9 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.26.4"
+version = "0.26.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
+checksum = "b0c85f2c3ef0b1cd58b36682f4b17aaa995f0e5db534d85692b4903abce21f67"
dependencies = [
"rustls",
"tokio",
diff --git a/libeufin-bank/src/api.rs b/libeufin-bank/src/api.rs
@@ -354,7 +354,7 @@ pub mod test {
async {
let res = pw_auth(
self.server.post(format!("/accounts/{username}/token")),
- Some("admin"),
+ Some(&username),
)
.json(json!({
"scope": "readwrite",
@@ -363,6 +363,8 @@ pub mod test {
}
}))
.await
+ .maybe_challenge(&self)
+ .await
.assert_ok_json::<serde_json::Value>();
let token = res["access_token"].as_str().unwrap();
(username, format!("Bearer {token}"))
@@ -477,7 +479,12 @@ pub mod test {
.await
.assert_error(ErrorCode::GENERIC_FORBIDDEN);
}
- Auth::UserOrAdmin | Auth::Token | Auth::Optional => {}
+ Auth::UserOrAdmin | Auth::Optional => {}
+ Auth::Token => {
+ self.requesta(method.clone(), path, Some("admin"))
+ .await
+ .assert_error(ErrorCode::GENERIC_TOKEN_PERMISSION_INSUFFICIENT);
+ }
Auth::UserOnly => {
self.requesta(method.clone(), path, Some("admin"))
.await
@@ -885,21 +892,21 @@ pub mod test {
pub trait MfaRequest {
fn assert_challenge_check(
&self,
- ctx: &BankTestCtx,
+ ctx: &BankClient,
check: impl AsyncFnOnce(&ChallengeResponse),
) -> impl std::future::Future<Output = Self>;
- fn assert_challenge(&self, ctx: &BankTestCtx) -> impl std::future::Future<Output = Self> {
+ fn assert_challenge(&self, ctx: &BankClient) -> impl std::future::Future<Output = Self> {
self.assert_challenge_check(ctx, async |_| {})
}
- fn maybe_challenge(self, ctx: &BankTestCtx) -> impl std::future::Future<Output = Self>;
+ fn maybe_challenge(self, ctx: &BankClient) -> impl std::future::Future<Output = Self>;
}
impl MfaRequest for TestResponse {
async fn assert_challenge_check(
&self,
- ctx: &BankTestCtx,
+ ctx: &BankClient,
check: impl AsyncFnOnce(&ChallengeResponse),
) -> TestResponse {
let res: ChallengeResponse = self.assert_accepted_json();
@@ -912,7 +919,7 @@ pub mod test {
};
for challenge in challenges {
- ctx.posta(format!(
+ ctx.post(format!(
"/accounts/{username}/challenge/{}",
challenge.challenge_id
))
@@ -922,8 +929,13 @@ pub mod test {
check(&res).await;
for challenge in challenges {
- let code = tan_code(&challenge.tan_info).unwrap();
- ctx.posta(format!(
+ let info = if challenge.tan_info == "REDACTED" {
+ "+456"
+ } else {
+ &challenge.tan_info
+ };
+ let code = tan_code(info).unwrap();
+ ctx.post(format!(
"/accounts/{username}/challenge/{}/confirm",
challenge.challenge_id
))
@@ -937,13 +949,19 @@ pub mod test {
.into_iter()
.map(|it| it.challenge_id)
.join_compact(", ");
- ctx.requesta(self.method.clone(), self.uri.path(), Some(username))
- .header(TALER_CHALLENGE_IDS, ids.to_string())
- .raw_json(self.req_body.clone())
- .await
+ let req = ctx
+ .request(self.method.clone(), self.uri.path())
+ .header(TALER_CHALLENGE_IDS, ids.to_string());
+ if let Some(auth) = self.req_headers.get(AUTHORIZATION) {
+ req.header(AUTHORIZATION, auth)
+ } else {
+ req
+ }
+ .raw_json(self.req_body.clone())
+ .await
}
- async fn maybe_challenge(self, ctx: &BankTestCtx) -> Self {
+ async fn maybe_challenge(self, ctx: &BankClient) -> Self {
if self.status == StatusCode::ACCEPTED {
self.assert_challenge(ctx).await
} else {
diff --git a/libeufin-bank/src/api/account.rs b/libeufin-bank/src/api/account.rs
@@ -561,7 +561,9 @@ pub fn account_api() -> Router<Arc<BankState>> {
mfa.response_validation(&auth, &state.db, &tans).await
}
}
- PatchResult::UnknownAccount => todo!(),
+ PatchResult::UnknownAccount => {
+ Err(failure_code(ErrorCode::BANK_UNKNOWN_ACCOUNT))
+ }
PatchResult::NonAdminName => {
Err(failure_code(ErrorCode::BANK_NON_ADMIN_PATCH_LEGAL_NAME))
}
@@ -801,10 +803,10 @@ pub async fn create_account(
}
/**
- * This function creates the admin account ONLY IF it was
- * NOT found in the database. It sets it to a random password that
- * is only meant to be overridden by a dedicated CLI tool
- */
+* This function creates the admin account ONLY IF it was
+* NOT found in the database. It sets it to a random password that
+* is only meant to be overridden by a dedicated CLI tool
+*/
pub async fn create_admin_account(
db: &PgPool,
cfg: &BankCfg,
@@ -1165,11 +1167,11 @@ pub mod test {
.assert_error(ErrorCode::BANK_PASSWORD_TOO_SHORT);
// Long password
ctx.post("/accounts")
- .json(json!(req +{
- "password": "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password"
- }))
- .await
- .assert_error(ErrorCode::BANK_PASSWORD_TOO_LONG);
+ .json(json!(req +{
+ "password": "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong-password"
+ }))
+ .await
+ .assert_error(ErrorCode::BANK_PASSWORD_TOO_LONG);
// Check currency
ctx.post_admin("/accounts")
.json(json!(req + { "debit_threshold": "EUR:100" }))
@@ -1392,7 +1394,7 @@ pub mod test {
#[tokio::test]
async fn delete() {
let mut ctx = bank_setup().await;
- ctx.auth_routine(Method::DELETE, "/accounts/merchant", Auth::Token)
+ ctx.auth_routine(Method::DELETE, "/accounts/merchant", Auth::UserOrAdmin)
.await;
// Reserved accounts
diff --git a/libeufin-bank/src/api/cashout.rs b/libeufin-bank/src/api/cashout.rs
@@ -36,7 +36,7 @@ use taler_api::{
use taler_common::{
api::{ShortHashCode, params::PageParams},
error_code::ErrorCode,
- types::{amount::Amount, timestamp::TalerTimestamp},
+ types::{amount::Amount, time::TalerTimestamp},
};
use crate::{
diff --git a/libeufin-bank/src/api/prepared.rs b/libeufin-bank/src/api/prepared.rs
@@ -38,7 +38,7 @@ use taler_common::{
TransferSubject, Unregistration,
},
error_code::ErrorCode,
- types::timestamp::TalerTimestamp,
+ types::time::TalerTimestamp,
};
use crate::{
diff --git a/libeufin-bank/src/api/tan.rs b/libeufin-bank/src/api/tan.rs
@@ -33,8 +33,9 @@ use taler_api::{
error::{failure, failure_code},
extract::{Path, Req},
};
-use taler_common::{error_code::ErrorCode, types::timestamp::TalerTimestamp};
+use taler_common::{error_code::ErrorCode, types::time::TalerTimestamp};
use tokio::{io::AsyncWriteExt as _, process::Command};
+use tracing::trace;
use uuid::Uuid;
use crate::{
@@ -88,6 +89,7 @@ pub fn tan_api() -> Router<Arc<BankState>> {
} => {
let (script, env) = &state.cfg.tan_channels[&channel];
let msg = format!("T-{code} is your {} verification code", state.cfg.name);
+ trace!(target: "tan", "send {code} with {script}");
let res = async {
let mut child = Command::new(script)
.arg(&info)
diff --git a/libeufin-bank/src/api/token.rs b/libeufin-bank/src/api/token.rs
@@ -36,13 +36,13 @@ use taler_common::{
error_code::ErrorCode::{self},
types::{
base32::Base32,
- timestamp::{RelativeTime, TalerTimestamp},
+ time::{RelativeTime, TalerTimestamp},
},
};
use crate::{
api::BankState,
- auth::{TOKEN_PREFIX, TokenScope, UserAuth, UserRAuth, UserRWAuth},
+ auth::{TOKEN_PREFIX, TokenScope, UserAuth, UserORWAuth, UserRAuth},
db::{
self,
token::{TokenCreationResult, access, create, refresh},
@@ -177,7 +177,7 @@ pub fn token_api() -> Router<Arc<BankState>> {
.route(
"/accounts/{username}/tokens/{id}",
delete(
- async |UserAuth { username, .. }: UserRWAuth,
+ async |UserAuth { username, .. }: UserORWAuth,
Path((_, id)): Path<((), u64)>,
State(state): State<Arc<BankState>>| {
if db::token::delete_by_id(&state.db, &username, id).await? {
@@ -221,12 +221,13 @@ pub mod test {
use taler_common::{
api::ErrorDetail,
error_code::ErrorCode,
- types::{base32::Base32, timestamp::TalerTimestamp},
+ types::{base32::Base32, time::TalerTimestamp},
};
use taler_test_utils::{json, server::TestServer};
use crate::{
api::{
+ account::AccountData,
tan::ChallengeResponse,
test::{Auth, MfaRequest, bank_setup, tan_code},
token::{TOKEN_DEFAULT_DURATION, TokenInfos, TokenSuccessResponse},
@@ -245,7 +246,7 @@ pub mod test {
ctx.auth_routine(
Method::DELETE,
"/accounts/merchant/tokens/1",
- Auth::UserOrAdmin,
+ Auth::UserOnly,
)
.await;
@@ -486,6 +487,43 @@ pub mod test {
.unwrap()
);
+ // Kotlin compatibility
+ {
+ let TokenSuccessResponse {
+ access_token,
+ token_id,
+ ..
+ } = ctx
+ .postpw("/accounts/customer/token")
+ .json(json!({
+ "scope": "readonly",
+ "refreshable" : true
+ }))
+ .await
+ .assert_ok_json();
+ // Patch ID to use old sentinel value
+ sqlx::query(
+ "UPDATE bearer_tokens SET expiration_time=9223372036854775807 WHERE bearer_token_id=$1",
+ )
+ .bind(token_id as i64)
+ .execute(&ctx.state.db)
+ .await
+ .unwrap();
+ // Check token works
+ ctx.get("/accounts/customer/tokens")
+ .header(AUTHORIZATION, format!("Bearer {access_token}"))
+ .await
+ .assert_ok();
+ // And can be refreshed
+ ctx.post("/accounts/customer/token")
+ .header(AUTHORIZATION, format!("Bearer {access_token}"))
+ .json(json!({
+ "scope": "readonly"
+ }))
+ .await
+ .assert_ok();
+ }
+
// 2FA
{
// Setup a known phone 2FA
@@ -578,7 +616,44 @@ pub mod test {
lock_account().await;
// Check token still works
- // TODO
+ assert!(
+ ctx.geta("/accounts/merchant")
+ .await
+ .assert_ok_json::<AccountData>()
+ .is_locked
+ );
+
+ // Check admin can unlock
+ ctx.patch_admin("/accounts/merchant/auth")
+ .json(json!({
+ "new_password": "merchant-password"
+ }))
+ .await
+ .assert_no_content();
+ assert!(
+ !ctx.geta("/accounts/merchant")
+ .await
+ .assert_ok_json::<AccountData>()
+ .is_locked
+ );
+ lock_account().await;
+
+ // Check token can unlock
+ ctx.patcha("/accounts/merchant/auth")
+ .json(json!({
+ "old_password": "merchant-password",
+ "new_password": "merchant-password"
+ }))
+ .await
+ .assert_challenge(&ctx)
+ .await
+ .assert_no_content();
+ assert!(
+ !ctx.geta("/accounts/merchant")
+ .await
+ .assert_ok_json::<AccountData>()
+ .is_locked
+ );
}
}
@@ -590,9 +665,11 @@ pub mod test {
// Check OK
for account in ["merchant", "customer"] {
- ctx.geta(format!("/accounts/{account}/tokens"))
+ let res = ctx
+ .geta(format!("/accounts/{account}/tokens"))
.await
- .assert_no_content();
+ .assert_ok_json::<TokenInfos>();
+ assert_eq!(res.tokens.len(), 1);
}
for scope in ["readonly", "readwrite"] {
ctx.postpw("/accounts/merchant/token")
@@ -600,20 +677,38 @@ pub mod test {
.await
.assert_ok();
}
- ctx.postpw("/accounts/customer/token")
+ ctx.postpw("/accounts/merchant/token")
+ .json(json!({
+ "scope": "revenue",
+ "duration": {
+ "d_us": "forever"
+ }
+ }))
+ .await
+ .assert_ok();
+ ctx.postpw("/accounts/merchant/token")
.json(json!({
"scope": "revenue",
+ "duration": {
+ "d_us": 0
+ }
+ }))
+ .await
+ .assert_ok();
+ ctx.postpw("/accounts/customer/token")
+ .json(json!({
+ "scope": "readonly",
"description": "description"
}))
.await
.assert_ok();
let res: TokenInfos = ctx.geta("/accounts/merchant/tokens").await.assert_ok_json();
- assert_eq!(res.tokens.len(), 2);
+ assert_eq!(res.tokens.len(), 4);
for token in res.tokens {
assert_eq!(token.description, None);
}
let res: TokenInfos = ctx.geta("/accounts/customer/tokens").await.assert_ok_json();
- assert_eq!(res.tokens.len(), 1);
+ assert_eq!(res.tokens.len(), 2);
assert_eq!(res.tokens[0].description.as_deref(), Some("description"));
}
}
diff --git a/libeufin-bank/src/api/tx.rs b/libeufin-bank/src/api/tx.rs
@@ -36,7 +36,7 @@ use taler_api::{
use taler_common::{
api::{ShortHashCode, params::HistoryParams},
error_code::ErrorCode,
- types::{amount::Amount, payto::ParsedPayto, timestamp::TalerTimestamp},
+ types::{amount::Amount, payto::ParsedPayto, time::TalerTimestamp},
};
use crate::{
diff --git a/libeufin-bank/src/auth.rs b/libeufin-bank/src/auth.rs
@@ -37,7 +37,7 @@ use taler_api::error::{
use taler_common::{
encoding::{base32, base64},
error_code::ErrorCode,
- types::timestamp::TalerTimestamp,
+ types::time::TalerTimestamp,
};
use taler_macros::EnumMeta;
use tracing::warn;
@@ -353,7 +353,7 @@ pub struct UserTokenScope;
impl UserAuthScope for UserTokenScope {
const SCOPE: TokenLogicalScope = TokenLogicalScope::refreshable;
- const KIND: AuthKind = AuthKind::UserOrAdmin;
+ const KIND: AuthKind = AuthKind::UserOnly;
const ALLOW_BASIC_AUTH: bool = true;
}
diff --git a/libeufin-bank/src/bench.rs b/libeufin-bank/src/bench.rs
@@ -34,7 +34,7 @@ use taler_common::{
error_code::ErrorCode,
types::{
amount::{Amount, Currency},
- timestamp::TalerTimestamp,
+ time::TalerTimestamp,
},
};
use taler_test_utils::{json, server::TestServer};
diff --git a/libeufin-bank/src/db/token.rs b/libeufin-bank/src/db/token.rs
@@ -26,7 +26,7 @@ use taler_api::{
db::{BindHelper, TypeHelper},
serialized,
};
-use taler_common::{api::params::Page, types::timestamp::TalerTimestamp};
+use taler_common::{api::params::Page, types::time::TalerTimestamp};
use crate::{
api::token::TokenInfo,
@@ -163,7 +163,7 @@ pub async fn access(
scope: r.try_get("scope")?,
is_refreshable: r.try_get("is_refreshable")?,
creation: r.try_get_timestamp("creation_time")?,
- expiration: r.try_get_taler_timestamp("expiration_time")?,
+ expiration: r.try_get("expiration_time")?,
})
})
.fetch_optional(db)
@@ -209,7 +209,7 @@ pub async fn access_info(
scope: r.try_get("scope")?,
is_refreshable: r.try_get("is_refreshable")?,
creation: r.try_get_timestamp("creation_time")?,
- expiration: r.try_get_taler_timestamp("expiration_time")?,
+ expiration: r.try_get("expiration_time")?,
},
BankInfo {
username: r.try_get("username")?,
@@ -281,7 +281,7 @@ pub async fn page(
bearer_token_id
FROM bearer_tokens
WHERE
- expiration_time > $1 AND
+ (expiration_time > $1 OR expiration_time IS NULL) AND
bank_customer=(SELECT customer_id FROM customers WHERE deleted_at IS NULL AND username = $2)
AND
",
@@ -290,12 +290,12 @@ pub async fn page(
},
|r: PgRow| {
Ok(TokenInfo {
- creation_time: r.try_get_timestamp("creation_time")?.into(),
- expiration: r.try_get_timestamp("expiration_time")?.into(),
+ creation_time: r.try_get("creation_time")?,
+ expiration: r.try_get("expiration_time")?,
scope: r.try_get("scope")?,
refreshable: r.try_get("is_refreshable")?,
description: r.try_get("description")?,
- last_access: r.try_get_timestamp("last_access")?.into(),
+ last_access: r.try_get("last_access")?,
row_id: r.try_get_u64("bearer_token_id")?,
token_id: r.try_get_u64("bearer_token_id")?,
})
diff --git a/libeufin-bank/src/lib.rs b/libeufin-bank/src/lib.rs
@@ -38,7 +38,7 @@ use taler_common::{
amount::Amount,
base32::Base32,
payto::IbanPayto,
- timestamp::{RelativeTime, TalerTimestamp},
+ time::{RelativeTime, TalerTimestamp},
},
};
use taler_macros::EnumMeta;
diff --git a/libeufin-bank/src/pw.rs b/libeufin-bank/src/pw.rs
@@ -206,7 +206,7 @@ fn pwh() {
// Check compatibility with kotlin hashes
let hash = "bcrypt$4$PfNp4JBeMU/t5mS5zaUY3A==$0Tjw0KzNA3ca3y9BVkh/e3TJDlHsdkEA";
assert_eq!(
- crypto.checkpw("password", &hash).unwrap(),
+ crypto.checkpw("password", hash).unwrap(),
PwCheck {
matches: true,
outdated: false
diff --git a/libeufin-nexus/src/api.rs b/libeufin-nexus/src/api.rs
@@ -52,7 +52,7 @@ use taler_common::{
amount::{Amount, Currency},
iban::IBAN,
payto::{FullIbanPayto, IbanPayto, PaytoURI},
- timestamp::TalerTimestamp,
+ time::TalerTimestamp,
},
};
use tokio::sync::watch::Sender;
diff --git a/libeufin-nexus/src/bench.rs b/libeufin-nexus/src/bench.rs
@@ -34,7 +34,7 @@ use taler_common::{
error_code::ErrorCode,
types::{
amount::{Amount, Currency},
- timestamp::TalerTimestamp,
+ time::TalerTimestamp,
},
};
use taler_test_utils::server::TestServer as _;