diff --git a/src/js/components/Beacon/BeaconQueryUi.tsx b/src/js/components/Beacon/BeaconQueryUi.tsx index 282e09cc..580593e5 100644 --- a/src/js/components/Beacon/BeaconQueryUi.tsx +++ b/src/js/components/Beacon/BeaconQueryUi.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState, ReactNode } from 'react'; -import { useAppSelector, useAppDispatch, useTranslationDefault, useBeaconWithAuthIfAllowed } from '@/hooks'; +import { useAppSelector, useAppDispatch, useTranslationDefault, useQueryWithAuthIfAllowed } from '@/hooks'; import { Button, Card, Col, Form, Row, Space, Tooltip, Typography } from 'antd'; import { InfoCircleOutlined } from '@ant-design/icons'; import { useIsAuthenticated } from 'bento-auth-js'; @@ -91,7 +91,7 @@ const BeaconQueryUi = () => { }, [isFetchingBeaconConfig, isAuthenticated]); // Disables max query param if user is authenticated and authorized - useBeaconWithAuthIfAllowed(); + useQueryWithAuthIfAllowed(); // beacon request handling diff --git a/src/js/components/Search/MakeQueryOption.tsx b/src/js/components/Search/MakeQueryOption.tsx index 63d46b97..f6fe4e24 100644 --- a/src/js/components/Search/MakeQueryOption.tsx +++ b/src/js/components/Search/MakeQueryOption.tsx @@ -29,6 +29,11 @@ const MakeQueryOption = ({ queryField }: MakeQueryOptionProps) => { dispatch(makeGetKatsuPublic()); }; + // TODO: allow disabling max query parameters for authenticated and authorized users when Katsu has AuthZ + // useQueryWithAuthIfAllowed() + // const maxQueryParametersRequired = useAppSelector((state) => state.config.maxQueryParametersRequired); + // const hasMaxFilters = maxQueryParametersRequired && queryParamCount >= maxQueryParameters; + // const disabled = isChecked ? false : hasMaxFilters; const disabled = isChecked ? false : queryParamCount >= maxQueryParameters; return ( diff --git a/src/js/components/Search/Search.tsx b/src/js/components/Search/Search.tsx index 1ab07e58..bd4c3dac 100644 --- a/src/js/components/Search/Search.tsx +++ b/src/js/components/Search/Search.tsx @@ -32,6 +32,10 @@ const RoutedSearch: React.FC = () => { attemptedFetch, } = useAppSelector((state) => state.query); + // TODO: allow disabling max query parameters for authenticated and authorized users when Katsu has AuthZ + // const maxQueryParametersRequired = useAppSelector((state) => state.config.maxQueryParametersRequired); + // const allowedQueyParamsCount = maxQueryParametersRequired ? maxQueryParameters : queryParamCount; + const searchFields = useMemo( () => searchSections.flatMap(({ fields }) => fields.map((field) => ({ id: field.id, options: field.options }))), [searchSections] @@ -45,6 +49,7 @@ const RoutedSearch: React.FC = () => { const queryParamArray = Array.from(query.entries()).map(([key, value]) => ({ key, value })); + // TODO: to disable max query parameters, slice with allowedQueyParamsCount instead const validQueryParamArray = queryParamArray .filter(({ key, value }) => validateQueryParam(key, value)) .slice(0, maxQueryParameters); diff --git a/src/js/constants/configConstants.ts b/src/js/constants/configConstants.ts index 6a37f09b..2d3cb501 100644 --- a/src/js/constants/configConstants.ts +++ b/src/js/constants/configConstants.ts @@ -3,6 +3,7 @@ import { PORTAL_URL } from '@/config'; export const MAX_CHARTS = 3; export const katsuPublicOverviewUrl = `${PORTAL_URL}/api/metadata/api/public_overview`; +export const katsuPublicRulesUrl = `${PORTAL_URL}/api/metadata/api/public_rules`; export const searchFieldsUrl = `${PORTAL_URL}/api/metadata/api/public_search_fields`; export const katsuUrl = `${PORTAL_URL}/api/metadata/api/public`; export const provenanceUrl = `${PORTAL_URL}/api/metadata/api/public_dataset`; diff --git a/src/js/features/config/config.store.ts b/src/js/features/config/config.store.ts index bee1afbb..a66f4943 100644 --- a/src/js/features/config/config.store.ts +++ b/src/js/features/config/config.store.ts @@ -1,17 +1,18 @@ import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; import axios from 'axios'; -import { katsuPublicOverviewUrl } from '@/constants/configConstants'; +import { katsuPublicRulesUrl } from '@/constants/configConstants'; import { printAPIError } from '@/utils/error.util'; import { ServiceInfoStore, ServicesResponse } from '@/types/services'; import { RootState } from '@/store'; import { PUBLIC_URL } from '@/config'; -import { KatsuPublicOverviewResponse } from '@/types/configResponse'; +import { DiscoveryRule } from '@/types/configResponse'; -export const makeGetConfigRequest = createAsyncThunk( +export const makeGetConfigRequest = createAsyncThunk( 'config/getConfigData', (_, { rejectWithValue }) => + // TODO: should be project/dataset scoped with url params axios - .get(katsuPublicOverviewUrl) + .get(katsuPublicRulesUrl) .then((res) => res.data) .catch(printAPIError(rejectWithValue)) ); @@ -57,13 +58,10 @@ const configStore = createSlice({ builder.addCase(makeGetConfigRequest.pending, (state) => { state.isFetchingConfig = true; }); - builder.addCase( - makeGetConfigRequest.fulfilled, - (state, { payload }: PayloadAction) => { - state.maxQueryParameters = payload.max_query_parameters; - state.isFetchingConfig = false; - } - ); + builder.addCase(makeGetConfigRequest.fulfilled, (state, { payload }: PayloadAction) => { + state.maxQueryParameters = payload.max_query_parameters; + state.isFetchingConfig = false; + }); builder.addCase(makeGetConfigRequest.rejected, (state) => { state.isFetchingConfig = false; }); diff --git a/src/js/hooks.ts b/src/js/hooks.ts index 761bf64b..1eba40be 100644 --- a/src/js/hooks.ts +++ b/src/js/hooks.ts @@ -41,12 +41,12 @@ export const useHasResourcePermissionWrapper = (resource: Resource, permission: }; }; -export const useBeaconWithAuthIfAllowed = () => { +export const useQueryWithAuthIfAllowed = () => { const dispatch = useAppDispatch(); const { hasPermission } = useHasResourcePermissionWrapper(RESOURCE_EVERYTHING, queryData); useEffect(() => { if (hasPermission) { - console.log('Beacon: user authorized for no max query parameters.'); + console.log('Beacon | Search: user authorized for no max query parameters.'); dispatch(setMaxQueryParametersRequired(false)); } }, [dispatch, hasPermission]); diff --git a/src/js/index.tsx b/src/js/index.tsx index 62d7d0d7..21a556cc 100644 --- a/src/js/index.tsx +++ b/src/js/index.tsx @@ -31,7 +31,7 @@ import { BentoAuthContextProvider, nop, } from 'bento-auth-js'; -import { useBeaconWithAuthIfAllowed } from '@/hooks'; +import { useQueryWithAuthIfAllowed } from '@/hooks'; // Store and configuration imports import { store } from './store'; @@ -97,7 +97,7 @@ const App = () => { useSessionWorkerTokenRefresh(sessionWorker, createSessionWorker, nop); - useBeaconWithAuthIfAllowed(); + useQueryWithAuthIfAllowed(); return ( diff --git a/src/js/types/configResponse.ts b/src/js/types/configResponse.ts index 0f1672ab..2937c01c 100644 --- a/src/js/types/configResponse.ts +++ b/src/js/types/configResponse.ts @@ -1,7 +1,10 @@ export interface KatsuPublicOverviewResponse { - count_threshold: number; counts: object; fields: object; layout: []; +} + +export interface DiscoveryRule { max_query_parameters: number; + count_threshold: number; }