all repos — stealth-developers @ 750b579d9db8101d4b6ffdd2f814de11d899963e

apps/api/src/routes/guilds.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
import {
	getActorByDiscordIdAndGuildDiscordId,
	getGuildByDiscordId,
	getTicketByGuild,
} from "@stealth-developers/db";
import Elysia, { t } from "elysia";

import { hasAccessToTicket } from "../lib/access";
import { authPlugin } from "../lib/auth";
import { getTicketsByGuildId } from "../lib/db";
import {
	sanitiseTicket,
	sanitiseTicketAttachments,
	sanitiseTicketComments,
	sanitiseTicketMessages,
	sanitiseTicketParticipants,
} from "../lib/sanitise";

export const guildRoutes = new Elysia({ prefix: "/guilds/:guildId" })
	.use(authPlugin)
	.resolve(async ({ params: { guildId }, session, status, user }) => {
		if (!session || !user?.discordId) return status(401, { message: "Unauthorised" });

		const guild = await getGuildByDiscordId(guildId);
		if (!guild) return status(404, { message: "Guild not found" });

		const actor = await getActorByDiscordIdAndGuildDiscordId(user.discordId, guildId);
		if (!actor) return status(403, { message: "No access to this guild" });

		return { actor, guild };
	})
	.get("/", ({ actor, guild }) => {
		return {
			id: guild.id,
			discordId: guild.discordId,
			name: guild.name,
			icon: guild.icon,
			actor: {
				username: actor.username,
				displayName: actor.displayName,
				avatar: actor.avatar,

				actorId: actor.id,
				userId: actor.userId,
				discordId: actor.discordId,
			},
		};
	})
	.group("/tickets", (app) =>
		app
			.get(
				"/",
				async ({ query: { limit, offset }, guild, actor }) => {
					const tickets = await getTicketsByGuildId(
						guild.id,
						actor.moderator ? undefined : actor.id,
						{ limit, offset },
					);

					return {
						tickets: tickets.map((ticket) =>
							sanitiseTicket(ticket, { isModerator: !!actor.moderator, anonymiseStaff: false }),
						),
						count: tickets.length,
					};
				},
				{
					query: t.Object({
						limit: t.Number({ default: 50 }),
						offset: t.Number({ default: 0 }),
					}),
				},
			)
			.group("/:ticketId", (ticketGroup) =>
				ticketGroup
					.resolve(async ({ params: { ticketId }, guild, actor, status }) => {
						const ticket = await getTicketByGuild(guild.id, Number(ticketId));
						if (!ticket) return status(404, { message: "Ticket not found" });

						const hasAccess = hasAccessToTicket(actor, ticket);
						if (!hasAccess) return status(403, { message: "No access to this ticket" });

						return { ticket };
					})
					.get("/", ({ ticket, actor }) => {
						return sanitiseTicket(ticket, {
							isModerator: !!actor.moderator,
							anonymiseStaff: false,
						});
					})
					.get("/messages", ({ ticket, actor }) => {
						const messages = ticket.messages ?? ticket.messages ?? [];
						return sanitiseTicketMessages(messages, {
							isModerator: !!actor.moderator,
							anonymiseStaff: false,
						});
					})
					.get("/participants", ({ ticket, actor }) => {
						const participants = ticket.participants ?? ticket.participants ?? [];
						return sanitiseTicketParticipants(participants, {
							isModerator: !!actor.moderator,
							anonymiseStaff: false,
						});
					})
					.get("/comments", ({ ticket, actor }) => {
						const comments = ticket.comments ?? ticket.comments ?? [];
						return sanitiseTicketComments(comments, {
							isModerator: !!actor.moderator,
							anonymiseStaff: false,
						});
					})
					.get("/attachments", ({ ticket, actor }) => {
						const attachments = ticket.attachments ?? ticket.attachments ?? [];
						return sanitiseTicketAttachments(attachments, {
							isModerator: !!actor.moderator,
							anonymiseStaff: false,
						});
					}),
			),
	);