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 authored Nov 21, 2023
1 parent 5f29710 commit c837003
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 37 deletions.
12 changes: 2 additions & 10 deletions src/components/my-career/CategoryCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import algoliasearch from 'algoliasearch/lite';
import { AppContext } from '@edx/frontend-platform/react';
import LevelBars from './LevelBars';
import SkillsRecommendationCourses from './SkillsRecommendationCourses';
import { useAlgoliaSearch } from "../../utils/hooks";

const CategoryCard = ({ topCategory }) => {
const { skillsSubcategories } = topCategory;
Expand All @@ -26,16 +27,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
13 changes: 2 additions & 11 deletions src/components/search/Search.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import SearchPathwayCard from '../pathway/SearchPathwayCard';
import { SubsidyRequestsContext } from '../enterprise-subsidy-requests';
import PathwayModal from '../pathway/PathwayModal';
import { useEnterpriseCuration } from './content-highlights/data';
import { useAlgoliaSearch } from "../../utils/hooks";

const Search = () => {
const { pathwayUUID } = useParams();
Expand Down Expand Up @@ -78,17 +79,7 @@ const Search = () => {
}, [openLearnerPathwayModal, pathwayUUID]);

const config = getConfig();
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);

const PAGE_TITLE = `${HEADER_TITLE} - ${enterpriseConfig.name}`;
const shouldDisplayBalanceAlert = hasNoEnterpriseOffersBalance || hasLowEnterpriseOffersBalance;
Expand Down
18 changes: 5 additions & 13 deletions src/components/skills-quiz/SkillsQuizStepper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,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 +49,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 +190,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
32 changes: 29 additions & 3 deletions src/utils/hooks.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
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 +24,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 c837003

Please sign in to comment.