Skip to content

Commit

Permalink
feat: fetching of a secured Algolia key
Browse files Browse the repository at this point in the history
  • Loading branch information
0x29a committed Dec 15, 2023
1 parent 12b1c2c commit 6c9c804
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 56 deletions.
16 changes: 3 additions & 13 deletions src/components/academies/AcademyDetailPage.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useMemo } from 'react';
import React, { useContext } from 'react';
import {
Container, Chip, Breadcrumb,
Skeleton, Spinner,
Expand All @@ -7,12 +7,12 @@ import {
useParams, Link,
} from 'react-router-dom';
import { AppContext } from '@edx/frontend-platform/react';
import algoliasearch from 'algoliasearch/lite';
import { getConfig } from '@edx/frontend-platform/config';
import { useAcademyMetadata } from './data/hooks';
import CourseCard from './CourseCard';
import NotFoundPage from '../NotFoundPage';
import { ACADEMY_NOT_FOUND_TITLE } from './data/constants';
import { useAlgoliaSearch } from '../../utils/hooks';

const AcademyDetailPage = () => {
const config = getConfig();
Expand All @@ -21,17 +21,7 @@ const AcademyDetailPage = () => {
const [academy, isAcademyAPILoading, academyAPIError] = useAcademyMetadata(academyUUID);
const academyURL = `/${enterpriseConfig.slug}/academy/${academyUUID}`;

// init algolia index
const courseIndex = useMemo(
() => {
const client = algoliasearch(
config.ALGOLIA_APP_ID,
config.ALGOLIA_SEARCH_API_KEY,
);
return client.initIndex(config.ALGOLIA_INDEX_NAME);
},
[config.ALGOLIA_APP_ID, config.ALGOLIA_INDEX_NAME, config.ALGOLIA_SEARCH_API_KEY],
);
const [courseIndex] = useAlgoliaSearch(config, config.ALGOLIA_INDEX_NAME);

if (academyAPIError) {
return (
Expand Down
15 changes: 3 additions & 12 deletions src/components/my-career/CategoryCard.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React, {
useContext, useEffect, useMemo, useState,
useContext, useEffect, useState,
} from 'react';

import PropTypes from 'prop-types';
import { Button, Card, useToggle } from '@edx/paragon';
import { getConfig } from '@edx/frontend-platform/config';
import algoliasearch from 'algoliasearch/lite';
import { AppContext } from '@edx/frontend-platform/react';
import LevelBars from './LevelBars';
import SkillsRecommendationCourses from './SkillsRecommendationCourses';
import { UserSubsidyContext } from '../enterprise-user-subsidy';
import { isDisableCourseSearch } from '../enterprise-user-subsidy/enterprise-offers/data/utils';
import { features } from '../../config';
import { useAlgoliaSearch } from '../../utils/hooks';

const CategoryCard = ({ topCategory }) => {
const { skillsSubcategories } = topCategory;
Expand Down Expand Up @@ -41,16 +41,7 @@ const CategoryCard = ({ topCategory }) => {

const config = getConfig();
const { enterpriseConfig } = useContext(AppContext);
const courseIndex = useMemo(
() => {
const client = algoliasearch(
config.ALGOLIA_APP_ID,
config.ALGOLIA_SEARCH_API_KEY,
);
return client.initIndex(config.ALGOLIA_INDEX_NAME);
},
[config.ALGOLIA_APP_ID, config.ALGOLIA_INDEX_NAME, config.ALGOLIA_SEARCH_API_KEY],
);
const [courseIndex] = useAlgoliaSearch(config, config.ALGOLIA_INDEX_NAME);

const filterRenderableSkills = (skills) => {
const renderableSkills = [];
Expand Down
16 changes: 3 additions & 13 deletions src/components/search/Search.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {
useContext, useMemo, useEffect,
useContext, useEffect,
} from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { Helmet } from 'react-helmet';
Expand All @@ -9,7 +9,6 @@ import { getConfig } from '@edx/frontend-platform/config';
import { SearchHeader, SearchContext } from '@edx/frontend-enterprise-catalog-search';
import { useToggle, Stack } from '@edx/paragon';

import algoliasearch from 'algoliasearch/lite';
import { useDefaultSearchFilters, useSearchCatalogs } from './data/hooks';
import {
NUM_RESULTS_PER_PAGE,
Expand Down Expand Up @@ -41,6 +40,7 @@ import AssignmentsOnlyEmptyState from './AssignmentsOnlyEmptyState';
import { LICENSE_STATUS } from '../enterprise-user-subsidy/data/constants';
import { POLICY_TYPES } from '../enterprise-user-subsidy/enterprise-offers/data/constants';
import AuthenticatedPageContext from '../app/AuthenticatedPageContext';
import { useAlgoliaSearch } from '../../utils/hooks';

const Search = () => {
const config = getConfig();
Expand Down Expand Up @@ -85,17 +85,7 @@ const Search = () => {
const enterpriseUUID = enterpriseConfig.uuid;
const { enterpriseCuration: { canOnlyViewHighlightSets } } = useEnterpriseCuration(enterpriseUUID);

const courseIndex = useMemo(
() => {
const client = algoliasearch(
config.ALGOLIA_APP_ID,
config.ALGOLIA_SEARCH_API_KEY,
);
const cIndex = client.initIndex(config.ALGOLIA_INDEX_NAME);
return cIndex;
},
[config.ALGOLIA_APP_ID, config.ALGOLIA_INDEX_NAME, config.ALGOLIA_SEARCH_API_KEY],
);
const [courseIndex] = useAlgoliaSearch(config, config.ALGOLIA_INDEX_NAME);

// If a pathwayUUID exists, open the pathway modal.
useEffect(() => {
Expand Down
21 changes: 6 additions & 15 deletions src/components/skills-quiz/SkillsQuizStepper.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/* eslint-disable object-curly-newline */
import React, { useEffect, useState, useContext, useMemo } from 'react';
import React, { useEffect, useState, useContext } from 'react';
import {
Button, Stepper, ModalDialog, Container, Form, Stack,
} from '@edx/paragon';
import algoliasearch from 'algoliasearch/lite';
import { Configure, InstantSearch } from 'react-instantsearch-dom';
import { getConfig } from '@edx/frontend-platform/config';
import { SearchContext } from '@edx/frontend-enterprise-catalog-search';
Expand Down Expand Up @@ -38,6 +37,7 @@ import {
import { SkillsContext } from './SkillsContextProvider';
import { SET_KEY_VALUE } from './data/constants';
import { checkValidGoalAndJobSelected } from '../utils/skills-quiz';
import { useAlgoliaSearch } from '../../utils/hooks';
import TopSkillsOverview from './TopSkillsOverview';
import SkillsQuizHeader from './SkillsQuizHeader';

Expand All @@ -48,18 +48,9 @@ import { fetchCourseEnrollments } from './data/service';
const SkillsQuizStepper = () => {
const config = getConfig();
const { userId } = getAuthenticatedUser();
const [searchClient, courseIndex, jobIndex] = useMemo(
() => {
const client = algoliasearch(
config.ALGOLIA_APP_ID,
config.ALGOLIA_SEARCH_API_KEY,
);
const cIndex = client.initIndex(config.ALGOLIA_INDEX_NAME);
const jIndex = client.initIndex(config.ALGOLIA_INDEX_NAME_JOBS);
return [client, cIndex, jIndex];
},
[config.ALGOLIA_APP_ID, config.ALGOLIA_INDEX_NAME, config.ALGOLIA_INDEX_NAME_JOBS, config.ALGOLIA_SEARCH_API_KEY],
);
const [courseIndex] = useAlgoliaSearch(config, config.ALGOLIA_INDEX_NAME);
const [jobSearchClient, jobIndex] = useAlgoliaSearch(config, config.ALGOLIA_INDEX_NAME_JOBS);

const [currentStep, setCurrentStep] = useState(STEP1);
const [isStudentChecked, setIsStudentChecked] = useState(false);
const handleIsStudentCheckedChange = e => setIsStudentChecked(e.target.checked);
Expand Down Expand Up @@ -198,7 +189,7 @@ const SkillsQuizStepper = () => {
<div>
<InstantSearch
indexName={config.ALGOLIA_INDEX_NAME_JOBS}
searchClient={searchClient}
searchClient={jobSearchClient}
>
<Configure
facetingAfterDistinct
Expand Down
2 changes: 2 additions & 0 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ initialize({
LICENSE_MANAGER_URL: process.env.LICENSE_MANAGER_URL || null,
ALGOLIA_APP_ID: process.env.ALGOLIA_APP_ID || null,
ALGOLIA_SEARCH_API_KEY: process.env.ALGOLIA_SEARCH_API_KEY || null,
ALGOLIA_SECURED_KEY_ENDPOINT: process.env.ALGOLIA_SECURED_KEY_ENDPOINT
|| `${process.env.LMS_BASE_URL}/enterprise/api/v1/enterprise-customer/algolia_key/`,
ALGOLIA_INDEX_NAME: process.env.ALGOLIA_INDEX_NAME || null,
ALGOLIA_INDEX_NAME_JOBS: process.env.ALGOLIA_INDEX_NAME_JOBS || null,
INTEGRATION_WARNING_DISMISSED_COOKIE_NAME: process.env.INTEGRATION_WARNING_DISMISSED_COOKIE_NAME || null,
Expand Down
17 changes: 17 additions & 0 deletions src/utils/common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Cookies from 'universal-cookie';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { getConfig } from '@edx/frontend-platform/config';
import { logError } from '@edx/frontend-platform/logging';
import dayjs from './dayjs';

export const isCourseEnded = endDate => dayjs(endDate) < dayjs();
Expand Down Expand Up @@ -66,6 +67,22 @@ export const loginRefresh = async () => {
}
};

export const fetchAlgoliaSecuredApiKey = async () => {
const config = getConfig();
const httpClient = getAuthenticatedHttpClient();

try {
const response = await httpClient.get(config.ALGOLIA_SECURED_KEY_ENDPOINT);
if (response && response.data) {
return response.data.key;
}
throw new Error('Response does not contain data');
} catch (error) {
logError(error);
return null;
}
};

export const fixedEncodeURIComponent = (str) => encodeURIComponent(str).replace(/[!()*]/g, (c) => `%${ c.charCodeAt(0).toString(16)}`);

export const formatStringAsNumber = (str, radix = 10) => {
Expand Down
37 changes: 34 additions & 3 deletions src/utils/hooks.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React, { useCallback, useMemo } from 'react';
import React, {
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import algoliasearch from 'algoliasearch';

import { fetchAlgoliaSecuredApiKey } from './common';

export const useRenderContactHelpText = (enterpriseConfig) => {
const renderContactHelpText = useCallback(
(LinkComponent = 'a') => {
Expand All @@ -22,17 +29,41 @@ export const useRenderContactHelpText = (enterpriseConfig) => {
return renderContactHelpText;
};

let cachedApiKey = null;

export const useAlgoliaSearchApiKey = (config) => {
// If the search API key is not provided in the config,
// fetch it from `ALGOLIA_SECURED_KEY_ENDPOINT`.

const [searchApiKey, setSearchApiKey] = useState(cachedApiKey || config.ALGOLIA_SEARCH_API_KEY);

useEffect(() => {
const fetchApiKey = async () => {
const key = await fetchAlgoliaSecuredApiKey();
cachedApiKey = key;
setSearchApiKey(key);
};

if (!searchApiKey) {
fetchApiKey();
}
}, [searchApiKey]);

return searchApiKey;
};

export const useAlgoliaSearch = (config, indexName) => {
const algoliaSearchApiKey = useAlgoliaSearchApiKey(config);
const [searchClient, searchIndex] = useMemo(
() => {
const client = algoliasearch(
config.ALGOLIA_APP_ID,
config.ALGOLIA_SEARCH_API_KEY,
algoliaSearchApiKey,
);
const index = client.initIndex(indexName || config.ALGOLIA_INDEX_NAME);
return [client, index];
},
[config.ALGOLIA_APP_ID, config.ALGOLIA_INDEX_NAME, config.ALGOLIA_SEARCH_API_KEY, indexName],
[config.ALGOLIA_APP_ID, config.ALGOLIA_INDEX_NAME, algoliaSearchApiKey, indexName],
);
return [searchClient, searchIndex];
};

0 comments on commit 6c9c804

Please sign in to comment.