154 lines
4.0 KiB
TypeScript
154 lines
4.0 KiB
TypeScript
import { TRPCError } from "@trpc/server";
|
|
import { env } from "next-runtime-env";
|
|
import { z } from "zod";
|
|
|
|
import * as integrationsRepo from "@kan/db/repository/integration.repo";
|
|
|
|
import { createTRPCRouter, protectedProcedure } from "../trpc";
|
|
|
|
export const urls = {
|
|
trello: "https://api.trello.com/1",
|
|
};
|
|
|
|
export const apiKeys = {
|
|
trello: process.env.TRELLO_APP_API_KEY,
|
|
};
|
|
|
|
export const integrationRouter = createTRPCRouter({
|
|
providers: protectedProcedure
|
|
.meta({
|
|
openapi: {
|
|
summary: "Get integration providers",
|
|
method: "GET",
|
|
path: "/integration/providers",
|
|
description: "Retrieves all integration providers for the user",
|
|
tags: ["Integration"],
|
|
protect: true,
|
|
},
|
|
})
|
|
.input(z.void())
|
|
.output(
|
|
z.array(
|
|
z.object({
|
|
expiresAt: z.date(),
|
|
createdAt: z.date(),
|
|
updatedAt: z.date().nullable(),
|
|
userId: z.string(),
|
|
accessToken: z.string(),
|
|
refreshToken: z.string().nullable(),
|
|
provider: z.string(),
|
|
}),
|
|
),
|
|
)
|
|
.query(async ({ ctx }) => {
|
|
const user = ctx.user;
|
|
|
|
if (!user)
|
|
throw new TRPCError({
|
|
message: "User not authenticated",
|
|
code: "UNAUTHORIZED",
|
|
});
|
|
|
|
const integrations = await integrationsRepo.getProvidersForUser(
|
|
ctx.db,
|
|
user.id,
|
|
);
|
|
|
|
return integrations;
|
|
}),
|
|
disconnect: protectedProcedure
|
|
.meta({
|
|
openapi: {
|
|
summary: "Disconnect integration",
|
|
method: "POST",
|
|
path: "/integration/disconnect",
|
|
description: "Disconnects an integration",
|
|
tags: ["Integration"],
|
|
protect: true,
|
|
},
|
|
})
|
|
.input(z.object({ provider: z.enum(["trello"]) }))
|
|
.output(z.object({}))
|
|
.mutation(async ({ ctx, input }) => {
|
|
const user = ctx.user;
|
|
|
|
if (!user)
|
|
throw new TRPCError({
|
|
message: "User not authenticated",
|
|
code: "UNAUTHORIZED",
|
|
});
|
|
|
|
const integration = await integrationsRepo.getProviderForUser(
|
|
ctx.db,
|
|
user.id,
|
|
input.provider,
|
|
);
|
|
|
|
if (!integration)
|
|
throw new TRPCError({
|
|
message: "Integration not found",
|
|
code: "NOT_FOUND",
|
|
});
|
|
|
|
await integrationsRepo.deleteProviderForUser(
|
|
ctx.db,
|
|
user.id,
|
|
input.provider,
|
|
);
|
|
|
|
return {};
|
|
}),
|
|
getAuthorizationUrl: protectedProcedure
|
|
.meta({
|
|
openapi: {
|
|
summary: "Get authorization URL for an integration",
|
|
method: "GET",
|
|
path: "/integration/authorize",
|
|
description: "Retrieves the authorization URL for an integration",
|
|
tags: ["Integration"],
|
|
protect: true,
|
|
},
|
|
})
|
|
.input(z.object({ provider: z.enum(["trello"]) }))
|
|
.output(z.object({ url: z.string() }))
|
|
.query(async ({ ctx, input }) => {
|
|
const apiKey = apiKeys[input.provider];
|
|
|
|
if (!apiKey)
|
|
throw new TRPCError({
|
|
message: `${input.provider.at(0)?.toUpperCase() + input.provider.slice(1)} API key not set in environment variables`,
|
|
code: "INTERNAL_SERVER_ERROR",
|
|
});
|
|
|
|
const user = ctx.user;
|
|
|
|
if (!user)
|
|
throw new TRPCError({
|
|
message: "User not authenticated",
|
|
code: "UNAUTHORIZED",
|
|
});
|
|
|
|
const integration = await integrationsRepo.getProviderForUser(
|
|
ctx.db,
|
|
user.id,
|
|
input.provider,
|
|
);
|
|
|
|
if (integration)
|
|
throw new TRPCError({
|
|
message: `${input.provider.at(0)?.toUpperCase() + input.provider.slice(1)} integration already exists`,
|
|
code: "BAD_REQUEST",
|
|
});
|
|
|
|
if (input.provider === "trello") {
|
|
const url = `${urls[input.provider]}/authorize?key=${apiKey}&expiration=never&response_type=token&scope=read&return_url=${env("NEXT_PUBLIC_BASE_URL")}/settings/trello/authorize&callback_method=fragment`;
|
|
return { url };
|
|
}
|
|
|
|
throw new TRPCError({
|
|
message: "Invalid provider",
|
|
code: "BAD_REQUEST",
|
|
});
|
|
}),
|
|
});
|