Skip to content

Commit

Permalink
Merge pull request #473 from ELEVATE-Project/1172_user_sessions_backu…
Browse files Browse the repository at this point in the history
…p_one

[1171- STORY ]- User Session Implementation added.
  • Loading branch information
rakeshSgr authored Apr 1, 2024
2 parents 8558d0a + ff92666 commit 7aa0e77
Show file tree
Hide file tree
Showing 19 changed files with 1,077 additions and 113 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:16
FROM node:20

#Set working directory
WORKDIR /var/src/
Expand Down
8 changes: 7 additions & 1 deletion src/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,11 @@ DOWNLOAD_URL_EXPIRATION_DURATION = 120000
#database url
DATABASE_URL=postgres://postgres:postgres@localhost:5432/elevate-user

#allowed idle time
ALLOWED_IDLE_TIME=300000

# Expiry time for the signed urls
SIGNED_URL_EXPIRY_IN_MILLISECONDS = 120000
SIGNED_URL_EXPIRY_IN_MILLISECONDS = 120000

# Allowed active sessions
ALLOWED_ACTIVE_SESSIONS = 5
2 changes: 2 additions & 0 deletions src/constants/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = {
'/user/v1/account/search',
'/user/v1/organization/list',
'/user/v1/user-role/default',
'/user/v1/account/validateUserSession',
],
notificationEmailType: 'email',
accessTokenExpiry: process.env.ACCESS_TOKEN_EXPIRY,
Expand Down Expand Up @@ -59,6 +60,7 @@ module.exports = {
roleAssociationName: 'user_roles',
ACTIVE_STATUS: 'ACTIVE',
INACTIVE_STATUS: 'INACTIVE',
EXPIRED_STATUS: 'EXPIRED',
MENTOR_ROLE: 'mentor',
MENTEE_ROLE: 'mentee',
SESSION_MANAGER_ROLE: 'session_manager',
Expand Down
52 changes: 47 additions & 5 deletions src/controllers/v1/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

// Dependencies
const accountService = require('@services/account')

const userSessionsService = require('@services/user-sessions')
module.exports = class Account {
/**
* create mentee account
Expand All @@ -24,8 +24,9 @@ module.exports = class Account {

async create(req) {
const params = req.body
const device_info = req.headers && req.headers['device-info'] ? JSON.parse(req.headers['device-info']) : {}
try {
const createdAccount = await accountService.create(params)
const createdAccount = await accountService.create(params, device_info)
return createdAccount
} catch (error) {
return error
Expand All @@ -45,8 +46,9 @@ module.exports = class Account {

async login(req) {
const params = req.body
const device_info = req.headers && req.headers['device-info'] ? JSON.parse(req.headers['device-info']) : {}
try {
const loggedInAccount = await accountService.login(params)
const loggedInAccount = await accountService.login(params, device_info)
return loggedInAccount
} catch (error) {
return error
Expand All @@ -69,7 +71,8 @@ module.exports = class Account {
const loggedOutAccount = await accountService.logout(
req.body,
req.decodedToken.id,
req.decodedToken.organization_id
req.decodedToken.organization_id,
req.decodedToken.session_id
)
return loggedOutAccount
} catch (error) {
Expand Down Expand Up @@ -128,7 +131,8 @@ module.exports = class Account {
async resetPassword(req) {
const params = req.body
try {
const result = await accountService.resetPassword(params)
const deviceInfo = req.headers && req.headers['device-info'] ? JSON.parse(req.headers['device-info']) : {}
const result = await accountService.resetPassword(params, deviceInfo)
return result
} catch (error) {
return error
Expand Down Expand Up @@ -266,4 +270,42 @@ module.exports = class Account {
return error
}
}

/**
* Retrieve user sessions based on the request parameters.
* @param {Object} req - The request object containing query parameters and decoded token.
* @returns {Promise<Object>} - A promise that resolves to the user session details.
*/

async sessions(req) {
try {
const filter = req.query && req.query.status ? req.query.status.toUpperCase() : ''
const userSessionDetails = await userSessionsService.list(
req.decodedToken.id,
filter,
req.pageSize,
req.pageNo
)
return userSessionDetails
} catch (error) {
return error
}
}

/**
* Validate a user session based on the provided token.
* @param {Object} req - The request object containing the token in the request body.
* @param {string} req.body.token - The token to validate the user session.
* @returns {Promise<Object>} - A promise that resolves to the validation result of the user session.
*/

async validateUserSession(req) {
try {
const token = req.body.token
const validateUserSession = await userSessionsService.validateUserSession(token)
return validateUserSession
} catch (error) {
return error
}
}
}
3 changes: 2 additions & 1 deletion src/controllers/v1/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ module.exports = class Admin {

async login(req) {
try {
const loggedInAccount = await adminService.login(req.body)
const device_info = req.headers && req.headers['device-info'] ? req.headers['device-info'] : {}
const loggedInAccount = await adminService.login(req.body, device_info)
return loggedInAccount
} catch (error) {
return error
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict'

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('user_sessions', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
user_id: {
type: Sequelize.INTEGER,
allowNull: false,
},
started_at: {
type: Sequelize.BIGINT,
allowNull: false,
},
ended_at: {
type: Sequelize.BIGINT,
allowNull: true,
},
token: {
type: Sequelize.TEXT,
allowNull: true,
},
device_info: {
type: Sequelize.JSONB,
allowNull: true,
},
refresh_token: {
type: Sequelize.TEXT,
allowNull: true,
},
created_at: {
allowNull: false,
type: Sequelize.DATE,
},
updated_at: {
allowNull: false,
type: Sequelize.DATE,
},
deleted_at: {
type: Sequelize.DATE,
},
})
},

async down(queryInterface, Sequelize) {
await queryInterface.dropTable('user_sessions')
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict'

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
try {
const permissionsData = [
{
code: 'get_user_sessions',
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
status: 'ACTIVE',
},
{
code: 'validate_user_sessions',
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
status: 'ACTIVE',
},
]

// Batch insert permissions
await queryInterface.bulkInsert(
'permissions',
permissionsData.map((permission) => ({
...permission,
created_at: new Date(),
updated_at: new Date(),
}))
)
} catch (error) {
console.error('Error in migration:', error)
throw error
}
},

async down(queryInterface, Sequelize) {
try {
// Rollback migration by deleting all permissions
await queryInterface.bulkDelete('permissions', null, {})
} catch (error) {
console.error('Error in rollback migration:', error)
throw error
}
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
'use strict'

require('module-alias/register')
require('dotenv').config()
const common = require('@constants/common')
const Permissions = require('@database/models/index').Permission

const getPermissionId = async (module, request_type, api_path) => {
try {
const permission = await Permissions.findOne({
where: { module, request_type, api_path },
})
if (!permission) {
throw new Error(
`Permission not found for module: ${module}, request_type: ${request_type}, api_path: ${api_path}`
)
}
return permission.id
} catch (error) {
throw new Error(`Error while fetching permission: ${error.message}`)
}
}

module.exports = {
up: async (queryInterface, Sequelize) => {
try {
const rolePermissionsData = await Promise.all([
{
role_title: common.MENTOR_ROLE,
permission_id: await getPermissionId('account', ['GET'], '/user/v1/account/sessions'),
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
},
{
role_title: common.ORG_ADMIN_ROLE,
permission_id: await getPermissionId('account', ['GET'], '/user/v1/account/sessions'),
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
},
{
role_title: common.USER_ROLE,
permission_id: await getPermissionId('account', ['GET'], '/user/v1/account/sessions'),
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
},
{
role_title: common.ADMIN_ROLE,
permission_id: await getPermissionId('account', ['GET'], '/user/v1/account/sessions'),
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
},
{
role_title: common.SESSION_MANAGER_ROLE,
permission_id: await getPermissionId('account', ['GET'], '/user/v1/account/sessions'),
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
},
{
role_title: common.MENTEE_ROLE,
permission_id: await getPermissionId('account', ['GET'], '/user/v1/account/sessions'),
module: 'account',
request_type: ['GET'],
api_path: '/user/v1/account/sessions',
},

{
role_title: common.MENTOR_ROLE,
permission_id: await getPermissionId('account', ['POST'], '/user/v1/account/validateUserSession'),
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
},
{
role_title: common.MENTEE_ROLE,
permission_id: await getPermissionId('account', ['POST'], '/user/v1/account/validateUserSession'),
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
},
{
role_title: common.ORG_ADMIN_ROLE,
permission_id: await getPermissionId('account', ['POST'], '/user/v1/account/validateUserSession'),
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
},
{
role_title: common.USER_ROLE,
permission_id: await getPermissionId('account', ['POST'], '/user/v1/account/validateUserSession'),
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
},
{
role_title: common.ADMIN_ROLE,
permission_id: await getPermissionId('account', ['POST'], '/user/v1/account/validateUserSession'),
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
},
{
role_title: common.SESSION_MANAGER_ROLE,
permission_id: await getPermissionId('account', ['POST'], '/user/v1/account/validateUserSession'),
module: 'account',
request_type: ['POST'],
api_path: '/user/v1/account/validateUserSession',
},
])

await queryInterface.bulkInsert(
'role_permission_mapping',
rolePermissionsData.map((data) => ({
...data,
created_at: new Date(),
updated_at: new Date(),
created_by: 0,
}))
)
} catch (error) {
console.log(error)
console.error(`Migration error: ${error.message}`)
throw error
}
},

down: async (queryInterface, Sequelize) => {
try {
await queryInterface.bulkDelete('role_permission_mapping', null, {})
} catch (error) {
console.error(`Rollback migration error: ${error.message}`)
throw error
}
},
}
Loading

0 comments on commit 7aa0e77

Please sign in to comment.