@@ -29,10 +29,13 @@ import { ParsedUrlQuery } from "querystring";
2929import { EntityGuard } from "../../app/components/Detail/components/EntityGuard/entityGuard" ;
3030import { readFile } from "../../app/utils/tsvParser" ;
3131import { useRouter } from "next/router" ;
32+ import { useConfig } from "@databiosphere/findable-ui/lib/hooks/useConfig" ;
3233import { useFeatureFlag } from "@databiosphere/findable-ui/lib/hooks/useFeatureFlag/useFeatureFlag" ;
3334import { FEATURES } from "../../app/shared/entities" ;
3435import NextError from "next/error" ;
3536import { ROUTES } from "../../site-config/anvil-cmg/dev/export/routes" ;
37+ import { getConsentGroup } from "../../app/apis/azul/anvil-cmg/common/transformers" ;
38+ import { DatasetsResponse } from "../../app/apis/azul/anvil-cmg/common/responses" ;
3639
3740const setOfProcessedIds = new Set < string > ( ) ;
3841
@@ -65,15 +68,21 @@ export interface EntityDetailPageProps extends AzulEntityStaticResponse {
6568 * @returns Entity detail view component.
6669 */
6770const EntityDetailPage = ( props : EntityDetailPageProps ) : JSX . Element => {
71+ const { config : siteConfig } = useConfig ( ) ;
72+ const isAnVIL = siteConfig . appTitle ?. includes ( "AnVIL" ) ;
6873 const isNCPIExportEnabled = useFeatureFlag ( FEATURES . NCPI_EXPORT ) ;
6974 const isCurlDownloadEnabled = useFeatureFlag ( FEATURES . CURL_DOWNLOAD ) ;
7075 const { query } = useRouter ( ) ;
7176 if ( ! props . entityListType ) return < > </ > ;
7277 if ( props . override ) return < EntityGuard override = { props . override } /> ;
7378 if ( ! isNCPIExportEnabled && isNCPIExportRoute ( query ) )
7479 return < NextError statusCode = { 404 } /> ;
75- if ( ! isCurlDownloadEnabled && isCurlDownloadRoute ( query ) )
76- return < NextError statusCode = { 404 } /> ;
80+ // Curl download requires feature flag AND NRES consent group (AnVIL only)
81+ if ( isAnVIL && isCurlDownloadRoute ( query ) ) {
82+ if ( ! isCurlDownloadEnabled || ! isNRESDataset ( props . data ) ) {
83+ return < NextError statusCode = { 404 } /> ;
84+ }
85+ }
7786 if ( isChooseExportView ( query ) ) return < EntityExportView { ...props } /> ;
7887 if ( isExportMethodView ( query ) ) return < EntityExportMethodView { ...props } /> ;
7988 return < EntityDetailView { ...props } /> ;
@@ -119,6 +128,17 @@ function isCurlDownloadRoute(query: ParsedUrlQuery): boolean {
119128 return lastParam === CURL_DOWNLOAD_PATH . replace ( "/export/" , "" ) ;
120129}
121130
131+ /**
132+ * Returns true if the dataset has NRES consent group.
133+ * @param data - Entity response data.
134+ * @returns True if the dataset has NRES consent group.
135+ */
136+ function isNRESDataset ( data : AzulEntityStaticResponse | undefined ) : boolean {
137+ if ( ! data ) return false ;
138+ const consentGroups = getConsentGroup ( data as DatasetsResponse ) ;
139+ return consentGroups . includes ( "NRES" ) ;
140+ }
141+
122142/**
123143 * Returns true if the entity is a special case e.g. an "override".
124144 * @param override - Override.
@@ -256,6 +276,7 @@ export const getStaticProps: GetStaticProps<AzulEntityStaticResponse> = async ({
256276 const slug = ( params as PageUrl ) . params ;
257277 const entityConfig = getEntityConfig ( entities , entityListType ) ;
258278 const entityTab = getSlugPath ( slug , PARAMS_INDEX_TAB ) ;
279+ const entityExportMethod = getSlugPath ( slug , PARAMS_INDEX_EXPORT_METHOD ) ;
259280 const entityId = getSlugPath ( slug , PARAMS_INDEX_UUID ) ;
260281
261282 if ( ! entityConfig || ! entityId ) return { notFound : true } ;
@@ -268,7 +289,13 @@ export const getStaticProps: GetStaticProps<AzulEntityStaticResponse> = async ({
268289 if ( props . override ) return { props } ;
269290
270291 // Process entity props.
271- await processEntityProps ( entityConfig , entityTab , entityId , props ) ;
292+ await processEntityProps (
293+ entityConfig ,
294+ entityTab ,
295+ entityExportMethod ,
296+ entityId ,
297+ props
298+ ) ;
272299
273300 return {
274301 props,
@@ -472,12 +499,14 @@ function processEntityPaths(
472499 * Processes the entity props for the given entity page.
473500 * @param entityConfig - Entity config.
474501 * @param entityTab - Entity tab.
502+ * @param entityExportMethod - Entity export method.
475503 * @param entityId - Entity ID.
476504 * @param props - Entity detail page props.
477505 */
478506async function processEntityProps (
479507 entityConfig : EntityConfig ,
480508 entityTab = "" ,
509+ entityExportMethod = "" ,
481510 entityId : string ,
482511 props : EntityDetailPageProps
483512) : Promise < void > {
@@ -487,8 +516,16 @@ async function processEntityProps(
487516 } = entityConfig ;
488517 // Early exit; return if the entity is not to be statically loaded.
489518 if ( ! staticLoad ) return ;
490- // When the entity detail is to be fetched from API, we only do so for the first tab.
491- if ( exploreMode === EXPLORE_MODE . SS_FETCH_SS_FILTERING && entityTab ) return ;
519+ // When the entity detail is to be fetched from API, we only do so for the first tab,
520+ // unless it's the curl download route which needs data for NRES check.
521+ const isCurlDownload =
522+ entityExportMethod === CURL_DOWNLOAD_PATH . replace ( "/export/" , "" ) ;
523+ if (
524+ exploreMode === EXPLORE_MODE . SS_FETCH_SS_FILTERING &&
525+ entityTab &&
526+ ! isCurlDownload
527+ )
528+ return ;
492529 if ( exploreMode === EXPLORE_MODE . CS_FETCH_CS_FILTERING ) {
493530 // Seed database.
494531 await seedDatabase ( entityConfig . route , entityConfig ) ;
0 commit comments