Skip to content

Commit

Permalink
fix(upload layer cors): upload layer now works with new CORS implemen…
Browse files Browse the repository at this point in the history
…tation [2024-12-27]
  • Loading branch information
CHRISCARLON committed Dec 27, 2024
1 parent 2b3257c commit 7e9588f
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 22 deletions.
23 changes: 16 additions & 7 deletions gridwalk-backend/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{app_state::AppState, core::Session};
use axum::{
body::Body,
extract::{FromRef, State},
http::{Request, StatusCode},
http::{Method, Request, StatusCode},
middleware::Next,
response::{IntoResponse, Response},
};
Expand All @@ -18,19 +18,28 @@ pub struct AuthUser {

pub async fn auth_middleware(
State(state): State<Arc<AppState>>,
TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
mut request: Request<Body>,
auth: Option<TypedHeader<Authorization<Bearer>>>,
request: Request<Body>,
next: Next,
) -> Result<Response, Response> {
// Allow OPTIONS requests to pass through without auth
if request.method() == Method::OPTIONS {
return Ok(next.run(request).await);
}

// Require auth for non-OPTIONS requests
let TypedHeader(auth) = auth.ok_or_else(|| {
(StatusCode::UNAUTHORIZED, "Missing authorization header").into_response()
})?;

let token = auth.token();
match Session::from_id(&state.app_data, token).await {
Ok(session) => {
if let Some(user_id) = session.user_id {
match User::from_id(&state.app_data, &user_id).await {
Ok(user) => {
request
.extensions_mut()
.insert(AuthUser { user: Some(user) });
let mut request = request;
request.extensions_mut().insert(AuthUser { user: Some(user) });
Ok(next.run(request).await)
}
Err(_) => {
Expand All @@ -43,4 +52,4 @@ pub async fn auth_middleware(
}
Err(_) => Err((StatusCode::UNAUTHORIZED, "Invalid token").into_response()),
}
}
}
21 changes: 11 additions & 10 deletions gridwalk-backend/src/routes/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ pub async fn upload_layer(
headers: HeaderMap,
mut multipart: Multipart,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {

// Ensure that the user has auth to upload layer
let user = auth_user.user.as_ref().ok_or_else(|| {
let error = json!({
"error": "Unauthorized request",
"details": null
});
(StatusCode::UNAUTHORIZED, Json(error))
})?;

// Extract chunk information sent from frontend
// Total chunks to be processed
let total_chunks = headers
Expand Down Expand Up @@ -54,15 +64,6 @@ pub async fn upload_layer(
(StatusCode::BAD_REQUEST, Json(error))
})?;

// Ensure that the user has auth to upload layer
let user = auth_user.user.as_ref().ok_or_else(|| {
let error = json!({
"error": "Unauthorized request",
"details": null
});
(StatusCode::UNAUTHORIZED, Json(error))
})?;

// Create layer info (layer name and workspace id holder) + holder for final file path
let mut layer_info: Option<CreateLayer> = None;
let mut file_path = None;
Expand Down Expand Up @@ -306,7 +307,7 @@ async fn process_layer(
return Err((StatusCode::FORBIDDEN, Json(error)));
}

// Check permissions - WE NEED TO RENAME THIS TO SOMETHING OTHER THAN CREATE
// TODO Check permissions - WE NEED TO RENAME THIS TO SOMETHING OTHER THAN CREATE
layer
.create(&state.app_data, user, &workspace)
.await
Expand Down
34 changes: 31 additions & 3 deletions gridwalk-backend/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use axum::{
routing::{delete, get, post},
Router,
};
use http::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE};
use http::{header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE}, HeaderName};
use http::Method;
use std::sync::Arc;
use tower_cookies::CookieManagerLayer;
Expand All @@ -33,7 +33,23 @@ fn create_dynamic_cors() -> CorsLayer {
CorsLayer::new()
.allow_credentials(true)
.allow_methods([Method::GET, Method::OPTIONS, Method::POST])
.allow_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE])
.allow_headers([
AUTHORIZATION,
ACCEPT,
CONTENT_TYPE,
HeaderName::from_static("x-file-type"),
HeaderName::from_static("x-workspace-id"),
HeaderName::from_static("x-chunk-number"),
HeaderName::from_static("x-total-chunks"),
HeaderName::from_static("x-file-size"),
])
.expose_headers([
HeaderName::from_static("x-file-type"),
HeaderName::from_static("x-workspace-id"),
HeaderName::from_static("x-chunk-number"),
HeaderName::from_static("x-total-chunks"),
HeaderName::from_static("x-file-size")
])
.allow_origin(origins)
}

Expand All @@ -45,6 +61,18 @@ pub fn create_app(app_state: AppState) -> Router {

let shared_state = Arc::new(app_state);


let upload_router = Router::new()
.route("/upload_layer", post(upload_layer))
.layer(DefaultBodyLimit::disable())
.layer(RequestBodyLimitLayer::new(100 * 1024 * 1024))
.layer(create_dynamic_cors())
.layer(middleware::from_fn_with_state(
shared_state.clone(),
auth_middleware,
))
.with_state(shared_state.clone());

let main_router = Router::new()
.route("/projects", get(get_projects))
.route("/projects", delete(delete_project))
Expand Down Expand Up @@ -72,7 +100,6 @@ pub fn create_app(app_state: AppState) -> Router {
get(list_sources),
)
.route("/create_project", post(create_project))
.route("/upload_layer", post(upload_layer))
.layer(DefaultBodyLimit::disable())
.layer(RequestBodyLimitLayer::new(100 * 1024 * 1024))
.layer(middleware::from_fn_with_state(
Expand Down Expand Up @@ -100,6 +127,7 @@ pub fn create_app(app_state: AppState) -> Router {
// Merge all routers and apply global middleware
Router::new()
.merge(main_router)
.merge(upload_router)
.nest(
"/workspaces/:workspace_id/connections/:connection_id/sources/:source_name/tiles",
tiles_router,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@ export async function getUploadHeaders() {

return {
Authorization: `Bearer ${sid.value}`,
Accept: "application/json",
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,23 @@ export const useFileUploader = () => {

// Headers matching backend expectations
const headers = {
...baseHeaders,
Authorization: baseHeaders.Authorization,
"X-File-Type": extension,
"X-Workspace-Id": currentWorkspaceId,
"X-Chunk-Number": currentChunk.toString(),
"X-Total-Chunks": totalChunks.toString(),
"X-File-Size": file.size.toString(),
};

console.log(headers);

const response = await fetch(
`${process.env.NEXT_PUBLIC_GRIDWALK_API}/upload_layer`,
{
method: "POST",
headers,
body: formData,
credentials: "include",
}
);

Expand Down

0 comments on commit 7e9588f

Please sign in to comment.