Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #478

Merged
merged 25 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a24b42b
user-sessions table added to user service
VISHNUDAS-tunerlabs Mar 26, 2024
12db6ce
user sessions
VISHNUDAS-tunerlabs Mar 27, 2024
b11acb2
changes pushed for internal api testing. code clean up and optimisati…
VISHNUDAS-tunerlabs Mar 28, 2024
ad59c98
change password - logout condition
sumanvpacewisdom Mar 28, 2024
b7bb2c3
removing commented lines
sumanvpacewisdom Mar 28, 2024
d2cfa8e
space
sumanvpacewisdom Mar 28, 2024
8114f1c
local merge check
VISHNUDAS-tunerlabs Mar 28, 2024
1d73640
code clean up before merge
VISHNUDAS-tunerlabs Mar 28, 2024
741614b
internal url updated
VISHNUDAS-tunerlabs Mar 28, 2024
2ab1c31
develop branch merged and conflicts addressed
VISHNUDAS-tunerlabs Mar 28, 2024
a9ae2e7
user table and related api changes
VISHNUDAS-tunerlabs Mar 29, 2024
49497e1
configurable active session check added
VISHNUDAS-tunerlabs Mar 29, 2024
3663260
parse device info
VISHNUDAS-tunerlabs Mar 30, 2024
ff92666
device info
VISHNUDAS-tunerlabs Mar 30, 2024
7aa0e77
Merge pull request #473 from ELEVATE-Project/1172_user_sessions_backu…
rakeshSgr Apr 1, 2024
d75e009
remove unwanted keys
VISHNUDAS-tunerlabs Apr 1, 2024
6111eb1
Merge pull request #471 from sumanvpacewisdom/change_password
rakeshSgr Apr 1, 2024
7d1da43
Merge pull request #474 from ELEVATE-Project/1172_user_sessions_backu…
rakeshSgr Apr 1, 2024
fe1b3c3
updated validation regex
nevil-mathew Apr 1, 2024
dc5d7f6
added whitespace
nevil-mathew Apr 1, 2024
7aa8e3b
Merge pull request #475 from ELEVATE-Project/regex-update
rakeshSgr Apr 1, 2024
31c9d9d
update TTL if idle time is provided
VISHNUDAS-tunerlabs Apr 1, 2024
d6b5918
Merge pull request #476 from ELEVATE-Project/1172_user_sessions_backu…
rakeshSgr Apr 1, 2024
71b8ba4
DC issue fix
VISHNUDAS-tunerlabs Apr 1, 2024
6f61580
Merge pull request #477 from ELEVATE-Project/1172_user_sessions_backu…
rakeshSgr Apr 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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