Merge branch 'admin-relay-api' into 'main'

Add an API to manage admin relays

See merge request soapbox-pub/ditto!178
This commit is contained in:
Alex Gleason 2024-04-24 01:14:24 +00:00
commit 443cede73e
2 changed files with 62 additions and 1 deletions

View File

@ -77,6 +77,7 @@ import { auth19, requirePubkey } from '@/middleware/auth19.ts';
import { auth98, requireProof, requireRole } from '@/middleware/auth98.ts'; import { auth98, requireProof, requireRole } from '@/middleware/auth98.ts';
import { cache } from '@/middleware/cache.ts'; import { cache } from '@/middleware/cache.ts';
import { csp } from '@/middleware/csp.ts'; import { csp } from '@/middleware/csp.ts';
import { adminRelaysController } from '@/controllers/api/ditto.ts';
interface AppEnv extends HonoEnv { interface AppEnv extends HonoEnv {
Variables: { Variables: {
@ -187,11 +188,14 @@ app.get('/api/v1/favourites', requirePubkey, favouritesController);
app.get('/api/v1/bookmarks', requirePubkey, bookmarksController); app.get('/api/v1/bookmarks', requirePubkey, bookmarksController);
app.get('/api/v1/blocks', requirePubkey, blocksController); app.get('/api/v1/blocks', requirePubkey, blocksController);
app.get('/api/v1/admin/accounts', adminAccountsController); app.get('/api/v1/admin/accounts', requireRole('admin'), adminAccountsController);
app.get('/api/v1/pleroma/admin/config', requireRole('admin'), configController); app.get('/api/v1/pleroma/admin/config', requireRole('admin'), configController);
app.post('/api/v1/pleroma/admin/config', requireRole('admin'), updateConfigController); app.post('/api/v1/pleroma/admin/config', requireRole('admin'), updateConfigController);
app.delete('/api/v1/pleroma/admin/statuses/:id', requireRole('admin'), pleromaAdminDeleteStatusController); app.delete('/api/v1/pleroma/admin/statuses/:id', requireRole('admin'), pleromaAdminDeleteStatusController);
app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController);
app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController);
// Not (yet) implemented. // Not (yet) implemented.
app.get('/api/v1/custom_emojis', emptyArrayController); app.get('/api/v1/custom_emojis', emptyArrayController);
app.get('/api/v1/filters', emptyArrayController); app.get('/api/v1/filters', emptyArrayController);

View File

@ -0,0 +1,57 @@
import { NostrEvent } from '@nostrify/nostrify';
import { z } from 'zod';
import { AppController } from '@/app.ts';
import { Conf } from '@/config.ts';
import { eventsDB } from '@/storages.ts';
import { AdminSigner } from '@/signers/AdminSigner.ts';
const relaySchema = z.object({
url: z.string().url(),
read: z.boolean(),
write: z.boolean(),
});
type RelayEntity = z.infer<typeof relaySchema>;
export const adminRelaysController: AppController = async (c) => {
const [event] = await eventsDB.query([
{ kinds: [10002], authors: [Conf.pubkey], limit: 1 },
]);
if (!event) {
return c.json([]);
}
return c.json(renderRelays(event));
};
export const adminSetRelaysController: AppController = async (c) => {
const relays = relaySchema.array().parse(await c.req.json());
const event = await new AdminSigner().signEvent({
kind: 10002,
tags: relays.map(({ url, read, write }) => ['r', url, read && write ? '' : read ? 'read' : 'write']),
content: '',
created_at: Math.floor(Date.now() / 1000),
});
await eventsDB.event(event);
return c.json(renderRelays(event));
};
/** Render Ditto API relays from a NIP-65 event. */
function renderRelays(event: NostrEvent): RelayEntity[] {
return event.tags.reduce((acc, [name, url, marker]) => {
if (name === 'r') {
const relay: RelayEntity = {
url,
read: !marker || marker === 'read',
write: !marker || marker === 'write',
};
acc.push(relay);
}
return acc;
}, [] as RelayEntity[]);
}