Skip to main content

haste_server/auth_n/oidc/middleware/
project_exists.rs

1use 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    // If not found automatically will error.
31    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}