From 637f188ebec71fe4b0b80bbab4592d4c269d7d93 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:46:06 +0200 Subject: [feature] Allow import/export/creation of domain allows via admin panel (#2264) * it's happening! * aaa * fix silly whoopsie * it's working pa! it's working ma! * model report parameters * shuffle some more stuff around * getting there * oo hoo * finish tidying up for now * aaa * fix use form submit errors * peepee poo poo * aaaaa * ffff * they see me typin', they hatin' * boop * aaa * oooo * typing typing tappa tappa * almost done typing * weee * alright * push it push it real good doo doo doo doo doo doo * thingy no worky * almost done * mutation modifers not quite right * hmm * it works * view blocks + allows nicely * it works! * typia install * the old linterino * linter plz --- web/source/settings/admin/accounts/detail.jsx | 6 +- .../settings/admin/domain-permissions/detail.tsx | 254 +++++++++++++ .../domain-permissions/export-format-table.jsx | 65 ++++ .../settings/admin/domain-permissions/form.tsx | 152 ++++++++ .../admin/domain-permissions/import-export.tsx | 90 +++++ .../settings/admin/domain-permissions/index.tsx | 49 +++ .../settings/admin/domain-permissions/overview.tsx | 198 ++++++++++ .../settings/admin/domain-permissions/process.tsx | 402 +++++++++++++++++++++ .../settings/admin/emoji/category-select.jsx | 5 +- web/source/settings/admin/emoji/local/detail.js | 18 +- web/source/settings/admin/emoji/local/new-emoji.js | 10 +- web/source/settings/admin/emoji/local/overview.js | 4 +- .../settings/admin/emoji/local/use-shortcode.js | 8 +- web/source/settings/admin/emoji/remote/index.js | 4 +- .../settings/admin/emoji/remote/parse-from-toot.js | 14 +- web/source/settings/admin/federation/detail.js | 168 --------- .../import-export/export-format-table.jsx | 65 ---- .../admin/federation/import-export/form.jsx | 124 ------- .../admin/federation/import-export/index.jsx | 75 ---- .../admin/federation/import-export/process.jsx | 329 ----------------- web/source/settings/admin/federation/index.js | 41 --- web/source/settings/admin/federation/overview.js | 101 ------ web/source/settings/admin/reports/detail.jsx | 14 +- web/source/settings/admin/reports/index.jsx | 7 +- web/source/settings/admin/settings/index.jsx | 13 +- web/source/settings/admin/settings/rules.jsx | 4 +- 26 files changed, 1267 insertions(+), 953 deletions(-) create mode 100644 web/source/settings/admin/domain-permissions/detail.tsx create mode 100644 web/source/settings/admin/domain-permissions/export-format-table.jsx create mode 100644 web/source/settings/admin/domain-permissions/form.tsx create mode 100644 web/source/settings/admin/domain-permissions/import-export.tsx create mode 100644 web/source/settings/admin/domain-permissions/index.tsx create mode 100644 web/source/settings/admin/domain-permissions/overview.tsx create mode 100644 web/source/settings/admin/domain-permissions/process.tsx delete mode 100644 web/source/settings/admin/federation/detail.js delete mode 100644 web/source/settings/admin/federation/import-export/export-format-table.jsx delete mode 100644 web/source/settings/admin/federation/import-export/form.jsx delete mode 100644 web/source/settings/admin/federation/import-export/index.jsx delete mode 100644 web/source/settings/admin/federation/import-export/process.jsx delete mode 100644 web/source/settings/admin/federation/index.js delete mode 100644 web/source/settings/admin/federation/overview.js (limited to 'web/source/settings/admin') diff --git a/web/source/settings/admin/accounts/detail.jsx b/web/source/settings/admin/accounts/detail.jsx index 0e906cd1c..63049c149 100644 --- a/web/source/settings/admin/accounts/detail.jsx +++ b/web/source/settings/admin/accounts/detail.jsx @@ -22,13 +22,13 @@ const { useRoute, Redirect } = require("wouter"); const query = require("../../lib/query"); -const FormWithData = require("../../lib/form/form-with-data"); +const FormWithData = require("../../lib/form/form-with-data").default; const { useBaseUrl } = require("../../lib/navigation/util"); const FakeProfile = require("../../components/fake-profile"); const MutationButton = require("../../components/form/mutation-button"); -const useFormSubmit = require("../../lib/form/submit"); +const useFormSubmit = require("../../lib/form/submit").default; const { useValue, useTextInput } = require("../../lib/form"); const { TextInput } = require("../../components/form/inputs"); @@ -77,7 +77,7 @@ function AccountDetailForm({ data: account }) { function ModifyAccount({ account }) { const form = { id: useValue("id", account.id), - reason: useTextInput("text", {}) + reason: useTextInput("text") }; const [modifyAccount, result] = useFormSubmit(form, query.useActionAccountMutation()); diff --git a/web/source/settings/admin/domain-permissions/detail.tsx b/web/source/settings/admin/domain-permissions/detail.tsx new file mode 100644 index 000000000..f74802666 --- /dev/null +++ b/web/source/settings/admin/domain-permissions/detail.tsx @@ -0,0 +1,254 @@ +/* + 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 . +*/ + +import React from "react"; + +import { useMemo } from "react"; +import { useLocation } from "wouter"; + +import { useTextInput, useBoolInput } from "../../lib/form"; + +import useFormSubmit from "../../lib/form/submit"; + +import { TextInput, Checkbox, TextArea } from "../../components/form/inputs"; + +import Loading from "../../components/loading"; +import BackButton from "../../components/back-button"; +import MutationButton from "../../components/form/mutation-button"; + +import { useDomainAllowsQuery, useDomainBlocksQuery } from "../../lib/query/admin/domain-permissions/get"; +import { useAddDomainAllowMutation, useAddDomainBlockMutation, useRemoveDomainAllowMutation, useRemoveDomainBlockMutation } from "../../lib/query/admin/domain-permissions/update"; +import { DomainPerm, PermType } from "../../lib/types/domain-permission"; +import { NoArg } from "../../lib/types/query"; +import { Error } from "../../components/error"; + +export interface DomainPermDetailProps { + baseUrl: string; + permType: PermType; + domain: string; +} + +export default function DomainPermDetail({ baseUrl, permType, domain }: DomainPermDetailProps) { + const { data: domainBlocks = {}, isLoading: isLoadingDomainBlocks } = useDomainBlocksQuery(NoArg, { skip: permType !== "block" }); + const { data: domainAllows = {}, isLoading: isLoadingDomainAllows } = useDomainAllowsQuery(NoArg, { skip: permType !== "allow" }); + + let isLoading; + switch (permType) { + case "block": + isLoading = isLoadingDomainBlocks; + break; + case "allow": + isLoading = isLoadingDomainAllows; + break; + default: + throw "perm type unknown"; + } + + if (domain == "view") { + // Retrieve domain from form field submission. + domain = (new URL(document.location.toString())).searchParams.get("domain")?? "unknown"; + } + + if (domain == "unknown") { + throw "unknown domain"; + } + + // Normalize / decode domain (it may be URL-encoded). + domain = decodeURIComponent(domain); + + // Check if we already have a perm of the desired type for this domain. + const existingPerm: DomainPerm | undefined = useMemo(() => { + if (permType == "block") { + return domainBlocks[domain]; + } else { + return domainAllows[domain]; + } + }, [domainBlocks, domainAllows, domain, permType]); + + let infoContent: React.JSX.Element; + + if (isLoading) { + infoContent = ; + } else if (existingPerm == undefined) { + infoContent = No stored {permType} yet, you can add one below:; + } else { + infoContent = ( +
+ + Editing domain permissions isn't implemented yet, check here for progress +
+ ); + } + + return ( +
+

Domain {permType} for: {domain}

+ {infoContent} + +
+ ); +} + +interface DomainPermFormProps { + defaultDomain: string; + perm?: DomainPerm; + permType: PermType; + baseUrl: string; +} + +function DomainPermForm({ defaultDomain, perm, permType, baseUrl }: DomainPermFormProps) { + const isExistingPerm = perm !== undefined; + const disabledForm = isExistingPerm + ? { + disabled: true, + title: "Domain permissions currently cannot be edited." + } + : { + disabled: false, + title: "", + }; + + const form = { + domain: useTextInput("domain", { source: perm, defaultValue: defaultDomain }), + obfuscate: useBoolInput("obfuscate", { source: perm }), + commentPrivate: useTextInput("private_comment", { source: perm }), + commentPublic: useTextInput("public_comment", { source: perm }) + }; + + // Check which perm type we're meant to be handling + // here, and use appropriate mutations and results. + // We can't call these hooks conditionally because + // react is like "weh" (mood), but we can decide + // which ones to use conditionally. + const [ addBlock, addBlockResult ] = useAddDomainBlockMutation(); + const [ removeBlock, removeBlockResult] = useRemoveDomainBlockMutation({ fixedCacheKey: perm?.id }); + const [ addAllow, addAllowResult ] = useAddDomainAllowMutation(); + const [ removeAllow, removeAllowResult ] = useRemoveDomainAllowMutation({ fixedCacheKey: perm?.id }); + + const [ + addTrigger, + addResult, + removeTrigger, + removeResult, + ] = useMemo(() => { + return permType == "block" + ? [ + addBlock, + addBlockResult, + removeBlock, + removeBlockResult, + ] + : [ + addAllow, + addAllowResult, + removeAllow, + removeAllowResult, + ]; + }, [permType, + addBlock, addBlockResult, removeBlock, removeBlockResult, + addAllow, addAllowResult, removeAllow, removeAllowResult, + ]); + + // Use appropriate submission params for this permType. + const [submitForm, submitFormResult] = useFormSubmit(form, [addTrigger, addResult], { changedOnly: false }); + + // Uppercase first letter of given permType. + const permTypeUpper = useMemo(() => { + return permType.charAt(0).toUpperCase() + permType.slice(1); + }, [permType]); + + const [location, setLocation] = useLocation(); + + function verifyUrlThenSubmit(e) { + // Adding a new domain permissions happens on a url like + // "/settings/admin/domain-permissions/:permType/domain.com", + // but if domain input changes, that doesn't match anymore + // and causes issues later on so, before submitting the form, + // silently change url, and THEN submit. + let correctUrl = `${baseUrl}/${form.domain.value}`; + if (location != correctUrl) { + setLocation(correctUrl); + } + return submitForm(e); + } + + return ( +
+ + + + +