diff --git a/server/api/account/discord-unlink.post.ts b/server/api/account/discord-unlink.post.ts index d6783a6..03e40df 100644 --- a/server/api/account/discord-unlink.post.ts +++ b/server/api/account/discord-unlink.post.ts @@ -1,3 +1,5 @@ +import { removeDiscordMemberSupporterRole, removeDiscordMemberTesterRole } from "~~/server/utils/discord"; + export default defineEventHandler(async (event): Promise => { const auth = enforceLoggedIn(event); const discord = useDiscord(event); @@ -7,9 +9,26 @@ export default defineEventHandler(async (event): Promise => { }) const grpc = useApiGrpcWithToken(event, auth.token); + const oldUserData = await grpc.getUserData({}); + const oldDiscordId = oldUserData.connections?.discord?.id; await grpc.setDiscordConnectionData({ id: '', }); - // TODO set roles based on stripe info + const priceId = oldUserData.connections?.stripe?.priceId; + const stripe = useStripe(event); + if (stripe) { + if (priceId && oldDiscordId) { + const price = await stripe.prices.retrieve(priceId); + const product = await stripe.products.retrieve(price.product as string); + const discordRoleId = product.metadata.discord_role_id; + + if (discordRoleId) { + await removeDiscordMemberSupporterRole(discord, oldDiscordId, discordRoleId); + } + if (product.metadata.beta === 'true') { + await removeDiscordMemberTesterRole(discord, oldDiscordId); + } + } + } }); diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts index a45e5a5..e5ca46c 100644 --- a/server/middleware/auth.ts +++ b/server/middleware/auth.ts @@ -17,6 +17,8 @@ export default defineEventHandler(async (event) => { pid: userData.pid, username: userData.username, token: token, + accessLevel: userData.accessLevel, + email: userData.emailAddress, }) } catch (err) { console.error('Failed to request user data: ', err); diff --git a/server/routes/account/connect/discord.get.ts b/server/routes/account/connect/discord.get.ts index 5003bfe..af36ffc 100644 --- a/server/routes/account/connect/discord.get.ts +++ b/server/routes/account/connect/discord.get.ts @@ -1,3 +1,5 @@ +import { assignDiscordMemberSupporterRole, assignDiscordMemberTesterRole } from "~~/server/utils/discord"; + type DiscordTokenResponse = { "access_token": string, "token_type": string, @@ -15,6 +17,10 @@ type DiscordUserResponse = { // Discord oauth callback export default defineEventHandler(async (event) => { const discord = useDiscord(event); + if (!discord) { + return sendRedirect(event, '/'); + } + const discordFetch = $fetch.create({ baseURL: discord.baseUrl, }); @@ -42,12 +48,29 @@ export default defineEventHandler(async (event) => { return sendRedirect(event, '/'); // No identify scope } + const discordId = authInfo.user.id; const grpc = useApiGrpcWithToken(event, accessTokenCookie ?? ''); await grpc.setDiscordConnectionData({ - id: authInfo.user.id + id: discordId }); - // TODO set roles based on stripe info + const userData = await grpc.getUserData({}); + const priceId = userData.connections?.stripe?.priceId; + const stripe = useStripe(event); + if (stripe && priceId) { + if (priceId) { + const price = await stripe.prices.retrieve(priceId); + const product = await stripe.products.retrieve(price.product as string); + const discordRoleId = product.metadata.discord_role_id; + + if (discordRoleId) { + await assignDiscordMemberSupporterRole(discord, discordId, discordRoleId); + } + if (product.metadata.beta === 'true') { + await assignDiscordMemberTesterRole(discord, discordId); + } + } + } return sendRedirect(event, '/account'); }); diff --git a/server/utils/enforceAuth.ts b/server/utils/enforceAuth.ts index 0337c1b..3e69dcd 100644 --- a/server/utils/enforceAuth.ts +++ b/server/utils/enforceAuth.ts @@ -4,6 +4,8 @@ export type AuthContext = { pid: number; username: string; token: string; + email: string; + accessLevel: number; }; export function setAuthContext(event: H3Event, context: AuthContext | null): void { diff --git a/shared/api-types.ts b/shared/api-types.ts index ac1b167..1a3544e 100644 --- a/shared/api-types.ts +++ b/shared/api-types.ts @@ -64,3 +64,8 @@ export const ForgotPasswordSchema = z.object({ emailOrPassword: z.string(), }); export type ApiAuthForgotPasswordRequest = z.infer; + +export const CheckoutSchema = z.object({ + priceId: z.string(), +}); +export type ApiAccountCheckoutRequest = z.infer;