fix: address code review findings (C1, I1, I2)

- C1: Include 'unreachable' peers in queueOutboxEvent query to prevent
  UNIQUE constraint violation when creating placeholders
- I1: Add 'rejected' to StatusFilter in FederationPanel so admins can
  see and manage rejected peers with delete/re-initiate actions
- I2: Map ensurePeered 'failed' to 'pending' in peer/ensure response
  to match spec and client expectations
This commit is contained in:
Jannis Braun
2026-04-09 14:08:54 +02:00
parent 7366b56fdf
commit b434a736a8
3 changed files with 7 additions and 7 deletions
+2 -2
View File
@@ -517,9 +517,9 @@ export async function federationRoutes(app: FastifyInstance): Promise<void> {
case 'rejected': case 'rejected':
return reply.code(200).send({ peeringStatus: 'rejected', error: result.error }); return reply.code(200).send({ peeringStatus: 'rejected', error: result.error });
case 'failed': case 'failed':
return reply.code(200).send({ peeringStatus: 'failed', error: result.error }); return reply.code(200).send({ peeringStatus: 'pending', error: result.error });
default: default:
return reply.code(200).send({ peeringStatus: 'failed', error: 'Unknown peering result' }); return reply.code(200).send({ peeringStatus: 'pending', error: 'Unknown peering result' });
} }
}, },
); );
@@ -138,7 +138,7 @@ export function queueOutboxEvent(
.select() .select()
.from(schema.federationPeers) .from(schema.federationPeers)
.where( .where(
inArray(schema.federationPeers.status, ['active', 'pending']), inArray(schema.federationPeers.status, ['active', 'pending', 'unreachable']),
) )
.all(); .all();
@@ -201,7 +201,7 @@ function peerStatusLabel(status: string): string {
type PeerView = 'active' | 'revoked'; type PeerView = 'active' | 'revoked';
type SortBy = 'name' | 'lastSeen' | 'dateAdded' | 'failures'; type SortBy = 'name' | 'lastSeen' | 'dateAdded' | 'failures';
type StatusFilter = 'active' | 'unreachable' | 'pending'; type StatusFilter = 'active' | 'unreachable' | 'pending' | 'rejected';
// ─── Filter Dropdown ───────────────────────────────────────────────────────── // ─── Filter Dropdown ─────────────────────────────────────────────────────────
@@ -263,7 +263,7 @@ function FilterDropdown({
{view === 'active' && ( {view === 'active' && (
<> <>
<div className="text-[10px] font-semibold text-txt-tertiary uppercase tracking-wider px-2 py-1">Status</div> <div className="text-[10px] font-semibold text-txt-tertiary uppercase tracking-wider px-2 py-1">Status</div>
{(['active', 'unreachable', 'pending'] as StatusFilter[]).map((s) => ( {(['active', 'unreachable', 'pending', 'rejected'] as StatusFilter[]).map((s) => (
<button <button
key={s} key={s}
type="button" type="button"
@@ -392,7 +392,7 @@ function PeerRow({ peer, view, expanded, onToggleExpand, onAction, defaultAutoRo
const addToast = useUIStore((s) => s.addToast); const addToast = useUIStore((s) => s.addToast);
const name = peer.instanceName || new URL(peer.origin).host; const name = peer.instanceName || new URL(peer.origin).host;
const isRevoked = view === 'revoked'; const isRevoked = view === 'revoked' || peer.status === 'rejected';
const isDefault = peer.autoRotateIntervalDays === defaultAutoRotateIntervalDays; const isDefault = peer.autoRotateIntervalDays === defaultAutoRotateIntervalDays;
const handleSaveInterval = async () => { const handleSaveInterval = async () => {
@@ -588,7 +588,7 @@ export function FederationPanel() {
const [peersLoading, setPeersLoading] = useState(false); const [peersLoading, setPeersLoading] = useState(false);
const [peersError, setPeersError] = useState(''); const [peersError, setPeersError] = useState('');
const [view, setView] = useState<PeerView>('active'); const [view, setView] = useState<PeerView>('active');
const [statusFilter, setStatusFilter] = useState<Set<StatusFilter>>(new Set(['active', 'unreachable', 'pending'])); const [statusFilter, setStatusFilter] = useState<Set<StatusFilter>>(new Set(['active', 'unreachable', 'pending', 'rejected']));
const [sortBy, setSortBy] = useState<SortBy>('name'); const [sortBy, setSortBy] = useState<SortBy>('name');
const [expandedPeerId, setExpandedPeerId] = useState<string | null>(null); const [expandedPeerId, setExpandedPeerId] = useState<string | null>(null);