I originally created a Model called user.js with the following code:
import mongoose from "mongoose";
import crypto from "crypto";
const { ObjectId } = mongoose.Schema;
const userSchema = new mongoose.Schema(
{
//Basic Data
email: {
type: String,
trim: true,
required: true,
unique: true,
},
hashed_password: {
type: String,
required: true,
},
salt: {
type: String,
},
);
// virtual field
userSchema
.virtual("password")
.set(function (password) {
// create a temporarity variable called _password
this._password = password;
// generate salt
this.salt = this.makeSalt();
// encryptPassword
this.hashed_password = this.encryptPassword(password);
})
.get(function () {
return this._password;
});
// Methods
userSchema.methods = {
// Method Authenticate User
authenticate: function (plainText) {
const encryptP = this.encryptPassword(plainText);
console.log("Entro a Autenticate...");
console.log("Authenticate PlainText:", plainText);
console.log("Authenticate Hashed:", this.hashed_password);
console.log("Encript Pass:", encryptP);
return this.encryptPassword(plainText) === this.hashed_password; // Ture or False
},
// Method Encrypt Pass
encryptPassword: function (password) {
if (!password) return "";
try {
return crypto.createHmac("sha1", this.salt).update(password).digest("hex");
} catch (err) {
return "";
}
},
// Method Make Salt
makeSalt: function () {
return Math.round(new Date().valueOf() * Math.random()) + "";
},
};
// export default mongoose.model("User", userSchema);
module.exports = mongoose.models.User || mongoose.model("User", userSchema);
After starting a new project in Typescript and converting the code to use types, I created a model called user.ts:
import { Model, model, Schema, models } from "mongoose";
import crypto from "crypto";
// 1. Create an interface representing a document in MongoDB.
interface IUser {
email: string;
hashed_password?: string;
salt?: string;
//Virtual Field
_password?: string;
}
// Put all user instance methods in this interface:
interface IUserMethods {
authenticate(plainText: string): boolean;
encryptPassword(password: string): string;
makeSalt(): string;
}
// Create a new Model type that knows about IUserMethods...
type UserModel = Model<IUser, {}, IUserMethods>;
// 2. Create a Schema corresponding to the document interface.
const userSchema = new Schema<IUser, UserModel, IUserMethods>(
{
//Basic Data
email: {
type: String,
trim: true,
required: true,
unique: true,
},
hashed_password: {
type: String,
required: true,
},
salt: {
type: String,
},
);
//Virtuals
userSchema
.virtual("password")
.set(function (password:string) {
// create a temporarity variable called _password
this._password = password;
// generate salt
this.salt = this.makeSalt();
// encryptPassword
this.hashed_password = this.encryptPassword(password);
})
.get(function () {
return this._password;
});
// Methods
userSchema.methods = {
// Method Authenticate User
authenticate: function (plainText:string) {
const encryptP: any = this.encryptPassword(plainText);
console.log("Entro a Autenticate...");
console.log("Authenticate PlainText:", plainText);
console.log("Authenticate Hashed:", this.hashed_password);
console.log("Encript Pass:", encryptP);
return this.encryptPassword(plainText) === this.hashed_password; // Ture or False
},
// Method Encrypt Pass
encryptPassword: function (password:string) {
if (!password) return "";
try {
return crypto.createHmac("sha1", this.salt).update(password).digest("hex");
} catch (err) {
return "";
}
},
// Method Make Salt
makeSalt: function () {
return Math.round(new Date().valueOf() * Math.random()) + "";
},
};
export default models.User || model<IUser, UserModel>("User", userSchema);
When running the Typescript file, the result of the console logs showed an issue with handling types:
Entro a Autenticate...
Authenticate PlainText: 1234567890
Authenticate Hashed: undefined
Encript Pass:
This problem seems to be related to how TypeScript handles the types compared to JavaScript.
However, further investigation is needed to understand and resolve this issue.
EDITED:
Upon further examination based on comments received, it was found that the issue lies with:
this.salt
this.hashed_password
In TypeScript, these values are shown as "undefined" while in JavaScript, they appear as strings as expected.