Skip to content

Commit

Permalink
#22 checking whether storage has storage workers or not; added endpoi…
Browse files Browse the repository at this point in the history
…nt for it; added 404 in UI
  • Loading branch information
Dominux committed Dec 19, 2023
1 parent ed2a609 commit c3ab2d9
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 13 deletions.
3 changes: 3 additions & 0 deletions pentaract/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub enum PentaractError {
InvalidFolderName,
#[error("You cannot manage access of yourself")]
CannotManageAccessOfYourself,
#[error("Storage does not have workers")]
StorageDoesNotHaveWorkers,
#[error("unknown error")]
Unknown,
#[error("{0} header is required")]
Expand All @@ -51,6 +53,7 @@ impl From<PentaractError> for (StatusCode, String) {
| PentaractError::StorageChatIdConflict
| PentaractError::StorageWorkerNameConflict
| PentaractError::StorageWorkerTokenConflict
| PentaractError::StorageDoesNotHaveWorkers
| PentaractError::CannotManageAccessOfYourself => (StatusCode::CONFLICT, e.to_string()),
PentaractError::NotAuthenticated => (StatusCode::UNAUTHORIZED, e.to_string()),
PentaractError::DoesNotExist(_) => (StatusCode::NOT_FOUND, e.to_string()),
Expand Down
12 changes: 12 additions & 0 deletions pentaract/src/repositories/storage_workers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ impl<'d> StorageWorkersRepository<'d> {
Ok(sw)
}

pub async fn storage_has_any(&self, storage_id: Uuid) -> PentaractResult<bool> {
let has_sws: (_,) = sqlx::query_as(&format!(
"SELECT COUNT(*) > 0 FROM {STORAGE_WORKERS_TABLE} WHERE storage_id = $1"
))
.bind(storage_id)
.fetch_one(self.db)
.await
.map_err(|e| map_not_found(e, "storage_workers"))?;

Ok(has_sws.0)
}

pub async fn list_by_user_id(&self, user_id: Uuid) -> PentaractResult<Vec<StorageWorker>> {
sqlx::query_as(&format!(
"SELECT * FROM {STORAGE_WORKERS_TABLE} WHERE user_id = $1"
Expand Down
24 changes: 21 additions & 3 deletions pentaract/src/routers/storage_workers.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
use std::sync::Arc;

use axum::{
extract::State, http::StatusCode, middleware, response::IntoResponse, routing::get, Extension,
Json, Router,
extract::{Query, State},
http::StatusCode,
middleware,
response::{IntoResponse, Response},
routing::get,
Extension, Json, Router,
};

use crate::{
common::{
jwt_manager::AuthUser,
routing::{app_state::AppState, middlewares::auth::logged_in_required},
},
schemas::storage_workers::InStorageWorkerSchema,
schemas::storage_workers::{
HasStorageWorkers, InStorageWorkerSchema, StorageWorkersStorageIDQuery,
},
services::storage_workers::StorageWorkersService,
};

Expand All @@ -20,6 +26,7 @@ impl StorageWorkersRouter {
pub fn get_router(state: Arc<AppState>) -> Router {
Router::new()
.route("/", get(Self::list).post(Self::create))
.route("/has_workers", get(Self::has_storages_workers))
.route_layer(middleware::from_fn_with_state(
state.clone(),
logged_in_required,
Expand All @@ -45,4 +52,15 @@ impl StorageWorkersRouter {
let sws = StorageWorkersService::new(&state.db).list(&user).await?;
Ok::<_, (StatusCode, String)>((StatusCode::OK, Json(sws)))
}

pub async fn has_storages_workers(
State(state): State<Arc<AppState>>,
Extension(user): Extension<AuthUser>,
query: Query<StorageWorkersStorageIDQuery>,
) -> Result<Response, (StatusCode, String)> {
let has = StorageWorkersService::new(&state.db)
.has_storage_workers(query.0.storage_id, &user)
.await?;
Ok(Json(HasStorageWorkers { has }).into_response())
}
}
15 changes: 13 additions & 2 deletions pentaract/src/schemas/storage_workers.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Deserialize)]
pub struct InStorageWorkerSchema {
pub name: String,
pub token: String,
pub storage_id: Option<uuid::Uuid>,
pub storage_id: Option<Uuid>,
}

#[derive(Deserialize)]
pub struct StorageWorkersStorageIDQuery {
pub storage_id: Uuid,
}

#[derive(Serialize)]
pub struct HasStorageWorkers {
pub has: bool,
}
31 changes: 27 additions & 4 deletions pentaract/src/services/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,28 @@ use crate::{
access::AccessType,
files::{FSElement, File, InFile},
},
repositories::{access::AccessRepository, files::FilesRepository},
repositories::{
access::AccessRepository, files::FilesRepository, storage_workers::StorageWorkersRepository,
},
schemas::files::{InFileSchema, InFolderSchema},
};

pub struct FilesService<'d> {
repo: FilesRepository<'d>,
storage_workers_repo: StorageWorkersRepository<'d>,
access_repo: AccessRepository<'d>,
tx: ClientSender,
}

impl<'d> FilesService<'d> {
pub fn new(db: &'d PgPool, tx: ClientSender) -> Self {
let repo = FilesRepository::new(db);
let storage_workers_repo = StorageWorkersRepository::new(db);
let access_repo = AccessRepository::new(db);
Self {
repo,
access_repo,
storage_workers_repo,
tx,
}
}
Expand Down Expand Up @@ -82,14 +87,17 @@ impl<'d> FilesService<'d> {
)
.await?;

// 1. path validation
// 1. check whether storage got workers
Self::check_storage_workers(&self, in_schema.storage_id).await?;

// 2. path validation
if !Self::validate_filepath(&in_schema.path) {
return Err(PentaractError::InvalidPath);
}

let in_file = InFile::new(in_schema.path, in_schema.size, in_schema.storage_id);

// 2. saving file to db
// 3. saving file to db
let file = self.repo.create_file(in_file).await?;

self._upload(file, in_schema.file, user).await
Expand All @@ -110,7 +118,10 @@ impl<'d> FilesService<'d> {
)
.await?;

// 1. saving file in db
// 1. check whether storage got workers
Self::check_storage_workers(&self, in_file.storage_id).await?;

// 2. saving file in db
let file = self.repo.create_file_anyway(in_file).await?;

self._upload(file, file_data, user).await
Expand Down Expand Up @@ -157,6 +168,18 @@ impl<'d> FilesService<'d> {
Ok(())
}

async fn check_storage_workers(&self, storage_id: Uuid) -> PentaractResult<()> {
if !self
.storage_workers_repo
.storage_has_any(storage_id)
.await?
{
Err(PentaractError::StorageDoesNotHaveWorkers)
} else {
Ok(())
}
}

pub async fn download(
&self,
path: &str,
Expand Down
25 changes: 21 additions & 4 deletions pentaract/src/services/storage_workers.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
use sqlx::PgPool;
use uuid::Uuid;

use crate::{
common::jwt_manager::AuthUser,
common::{access::check_access, jwt_manager::AuthUser},
errors::{PentaractError, PentaractResult},
models::storage_workers::{InStorageWorker, StorageWorker},
repositories::storage_workers::StorageWorkersRepository,
models::{
access::AccessType,
storage_workers::{InStorageWorker, StorageWorker},
},
repositories::{access::AccessRepository, storage_workers::StorageWorkersRepository},
schemas::storage_workers::InStorageWorkerSchema,
};

pub struct StorageWorkersService<'d> {
repo: StorageWorkersRepository<'d>,
access_repo: AccessRepository<'d>,
}

impl<'d> StorageWorkersService<'d> {
pub fn new(db: &'d PgPool) -> Self {
let repo = StorageWorkersRepository::new(db);
Self { repo }
let access_repo = AccessRepository::new(db);
Self { repo, access_repo }
}

pub async fn create(
Expand Down Expand Up @@ -45,4 +51,15 @@ impl<'d> StorageWorkersService<'d> {
pub async fn list(&self, user: &AuthUser) -> PentaractResult<Vec<StorageWorker>> {
self.repo.list_by_user_id(user.id).await
}

pub async fn has_storage_workers(
&self,
storage_id: Uuid,
user: &AuthUser,
) -> PentaractResult<bool> {
// 0. checking access
check_access(&self.access_repo, user.id, storage_id, &AccessType::R).await?;

self.repo.storage_has_any(storage_id).await
}
}
2 changes: 2 additions & 0 deletions ui/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import StorageWorkerCreateForm from './pages/StorageWorkers/StorageWorkerCreateF
import Files from './pages/Files'
import UploadFileTo from './pages/Files/UploadFileTo'
import Register from './pages/Register'
import NotFound from './pages/404'

const theme = createTheme({
palette: {
Expand Down Expand Up @@ -41,6 +42,7 @@ const App = () => {
path="/storage_workers/register"
component={StorageWorkerCreateForm}
/>
<Route path="*404" component={NotFound} />
</Route>
</Routes>

Expand Down
21 changes: 21 additions & 0 deletions ui/src/pages/404.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Typography from '@suid/material/Typography'
import Box from '@suid/material/Box'

const NotFound = () => {
return (
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
mt: 16,
}}
>
<Typography variant="h1">404</Typography>
<Typography variant="h4">Not found</Typography>
</Box>
)
}

export default NotFound

0 comments on commit c3ab2d9

Please sign in to comment.