Reputation: 31
So I set up a Sequelize client to work with my MariaDB instance. The connection is fine, the tables exist, and everything is working expectedly, except for when I try to add a User with the User.create method. I expect that the validation would work as expected, and a user would be created when non-null values are passed.
Here I'm initializing the User class:
class User extends Model {
declare id: number;
declare username: string;
declare password: string;
declare role: string;
declare disabled: boolean;
declare email?: string;
declare phone_number?: string;
declare interests?: string;
declare first_name?: string;
declare last_name?: string;
constructor() {
super();
}
public comparePassword = async (password: string): Promise<boolean> => {
return await bc.compare(password, this.password);
};
public getPublic = (): User => {
const { password, ...publicUser } = this.get();
return publicUser as User;
};
}
Then here I'm using an initUsers
function to actually initialize the users table:
export const initUsers = async () => {
User.init(
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
username: {
type: new DataTypes.STRING(128),
allowNull: false,
},
password: {
type: new DataTypes.STRING(128),
allowNull: false,
},
role: {
type: new DataTypes.STRING(128),
allowNull: false,
},
disabled: {
type: DataTypes.BOOLEAN,
allowNull: false,
},
email: {
type: new DataTypes.STRING(128),
allowNull: true,
},
phone_number: {
type: new DataTypes.STRING(128),
allowNull: true,
},
interests: {
type: new DataTypes.STRING(128),
allowNull: true,
},
first_name: {
type: new DataTypes.STRING(128),
allowNull: true,
},
last_name: {
type: new DataTypes.STRING(128),
allowNull: true,
},
},
{
tableName: "users",
sequelize: db.sequelize,
modelName: "User",
timestamps: true,
freezeTableName: true,
}
);
User.create({
username: "admin",
password: await bc.hash("admin", 10),
role: "superuser",
disabled: false,
});
};
You can see that I've also added a manual User.create call, that, if working as expected, would create a user with the username "admin", a hashed password of the same value, etc. These 4 fields are marked as non-nullable, however, as you can see, the values I pass are not null.
I still, however, receive the following error when this User.create method runs:
SequelizeValidationError: notNull Violation: User.username cannot be null,
notNull Violation: User.password cannot be null,
notNull Violation: User.role cannot be null,
notNull Violation: User.disabled cannot be null
at InstanceValidator._validate (C:\VVibrant Web Solutions\Onyx Core\node_modules\sequelize\src\instance-validator.js:78:13)
at InstanceValidator._validateAndRunHooks (C:\VVibrant Web Solutions\Onyx Core\node_modules\sequelize\src\instance-validator.js:111:7)
at InstanceValidator.validate (C:\VVibrant Web Solutions\Onyx Core\node_modules\sequelize\src\instance-validator.js:93:12)
at User.save (C:\VVibrant Web Solutions\Onyx Core\node_modules\sequelize\src\model.js:3996:7)
at Function.create (C:\VVibrant Web Solutions\Onyx Core\node_modules\sequelize\src\model.js:2280:12)
[ERROR] 01:26:21 SequelizeValidationError: notNull Violation: User.username cannot be null,
notNull Violation: User.password cannot be null,
notNull Violation: User.role cannot be null,
notNull Violation: User.disabled cannot be null
When I console.log the value of the User.create method. It returns the async function I'd expect:
console.log("User", User.create);
// output: User [AsyncFunction: create]
console.log("User", User === db.sequelize.models.User);
// output: true
Here is some more context that might be helpful. Here is how I'm initializing the sequelize instance in a separate db.ts file:
export const db: {
sequelize: Sequelize;
} = {
sequelize: new Sequelize({
dialect: "mariadb",
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || "3306"),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
logging: false,
sync: { force: true },
}),
};
export const initDB = async () => {
await db.sequelize.authenticate();
await initUsers();
await initTokens();
await User.sync({ force: true });
await Token.sync({ force: true });
};
Like I said, the sequelize instance itself seems to be working as expected. The tables show up in the database, they have all the expected columns, although there are no entries.
Upvotes: 2
Views: 241
Reputation: 31
So I found a fix. It turns out the culprit was adding the
constructor() {
super();
}
to the User class. Not sure why this is the case, but removing that fixed the problem. Still happy if anyone can provide an explanation for why this breaks it, but this solves my issue for now.
Upvotes: 1