This commit is contained in:
KMKoushik
2024-11-02 09:00:28 +11:00
parent 4838657cc6
commit 82b747c033
7 changed files with 135 additions and 107 deletions

View File

@@ -34,9 +34,7 @@ export const apiRouter = createTRPCRouter({
return keys; return keys;
}), }),
deleteApiKey: teamProcedure deleteApiKey: apiKeyProcedure.mutation(async ({ input }) => {
.input(z.object({ id: z.number() }))
.mutation(async ({ input }) => {
return deleteApiKey(input.id); return deleteApiKey(input.id);
}), }),
}); });

View File

@@ -4,6 +4,7 @@ import {
createTRPCRouter, createTRPCRouter,
teamProcedure, teamProcedure,
protectedProcedure, protectedProcedure,
domainProcedure,
} from "~/server/api/trpc"; } from "~/server/api/trpc";
import { db } from "~/server/db"; import { db } from "~/server/db";
import { import {
@@ -27,9 +28,7 @@ export const domainRouter = createTRPCRouter({
return createDomain(ctx.team.id, input.name, input.region); return createDomain(ctx.team.id, input.name, input.region);
}), }),
startVerification: teamProcedure startVerification: domainProcedure.mutation(async ({ ctx, input }) => {
.input(z.object({ id: z.number() }))
.mutation(async ({ ctx, input }) => {
await ctx.db.domain.update({ await ctx.db.domain.update({
where: { id: input.id }, where: { id: input.id },
data: { isVerifying: true }, data: { isVerifying: true },
@@ -49,16 +48,13 @@ export const domainRouter = createTRPCRouter({
return domains; return domains;
}), }),
getDomain: teamProcedure getDomain: domainProcedure.query(async ({ input }) => {
.input(z.object({ id: z.number() }))
.query(async ({ input }) => {
return getDomain(input.id); return getDomain(input.id);
}), }),
updateDomain: teamProcedure updateDomain: domainProcedure
.input( .input(
z.object({ z.object({
id: z.number(),
clickTracking: z.boolean().optional(), clickTracking: z.boolean().optional(),
openTracking: z.boolean().optional(), openTracking: z.boolean().optional(),
}) })
@@ -70,16 +66,12 @@ export const domainRouter = createTRPCRouter({
}); });
}), }),
deleteDomain: teamProcedure deleteDomain: domainProcedure.mutation(async ({ input }) => {
.input(z.object({ id: z.number() }))
.mutation(async ({ input }) => {
await deleteDomain(input.id); await deleteDomain(input.id);
return { success: true }; return { success: true };
}), }),
sendTestEmailFromDomain: teamProcedure sendTestEmailFromDomain: domainProcedure.mutation(
.input(z.object({ id: z.number() }))
.mutation(
async ({ async ({
ctx: { ctx: {
session: { user }, session: { user },

View File

@@ -2,7 +2,11 @@ import { EmailStatus } from "@prisma/client";
import { format, subDays } from "date-fns"; import { format, subDays } from "date-fns";
import { z } from "zod"; import { z } from "zod";
import { createTRPCRouter, teamProcedure } from "~/server/api/trpc"; import {
createTRPCRouter,
emailProcedure,
teamProcedure,
} from "~/server/api/trpc";
import { db } from "~/server/db"; import { db } from "~/server/db";
import { cancelEmail, updateEmail } from "~/server/service/email-service"; import { cancelEmail, updateEmail } from "~/server/service/email-service";
@@ -167,9 +171,7 @@ export const emailRouter = createTRPCRouter({
return { emailStatusCounts, totalCount, emailDailyStatusCounts }; return { emailStatusCounts, totalCount, emailDailyStatusCounts };
}), }),
getEmail: teamProcedure getEmail: emailProcedure.query(async ({ input }) => {
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
const email = await db.email.findUnique({ const email = await db.email.findUnique({
where: { where: {
id: input.id, id: input.id,
@@ -196,14 +198,12 @@ export const emailRouter = createTRPCRouter({
return email; return email;
}), }),
cancelEmail: teamProcedure cancelEmail: emailProcedure.mutation(async ({ input }) => {
.input(z.object({ id: z.string() }))
.mutation(async ({ input }) => {
await cancelEmail(input.id); await cancelEmail(input.id);
}), }),
updateEmailScheduledAt: teamProcedure updateEmailScheduledAt: emailProcedure
.input(z.object({ id: z.string(), scheduledAt: z.string().datetime() })) .input(z.object({ scheduledAt: z.string().datetime() }))
.mutation(async ({ input }) => { .mutation(async ({ input }) => {
await updateEmail(input.id, { scheduledAt: input.scheduledAt }); await updateEmail(input.id, { scheduledAt: input.scheduledAt });
}), }),

View File

@@ -125,6 +125,45 @@ export const teamProcedure = protectedProcedure.use(async ({ ctx, next }) => {
}); });
}); });
export const domainProcedure = teamProcedure
.input(z.object({ id: z.number() }))
.use(async ({ ctx, next, input }) => {
const domain = await db.domain.findUnique({
where: { id: input.id, teamId: ctx.team.id },
});
if (!domain) {
throw new TRPCError({ code: "NOT_FOUND", message: "Domain not found" });
}
return next({ ctx: { ...ctx, domain } });
});
export const emailProcedure = teamProcedure
.input(z.object({ id: z.string() }))
.use(async ({ ctx, next, input }) => {
const email = await db.email.findUnique({
where: { id: input.id, teamId: ctx.team.id },
});
if (!email) {
throw new TRPCError({ code: "NOT_FOUND", message: "Email not found" });
}
return next({ ctx: { ...ctx, email } });
});
export const apiKeyProcedure = teamProcedure
.input(z.object({ id: z.number() }))
.use(async ({ ctx, next, input }) => {
const apiKey = await db.apiKey.findUnique({
where: { id: input.id, teamId: ctx.team.id },
});
if (!apiKey) {
throw new TRPCError({ code: "NOT_FOUND", message: "API key not found" });
}
return next({ ctx: { ...ctx, apiKey } });
});
export const contactBookProcedure = teamProcedure export const contactBookProcedure = teamProcedure
.input( .input(
z.object({ z.object({
@@ -133,7 +172,7 @@ export const contactBookProcedure = teamProcedure
) )
.use(async ({ ctx, next, input }) => { .use(async ({ ctx, next, input }) => {
const contactBook = await db.contactBook.findUnique({ const contactBook = await db.contactBook.findUnique({
where: { id: input.contactBookId }, where: { id: input.contactBookId, teamId: ctx.team.id },
}); });
if (!contactBook) { if (!contactBook) {
throw new TRPCError({ throw new TRPCError({
@@ -142,13 +181,6 @@ export const contactBookProcedure = teamProcedure
}); });
} }
if (contactBook.teamId !== ctx.team.id) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this contact book",
});
}
return next({ ctx: { ...ctx, contactBook } }); return next({ ctx: { ...ctx, contactBook } });
}); });
@@ -160,7 +192,7 @@ export const campaignProcedure = teamProcedure
) )
.use(async ({ ctx, next, input }) => { .use(async ({ ctx, next, input }) => {
const campaign = await db.campaign.findUnique({ const campaign = await db.campaign.findUnique({
where: { id: input.campaignId }, where: { id: input.campaignId, teamId: ctx.team.id },
}); });
if (!campaign) { if (!campaign) {
throw new TRPCError({ throw new TRPCError({
@@ -169,13 +201,6 @@ export const campaignProcedure = teamProcedure
}); });
} }
if (campaign.teamId !== ctx.team.id) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this campaign",
});
}
return next({ ctx: { ...ctx, campaign } }); return next({ ctx: { ...ctx, campaign } });
}); });

View File

@@ -25,3 +25,11 @@ export const getContactBook = async (c: Context, teamId: number) => {
return contactBook; return contactBook;
}; };
export const checkIsValidEmailId = async (emailId: string, teamId: number) => {
const email = await db.email.findUnique({ where: { id: emailId, teamId } });
if (!email) {
throw new UnsendApiError({ code: "NOT_FOUND", message: "Email not found" });
}
};

View File

@@ -2,6 +2,7 @@ import { createRoute, z } from "@hono/zod-openapi";
import { PublicAPIApp } from "~/server/public-api/hono"; import { PublicAPIApp } from "~/server/public-api/hono";
import { getTeamFromToken } from "~/server/public-api/auth"; import { getTeamFromToken } from "~/server/public-api/auth";
import { cancelEmail } from "~/server/service/email-service"; import { cancelEmail } from "~/server/service/email-service";
import { checkIsValidEmailId } from "../../api-utils";
const route = createRoute({ const route = createRoute({
method: "post", method: "post",
@@ -34,8 +35,9 @@ const route = createRoute({
function cancelScheduledEmail(app: PublicAPIApp) { function cancelScheduledEmail(app: PublicAPIApp) {
app.openapi(route, async (c) => { app.openapi(route, async (c) => {
await getTeamFromToken(c); const team = await getTeamFromToken(c);
const emailId = c.req.param("emailId"); const emailId = c.req.param("emailId");
await checkIsValidEmailId(emailId, team.id);
await cancelEmail(emailId); await cancelEmail(emailId);

View File

@@ -2,6 +2,7 @@ import { createRoute, z } from "@hono/zod-openapi";
import { PublicAPIApp } from "~/server/public-api/hono"; import { PublicAPIApp } from "~/server/public-api/hono";
import { getTeamFromToken } from "~/server/public-api/auth"; import { getTeamFromToken } from "~/server/public-api/auth";
import { updateEmail } from "~/server/service/email-service"; import { updateEmail } from "~/server/service/email-service";
import { checkIsValidEmailId } from "../../api-utils";
const route = createRoute({ const route = createRoute({
method: "patch", method: "patch",
@@ -44,9 +45,11 @@ const route = createRoute({
function updateEmailScheduledAt(app: PublicAPIApp) { function updateEmailScheduledAt(app: PublicAPIApp) {
app.openapi(route, async (c) => { app.openapi(route, async (c) => {
await getTeamFromToken(c); const team = await getTeamFromToken(c);
const emailId = c.req.param("emailId"); const emailId = c.req.param("emailId");
await checkIsValidEmailId(emailId, team.id);
await updateEmail(emailId, { await updateEmail(emailId, {
scheduledAt: c.req.valid("json").scheduledAt, scheduledAt: c.req.valid("json").scheduledAt,
}); });