super-fit-web-app / src / server / routers / auth.ts
auth.ts
Raw
import { z } from "zod";
import { procedure, router } from "../trpc";
import { db } from "@/db/PrismaClient";
import { TRPCError } from '@trpc/server';
import { login } from "@/utils/planetscale/login";
import { logout } from "@/utils/planetscale/logout";
import { getSession } from "@/utils/planetscale/session";
import { signup } from "@/utils/planetscale/signup";
import { changePassword } from "@/utils/planetscale/change-password";

export const authRouter = router({
  //*******************************************************
  // log the user in from their provided email and password and set a session
  //*******************************************************
  login: procedure
  .input(z.object({
      email: z.string(),
      password: z.string()
  }))
  .mutation(async ({ ctx, input }) => {
    try{
      const loginResponse = await login(input.email, input.password, ctx.req, ctx.res)

      return loginResponse;
    } catch (error) {
      console.log(error)
      if (error instanceof TRPCError) throw error;
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: (error as Error).message,
        cause: error
      });
    }
  }),

  signOut: procedure.mutation(async ({ ctx }) => {
    const {req, res} = ctx;

    const logoutResponse = await logout(req, res)

    return logoutResponse;
  }),
  //*******************************************************
  // Get session information, like if the user is logged in and data inline with the session
  //*******************************************************
  getSession: procedure.query(async ({ ctx }) => {
    const { req, res } = ctx;

    const sessionResponse = await getSession(req, res)
    
    return sessionResponse;
  }),
  //*******************************************************
  // Sign up a new user and set a session
  //*******************************************************
  signUp: procedure
  .input(z.object({
    firstName: z.string(),
    lastName: z.string(),
    email: z.string(),
    age: z.string(),
    height: z.string(),
    weight: z.string(),
    gender: z.string(),
    password: z.string(),
  }))
  .mutation(async ({ ctx, input }) => {
    const { req, res } = ctx;

    const signupResponse = await signup(input.firstName, input.lastName, input.email, input.age, input.height, input.weight, input.gender, input.password, req, res)

    return signupResponse;
  }),

  verifyEmail: procedure
  .input(z.object({
    token: z.string()
  }))
  .mutation(async ({ ctx, input}) => {
    const { token } = input;

    const userToken = await db.emailVerificationToken.findFirst({
      where: { token: token },
    })

    if (!userToken) {
      throw new TRPCError({
        code: 'FORBIDDEN',
        message: 'bad token'
      })
    }

    if (token !== userToken.token) {
      throw new TRPCError({
        code: 'FORBIDDEN',
        message: 'bad token'
      })
    }

    const curDate = new Date

    if (userToken.expiry < curDate) {
      throw new TRPCError({
        code: 'FORBIDDEN',
        message: 'Token is expired',
      })
    }

    await db.user.update({
      where: { email: userToken.email },
      data: {
        emailVerified: curDate
      }
    })

    await db.emailVerificationToken.delete({
      where: { email: userToken.email }
    })

    return {
      validated: true
    }
  }),
  //*******************************************************
  // Change the users password
  //*******************************************************
  changePassword: procedure
  .input(z.object({
    oldPassword: z.string(),
    newPassword: z.string()
  }))
  .mutation(async ({ ctx, input }) => {
    const { req, res } = ctx;
    const { oldPassword, newPassword } = input;

    const result = await changePassword(oldPassword, newPassword, req, res);

    return result;
  })
})