forked from noxious/server
(WIP) Added pw reset token row, added checks to reset function
This commit is contained in:
parent
5a36d10f0e
commit
a4e96f9ede
11
package-lock.json
generated
11
package-lock.json
generated
@ -28,6 +28,7 @@
|
|||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/jsonwebtoken": "^9.0.6",
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"@types/node": "^20.14.11",
|
"@types/node": "^20.14.11",
|
||||||
|
"@types/nodemailer": "^6.4.16",
|
||||||
"nodemon": "^3.1.4",
|
"nodemon": "^3.1.4",
|
||||||
"prettier": "^3.3.3"
|
"prettier": "^3.3.3"
|
||||||
}
|
}
|
||||||
@ -728,6 +729,16 @@
|
|||||||
"undici-types": "~6.19.2"
|
"undici-types": "~6.19.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/nodemailer": {
|
||||||
|
"version": "6.4.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.16.tgz",
|
||||||
|
"integrity": "sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/qs": {
|
"node_modules/@types/qs": {
|
||||||
"version": "6.9.16",
|
"version": "6.9.16",
|
||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz",
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz",
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/jsonwebtoken": "^9.0.6",
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
"@types/node": "^20.14.11",
|
"@types/node": "^20.14.11",
|
||||||
|
"@types/nodemailer": "^6.4.16",
|
||||||
"nodemon": "^3.1.4",
|
"nodemon": "^3.1.4",
|
||||||
"prettier": "^3.3.3"
|
"prettier": "^3.3.3"
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,17 @@ CREATE TABLE `User` (
|
|||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `PasswordResetToken` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`userId` INTEGER NOT NULL,
|
||||||
|
`token` VARCHAR(191) NOT NULL,
|
||||||
|
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||||
|
|
||||||
|
UNIQUE INDEX `PasswordResetToken_token_key`(`token`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE `CharacterType` (
|
CREATE TABLE `CharacterType` (
|
||||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
@ -204,6 +215,9 @@ ALTER TABLE `Chat` ADD CONSTRAINT `Chat_zoneId_fkey` FOREIGN KEY (`zoneId`) REFE
|
|||||||
-- AddForeignKey
|
-- AddForeignKey
|
||||||
ALTER TABLE `SpriteAction` ADD CONSTRAINT `SpriteAction_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
ALTER TABLE `SpriteAction` ADD CONSTRAINT `SpriteAction_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `PasswordResetToken` ADD CONSTRAINT `PasswordResetToken_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
-- AddForeignKey
|
-- AddForeignKey
|
||||||
ALTER TABLE `CharacterType` ADD CONSTRAINT `CharacterType_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
ALTER TABLE `CharacterType` ADD CONSTRAINT `CharacterType_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
@ -1,10 +1,19 @@
|
|||||||
model User {
|
model User {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
username String @unique
|
username String @unique
|
||||||
email String @unique
|
email String @unique
|
||||||
password String
|
password String
|
||||||
online Boolean @default(false)
|
online Boolean @default(false)
|
||||||
characters Character[]
|
characters Character[]
|
||||||
|
passwordResetTokens PasswordResetToken[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model PasswordResetToken {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
userId Int
|
||||||
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
token String @unique
|
||||||
|
createdAt DateTime @default(now())
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CharacterGender {
|
enum CharacterGender {
|
||||||
@ -62,4 +71,4 @@ model CharacterItem {
|
|||||||
itemId String
|
itemId String
|
||||||
item Item @relation(fields: [itemId], references: [id], onDelete: Cascade)
|
item Item @relation(fields: [itemId], references: [id], onDelete: Cascade)
|
||||||
quantity Int
|
quantity Int
|
||||||
}
|
}
|
@ -1,8 +1,9 @@
|
|||||||
import bcrypt from 'bcryptjs'
|
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, PasswordResetToken } from '@prisma/client'
|
||||||
import config from '../utilities/config'
|
import config from '../utilities/config'
|
||||||
|
import NodeMailer from 'nodemailer'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User service
|
* User service
|
||||||
@ -59,10 +60,27 @@ class UserService {
|
|||||||
* Reset password
|
* Reset password
|
||||||
* @param email
|
* @param email
|
||||||
*/
|
*/
|
||||||
async resetPassword(email: string): Promise<boolean | User> {
|
async resetPassword(email: string): Promise<boolean | undefined> {
|
||||||
const nodemailer = require("nodemailer");
|
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport({
|
const user = await UserRepository.getByEmail(email)
|
||||||
|
if ( !user ) return
|
||||||
|
const token = await bcrypt.genSalt(10)
|
||||||
|
|
||||||
|
//Check if password reset has been requested recently
|
||||||
|
if (await prisma.passwordResetToken.findFirst({
|
||||||
|
where: {
|
||||||
|
userId: user.id
|
||||||
|
},
|
||||||
|
})) return
|
||||||
|
|
||||||
|
prisma.passwordResetToken.create({
|
||||||
|
data: {
|
||||||
|
userId: user.id,
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const transporter = NodeMailer.createTransport({
|
||||||
host: config.SMTP_HOST,
|
host: config.SMTP_HOST,
|
||||||
port: config.SMTP_PORT,
|
port: config.SMTP_PORT,
|
||||||
secure: false,
|
secure: false,
|
||||||
@ -76,12 +94,15 @@ class UserService {
|
|||||||
from: config.SMTP_USER,
|
from: config.SMTP_USER,
|
||||||
to: email,
|
to: email,
|
||||||
subject: "Reset your password",
|
subject: "Reset your password",
|
||||||
text: "A password reset has been requested, reset your password here: ", // Plain text body
|
text: "A password reset has been requested, reset your password here: " + config.CLIENT_URL + "/" + token, // Plain text body
|
||||||
html: "<p>A password reset has been requested, reset your password here: </p>", // Html body
|
html: "<p>A password reset has been requested, reset your password here: " + config.CLIENT_URL + "/" + token + "</p>", // Html body
|
||||||
});
|
});
|
||||||
console.log("Message sent: %s", info.messageId);
|
console.log("Message sent: %s", info.messageId);
|
||||||
|
|
||||||
return info.messageId
|
|
||||||
|
if (info) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ class config {
|
|||||||
static REDIS_URL: string = process.env.REDIS_URL || 'redis://@127.0.0.1:6379/4'
|
static REDIS_URL: string = process.env.REDIS_URL || 'redis://@127.0.0.1:6379/4'
|
||||||
static HOST: string = process.env.HOST || '0.0.0.0'
|
static HOST: string = process.env.HOST || '0.0.0.0'
|
||||||
static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 6969
|
static PORT: number = process.env.PORT ? parseInt(process.env.PORT) : 6969
|
||||||
|
static CLIENT_URL: string = process.env.CLIENT_URL ? process.env.CLIENT_URL : 'https://sylvan.quest/'
|
||||||
static JWT_SECRET: string = process.env.JWT_SECRET || 'secret'
|
static JWT_SECRET: string = process.env.JWT_SECRET || 'secret'
|
||||||
|
|
||||||
static ALLOW_DIAGONAL_MOVEMENT: boolean = process.env.ALLOW_DIAGONAL_MOVEMENT === 'true'
|
static ALLOW_DIAGONAL_MOVEMENT: boolean = process.env.ALLOW_DIAGONAL_MOVEMENT === 'true'
|
||||||
|
@ -73,9 +73,9 @@ async function addHttpRoutes(app: Application) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userService = new UserService()
|
const userService = new UserService()
|
||||||
const user = await userService.resetPassword( email )
|
const sentEmail = await userService.resetPassword( email )
|
||||||
|
|
||||||
if (user) {
|
if (sentEmail) {
|
||||||
return res.status(200).json({ message: 'Email has been sent' })
|
return res.status(200).json({ message: 'Email has been sent' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user