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:
@@ -237,10 +237,11 @@ export const FEDERATION_ALLOW_PRIVATE: boolean =
|
||||
*
|
||||
* - `incoming` (`GERBEUR_FEDERATION_INCOMING`): users of other instances sign
|
||||
* in here. Off, the login and register pages offer no other instance,
|
||||
* `/manage` no list of instances to trust or block,
|
||||
* `federation-service.ts` refuses their sign-ins, and the accounts that came
|
||||
* from one are signed out (`getSessionState`) until it is on again. Their
|
||||
* homes' events are still applied, so that none is lost meanwhile.
|
||||
* `/manage` lists only the blocked ones, which this instance's users can't
|
||||
* sign in to (and none with `outgoing` off too), `federation-service.ts`
|
||||
* refuses their sign-ins, and the accounts that came from one are signed
|
||||
* out (`getSessionState`) until it is on again. Their homes' events are
|
||||
* still applied, so that none is lost meanwhile.
|
||||
* - `outgoing` (`GERBEUR_FEDERATION_OUTGOING`): this instance's users sign in
|
||||
* to others. Off, `identity-provider-service.ts` lets no instance sign them
|
||||
* in, and its metadata says so, which the others check before sending
|
||||
|
||||
@@ -354,7 +354,7 @@ msgstr "Already dumped by {0} {1}"
|
||||
msgid "Already have an account? <0>Log in</0>"
|
||||
msgstr "Already have an account? <0>Log in</0>"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:149
|
||||
#: src/components/federation/PeerManager.tsx:167
|
||||
msgid "An instance's address, like music.example"
|
||||
msgstr "An instance's address, like music.example"
|
||||
|
||||
@@ -395,11 +395,12 @@ msgstr "Back to login"
|
||||
msgid "Back to the login page"
|
||||
msgstr "Back to the login page"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:163
|
||||
#: src/components/federation/PeerManager.tsx:184
|
||||
#: src/components/federation/PeerManager.tsx:190
|
||||
msgid "Block"
|
||||
msgstr "Block"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:33
|
||||
#: src/components/federation/PeerManager.tsx:39
|
||||
msgid "Blocked"
|
||||
msgstr "Blocked"
|
||||
|
||||
@@ -453,7 +454,7 @@ msgid "Cancel search"
|
||||
msgstr "Cancel search"
|
||||
|
||||
#: src/components/category/CategorySelect.tsx:33
|
||||
#: src/pages/Manage.tsx:38
|
||||
#: src/pages/Manage.tsx:42
|
||||
msgid "Categories"
|
||||
msgstr "Categories"
|
||||
|
||||
@@ -502,7 +503,8 @@ msgstr "Chat ({unreadChatCount} unread)"
|
||||
msgid "Checking invite…"
|
||||
msgstr "Checking invite…"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:154
|
||||
#: src/components/federation/PeerManager.tsx:175
|
||||
#: src/components/federation/PeerManager.tsx:189
|
||||
msgid "Checking…"
|
||||
msgstr "Checking…"
|
||||
|
||||
@@ -590,7 +592,7 @@ msgstr "Could not rename"
|
||||
msgid "Could not save"
|
||||
msgstr "Could not save"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:146
|
||||
#: src/components/federation/PeerManager.tsx:164
|
||||
msgid "Couldn't add that instance"
|
||||
msgstr "Couldn't add that instance"
|
||||
|
||||
@@ -885,7 +887,7 @@ msgid "Failed to post reply"
|
||||
msgstr "Failed to post reply"
|
||||
|
||||
#: src/components/federation/GrantList.tsx:98
|
||||
#: src/components/federation/PeerManager.tsx:143
|
||||
#: src/components/federation/PeerManager.tsx:158
|
||||
#: src/components/playlist/PlaylistEditForm.tsx:185
|
||||
#: src/components/profile/DescriptionEditor.tsx:99
|
||||
#: src/components/profile/EmailEditor.tsx:86
|
||||
@@ -1029,7 +1031,7 @@ msgstr "In the chat"
|
||||
msgid "Insert emoji"
|
||||
msgstr "Insert emoji"
|
||||
|
||||
#: src/pages/Manage.tsx:45
|
||||
#: src/pages/Manage.tsx:49
|
||||
msgid "Instances"
|
||||
msgstr "Instances"
|
||||
|
||||
@@ -1145,7 +1147,7 @@ msgstr "Loading profile…"
|
||||
#: src/components/category/CategoryManager.tsx:60
|
||||
#: src/components/chat/ChatModal.tsx:763
|
||||
#: src/components/editor/EmojiPickerPopup.tsx:125
|
||||
#: src/components/federation/PeerManager.tsx:108
|
||||
#: src/components/federation/PeerManager.tsx:120
|
||||
#: src/components/playlist/PlaylistMembershipPanel.tsx:45
|
||||
#: src/components/shared/ListState.tsx:38
|
||||
#: src/components/shared/LoadMoreButton.tsx:32
|
||||
@@ -1194,8 +1196,8 @@ msgid "Lowercase letters, numbers and single hyphens only"
|
||||
msgstr "Lowercase letters, numbers and single hyphens only"
|
||||
|
||||
#: src/components/layout/UserMenu.tsx:114
|
||||
#: src/pages/Manage.tsx:29
|
||||
#: src/pages/Manage.tsx:36
|
||||
#: src/pages/Manage.tsx:32
|
||||
#: src/pages/Manage.tsx:40
|
||||
#: src/pages/UserPublicProfile.tsx:164
|
||||
msgid "Manage"
|
||||
msgstr "Manage"
|
||||
@@ -1538,8 +1540,8 @@ msgid "Related"
|
||||
msgstr "Related"
|
||||
|
||||
#. placeholder {0}: peer.host
|
||||
#: src/components/federation/PeerManager.tsx:133
|
||||
#: src/components/federation/PeerManager.tsx:134
|
||||
#: src/components/federation/PeerManager.tsx:148
|
||||
#: src/components/federation/PeerManager.tsx:149
|
||||
msgid "Remove {0}"
|
||||
msgstr "Remove {0}"
|
||||
|
||||
@@ -1893,11 +1895,11 @@ msgstr "Top this week"
|
||||
msgid "Track {0}"
|
||||
msgstr "Track {0}"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:155
|
||||
#: src/components/federation/PeerManager.tsx:176
|
||||
msgid "Trust"
|
||||
msgstr "Trust"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:32
|
||||
#: src/components/federation/PeerManager.tsx:38
|
||||
msgid "Trusted"
|
||||
msgstr "Trusted"
|
||||
|
||||
@@ -2032,7 +2034,15 @@ msgstr "Username"
|
||||
msgid "Users"
|
||||
msgstr "Users"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:169
|
||||
#: src/components/federation/PeerManager.tsx:198
|
||||
msgid "Users here can't sign in to a blocked instance."
|
||||
msgstr "Users here can't sign in to a blocked instance."
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:201
|
||||
msgid "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."
|
||||
msgstr "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."
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:208
|
||||
msgid "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."
|
||||
msgstr "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."
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ msgstr "Déjà recommandé par {0} {1}"
|
||||
msgid "Already have an account? <0>Log in</0>"
|
||||
msgstr "Vous avez déjà un compte ? <0>Se connecter</0>"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:149
|
||||
#: src/components/federation/PeerManager.tsx:167
|
||||
msgid "An instance's address, like music.example"
|
||||
msgstr "L'adresse d'une instance, comme music.example"
|
||||
|
||||
@@ -395,11 +395,12 @@ msgstr "Retour à la connexion"
|
||||
msgid "Back to the login page"
|
||||
msgstr "Retour à la page de connexion"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:163
|
||||
#: src/components/federation/PeerManager.tsx:184
|
||||
#: src/components/federation/PeerManager.tsx:190
|
||||
msgid "Block"
|
||||
msgstr "Bloquer"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:33
|
||||
#: src/components/federation/PeerManager.tsx:39
|
||||
msgid "Blocked"
|
||||
msgstr "Bloquée"
|
||||
|
||||
@@ -453,7 +454,7 @@ msgid "Cancel search"
|
||||
msgstr "Annuler la recherche"
|
||||
|
||||
#: src/components/category/CategorySelect.tsx:33
|
||||
#: src/pages/Manage.tsx:38
|
||||
#: src/pages/Manage.tsx:42
|
||||
msgid "Categories"
|
||||
msgstr "Catégories"
|
||||
|
||||
@@ -502,7 +503,8 @@ msgstr "{unreadChatCount} messages non lus"
|
||||
msgid "Checking invite…"
|
||||
msgstr "Vérification de l'invitation…"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:154
|
||||
#: src/components/federation/PeerManager.tsx:175
|
||||
#: src/components/federation/PeerManager.tsx:189
|
||||
msgid "Checking…"
|
||||
msgstr "Vérification…"
|
||||
|
||||
@@ -590,7 +592,7 @@ msgstr "Renommage impossible"
|
||||
msgid "Could not save"
|
||||
msgstr "Sauvegarde impossible"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:146
|
||||
#: src/components/federation/PeerManager.tsx:164
|
||||
msgid "Couldn't add that instance"
|
||||
msgstr "Impossible d'ajouter cette instance"
|
||||
|
||||
@@ -885,7 +887,7 @@ msgid "Failed to post reply"
|
||||
msgstr "Impossible de publier la réponse"
|
||||
|
||||
#: src/components/federation/GrantList.tsx:98
|
||||
#: src/components/federation/PeerManager.tsx:143
|
||||
#: src/components/federation/PeerManager.tsx:158
|
||||
#: src/components/playlist/PlaylistEditForm.tsx:185
|
||||
#: src/components/profile/DescriptionEditor.tsx:99
|
||||
#: src/components/profile/EmailEditor.tsx:86
|
||||
@@ -1029,7 +1031,7 @@ msgstr "Dans la tribune"
|
||||
msgid "Insert emoji"
|
||||
msgstr "Insérer un emoji"
|
||||
|
||||
#: src/pages/Manage.tsx:45
|
||||
#: src/pages/Manage.tsx:49
|
||||
msgid "Instances"
|
||||
msgstr "Instances"
|
||||
|
||||
@@ -1145,7 +1147,7 @@ msgstr "Chargement du profil…"
|
||||
#: src/components/category/CategoryManager.tsx:60
|
||||
#: src/components/chat/ChatModal.tsx:763
|
||||
#: src/components/editor/EmojiPickerPopup.tsx:125
|
||||
#: src/components/federation/PeerManager.tsx:108
|
||||
#: src/components/federation/PeerManager.tsx:120
|
||||
#: src/components/playlist/PlaylistMembershipPanel.tsx:45
|
||||
#: src/components/shared/ListState.tsx:38
|
||||
#: src/components/shared/LoadMoreButton.tsx:32
|
||||
@@ -1194,8 +1196,8 @@ msgid "Lowercase letters, numbers and single hyphens only"
|
||||
msgstr "Minuscules, chiffres et tirets simples seulement"
|
||||
|
||||
#: src/components/layout/UserMenu.tsx:114
|
||||
#: src/pages/Manage.tsx:29
|
||||
#: src/pages/Manage.tsx:36
|
||||
#: src/pages/Manage.tsx:32
|
||||
#: src/pages/Manage.tsx:40
|
||||
#: src/pages/UserPublicProfile.tsx:164
|
||||
msgid "Manage"
|
||||
msgstr "Administration"
|
||||
@@ -1538,8 +1540,8 @@ msgid "Related"
|
||||
msgstr "Connexe"
|
||||
|
||||
#. placeholder {0}: peer.host
|
||||
#: src/components/federation/PeerManager.tsx:133
|
||||
#: src/components/federation/PeerManager.tsx:134
|
||||
#: src/components/federation/PeerManager.tsx:148
|
||||
#: src/components/federation/PeerManager.tsx:149
|
||||
msgid "Remove {0}"
|
||||
msgstr "Retirer {0}"
|
||||
|
||||
@@ -1893,11 +1895,11 @@ msgstr "Les plus votées de la semaine"
|
||||
msgid "Track {0}"
|
||||
msgstr "Piste {0}"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:155
|
||||
#: src/components/federation/PeerManager.tsx:176
|
||||
msgid "Trust"
|
||||
msgstr "Approuver"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:32
|
||||
#: src/components/federation/PeerManager.tsx:38
|
||||
msgid "Trusted"
|
||||
msgstr "Approuvée"
|
||||
|
||||
@@ -2032,7 +2034,15 @@ msgstr "Nom d'utilisateur"
|
||||
msgid "Users"
|
||||
msgstr "Utilisateurs"
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:169
|
||||
#: src/components/federation/PeerManager.tsx:198
|
||||
msgid "Users here can't sign in to a blocked instance."
|
||||
msgstr "Les utilisateurs d'ici ne peuvent pas se connecter à une instance bloquée."
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:201
|
||||
msgid "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."
|
||||
msgstr "Les utilisateurs d'une instance approuvée se connectent ici avec leur compte de là-bas. Ceux d'une instance bloquée ne le peuvent pas, et les utilisateurs d'ici ne peuvent pas s'y connecter. Ceux de toute autre instance ont besoin d'une invitation."
|
||||
|
||||
#: src/components/federation/PeerManager.tsx:208
|
||||
msgid "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."
|
||||
msgstr "Les utilisateurs d'une instance approuvée se connectent ici avec leur compte de là-bas. Ceux d'une instance bloquée ne le peuvent pas. Ceux de toute autre instance ont besoin d'une invitation."
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -16,20 +16,24 @@ import { PageHeader } from "../components/layout/PageHeader.tsx";
|
||||
import { PageGroup } from "../components/layout/PageGroup.tsx";
|
||||
import { CategoryManager } from "../components/category/CategoryManager.tsx";
|
||||
import { PeerManager } from "../components/federation/PeerManager.tsx";
|
||||
import { FEDERATION_INCOMING } from "../config/instance.ts";
|
||||
import {
|
||||
FEDERATION_INCOMING,
|
||||
FEDERATION_OUTGOING,
|
||||
} from "../config/instance.ts";
|
||||
import { NotFound } from "./NotFound.tsx";
|
||||
|
||||
/**
|
||||
* Renders the category manager and the instances the site trusts or blocks,
|
||||
* each to those who hold its permission, which the API checks again, the
|
||||
* instances only while users of other instances may sign in here; without
|
||||
* instances only while federated sign-in goes at least one way; without
|
||||
* either, the page isn't found.
|
||||
*/
|
||||
export function Manage(): React.JSX.Element {
|
||||
useDocumentTitle(t`Manage`);
|
||||
const { user } = useRequiredAuth();
|
||||
const categories = can(user, "category:manage");
|
||||
const instances = FEDERATION_INCOMING && can(user, "federation:manage");
|
||||
const instances = (FEDERATION_INCOMING || FEDERATION_OUTGOING) &&
|
||||
can(user, "federation:manage");
|
||||
if (!categories && !instances) return <NotFound />;
|
||||
return (
|
||||
<PageShell narrow>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import { userEvent } from "@testing-library/user-event";
|
||||
import { Manage } from "../../pages/Manage.tsx";
|
||||
@@ -6,6 +6,20 @@ import { calls, fail, route } from "../fetch.ts";
|
||||
import { makeCategory, makeSession, wire } from "../fixtures.ts";
|
||||
import { renderApp } from "../render.tsx";
|
||||
|
||||
const instance = vi.hoisted(() => ({
|
||||
federationIncoming: true,
|
||||
federationOutgoing: true,
|
||||
}));
|
||||
vi.mock("../../config/instance.ts", async (importOriginal) => ({
|
||||
...await importOriginal<typeof import("../../config/instance.ts")>(),
|
||||
get FEDERATION_INCOMING() {
|
||||
return instance.federationIncoming;
|
||||
},
|
||||
get FEDERATION_OUTGOING() {
|
||||
return instance.federationOutgoing;
|
||||
},
|
||||
}));
|
||||
|
||||
const admin = makeSession({ id: "ann", username: "ann", role: "admin" });
|
||||
|
||||
function open(session = admin) {
|
||||
@@ -16,6 +30,11 @@ function open(session = admin) {
|
||||
}
|
||||
|
||||
describe("Manage", () => {
|
||||
afterEach(() => {
|
||||
instance.federationIncoming = true;
|
||||
instance.federationOutgoing = true;
|
||||
});
|
||||
|
||||
test("an admin manages categories", async () => {
|
||||
const music = makeCategory({ id: "c1", slug: "music", name: "Music" });
|
||||
let list = [music];
|
||||
@@ -128,6 +147,52 @@ describe("Manage", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("where users of other instances don't sign in, an admin only blocks instances", async () => {
|
||||
instance.federationIncoming = false;
|
||||
route("GET /api/categories", () => []);
|
||||
const peer = (name: string, host: string, status: string) => ({
|
||||
issuer: `https://${host}`,
|
||||
host,
|
||||
name,
|
||||
status,
|
||||
createdAt: new Date().toISOString(),
|
||||
});
|
||||
route("GET /api/federation/peers", () => [
|
||||
peer("Films", "films.example", "trusted"),
|
||||
peer("Spam", "spam.example", "blocked"),
|
||||
]);
|
||||
route(
|
||||
"PUT /api/federation/peers",
|
||||
() => peer("Music", "music.example", "blocked"),
|
||||
);
|
||||
const user = open();
|
||||
expect(await screen.findByText("Spam")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Films")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Trust" })).not
|
||||
.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Blocked" })).not
|
||||
.toBeInTheDocument();
|
||||
await user.type(
|
||||
screen.getByPlaceholderText("An instance's address, like music.example"),
|
||||
"music.example{Enter}",
|
||||
);
|
||||
await waitFor(() =>
|
||||
expect(calls("PUT /api/federation/peers")[0]?.body).toEqual({
|
||||
instance: "music.example",
|
||||
status: "blocked",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("without federated sign-in either way, there are no instances to manage", async () => {
|
||||
instance.federationIncoming = false;
|
||||
instance.federationOutgoing = false;
|
||||
route("GET /api/categories", () => []);
|
||||
open();
|
||||
expect(await screen.findByText("Categories")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Instances")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("without category:manage, the page isn't found", async () => {
|
||||
open(makeSession({ id: "mod", role: "moderator" }));
|
||||
expect(await screen.findByText("This page does not exist."))
|
||||
|
||||
Reference in New Issue
Block a user