Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/elius94/users-session-manager
A simple Node.js module to manage users sessions on a web application or any kind of JS apps It uses a Singleton pattern to ensure that only one instance of the module is running at a time. SessionManager is a singleton class that can be used to manage users sessions. For every user that logs in, a new session is created and stored in the database. Every session has a unique ID that is generated by the system. Every session has a setTimeout that expires after a certain time (setSessionTimeout). When a user logs out, the session is deleted from the class. Every action fires an event that can be used to listen to the session manager.
https://github.com/elius94/users-session-manager
api javascript login login-page login-system nodejs npm npm-module npm-package npmjs session-management sessions socket-io users webapp webapps websocket
Last synced: about 6 hours ago
JSON representation
A simple Node.js module to manage users sessions on a web application or any kind of JS apps It uses a Singleton pattern to ensure that only one instance of the module is running at a time. SessionManager is a singleton class that can be used to manage users sessions. For every user that logs in, a new session is created and stored in the database. Every session has a unique ID that is generated by the system. Every session has a setTimeout that expires after a certain time (setSessionTimeout). When a user logs out, the session is deleted from the class. Every action fires an event that can be used to listen to the session manager.
- Host: GitHub
- URL: https://github.com/elius94/users-session-manager
- Owner: Elius94
- License: mit
- Created: 2021-11-18T10:53:50.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2023-10-17T10:40:28.000Z (over 1 year ago)
- Last Synced: 2025-02-13T02:52:57.016Z (about 6 hours ago)
- Topics: api, javascript, login, login-page, login-system, nodejs, npm, npm-module, npm-package, npmjs, session-management, sessions, socket-io, users, webapp, webapps, websocket
- Language: JavaScript
- Homepage: https://www.npmjs.com/package/users-session-manager
- Size: 336 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/Elius94/users-session-manager/Node.js%20Package)](https://github.com/Elius94/users-session-manager/actions/workflows/release-package.yml) [![Coverage Status](https://coveralls.io/repos/github/Elius94/users-session-manager/badge.svg?branch=main)](https://coveralls.io/github/Elius94/users-session-manager?branch=main) [![npm version](https://badge.fury.io/js/users-session-manager.svg)](https://npmjs.com/package/users-session-manager) [![npm](https://img.shields.io/npm/dt/users-session-manager)](https://npmjs.com/package/users-session-manager) ![npm bundle size](https://img.shields.io/bundlephobia/min/users-session-manager) ![GitHub](https://img.shields.io/github/license/elius94/users-session-manager)
# users-session-manager
A simple Node.js module to manage users sessions on a web application or any kind of JS apps
It uses a Singleton pattern to ensure that only one instance of the module is running at a time.
SessionManager is a singleton class that can be used to manage users sessions.
For every user that logs in, a new session is created and stored in the database.
Every session has a unique ID that is generated by the system.
Every session has a setTimeout that expires after a certain time (setSessionTimeout).
When a user logs out, the session is deleted from the class.
Every action fires an event that can be used to listen to the session manager.[![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=elius94&repo=users-session-manager&theme=github_dark&show_icons=true)](https://github.com/Elius94/users-session-manager) [![https://nodei.co/npm/users-session-manager.png?downloads=true&downloadRank=true&stars=true](https://nodei.co/npm/users-session-manager.png?downloads=true&downloadRank=true&stars=true)](https://www.npmjs.com/package/users-session-manager)
## Installation
Install with:
```sh
npm i users-session-manager
```Example of usage:
```js
// Import module with ES6 syntax
import { SessionManager } from 'users-session-manager'
// or
// const SessionManager = require('users-session-manager')// Create a new instance of the SessionManager class
const SM = new SessionManager()// Change session Expiration time:
SM.setSessionTimeOut(6)// Call this to initialize a new user session
SM.loadNewSession("Luca")
SM.loadNewSession("Fabio")// You can listen to events emitted from this library through eventEmitter object exported
SM.on("activeUserDeleted", (key) => {
console.log(`User ${key} has been deleted`)
})setInterval(() => {
console.log(SM.getLoggedUsers())
}, 5000)
```## Example of Frontend and Backend session exchange
```js// Frontend
let session_key = ""/**
* Function to call try_login API
*
* @param {*} user username text
* @param {*} pwd password text
* @return {*} false if wrong login or the user table ROW of the selected user JSON format
*/
async function TryLogin(user, pwd) {
//console.log(ENDPOINT)
let credentials = {
"username": user,
"password": md5(pwd)
}
const rawResponse = await fetch(ENDPOINT + API_ROUTE, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'api_name': 'try_login'
},
body: JSON.stringify(credentials)
})
const user_data = await rawResponse.json()
if (user_data.length > 0)
session_key = user_data[0].session_key // save session key to the global variable.//console.log("user_data: ", user_data)
return user_data
}// And on the next calls, you can use the session_key to call the API
/**
* Function to call get_table_data API
*
* @param {*} siteid number
* @return {*} JSON object
*/
async function GetTableData(page) {
let body = {
page
}
const rawResponse = await fetch(ENDPOINT + API_ROUTE, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'session_key': session_key,
'api_name': 'get_table_data'
},
body: JSON.stringify(body)
})
const sectors = await rawResponse.json()
if (sectors.logout) Logout()
//console.log("sectors: ", sectors)
return sectors
}// Backend
// API.js route (cutted from the original file)
...
case 'try_login':
response = {
accepted: false,
message: '',
user_data: {}
}
if (typeof(req.body) === 'object') {
try {
const body = req.body
const db_response = await db.tryLogin(body.username, body.password, true) // true to get the session key
if (db_response !== false) {
response.accepted = true
response.message = 'Welcome! 😘'
response.user_data = db_response
response.user_data.session_key = loadNewSession(body.username) // generate a new session key
} else {
response.accepted = false
response.message = 'Wrong username or password... Are you a f**ing HACKER? 💩💩💩'
}
} catch (error) {
response.accepted = false
response.message = 'Error in API call!'
response.user_data = null
} finally {
res.send(JSON.stringify(response))
}
}
break
case 'get_table_data':
response = {
accepted: false,
message: '',
table_data: {}
}
if (typeof(req.body) === 'object') {
try {
const body = req.body
if (await db.validateApiRequest(req.headers.session_key, "get_data")) {
const dbResponse = await db.getTableData(body.table)
if (dbResponse !== false) {
response.accepted = true
response.message = 'OK'
response.table_data = dbResponse
} else {
response.accepted = false
response.message = 'Error in API call!'
response.table_data = null
}
} else {
response.accepted = false
response.message = 'Action not allowed!'
console.warn('Action not allowed! api_name:', api_name)
}
} catch (error) {
response.accepted = false
response.message = 'Error in API call!'
response.analytics = null
} finally {
res.send(JSON.stringify(response))
}
}
break
...// In file db.js (cutted from the original file)
...
/**
* @async
* @description Validate the session key
* @param {string} sessionKey Session key
* @param {string} action Action to validate
* @throws Will throw if query to DB will fail
* @returns {Promise} Return true if session key is valid, false otherwise
*/
async function validateApiRequest(sessionKey, action = undefined) {
const username = getUsernameFromSessionKey(sessionKey)
if (username) {
let user_data = undefined
const query_user_id = {
text: 'SELECT users_management, dataset_management ' +
'FROM users WHERE username = $1;',
values: [username]
}
try {
const userIdRes = await pool.query(query_user_id)
// console.log('[getUserProfilePic]', userProfilePicPathRes.rows)
if (!userIdRes.rows.length) {
user_data = undefined
return false
} else {
/* This may be a string or null */
user_data = userIdRes.rows[0]
}
} catch (err) {
console.error(err)
throw err.message
}
switch (action) {
case "get_data":
{
// check data validity here
}
break
default:
return true
}
}
return false
}
...
```## Integrate with Socket.io server to notify clients
```js
// Import module with ES6 syntax
import { SessionManager } from '../index.js';const http = require('http')
// Create a new instance of the SessionManager class
const SM = new SessionManager();/**
* Create and start an ioSocket server
* @param {*} app
* "Express" handle
* @param {*} port
* Port the server should listen on
* @returns {SocketIO.Server}
* The newly created server
*/
function startServer(app, port) {
// Create an http server
const server = http.createServer(app)
server.listen(port)
server.on('error', function(error) { onError(error, port) })
server.on('listening', function() { onListening(server) })// Create the socketIO server
const ENDPOINT = `localhost:3000`;
const { Server } = require("socket.io");
const io = new Server(server, {
cors: {
origin: ENDPOINT,
methods: ["GET", "POST"]
}
});io.on('connection', (sk) => {
console.log('Browser Connected!')
sk.on('session_key', async function(data) {
const key = data.session_key
console.log(`User ${data.user} joined key ${key}`)
sk.join(key)
})
})return io
}SM.initSocketReferences(startServer(app, port)) // Initialize the socket references
SM.on("notifyClientToLogout", (io, key) => { // When a user logs out, notify the client
console.debug(`Session is expired for key ${key}... Logging out now!`)
io.in(key).emit('logout') // Emit the logout event to the client
})
```## Exported APIs
- ```eventEmitter```:
Node.js Event Emitter object, is extended by the class. It fires the following events:
- 'error': Called when some error happens (eg: Session is rejected)
- 'sessionDeleted': Called when a session is deleted or if expired
- 'sessionCreated': Called when a user session is created
- 'notifyClientToLogout': Called when a session timer is expired, bind this to a Socket.io server to force clients to logout## Integrate with metrics tools like PM2
```js
const io = require('@pm2/io') // Initialize the pm2 io module// The PM2 IO metrics to monitor the number of connected users
const realtimeUser = io.counter({
name: 'Realtime Users',
id: 'app/realtime/users',
})SM.on("sessionCreated", (key) => { // When a user logs out, notify the client
realtimeUser.inc() // Increment the number of active users
})SM.on("sessionDeleted", (key) => { // When a user logs out, notify the client
realtimeUser.dec() // Decrement the number of active users
})
```## Classes
-
SessionManager ⇐EventEmitter
-
SessionManager is a class that manages the sessions of the users.
## Constants
-
sessions :Object
-
The sessions of the users.
-
MIN_SESSION_TIMEOUT :number
-
The minimum session timeout.
-
settings :Object
-
The settings of the session manager.
## Functions
-
log(msg) ⇒void
-
Logs a message to the console if the debug flag is set to true in the config.
## SessionManager ⇐ EventEmitter
SessionManager is a class that manages the sessions of the users.
**Kind**: global class
**Extends**: EventEmitter
* [SessionManager](#SessionManager) ⇐ EventEmitter
* [.setSessionTimeOut(sessionTimeout)](#SessionManager+setSessionTimeOut) ⇒ boolean
* [.getSessionTimeout()](#SessionManager+getSessionTimeout) ⇒ number
* [.getLoggedUsers()](#SessionManager+getLoggedUsers) ⇒ array
* [.initSocketReference(ioRef)](#SessionManager+initSocketReference) ⇒ boolean
* [.getSocketReference()](#SessionManager+getSocketReference) ⇒ SocketIO.Server
* [.loadNewSession(username)](#SessionManager+loadNewSession) ⇒ string
* [.setSessionData(key, data)](#SessionManager+setSessionData) ⇒ boolean
* [.getSessionData(key)](#SessionManager+getSessionData) ⇒ object
* [.restartSessionTimer(key)](#SessionManager+restartSessionTimer) ⇒ boolean
* [.getSessionDetails(key)](#SessionManager+getSessionDetails) ⇒ object
\| boolean
* [.deleteSession(key)](#SessionManager+deleteSession) ⇒ boolean
* [.deleteAllSessions()](#SessionManager+deleteAllSessions) ⇒ boolean
* [.sendLogoutMessage(key)](#SessionManager+sendLogoutMessage) ⇒ boolean
* [.createNewSessionTimer(key, username)](#SessionManager+createNewSessionTimer) ⇒ NodeJS.Timeout
* [.checkSessionStatus(key)](#SessionManager+checkSessionStatus) ⇒ boolean
* [.getUsernameFromSessionKey(key)](#SessionManager+getUsernameFromSessionKey) ⇒ string
### sessionManager.setSessionTimeOut(sessionTimeout) ⇒ boolean
This function is used to set the session timeout
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false: true if ok
| Param | Type | Description |
| --- | --- | --- |
| sessionTimeout | number
| The session timeout in seconds |
**Example**
```js
setSessionTimeOut(3000) // Returns true or false
```
### sessionManager.getSessionTimeout() ⇒ number
This function is used to get the session timeout
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: number
- The session timeout in seconds
**Example**
```js
getSessionTimeOut() // Returns 3000
```
### sessionManager.getLoggedUsers() ⇒ array
This function is used to get the list of logged users
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: array
- The list of logged users
**Example**
```js
getLoggedUsers() // Returns ['Gino', 'Gino2']
```
### sessionManager.initSocketReference(ioRef) ⇒ boolean
Function to copy the Socket IO http server reference
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false, true if ok
| Param | Type |
| --- | --- |
| ioRef | \*
|
### sessionManager.getSocketReference() ⇒ SocketIO.Server
Function to get the socket reference
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: SocketIO.Server
- The socket reference
### sessionManager.loadNewSession(username) ⇒ string
Function to add users sessions in this module. Use it at login
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: string
- user unique key
| Param | Type | Description |
| --- | --- | --- |
| username | string
| The username provided on successful login |
**Example**
```js
addSession('Gino') // Returns 'session_key'
```
### sessionManager.setSessionData(key, data) ⇒ boolean
Function to set the property 'data' of a session. Use it for example to store something in the session, like the user actions history, etc.
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false, true if ok
**Throws**:
- Error
If the session_key is not found
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key provided on successful login |
| data | object
| The data to be stored in the session |
**Example**
```js
setSessionData('session_key', {'actions': ["logged in", ...]}) // Returns true or false
```
### sessionManager.getSessionData(key) ⇒ object
Function to get the property 'data' of a session. Use it for example to get the user actions history, etc.
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: object
- The data stored in the session
**Throws**:
- Error
If the session_key is not found
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key provided on successful login |
**Example**
```js
getSessionData('session_key') // Returns {'actions': ["logged in", ...]}
```
### sessionManager.restartSessionTimer(key) ⇒ boolean
Function that restart the session timer. Use it after an API call to keep the session alive.
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false, true if ok
**Throws**:
- Error
If the session key is not found
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key |
**Example**
```js
restartSessionTimer('session_key') // Returns true or false
```
### sessionManager.getSessionDetails(key) ⇒ object
\| boolean
Function to get details of a session. Use it to get the username, the creation date and the data.
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: object
\| boolean
- The session details or false if not found
**Throws**:
- Error
If the session key is not found
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key |
**Example**
```js
getSessionDetails('session_key') // Returns {'username': 'Gino', 'createdAt': 1523456789, 'data': {'actions': ["logged in", ...]}}
```
### sessionManager.deleteSession(key) ⇒ boolean
Function to delete users sessions in this module. Use it at client logout
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false, true if ok
**Throws**:
- Error
If the session_key is not found
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key provided on successful login |
**Example**
```js
deleteSession('session_key') // Returns true or false
```
### sessionManager.deleteAllSessions() ⇒ boolean
Function to delete all sessions
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false, true if ok
### sessionManager.sendLogoutMessage(key) ⇒ boolean
Use this to notify the client to logout with WebSocket
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false, true if ok
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key |
**Example**
```js
sendLogoutMessage('session_key') // Returns true or false
```
### sessionManager.createNewSessionTimer(key, username) ⇒ NodeJS.Timeout
Function to return a new setTimeout object and start it.
**Kind**: instance method of [SessionManager
](#SessionManager)
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session_key |
| username | string
| The username, only for logging features |
**Example**
```js
createNewSessionTimer('session_key', 'username') // Returns a new setTimeout object
```
### sessionManager.checkSessionStatus(key) ⇒ boolean
Use this before every API.js function execution.n the stored collection
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: boolean
- true or false: true if session is active
**Throws**:
- Error
if the session is not valid
- Error
if the session is expired
| Param | Type | Description |
| --- | --- | --- |
| key | string
| the user key generated at login |
**Example**
```js
checkSessionStatus('my_session_key') // true or false
```
### sessionManager.getUsernameFromSessionKey(key) ⇒ string
Function to get the username from a session key
**Kind**: instance method of [SessionManager
](#SessionManager)
**Returns**: string
- The username or false if not found
| Param | Type | Description |
| --- | --- | --- |
| key | string
| The session key |
**Example**
```js
getUsernameFromSessionKey('123456789_123456789') // 'username'
```
## sessions : Object
The sessions of the users.
## MIN\_SESSION\_TIMEOUT : number
The minimum session timeout.
## settings : Object
The settings of the session manager.
## log(msg) ⇒ void
Logs a message to the console if the debug flag is set to true in the config.
**Kind**: global function
| Param | Type |
| --- | --- |
| msg | string
|