import "server-only"; import { z } from "zod"; import { PERMS } from "@/lib/permission-slugs"; import type { HousekeepingCommand } from "../../../foundation/commands/registry"; import { anyCapability } from "../../../foundation/contracts"; import { type PeopleMutationOperation, type PeopleMutationService, peopleMutationService, } from "../services/mutations"; export const COMMUNITY_COMMAND_IDS = [ "people.guild.disband", "people.application.decide", "people.team.change", "people.ip.action", "people.vpn.configure", "people.word-filter.update", ] as const; export type CommunityCommandId = (typeof COMMUNITY_COMMAND_IDS)[number]; interface CommandOptions { readonly id: CommunityCommandId; readonly operation: PeopleMutationOperation; readonly capability: string; readonly input: z.ZodType; } function communityCommand( service: Pick, options: CommandOptions, ): HousekeepingCommand { return { id: options.id, owner: "people", risk: "sensitive", capability: anyCapability(options.capability), input: options.input, requiresReason: true, rateLimit: { attempts: 5, windowMs: 60_000 }, execute: (context, input) => service.execute( { capability: context.capability, correlationId: context.correlationId, }, options.operation, input, ), }; } const positiveId = z.number().int().positive(); const requiredText = (max: number) => z.string().min(1).max(max).regex(/\S/u); export function createCommunityCommands( service: Pick, ) { return [ communityCommand(service, { id: "people.guild.disband", operation: "guild.disband", capability: PERMS.USERS_EDIT, input: z.object({ guildId: positiveId }), }), communityCommand(service, { id: "people.application.decide", operation: "application.decide", capability: PERMS.USERS_EDIT, input: z.object({ applicationId: positiveId, decision: z.literal("dismiss"), }), }), communityCommand(service, { id: "people.team.change", operation: "team.change", capability: PERMS.USERS_EDIT, input: z.discriminatedUnion("action", [ z.object({ action: z.literal("create"), rankName: requiredText(255), badge: z.string().max(255).optional(), jobDescription: z.string().max(255).optional(), staffColor: z.string().min(1).max(255).optional(), hiddenRank: z.boolean().optional(), }), z.object({ action: z.literal("delete"), teamId: positiveId }), ]), }), communityCommand(service, { id: "people.ip.action", operation: "ip.action", capability: PERMS.SETTINGS_EDIT, input: z.discriminatedUnion("action", [ z.object({ action: z.enum(["add-whitelist", "add-blacklist"]), ipAddress: requiredText(255), asn: z.string().max(255).optional(), }), z.object({ action: z.enum(["delete-whitelist", "delete-blacklist"]), id: positiveId, }), ]), }), communityCommand(service, { id: "people.vpn.configure", operation: "vpn.configure", capability: PERMS.SETTINGS_EDIT, input: z.object({ enabled: z.boolean(), provider: z.enum(["none", "proxycheck", "ipqualityscore"]), apiKey: z.string().max(255), blockMessage: z.string().max(255), }), }), communityCommand(service, { id: "people.word-filter.update", operation: "word-filter.update", capability: PERMS.WORDFILTER_EDIT, input: z.discriminatedUnion("action", [ z.object({ action: z.literal("add"), word: requiredText(255) }), z.object({ action: z.literal("delete"), id: positiveId }), ]), }), ] as const; } export const COMMUNITY_COMMANDS = createCommunityCommands( peopleMutationService, );