v4: an instance that takes no users of others still blocks instances its own users may not sign in to — with GERBEUR_FEDERATION_INCOMING=0, /manage hid its list of instances, though a blocked one still kept the instance's users from signing in there, and no admin could block another. The list now stays while federated sign-in goes either way: without incoming sign-ins it shows and adds only blocked instances, the trusted ones kept for when they're back, and says what blocking does there. Where both ways are on, its note now says that users here can't sign in to a blocked instance either.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* Renders the list of the other gerbeur instances an admin trusts or blocks,
|
||||
* on `/manage`, for those who hold `federation:manage`.
|
||||
* on `/manage`, for those who hold `federation:manage`. Where users of other
|
||||
* instances don't sign in, only blocking is left: it keeps this instance's
|
||||
* users from signing in to one.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
@@ -11,6 +13,10 @@ import { Trans } from "@lingui/react/macro";
|
||||
import { FormProvider } from "react-hook-form";
|
||||
|
||||
import { API_URL } from "../../config/api.ts";
|
||||
import {
|
||||
FEDERATION_INCOMING,
|
||||
FEDERATION_OUTGOING,
|
||||
} from "../../config/instance.ts";
|
||||
import type { Wire } from "../../../shared/api.ts";
|
||||
import type {
|
||||
FederationPeer,
|
||||
@@ -42,6 +48,8 @@ interface Values {
|
||||
* (`PUT /api/federation/peers`), and a button that takes it off the lists
|
||||
* (`DELETE /api/federation/peers/:host`), then a field that adds one. The
|
||||
* server checks that it answers as a gerbeur, and the permission again.
|
||||
* Without {@link FEDERATION_INCOMING} it lists and adds only blocked
|
||||
* instances; the trusted ones are kept for when it is back.
|
||||
*/
|
||||
export function PeerManager(): React.JSX.Element {
|
||||
const { authFetch } = useAuth();
|
||||
@@ -101,6 +109,10 @@ export function PeerManager(): React.JSX.Element {
|
||||
form.reset();
|
||||
});
|
||||
|
||||
const shown = FEDERATION_INCOMING
|
||||
? peers
|
||||
: peers?.filter((peer) => peer.status === "blocked") ?? null;
|
||||
|
||||
return (
|
||||
<div className="peer-manager">
|
||||
{peers === null && !error && (
|
||||
@@ -108,9 +120,9 @@ export function PeerManager(): React.JSX.Element {
|
||||
<Trans>Loading…</Trans>
|
||||
</p>
|
||||
)}
|
||||
{peers && peers.length > 0 && (
|
||||
{shown && shown.length > 0 && (
|
||||
<div className="profile-appearance-grid">
|
||||
{peers.map((peer) => (
|
||||
{shown.map((peer) => (
|
||||
<SettingRow
|
||||
key={peer.issuer}
|
||||
label={
|
||||
@@ -121,11 +133,14 @@ export function PeerManager(): React.JSX.Element {
|
||||
}
|
||||
>
|
||||
<span className="peer-controls">
|
||||
<Segmented
|
||||
options={STATUS_OPTIONS}
|
||||
value={peer.status}
|
||||
onChange={(status) => change(() => save(peer.issuer, status))}
|
||||
/>
|
||||
{FEDERATION_INCOMING && (
|
||||
<Segmented
|
||||
options={STATUS_OPTIONS}
|
||||
value={peer.status}
|
||||
onChange={(status) =>
|
||||
change(() => save(peer.issuer, status))}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="btn--ghost peer-remove"
|
||||
@@ -142,7 +157,10 @@ export function PeerManager(): React.JSX.Element {
|
||||
)}
|
||||
{error && <ErrorCard title={t`Failed to save`} message={error} />}
|
||||
<FormProvider {...form}>
|
||||
<form className="form peer-add" onSubmit={add("trusted")}>
|
||||
<form
|
||||
className="form peer-add"
|
||||
onSubmit={add(FEDERATION_INCOMING ? "trusted" : "blocked")}
|
||||
>
|
||||
<FormError title={t`Couldn't add that instance`} />
|
||||
<TextField<Values>
|
||||
name="instance"
|
||||
@@ -151,26 +169,48 @@ export function PeerManager(): React.JSX.Element {
|
||||
rules={{ required: true }}
|
||||
/>
|
||||
<div className="peer-add-actions">
|
||||
<SubmitButton pendingLabel={<Trans>Checking…</Trans>}>
|
||||
<Trans>Trust</Trans>
|
||||
</SubmitButton>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-secondary"
|
||||
disabled={form.formState.isSubmitting}
|
||||
onClick={add("blocked")}
|
||||
>
|
||||
<Trans>Block</Trans>
|
||||
</button>
|
||||
{FEDERATION_INCOMING
|
||||
? (
|
||||
<>
|
||||
<SubmitButton pendingLabel={<Trans>Checking…</Trans>}>
|
||||
<Trans>Trust</Trans>
|
||||
</SubmitButton>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-secondary"
|
||||
disabled={form.formState.isSubmitting}
|
||||
onClick={add("blocked")}
|
||||
>
|
||||
<Trans>Block</Trans>
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<SubmitButton pendingLabel={<Trans>Checking…</Trans>}>
|
||||
<Trans>Block</Trans>
|
||||
</SubmitButton>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
<p className="form-hint">
|
||||
<Trans>
|
||||
Users of a trusted instance sign in here with their account there.
|
||||
Those of a blocked one can't. Users of any other instance need an
|
||||
invite.
|
||||
</Trans>
|
||||
{!FEDERATION_INCOMING
|
||||
? <Trans>Users here can't sign in to a blocked instance.</Trans>
|
||||
: FEDERATION_OUTGOING
|
||||
? (
|
||||
<Trans>
|
||||
Users of a trusted instance sign in here with their account there.
|
||||
Those of a blocked one can't, and users here can't sign in to it.
|
||||
Users of any other instance need an invite.
|
||||
</Trans>
|
||||
)
|
||||
: (
|
||||
<Trans>
|
||||
Users of a trusted instance sign in here with their account there.
|
||||
Those of a blocked one can't. Users of any other instance need an
|
||||
invite.
|
||||
</Trans>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user