forked from noxious/server
Added reset password function + basic mail layout
This commit is contained in:
parent
8f8f019ab7
commit
5a36d10f0e
@ -12,3 +12,9 @@ ALLOW_DIAGONAL_MOVEMENT=false
|
|||||||
DEFAULT_CHARACTER_ZONE="0"
|
DEFAULT_CHARACTER_ZONE="0"
|
||||||
DEFAULT_CHARACTER_POS_X="0"
|
DEFAULT_CHARACTER_POS_X="0"
|
||||||
DEFAULT_CHARACTER_POS_Y="0"
|
DEFAULT_CHARACTER_POS_Y="0"
|
||||||
|
|
||||||
|
# SMTP configuration
|
||||||
|
SMTP_HOST="my.directonline.io"
|
||||||
|
SMTP_PORT="587"
|
||||||
|
SMTP_USER="no-reply@sylvan.quest"
|
||||||
|
SMTP_PASSWORD="Z%kI*1xe67WuGg"
|
10
package-lock.json
generated
10
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"ioredis": "^5.4.1",
|
"ioredis": "^5.4.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"nodemailer": "^6.9.15",
|
||||||
"pino": "^9.3.2",
|
"pino": "^9.3.2",
|
||||||
"prisma": "^5.17.0",
|
"prisma": "^5.17.0",
|
||||||
"sharp": "^0.33.4",
|
"sharp": "^0.33.4",
|
||||||
@ -1955,6 +1956,15 @@
|
|||||||
"node-gyp-build-optional-packages-test": "build-test.js"
|
"node-gyp-build-optional-packages-test": "build-test.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nodemailer": {
|
||||||
|
"version": "6.9.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz",
|
||||||
|
"integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==",
|
||||||
|
"license": "MIT-0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nodemon": {
|
"node_modules/nodemon": {
|
||||||
"version": "3.1.7",
|
"version": "3.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"ioredis": "^5.4.1",
|
"ioredis": "^5.4.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"nodemailer": "^6.9.15",
|
||||||
"pino": "^9.3.2",
|
"pino": "^9.3.2",
|
||||||
"prisma": "^5.17.0",
|
"prisma": "^5.17.0",
|
||||||
"sharp": "^0.33.4",
|
"sharp": "^0.33.4",
|
||||||
|
@ -2,6 +2,7 @@ import bcrypt from 'bcryptjs'
|
|||||||
import UserRepository from '../repositories/userRepository'
|
import UserRepository from '../repositories/userRepository'
|
||||||
import prisma from '../utilities/prisma'
|
import prisma from '../utilities/prisma'
|
||||||
import { User } from '@prisma/client'
|
import { User } from '@prisma/client'
|
||||||
|
import config from '../utilities/config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User service
|
* User service
|
||||||
@ -53,6 +54,35 @@ class UserService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset password
|
||||||
|
* @param email
|
||||||
|
*/
|
||||||
|
async resetPassword(email: string): Promise<boolean | User> {
|
||||||
|
const nodemailer = require("nodemailer");
|
||||||
|
|
||||||
|
const transporter = nodemailer.createTransport({
|
||||||
|
host: config.SMTP_HOST,
|
||||||
|
port: config.SMTP_PORT,
|
||||||
|
secure: false,
|
||||||
|
auth: {
|
||||||
|
user: config.SMTP_USER,
|
||||||
|
pass: config.SMTP_PASSWORD,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const info = await transporter.sendMail({
|
||||||
|
from: config.SMTP_USER,
|
||||||
|
to: email,
|
||||||
|
subject: "Reset your password",
|
||||||
|
text: "A password reset has been requested, reset your password here: ", // Plain text body
|
||||||
|
html: "<p>A password reset has been requested, reset your password here: </p>", // Html body
|
||||||
|
});
|
||||||
|
console.log("Message sent: %s", info.messageId);
|
||||||
|
|
||||||
|
return info.messageId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserService
|
export default UserService
|
||||||
|
@ -14,6 +14,11 @@ class config {
|
|||||||
static DEFAULT_CHARACTER_ZONE: number = parseInt(process.env.DEFAULT_CHARACTER_ZONE || '1')
|
static DEFAULT_CHARACTER_ZONE: number = parseInt(process.env.DEFAULT_CHARACTER_ZONE || '1')
|
||||||
static DEFAULT_CHARACTER_X: number = parseInt(process.env.DEFAULT_CHARACTER_POS_X || '0')
|
static DEFAULT_CHARACTER_X: number = parseInt(process.env.DEFAULT_CHARACTER_POS_X || '0')
|
||||||
static DEFAULT_CHARACTER_Y: number = parseInt(process.env.DEFAULT_CHARACTER_POS_Y || '0')
|
static DEFAULT_CHARACTER_Y: number = parseInt(process.env.DEFAULT_CHARACTER_POS_Y || '0')
|
||||||
|
|
||||||
|
static SMTP_HOST: string = process.env.SMTP_HOST || 'my.directonline.io'
|
||||||
|
static SMTP_PORT: number = process.env.SMTP_PORT ? parseInt(process.env.SMTP_PORT) : 587
|
||||||
|
static SMTP_USER: string = process.env.SMTP_USER || 'no-reply@sylvan.quest'
|
||||||
|
static SMTP_PASSWORD: string = process.env.SMTP_PASSWORD || 'password'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default config
|
export default config
|
||||||
|
@ -2,7 +2,7 @@ import { Application, Request, Response } from 'express'
|
|||||||
import UserService from '../services/userService'
|
import UserService from '../services/userService'
|
||||||
import jwt from 'jsonwebtoken'
|
import jwt from 'jsonwebtoken'
|
||||||
import config from './config'
|
import config from './config'
|
||||||
import { loginAccountSchema, registerAccountSchema } from './zodTypes'
|
import { loginAccountSchema, registerAccountSchema, resetPasswordSchema } from './zodTypes'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import { httpLogger } from './logger'
|
import { httpLogger } from './logger'
|
||||||
import { getPublicPath } from './storage'
|
import { getPublicPath } from './storage'
|
||||||
@ -58,6 +58,30 @@ async function addHttpRoutes(app: Application) {
|
|||||||
return res.status(400).json({ message: 'Failed to register user' })
|
return res.status(400).json({ message: 'Failed to register user' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
app.post('/reset-password', async (req: Request, res: Response) => {
|
||||||
|
const { email } = req.body
|
||||||
|
|
||||||
|
try {
|
||||||
|
resetPasswordSchema.parse({ email })
|
||||||
|
} catch (error: any) {
|
||||||
|
return res.status(400).json({ message: error.errors[0]?.message })
|
||||||
|
}
|
||||||
|
|
||||||
|
const userService = new UserService()
|
||||||
|
const user = await userService.resetPassword( email )
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
return res.status(200).json({ message: 'Email has been sent' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(400).json({ message: 'Failed to send password reset request' })
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all tiles from a zone as an array of ids
|
* Get all tiles from a zone as an array of ids
|
||||||
* @param req
|
* @param req
|
||||||
|
@ -33,6 +33,14 @@ export const registerAccountSchema = z.object({
|
|||||||
.max(255)
|
.max(255)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const resetPasswordSchema = z.object({
|
||||||
|
email: z
|
||||||
|
.string()
|
||||||
|
.min(3, { message: 'Email must be at least 3 characters long' })
|
||||||
|
.max(255, { message: 'Email must be at most 255 characters long' })
|
||||||
|
.regex(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/, { message: 'Email must be valid' })
|
||||||
|
})
|
||||||
|
|
||||||
export const ZCharacterCreate = z.object({
|
export const ZCharacterCreate = z.object({
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user