From 95c2670eebdcbe0a4c644ec1fec3cce7a35a2246 Mon Sep 17 00:00:00 2001 From: Jonatan Ziegler Date: Fri, 21 Jun 2024 21:37:36 +0200 Subject: [PATCH] added command function scafholdings --- backend/src/interface/api_command.rs | 14 +++++ .../logic/api_command/command_handler.rs | 8 +++ backend/src/layer/trigger/api/admin.rs | 58 +++++++++++++++---- backend/src/layer/trigger/api/mock.rs | 8 +++ backend/src/layer/trigger/api/server.rs | 14 ++--- 5 files changed, 82 insertions(+), 20 deletions(-) diff --git a/backend/src/interface/api_command.rs b/backend/src/interface/api_command.rs index c5e1bcc8..caa2e6c7 100644 --- a/backend/src/interface/api_command.rs +++ b/backend/src/interface/api_command.rs @@ -49,6 +49,12 @@ pub trait Command: Send + Sync { /// command to add a rating to a meal. async fn set_meal_rating(&self, meal_id: Uuid, rating: u32, client_id: Uuid) -> Result<()>; + + /// Marks an image as verified and deletes all its reports. // todo do we want this? + async fn verify_image(&self, image_id: Uuid) -> Result<()>; + + /// Deletes an image. // todo only hide? + async fn delete_image(&self, image_id: Uuid) -> Result<()>; } #[async_trait] @@ -105,6 +111,14 @@ impl Command for Arc { .set_meal_rating(meal_id, rating, client_id) .await } + + async fn verify_image(&self, image_id: Uuid) -> Result<()> { + Self::as_ref(self).verify_image(image_id).await + } + + async fn delete_image(&self, image_id: Uuid) -> Result<()> { + Self::as_ref(self).delete_image(image_id).await + } } /// Enum describing the possible ways, a command can fail. diff --git a/backend/src/layer/logic/api_command/command_handler.rs b/backend/src/layer/logic/api_command/command_handler.rs index 058711a5..43386cb5 100644 --- a/backend/src/layer/logic/api_command/command_handler.rs +++ b/backend/src/layer/logic/api_command/command_handler.rs @@ -190,6 +190,14 @@ where .await?; Ok(()) } + + async fn delete_image(&self, _image_id: Uuid) -> Result<()> { + todo!() + } + + async fn verify_image(&self, _image_id: Uuid) -> Result<()> { + todo!() + } } #[cfg(test)] diff --git a/backend/src/layer/trigger/api/admin.rs b/backend/src/layer/trigger/api/admin.rs index 809c3fe0..bd1a3557 100644 --- a/backend/src/layer/trigger/api/admin.rs +++ b/backend/src/layer/trigger/api/admin.rs @@ -4,33 +4,71 @@ use std::sync::Arc; use axum::{ debug_handler, - extract::State, + extract::{Path, State}, headers::{authorization::Basic, Authorization}, http::HeaderValue, - middleware::Next, + middleware::{self, Next}, response::IntoResponse, routing::method_routing::get, Router, TypedHeader, }; use hyper::{header::WWW_AUTHENTICATE, HeaderMap, Request, StatusCode}; -use crate::interface::api_command::Command; +use tracing::warn; + +use crate::{ + interface::api_command::{Command, CommandError}, + util::Uuid, +}; #[derive(Clone)] -pub(super) struct AdminKey(pub String); +pub(super) struct AdminKey(String); pub(super) type ArcCommand = Arc; -pub(super) fn admin_router() -> Router { - Router::new().route("/test", get(test_command)) +pub(super) fn admin_router(admin_key: String, command: ArcCommand) -> Router<()> { + let admin_auth = middleware::from_fn_with_state(AdminKey(admin_key), admin_auth_middleware); + // let router = Router::new() + // .route("/version", get(version)) + // .route("/report/delete_image/:image_id", get(delete_image)) + // .route("/report/verify_image/:image_id", get(verify_image)) + // .layer(HandleErrorLayer::new(handle_error)); + + Router::new() + .route("/version", get(version)) + .route("/report/delete_image/:image_id", get(delete_image)) + .route("/report/verify_image/:image_id", get(verify_image)) + .layer(admin_auth) + .with_state(command) +} + +impl IntoResponse for CommandError { + fn into_response(self) -> axum::response::Response { + let error = self.to_string(); + warn!("On Admin API request: {error}"); + (StatusCode::INTERNAL_SERVER_ERROR, error).into_response() + } +} + +#[debug_handler] +async fn version() -> &'static str { + env!("CARGO_PKG_VERSION") +} + +#[debug_handler] +async fn verify_image( + State(command): State, + Path(image_id): Path, +) -> Result<(), CommandError> { + command.verify_image(image_id).await } #[debug_handler] -async fn test_command( +async fn delete_image( State(command): State, - body: Request, -) -> &'static str { - "working" // todo + Path(image_id): Path, +) -> Result<(), CommandError> { + command.delete_image(image_id).await } const ADMIN_USER: &str = "admin"; diff --git a/backend/src/layer/trigger/api/mock.rs b/backend/src/layer/trigger/api/mock.rs index ac0b0e1a..d164b6aa 100644 --- a/backend/src/layer/trigger/api/mock.rs +++ b/backend/src/layer/trigger/api/mock.rs @@ -354,6 +354,14 @@ impl Command for CommandMock { ) -> CommandResult<()> { Ok(()) } + + async fn delete_image(&self, _image_id: Uuid) -> CommandResult<()> { + Ok(()) + } + + async fn verify_image(&self, _image_id: Uuid) -> CommandResult<()> { + Ok(()) + } } pub struct AuthDataMock; diff --git a/backend/src/layer/trigger/api/server.rs b/backend/src/layer/trigger/api/server.rs index 7c508052..553d452e 100644 --- a/backend/src/layer/trigger/api/server.rs +++ b/backend/src/layer/trigger/api/server.rs @@ -147,11 +147,10 @@ impl ApiServer { Duration::from_secs(1), )); - let admin_auth = middleware::from_fn_with_state( - AdminKey(self.server_info.admin_key.clone()), - admin_auth_middleware, + let admin_router = admin_router( + self.server_info.admin_key.clone(), + self.command_copy.clone() as ArcCommand, ); - let admin_router = admin_router(); let app = Router::new() .route( @@ -159,12 +158,7 @@ impl ApiServer { get(graphql_playground).post(graphql_handler.layer(auth)), ) .layer(Extension(self.schema.clone())) - .nest( - "/admin", - admin_router - .layer(admin_auth) - .with_state(self.command_copy.clone() as ArcCommand), - ) + .nest("/admin", admin_router) .nest_service(IMAGE_BASE_PATH, ServeDir::new(&self.server_info.image_dir)) .layer(rate_limit) .layer(DefaultBodyLimit::max(