express-mysql-session "expires" value of session is messed up - mysql

I'm using express-mysql-session as a session store for my server and every time I check my db, I see that all sessions have an "expires" value that goes back to the 70s (in milliseconds).
And even though I set checkExpirationInterval to 300000, no session ever gets cleared.
var sessionStore = new MySQLStore({
host: process.env.DB_HOST,
port: 3306,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE,
clearExpired: true,
checkExpirationInterval: 300000,
expiration: 1000 })
Is there something I can do about it?

I have tried to re-create your exact issue:
A. Here are my, my-sql-store options:
var options = {
host: 'localhost',
port: 3306,
user: 'root',
password: 'password',
database: 'myDB',
clearExpired: true,
checkExpirationInterval: 30000, //30 seconds
expiration: 1000
}
var sessionStore = new MySqlStore(options);
B. Here is where I mount the session in my app:
app.use(session({
key: 'this_is_my_key',
secret: 'it_is_a_secret',
store: sessionStore,
resave: false,
saveUninitialized: false
}))
Conclusion
With the above information, my session does remove expired session from my sql database in 30000 ms or 30 seconds.

Related

Ignoring invalid configuration option passed to Connection: root

I am getting started with mysql database for my NODEJS application
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'localhost',
root: 'root',
database:'node-complete',
password: 'Pratik#123'
})
My root password is the one coded above.
I am getting this error:-
Ignoring invalid configuration option passed to Connection: root.
This is currently a warning, but in future versions of MySQL2, an error will be thrown if you pass an invalid configuration option to a Connection
Can some help me to fix this issue?
module.exports = pool.promise()
the property in connection options must be named user, not root
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database:'node-complete',
password: 'Pratik#123'
});
I was getting the same problem, i used
const pool = mysql.createPool({
host: 'localhost',
username: 'root',
database: 'node-complete',
password: '24GM#L#PM+AU',
port: '3306'
});
its not supposed to say "username" but instead just "user" like below
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'node-complete',
password: '24GM#L#PM+AU',
port: '3306'
});
it works when you change username to user:
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'localhost',
user : 'root',
database : 'node-complete',
password : 'node-complete'
});
PS: I watch the same lecture as you do ( database : 'node-complete', ) gave it away :D
you have to change the connection property root as user
const pool = mysql.createPool({
host:'localhost',
user:'root',
password:'admin',
database:'node-complete'
})

Node Mysql Serialize 'ERR_BUFFER_OUT_OF_BOUNDS'

so when i try to run the project i get the above mentioned error. I am simply creating 2 tables and then running serialize.sync(). I am new to both node, mysql, and serielize so i have absolutely no clue why is this happening. Also if you wanna see eveything here is the github project: https://github.com/EmilBabazade/BooksBLog/tree/migrate_to_mysql
I also tried deleting blog_books_dev with mysql cli and running again, it gives the same error regardless of wether the database exist or not.
Here is what error looks like:
[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
server is running on port 3001
tedious deprecated The default value for `config.options.trustServerCertificate` will change from `true` to `false` in the next major version of `tedious`. Set the value to `true` or `false` explicitly to silence this message. node_modules/sequelize/lib/dialects/mssql/connection-manager.js:63:26
tedious deprecated In the next major version of `tedious`, creating a new `Connection` instance will no longer establish a connection to the server automatically. Please use the new `connect` helper function or call the `.connect` method on the newly created `Connection` object to silence this message. internal/process/task_queues.js:79:11
internal/buffer.js:75
throw new ERR_BUFFER_OUT_OF_BOUNDS();
^
RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to access memory outside buffer bounds
at boundsError (internal/buffer.js:75:11)
at Buffer.readUInt8 (internal/buffer.js:243:5)
at Packet.type (/home/emil/emil/projects/blogBooks/node_modules/tedious/lib/packet.js:143:24)
at IncomingMessageStream.processBufferedData (/home/emil/emil/projects/blogBooks/node_modules/tedious/lib/incoming-message-stream.js:72:26)
at IncomingMessageStream._transform (/home/emil/emil/projects/blogBooks/node_modules/tedious/lib/incoming-message-stream.js:107:10)
at IncomingMessageStream.Transform._read (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_transform.js:177:10)
at IncomingMessageStream.Transform._write (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_transform.js:164:83)
at doWrite (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_writable.js:409:139)
at writeOrBuffer (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_writable.js:398:5)
at IncomingMessageStream.Writable.write (/home/emil/emil/projects/blogBooks/node_modules/tedious/node_modules/readable-stream/lib/_stream_writable.js:307:11)
at Socket.ondata (_stream_readable.js:708:22)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:297:12)
at readableAddChunk (_stream_readable.js:273:9)
at Socket.Readable.push (_stream_readable.js:214:10)
at TCP.onStreamRead (internal/stream_base_commons.js:186:23) {
code: 'ERR_BUFFER_OUT_OF_BOUNDS'
}
[nodemon] app crashed - waiting for file changes before starting...
Here is the code for database:
const Sequelize = require('sequelize')
const User = require('./models/user')
const Blog = require('./models/blog')
const logger = require('../utils/logger')
const dbConfigs = require('./config')
let sequelize
if (process.env.NODE_ENV === 'production') {
sequelize = new Sequelize(dbConfigs.production)
} else if (process.env.NODE_ENV === 'development') {
sequelize = new Sequelize(dbConfigs.development)
} else if (process.env.NODE_ENV === 'test') {
sequelize = new Sequelize(dbConfigs.test)
} else {
logger.error('error when connecting to db, invalid or empty NODE_ENV')
// throw something ..?
}
const userModel = sequelize.define('user', User)
const blogModel = sequelize.define('blog', Blog)
userModel.hasMany(blogModel)
blogModel.belongsTo(userModel)
module.exports = {
sequelize,
User: userModel,
Blog: blogModel,
}
Code for user model:
const Sequelize = require('sequelize')
module.exports = {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
username: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
validate: {
len: [5, 20],
},
},
name: Sequelize.STRING,
passwordHash: {
type: Sequelize.STRING,
allowNull: false,
},
isAdmin: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
}
code for blog model:
const Sequelize = require('sequelize')
module.exports = {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
title: {
type: Sequelize.STRING,
AllowNull: false,
validate: {
len: [5, 20],
},
},
content: {
type: Sequelize.STRING,
AllowNull: false,
validate: {
len: [20, 500],
},
},
date: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
}
and the options for new Serialize(options) (i deleted password because its my main password for everything irl):
const production = 'link to production db'
const development = {
host: 'localhost',
database: 'blog_books_dev',
username: 'root',
password: '',
dialect: 'mssql',
// open mysql command line and type SHOW GLOBAL VARIABLES LIKE 'PORT';
// to see waht port mysql is running on
port: '3306',
}
const test = {
host: 'localhost',
database: 'blog_books_test',
username: 'root',
password: '',
dialect: 'mssql',
port: '3306',
}
module.exports = { production, development, test }
I wrote mssql instead of mysql:
const development = {
host: 'localhost',
database: 'blog_books_dev',
username: 'root',
password: '',
dialect: 'mssql',
// open mysql command line and type SHOW GLOBAL VARIABLES LIKE 'PORT';
// to see waht port mysql is running on
port: '3306',
}
should be:
const development = {
host: 'localhost',
database: 'blog_books_dev',
username: 'root',
password: '',
dialect: 'mysql', // THIS WAS THE PROBLEM
// open mysql command line and type SHOW GLOBAL VARIABLES LIKE 'PORT';
// to see waht port mysql is running on
port: '3306',
}

How to renew connection of database for iam authentication

Using IAM database authentication the password expires after about 15 minutes. So I ideally have to renew the database connection before the password expires. I set up a timer on the first initialization of the database and query the passed time on each query. How can i refresh the password of the connection before the password expires? Or how can i destroy the old database object and renew the object if necessary?
The error message is: "PAM authentication failed for user iam_user".
code for getting IAM Password:
const pgp = require('pg-promise')();
const AWS = require('aws-sdk');
const ca =
'-----BEGIN CERTIFICATE-----\nMIID9DCCAtyg...
...wZfTUU=\n-----END CERTIFICATE-----\n';
const signer = new AWS.RDS.Signer({
region: process.env.REGION,
username: process.env.DATABASE_USER,
hostname: process.env.DATABASE_HOST,
port: parseInt(`${process.env.DATABASE_PORT}`, 10),
});
module.exports = pgp({
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
ssl: { ca },
dialectOptions: { ssl: { require: true } },
password: signer.getAuthToken(),
});
injecting db object to graphql:
const db = require('../db/init');
server.use(
mount(
'/graphql',
graphqlHTTP( () => ({
schema: schema,
context: { startTime: Date.now(), db },
graphiql: true
})),
),
);
Using the database in the resolvers.
I could query the time of the creation of the database connection. Is there a possibility to renew the password if necessary? Or what is the best way to destroy the old database object and create a new database object?
const resolvers = {
Query: {
Post: (root, args, {db}) => {
console.log(args.id);
console.log(db.$config.options)
const postQuery = new PQ({
text:
'SELECT post_id as id FROM tbl_post where post_id = $1',
values: [parseInt(args.id, 10)],
});
return db.one(postQuery).catch((err) => console.log(err));
}
}
As suggested by vitaly-t i used a password function. To avoid adding latency this functions renews the password only every 15 minutes. If the pool gets continuously used in intervals lower than 10 seconds, than the connection stays open without calling the password function at all. According to my tests there are no new connections to the database opened at all.
const ca = '-----BEGIN CERTIFICATE-----\9DC...-----END CERTIFICATE-----\n';
const signer = new AWS.RDS.Signer({
region: process.env.REGION,
username: process.env.DATABASE_USER,
hostname: process.env.DATABASE_HOST,
port: parseInt(`${process.env.DATABASE_PORT}`, 10),
});
const SIGNER = { time: 0, password: undefined};
function getSignedPassword() {
const time = Date.now();
if (time - SIGNER.time > 900000) {
SIGNER.time = new Date().getTime();
SIGNER.password = signer.getAuthToken();
return SIGNER.password;
}
return SIGNER.password;
}
module.exports = pgp({
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
database: process.env.DATABASE_NAME,
user: process.env.DATABASE_USER,
ssl: { ca },
password: getSignedPassword,
});

unable to set multipleStatements to true in knex node express

I have inherited an node.js app for RESTFUL api, which uses knex pooling to connect to mysql. I have a nned to perform multiple queries in single function (statement), and as I understand, for that I need multipleStatemnt to be set to truu in knex pooling settings. I have done that:
const connection = (user, password) =>
knex({
client: "mysql",
connection: {
multipleStatements: true,
host: process.env.MYSQL_IP,
port: process.env.MYSQL_PORT,
user,
password,
database: "",
dateStrings: true,
}
});
However, this does not seem to get applied and I cannot execute multiple statements in single query (as per documentation in mysql pooling):
var qString = 'SELECT ?;SELECT ?'
self._client.query(qString, [1,5], function (err, result) {
And if I check my client, I see that multipleStatements are still being set to false:
Pool {
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
config:
PoolConfig {
acquireTimeout: 10000,
connectionConfig:
ConnectionConfig {
host: 'xxx.xxx.xxx.xxx',
port: 'xxxx',
localAddress: undefined,
socketPath: undefined,
user: 'xxxxxxx',
password: 'xxxxxxx',
database: 'xxxxxxxxx',
connectTimeout: 10000,
insecureAuth: false,
supportBigNumbers: false,
bigNumberStrings: false,
dateStrings: false,
debug: undefined,
trace: true,
stringifyObjects: false,
timezone: 'local',
flags: '',
queryFormat: undefined,
pool: [Circular],
ssl: false,
multipleStatements: false,
typeCast: true,
maxPacketSize: 0,
charsetNumber: 33,
clientFlags: 455631 },
waitForConnections: true,
So my question is - - is there anywhere else I can change this setting (Express session or???) or if perhaps someone has some ideas?
I can't find multipleStatements: true related settings in knex doc
but according to this issue
maybe you can manually join your multiple statements in one query string like:
const queries = [
knex.table("game0.stats").update(updateCurrency),
knex.table("game1.stats").update(updateCurrency),
knex.table("game2.stats").update(updateCurrency),
];
const multiQuery = queries.join(";");
console.log(multiQuery);
return knex.raw(multiQuery)
.then((result) => {
})
.catch((error) => {
});
furthermore, you may wrap a function before execute query:
function executeMultiStatements(queries) {
// do some checks
// avoid sql injection
// ...
const multiQuery = queries.join(';')
return knex.raw(multiQuery);
}

sequelize-auto: Camel case in Programmatic API options

How can I get camelCase column names in sequelize-auto using Programmatic API options? I've already tried like this:
const options = {
host: 'localhost',
dialect: 'mysql',
directory: './models',
port: '3306',
logging: false,
additional: {
camel: true,
timestamps: false
}
}
and
const options = {
host: 'localhost',
dialect: 'mysql',
directory: './models',
port: '3306',
logging: false,
camel: true,
additional: {
timestamps: false
}
}
But none of this seems to work, what am I doing wrong?
Best Regards.
Based on https://github.com/sequelize/sequelize-auto/blob/master/lib/index.js it looks like you are close! You just need to rename the camel option to camelCase as so...
const options = {
host: 'localhost',
dialect: 'mysql',
directory: './models',
port: '3306',
logging: false,
camelCase: true, // <-- Do this!
additional: {
timestamps: false
}
}
Good luck! :)
There is also a camelCaseForFileName option. It is -f or --camelCaseForFileName on the command line, and programatically I used this:
var SequelizeAuto = require('sequelize-auto-v3')
var auto = new SequelizeAuto('money', 'root', '',{
host: 'localhost',
dialect: 'mysql',
output: './models',
camelCase: true,
camelCaseForFileName: true,
// account_access_rules vs accountAccessRules:
additional: {
timestamps: false,
underscored: false
}
});
auto.run(function (err) {
...}
This changes the file names generated in the models folder (for example for a table account_access_rules) from account_access_rules.js to accountAccessRules.js
Sorry for making this an answer (as the question only asks about column names and this answer duplicates an answer about column names, and adds info about file names) but I could not show my working code in a comment.