Merge branch 'admin-accounts-perform-action' into 'main'
Implement Mastodon API - perform action against an account Closes #114 See merge request soapbox-pub/ditto!240
This commit is contained in:
commit
afcf28b506
|
@ -25,7 +25,7 @@ import {
|
||||||
updateCredentialsController,
|
updateCredentialsController,
|
||||||
verifyCredentialsController,
|
verifyCredentialsController,
|
||||||
} from '@/controllers/api/accounts.ts';
|
} from '@/controllers/api/accounts.ts';
|
||||||
import { adminAccountsController } from '@/controllers/api/admin.ts';
|
import { adminAccountAction, adminAccountsController } from '@/controllers/api/admin.ts';
|
||||||
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';
|
||||||
|
@ -222,6 +222,8 @@ app.post(
|
||||||
adminReportResolveController,
|
adminReportResolveController,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
app.post('/api/v1/admin/accounts/:id{[0-9a-f]{64}}/action', requirePubkey, requireRole('admin'), adminAccountAction);
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { Conf } from '@/config.ts';
|
||||||
import { booleanParamSchema } from '@/schema.ts';
|
import { booleanParamSchema } from '@/schema.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { renderAdminAccount } from '@/views/mastodon/admin-accounts.ts';
|
import { renderAdminAccount } from '@/views/mastodon/admin-accounts.ts';
|
||||||
import { paginated, paginationSchema } from '@/utils/api.ts';
|
import { paginated, paginationSchema, parseBody, updateListAdminEvent } from '@/utils/api.ts';
|
||||||
|
import { addTag } from '@/tags.ts';
|
||||||
|
|
||||||
const adminAccountQuerySchema = z.object({
|
const adminAccountQuerySchema = z.object({
|
||||||
local: booleanParamSchema.optional(),
|
local: booleanParamSchema.optional(),
|
||||||
|
@ -57,4 +58,32 @@ const adminAccountsController: AppController = async (c) => {
|
||||||
return paginated(c, events, accounts);
|
return paginated(c, events, accounts);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { adminAccountsController };
|
const adminAccountActionSchema = z.object({
|
||||||
|
type: z.enum(['none', 'sensitive', 'disable', 'silence', 'suspend']),
|
||||||
|
});
|
||||||
|
|
||||||
|
const adminAccountAction: AppController = async (c) => {
|
||||||
|
const body = await parseBody(c.req.raw);
|
||||||
|
const result = adminAccountActionSchema.safeParse(body);
|
||||||
|
const authorId = c.req.param('id');
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
return c.json({ error: 'This action is not allowed' }, 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = result;
|
||||||
|
|
||||||
|
if (data.type !== 'disable') {
|
||||||
|
return c.json({ error: 'Record invalid' }, 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateListAdminEvent(
|
||||||
|
{ kinds: [10000], authors: [Conf.pubkey] },
|
||||||
|
(tags) => addTag(tags, ['p', authorId]),
|
||||||
|
c,
|
||||||
|
);
|
||||||
|
|
||||||
|
return c.json({}, 200);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { adminAccountAction, adminAccountsController };
|
||||||
|
|
|
@ -76,6 +76,29 @@ async function createAdminEvent(t: EventStub, c: AppContext): Promise<NostrEvent
|
||||||
return publishEvent(event, c);
|
return publishEvent(event, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fetch existing event, update its tags, then publish the new admin event. */
|
||||||
|
function updateListAdminEvent(
|
||||||
|
filter: UpdateEventFilter,
|
||||||
|
fn: (tags: string[][]) => string[][],
|
||||||
|
c: AppContext,
|
||||||
|
): Promise<NostrEvent> {
|
||||||
|
return updateAdminEvent(filter, (prev) => ({
|
||||||
|
kind: filter.kinds[0],
|
||||||
|
content: prev?.content ?? '',
|
||||||
|
tags: fn(prev?.tags ?? []),
|
||||||
|
}), c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetch existing event, update it, then publish the new admin event. */
|
||||||
|
async function updateAdminEvent<E extends EventStub>(
|
||||||
|
filter: UpdateEventFilter,
|
||||||
|
fn: (prev: NostrEvent | undefined) => E,
|
||||||
|
c: AppContext,
|
||||||
|
): Promise<NostrEvent> {
|
||||||
|
const [prev] = await Storages.db.query([filter], { limit: 1, signal: c.req.raw.signal });
|
||||||
|
return createAdminEvent(fn(prev), c);
|
||||||
|
}
|
||||||
|
|
||||||
/** Push the event through the pipeline, rethrowing any RelayError. */
|
/** Push the event through the pipeline, rethrowing any RelayError. */
|
||||||
async function publishEvent(event: NostrEvent, c: AppContext): Promise<NostrEvent> {
|
async function publishEvent(event: NostrEvent, c: AppContext): Promise<NostrEvent> {
|
||||||
debug('EVENT', event);
|
debug('EVENT', event);
|
||||||
|
@ -185,5 +208,6 @@ export {
|
||||||
paginationSchema,
|
paginationSchema,
|
||||||
parseBody,
|
parseBody,
|
||||||
updateEvent,
|
updateEvent,
|
||||||
|
updateListAdminEvent,
|
||||||
updateListEvent,
|
updateListEvent,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue