haste_server/auth_n/oidc/middleware/
project_exists.rs1use axum::{
2 extract::{Request, State},
3 middleware::Next,
4 response::Response,
5};
6
7use axum_extra::extract::Cached;
8use haste_fhir_operation_error::OperationOutcomeError;
9use haste_fhir_search::SearchEngine;
10use haste_fhir_terminology::FHIRTerminology;
11use haste_repository::{Repository, admin::TenantModelAdmin, types::project::CreateProject};
12use std::sync::Arc;
13
14use crate::{
15 extract::path_tenant::{ProjectIdentifier, TenantIdentifier},
16 services::ServerState,
17};
18
19pub async fn project_exists<
20 Repo: Repository + Send + Sync,
21 Search: SearchEngine + Send + Sync,
22 Terminology: FHIRTerminology + Send + Sync,
23>(
24 State(state): State<Arc<ServerState<Repo, Search, Terminology>>>,
25 Cached(TenantIdentifier { tenant }): Cached<TenantIdentifier>,
26 Cached(ProjectIdentifier { project }): Cached<ProjectIdentifier>,
27 request: Request,
28 next: Next,
29) -> Result<Response, OperationOutcomeError> {
30 TenantModelAdmin::<CreateProject, _, _, _, _>::read(
32 &*state.repo,
33 &tenant,
34 &project.as_ref().to_string(),
35 )
36 .await?
37 .ok_or_else(|| {
38 OperationOutcomeError::fatal(
39 haste_fhir_model::r4::generated::terminology::IssueType::not_found(),
40 format!(
41 "Project '{}' not found for tenant '{}'",
42 project.as_ref(),
43 tenant.as_ref()
44 ),
45 )
46 })?;
47
48 Ok(next.run(request).await)
49}