mirror of
https://git.dirksys.ovh/dirk/bankserver.git
synced 2025-12-20 02:59:20 +01:00
key based user data
This commit is contained in:
parent
ac695a4b16
commit
e8eef372aa
@ -1,6 +1,8 @@
|
||||
create table user_data(
|
||||
owner uuid not null references users(id) on delete cascade,
|
||||
"user" uuid not null references users(id) on delete cascade,
|
||||
"key" text not null,
|
||||
data jsonb not null,
|
||||
primary key (owner, "user")
|
||||
unique (owner, "user"),
|
||||
primary key (owner, "user", "key")
|
||||
);
|
||||
|
||||
@ -21,7 +21,8 @@ pub(super) fn router() -> Router<Arc<AppState>> {
|
||||
Router::new()
|
||||
.route("/{target}", get(user_info))
|
||||
.route("/@me/balance", get(user_balance))
|
||||
.route("/@me/data", get(get_user_data).post(set_user_data))
|
||||
.route("/@me/data", get(list_user_data_keys))
|
||||
.route("/@me/data/{key}", get(get_user_data).post(set_user_data))
|
||||
.route("/@me/accounts", get(user_accounts))
|
||||
.route("/@me/transactions", get(me_transaction_history))
|
||||
.route("/", get(list_users))
|
||||
@ -101,14 +102,26 @@ pub async fn user_accounts(EState(state): State, auth: Auth) -> Result<Json<User
|
||||
Ok(Json(UserAccounts { result }))
|
||||
}
|
||||
|
||||
#[instrument(skip(state))]
|
||||
pub async fn list_user_data_keys(
|
||||
EState(state): State,
|
||||
auth: Auth,
|
||||
) -> Result<Json<Vec<String>>, Error> {
|
||||
let user = auth.user_id();
|
||||
let conn = state.conn().await?;
|
||||
let data = Users::list_data(&conn, user).await?;
|
||||
Ok(Json(data))
|
||||
}
|
||||
|
||||
#[instrument(skip(state))]
|
||||
pub async fn get_user_data(
|
||||
EState(state): State,
|
||||
auth: Auth,
|
||||
Path(key): Path<String>,
|
||||
) -> Result<Json<Option<serde_json::Value>>, Error> {
|
||||
let user = auth.user_id();
|
||||
let conn = state.conn().await?;
|
||||
let data = Users::get_data(&conn, user).await?;
|
||||
let data = Users::get_data(&conn, user, &key).await?;
|
||||
Ok(Json(data))
|
||||
}
|
||||
|
||||
@ -116,13 +129,14 @@ pub async fn get_user_data(
|
||||
pub async fn set_user_data(
|
||||
EState(state): State,
|
||||
auth: Auth,
|
||||
Path(key): Path<String>,
|
||||
Json(body): Json<Option<serde_json::Value>>,
|
||||
) -> Result<(), Error> {
|
||||
let user = auth.user_id();
|
||||
let mut conn = state.conn().await?;
|
||||
match body {
|
||||
Some(data) => Users::set_data(&mut conn, user, data).await?,
|
||||
None => Users::delete_data(&mut conn, user).await?,
|
||||
Some(data) => Users::set_data(&mut conn, user, &key, data).await?,
|
||||
None => Users::delete_data(&mut conn, user, &key).await?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -121,37 +121,64 @@ impl Users {
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
#[instrument(skip(client))]
|
||||
pub async fn list_data(
|
||||
client: &impl GenericClient,
|
||||
user: Uuid,
|
||||
) -> Result<Vec<String>, tokio_postgres::Error> {
|
||||
let stmt = client
|
||||
.prepare_cached("select \"key\" from user_data where owner = $1 and \"user\" = $1")
|
||||
.await?;
|
||||
let res = client
|
||||
.query(&stmt, &[&user])
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|row| row.get(0))
|
||||
.collect();
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[instrument(skip(client))]
|
||||
pub async fn get_data(
|
||||
client: &impl GenericClient,
|
||||
user: Uuid,
|
||||
key: &str,
|
||||
) -> Result<Option<serde_json::Value>, tokio_postgres::Error> {
|
||||
let stmt = client
|
||||
.prepare_cached("select data from user_data where owner = $1 and \"user\" = $1")
|
||||
.prepare_cached(
|
||||
"select data from user_data where owner = $1 and \"user\" = $1 and \"key\" = $2 ",
|
||||
)
|
||||
.await?;
|
||||
let res = client.query_opt(&stmt, &[&user]).await?;
|
||||
let res = client.query_opt(&stmt, &[&user, &key]).await?;
|
||||
Ok(res.map(|row| row.get(0)))
|
||||
}
|
||||
|
||||
#[instrument(skip(client, data))]
|
||||
pub async fn set_data(
|
||||
client: &mut impl GenericClient,
|
||||
user: Uuid,
|
||||
key: &str,
|
||||
data: serde_json::Value,
|
||||
) -> Result<(), tokio_postgres::Error> {
|
||||
let stmt = client
|
||||
.prepare_cached("insert into user_data(owner, \"user\", data) values ($1, $1, $2) on conflict (owner, \"user\") do update set data = $2")
|
||||
.prepare_cached("insert into user_data(owner, \"user\", \"key\", data) values ($1, $1, $2, $3) on conflict (owner, \"user\") do update set data = $3")
|
||||
.await?;
|
||||
client.execute(&stmt, &[&user, &data]).await?;
|
||||
client.execute(&stmt, &[&user, &key, &data]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(client))]
|
||||
pub async fn delete_data(
|
||||
client: &mut impl GenericClient,
|
||||
user: Uuid,
|
||||
key: &str,
|
||||
) -> Result<(), tokio_postgres::Error> {
|
||||
let stmt = client
|
||||
.prepare_cached("delete from user_data where \"owner\" = $1 and user = $2")
|
||||
.prepare_cached(
|
||||
"delete from user_data where \"owner\" = $1 and \"user\" = $1 and \"key\" = $2",
|
||||
)
|
||||
.await?;
|
||||
client.execute(&stmt, &[&user]).await?;
|
||||
client.execute(&stmt, &[&user, &key]).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,16 +8,60 @@ HTTP 200
|
||||
[Captures]
|
||||
token: jsonpath "$.token"
|
||||
|
||||
POST {{host}}/api/users/@me/data
|
||||
GET {{host}}/api/users/@me/data
|
||||
Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
|
||||
[Asserts]
|
||||
jsonpath "$" isCollection
|
||||
jsonpath "$" isEmpty
|
||||
|
||||
GET {{host}}/api/users/@me/data/test
|
||||
Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
|
||||
[Asserts]
|
||||
jsonpath "$" == null
|
||||
|
||||
POST {{host}}/api/users/@me/data/test
|
||||
Authorization: Bearer {{token}}
|
||||
{
|
||||
"hello": "world"
|
||||
}
|
||||
HTTP 200
|
||||
|
||||
GET {{host}}/api/users/@me/data
|
||||
GET {{host}}/api/users/@me/data/test
|
||||
Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
|
||||
[Asserts]
|
||||
jsonpath "$.hello" == "world"
|
||||
|
||||
GET {{host}}/api/users/@me/data
|
||||
Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
|
||||
[Asserts]
|
||||
jsonpath "$" isCollection
|
||||
jsonpath "$" count == 1
|
||||
jsonpath "$[0]" == "test"
|
||||
|
||||
POST {{host}}/api/users/@me/data/test
|
||||
Authorization: Bearer {{token}}
|
||||
null
|
||||
HTTP 200
|
||||
|
||||
GET {{host}}/api/users/@me/data/test
|
||||
Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
|
||||
[Asserts]
|
||||
jsonpath "$" == null
|
||||
|
||||
GET {{host}}/api/users/@me/data
|
||||
Authorization: Bearer {{token}}
|
||||
HTTP 200
|
||||
|
||||
[Asserts]
|
||||
jsonpath "$" isCollection
|
||||
jsonpath "$" isEmpty
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user