diff --git a/phono-server/src/routes/relations_single/update_field_ordinality_handler.rs b/phono-server/src/routes/relations_single/update_field_ordinality_handler.rs index 000c251..b41ba54 100644 --- a/phono-server/src/routes/relations_single/update_field_ordinality_handler.rs +++ b/phono-server/src/routes/relations_single/update_field_ordinality_handler.rs @@ -1,5 +1,12 @@ -use axum::{debug_handler, extract::Path, response::Response}; -use phono_models::field::Field; +use axum::{ + debug_handler, + extract::{Path, State}, + response::Response, +}; +use phono_models::{ + accessors::{Accessor as _, Actor, portal::PortalAccessor}, + field::Field, +}; use serde::Deserialize; use sqlx::postgres::types::Oid; use uuid::Uuid; @@ -11,6 +18,7 @@ use crate::{ extractors::ValidatedForm, navigator::{Navigator, NavigatorPage}, user::CurrentUser, + workspace_pooler::{RoleAssignment, WorkspacePooler}, }; #[derive(Debug, Deserialize)] @@ -36,8 +44,9 @@ pub(super) struct FormBody { /// [`PathParams`]. #[debug_handler(state = crate::app::App)] pub(super) async fn post( + State(mut pooler): State, AppDbConn(mut app_db): AppDbConn, - CurrentUser(_user): CurrentUser, + CurrentUser(user): CurrentUser, navigator: Navigator, Path(PathParams { portal_id, @@ -51,11 +60,23 @@ pub(super) async fn post( ) -> Result { // FIXME CSRF - // FIXME ensure workspace corresponds to rel/portal, and that user has - // permission to access/alter both as needed. + let mut workspace_client = pooler + .acquire_for(workspace_id, RoleAssignment::User(user.id)) + .await?; + + let portal = PortalAccessor::new() + .id(portal_id) + .as_actor(Actor::User(user.id)) + .verify_workspace_id(workspace_id) + .verify_rel_oid(Oid(rel_oid)) + .verify_rel_ownership() + .using_app_db(&mut app_db) + .using_workspace_client(&mut workspace_client) + .fetch_one() + .await?; // Ensure field exists and belongs to portal. - Field::belonging_to_portal(portal_id) + Field::belonging_to_portal(portal.id) .with_id(field_id) .fetch_one(&mut app_db) .await?; @@ -67,11 +88,12 @@ pub(super) async fn post( .execute(&mut app_db) .await?; + // TODO: Redirect with subfilter query intact. Ok(navigator .portal_page() .workspace_id(workspace_id) .rel_oid(Oid(rel_oid)) - .portal_id(portal_id) + .portal_id(portal.id) .build()? .redirect_to()) }