add tests and fix account and user list endpoints

This commit is contained in:
DSeeLP 2025-03-07 14:00:01 +01:00
parent 456c507c10
commit 6e04bb561c
11 changed files with 80 additions and 14 deletions

View File

@ -2,6 +2,7 @@ use std::sync::Arc;
use axum::{Router, extract::Path, http::StatusCode, routing::get};
use serde::Serialize;
use tracing::instrument;
use uuid::Uuid;
use crate::{
@ -29,7 +30,10 @@ pub struct ListAccounts {
accounts: Vec<AccountInfo>,
}
#[instrument(skip(state))]
pub async fn account_info(EState(state): State, _: Auth, Path(id): Path<Uuid>) {}
#[instrument(skip(state))]
pub async fn account_transactions(
EState(state): State,
auth: Auth,
@ -53,6 +57,8 @@ pub async fn account_transactions(
Ok(Json(result))
}
#[instrument(skip(state))]
pub async fn list_accounts(
EState(state): State,
_: Auth,

View File

@ -404,7 +404,7 @@ impl RequestPagination {
}
#[inline]
pub const fn offset(&self) -> i64 {
self.limit as i64
self.offset as i64
}
}

View File

@ -333,7 +333,7 @@ impl MakePayment {
}
}
#[derive(Deserialize)]
#[derive(Debug, Deserialize)]
pub struct TransactionQuery {
#[serde(flatten)]
pub pagination: RequestPagination,

View File

@ -2,6 +2,7 @@ use std::sync::Arc;
use axum::{Router, extract::Path, http::StatusCode, routing::get};
use serde::{Deserialize, Serialize};
use tracing::instrument;
use uuid::Uuid;
use crate::{
@ -69,12 +70,16 @@ pub async fn user_info(
}
Err(ApiError::NOT_FOUND.into())
}
#[instrument(skip(state))]
pub async fn user_balance(EState(state): State, auth: Auth) -> Result<Json<UserBalance>, Error> {
let conn = state.conn().await?;
let info = Account::list_for_user(&conn, auth.user_id()).await?;
let balance = info.iter().map(|info| info.balance).sum();
Ok(Json(UserBalance { balance }))
}
#[instrument(skip(state))]
pub async fn list_users(
EState(state): State,
_: Auth,
@ -84,6 +89,8 @@ pub async fn list_users(
let users = User::list(&conn, pagination).await?;
Ok(Json(users))
}
#[instrument(skip(state))]
pub async fn me_transaction_history(
EState(state): State,
auth: Auth,
@ -97,6 +104,7 @@ pub async fn me_transaction_history(
Ok(Json(result))
}
#[instrument(skip(state))]
pub async fn user_accounts(EState(state): State, auth: Auth) -> Result<Json<UserAccounts>, Error> {
let user = auth.user_id();
let conn = state.conn().await?;

View File

@ -96,7 +96,7 @@ impl Account {
.prepare_cached("select id,\"user\",name from accounts limit $1 offset $2")
.await?;
let stmt_count = client
.prepare_cached("select count(*) from accounts limit $1 offset $2")
.prepare_cached("select count(*) from accounts")
.await?;
let users = client
.query(&stmt, &[&pagination.limit(), &pagination.offset()])

View File

@ -5,6 +5,7 @@ use garde::Validate;
use regex::Regex;
use serde::{Deserialize, Serialize};
use tokio_postgres::{ToStatement, types::ToSql};
use tracing::{info, instrument};
use uuid::Uuid;
mod account;
@ -50,7 +51,8 @@ pub struct IdWithName {
pub name: Name,
}
async fn count<T: ?Sized + ToStatement + Sync + Send>(
#[instrument(skip(client))]
async fn count<T: ?Sized + ToStatement + Sync + Send + std::fmt::Debug>(
client: &impl GenericClient,
statement: &T,
params: &[&(dyn ToSql + Sync)],

View File

@ -8,7 +8,7 @@ use crate::api::{Pagination, RequestPagination};
use super::{User, account::ReducedAccountInfo};
#[derive(Deserialize)]
#[derive(Debug, Deserialize)]
#[cfg_attr(feature = "schemas", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum Direction {

View File

@ -100,21 +100,14 @@ impl User {
let stmt = client
.prepare_cached("select id,name from users limit $1 offset $2")
.await?;
let stmt_count = client
.prepare_cached("select count(*) from users limit $1 offset $2")
.await?;
let stmt_count = client.prepare_cached("select count(*) from users").await?;
let users = client
.query(&stmt, &[&pagination.limit(), &pagination.offset()])
.await?
.into_iter()
.map(User::from)
.collect();
let count = count(
client,
&stmt_count,
&[&pagination.limit(), &pagination.offset()],
)
.await?;
let count = count(client, &stmt_count, &[]).await?;
Ok(Pagination::new(users, count, pagination))
}

View File

@ -0,0 +1,25 @@
POST {{host}}/api/login
{
"name": "user1",
"password": "this-is-a-password"
}
HTTP 200
[Captures]
token: jsonpath "$.token"
GET {{host}}/api/accounts?limit=50
Authorization: Bearer {{token}}
HTTP 200
[Asserts]
jsonpath "$.pagination.total" == 7
jsonpath "$.pagination.limit" == 50
jsonpath "$.pagination.offset" == 0
jsonpath "$.result" isCollection
jsonpath "$.result[0].name" == "user1"
jsonpath "$.result[1].name" == "user2"
jsonpath "$.result[2].name" == "user3"
jsonpath "$.result[3].name" == "user4"
jsonpath "$.result[4].name" == "user5"
jsonpath "$.result[5].name" == "user6"
jsonpath "$.result[6].name" == "test-user"

View File

@ -18,3 +18,10 @@ POST {{host}}/api/login
"password": "this-is-a-test"
}
HTTP 200
[Captures]
token: jsonpath "$.token"
GET {{host}}/api/users/@me
Authorization: Bearer {{token}}
HTTP 200

View File

@ -0,0 +1,25 @@
POST {{host}}/api/login
{
"name": "user1",
"password": "this-is-a-password"
}
HTTP 200
[Captures]
token: jsonpath "$.token"
GET {{host}}/api/users?limit=50
Authorization: Bearer {{token}}
HTTP 200
[Asserts]
jsonpath "$.pagination.total" == 7
jsonpath "$.pagination.limit" == 50
jsonpath "$.pagination.offset" == 0
jsonpath "$.result" isCollection
jsonpath "$.result[0].name" == "user1"
jsonpath "$.result[1].name" == "user2"
jsonpath "$.result[2].name" == "user3"
jsonpath "$.result[3].name" == "user4"
jsonpath "$.result[4].name" == "user5"
jsonpath "$.result[5].name" == "user6"
jsonpath "$.result[6].name" == "test-user"