saleor-apps-redis_apl/apps/search/src/pages/api/webhooks-status.ts
Lukasz Ostrowski 1e3c08c029
Algolia fields filtering (#946)
* wip

* crud for algolia fields settings

* add ui form fields confiugraion

* adjust app to new config

* filter mapping with fields

* fix lang

* fix lang
2023-09-01 17:01:41 +02:00

137 lines
4.4 KiB
TypeScript

import { createProtectedHandler, NextProtectedApiHandler } from "@saleor/app-sdk/handlers/next";
import { saleorApp } from "../../../saleor-app";
import { FetchOwnWebhooksDocument, OwnWebhookFragment } from "../../../generated/graphql";
import { AlgoliaSearchProvider } from "../../lib/algolia/algoliaSearchProvider";
import { createSettingsManager } from "../../lib/metadata";
import {
IWebhookActivityTogglerService,
WebhookActivityTogglerService,
} from "../../domain/WebhookActivityToggler.service";
import { createLogger } from "../../lib/logger";
import { SettingsManager } from "@saleor/app-sdk/settings-manager";
import { SearchProvider } from "../../lib/searchProvider";
import { createGraphQLClient } from "@saleor/apps-shared";
import { Client } from "urql";
import { isWebhookUpdateNeeded } from "../../lib/algolia/is-webhook-update-needed";
const logger = createLogger({
service: "webhooksStatusHandler",
});
/**
* Simple dependency injection - factory injects all services, in tests everything can be configured without mocks
*/
type FactoryProps = {
settingsManagerFactory: (
client: Pick<Client, "query" | "mutation">,
appId: string,
) => SettingsManager;
webhookActivityTogglerFactory: (
appId: string,
client: Pick<Client, "query" | "mutation">,
) => IWebhookActivityTogglerService;
algoliaSearchProviderFactory: (appId: string, apiKey: string) => Pick<SearchProvider, "ping">;
graphqlClientFactory: (saleorApiUrl: string, token: string) => Pick<Client, "query" | "mutation">;
};
export type WebhooksStatusResponse = {
webhooks: OwnWebhookFragment[];
isUpdateNeeded: boolean;
};
export const webhooksStatusHandlerFactory =
({
settingsManagerFactory,
webhookActivityTogglerFactory,
algoliaSearchProviderFactory,
graphqlClientFactory,
}: FactoryProps): NextProtectedApiHandler<WebhooksStatusResponse> =>
async (req, res, { authData }) => {
/**
* Initialize services
*/
const client = graphqlClientFactory(authData.saleorApiUrl, authData.token);
const webhooksToggler = webhookActivityTogglerFactory(authData.appId, client);
const settingsManager = settingsManagerFactory(client, authData.appId);
const domain = new URL(authData.saleorApiUrl).host;
const [secretKey, appId] = await Promise.all([
settingsManager.get("secretKey", domain),
settingsManager.get("appId", domain),
]);
const settings = { secretKey, appId };
logger.debug(settings, "fetched settings");
/**
* If settings are incomplete, disable webhooks
*
* TODO Extract config operations to domain/
*/
if (!settings.appId || !settings.secretKey) {
logger.debug("Settings not set, will disable webhooks");
await webhooksToggler.disableOwnWebhooks();
} else {
/**
* Otherwise, if settings are set, check in Algolia if tokens are valid
*/
const algoliaService = algoliaSearchProviderFactory(settings.appId, settings.secretKey);
try {
logger.debug("Settings set, will ping Algolia");
await algoliaService.ping();
} catch (e) {
logger.debug("Algolia ping failed, will disable webhooks");
/**
* If credentials are invalid, also disable webhooks
*/
await webhooksToggler.disableOwnWebhooks();
}
}
try {
logger.debug("Settings and Algolia are correct, will fetch Webhooks from Saleor");
const webhooks = await client
.query(FetchOwnWebhooksDocument, { id: authData.appId })
.toPromise()
.then((r) => r.data?.app?.webhooks);
if (!webhooks) {
return res.status(500).end();
}
const isUpdateNeeded = isWebhookUpdateNeeded({
existingWebhookNames: webhooks.map((w) => w.name),
});
return res.status(200).json({
webhooks,
isUpdateNeeded,
});
} catch (e) {
console.error(e);
return res.status(500).end();
}
};
export default createProtectedHandler(
webhooksStatusHandlerFactory({
settingsManagerFactory: createSettingsManager,
webhookActivityTogglerFactory: function (appId, client) {
return new WebhookActivityTogglerService(appId, client);
},
algoliaSearchProviderFactory(appId, apiKey) {
return new AlgoliaSearchProvider({ appId, apiKey, enabledKeys: [] });
},
graphqlClientFactory(saleorApiUrl: string, token: string) {
return createGraphQLClient({ saleorApiUrl, token });
},
}),
saleorApp.apl,
[],
);