add / edit / delete user warrens

This commit is contained in:
2025-07-21 19:27:41 +02:00
parent 50e066f794
commit 2c26002507
86 changed files with 2197 additions and 300 deletions

View File

@@ -13,7 +13,6 @@ impl WarrenMetrics for MetricsDebugLogger {
async fn record_warren_list_success(&self) {
tracing::debug!("[Metrics] Warren list succeeded");
}
async fn record_warren_list_failure(&self) {
tracing::debug!("[Metrics] Warren list failed");
}
@@ -21,11 +20,17 @@ impl WarrenMetrics for MetricsDebugLogger {
async fn record_warren_fetch_success(&self) {
tracing::debug!("[Metrics] Warren fetch succeeded");
}
async fn record_warren_fetch_failure(&self) {
tracing::debug!("[Metrics] Warren fetch failed");
}
async fn record_warrens_fetch_success(&self) {
tracing::debug!("[Metrics] Fetch warrens succeeded");
}
async fn record_warrens_fetch_failure(&self) {
tracing::debug!("[Metrics] Fetch warrens failed");
}
async fn record_list_warren_files_success(&self) {
tracing::debug!("[Metrics] Warren list files succeeded");
}
@@ -187,6 +192,27 @@ impl AuthMetrics for MetricsDebugLogger {
tracing::debug!("[Metrics] Auth session fetch failed");
}
async fn record_auth_user_warren_creation_success(&self) {
tracing::debug!("[Metrics] User warren creation succeeded");
}
async fn record_auth_user_warren_creation_failure(&self) {
tracing::debug!("[Metrics] User warren creation failed");
}
async fn record_auth_user_warren_edit_success(&self) {
tracing::debug!("[Metrics] User warren edit succeeded");
}
async fn record_auth_user_warren_edit_failure(&self) {
tracing::debug!("[Metrics] User warren edit failed");
}
async fn record_auth_user_warren_deletion_success(&self) {
tracing::debug!("[Metrics] User warren deletion succeeded");
}
async fn record_auth_user_warren_deletion_failure(&self) {
tracing::debug!("[Metrics] User warren deletion failed");
}
async fn record_auth_fetch_user_warren_list_success(&self) {
tracing::debug!("[Metrics] Auth warren list succeeded");
}

View File

@@ -24,6 +24,10 @@ impl NotifierDebugLogger {
}
impl WarrenNotifier for NotifierDebugLogger {
async fn warrens_fetched(&self, warrens: &Vec<Warren>) {
tracing::debug!("[Notifier] Fetched {} warren(s)", warrens.len());
}
async fn warrens_listed(&self, warrens: &Vec<Warren>) {
tracing::debug!("[Notifier] Listed {} warren(s)", warrens.len());
}
@@ -182,6 +186,33 @@ impl AuthNotifier for NotifierDebugLogger {
);
}
async fn auth_user_warren_created(&self, creator: &User, user_warren: &UserWarren) {
tracing::debug!(
"[Notifier] Admin user {} added user {} to warren {}",
creator.id(),
user_warren.user_id(),
user_warren.warren_id(),
);
}
async fn auth_user_warren_edited(&self, editor: &User, user_warren: &UserWarren) {
tracing::debug!(
"[Notifier] Admin user {} edited the access of user {} to warren {}",
editor.id(),
user_warren.user_id(),
user_warren.warren_id(),
);
}
async fn auth_user_warren_deleted(&self, deleter: &User, user_warren: &UserWarren) {
tracing::debug!(
"[Notifier] Admin user {} added removed {} from warren {}",
deleter.id(),
user_warren.user_id(),
user_warren.warren_id(),
);
}
async fn auth_user_warrens_fetched(&self, user_id: &Uuid, warren_ids: &Vec<UserWarren>) {
tracing::debug!(
"[Notifier] Fetched {} user warrens for authenticated user {}",

View File

@@ -33,12 +33,15 @@ use crate::domain::warren::{
user_warren::{
UserWarren,
requests::{
CreateUserWarrenError, CreateUserWarrenRequest, DeleteUserWarrenError,
DeleteUserWarrenRequest, EditUserWarrenError, EditUserWarrenRequest,
FetchUserWarrenError, FetchUserWarrenRequest, FetchUserWarrensError,
FetchUserWarrensRequest, ListUserWarrensError, ListUserWarrensRequest,
},
},
warren::{
FetchWarrenError, FetchWarrenRequest, FetchWarrensError, FetchWarrensRequest, Warren,
FetchWarrenError, FetchWarrenRequest, FetchWarrensError, FetchWarrensRequest,
ListWarrensError, ListWarrensRequest, Warren,
},
},
ports::{AuthRepository, WarrenRepository, WarrenService},
@@ -109,7 +112,7 @@ impl Postgres {
Ok(warren)
}
async fn list_warrens(
async fn fetch_warrens(
&self,
connection: &mut PgConnection,
ids: &[Uuid],
@@ -131,6 +134,24 @@ impl Postgres {
Ok(warrens)
}
async fn fetch_all_warrens(
&self,
connection: &mut PgConnection,
) -> Result<Vec<Warren>, sqlx::Error> {
let warrens: Vec<Warren> = sqlx::query_as::<sqlx::Postgres, Warren>(
"
SELECT
*
FROM
warrens
",
)
.fetch_all(&mut *connection)
.await?;
Ok(warrens)
}
async fn create_user(
&self,
connection: &mut PgConnection,
@@ -470,10 +491,110 @@ impl Postgres {
Ok(users)
}
async fn add_user_to_warren(
&self,
connection: &mut PgConnection,
user_warren: &UserWarren,
) -> Result<UserWarren, sqlx::Error> {
let user_warren: UserWarren = sqlx::query_as(
"
INSERT INTO user_warrens (
user_id,
warren_id,
can_list_files,
can_read_files,
can_modify_files,
can_delete_files
) VALUES (
$1,
$2,
$3,
$4,
$5,
$6
)
RETURNING
*
",
)
.bind(user_warren.user_id())
.bind(user_warren.warren_id())
.bind(user_warren.can_list_files())
.bind(user_warren.can_read_files())
.bind(user_warren.can_modify_files())
.bind(user_warren.can_delete_files())
.fetch_one(connection)
.await?;
Ok(user_warren)
}
async fn update_user_warren(
&self,
connection: &mut PgConnection,
user_warren: &UserWarren,
) -> Result<UserWarren, sqlx::Error> {
let user_warren: UserWarren = sqlx::query_as(
"
UPDATE
user_warrens
SET
can_list_files = $3,
can_read_files = $4,
can_modify_files = $5,
can_delete_files = $6
WHERE
user_id = $1 AND
warren_id = $2
RETURNING
*
",
)
.bind(user_warren.user_id())
.bind(user_warren.warren_id())
.bind(user_warren.can_list_files())
.bind(user_warren.can_read_files())
.bind(user_warren.can_modify_files())
.bind(user_warren.can_delete_files())
.fetch_one(connection)
.await?;
Ok(user_warren)
}
async fn remove_user_from_warren(
&self,
connection: &mut PgConnection,
user_id: &Uuid,
warren_id: &Uuid,
) -> Result<UserWarren, sqlx::Error> {
let mut tx = connection.begin().await?;
let user_warren = sqlx::query_as(
"
DELETE FROM
user_warrens
WHERE
user_id = $1 AND
warren_id = $2
RETURNING
*
",
)
.bind(user_id)
.bind(warren_id)
.fetch_one(&mut *tx)
.await?;
tx.commit().await?;
Ok(user_warren)
}
}
impl WarrenRepository for Postgres {
async fn list_warrens(
async fn fetch_warrens(
&self,
request: FetchWarrensRequest,
) -> Result<Vec<Warren>, FetchWarrensError> {
@@ -484,9 +605,27 @@ impl WarrenRepository for Postgres {
.context("Failed to get a PostgreSQL connection")?;
let warrens = self
.list_warrens(&mut connection, request.ids())
.fetch_warrens(&mut connection, request.ids())
.await
.map_err(|err| anyhow!(err).context("Failed to list warrens"))?;
.map_err(|err| anyhow!(err).context("Failed to fetch warrens"))?;
Ok(warrens)
}
async fn list_warrens(
&self,
_request: ListWarrensRequest,
) -> Result<Vec<Warren>, ListWarrensError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a PostgreSQL connection")?;
let warrens = self
.fetch_all_warrens(&mut connection)
.await
.map_err(|err| anyhow!(err).context("Failed to list all warrens"))?;
Ok(warrens)
}
@@ -649,6 +788,66 @@ impl AuthRepository for Postgres {
Ok(FetchAuthSessionResponse::new(session, user))
}
async fn create_user_warren(
&self,
request: CreateUserWarrenRequest,
) -> Result<UserWarren, CreateUserWarrenError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a PostgreSQL connection")?;
let user_warren = self
.add_user_to_warren(&mut connection, request.user_warren())
.await
.context("Failed to create user warren")?;
Ok(user_warren)
}
async fn edit_user_warren(
&self,
request: EditUserWarrenRequest,
) -> Result<UserWarren, EditUserWarrenError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a PostgreSQL connection")?;
let user_warren = self
.update_user_warren(&mut connection, request.user_warren())
.await
.context("Failed to edit user warren")?;
Ok(user_warren)
}
async fn delete_user_warren(
&self,
request: DeleteUserWarrenRequest,
) -> Result<UserWarren, DeleteUserWarrenError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a PostgreSQL connection")?;
let user_warren = self
.remove_user_from_warren(&mut connection, request.user_id(), request.warren_id())
.await
.map_err(|e| {
if is_not_found_error(&e) {
DeleteUserWarrenError::NotFound
} else {
anyhow!("Failed to delete user warren: {e:?}").into()
}
})?;
Ok(user_warren)
}
async fn fetch_user_warrens(
&self,
request: FetchUserWarrensRequest,
@@ -741,14 +940,9 @@ impl AuthRepository for Postgres {
.await
.context("Failed to fetch all user warrens")?;
let warrens = warren_service
.list_warrens(FetchWarrensRequest::new(
user_warrens
.iter()
.map(|uw| uw.warren_id().clone())
.collect(),
))
.list_warrens(ListWarrensRequest::new())
.await
.context("Failed to get warrens")?;
.context("Failed to get all warrens")?;
Ok(ListAllUsersAndWarrensResponse::new(
users,