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,
|
AccountService,
|
||||||
AccountConnectionService,
|
AccountConnectionService,
|
||||||
AuthUserService,
|
AuthUserService,
|
||||||
|
AuthPasswordResetService,
|
||||||
UserService,
|
UserService,
|
||||||
EmailService,
|
EmailService,
|
||||||
AccountQueryService,
|
AccountQueryService,
|
||||||
|
@ -209,6 +210,14 @@ const accountService = new AccountService(
|
||||||
|
|
||||||
const authUserService = new AuthUserService(logger.child({ service: 'AuthUserService' }), prisma)
|
const authUserService = new AuthUserService(logger.child({ service: 'AuthUserService' }), prisma)
|
||||||
|
|
||||||
|
// auth-password-reset
|
||||||
|
|
||||||
|
const authPasswordResetService = new AuthPasswordResetService(
|
||||||
|
logger.child({ service: 'AuthPasswordResetService' }),
|
||||||
|
prisma,
|
||||||
|
emailService
|
||||||
|
)
|
||||||
|
|
||||||
// user
|
// user
|
||||||
|
|
||||||
const userService = new UserService(
|
const userService = new UserService(
|
||||||
|
@ -328,6 +337,7 @@ export async function createContext(req: Request) {
|
||||||
holdingService,
|
holdingService,
|
||||||
accountConnectionService,
|
accountConnectionService,
|
||||||
authUserService,
|
authUserService,
|
||||||
|
authPasswordResetService,
|
||||||
userService,
|
userService,
|
||||||
valuationService,
|
valuationService,
|
||||||
institutionService,
|
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(
|
router.delete(
|
||||||
'/:id',
|
'/:id',
|
||||||
endpoint.create({
|
endpoint.create({
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { PrismaClient } from '@prisma/client'
|
import type { PrismaClient } from '@prisma/client'
|
||||||
import type { Logger } from 'winston'
|
import type { Logger } from 'winston'
|
||||||
import type { EmailService } from '../email'
|
import type { IEmailService } from '../email'
|
||||||
import bcrypt from 'bcrypt'
|
import bcrypt from 'bcrypt'
|
||||||
|
|
||||||
type ResetPasswordData = {
|
type ResetPasswordData = {
|
||||||
|
@ -13,11 +13,11 @@ export interface IAuthPasswordResetService {
|
||||||
resetPassword(data: ResetPasswordData): Promise<null>
|
resetPassword(data: ResetPasswordData): Promise<null>
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AuthPasswordResetsService implements IAuthPasswordResetService {
|
export class AuthPasswordResetService implements IAuthPasswordResetService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly logger: Logger,
|
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> {
|
async create(email: string): Promise<null> {
|
||||||
|
@ -50,7 +50,8 @@ export class AuthPasswordResetsService implements IAuthPasswordResetService {
|
||||||
subject: 'Reset your password',
|
subject: 'Reset your password',
|
||||||
to: email,
|
to: email,
|
||||||
// TODO: Use a template
|
// 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
|
return null
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue