user permissions
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE user_warrens (
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
warren_id UUID NOT NULL REFERENCES warrens(id) ON DELETE CASCADE,
|
||||||
|
can_create_children BOOLEAN NOT NULL,
|
||||||
|
can_list_files BOOLEAN NOT NULL,
|
||||||
|
can_read_files BOOLEAN NOT NULL,
|
||||||
|
can_modify_files BOOLEAN NOT NULL,
|
||||||
|
can_delete_files BOOLEAN NOT NULL,
|
||||||
|
can_delete_warren BOOLEAN NOT NULL,
|
||||||
|
PRIMARY KEY(user_id, warren_id)
|
||||||
|
);
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
|
use requests::FetchAuthSessionError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use super::user_warren::requests::FetchUserWarrenError;
|
||||||
|
|
||||||
pub mod requests;
|
pub mod requests;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::FromRow)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::FromRow)]
|
||||||
@@ -41,6 +44,58 @@ impl AuthSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum AuthSessionType {
|
||||||
|
WarrenAuth,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct AuthSessionIdWithType {
|
||||||
|
session_type: AuthSessionType,
|
||||||
|
session_id: AuthSessionId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthSessionIdWithType {
|
||||||
|
pub fn from_str(raw: &str) -> Result<Self, AuthSessionIdWithTypeError> {
|
||||||
|
let trimmed = raw.trim();
|
||||||
|
|
||||||
|
if trimmed.len() < 1 {
|
||||||
|
return Err(AuthSessionIdWithTypeError::Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (prefix_length, session_type) = if trimmed.starts_with("WarrenAuth ") {
|
||||||
|
("WarrenAuth ".len(), AuthSessionType::WarrenAuth)
|
||||||
|
} else {
|
||||||
|
return Err(AuthSessionIdWithTypeError::InvalidType);
|
||||||
|
};
|
||||||
|
|
||||||
|
let session_id = AuthSessionId::new(&trimmed[prefix_length..])?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
session_type,
|
||||||
|
session_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn session_type(&self) -> AuthSessionType {
|
||||||
|
self.session_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn session_id(&self) -> &AuthSessionId {
|
||||||
|
&self.session_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum AuthSessionIdWithTypeError {
|
||||||
|
#[error("Invalid auth session type")]
|
||||||
|
InvalidType,
|
||||||
|
#[error(transparent)]
|
||||||
|
AuthSessionId(#[from] AuthSessionIdError),
|
||||||
|
#[error("The auth session id is empty")]
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
/// A valid auth session id
|
/// A valid auth session id
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display, sqlx::Type)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display, sqlx::Type)]
|
||||||
#[sqlx(transparent)]
|
#[sqlx(transparent)]
|
||||||
@@ -67,3 +122,41 @@ pub enum AuthSessionIdError {
|
|||||||
#[error("An auth session id must not be empty")]
|
#[error("An auth session id must not be empty")]
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct AuthRequest<T> {
|
||||||
|
auth: AuthSessionIdWithType,
|
||||||
|
value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> AuthRequest<T> {
|
||||||
|
pub fn new(auth: AuthSessionIdWithType, value: T) -> Self {
|
||||||
|
Self { auth, value }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auth(&self) -> &AuthSessionIdWithType {
|
||||||
|
&self.auth
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> &T {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unpack(self) -> (AuthSessionIdWithType, T) {
|
||||||
|
(self.auth, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum AuthError<T: std::error::Error> {
|
||||||
|
#[error("The requested operation is not permitted")]
|
||||||
|
InsufficientPermissions,
|
||||||
|
#[error(transparent)]
|
||||||
|
FetchAuthSession(#[from] FetchAuthSessionError),
|
||||||
|
#[error(transparent)]
|
||||||
|
FetchUserWarren(#[from] FetchUserWarrenError),
|
||||||
|
#[error(transparent)]
|
||||||
|
Custom(T),
|
||||||
|
#[error(transparent)]
|
||||||
|
Unknown(#[from] anyhow::Error),
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod auth_session;
|
pub mod auth_session;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
pub mod user_warren;
|
||||||
pub mod warren;
|
pub mod warren;
|
||||||
|
|||||||
74
backend/src/lib/domain/warren/models/user_warren/mod.rs
Normal file
74
backend/src/lib/domain/warren/models/user_warren/mod.rs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
pub mod requests;
|
||||||
|
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::FromRow)]
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_id(&self) -> &Uuid {
|
||||||
|
&self.user_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren_id(&self) -> &Uuid {
|
||||||
|
&self.warren_id
|
||||||
|
}
|
||||||
|
pub fn into_warren_id(self) -> Uuid {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_read_files(&self) -> bool {
|
||||||
|
self.can_read_files
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_modify_files(&self) -> bool {
|
||||||
|
self.can_modify_files
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_delete_files(&self) -> bool {
|
||||||
|
self.can_delete_files
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_delete_warren(&self) -> bool {
|
||||||
|
self.can_delete_warren
|
||||||
|
}
|
||||||
|
}
|
||||||
72
backend/src/lib/domain/warren/models/user_warren/requests.rs
Normal file
72
backend/src/lib/domain/warren/models/user_warren/requests.rs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::domain::warren::models::warren::FetchWarrensError;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct FetchUserWarrensRequest {
|
||||||
|
user_id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FetchUserWarrensRequest {
|
||||||
|
pub fn new(user_id: Uuid) -> Self {
|
||||||
|
Self { user_id }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn user_id(&self) -> &Uuid {
|
||||||
|
&self.user_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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),
|
||||||
|
#[error(transparent)]
|
||||||
|
Unknown(#[from] anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct FetchUserWarrenRequest {
|
||||||
|
user_id: Uuid,
|
||||||
|
warren_id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FetchUserWarrenRequest {
|
||||||
|
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 FetchUserWarrenError {
|
||||||
|
#[error("This user warren does not exist")]
|
||||||
|
NotFound,
|
||||||
|
#[error(transparent)]
|
||||||
|
Unknown(#[from] anyhow::Error),
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ use uuid::Uuid;
|
|||||||
use crate::domain::warren::models::file::{
|
use crate::domain::warren::models::file::{
|
||||||
AbsoluteFilePath, CreateDirectoryError, CreateDirectoryRequest, CreateFileError,
|
AbsoluteFilePath, CreateDirectoryError, CreateDirectoryRequest, CreateFileError,
|
||||||
CreateFileRequest, DeleteDirectoryError, DeleteDirectoryRequest, DeleteFileError,
|
CreateFileRequest, DeleteDirectoryError, DeleteDirectoryRequest, DeleteFileError,
|
||||||
DeleteFileRequest, FileName, FilePath, ListFilesError, ListFilesRequest, RelativeFilePath,
|
DeleteFileRequest, File, FileName, FilePath, ListFilesError, ListFilesRequest,
|
||||||
RenameEntryError, RenameEntryRequest,
|
RelativeFilePath, RenameEntryError, RenameEntryRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Warren;
|
use super::Warren;
|
||||||
@@ -34,16 +34,22 @@ pub enum FetchWarrenError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct ListWarrensRequest;
|
pub struct FetchWarrensRequest {
|
||||||
|
ids: Vec<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
impl ListWarrensRequest {
|
impl FetchWarrensRequest {
|
||||||
pub fn new() -> Self {
|
pub fn new(ids: Vec<Uuid>) -> Self {
|
||||||
Self {}
|
Self { ids }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ids(&self) -> &Vec<Uuid> {
|
||||||
|
&self.ids
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ListWarrensError {
|
pub enum FetchWarrensError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Unknown(#[from] anyhow::Error),
|
Unknown(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
@@ -66,6 +72,11 @@ impl ListWarrenFilesRequest {
|
|||||||
pub fn path(&self) -> &AbsoluteFilePath {
|
pub fn path(&self) -> &AbsoluteFilePath {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_fs_request(self, warren: &Warren) -> ListFilesRequest {
|
||||||
|
let path = warren.path().clone().join(&self.path.to_relative());
|
||||||
|
ListFilesRequest::new(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<FetchWarrenRequest> for ListWarrenFilesRequest {
|
impl Into<FetchWarrenRequest> for ListWarrenFilesRequest {
|
||||||
@@ -74,10 +85,23 @@ impl Into<FetchWarrenRequest> for ListWarrenFilesRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListWarrenFilesRequest {
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub fn to_fs_request(self, warren: &Warren) -> ListFilesRequest {
|
pub struct ListWarrenFilesResponse {
|
||||||
let path = warren.path().clone().join(&self.path.to_relative());
|
warren: Warren,
|
||||||
ListFilesRequest::new(path)
|
files: Vec<File>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListWarrenFilesResponse {
|
||||||
|
pub fn new(warren: Warren, files: Vec<File>) -> Self {
|
||||||
|
Self { warren, files }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren(&self) -> &Warren {
|
||||||
|
&self.warren
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn files(&self) -> &Vec<File> {
|
||||||
|
&self.files
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +110,8 @@ pub enum ListWarrenFilesError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FileSystem(#[from] ListFilesError),
|
FileSystem(#[from] ListFilesError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
FetchWarren(#[from] FetchWarrenError),
|
||||||
|
#[error(transparent)]
|
||||||
Unknown(#[from] anyhow::Error),
|
Unknown(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +133,11 @@ impl CreateWarrenDirectoryRequest {
|
|||||||
pub fn path(&self) -> &AbsoluteFilePath {
|
pub fn path(&self) -> &AbsoluteFilePath {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_fs_request(self, warren: &Warren) -> CreateDirectoryRequest {
|
||||||
|
let path = warren.path().clone().join(&self.path.to_relative());
|
||||||
|
CreateDirectoryRequest::new(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<FetchWarrenRequest> for CreateWarrenDirectoryRequest {
|
impl Into<FetchWarrenRequest> for CreateWarrenDirectoryRequest {
|
||||||
@@ -115,10 +146,23 @@ impl Into<FetchWarrenRequest> for CreateWarrenDirectoryRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateWarrenDirectoryRequest {
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub fn to_fs_request(self, warren: &Warren) -> CreateDirectoryRequest {
|
pub struct CreateWarrenDirectoryResponse {
|
||||||
let path = warren.path().clone().join(&self.path.to_relative());
|
warren: Warren,
|
||||||
CreateDirectoryRequest::new(path)
|
path: FilePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CreateWarrenDirectoryResponse {
|
||||||
|
pub fn new(warren: Warren, path: FilePath) -> Self {
|
||||||
|
Self { warren, path }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren(&self) -> &Warren {
|
||||||
|
&self.warren
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &FilePath {
|
||||||
|
&self.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +171,8 @@ pub enum CreateWarrenDirectoryError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FileSystem(#[from] CreateDirectoryError),
|
FileSystem(#[from] CreateDirectoryError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
FetchWarren(#[from] FetchWarrenError),
|
||||||
|
#[error(transparent)]
|
||||||
Unknown(#[from] anyhow::Error),
|
Unknown(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,11 +216,33 @@ impl Into<FetchWarrenRequest> for &DeleteWarrenDirectoryRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct DeleteWarrenDirectoryResponse {
|
||||||
|
warren: Warren,
|
||||||
|
path: FilePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeleteWarrenDirectoryResponse {
|
||||||
|
pub fn new(warren: Warren, path: FilePath) -> Self {
|
||||||
|
Self { warren, path }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren(&self) -> &Warren {
|
||||||
|
&self.warren
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &FilePath {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum DeleteWarrenDirectoryError {
|
pub enum DeleteWarrenDirectoryError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FileSystem(#[from] DeleteDirectoryError),
|
FileSystem(#[from] DeleteDirectoryError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
FetchWarren(#[from] FetchWarrenError),
|
||||||
|
#[error(transparent)]
|
||||||
Unknown(#[from] anyhow::Error),
|
Unknown(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,11 +277,33 @@ impl Into<FetchWarrenRequest> for &DeleteWarrenFileRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct DeleteWarrenFileResponse {
|
||||||
|
warren: Warren,
|
||||||
|
path: FilePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeleteWarrenFileResponse {
|
||||||
|
pub fn new(warren: Warren, path: FilePath) -> Self {
|
||||||
|
Self { warren, path }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren(&self) -> &Warren {
|
||||||
|
&self.warren
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &FilePath {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum DeleteWarrenFileError {
|
pub enum DeleteWarrenFileError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FileSystem(#[from] DeleteFileError),
|
FileSystem(#[from] DeleteFileError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
FetchWarren(#[from] FetchWarrenError),
|
||||||
|
#[error(transparent)]
|
||||||
Unknown(#[from] anyhow::Error),
|
Unknown(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +353,26 @@ impl Into<FetchWarrenRequest> for &UploadWarrenFilesRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct UploadWarrenFilesResponse {
|
||||||
|
warren: Warren,
|
||||||
|
paths: Vec<FilePath>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UploadWarrenFilesResponse {
|
||||||
|
pub fn new(warren: Warren, paths: Vec<FilePath>) -> Self {
|
||||||
|
Self { warren, paths }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren(&self) -> &Warren {
|
||||||
|
&self.warren
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paths(&self) -> &Vec<FilePath> {
|
||||||
|
&self.paths
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum UploadWarrenFilesError {
|
pub enum UploadWarrenFilesError {
|
||||||
#[error("Failed to upload the file at index {fail_index}")]
|
#[error("Failed to upload the file at index {fail_index}")]
|
||||||
@@ -270,6 +380,8 @@ pub enum UploadWarrenFilesError {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FileSystem(#[from] CreateFileError),
|
FileSystem(#[from] CreateFileError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
FetchWarren(#[from] FetchWarrenError),
|
||||||
|
#[error(transparent)]
|
||||||
Unknown(#[from] anyhow::Error),
|
Unknown(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,10 +464,39 @@ impl Into<FetchWarrenRequest> for &RenameWarrenEntryRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct RenameWarrenEntryResponse {
|
||||||
|
warren: Warren,
|
||||||
|
old_path: AbsoluteFilePath,
|
||||||
|
path: FilePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenameWarrenEntryResponse {
|
||||||
|
pub fn new(warren: Warren, old_path: AbsoluteFilePath, path: FilePath) -> Self {
|
||||||
|
Self {
|
||||||
|
warren,
|
||||||
|
old_path,
|
||||||
|
path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warren(&self) -> &Warren {
|
||||||
|
&self.warren
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn old_path(&self) -> &AbsoluteFilePath {
|
||||||
|
&self.old_path
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &FilePath {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum RenameWarrenEntryError {
|
pub enum RenameWarrenEntryError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Fetch(#[from] FetchWarrenError),
|
FetchWarren(#[from] FetchWarrenError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Rename(#[from] RenameEntryError),
|
Rename(#[from] RenameEntryError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|||||||
@@ -61,4 +61,33 @@ pub trait AuthMetrics: Clone + Send + Sync + 'static {
|
|||||||
|
|
||||||
fn record_auth_session_fetch_success(&self) -> impl Future<Output = ()> + Send;
|
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_session_fetch_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;
|
||||||
|
|
||||||
|
fn record_auth_fetch_user_warren_list_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_fetch_user_warren_list_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_auth_warren_fetch_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_warren_fetch_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_auth_warren_file_list_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_warren_file_list_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_auth_warren_directory_creation_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_warren_directory_creation_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_auth_warren_directory_deletion_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_warren_directory_deletion_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
/// An upload succeeded fully
|
||||||
|
fn record_auth_warren_files_upload_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
/// An upload failed at least partially
|
||||||
|
fn record_auth_warren_files_upload_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_auth_warren_file_deletion_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_warren_file_deletion_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_auth_warren_entry_rename_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_auth_warren_entry_rename_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub use repository::*;
|
|||||||
|
|
||||||
use super::models::{
|
use super::models::{
|
||||||
auth_session::{
|
auth_session::{
|
||||||
AuthSession,
|
AuthError, AuthRequest, AuthSession,
|
||||||
requests::{
|
requests::{
|
||||||
CreateAuthSessionError, CreateAuthSessionRequest, FetchAuthSessionError,
|
CreateAuthSessionError, CreateAuthSessionRequest, FetchAuthSessionError,
|
||||||
FetchAuthSessionRequest, FetchAuthSessionResponse,
|
FetchAuthSessionRequest, FetchAuthSessionResponse,
|
||||||
@@ -23,54 +23,62 @@ use super::models::{
|
|||||||
LoginUserError, LoginUserRequest, LoginUserResponse, RegisterUserError,
|
LoginUserError, LoginUserRequest, LoginUserResponse, RegisterUserError,
|
||||||
RegisterUserRequest, User,
|
RegisterUserRequest, User,
|
||||||
},
|
},
|
||||||
|
user_warren::{
|
||||||
|
UserWarren,
|
||||||
|
requests::{
|
||||||
|
FetchUserWarrensError, FetchUserWarrensRequest, ListWarrensError, ListWarrensRequest,
|
||||||
|
},
|
||||||
|
},
|
||||||
warren::{
|
warren::{
|
||||||
CreateWarrenDirectoryError, CreateWarrenDirectoryRequest, DeleteWarrenDirectoryError,
|
CreateWarrenDirectoryError, CreateWarrenDirectoryRequest, CreateWarrenDirectoryResponse,
|
||||||
DeleteWarrenDirectoryRequest, DeleteWarrenFileError, DeleteWarrenFileRequest,
|
DeleteWarrenDirectoryError, DeleteWarrenDirectoryRequest, DeleteWarrenDirectoryResponse,
|
||||||
FetchWarrenError, FetchWarrenRequest, ListWarrenFilesError, ListWarrenFilesRequest,
|
DeleteWarrenFileError, DeleteWarrenFileRequest, DeleteWarrenFileResponse, FetchWarrenError,
|
||||||
ListWarrensError, ListWarrensRequest, RenameWarrenEntryError, RenameWarrenEntryRequest,
|
FetchWarrenRequest, FetchWarrensError, FetchWarrensRequest, ListWarrenFilesError,
|
||||||
UploadWarrenFilesError, UploadWarrenFilesRequest, Warren,
|
ListWarrenFilesRequest, ListWarrenFilesResponse, RenameWarrenEntryError,
|
||||||
|
RenameWarrenEntryRequest, RenameWarrenEntryResponse, UploadWarrenFilesError,
|
||||||
|
UploadWarrenFilesRequest, UploadWarrenFilesResponse, Warren,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait WarrenService: Clone + Send + Sync + 'static {
|
pub trait WarrenService: Clone + Send + Sync + 'static {
|
||||||
fn list_warrens(
|
fn list_warrens(
|
||||||
&self,
|
&self,
|
||||||
request: ListWarrensRequest,
|
request: FetchWarrensRequest,
|
||||||
) -> impl Future<Output = Result<Vec<Warren>, ListWarrensError>> + Send;
|
) -> impl Future<Output = Result<Vec<Warren>, FetchWarrensError>> + Send;
|
||||||
|
|
||||||
fn fetch_warren(
|
fn fetch_warren(
|
||||||
&self,
|
&self,
|
||||||
request: FetchWarrenRequest,
|
request: FetchWarrenRequest,
|
||||||
) -> impl Future<Output = Result<Warren, FetchWarrenError>> + Send;
|
) -> impl Future<Output = Result<Warren, FetchWarrenError>> + Send;
|
||||||
|
|
||||||
fn list_files(
|
fn list_warren_files(
|
||||||
&self,
|
&self,
|
||||||
request: ListWarrenFilesRequest,
|
request: ListWarrenFilesRequest,
|
||||||
) -> impl Future<Output = Result<Vec<File>, ListWarrenFilesError>> + Send;
|
) -> impl Future<Output = Result<ListWarrenFilesResponse, ListWarrenFilesError>> + Send;
|
||||||
|
|
||||||
fn create_warren_directory(
|
fn create_warren_directory(
|
||||||
&self,
|
&self,
|
||||||
request: CreateWarrenDirectoryRequest,
|
request: CreateWarrenDirectoryRequest,
|
||||||
) -> impl Future<Output = Result<FilePath, CreateWarrenDirectoryError>> + Send;
|
) -> impl Future<Output = Result<CreateWarrenDirectoryResponse, CreateWarrenDirectoryError>> + Send;
|
||||||
|
|
||||||
fn delete_warren_directory(
|
fn delete_warren_directory(
|
||||||
&self,
|
&self,
|
||||||
request: DeleteWarrenDirectoryRequest,
|
request: DeleteWarrenDirectoryRequest,
|
||||||
) -> impl Future<Output = Result<FilePath, DeleteWarrenDirectoryError>> + Send;
|
) -> impl Future<Output = Result<DeleteWarrenDirectoryResponse, DeleteWarrenDirectoryError>> + Send;
|
||||||
|
|
||||||
fn upload_warren_files(
|
fn upload_warren_files(
|
||||||
&self,
|
&self,
|
||||||
request: UploadWarrenFilesRequest,
|
request: UploadWarrenFilesRequest,
|
||||||
) -> impl Future<Output = Result<Vec<FilePath>, UploadWarrenFilesError>> + Send;
|
) -> impl Future<Output = Result<UploadWarrenFilesResponse, UploadWarrenFilesError>> + Send;
|
||||||
fn delete_warren_file(
|
fn delete_warren_file(
|
||||||
&self,
|
&self,
|
||||||
request: DeleteWarrenFileRequest,
|
request: DeleteWarrenFileRequest,
|
||||||
) -> impl Future<Output = Result<FilePath, DeleteWarrenFileError>> + Send;
|
) -> impl Future<Output = Result<DeleteWarrenFileResponse, DeleteWarrenFileError>> + Send;
|
||||||
|
|
||||||
fn rename_warren_entry(
|
fn rename_warren_entry(
|
||||||
&self,
|
&self,
|
||||||
request: RenameWarrenEntryRequest,
|
request: RenameWarrenEntryRequest,
|
||||||
) -> impl Future<Output = Result<FilePath, RenameWarrenEntryError>> + Send;
|
) -> impl Future<Output = Result<RenameWarrenEntryResponse, RenameWarrenEntryError>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FileSystemService: Clone + Send + Sync + 'static {
|
pub trait FileSystemService: Clone + Send + Sync + 'static {
|
||||||
@@ -112,6 +120,7 @@ pub trait AuthService: Clone + Send + Sync + 'static {
|
|||||||
&self,
|
&self,
|
||||||
request: LoginUserRequest,
|
request: LoginUserRequest,
|
||||||
) -> impl Future<Output = Result<LoginUserResponse, LoginUserError>> + Send;
|
) -> impl Future<Output = Result<LoginUserResponse, LoginUserError>> + Send;
|
||||||
|
|
||||||
fn create_auth_session(
|
fn create_auth_session(
|
||||||
&self,
|
&self,
|
||||||
request: CreateAuthSessionRequest,
|
request: CreateAuthSessionRequest,
|
||||||
@@ -120,4 +129,60 @@ pub trait AuthService: Clone + Send + Sync + 'static {
|
|||||||
&self,
|
&self,
|
||||||
request: FetchAuthSessionRequest,
|
request: FetchAuthSessionRequest,
|
||||||
) -> impl Future<Output = Result<FetchAuthSessionResponse, FetchAuthSessionError>> + Send;
|
) -> impl Future<Output = Result<FetchAuthSessionResponse, FetchAuthSessionError>> + Send;
|
||||||
|
|
||||||
|
fn list_warrens<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<ListWarrensRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<Output = Result<Vec<Warren>, AuthError<ListWarrensError>>> + Send;
|
||||||
|
|
||||||
|
fn fetch_user_warrens(
|
||||||
|
&self,
|
||||||
|
request: FetchUserWarrensRequest,
|
||||||
|
) -> impl Future<Output = Result<Vec<UserWarren>, FetchUserWarrensError>> + Send;
|
||||||
|
|
||||||
|
fn fetch_warren<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<FetchWarrenRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<Output = Result<Warren, AuthError<FetchWarrenError>>> + Send;
|
||||||
|
|
||||||
|
fn list_warren_files<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<ListWarrenFilesRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<Output = Result<ListWarrenFilesResponse, AuthError<ListWarrenFilesError>>> + Send;
|
||||||
|
|
||||||
|
fn create_warren_directory<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<CreateWarrenDirectoryRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<
|
||||||
|
Output = Result<CreateWarrenDirectoryResponse, AuthError<CreateWarrenDirectoryError>>,
|
||||||
|
> + Send;
|
||||||
|
|
||||||
|
fn delete_warren_directory<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<DeleteWarrenDirectoryRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<
|
||||||
|
Output = Result<DeleteWarrenDirectoryResponse, AuthError<DeleteWarrenDirectoryError>>,
|
||||||
|
> + Send;
|
||||||
|
|
||||||
|
fn upload_warren_files<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<UploadWarrenFilesRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<Output = Result<UploadWarrenFilesResponse, AuthError<UploadWarrenFilesError>>> + Send;
|
||||||
|
fn delete_warren_file<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<DeleteWarrenFileRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<Output = Result<DeleteWarrenFileResponse, AuthError<DeleteWarrenFileError>>> + Send;
|
||||||
|
|
||||||
|
fn rename_warren_entry<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<RenameWarrenEntryRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> impl Future<Output = Result<RenameWarrenEntryResponse, AuthError<RenameWarrenEntryError>>> + Send;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use crate::domain::warren::models::{
|
use crate::domain::warren::models::{
|
||||||
auth_session::requests::FetchAuthSessionResponse,
|
auth_session::requests::FetchAuthSessionResponse,
|
||||||
file::{AbsoluteFilePath, File, FilePath},
|
file::{File, FilePath},
|
||||||
user::{LoginUserResponse, User},
|
user::{LoginUserResponse, User},
|
||||||
warren::Warren,
|
user_warren::UserWarren,
|
||||||
|
warren::{
|
||||||
|
CreateWarrenDirectoryResponse, DeleteWarrenDirectoryResponse, DeleteWarrenFileResponse,
|
||||||
|
ListWarrenFilesResponse, RenameWarrenEntryResponse, UploadWarrenFilesResponse, Warren,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait WarrenNotifier: Clone + Send + Sync + 'static {
|
pub trait WarrenNotifier: Clone + Send + Sync + 'static {
|
||||||
@@ -12,18 +16,15 @@ pub trait WarrenNotifier: Clone + Send + Sync + 'static {
|
|||||||
fn warren_fetched(&self, warren: &Warren) -> impl Future<Output = ()> + Send;
|
fn warren_fetched(&self, warren: &Warren) -> impl Future<Output = ()> + Send;
|
||||||
fn warren_files_listed(
|
fn warren_files_listed(
|
||||||
&self,
|
&self,
|
||||||
warren: &Warren,
|
response: &ListWarrenFilesResponse,
|
||||||
files: &Vec<File>,
|
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
fn warren_directory_created(
|
fn warren_directory_created(
|
||||||
&self,
|
&self,
|
||||||
warren: &Warren,
|
response: &CreateWarrenDirectoryResponse,
|
||||||
path: &FilePath,
|
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
fn warren_directory_deleted(
|
fn warren_directory_deleted(
|
||||||
&self,
|
&self,
|
||||||
warren: &Warren,
|
response: &DeleteWarrenDirectoryResponse,
|
||||||
path: &FilePath,
|
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
/// A single file was uploaded
|
/// A single file was uploaded
|
||||||
///
|
///
|
||||||
@@ -40,20 +41,16 @@ pub trait WarrenNotifier: Clone + Send + Sync + 'static {
|
|||||||
/// * `files`: The files' paths
|
/// * `files`: The files' paths
|
||||||
fn warren_files_uploaded(
|
fn warren_files_uploaded(
|
||||||
&self,
|
&self,
|
||||||
warren: &Warren,
|
response: &UploadWarrenFilesResponse,
|
||||||
files: &[FilePath],
|
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
fn warren_file_deleted(
|
fn warren_file_deleted(
|
||||||
&self,
|
&self,
|
||||||
warren: &Warren,
|
response: &DeleteWarrenFileResponse,
|
||||||
path: &FilePath,
|
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
fn warren_entry_renamed(
|
fn warren_entry_renamed(
|
||||||
&self,
|
&self,
|
||||||
warren: &Warren,
|
response: &RenameWarrenEntryResponse,
|
||||||
old_path: &AbsoluteFilePath,
|
|
||||||
new_path: &FilePath,
|
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,4 +78,52 @@ pub trait AuthNotifier: Clone + Send + Sync + 'static {
|
|||||||
&self,
|
&self,
|
||||||
response: &FetchAuthSessionResponse,
|
response: &FetchAuthSessionResponse,
|
||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn auth_user_warrens_listed(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
warrens: &Vec<Warren>,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
fn auth_user_warrens_fetched(
|
||||||
|
&self,
|
||||||
|
user_id: &Uuid,
|
||||||
|
user_warrens: &Vec<UserWarren>,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn auth_warren_fetched(&self, user: &User, warren: &Warren) -> impl Future<Output = ()> + Send;
|
||||||
|
fn auth_warren_files_listed(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &ListWarrenFilesResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
fn auth_warren_directory_created(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &CreateWarrenDirectoryResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
fn auth_warren_directory_deleted(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &DeleteWarrenDirectoryResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
/// A collection of files was uploaded
|
||||||
|
///
|
||||||
|
/// * `warren`: The warren the file was uploaded to
|
||||||
|
/// * `files`: The files' paths
|
||||||
|
fn auth_warren_files_uploaded(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &UploadWarrenFilesResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
fn auth_warren_file_deleted(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &DeleteWarrenFileResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn auth_warren_entry_renamed(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &RenameWarrenEntryResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,23 @@ use crate::domain::warren::models::{
|
|||||||
RegisterUserError, RegisterUserRequest, User, VerifyUserPasswordError,
|
RegisterUserError, RegisterUserRequest, User, VerifyUserPasswordError,
|
||||||
VerifyUserPasswordRequest,
|
VerifyUserPasswordRequest,
|
||||||
},
|
},
|
||||||
warren::{FetchWarrenError, FetchWarrenRequest, ListWarrensError, ListWarrensRequest, Warren},
|
user_warren::{
|
||||||
|
UserWarren,
|
||||||
|
requests::{
|
||||||
|
FetchUserWarrenError, FetchUserWarrenRequest, FetchUserWarrensError,
|
||||||
|
FetchUserWarrensRequest,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warren::{
|
||||||
|
FetchWarrenError, FetchWarrenRequest, FetchWarrensError, FetchWarrensRequest, Warren,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait WarrenRepository: Clone + Send + Sync + 'static {
|
pub trait WarrenRepository: Clone + Send + Sync + 'static {
|
||||||
fn list_warrens(
|
fn list_warrens(
|
||||||
&self,
|
&self,
|
||||||
request: ListWarrensRequest,
|
request: FetchWarrensRequest,
|
||||||
) -> impl Future<Output = Result<Vec<Warren>, ListWarrensError>> + Send;
|
) -> impl Future<Output = Result<Vec<Warren>, FetchWarrensError>> + Send;
|
||||||
|
|
||||||
fn fetch_warren(
|
fn fetch_warren(
|
||||||
&self,
|
&self,
|
||||||
@@ -77,4 +86,12 @@ pub trait AuthRepository: Clone + Send + Sync + 'static {
|
|||||||
&self,
|
&self,
|
||||||
request: FetchAuthSessionRequest,
|
request: FetchAuthSessionRequest,
|
||||||
) -> impl Future<Output = Result<FetchAuthSessionResponse, FetchAuthSessionError>> + Send;
|
) -> impl Future<Output = Result<FetchAuthSessionResponse, FetchAuthSessionError>> + Send;
|
||||||
|
fn fetch_user_warrens(
|
||||||
|
&self,
|
||||||
|
request: FetchUserWarrensRequest,
|
||||||
|
) -> impl Future<Output = Result<Vec<UserWarren>, FetchUserWarrensError>> + Send;
|
||||||
|
fn fetch_user_warren(
|
||||||
|
&self,
|
||||||
|
request: FetchUserWarrenRequest,
|
||||||
|
) -> impl Future<Output = Result<UserWarren, FetchUserWarrenError>> + Send;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::{
|
|||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
auth_session::{
|
auth_session::{
|
||||||
AuthSession,
|
AuthError, AuthRequest, AuthSession,
|
||||||
requests::{
|
requests::{
|
||||||
CreateAuthSessionError, CreateAuthSessionRequest, FetchAuthSessionError,
|
CreateAuthSessionError, CreateAuthSessionRequest, FetchAuthSessionError,
|
||||||
FetchAuthSessionRequest, FetchAuthSessionResponse, SessionExpirationTime,
|
FetchAuthSessionRequest, FetchAuthSessionResponse, SessionExpirationTime,
|
||||||
@@ -13,8 +13,25 @@ use crate::{
|
|||||||
LoginUserError, LoginUserRequest, LoginUserResponse, RegisterUserError,
|
LoginUserError, LoginUserRequest, LoginUserResponse, RegisterUserError,
|
||||||
RegisterUserRequest, User,
|
RegisterUserRequest, User,
|
||||||
},
|
},
|
||||||
|
user_warren::{
|
||||||
|
UserWarren,
|
||||||
|
requests::{
|
||||||
|
FetchUserWarrenRequest, FetchUserWarrensError, FetchUserWarrensRequest,
|
||||||
|
ListWarrensError, ListWarrensRequest,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warren::{
|
||||||
|
CreateWarrenDirectoryError, CreateWarrenDirectoryRequest,
|
||||||
|
CreateWarrenDirectoryResponse, DeleteWarrenDirectoryError,
|
||||||
|
DeleteWarrenDirectoryRequest, DeleteWarrenDirectoryResponse, DeleteWarrenFileError,
|
||||||
|
DeleteWarrenFileRequest, DeleteWarrenFileResponse, FetchWarrenError,
|
||||||
|
FetchWarrenRequest, FetchWarrensRequest, ListWarrenFilesError,
|
||||||
|
ListWarrenFilesRequest, ListWarrenFilesResponse, RenameWarrenEntryError,
|
||||||
|
RenameWarrenEntryRequest, RenameWarrenEntryResponse, UploadWarrenFilesError,
|
||||||
|
UploadWarrenFilesRequest, UploadWarrenFilesResponse, Warren,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ports::{AuthMetrics, AuthNotifier, AuthRepository, AuthService},
|
ports::{AuthMetrics, AuthNotifier, AuthRepository, AuthService, WarrenService},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,4 +170,310 @@ where
|
|||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fetch_warren<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<FetchWarrenRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<Warren, AuthError<FetchWarrenError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let result = warren_service.fetch_warren(request).await;
|
||||||
|
|
||||||
|
if let Ok(result) = result.as_ref() {
|
||||||
|
self.metrics.record_auth_warren_fetch_success().await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_fetched(response.user(), result)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics.record_auth_warren_fetch_failure().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_user_warrens(
|
||||||
|
&self,
|
||||||
|
request: FetchUserWarrensRequest,
|
||||||
|
) -> Result<Vec<UserWarren>, FetchUserWarrensError> {
|
||||||
|
let user_id = request.user_id().clone();
|
||||||
|
let result = self.repository.fetch_user_warrens(request).await;
|
||||||
|
|
||||||
|
if let Ok(warren_ids) = result.as_ref() {
|
||||||
|
self.metrics.record_auth_fetch_user_warrens_success().await;
|
||||||
|
self.notifier
|
||||||
|
.auth_user_warrens_fetched(&user_id, warren_ids)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics.record_auth_fetch_user_warrens_failure().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_warrens<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<ListWarrensRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<Vec<Warren>, AuthError<ListWarrensError>> {
|
||||||
|
let (session, _) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let ids = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warrens(FetchUserWarrensRequest::new(*session_response.user().id()))
|
||||||
|
.await
|
||||||
|
.map_err(|e| AuthError::Custom(e.into()))?;
|
||||||
|
|
||||||
|
let result = warren_service
|
||||||
|
.list_warrens(FetchWarrensRequest::new(
|
||||||
|
ids.into_iter().map(|uw| uw.into_warren_id()).collect(),
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
result.map_err(|e| AuthError::Custom(e.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn list_warren_files<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<ListWarrenFilesRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<ListWarrenFilesResponse, AuthError<ListWarrenFilesError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user_warren = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warren(FetchUserWarrenRequest::new(
|
||||||
|
session_response.user().id().clone(),
|
||||||
|
request.warren_id().clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !user_warren.can_list_files() {
|
||||||
|
return Err(AuthError::InsufficientPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = warren_service.list_warren_files(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics.record_auth_warren_file_list_success().await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_files_listed(session_response.user(), response)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics.record_auth_warren_file_list_failure().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn rename_warren_entry<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<RenameWarrenEntryRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<RenameWarrenEntryResponse, AuthError<RenameWarrenEntryError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user_warren = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warren(FetchUserWarrenRequest::new(
|
||||||
|
session_response.user().id().clone(),
|
||||||
|
request.warren_id().clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !user_warren.can_modify_files() {
|
||||||
|
return Err(AuthError::InsufficientPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = warren_service.rename_warren_entry(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics.record_auth_warren_entry_rename_success().await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_entry_renamed(session_response.user(), response)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics.record_auth_warren_entry_rename_failure().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_warren_directory<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<CreateWarrenDirectoryRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<CreateWarrenDirectoryResponse, AuthError<CreateWarrenDirectoryError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user_warren = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warren(FetchUserWarrenRequest::new(
|
||||||
|
session_response.user().id().clone(),
|
||||||
|
request.warren_id().clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// TODO: Maybe create a separate permission for this
|
||||||
|
if !user_warren.can_modify_files() {
|
||||||
|
return Err(AuthError::InsufficientPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = warren_service.create_warren_directory(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics
|
||||||
|
.record_auth_warren_directory_creation_success()
|
||||||
|
.await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_directory_created(session_response.user(), response)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics
|
||||||
|
.record_auth_warren_directory_creation_failure()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_warren_file<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<DeleteWarrenFileRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<DeleteWarrenFileResponse, AuthError<DeleteWarrenFileError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user_warren = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warren(FetchUserWarrenRequest::new(
|
||||||
|
session_response.user().id().clone(),
|
||||||
|
request.warren_id().clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !user_warren.can_delete_files() {
|
||||||
|
return Err(AuthError::InsufficientPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = warren_service.delete_warren_file(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics
|
||||||
|
.record_auth_warren_file_deletion_success()
|
||||||
|
.await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_file_deleted(session_response.user(), response)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics
|
||||||
|
.record_auth_warren_file_deletion_failure()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete_warren_directory<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<DeleteWarrenDirectoryRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<DeleteWarrenDirectoryResponse, AuthError<DeleteWarrenDirectoryError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user_warren = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warren(FetchUserWarrenRequest::new(
|
||||||
|
session_response.user().id().clone(),
|
||||||
|
request.warren_id().clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !user_warren.can_delete_files() {
|
||||||
|
return Err(AuthError::InsufficientPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = warren_service.delete_warren_directory(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics
|
||||||
|
.record_auth_warren_directory_deletion_success()
|
||||||
|
.await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_directory_deleted(session_response.user(), response)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics
|
||||||
|
.record_auth_warren_directory_deletion_failure()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn upload_warren_files<WS: WarrenService>(
|
||||||
|
&self,
|
||||||
|
request: AuthRequest<UploadWarrenFilesRequest>,
|
||||||
|
warren_service: &WS,
|
||||||
|
) -> Result<UploadWarrenFilesResponse, AuthError<UploadWarrenFilesError>> {
|
||||||
|
let (session, request) = request.unpack();
|
||||||
|
|
||||||
|
let session_response = self
|
||||||
|
.fetch_auth_session(FetchAuthSessionRequest::new(session.session_id().clone()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let user_warren = self
|
||||||
|
.repository
|
||||||
|
.fetch_user_warren(FetchUserWarrenRequest::new(
|
||||||
|
session_response.user().id().clone(),
|
||||||
|
request.warren_id().clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// TODO: Maybe create a separate permission for this
|
||||||
|
if !user_warren.can_modify_files() {
|
||||||
|
return Err(AuthError::InsufficientPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = warren_service.upload_warren_files(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics.record_auth_warren_files_upload_success().await;
|
||||||
|
self.notifier
|
||||||
|
.auth_warren_files_uploaded(session_response.user(), response)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
self.metrics.record_auth_warren_files_upload_failure().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.map_err(AuthError::Custom)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
use anyhow::Context;
|
|
||||||
|
|
||||||
use crate::domain::warren::{
|
use crate::domain::warren::{
|
||||||
models::{
|
models::warren::{
|
||||||
file::{File, FilePath},
|
CreateWarrenDirectoryResponse, DeleteWarrenDirectoryResponse, DeleteWarrenFileResponse,
|
||||||
warren::{
|
FetchWarrensError, FetchWarrensRequest, ListWarrenFilesResponse, RenameWarrenEntryError,
|
||||||
ListWarrensError, ListWarrensRequest, RenameWarrenEntryError, RenameWarrenEntryRequest,
|
RenameWarrenEntryRequest, RenameWarrenEntryResponse, UploadWarrenFilesResponse,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
ports::FileSystemService,
|
ports::FileSystemService,
|
||||||
};
|
};
|
||||||
@@ -60,8 +57,8 @@ where
|
|||||||
{
|
{
|
||||||
async fn list_warrens(
|
async fn list_warrens(
|
||||||
&self,
|
&self,
|
||||||
request: ListWarrensRequest,
|
request: FetchWarrensRequest,
|
||||||
) -> Result<Vec<Warren>, ListWarrensError> {
|
) -> Result<Vec<Warren>, FetchWarrensError> {
|
||||||
let result = self.repository.list_warrens(request).await;
|
let result = self.repository.list_warrens(request).await;
|
||||||
|
|
||||||
if let Ok(warren) = result.as_ref() {
|
if let Ok(warren) = result.as_ref() {
|
||||||
@@ -87,24 +84,21 @@ where
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_files(
|
async fn list_warren_files(
|
||||||
&self,
|
&self,
|
||||||
request: ListWarrenFilesRequest,
|
request: ListWarrenFilesRequest,
|
||||||
) -> Result<Vec<File>, ListWarrenFilesError> {
|
) -> Result<ListWarrenFilesResponse, ListWarrenFilesError> {
|
||||||
let warren = self
|
let warren = self.repository.fetch_warren(request.clone().into()).await?;
|
||||||
.repository
|
|
||||||
.fetch_warren(request.clone().into())
|
|
||||||
.await
|
|
||||||
.context("Failed to fetch warren")?;
|
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.fs_service
|
.fs_service
|
||||||
.list_files(request.to_fs_request(&warren))
|
.list_files(request.to_fs_request(&warren))
|
||||||
.await;
|
.await
|
||||||
|
.map(|files| ListWarrenFilesResponse::new(warren, files));
|
||||||
|
|
||||||
if let Ok(files) = result.as_ref() {
|
if let Ok(response) = result.as_ref() {
|
||||||
self.metrics.record_list_warren_files_success().await;
|
self.metrics.record_list_warren_files_success().await;
|
||||||
self.notifier.warren_files_listed(&warren, files).await;
|
self.notifier.warren_files_listed(response).await;
|
||||||
} else {
|
} else {
|
||||||
self.metrics.record_list_warren_files_failure().await;
|
self.metrics.record_list_warren_files_failure().await;
|
||||||
}
|
}
|
||||||
@@ -115,23 +109,20 @@ where
|
|||||||
async fn create_warren_directory(
|
async fn create_warren_directory(
|
||||||
&self,
|
&self,
|
||||||
request: CreateWarrenDirectoryRequest,
|
request: CreateWarrenDirectoryRequest,
|
||||||
) -> Result<FilePath, CreateWarrenDirectoryError> {
|
) -> Result<CreateWarrenDirectoryResponse, CreateWarrenDirectoryError> {
|
||||||
let warren = self
|
let warren = self.repository.fetch_warren(request.clone().into()).await?;
|
||||||
.repository
|
|
||||||
.fetch_warren(request.clone().into())
|
|
||||||
.await
|
|
||||||
.context("Failed to fetch warren")?;
|
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.fs_service
|
.fs_service
|
||||||
.create_directory(request.to_fs_request(&warren))
|
.create_directory(request.to_fs_request(&warren))
|
||||||
.await;
|
.await
|
||||||
|
.map(|path| CreateWarrenDirectoryResponse::new(warren, path));
|
||||||
|
|
||||||
if let Ok(path) = result.as_ref() {
|
if let Ok(response) = result.as_ref() {
|
||||||
self.metrics
|
self.metrics
|
||||||
.record_warren_directory_creation_success()
|
.record_warren_directory_creation_success()
|
||||||
.await;
|
.await;
|
||||||
self.notifier.warren_directory_created(&warren, path).await;
|
self.notifier.warren_directory_created(response).await;
|
||||||
} else {
|
} else {
|
||||||
self.metrics
|
self.metrics
|
||||||
.record_warren_directory_creation_failure()
|
.record_warren_directory_creation_failure()
|
||||||
@@ -144,23 +135,20 @@ where
|
|||||||
async fn delete_warren_directory(
|
async fn delete_warren_directory(
|
||||||
&self,
|
&self,
|
||||||
request: DeleteWarrenDirectoryRequest,
|
request: DeleteWarrenDirectoryRequest,
|
||||||
) -> Result<FilePath, DeleteWarrenDirectoryError> {
|
) -> Result<DeleteWarrenDirectoryResponse, DeleteWarrenDirectoryError> {
|
||||||
let warren = self
|
let warren = self.repository.fetch_warren((&request).into()).await?;
|
||||||
.repository
|
|
||||||
.fetch_warren((&request).into())
|
|
||||||
.await
|
|
||||||
.context("Failed to fetch warren")?;
|
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.fs_service
|
.fs_service
|
||||||
.delete_directory(request.to_fs_request(&warren))
|
.delete_directory(request.to_fs_request(&warren))
|
||||||
.await;
|
.await
|
||||||
|
.map(|path| DeleteWarrenDirectoryResponse::new(warren, path));
|
||||||
|
|
||||||
if let Ok(path) = result.as_ref() {
|
if let Ok(response) = result.as_ref() {
|
||||||
self.metrics
|
self.metrics
|
||||||
.record_warren_directory_deletion_success()
|
.record_warren_directory_deletion_success()
|
||||||
.await;
|
.await;
|
||||||
self.notifier.warren_directory_deleted(&warren, path).await;
|
self.notifier.warren_directory_deleted(response).await;
|
||||||
} else {
|
} else {
|
||||||
self.metrics
|
self.metrics
|
||||||
.record_warren_directory_deletion_failure()
|
.record_warren_directory_deletion_failure()
|
||||||
@@ -174,12 +162,8 @@ where
|
|||||||
async fn upload_warren_files(
|
async fn upload_warren_files(
|
||||||
&self,
|
&self,
|
||||||
request: UploadWarrenFilesRequest,
|
request: UploadWarrenFilesRequest,
|
||||||
) -> Result<Vec<FilePath>, UploadWarrenFilesError> {
|
) -> Result<UploadWarrenFilesResponse, UploadWarrenFilesError> {
|
||||||
let warren = self
|
let warren = self.repository.fetch_warren((&request).into()).await?;
|
||||||
.repository
|
|
||||||
.fetch_warren((&request).into())
|
|
||||||
.await
|
|
||||||
.context("Failed to fetch warren")?;
|
|
||||||
|
|
||||||
let fs_requests = request.to_fs_requests(&warren);
|
let fs_requests = request.to_fs_requests(&warren);
|
||||||
|
|
||||||
@@ -202,30 +186,29 @@ where
|
|||||||
paths.push(file_path);
|
paths.push(file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.metrics.record_warren_files_upload_success().await;
|
let response = UploadWarrenFilesResponse::new(warren, paths);
|
||||||
self.notifier.warren_files_uploaded(&warren, &paths).await;
|
|
||||||
|
|
||||||
Ok(paths)
|
self.metrics.record_warren_files_upload_success().await;
|
||||||
|
self.notifier.warren_files_uploaded(&response).await;
|
||||||
|
|
||||||
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_warren_file(
|
async fn delete_warren_file(
|
||||||
&self,
|
&self,
|
||||||
request: DeleteWarrenFileRequest,
|
request: DeleteWarrenFileRequest,
|
||||||
) -> Result<FilePath, DeleteWarrenFileError> {
|
) -> Result<DeleteWarrenFileResponse, DeleteWarrenFileError> {
|
||||||
let warren = self
|
let warren = self.repository.fetch_warren((&request).into()).await?;
|
||||||
.repository
|
|
||||||
.fetch_warren((&request).into())
|
|
||||||
.await
|
|
||||||
.context("Failed to fetch warren")?;
|
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.fs_service
|
.fs_service
|
||||||
.delete_file(request.to_fs_request(&warren))
|
.delete_file(request.to_fs_request(&warren))
|
||||||
.await;
|
.await
|
||||||
|
.map(|path| DeleteWarrenFileResponse::new(warren, path));
|
||||||
|
|
||||||
if let Ok(path) = result.as_ref() {
|
if let Ok(response) = result.as_ref() {
|
||||||
self.metrics.record_warren_file_deletion_success().await;
|
self.metrics.record_warren_file_deletion_success().await;
|
||||||
self.notifier.warren_file_deleted(&warren, path).await;
|
self.notifier.warren_file_deleted(response).await;
|
||||||
} else {
|
} else {
|
||||||
self.metrics.record_warren_file_deletion_failure().await;
|
self.metrics.record_warren_file_deletion_failure().await;
|
||||||
}
|
}
|
||||||
@@ -236,20 +219,19 @@ where
|
|||||||
async fn rename_warren_entry(
|
async fn rename_warren_entry(
|
||||||
&self,
|
&self,
|
||||||
request: RenameWarrenEntryRequest,
|
request: RenameWarrenEntryRequest,
|
||||||
) -> Result<FilePath, RenameWarrenEntryError> {
|
) -> Result<RenameWarrenEntryResponse, RenameWarrenEntryError> {
|
||||||
let warren = self.repository.fetch_warren((&request).into()).await?;
|
let warren = self.repository.fetch_warren((&request).into()).await?;
|
||||||
|
|
||||||
let old_path = request.path().clone();
|
let old_path = request.path().clone();
|
||||||
let result = self
|
let result = self
|
||||||
.fs_service
|
.fs_service
|
||||||
.rename_entry(request.to_fs_request(&warren))
|
.rename_entry(request.to_fs_request(&warren))
|
||||||
.await;
|
.await
|
||||||
|
.map(|new_path| RenameWarrenEntryResponse::new(warren, old_path, new_path));
|
||||||
|
|
||||||
if let Ok(new_path) = result.as_ref() {
|
if let Ok(response) = result.as_ref() {
|
||||||
self.metrics.record_warren_entry_rename_success().await;
|
self.metrics.record_warren_entry_rename_success().await;
|
||||||
self.notifier
|
self.notifier.warren_entry_renamed(response).await;
|
||||||
.warren_entry_renamed(&warren, &old_path, new_path)
|
|
||||||
.await;
|
|
||||||
} else {
|
} else {
|
||||||
self.metrics.record_warren_entry_rename_failure().await;
|
self.metrics.record_warren_entry_rename_failure().await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::models::{
|
domain::warren::models::{
|
||||||
auth_session::requests::FetchAuthSessionError,
|
auth_session::{AuthError, requests::FetchAuthSessionError},
|
||||||
file::{CreateDirectoryError, DeleteDirectoryError, DeleteFileError, ListFilesError},
|
file::{CreateDirectoryError, DeleteDirectoryError, DeleteFileError, ListFilesError},
|
||||||
user::{LoginUserError, RegisterUserError, VerifyUserPasswordError},
|
user::{LoginUserError, RegisterUserError, VerifyUserPasswordError},
|
||||||
|
user_warren::requests::FetchUserWarrenError,
|
||||||
warren::{
|
warren::{
|
||||||
CreateWarrenDirectoryError, DeleteWarrenDirectoryError, DeleteWarrenFileError,
|
CreateWarrenDirectoryError, DeleteWarrenDirectoryError, DeleteWarrenFileError,
|
||||||
FetchWarrenError, ListWarrenFilesError, ListWarrensError, RenameWarrenEntryError,
|
FetchWarrenError, FetchWarrensError, ListWarrenFilesError, RenameWarrenEntryError,
|
||||||
UploadWarrenFilesError,
|
UploadWarrenFilesError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -32,6 +33,7 @@ impl From<CreateWarrenDirectoryError> for ApiError {
|
|||||||
fn from(value: CreateWarrenDirectoryError) -> Self {
|
fn from(value: CreateWarrenDirectoryError) -> Self {
|
||||||
match value {
|
match value {
|
||||||
CreateWarrenDirectoryError::FileSystem(fs) => fs.into(),
|
CreateWarrenDirectoryError::FileSystem(fs) => fs.into(),
|
||||||
|
CreateWarrenDirectoryError::FetchWarren(err) => err.into(),
|
||||||
CreateWarrenDirectoryError::Unknown(error) => {
|
CreateWarrenDirectoryError::Unknown(error) => {
|
||||||
Self::InternalServerError(error.to_string())
|
Self::InternalServerError(error.to_string())
|
||||||
}
|
}
|
||||||
@@ -57,6 +59,7 @@ impl From<DeleteWarrenDirectoryError> for ApiError {
|
|||||||
fn from(value: DeleteWarrenDirectoryError) -> Self {
|
fn from(value: DeleteWarrenDirectoryError) -> Self {
|
||||||
match value {
|
match value {
|
||||||
DeleteWarrenDirectoryError::FileSystem(fs) => fs.into(),
|
DeleteWarrenDirectoryError::FileSystem(fs) => fs.into(),
|
||||||
|
DeleteWarrenDirectoryError::FetchWarren(err) => err.into(),
|
||||||
DeleteWarrenDirectoryError::Unknown(error) => {
|
DeleteWarrenDirectoryError::Unknown(error) => {
|
||||||
Self::InternalServerError(error.to_string())
|
Self::InternalServerError(error.to_string())
|
||||||
}
|
}
|
||||||
@@ -74,6 +77,7 @@ impl From<DeleteWarrenFileError> for ApiError {
|
|||||||
fn from(value: DeleteWarrenFileError) -> Self {
|
fn from(value: DeleteWarrenFileError) -> Self {
|
||||||
match value {
|
match value {
|
||||||
DeleteWarrenFileError::FileSystem(fs) => fs.into(),
|
DeleteWarrenFileError::FileSystem(fs) => fs.into(),
|
||||||
|
DeleteWarrenFileError::FetchWarren(err) => err.into(),
|
||||||
DeleteWarrenFileError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
DeleteWarrenFileError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,13 +109,14 @@ impl From<ListWarrenFilesError> for ApiError {
|
|||||||
fn from(value: ListWarrenFilesError) -> Self {
|
fn from(value: ListWarrenFilesError) -> Self {
|
||||||
match value {
|
match value {
|
||||||
ListWarrenFilesError::FileSystem(fs_error) => fs_error.into(),
|
ListWarrenFilesError::FileSystem(fs_error) => fs_error.into(),
|
||||||
|
ListWarrenFilesError::FetchWarren(err) => err.into(),
|
||||||
ListWarrenFilesError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
ListWarrenFilesError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ListWarrensError> for ApiError {
|
impl From<FetchWarrensError> for ApiError {
|
||||||
fn from(error: ListWarrensError) -> Self {
|
fn from(error: FetchWarrensError) -> Self {
|
||||||
Self::InternalServerError(error.to_string())
|
Self::InternalServerError(error.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,3 +172,28 @@ impl From<FetchAuthSessionError> for ApiError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<FetchUserWarrenError> for ApiError {
|
||||||
|
fn from(value: FetchUserWarrenError) -> Self {
|
||||||
|
match value {
|
||||||
|
FetchUserWarrenError::NotFound => {
|
||||||
|
Self::NotFound("Could not find the requested warren".to_string())
|
||||||
|
}
|
||||||
|
FetchUserWarrenError::Unknown(err) => Self::InternalServerError(err.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::error::Error> From<AuthError<T>> for ApiError {
|
||||||
|
fn from(value: AuthError<T>) -> Self {
|
||||||
|
match value {
|
||||||
|
AuthError::InsufficientPermissions => {
|
||||||
|
Self::Unauthorized("Insufficient permissions".to_string())
|
||||||
|
}
|
||||||
|
AuthError::FetchAuthSession(err) => err.into(),
|
||||||
|
AuthError::FetchUserWarren(err) => err.into(),
|
||||||
|
AuthError::Custom(err) => Self::InternalServerError(err.to_string()),
|
||||||
|
AuthError::Unknown(err) => Self::InternalServerError(err.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
35
backend/src/lib/inbound/http/handlers/extractors.rs
Normal file
35
backend/src/lib/inbound/http/handlers/extractors.rs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
use axum::{
|
||||||
|
extract::FromRequestParts,
|
||||||
|
http::{header::AUTHORIZATION, request::Parts},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
domain::warren::models::auth_session::AuthSessionIdWithType, inbound::http::responses::ApiError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SessionIdHeader(pub AuthSessionIdWithType);
|
||||||
|
|
||||||
|
impl<S> FromRequestParts<S> for SessionIdHeader
|
||||||
|
where
|
||||||
|
S: Send + Sync,
|
||||||
|
{
|
||||||
|
type Rejection = ApiError;
|
||||||
|
|
||||||
|
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
||||||
|
let Some(header) = parts.headers.get(AUTHORIZATION) else {
|
||||||
|
return Err(ApiError::Unauthorized(
|
||||||
|
"Missing authorization header".to_string(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let header_str = header.to_str().map_err(|_| {
|
||||||
|
ApiError::InternalServerError(
|
||||||
|
"Failed to get authorization header as string".to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
AuthSessionIdWithType::from_str(header_str)
|
||||||
|
.map(|session_id| SessionIdHeader(session_id))
|
||||||
|
.map_err(|_| ApiError::BadRequest("Invalid session id".to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use uuid::Uuid;
|
|||||||
use crate::domain::warren::models::user::User;
|
use crate::domain::warren::models::user::User;
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
pub mod extractors;
|
||||||
pub mod warrens;
|
pub mod warrens;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
||||||
warren::CreateWarrenDirectoryRequest,
|
warren::CreateWarrenDirectoryRequest,
|
||||||
},
|
},
|
||||||
@@ -13,6 +14,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -64,13 +66,14 @@ impl CreateWarrenDirectoryHttpRequestBody {
|
|||||||
|
|
||||||
pub async fn create_warren_directory<WS: WarrenService, AS: AuthService>(
|
pub async fn create_warren_directory<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
Json(request): Json<CreateWarrenDirectoryHttpRequestBody>,
|
Json(request): Json<CreateWarrenDirectoryHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<()>, ApiError> {
|
) -> Result<ApiSuccess<()>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, request.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.create_warren_directory(domain_request)
|
.create_warren_directory(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
||||||
warren::DeleteWarrenDirectoryRequest,
|
warren::DeleteWarrenDirectoryRequest,
|
||||||
},
|
},
|
||||||
@@ -13,6 +14,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -66,13 +68,14 @@ impl DeleteWarrenDirectoryHttpRequestBody {
|
|||||||
|
|
||||||
pub async fn delete_warren_directory<WS: WarrenService, AS: AuthService>(
|
pub async fn delete_warren_directory<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
Json(request): Json<DeleteWarrenDirectoryHttpRequestBody>,
|
Json(request): Json<DeleteWarrenDirectoryHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<()>, ApiError> {
|
) -> Result<ApiSuccess<()>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, request.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.delete_warren_directory(domain_request)
|
.delete_warren_directory(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
||||||
warren::DeleteWarrenFileRequest,
|
warren::DeleteWarrenFileRequest,
|
||||||
},
|
},
|
||||||
@@ -13,6 +14,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -64,13 +66,14 @@ impl DeleteWarrenFileHttpRequestBody {
|
|||||||
|
|
||||||
pub async fn delete_warren_file<WS: WarrenService, AS: AuthService>(
|
pub async fn delete_warren_file<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
Json(request): Json<DeleteWarrenFileHttpRequestBody>,
|
Json(request): Json<DeleteWarrenFileHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<()>, ApiError> {
|
) -> Result<ApiSuccess<()>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, request.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.delete_warren_file(domain_request)
|
.delete_warren_file(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::warren::{FetchWarrenRequest, Warren},
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
|
warren::{FetchWarrenRequest, Warren},
|
||||||
|
},
|
||||||
ports::{AuthService, WarrenService},
|
ports::{AuthService, WarrenService},
|
||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -51,13 +55,14 @@ impl FetchWarrenHttpRequestBody {
|
|||||||
|
|
||||||
pub async fn fetch_warren<WS: WarrenService, AS: AuthService>(
|
pub async fn fetch_warren<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
Json(request): Json<FetchWarrenHttpRequestBody>,
|
Json(request): Json<FetchWarrenHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<FetchWarrenResponseData>, ApiError> {
|
) -> Result<ApiSuccess<FetchWarrenResponseData>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, request.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.fetch_warren(domain_request)
|
.fetch_warren(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|ref warren| ApiSuccess::new(StatusCode::OK, warren.into()))
|
.map(|ref warren| ApiSuccess::new(StatusCode::OK, warren.into()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
file::{AbsoluteFilePathError, File, FileMimeType, FilePath, FilePathError, FileType},
|
file::{AbsoluteFilePathError, File, FileMimeType, FilePath, FilePathError, FileType},
|
||||||
warren::ListWarrenFilesRequest,
|
warren::ListWarrenFilesRequest,
|
||||||
},
|
},
|
||||||
@@ -13,6 +14,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -75,8 +77,8 @@ pub struct ListWarrenFilesResponseData {
|
|||||||
files: Vec<WarrenFileElement>,
|
files: Vec<WarrenFileElement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<File> for WarrenFileElement {
|
impl From<&File> for WarrenFileElement {
|
||||||
fn from(value: File) -> Self {
|
fn from(value: &File) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: value.name().to_string(),
|
name: value.name().to_string(),
|
||||||
file_type: value.file_type().to_owned(),
|
file_type: value.file_type().to_owned(),
|
||||||
@@ -86,24 +88,25 @@ impl From<File> for WarrenFileElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<File>> for ListWarrenFilesResponseData {
|
impl From<&Vec<File>> for ListWarrenFilesResponseData {
|
||||||
fn from(value: Vec<File>) -> Self {
|
fn from(value: &Vec<File>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
files: value.into_iter().map(WarrenFileElement::from).collect(),
|
files: value.iter().map(WarrenFileElement::from).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_warren_files<WS: WarrenService, AS: AuthService>(
|
pub async fn list_warren_files<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
Json(request): Json<ListWarrenFilesHttpRequestBody>,
|
Json(request): Json<ListWarrenFilesHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<ListWarrenFilesResponseData>, ApiError> {
|
) -> Result<ApiSuccess<ListWarrenFilesResponseData>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, request.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.list_files(domain_request)
|
.list_warren_files(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|files| ApiSuccess::new(StatusCode::OK, files.into()))
|
.map(|response| ApiSuccess::new(StatusCode::OK, response.files().into()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::warren::{ListWarrensRequest, Warren},
|
models::{
|
||||||
|
auth_session::AuthRequest, user_warren::requests::ListWarrensRequest, warren::Warren,
|
||||||
|
},
|
||||||
ports::{AuthService, WarrenService},
|
ports::{AuthService, WarrenService},
|
||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -43,12 +46,13 @@ impl From<&Vec<Warren>> for ListWarrensResponseData {
|
|||||||
|
|
||||||
pub async fn list_warrens<WS: WarrenService, AS: AuthService>(
|
pub async fn list_warrens<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
) -> Result<ApiSuccess<ListWarrensResponseData>, ApiError> {
|
) -> Result<ApiSuccess<ListWarrensResponseData>, ApiError> {
|
||||||
let domain_request = ListWarrensRequest::new();
|
let domain_request = AuthRequest::new(session, ListWarrensRequest::new());
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.list_warrens(domain_request)
|
.list_warrens(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
.map(|ref warrens| ApiSuccess::new(StatusCode::OK, warrens.into()))
|
.map(|ref warrens| ApiSuccess::new(StatusCode::OK, warrens.into()))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
file::{
|
file::{
|
||||||
AbsoluteFilePath, AbsoluteFilePathError, FileName, FileNameError, FilePath,
|
AbsoluteFilePath, AbsoluteFilePathError, FileName, FileNameError, FilePath,
|
||||||
FilePathError,
|
FilePathError,
|
||||||
@@ -16,6 +17,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -80,13 +82,14 @@ impl From<ParseRenameWarrenEntryHttpRequestError> for ApiError {
|
|||||||
|
|
||||||
pub async fn rename_warren_entry<WS: WarrenService, AS: AuthService>(
|
pub async fn rename_warren_entry<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
Json(request): Json<RenameWarrenEntryHttpRequestBody>,
|
Json(request): Json<RenameWarrenEntryHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<()>, ApiError> {
|
) -> Result<ApiSuccess<()>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, request.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.rename_warren_entry(domain_request)
|
.rename_warren_entry(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|_| ApiSuccess::new(StatusCode::OK, ()))
|
.map(|_| ApiSuccess::new(StatusCode::OK, ()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
domain::warren::{
|
domain::warren::{
|
||||||
models::{
|
models::{
|
||||||
|
auth_session::AuthRequest,
|
||||||
file::{AbsoluteFilePathError, FileName, FileNameError, FilePath, FilePathError},
|
file::{AbsoluteFilePathError, FileName, FileNameError, FilePath, FilePathError},
|
||||||
warren::{UploadFile, UploadFileList, UploadFileListError, UploadWarrenFilesRequest},
|
warren::{UploadFile, UploadFileList, UploadFileListError, UploadWarrenFilesRequest},
|
||||||
},
|
},
|
||||||
@@ -13,6 +14,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SessionIdHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -94,13 +96,14 @@ impl From<ParseUploadWarrenFilesHttpRequestError> for ApiError {
|
|||||||
|
|
||||||
pub async fn upload_warren_files<WS: WarrenService, AS: AuthService>(
|
pub async fn upload_warren_files<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SessionIdHeader(session): SessionIdHeader,
|
||||||
TypedMultipart(multipart): TypedMultipart<UploadWarrenFilesHttpRequestBody>,
|
TypedMultipart(multipart): TypedMultipart<UploadWarrenFilesHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<()>, ApiError> {
|
) -> Result<ApiSuccess<()>, ApiError> {
|
||||||
let domain_request = multipart.try_into_domain()?;
|
let domain_request = AuthRequest::new(session, multipart.try_into_domain()?);
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.auth_service
|
||||||
.upload_warren_files(domain_request)
|
.upload_warren_files(domain_request, state.warren_service.as_ref())
|
||||||
.await
|
.await
|
||||||
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
.map(|_| ApiSuccess::new(StatusCode::CREATED, ()))
|
||||||
.map_err(ApiError::from)
|
.map_err(ApiError::from)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ impl<T: Serialize + PartialEq> IntoResponse for ApiSuccess<T> {
|
|||||||
pub enum ApiError {
|
pub enum ApiError {
|
||||||
BadRequest(String),
|
BadRequest(String),
|
||||||
NotFound(String),
|
NotFound(String),
|
||||||
|
Unauthorized(String),
|
||||||
InternalServerError(String),
|
InternalServerError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ impl IntoResponse for ApiError {
|
|||||||
match self {
|
match self {
|
||||||
BadRequest(e) => (StatusCode::BAD_REQUEST, e).into_response(),
|
BadRequest(e) => (StatusCode::BAD_REQUEST, e).into_response(),
|
||||||
NotFound(e) => (StatusCode::NOT_FOUND, e).into_response(),
|
NotFound(e) => (StatusCode::NOT_FOUND, e).into_response(),
|
||||||
|
Unauthorized(e) => (StatusCode::UNAUTHORIZED, e).into_response(),
|
||||||
InternalServerError(e) => {
|
InternalServerError(e) => {
|
||||||
tracing::error!("{}", e);
|
tracing::error!("{}", e);
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -151,4 +151,67 @@ impl AuthMetrics for MetricsDebugLogger {
|
|||||||
async fn record_auth_session_fetch_failure(&self) {
|
async fn record_auth_session_fetch_failure(&self) {
|
||||||
tracing::debug!("[Metrics] Auth session fetch failed");
|
tracing::debug!("[Metrics] Auth session fetch failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn record_auth_fetch_user_warren_list_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren list succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_fetch_user_warren_list_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren list failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_fetch_user_warrens_success(&self) -> () {
|
||||||
|
tracing::debug!("[Metrics] Auth user warren id fetch succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_fetch_user_warrens_failure(&self) -> () {
|
||||||
|
tracing::debug!("[Metrics] Auth user warren id fetch failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_fetch_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren fetch succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_fetch_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren fetch failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_file_list_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren file list succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_file_list_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren file list failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_directory_creation_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren directory creation succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_directory_creation_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren directory creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_directory_deletion_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren directory deletion succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_directory_deletion_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren directory deletion failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_file_deletion_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren file deletion succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_file_deletion_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren file deletion failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_entry_rename_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren entry rename succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_entry_rename_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren entry rename failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn record_auth_warren_files_upload_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren files upload succeeded");
|
||||||
|
}
|
||||||
|
async fn record_auth_warren_files_upload_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Auth warren files upload failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ use crate::domain::warren::{
|
|||||||
auth_session::requests::FetchAuthSessionResponse,
|
auth_session::requests::FetchAuthSessionResponse,
|
||||||
file::{File, FilePath},
|
file::{File, FilePath},
|
||||||
user::{LoginUserResponse, User},
|
user::{LoginUserResponse, User},
|
||||||
warren::Warren,
|
user_warren::UserWarren,
|
||||||
|
warren::{
|
||||||
|
CreateWarrenDirectoryResponse, DeleteWarrenDirectoryResponse, DeleteWarrenFileResponse,
|
||||||
|
ListWarrenFilesResponse, RenameWarrenEntryResponse, UploadWarrenFilesResponse, Warren,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ports::{AuthNotifier, FileSystemNotifier, WarrenNotifier},
|
ports::{AuthNotifier, FileSystemNotifier, WarrenNotifier},
|
||||||
};
|
};
|
||||||
@@ -28,27 +32,27 @@ impl WarrenNotifier for NotifierDebugLogger {
|
|||||||
tracing::debug!("[Notifier] Fetched warren {}", warren.name());
|
tracing::debug!("[Notifier] Fetched warren {}", warren.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn warren_files_listed(&self, warren: &Warren, files: &Vec<File>) {
|
async fn warren_files_listed(&self, response: &ListWarrenFilesResponse) {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"[Notifier] Listed {} file(s) in warren {}",
|
"[Notifier] Listed {} file(s) in warren {}",
|
||||||
files.len(),
|
response.files().len(),
|
||||||
warren.name()
|
response.warren().name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn warren_directory_created(&self, warren: &Warren, path: &FilePath) {
|
async fn warren_directory_created(&self, response: &CreateWarrenDirectoryResponse) {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"[Notifier] Created directory {} in warren {}",
|
"[Notifier] Created directory {} in warren {}",
|
||||||
path,
|
response.path(),
|
||||||
warren.name()
|
response.warren().name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn warren_directory_deleted(&self, warren: &Warren, path: &FilePath) {
|
async fn warren_directory_deleted(&self, response: &DeleteWarrenDirectoryResponse) {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"[Notifier] Deleted directory {} in warren {}",
|
"[Notifier] Deleted directory {} in warren {}",
|
||||||
path,
|
response.path(),
|
||||||
warren.name()
|
response.warren().name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,33 +64,28 @@ impl WarrenNotifier for NotifierDebugLogger {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn warren_files_uploaded(&self, warren: &Warren, paths: &[FilePath]) {
|
async fn warren_files_uploaded(&self, response: &UploadWarrenFilesResponse) {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"[Notifier] Uploaded {} file(s) to warren {}",
|
"[Notifier] Uploaded {} file(s) to warren {}",
|
||||||
paths.len(),
|
response.paths().len(),
|
||||||
warren.name()
|
response.warren().name()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn warren_file_deleted(&self, warren: &Warren, path: &FilePath) {
|
async fn warren_file_deleted(&self, response: &DeleteWarrenFileResponse) {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"[Notifier] Deleted file {} from warren {}",
|
"[Notifier] Deleted file {} from warren {}",
|
||||||
path,
|
response.path(),
|
||||||
warren.name(),
|
response.warren().name(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn warren_entry_renamed(
|
async fn warren_entry_renamed(&self, response: &RenameWarrenEntryResponse) {
|
||||||
&self,
|
|
||||||
warren: &Warren,
|
|
||||||
old_path: &crate::domain::warren::models::file::AbsoluteFilePath,
|
|
||||||
new_path: &FilePath,
|
|
||||||
) {
|
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"[Notifier] Renamed file {} to {} in warren {}",
|
"[Notifier] Renamed file {} to {} in warren {}",
|
||||||
old_path,
|
response.old_path(),
|
||||||
new_path,
|
response.path(),
|
||||||
warren.name(),
|
response.warren().name(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,4 +135,91 @@ impl AuthNotifier for NotifierDebugLogger {
|
|||||||
response.user().id()
|
response.user().id()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn auth_user_warrens_fetched(&self, user_id: &Uuid, warren_ids: &Vec<UserWarren>) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Fetched {} user warrens for authenticated user {}",
|
||||||
|
warren_ids.len(),
|
||||||
|
user_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_user_warrens_listed(&self, user: &User, warrens: &Vec<Warren>) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Fetched {} warren(s) for authenticated user {}",
|
||||||
|
warrens.len(),
|
||||||
|
user.id()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_fetched(&self, user: &User, warren: &Warren) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Fetched warren {} for authenticated user {}",
|
||||||
|
warren.name(),
|
||||||
|
user.id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_files_listed(&self, user: &User, response: &ListWarrenFilesResponse) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Listed {} file(s) in warren {} for authenticated user {}",
|
||||||
|
response.files().len(),
|
||||||
|
response.warren().name(),
|
||||||
|
user.id()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_directory_created(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &CreateWarrenDirectoryResponse,
|
||||||
|
) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Created directory {} in warren {} for authenticated user {}",
|
||||||
|
response.path(),
|
||||||
|
response.warren().name(),
|
||||||
|
user.id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_directory_deleted(
|
||||||
|
&self,
|
||||||
|
user: &User,
|
||||||
|
response: &DeleteWarrenDirectoryResponse,
|
||||||
|
) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Deleted directory {} in warren {} for authenticated user {}",
|
||||||
|
response.path(),
|
||||||
|
response.warren().name(),
|
||||||
|
user.id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_files_uploaded(&self, user: &User, response: &UploadWarrenFilesResponse) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Uploaded {} file(s) to warren {} for authenticated user {}",
|
||||||
|
response.paths().len(),
|
||||||
|
response.warren().name(),
|
||||||
|
user.id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_file_deleted(&self, user: &User, response: &DeleteWarrenFileResponse) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Deleted file {} from warren {} for authenticated user {}",
|
||||||
|
response.path(),
|
||||||
|
response.warren().name(),
|
||||||
|
user.id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_warren_entry_renamed(&self, user: &User, response: &RenameWarrenEntryResponse) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Renamed file {} to {} in warren {} for authenticated user {}",
|
||||||
|
response.old_path(),
|
||||||
|
response.path(),
|
||||||
|
response.warren().name(),
|
||||||
|
user.id(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,15 @@ use crate::domain::warren::{
|
|||||||
RegisterUserError, RegisterUserRequest, User, UserEmail, UserName, UserPassword,
|
RegisterUserError, RegisterUserRequest, User, UserEmail, UserName, UserPassword,
|
||||||
VerifyUserPasswordError, VerifyUserPasswordRequest,
|
VerifyUserPasswordError, VerifyUserPasswordRequest,
|
||||||
},
|
},
|
||||||
|
user_warren::{
|
||||||
|
UserWarren,
|
||||||
|
requests::{
|
||||||
|
FetchUserWarrenError, FetchUserWarrenRequest, FetchUserWarrensError,
|
||||||
|
FetchUserWarrensRequest,
|
||||||
|
},
|
||||||
|
},
|
||||||
warren::{
|
warren::{
|
||||||
FetchWarrenError, FetchWarrenRequest, ListWarrensError, ListWarrensRequest, Warren,
|
FetchWarrenError, FetchWarrenRequest, FetchWarrensError, FetchWarrensRequest, Warren,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ports::{AuthRepository, WarrenRepository},
|
ports::{AuthRepository, WarrenRepository},
|
||||||
@@ -103,6 +110,7 @@ impl Postgres {
|
|||||||
async fn list_warrens(
|
async fn list_warrens(
|
||||||
&self,
|
&self,
|
||||||
connection: &mut PgConnection,
|
connection: &mut PgConnection,
|
||||||
|
ids: &[Uuid],
|
||||||
) -> Result<Vec<Warren>, sqlx::Error> {
|
) -> Result<Vec<Warren>, sqlx::Error> {
|
||||||
let warrens: Vec<Warren> = sqlx::query_as::<sqlx::Postgres, Warren>(
|
let warrens: Vec<Warren> = sqlx::query_as::<sqlx::Postgres, Warren>(
|
||||||
"
|
"
|
||||||
@@ -110,10 +118,11 @@ impl Postgres {
|
|||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
warrens
|
warrens
|
||||||
LIMIT
|
WHERE
|
||||||
50
|
id = ANY($1)
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
|
.bind(ids)
|
||||||
.fetch_all(&mut *connection)
|
.fetch_all(&mut *connection)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -292,13 +301,60 @@ impl Postgres {
|
|||||||
|
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_user_warrens(
|
||||||
|
&self,
|
||||||
|
connection: &mut PgConnection,
|
||||||
|
user_id: &Uuid,
|
||||||
|
) -> Result<Vec<UserWarren>, sqlx::Error> {
|
||||||
|
let ids: Vec<UserWarren> = sqlx::query_as(
|
||||||
|
"
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
user_warrens
|
||||||
|
WHERE
|
||||||
|
user_id = $1
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.fetch_all(connection)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_user_warren(
|
||||||
|
&self,
|
||||||
|
connection: &mut PgConnection,
|
||||||
|
user_id: &Uuid,
|
||||||
|
warren_id: &Uuid,
|
||||||
|
) -> Result<UserWarren, sqlx::Error> {
|
||||||
|
let ids: UserWarren = sqlx::query_as(
|
||||||
|
"
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
user_warrens
|
||||||
|
WHERE
|
||||||
|
user_id = $1 AND
|
||||||
|
warren_id = $2
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(warren_id)
|
||||||
|
.fetch_one(connection)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(ids)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WarrenRepository for Postgres {
|
impl WarrenRepository for Postgres {
|
||||||
async fn list_warrens(
|
async fn list_warrens(
|
||||||
&self,
|
&self,
|
||||||
_request: ListWarrensRequest,
|
request: FetchWarrensRequest,
|
||||||
) -> Result<Vec<Warren>, ListWarrensError> {
|
) -> Result<Vec<Warren>, FetchWarrensError> {
|
||||||
let mut connection = self
|
let mut connection = self
|
||||||
.pool
|
.pool
|
||||||
.acquire()
|
.acquire()
|
||||||
@@ -306,7 +362,7 @@ impl WarrenRepository for Postgres {
|
|||||||
.context("Failed to get a PostgreSQL connection")?;
|
.context("Failed to get a PostgreSQL connection")?;
|
||||||
|
|
||||||
let warrens = self
|
let warrens = self
|
||||||
.list_warrens(&mut connection)
|
.list_warrens(&mut connection, request.ids())
|
||||||
.await
|
.await
|
||||||
.map_err(|err| anyhow!(err).context("Failed to list warrens"))?;
|
.map_err(|err| anyhow!(err).context("Failed to list warrens"))?;
|
||||||
|
|
||||||
@@ -424,6 +480,45 @@ impl AuthRepository for Postgres {
|
|||||||
|
|
||||||
Ok(FetchAuthSessionResponse::new(session, user))
|
Ok(FetchAuthSessionResponse::new(session, user))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn fetch_user_warrens(
|
||||||
|
&self,
|
||||||
|
request: FetchUserWarrensRequest,
|
||||||
|
) -> Result<Vec<UserWarren>, FetchUserWarrensError> {
|
||||||
|
let mut connection = self
|
||||||
|
.pool
|
||||||
|
.acquire()
|
||||||
|
.await
|
||||||
|
.context("Failed to get a PostgreSQL connection")?;
|
||||||
|
|
||||||
|
let warren_ids = self
|
||||||
|
.get_user_warrens(&mut connection, request.user_id())
|
||||||
|
.await
|
||||||
|
.context("Failed to get user warrens")?;
|
||||||
|
|
||||||
|
Ok(warren_ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_user_warren(
|
||||||
|
&self,
|
||||||
|
request: FetchUserWarrenRequest,
|
||||||
|
) -> Result<UserWarren, FetchUserWarrenError> {
|
||||||
|
let mut connection = self
|
||||||
|
.pool
|
||||||
|
.acquire()
|
||||||
|
.await
|
||||||
|
.context("Failed to get a PostgreSQL connection")?;
|
||||||
|
|
||||||
|
self.get_user_warren(&mut connection, request.user_id(), request.warren_id())
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
if is_not_found_error(&e) {
|
||||||
|
FetchUserWarrenError::NotFound
|
||||||
|
} else {
|
||||||
|
FetchUserWarrenError::Unknown(anyhow!(e))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_not_found_error(err: &sqlx::Error) -> bool {
|
fn is_not_found_error(err: &sqlx::Error) -> bool {
|
||||||
|
|||||||
@@ -11,5 +11,7 @@ export function getApiHeaders(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
headers['content-type'] = 'application/json';
|
||||||
|
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,7 @@ export async function getWarrenDirectory(
|
|||||||
ApiResponse<{ files: DirectoryEntry[] }>
|
ApiResponse<{ files: DirectoryEntry[] }>
|
||||||
>(getApiUrl(`warrens/files`), {
|
>(getApiUrl(`warrens/files`), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: getApiHeaders(),
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
warrenId,
|
warrenId,
|
||||||
path,
|
path,
|
||||||
@@ -65,9 +63,7 @@ export async function createDirectory(
|
|||||||
|
|
||||||
const { status } = await useFetch(getApiUrl(`warrens/files/directory`), {
|
const { status } = await useFetch(getApiUrl(`warrens/files/directory`), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: getApiHeaders(),
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
warrenId,
|
warrenId,
|
||||||
path,
|
path,
|
||||||
@@ -106,9 +102,7 @@ export async function deleteWarrenDirectory(
|
|||||||
|
|
||||||
const { status } = await useFetch(getApiUrl(`warrens/files/directory`), {
|
const { status } = await useFetch(getApiUrl(`warrens/files/directory`), {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: getApiHeaders(),
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
warrenId,
|
warrenId,
|
||||||
path,
|
path,
|
||||||
@@ -148,9 +142,7 @@ export async function deleteWarrenFile(
|
|||||||
|
|
||||||
const { status } = await useFetch(getApiUrl(`warrens/files/file`), {
|
const { status } = await useFetch(getApiUrl(`warrens/files/file`), {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: getApiHeaders(),
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
warrenId,
|
warrenId,
|
||||||
path,
|
path,
|
||||||
@@ -209,6 +201,11 @@ export async function uploadToWarren(
|
|||||||
body.append('files', file);
|
body.append('files', file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const headers = getApiHeaders();
|
||||||
|
for (const [key, value] of Object.entries(headers)) {
|
||||||
|
xhr.setRequestHeader(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
xhr.send(body);
|
xhr.send(body);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -244,9 +241,7 @@ export async function renameWarrenEntry(
|
|||||||
|
|
||||||
const { status } = await useFetch(getApiUrl(`warrens/files/rename`), {
|
const { status } = await useFetch(getApiUrl(`warrens/files/rename`), {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: getApiHeaders(),
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
warrenId,
|
warrenId,
|
||||||
path,
|
path,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const useWarrenStore = defineStore('warrens', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.current.path.endsWith('/')) {
|
if (!this.current.path.endsWith('/')) {
|
||||||
this.current.path += '/';
|
path = '/' + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.current.path += path;
|
this.current.path += path;
|
||||||
|
|||||||
Reference in New Issue
Block a user