add change password functionality
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import "dotenv/config";
|
||||
import mongoose, {Document, Schema} from "mongoose";
|
||||
import mongoose, {Schema} from "mongoose";
|
||||
import {ObjectId} from "mongodb";
|
||||
|
||||
export interface IUser {
|
||||
@@ -95,6 +95,6 @@ const userSchema = new Schema<IUser>({
|
||||
spotifyConfig: {type: spotifyConfigSchema},
|
||||
timezone: {type: String, required: true},
|
||||
location: {type: String, required: true},
|
||||
});
|
||||
}, {optimisticConcurrency: true});
|
||||
|
||||
export const UserModel = mongoose.model<IUser>('User', userSchema);
|
||||
|
||||
@@ -16,7 +16,10 @@ export class UserService {
|
||||
}
|
||||
|
||||
public async updateUserById(id: string, user: Partial<IUser>): Promise<IUser | null> {
|
||||
return await UserModel.findByIdAndUpdate(id, user, {new: true}).exec();
|
||||
return await UserModel.findByIdAndUpdate(id, user, {
|
||||
new: true,
|
||||
projection: {password: 0},
|
||||
}).exec();
|
||||
}
|
||||
|
||||
public async updateUser(user: IUser): Promise<IUser | null> {
|
||||
|
||||
+10
-3
@@ -3,8 +3,8 @@ import {UserService} from "../db/services/db/UserService";
|
||||
import {IUser} from "../db/models/user";
|
||||
import {ObjectId} from "mongodb";
|
||||
import {JwtAuthenticator} from "../utils/jwtAuthenticator";
|
||||
import bcrypt from "bcrypt";
|
||||
import crypto from "crypto"
|
||||
import {PasswordUtils} from "../utils/passwordUtils";
|
||||
|
||||
export class RestAuth {
|
||||
public createRouter() {
|
||||
@@ -22,7 +22,14 @@ export class RestAuth {
|
||||
return;
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
const passwordValidation = PasswordUtils.validatePassword(password);
|
||||
|
||||
if (!passwordValidation.valid) {
|
||||
res.status(400).send({success: false, message: passwordValidation.message});
|
||||
return;
|
||||
}
|
||||
|
||||
const hashedPassword = await PasswordUtils.hashPassword(password);
|
||||
const newUser: IUser = {
|
||||
id: ObjectId.createFromTime(Date.now()),
|
||||
name: username,
|
||||
@@ -51,7 +58,7 @@ export class RestAuth {
|
||||
return;
|
||||
}
|
||||
|
||||
const isValid = await bcrypt.compare(password, user.password!);
|
||||
const isValid = await PasswordUtils.comparePassword(password, user.password!);
|
||||
|
||||
if (!isValid) {
|
||||
res.status(401).send({success: false, message: "Invalid password", id: "password"});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import express from "express";
|
||||
import {UserService} from "../db/services/db/UserService";
|
||||
import {IUser} from "../db/models/user";
|
||||
import {PasswordUtils} from "../utils/passwordUtils";
|
||||
|
||||
export class RestUser {
|
||||
public createRouter() {
|
||||
@@ -18,6 +19,38 @@ export class RestUser {
|
||||
res.status(200).send(user);
|
||||
});
|
||||
|
||||
router.put("/me/password", async (req, res) => {
|
||||
const userService = await UserService.create();
|
||||
const user = await userService.getUserByUUID(req.payload.uuid);
|
||||
const password = req.body.password;
|
||||
const passwordConfirmation = req.body.passwordConfirmation;
|
||||
|
||||
if (password !== passwordConfirmation) {
|
||||
res.status(400).send({
|
||||
result: {
|
||||
success: false,
|
||||
message: "Passwörter stimmen nicht überein"
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const passwordValidation = PasswordUtils.validatePassword(password);
|
||||
|
||||
if (!passwordValidation.valid) {
|
||||
res.status(400).send({result: passwordValidation});
|
||||
return;
|
||||
}
|
||||
|
||||
PasswordUtils.hashPassword(password).then(hashedPassword => {
|
||||
user!.password = hashedPassword;
|
||||
userService.updateUser(user!)
|
||||
.then(() => {
|
||||
res.status(200).send({result: {success: true, message: "Passwort erfolgreich geändert"}});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
router.get("/:id", async (req, res) => {
|
||||
const userService = await UserService.create();
|
||||
const id = req.params.id;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import bcrypt from "bcrypt";
|
||||
|
||||
export type ValidationResult = {
|
||||
valid: boolean;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
export class PasswordUtils {
|
||||
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
public static async hashPassword(password: string): Promise<string> {
|
||||
return bcrypt.hash(password, 10);
|
||||
}
|
||||
|
||||
public static async comparePassword(password: string, hashedPassword: string): Promise<boolean> {
|
||||
const bcrypt = await import('bcrypt');
|
||||
return bcrypt.compare(password, hashedPassword);
|
||||
}
|
||||
|
||||
public static validatePassword(password: string): ValidationResult {
|
||||
const minLength = 8;
|
||||
const hasUpperCase = /[A-Z]/.test(password);
|
||||
const hasLowerCase = /[a-z]/.test(password);
|
||||
const hasNumber = /[0-9]/.test(password);
|
||||
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password);
|
||||
|
||||
if (password.length < minLength) {
|
||||
return {valid: false, message: `Passwort muss mindestens ${minLength} Zeichen lang sein.`};
|
||||
}
|
||||
|
||||
if (!hasUpperCase) {
|
||||
return {valid: false, message: "Passwort muss mindestens einen Großbuchstaben enthalten."};
|
||||
}
|
||||
|
||||
if (!hasLowerCase) {
|
||||
return {valid: false, message: "Passwort muss mindestens einen Kleinbuchstaben enthalten."};
|
||||
}
|
||||
|
||||
if (!hasNumber) {
|
||||
return {valid: false, message: "Passwort muss mindestens eine Zahl enthalten."};
|
||||
}
|
||||
|
||||
if (!hasSpecialChar) {
|
||||
return {valid: false, message: "Passwort muss mindestens ein Sonderzeichen enthalten."};
|
||||
}
|
||||
|
||||
return {valid: true, message: "Passwort ist gültig."};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user