Add admin name approve/reject endpoints
This commit is contained in:
parent
594f37ea33
commit
2a2f43d106
16
src/app.ts
16
src/app.ts
|
@ -30,7 +30,15 @@ import { adminAccountsController, adminActionController } from '@/controllers/ap
|
||||||
import { appCredentialsController, createAppController } from '@/controllers/api/apps.ts';
|
import { appCredentialsController, createAppController } from '@/controllers/api/apps.ts';
|
||||||
import { blocksController } from '@/controllers/api/blocks.ts';
|
import { blocksController } from '@/controllers/api/blocks.ts';
|
||||||
import { bookmarksController } from '@/controllers/api/bookmarks.ts';
|
import { bookmarksController } from '@/controllers/api/bookmarks.ts';
|
||||||
import { adminRelaysController, adminSetRelaysController, nameRequestController } from '@/controllers/api/ditto.ts';
|
import {
|
||||||
|
adminNameApproveController,
|
||||||
|
adminNameRejectController,
|
||||||
|
adminNameRequestsController,
|
||||||
|
adminRelaysController,
|
||||||
|
adminSetRelaysController,
|
||||||
|
nameRequestController,
|
||||||
|
nameRequestsController,
|
||||||
|
} from '@/controllers/api/ditto.ts';
|
||||||
import { emptyArrayController, emptyObjectController, notImplementedController } from '@/controllers/api/fallback.ts';
|
import { emptyArrayController, emptyObjectController, notImplementedController } from '@/controllers/api/fallback.ts';
|
||||||
import { instanceController } from '@/controllers/api/instance.ts';
|
import { instanceController } from '@/controllers/api/instance.ts';
|
||||||
import { markersController, updateMarkersController } from '@/controllers/api/markers.ts';
|
import { markersController, updateMarkersController } from '@/controllers/api/markers.ts';
|
||||||
|
@ -245,6 +253,12 @@ app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysControlle
|
||||||
app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysController);
|
app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysController);
|
||||||
|
|
||||||
app.post('/api/v1/ditto/names', requireSigner, nameRequestController);
|
app.post('/api/v1/ditto/names', requireSigner, nameRequestController);
|
||||||
|
app.get('/api/v1/ditto/names', requireSigner, nameRequestsController);
|
||||||
|
|
||||||
|
app.get('/api/v1/admin/ditto/names', requireRole('admin'), adminNameRequestsController);
|
||||||
|
app.post('/api/v1/admin/ditto/names/:id{[0-9a-f]{64}}/approve', requireRole('admin'), adminNameApproveController);
|
||||||
|
app.post('/api/v1/admin/ditto/names/:id{[0-9a-f]{64}}/reject', requireRole('admin'), adminNameRejectController);
|
||||||
|
|
||||||
app.post('/api/v1/ditto/zap', requireSigner, zapController);
|
app.post('/api/v1/ditto/zap', requireSigner, zapController);
|
||||||
|
|
||||||
app.post('/api/v1/reports', requireSigner, reportController);
|
app.post('/api/v1/reports', requireSigner, reportController);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { booleanParamSchema } from '@/schema.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { createEvent, paginated, paginationSchema } from '@/utils/api.ts';
|
import { createAdminEvent, createEvent, paginated, paginationSchema, updateEventInfo } from '@/utils/api.ts';
|
||||||
import { renderNameRequest } from '@/views/ditto.ts';
|
import { renderNameRequest } from '@/views/ditto.ts';
|
||||||
|
|
||||||
const markerSchema = z.enum(['read', 'write']);
|
const markerSchema = z.enum(['read', 'write']);
|
||||||
|
@ -183,3 +183,58 @@ export const adminNameRequestsController: AppController = async (c) => {
|
||||||
|
|
||||||
return paginated(c, orig, nameRequests);
|
return paginated(c, orig, nameRequests);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const adminNameApproveController: AppController = async (c) => {
|
||||||
|
const eventId = c.req.param('id');
|
||||||
|
const store = await Storages.db();
|
||||||
|
|
||||||
|
const [event] = await store.query([{ kinds: [3036], ids: [eventId] }]);
|
||||||
|
if (!event) {
|
||||||
|
return c.json({ error: 'Event not found' }, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
const r = event.tags.find(([name]) => name === 'r')?.[1];
|
||||||
|
if (!r) {
|
||||||
|
return c.json({ error: 'NIP-05 not found' }, 404);
|
||||||
|
}
|
||||||
|
if (!z.string().email().safeParse(r).success) {
|
||||||
|
return c.json({ error: 'Invalid NIP-05' }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [existing] = await store.query([{ kinds: [30360], authors: [Conf.pubkey], '#d': [r], limit: 1 }]);
|
||||||
|
if (existing) {
|
||||||
|
return c.json({ error: 'NIP-05 already granted to another user' }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
await createAdminEvent({
|
||||||
|
kind: 30360,
|
||||||
|
tags: [
|
||||||
|
['d', r],
|
||||||
|
['L', 'nip05.domain'],
|
||||||
|
['l', r.split('@')[1], 'nip05.domain'],
|
||||||
|
['p', event.pubkey],
|
||||||
|
],
|
||||||
|
}, c);
|
||||||
|
|
||||||
|
await updateEventInfo(eventId, { pending: false, approved: true, rejected: false }, c);
|
||||||
|
await hydrateEvents({ events: [event], store });
|
||||||
|
|
||||||
|
const nameRequest = await renderNameRequest(event);
|
||||||
|
return c.json(nameRequest);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const adminNameRejectController: AppController = async (c) => {
|
||||||
|
const eventId = c.req.param('id');
|
||||||
|
const store = await Storages.db();
|
||||||
|
|
||||||
|
const [event] = await store.query([{ kinds: [3036], ids: [eventId] }]);
|
||||||
|
if (!event) {
|
||||||
|
return c.json({ error: 'Event not found' }, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateEventInfo(eventId, { pending: false, approved: false, rejected: true }, c);
|
||||||
|
await hydrateEvents({ events: [event], store });
|
||||||
|
|
||||||
|
const nameRequest = await renderNameRequest(event);
|
||||||
|
return c.json(nameRequest);
|
||||||
|
};
|
||||||
|
|
|
@ -223,6 +223,8 @@ class EventsDB implements NStore {
|
||||||
return event.content;
|
return event.content;
|
||||||
case 30009:
|
case 30009:
|
||||||
return EventsDB.buildTagsSearchContent(event.tags.filter(([t]) => t !== 'alt'));
|
return EventsDB.buildTagsSearchContent(event.tags.filter(([t]) => t !== 'alt'));
|
||||||
|
case 30360:
|
||||||
|
return event.tags.find(([name]) => name === 'd')?.[1] || '';
|
||||||
default:
|
default:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue