feat: handle 202 queued response and awaiting_approval status in ensurePeered
This commit is contained in:
@@ -31,4 +31,15 @@ describe('EnsurePeeredResult type', () => {
|
|||||||
};
|
};
|
||||||
expect(result.status).toBe('failed');
|
expect(result.status).toBe('failed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('pending result has error', () => {
|
||||||
|
const result: EnsurePeeredResult = {
|
||||||
|
status: 'pending',
|
||||||
|
error: 'Awaiting admin approval on remote instance',
|
||||||
|
};
|
||||||
|
expect(result.status).toBe('pending');
|
||||||
|
if (result.status === 'pending') {
|
||||||
|
expect(result.error).toContain('admin approval');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,20 @@ import { validateOrigin } from '../routes/federation.js';
|
|||||||
export type EnsurePeeredResult =
|
export type EnsurePeeredResult =
|
||||||
| { status: 'active'; peerId: string }
|
| { status: 'active'; peerId: string }
|
||||||
| { status: 'rejected'; error: string }
|
| { status: 'rejected'; error: string }
|
||||||
| { status: 'failed'; error: string };
|
| { status: 'failed'; error: string }
|
||||||
|
| { status: 'pending'; error: string };
|
||||||
|
|
||||||
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function getInstanceName(): string | undefined {
|
||||||
|
const db = getDb();
|
||||||
|
const row = db
|
||||||
|
.select({ name: schema.instanceSettings.instanceName })
|
||||||
|
.from(schema.instanceSettings)
|
||||||
|
.where(eq(schema.instanceSettings.id, 1))
|
||||||
|
.get();
|
||||||
|
return row?.name ?? undefined;
|
||||||
|
}
|
||||||
|
|
||||||
// ─── In-flight deduplication ─────────────────────────────────────────────────
|
// ─── In-flight deduplication ─────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -59,6 +72,8 @@ export async function ensurePeered(origin: string): Promise<EnsurePeeredResult>
|
|||||||
// Unreachable peers were previously active — treat as active for peering
|
// Unreachable peers were previously active — treat as active for peering
|
||||||
// (the health check will restore them; don't re-handshake)
|
// (the health check will restore them; don't re-handshake)
|
||||||
return { status: 'active', peerId: existing.id };
|
return { status: 'active', peerId: existing.id };
|
||||||
|
case 'awaiting_approval':
|
||||||
|
return { status: 'pending', error: 'Awaiting admin approval on remote instance' };
|
||||||
case 'pending':
|
case 'pending':
|
||||||
// Fall through to dedup logic below
|
// Fall through to dedup logic below
|
||||||
break;
|
break;
|
||||||
@@ -119,6 +134,7 @@ async function performHandshake(
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
sourceOrigin: ourOrigin,
|
sourceOrigin: ourOrigin,
|
||||||
hmacSecret,
|
hmacSecret,
|
||||||
|
instanceName: getInstanceName(),
|
||||||
}),
|
}),
|
||||||
signal: AbortSignal.timeout(10_000),
|
signal: AbortSignal.timeout(10_000),
|
||||||
});
|
});
|
||||||
@@ -132,6 +148,15 @@ async function performHandshake(
|
|||||||
return { status: 'active', peerId };
|
return { status: 'active', peerId };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.status === 202) {
|
||||||
|
// Request queued for admin approval on the remote side
|
||||||
|
db.update(schema.federationPeers)
|
||||||
|
.set({ status: 'awaiting_approval' })
|
||||||
|
.where(eq(schema.federationPeers.id, peerId))
|
||||||
|
.run();
|
||||||
|
return { status: 'pending', error: 'Awaiting admin approval on remote instance' };
|
||||||
|
}
|
||||||
|
|
||||||
// Check for explicit rejection (autoAcceptPeering = 0)
|
// Check for explicit rejection (autoAcceptPeering = 0)
|
||||||
let code: string | undefined;
|
let code: string | undefined;
|
||||||
let errorMessage = `Remote rejected peering (HTTP ${response.status})`;
|
let errorMessage = `Remote rejected peering (HTTP ${response.status})`;
|
||||||
|
|||||||
Reference in New Issue
Block a user