add / edit / delete user warrens
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ALTER TABLE user_warrens DROP COLUMN can_create_children, DROP COLUMN can_delete_warren;
|
||||
@@ -6,34 +6,28 @@ use uuid::Uuid;
|
||||
pub struct UserWarren {
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
can_create_children: bool,
|
||||
can_list_files: bool,
|
||||
can_read_files: bool,
|
||||
can_modify_files: bool,
|
||||
can_delete_files: bool,
|
||||
can_delete_warren: bool,
|
||||
}
|
||||
|
||||
impl UserWarren {
|
||||
pub fn new(
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
can_create_children: bool,
|
||||
can_list_files: bool,
|
||||
can_read_files: bool,
|
||||
can_modify_files: bool,
|
||||
can_delete_files: bool,
|
||||
can_delete_warren: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
user_id,
|
||||
warren_id,
|
||||
can_create_children,
|
||||
can_list_files,
|
||||
can_read_files,
|
||||
can_modify_files,
|
||||
can_delete_files,
|
||||
can_delete_warren,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,10 +42,6 @@ impl UserWarren {
|
||||
self.warren_id
|
||||
}
|
||||
|
||||
pub fn can_create_children(&self) -> bool {
|
||||
self.can_create_children
|
||||
}
|
||||
|
||||
pub fn can_list_files(&self) -> bool {
|
||||
self.can_list_files
|
||||
}
|
||||
@@ -67,8 +57,4 @@ impl UserWarren {
|
||||
pub fn can_delete_files(&self) -> bool {
|
||||
self.can_delete_files
|
||||
}
|
||||
|
||||
pub fn can_delete_warren(&self) -> bool {
|
||||
self.can_delete_warren
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::domain::warren::models::user_warren::UserWarren;
|
||||
|
||||
/// A request to create a new user warren (admin only)
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct CreateUserWarrenRequest {
|
||||
user_warren: UserWarren,
|
||||
}
|
||||
|
||||
impl CreateUserWarrenRequest {
|
||||
pub fn new(user_warren: UserWarren) -> Self {
|
||||
Self { user_warren }
|
||||
}
|
||||
|
||||
pub fn user_warren(&self) -> &UserWarren {
|
||||
&self.user_warren
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreateUserWarrenError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// A request to delete an existing user warren (admin only)
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeleteUserWarrenRequest {
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
}
|
||||
|
||||
impl DeleteUserWarrenRequest {
|
||||
pub fn new(user_id: Uuid, warren_id: Uuid) -> Self {
|
||||
Self { user_id, warren_id }
|
||||
}
|
||||
|
||||
pub fn user_id(&self) -> &Uuid {
|
||||
&self.user_id
|
||||
}
|
||||
|
||||
pub fn warren_id(&self) -> &Uuid {
|
||||
&self.warren_id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DeleteUserWarrenError {
|
||||
#[error("This user warren does not exist")]
|
||||
NotFound,
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::domain::warren::models::user_warren::UserWarren;
|
||||
|
||||
/// A request to edit a new user warren (admin only)
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct EditUserWarrenRequest {
|
||||
user_warren: UserWarren,
|
||||
}
|
||||
|
||||
impl EditUserWarrenRequest {
|
||||
pub fn new(user_warren: UserWarren) -> Self {
|
||||
Self { user_warren }
|
||||
}
|
||||
|
||||
pub fn user_warren(&self) -> &UserWarren {
|
||||
&self.user_warren
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum EditUserWarrenError {
|
||||
#[error("This user warren does not exist")]
|
||||
NotFound,
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
@@ -21,24 +21,7 @@ impl FetchUserWarrensRequest {
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FetchUserWarrensError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ListWarrensRequest {}
|
||||
|
||||
impl ListWarrensRequest {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ListWarrensError {
|
||||
#[error(transparent)]
|
||||
FetchUserWarrenIds(#[from] FetchUserWarrensError),
|
||||
#[error(transparent)]
|
||||
ListWarrens(#[from] FetchWarrensError),
|
||||
FetchWarrens(#[from] FetchWarrensError),
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
mod create_user_warren;
|
||||
mod delete_user_warren;
|
||||
mod edit_user_warren;
|
||||
mod fetch_user_warren;
|
||||
mod fetch_user_warrens;
|
||||
mod list_user_warrens;
|
||||
|
||||
pub use create_user_warren::*;
|
||||
pub use delete_user_warren::*;
|
||||
pub use edit_user_warren::*;
|
||||
pub use fetch_user_warren::*;
|
||||
pub use fetch_user_warrens::*;
|
||||
pub use list_user_warrens::*;
|
||||
|
||||
@@ -502,3 +502,18 @@ pub enum RenameWarrenEntryError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ListWarrensRequest {}
|
||||
|
||||
impl ListWarrensRequest {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ListWarrensError {
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
pub trait WarrenMetrics: Clone + Send + Sync + 'static {
|
||||
fn record_warren_list_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_warren_list_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_warren_fetch_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_warren_fetch_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_warrens_fetch_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_warrens_fetch_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_warren_list_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_warren_list_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_list_warren_files_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_list_warren_files_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
@@ -77,6 +80,15 @@ pub trait AuthMetrics: Clone + Send + Sync + 'static {
|
||||
fn record_auth_session_fetch_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_auth_session_fetch_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_auth_user_warren_creation_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_auth_user_warren_creation_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_auth_user_warren_edit_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_auth_user_warren_edit_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_auth_user_warren_deletion_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_auth_user_warren_deletion_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn record_auth_fetch_user_warrens_success(&self) -> impl Future<Output = ()> + Send;
|
||||
fn record_auth_fetch_user_warrens_failure(&self) -> impl Future<Output = ()> + Send;
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ use super::models::{
|
||||
user_warren::{
|
||||
UserWarren,
|
||||
requests::{
|
||||
FetchUserWarrensError, FetchUserWarrensRequest, ListWarrensError, ListWarrensRequest,
|
||||
CreateUserWarrenError, CreateUserWarrenRequest, DeleteUserWarrenError,
|
||||
DeleteUserWarrenRequest, EditUserWarrenError, EditUserWarrenRequest,
|
||||
FetchUserWarrensError, FetchUserWarrensRequest,
|
||||
},
|
||||
},
|
||||
warren::{
|
||||
@@ -36,18 +38,21 @@ use super::models::{
|
||||
DeleteWarrenDirectoryError, DeleteWarrenDirectoryRequest, DeleteWarrenDirectoryResponse,
|
||||
DeleteWarrenFileError, DeleteWarrenFileRequest, DeleteWarrenFileResponse, FetchWarrenError,
|
||||
FetchWarrenRequest, FetchWarrensError, FetchWarrensRequest, ListWarrenFilesError,
|
||||
ListWarrenFilesRequest, ListWarrenFilesResponse, RenameWarrenEntryError,
|
||||
RenameWarrenEntryRequest, RenameWarrenEntryResponse, UploadWarrenFilesError,
|
||||
UploadWarrenFilesRequest, UploadWarrenFilesResponse, Warren,
|
||||
ListWarrenFilesRequest, ListWarrenFilesResponse, ListWarrensError, ListWarrensRequest,
|
||||
RenameWarrenEntryError, RenameWarrenEntryRequest, RenameWarrenEntryResponse,
|
||||
UploadWarrenFilesError, UploadWarrenFilesRequest, UploadWarrenFilesResponse, Warren,
|
||||
},
|
||||
};
|
||||
|
||||
pub trait WarrenService: Clone + Send + Sync + 'static {
|
||||
fn list_warrens(
|
||||
fn fetch_warrens(
|
||||
&self,
|
||||
request: FetchWarrensRequest,
|
||||
) -> impl Future<Output = Result<Vec<Warren>, FetchWarrensError>> + Send;
|
||||
|
||||
fn list_warrens(
|
||||
&self,
|
||||
request: ListWarrensRequest,
|
||||
) -> impl Future<Output = Result<Vec<Warren>, ListWarrensError>> + Send;
|
||||
fn fetch_warren(
|
||||
&self,
|
||||
request: FetchWarrenRequest,
|
||||
@@ -164,9 +169,25 @@ pub trait AuthService: Clone + Send + Sync + 'static {
|
||||
|
||||
fn list_warrens<WS: WarrenService>(
|
||||
&self,
|
||||
request: AuthRequest<ListWarrensRequest>,
|
||||
request: AuthRequest<()>,
|
||||
warren_service: &WS,
|
||||
) -> impl Future<Output = Result<Vec<Warren>, AuthError<ListWarrensError>>> + Send;
|
||||
) -> impl Future<Output = Result<Vec<Warren>, AuthError<FetchUserWarrensError>>> + Send;
|
||||
|
||||
/// An action that creates an association between a user and a warren (MUST REQUIRE ADMIN PRIVILEGES)
|
||||
fn create_user_warren(
|
||||
&self,
|
||||
request: AuthRequest<CreateUserWarrenRequest>,
|
||||
) -> impl Future<Output = Result<UserWarren, AuthError<CreateUserWarrenError>>> + Send;
|
||||
/// An action that edits an association between a user and a warren (MUST REQUIRE ADMIN PRIVILEGES)
|
||||
fn edit_user_warren(
|
||||
&self,
|
||||
request: AuthRequest<EditUserWarrenRequest>,
|
||||
) -> impl Future<Output = Result<UserWarren, AuthError<EditUserWarrenError>>> + Send;
|
||||
/// An action that deletes an association between a user and a warren (MUST REQUIRE ADMIN PRIVILEGES)
|
||||
fn delete_user_warren(
|
||||
&self,
|
||||
request: AuthRequest<DeleteUserWarrenRequest>,
|
||||
) -> impl Future<Output = Result<UserWarren, AuthError<DeleteUserWarrenError>>> + Send;
|
||||
|
||||
fn fetch_user_warrens(
|
||||
&self,
|
||||
|
||||
@@ -12,8 +12,9 @@ use crate::domain::warren::models::{
|
||||
};
|
||||
|
||||
pub trait WarrenNotifier: Clone + Send + Sync + 'static {
|
||||
fn warrens_listed(&self, warrens: &Vec<Warren>) -> impl Future<Output = ()> + Send;
|
||||
fn warrens_fetched(&self, warrens: &Vec<Warren>) -> impl Future<Output = ()> + Send;
|
||||
fn warren_fetched(&self, warren: &Warren) -> impl Future<Output = ()> + Send;
|
||||
fn warrens_listed(&self, warrens: &Vec<Warren>) -> impl Future<Output = ()> + Send;
|
||||
fn warren_files_listed(
|
||||
&self,
|
||||
response: &ListWarrenFilesResponse,
|
||||
@@ -93,6 +94,21 @@ pub trait AuthNotifier: Clone + Send + Sync + 'static {
|
||||
response: &FetchAuthSessionResponse,
|
||||
) -> impl Future<Output = ()> + Send;
|
||||
|
||||
fn auth_user_warren_created(
|
||||
&self,
|
||||
creator: &User,
|
||||
user_warren: &UserWarren,
|
||||
) -> impl Future<Output = ()> + Send;
|
||||
fn auth_user_warren_edited(
|
||||
&self,
|
||||
editor: &User,
|
||||
user_warren: &UserWarren,
|
||||
) -> impl Future<Output = ()> + Send;
|
||||
fn auth_user_warren_deleted(
|
||||
&self,
|
||||
deleter: &User,
|
||||
user_warren: &UserWarren,
|
||||
) -> impl Future<Output = ()> + Send;
|
||||
fn auth_user_warrens_listed(
|
||||
&self,
|
||||
user: &User,
|
||||
|
||||
@@ -20,23 +20,31 @@ use crate::domain::warren::models::{
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
use super::WarrenService;
|
||||
|
||||
pub trait WarrenRepository: Clone + Send + Sync + 'static {
|
||||
fn list_warrens(
|
||||
fn fetch_warrens(
|
||||
&self,
|
||||
request: FetchWarrensRequest,
|
||||
) -> impl Future<Output = Result<Vec<Warren>, FetchWarrensError>> + Send;
|
||||
|
||||
fn list_warrens(
|
||||
&self,
|
||||
request: ListWarrensRequest,
|
||||
) -> impl Future<Output = Result<Vec<Warren>, ListWarrensError>> + Send;
|
||||
|
||||
fn fetch_warren(
|
||||
&self,
|
||||
request: FetchWarrenRequest,
|
||||
@@ -104,6 +112,19 @@ pub trait AuthRepository: Clone + Send + Sync + 'static {
|
||||
request: VerifyUserPasswordRequest,
|
||||
) -> impl Future<Output = Result<User, VerifyUserPasswordError>> + Send;
|
||||
|
||||
fn create_user_warren(
|
||||
&self,
|
||||
request: CreateUserWarrenRequest,
|
||||
) -> impl Future<Output = Result<UserWarren, CreateUserWarrenError>> + Send;
|
||||
fn edit_user_warren(
|
||||
&self,
|
||||
request: EditUserWarrenRequest,
|
||||
) -> impl Future<Output = Result<UserWarren, EditUserWarrenError>> + Send;
|
||||
fn delete_user_warren(
|
||||
&self,
|
||||
request: DeleteUserWarrenRequest,
|
||||
) -> impl Future<Output = Result<UserWarren, DeleteUserWarrenError>> + Send;
|
||||
|
||||
fn list_user_warrens(
|
||||
&self,
|
||||
request: ListUserWarrensRequest,
|
||||
|
||||
@@ -19,8 +19,9 @@ use crate::{
|
||||
user_warren::{
|
||||
UserWarren,
|
||||
requests::{
|
||||
CreateUserWarrenError, CreateUserWarrenRequest, DeleteUserWarrenError,
|
||||
DeleteUserWarrenRequest, EditUserWarrenError, EditUserWarrenRequest,
|
||||
FetchUserWarrenRequest, FetchUserWarrensError, FetchUserWarrensRequest,
|
||||
ListWarrensError, ListWarrensRequest,
|
||||
},
|
||||
},
|
||||
warren::{
|
||||
@@ -343,6 +344,101 @@ where
|
||||
result.map_err(AuthError::Custom)
|
||||
}
|
||||
|
||||
async fn create_user_warren(
|
||||
&self,
|
||||
request: AuthRequest<CreateUserWarrenRequest>,
|
||||
) -> Result<UserWarren, AuthError<CreateUserWarrenError>> {
|
||||
let (session, request) = request.unpack();
|
||||
|
||||
let session_response = self
|
||||
.repository
|
||||
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||
.await?;
|
||||
|
||||
if !session_response.user().admin() {
|
||||
return Err(AuthError::InsufficientPermissions);
|
||||
}
|
||||
|
||||
let result = self.repository.create_user_warren(request).await;
|
||||
|
||||
if let Ok(user_warren) = result.as_ref() {
|
||||
self.metrics
|
||||
.record_auth_user_warren_creation_success()
|
||||
.await;
|
||||
self.notifier
|
||||
.auth_user_warren_created(session_response.user(), user_warren)
|
||||
.await;
|
||||
} else {
|
||||
self.metrics
|
||||
.record_auth_user_warren_creation_failure()
|
||||
.await;
|
||||
}
|
||||
|
||||
result.map_err(AuthError::Custom)
|
||||
}
|
||||
|
||||
async fn edit_user_warren(
|
||||
&self,
|
||||
request: AuthRequest<EditUserWarrenRequest>,
|
||||
) -> Result<UserWarren, AuthError<EditUserWarrenError>> {
|
||||
let (session, request) = request.unpack();
|
||||
|
||||
let session_response = self
|
||||
.repository
|
||||
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||
.await?;
|
||||
|
||||
if !session_response.user().admin() {
|
||||
return Err(AuthError::InsufficientPermissions);
|
||||
}
|
||||
|
||||
let result = self.repository.edit_user_warren(request).await;
|
||||
|
||||
if let Ok(user_warren) = result.as_ref() {
|
||||
self.metrics.record_auth_user_warren_edit_success().await;
|
||||
self.notifier
|
||||
.auth_user_warren_edited(session_response.user(), user_warren)
|
||||
.await;
|
||||
} else {
|
||||
self.metrics.record_auth_user_warren_edit_failure().await;
|
||||
}
|
||||
|
||||
result.map_err(AuthError::Custom)
|
||||
}
|
||||
|
||||
async fn delete_user_warren(
|
||||
&self,
|
||||
request: AuthRequest<DeleteUserWarrenRequest>,
|
||||
) -> Result<UserWarren, AuthError<DeleteUserWarrenError>> {
|
||||
let (session, request) = request.unpack();
|
||||
|
||||
let session_response = self
|
||||
.repository
|
||||
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||
.await?;
|
||||
|
||||
if !session_response.user().admin() {
|
||||
return Err(AuthError::InsufficientPermissions);
|
||||
}
|
||||
|
||||
let result = self.repository.delete_user_warren(request).await;
|
||||
|
||||
if let Ok(user_warren) = result.as_ref() {
|
||||
self.metrics
|
||||
.record_auth_user_warren_deletion_success()
|
||||
.await;
|
||||
self.notifier
|
||||
.auth_user_warren_deleted(session_response.user(), user_warren)
|
||||
.await;
|
||||
} else {
|
||||
self.metrics
|
||||
.record_auth_user_warren_deletion_failure()
|
||||
.await;
|
||||
}
|
||||
|
||||
result.map_err(AuthError::Custom)
|
||||
}
|
||||
|
||||
async fn fetch_user_warrens(
|
||||
&self,
|
||||
request: FetchUserWarrensRequest,
|
||||
@@ -364,9 +460,9 @@ where
|
||||
|
||||
async fn list_warrens<WS: WarrenService>(
|
||||
&self,
|
||||
request: AuthRequest<ListWarrensRequest>,
|
||||
request: AuthRequest<()>,
|
||||
warren_service: &WS,
|
||||
) -> Result<Vec<Warren>, AuthError<ListWarrensError>> {
|
||||
) -> Result<Vec<Warren>, AuthError<FetchUserWarrensError>> {
|
||||
let (session, _) = request.unpack();
|
||||
|
||||
let session_response = self
|
||||
@@ -380,7 +476,7 @@ where
|
||||
.map_err(|e| AuthError::Custom(e.into()))?;
|
||||
|
||||
let result = warren_service
|
||||
.list_warrens(FetchWarrensRequest::new(
|
||||
.fetch_warrens(FetchWarrensRequest::new(
|
||||
ids.into_iter().map(|uw| uw.into_warren_id()).collect(),
|
||||
))
|
||||
.await;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::domain::warren::{
|
||||
models::warren::{
|
||||
CreateWarrenDirectoryResponse, DeleteWarrenDirectoryResponse, DeleteWarrenFileResponse,
|
||||
FetchWarrensError, FetchWarrensRequest, ListWarrenFilesResponse, RenameWarrenEntryError,
|
||||
RenameWarrenEntryRequest, RenameWarrenEntryResponse, UploadWarrenFilesResponse,
|
||||
FetchWarrensError, FetchWarrensRequest, ListWarrenFilesResponse, ListWarrensError,
|
||||
ListWarrensRequest, RenameWarrenEntryError, RenameWarrenEntryRequest,
|
||||
RenameWarrenEntryResponse, UploadWarrenFilesResponse,
|
||||
},
|
||||
ports::FileSystemService,
|
||||
};
|
||||
@@ -55,10 +56,26 @@ where
|
||||
N: WarrenNotifier,
|
||||
FSS: FileSystemService,
|
||||
{
|
||||
async fn list_warrens(
|
||||
async fn fetch_warrens(
|
||||
&self,
|
||||
request: FetchWarrensRequest,
|
||||
) -> Result<Vec<Warren>, FetchWarrensError> {
|
||||
let result = self.repository.fetch_warrens(request).await;
|
||||
|
||||
if let Ok(warren) = result.as_ref() {
|
||||
self.metrics.record_warrens_fetch_success().await;
|
||||
self.notifier.warrens_fetched(warren).await;
|
||||
} else {
|
||||
self.metrics.record_warrens_fetch_failure().await;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
async fn list_warrens(
|
||||
&self,
|
||||
request: ListWarrensRequest,
|
||||
) -> Result<Vec<Warren>, ListWarrensError> {
|
||||
let result = self.repository.list_warrens(request).await;
|
||||
|
||||
if let Ok(warren) = result.as_ref() {
|
||||
|
||||
@@ -164,10 +164,10 @@ impl From<FetchAuthSessionError> for ApiError {
|
||||
fn from(value: FetchAuthSessionError) -> Self {
|
||||
match value {
|
||||
FetchAuthSessionError::NotFound => {
|
||||
Self::BadRequest("This session does not exist".to_string())
|
||||
Self::Unauthorized("This session does not exist".to_string())
|
||||
}
|
||||
FetchAuthSessionError::Expired => {
|
||||
Self::BadRequest("This session has expired".to_string())
|
||||
Self::Unauthorized("This session has expired".to_string())
|
||||
}
|
||||
FetchAuthSessionError::Unknown(e) => Self::InternalServerError(e.to_string()),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
use axum::{Json, extract::State, http::StatusCode};
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
auth_session::AuthRequest,
|
||||
user_warren::{UserWarren, requests::CreateUserWarrenRequest},
|
||||
},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{
|
||||
AppState,
|
||||
handlers::{UserWarrenData, extractors::SessionIdHeader},
|
||||
responses::{ApiError, ApiSuccess},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(super) struct CreateUserWarrenHttpRequestBody {
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
can_list_files: bool,
|
||||
can_read_files: bool,
|
||||
can_modify_files: bool,
|
||||
can_delete_files: bool,
|
||||
}
|
||||
|
||||
impl CreateUserWarrenHttpRequestBody {
|
||||
fn into_domain(self) -> CreateUserWarrenRequest {
|
||||
CreateUserWarrenRequest::new(UserWarren::new(
|
||||
self.user_id,
|
||||
self.warren_id,
|
||||
self.can_list_files,
|
||||
self.can_read_files,
|
||||
self.can_modify_files,
|
||||
self.can_delete_files,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create_user_warren<WS: WarrenService, AS: AuthService>(
|
||||
State(state): State<AppState<WS, AS>>,
|
||||
SessionIdHeader(session): SessionIdHeader,
|
||||
Json(request): Json<CreateUserWarrenHttpRequestBody>,
|
||||
) -> Result<ApiSuccess<UserWarrenData>, ApiError> {
|
||||
let domain_request = request.into_domain();
|
||||
|
||||
state
|
||||
.auth_service
|
||||
.create_user_warren(AuthRequest::new(session, domain_request))
|
||||
.await
|
||||
.map(|user_warren| ApiSuccess::new(StatusCode::OK, user_warren.into()))
|
||||
.map_err(ApiError::from)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
use axum::{Json, extract::State, http::StatusCode};
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{auth_session::AuthRequest, user_warren::requests::DeleteUserWarrenRequest},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{
|
||||
AppState,
|
||||
handlers::{UserWarrenData, extractors::SessionIdHeader},
|
||||
responses::{ApiError, ApiSuccess},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(super) struct DeleteUserWarrenHttpRequestBody {
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
}
|
||||
|
||||
impl DeleteUserWarrenHttpRequestBody {
|
||||
fn into_domain(self) -> DeleteUserWarrenRequest {
|
||||
DeleteUserWarrenRequest::new(self.user_id, self.warren_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_user_warren<WS: WarrenService, AS: AuthService>(
|
||||
State(state): State<AppState<WS, AS>>,
|
||||
SessionIdHeader(session): SessionIdHeader,
|
||||
Json(request): Json<DeleteUserWarrenHttpRequestBody>,
|
||||
) -> Result<ApiSuccess<UserWarrenData>, ApiError> {
|
||||
let domain_request = request.into_domain();
|
||||
|
||||
state
|
||||
.auth_service
|
||||
.delete_user_warren(AuthRequest::new(session, domain_request))
|
||||
.await
|
||||
.map(|user_warren| ApiSuccess::new(StatusCode::OK, user_warren.into()))
|
||||
.map_err(ApiError::from)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
use axum::{Json, extract::State, http::StatusCode};
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
auth_session::AuthRequest,
|
||||
user_warren::{UserWarren, requests::EditUserWarrenRequest},
|
||||
},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{
|
||||
AppState,
|
||||
handlers::{UserWarrenData, extractors::SessionIdHeader},
|
||||
responses::{ApiError, ApiSuccess},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(super) struct EditUserWarrenHttpRequestBody {
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
can_list_files: bool,
|
||||
can_read_files: bool,
|
||||
can_modify_files: bool,
|
||||
can_delete_files: bool,
|
||||
}
|
||||
|
||||
impl EditUserWarrenHttpRequestBody {
|
||||
fn into_domain(self) -> EditUserWarrenRequest {
|
||||
EditUserWarrenRequest::new(UserWarren::new(
|
||||
self.user_id,
|
||||
self.warren_id,
|
||||
self.can_list_files,
|
||||
self.can_read_files,
|
||||
self.can_modify_files,
|
||||
self.can_delete_files,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn edit_user_warren<WS: WarrenService, AS: AuthService>(
|
||||
State(state): State<AppState<WS, AS>>,
|
||||
SessionIdHeader(session): SessionIdHeader,
|
||||
Json(request): Json<EditUserWarrenHttpRequestBody>,
|
||||
) -> Result<ApiSuccess<UserWarrenData>, ApiError> {
|
||||
let domain_request = request.into_domain();
|
||||
|
||||
state
|
||||
.auth_service
|
||||
.edit_user_warren(AuthRequest::new(session, domain_request))
|
||||
.await
|
||||
.map(|user_warren| ApiSuccess::new(StatusCode::OK, user_warren.into()))
|
||||
.map_err(ApiError::from)
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
},
|
||||
inbound::http::{
|
||||
AppState,
|
||||
handlers::{UserData, UserWarrenData, WarrenData, extractors::SessionIdHeader},
|
||||
handlers::{AdminWarrenData, UserData, UserWarrenData, extractors::SessionIdHeader},
|
||||
responses::{ApiError, ApiSuccess},
|
||||
},
|
||||
};
|
||||
@@ -21,7 +21,7 @@ use crate::{
|
||||
pub(super) struct ListAllUsersAndWarrensHttpResponseBody {
|
||||
users: Vec<UserData>,
|
||||
user_warrens: Vec<UserWarrenData>,
|
||||
warrens: Vec<WarrenData>,
|
||||
warrens: Vec<AdminWarrenData>,
|
||||
}
|
||||
|
||||
impl From<ListAllUsersAndWarrensResponse> for ListAllUsersAndWarrensHttpResponseBody {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
mod create_user;
|
||||
mod create_user_warren;
|
||||
mod delete_user;
|
||||
mod delete_user_warren;
|
||||
mod edit_user;
|
||||
mod edit_user_warren;
|
||||
mod list_all_users_and_warrens;
|
||||
mod list_users;
|
||||
|
||||
use create_user::create_user;
|
||||
use create_user_warren::create_user_warren;
|
||||
use delete_user::delete_user;
|
||||
use delete_user_warren::delete_user_warren;
|
||||
use edit_user::edit_user;
|
||||
use edit_user_warren::edit_user_warren;
|
||||
use list_all_users_and_warrens::list_all_users_and_warrens;
|
||||
use list_users::list_users;
|
||||
|
||||
@@ -27,4 +33,7 @@ pub fn routes<WS: WarrenService, AS: AuthService>() -> Router<AppState<WS, AS>>
|
||||
.route("/users", post(create_user))
|
||||
.route("/users", patch(edit_user))
|
||||
.route("/users", delete(delete_user))
|
||||
.route("/user-warrens", post(create_user_warren))
|
||||
.route("/user-warrens", patch(edit_user_warren))
|
||||
.route("/user-warrens", delete(delete_user_warren))
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ impl From<FetchAuthSessionResponse> for FetchSessionResponseBody {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Remove the `WarrenAuth ` bit and let the service handle that
|
||||
pub async fn fetch_session<WS: WarrenService, AS: AuthService>(
|
||||
State(state): State<AppState<WS, AS>>,
|
||||
headers: HeaderMap,
|
||||
@@ -43,7 +44,7 @@ pub async fn fetch_session<WS: WarrenService, AS: AuthService>(
|
||||
h.to_str()
|
||||
.map(|h| AuthSessionId::new(&h["WarrenAuth ".len()..]))
|
||||
}) else {
|
||||
return Err(ApiError::BadRequest(
|
||||
return Err(ApiError::Unauthorized(
|
||||
"No authorization header set".to_string(),
|
||||
));
|
||||
};
|
||||
|
||||
@@ -35,12 +35,10 @@ impl From<User> for UserData {
|
||||
pub(super) struct UserWarrenData {
|
||||
user_id: Uuid,
|
||||
warren_id: Uuid,
|
||||
can_create_children: bool,
|
||||
can_list_files: bool,
|
||||
can_read_files: bool,
|
||||
can_modify_files: bool,
|
||||
can_delete_files: bool,
|
||||
can_delete_warren: bool,
|
||||
}
|
||||
|
||||
impl From<UserWarren> for UserWarrenData {
|
||||
@@ -48,12 +46,10 @@ impl From<UserWarren> for UserWarrenData {
|
||||
Self {
|
||||
user_id: *value.user_id(),
|
||||
warren_id: *value.warren_id(),
|
||||
can_create_children: value.can_create_children(),
|
||||
can_list_files: value.can_list_files(),
|
||||
can_read_files: value.can_read_files(),
|
||||
can_modify_files: value.can_modify_files(),
|
||||
can_delete_files: value.can_delete_files(),
|
||||
can_delete_warren: value.can_delete_warren(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,3 +70,22 @@ impl From<Warren> for WarrenData {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
/// A warren with admin data that can be safely sent to the client
|
||||
pub(super) struct AdminWarrenData {
|
||||
id: Uuid,
|
||||
name: String,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl From<Warren> for AdminWarrenData {
|
||||
fn from(value: Warren) -> Self {
|
||||
Self {
|
||||
id: *value.id(),
|
||||
name: value.name().to_string(),
|
||||
path: value.path().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
auth_session::AuthRequest, user_warren::requests::ListWarrensRequest, warren::Warren,
|
||||
},
|
||||
models::{auth_session::AuthRequest, warren::Warren},
|
||||
ports::{AuthService, WarrenService},
|
||||
},
|
||||
inbound::http::{
|
||||
@@ -48,7 +46,7 @@ pub async fn list_warrens<WS: WarrenService, AS: AuthService>(
|
||||
State(state): State<AppState<WS, AS>>,
|
||||
SessionIdHeader(session): SessionIdHeader,
|
||||
) -> Result<ApiSuccess<ListWarrensResponseData>, ApiError> {
|
||||
let domain_request = AuthRequest::new(session, ListWarrensRequest::new());
|
||||
let domain_request = AuthRequest::new(session, ());
|
||||
|
||||
state
|
||||
.auth_service
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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 {}",
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user