From 89e0cfd8741b6763ca04e90558bccf4c3c380cfa Mon Sep 17 00:00:00 2001
From: tobi <31960611+tsmethurst@users.noreply.github.com>
Date: Sat, 13 Apr 2024 13:25:10 +0200
Subject: [feature] Admin accounts endpoints; approve/reject sign-ups (#2826)

* update settings panels, add pending overview + approve/deny functions

* add admin accounts get, approve, reject

* send approved/rejected emails

* use signup URL

* docs!

* email

* swagger

* web linting

* fix email tests

* wee lil fixerinos

* use new paging logic for GetAccounts() series of admin endpoints, small changes to query building

* shuffle useAccountIDIn check *before* adding to query

* fix parse from toot react error

* use `netip.Addr`

* put valid slices in globals

* optimistic updates for account state

---------

Co-authored-by: kim <grufwub@gmail.com>
---
 .../settings/admin/accounts/search/index.tsx       | 125 +++++++++++++++++++++
 1 file changed, 125 insertions(+)
 create mode 100644 web/source/settings/admin/accounts/search/index.tsx

(limited to 'web/source/settings/admin/accounts/search/index.tsx')

diff --git a/web/source/settings/admin/accounts/search/index.tsx b/web/source/settings/admin/accounts/search/index.tsx
new file mode 100644
index 000000000..560bbb76a
--- /dev/null
+++ b/web/source/settings/admin/accounts/search/index.tsx
@@ -0,0 +1,125 @@
+/*
+	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 React from "react";
+
+import { useLazySearchAccountsQuery } from "../../../lib/query";
+import { useTextInput } from "../../../lib/form";
+
+import { AccountList } from "../../../components/account-list";
+import { SearchAccountParams } from "../../../lib/types/account";
+import { Select, TextInput } from "../../../components/form/inputs";
+import MutationButton from "../../../components/form/mutation-button";
+
+export function AccountSearchForm() {
+	const [searchAcct, searchRes] = useLazySearchAccountsQuery();
+
+	const form = {
+		origin: useTextInput("origin"),
+		status: useTextInput("status"),
+		permissions: useTextInput("permissions"),
+		username: useTextInput("username"),
+		display_name: useTextInput("display_name"),
+		by_domain: useTextInput("by_domain"),
+		email: useTextInput("email"),
+		ip: useTextInput("ip"),
+	};
+
+	function submitSearch(e) {
+		e.preventDefault();
+		
+		// Parse query parameters.
+		const entries = Object.entries(form).map(([k, v]) => {
+			// Take only defined form fields.
+			if (v.value === undefined || v.value.length === 0) {
+				return null;
+			}
+			return [[k, v.value]];
+		}).flatMap(kv => {
+			// Remove any nulls.
+			return kv || [];
+		});
+
+		const params: SearchAccountParams = Object.fromEntries(entries);
+		searchAcct(params);
+	}
+
+	return (
+		<>
+			<form onSubmit={submitSearch}>
+				<TextInput
+					field={form.username}
+					label={"(Optional) username (without leading '@' symbol)"}
+					placeholder="someone"
+				/>
+				<TextInput
+					field={form.by_domain}
+					label={"(Optional) domain"}
+					placeholder="example.org"
+				/>
+				<Select
+					field={form.origin}
+					label="Account origin"
+					options={
+						<>
+							<option value="">Local or remote</option>
+							<option value="local">Local only</option>
+							<option value="remote">Remote only</option>
+						</>
+					}
+				></Select>
+				<TextInput
+					field={form.email}
+					label={"(Optional) email address (local accounts only)"}
+					placeholder={"someone@example.org"}
+				/>
+				<TextInput
+					field={form.ip}
+					label={"(Optional) IP address (local accounts only)"}
+					placeholder={"198.51.100.0"}
+				/>
+				<Select
+					field={form.status}
+					label="Account status"
+					options={
+						<>
+							<option value="">Any</option>
+							<option value="pending">Pending only</option>
+							<option value="disabled">Disabled only</option>
+							<option value="suspended">Suspended only</option>
+						</>
+					}
+				></Select>
+				<MutationButton
+					disabled={false}
+					label={"Search"}
+					result={searchRes}
+				/>
+			</form>
+			<AccountList
+				isLoading={searchRes.isLoading}
+				isSuccess={searchRes.isSuccess}
+				data={searchRes.data}
+				isError={searchRes.isError}
+				error={searchRes.error}
+				emptyMessage="No accounts found that match your query"
+			/>
+		</>
+	);
+}
-- 
cgit v1.2.3

