summaryrefslogtreecommitdiff
path: root/web/source/settings/lib/query/admin/domain-permissions/export.ts
diff options
context:
space:
mode:
Diffstat (limited to 'web/source/settings/lib/query/admin/domain-permissions/export.ts')
-rw-r--r--web/source/settings/lib/query/admin/domain-permissions/export.ts155
1 files changed, 155 insertions, 0 deletions
diff --git a/web/source/settings/lib/query/admin/domain-permissions/export.ts b/web/source/settings/lib/query/admin/domain-permissions/export.ts
new file mode 100644
index 000000000..b6ef560f4
--- /dev/null
+++ b/web/source/settings/lib/query/admin/domain-permissions/export.ts
@@ -0,0 +1,155 @@
+/*
+ GoToSocial
+ Copyright (C) GoToSocial Authors admin@gotosocial.org
+ SPDX-License-Identifier: AGPL-3.0-or-later
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+import fileDownload from "js-file-download";
+import { unparse as csvUnparse } from "papaparse";
+
+import { gtsApi } from "../../gts-api";
+import { RootState } from "../../../../redux/store";
+import { FetchBaseQueryError } from "@reduxjs/toolkit/query";
+import { DomainPerm, ExportDomainPermsParams } from "../../../types/domain-permission";
+
+interface _exportProcess {
+ transformEntry: (_entry: DomainPerm) => any;
+ stringify: (_list: any[]) => string;
+ extension: string;
+ mime: string;
+}
+
+/**
+ * Derive process functions and metadata
+ * from provided export request form.
+ *
+ * @param formData
+ * @returns
+ */
+function exportProcess(formData: ExportDomainPermsParams): _exportProcess {
+ if (formData.exportType == "json") {
+ return {
+ transformEntry: (entry) => ({
+ domain: entry.domain,
+ public_comment: entry.public_comment,
+ obfuscate: entry.obfuscate
+ }),
+ stringify: (list) => JSON.stringify(list),
+ extension: ".json",
+ mime: "application/json"
+ };
+ }
+
+ if (formData.exportType == "csv") {
+ return {
+ transformEntry: (entry) => [
+ entry.domain, // #domain
+ "suspend", // #severity
+ false, // #reject_media
+ false, // #reject_reports
+ entry.public_comment, // #public_comment
+ entry.obfuscate ?? false // #obfuscate
+ ],
+ stringify: (list) => csvUnparse({
+ fields: [
+ "#domain",
+ "#severity",
+ "#reject_media",
+ "#reject_reports",
+ "#public_comment",
+ "#obfuscate",
+ ],
+ data: list
+ }),
+ extension: ".csv",
+ mime: "text/csv"
+ };
+ }
+
+ // Fall back to plain text export.
+ return {
+ transformEntry: (entry) => entry.domain,
+ stringify: (list) => list.join("\n"),
+ extension: ".txt",
+ mime: "text/plain"
+ };
+}
+
+const extended = gtsApi.injectEndpoints({
+ endpoints: (build) => ({
+ exportDomainList: build.mutation<string | null, ExportDomainPermsParams>({
+ async queryFn(formData, api, _extraOpts, fetchWithBQ) {
+ // Fetch domain perms from relevant endpoint.
+ // We could have used 'useDomainBlocksQuery'
+ // or 'useDomainAllowsQuery' for this, but
+ // we want the untransformed array version.
+ const permsRes = await fetchWithBQ({ url: `/api/v1/admin/domain_${formData.permType}s` });
+ if (permsRes.error) {
+ return { error: permsRes.error as FetchBaseQueryError };
+ }
+
+ // Process perms into desired export format.
+ const process = exportProcess(formData);
+ const transformed = (permsRes.data as DomainPerm[]).map(process.transformEntry);
+ const exportAsString = process.stringify(transformed);
+
+ if (formData.action == "export") {
+ // Data will just be exported
+ // to the domains text field.
+ return { data: exportAsString };
+ }
+
+ // File export has been requested.
+ // Parse filename to something like:
+ // `example.org-blocklist-2023-10-09.json`.
+ const state = api.getState() as RootState;
+ const instanceUrl = state.oauth.instanceUrl?? "unknown";
+ const domain = new URL(instanceUrl).host;
+ const date = new Date();
+ const filename = [
+ domain,
+ "blocklist",
+ date.getFullYear(),
+ (date.getMonth() + 1).toString().padStart(2, "0"),
+ date.getDate().toString().padStart(2, "0"),
+ ].join("-");
+
+ fileDownload(
+ exportAsString,
+ filename + process.extension,
+ process.mime
+ );
+
+ // js-file-download handles the
+ // nitty gritty for us, so we can
+ // just return null data.
+ return { data: null };
+ }
+ }),
+ })
+});
+
+/**
+ * Makes a GET to `/api/v1/admin/domain_{perm_type}s`
+ * and exports the result in the requested format.
+ *
+ * Return type will be string if `action` is "export",
+ * else it will be null, since the file downloader handles
+ * the rest of the request then.
+ */
+const useExportDomainListMutation = extended.useExportDomainListMutation;
+
+export { useExportDomainListMutation };