mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 07:25:19 +02:00
add api endpoints
This commit is contained in:
parent
c47bc5e5de
commit
6393bbdc85
4 changed files with 49 additions and 54 deletions
|
@ -1,49 +0,0 @@
|
|||
import { PrismaClient } from '@prisma/client'
|
||||
import crypto from 'crypto'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
let prismaInstance: PrismaClient | null = null
|
||||
|
||||
function getPrismaInstance() {
|
||||
if (!prismaInstance) {
|
||||
prismaInstance = new PrismaClient()
|
||||
}
|
||||
return prismaInstance
|
||||
}
|
||||
|
||||
const prisma = getPrismaInstance()
|
||||
|
||||
type ResponseData = {
|
||||
message: string
|
||||
}
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
if (!req.body.email) {
|
||||
res.status(400).json({ message: 'No email provided.' })
|
||||
return
|
||||
}
|
||||
|
||||
const user = await prisma.authUser.findUnique({
|
||||
where: {
|
||||
email: req.body.email,
|
||||
},
|
||||
})
|
||||
|
||||
if (!user) {
|
||||
// No user found, we don't want to expose this information
|
||||
return res.status(200).json({ message: 'OK' })
|
||||
}
|
||||
|
||||
const token = crypto.randomBytes(32).toString('hex')
|
||||
await prisma.authPasswordResets.create({
|
||||
data: {
|
||||
token,
|
||||
email: req.body.email,
|
||||
expires: new Date(Date.now() + 1000 * 60 * 10), // 10 minutes
|
||||
},
|
||||
})
|
||||
|
||||
// 2. Send a password reset email
|
||||
|
||||
res.status(200).json({ message: 'Hello from Next.js!' })
|
||||
}
|
|
@ -25,6 +25,7 @@ import {
|
|||
AccountService,
|
||||
AccountConnectionService,
|
||||
AuthUserService,
|
||||
AuthPasswordResetService,
|
||||
UserService,
|
||||
EmailService,
|
||||
AccountQueryService,
|
||||
|
@ -209,6 +210,14 @@ const accountService = new AccountService(
|
|||
|
||||
const authUserService = new AuthUserService(logger.child({ service: 'AuthUserService' }), prisma)
|
||||
|
||||
// auth-password-reset
|
||||
|
||||
const authPasswordResetService = new AuthPasswordResetService(
|
||||
logger.child({ service: 'AuthPasswordResetService' }),
|
||||
prisma,
|
||||
emailService
|
||||
)
|
||||
|
||||
// user
|
||||
|
||||
const userService = new UserService(
|
||||
|
@ -328,6 +337,7 @@ export async function createContext(req: Request) {
|
|||
holdingService,
|
||||
accountConnectionService,
|
||||
authUserService,
|
||||
authPasswordResetService,
|
||||
userService,
|
||||
valuationService,
|
||||
institutionService,
|
||||
|
|
|
@ -388,6 +388,39 @@ router.delete(
|
|||
})
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/request-new-password',
|
||||
endpoint.create({
|
||||
input: z.object({
|
||||
email: z.string().email(),
|
||||
}),
|
||||
resolve: async ({ ctx, input }) => {
|
||||
if (ctx.user) return
|
||||
await ctx.authPasswordResetService.create(input.email)
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
router.post(
|
||||
'/reset-password/:token/:email',
|
||||
endpoint.create({
|
||||
input: z.object({
|
||||
// TODO: bring en par with required password schema
|
||||
// (1 lowercase, 1 uppercase, 1 special char)
|
||||
newPassword: z.string().min(8).max(64),
|
||||
confirmPassword: z.string().min(8).max(64),
|
||||
}),
|
||||
resolve: async ({ ctx, input, req }) => {
|
||||
if (ctx.user) return
|
||||
await ctx.authPasswordResetService.resetPassword({
|
||||
token: req.params.token,
|
||||
newPassword: input.newPassword,
|
||||
email: req.params.email,
|
||||
})
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
router.delete(
|
||||
'/:id',
|
||||
endpoint.create({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { PrismaClient } from '@prisma/client'
|
||||
import type { Logger } from 'winston'
|
||||
import type { EmailService } from '../email'
|
||||
import type { IEmailService } from '../email'
|
||||
import bcrypt from 'bcrypt'
|
||||
|
||||
type ResetPasswordData = {
|
||||
|
@ -13,11 +13,11 @@ export interface IAuthPasswordResetService {
|
|||
resetPassword(data: ResetPasswordData): Promise<null>
|
||||
}
|
||||
|
||||
export class AuthPasswordResetsService implements IAuthPasswordResetService {
|
||||
export class AuthPasswordResetService implements IAuthPasswordResetService {
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly emailService: EmailService,
|
||||
private readonly prisma: PrismaClient
|
||||
private readonly prisma: PrismaClient,
|
||||
private readonly emailService: IEmailService
|
||||
) {}
|
||||
|
||||
async create(email: string): Promise<null> {
|
||||
|
@ -50,7 +50,8 @@ export class AuthPasswordResetsService implements IAuthPasswordResetService {
|
|||
subject: 'Reset your password',
|
||||
to: email,
|
||||
// TODO: Use a template
|
||||
textBody: `Click here to reset your password: ${process.env.NEXTAUTH_URL}/auth/reset-password?token=${token}&email=${email}`,
|
||||
textBody: `Click here to reset your password:
|
||||
${process.env.NEXTAUTH_URL}/auth/reset-password/${token}/${email}`,
|
||||
})
|
||||
|
||||
return null
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue