Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions src/constants/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ module.exports = {
'/user/v1/account/validateUserSession',
'/user/v1/account/validatingEmailIds',
'/user/v1/tenant/list',
'/user/v1/tenant/read/',
'/user/v1/tenant/domain/',
Comment on lines +33 to +34
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot have public facing API (tenant/read) to be used an internal API, please add a new endpoint if needed.

'/user/v1/tenant/readInternal/',
Comment on lines +33 to 35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Verify whitelist matching for new internalAccessUrls entries

If the whitelist checks exact matches (not prefix), trailing slashes and missing route params could block access. Ensure middleware matches these paths correctly and the routes exist.


🏁 Script executed:

#!/bin/bash
# 1) Find where internalAccessUrls is used to verify matching logic (exact vs prefix).
rg -n -C3 'internalAccessUrls' --type js --type ts

# 2) Locate tenant controller routes to confirm endpoints exist and match patterns.
rg -n -C3 '/tenant/(read|domain)' --type js --type ts

# 3) List all router definitions mentioning tenant to confirm exact paths.
rg -n -C3 'router\.(get|post|patch|put|delete)\(.*tenant' --type js --type ts

Length of output: 4508


Normalize whitelist matching for internalAccessUrls
internalAccessUrls uses req.path.includes(path), so patterns with trailing slashes (e.g. /user/v1/tenant/read/) won’t match routes defined without them. Remove trailing slashes from these entries or trim/normalize req.path (or switch to startsWith) so the intended endpoints are correctly whitelisted.

🤖 Prompt for AI Agents
In src/constants/common.js around lines 33 to 35, the whitelist entries have
trailing slashes which fail to match when code uses req.path.includes(path);
remove the trailing slashes from '/user/v1/tenant/read/',
'/user/v1/tenant/domain/', and '/user/v1/tenant/readInternal/' so they become
'/user/v1/tenant/read', '/user/v1/tenant/domain', and
'/user/v1/tenant/readInternal'; alternatively, if you prefer matching logic
changes instead, normalize req.path by trimming trailing slashes or replace
includes() with startsWith() so route comparisons are consistent.

'/v1/cloud-services/file/getDownloadableUrl',
],
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/v1/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ module.exports = class Admin {
})
}

const result = await adminService.deactivateUser(req.body, req.decodedToken.id)
const result = await adminService.deactivateUser(req.body, req.decodedToken.id, req.decodedToken.tenant_code, req.decodedToken.organization_code)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these changes here?


return result
} catch (error) {
Expand Down
6 changes: 4 additions & 2 deletions src/controllers/v1/organization.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ module.exports = class Organization {
try {
const result = await orgService.addRelatedOrg(
req.params.id ? req.params.id : '',
req.body.related_orgs ? req.body.related_orgs : []
req.body.related_orgs ? req.body.related_orgs : [],
req?.decodedToken?.tenant_code
Comment on lines +191 to +192
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot have req?.decodedToken?.tenant_code as of now, as the admin tenant and orgs tenant_code might not match.

)
return result
} catch (error) {
Expand All @@ -199,7 +200,8 @@ module.exports = class Organization {
try {
const result = await orgService.removeRelatedOrg(
req.params.id ? req.params.id : '',
req.body.related_orgs ? req.body.related_orgs : []
req.body.related_orgs ? req.body.related_orgs : [],
req?.decodedToken?.tenant_code
Comment on lines +203 to +204
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment in addRelatedOrg

)
return result
} catch (error) {
Expand Down
4 changes: 4 additions & 0 deletions src/helpers/userInvite.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const notificationUtils = require('@utils/notification')
const tenantDomainQueries = require('@database/queries/tenantDomain')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need changes in userInvite?

const tenantQueries = require('@database/queries/tenants')
const userSessionsService = require('@services/user-sessions')
const { organization } = require('@constants/blacklistConfig')
let defaultOrg = {}
let modelName = ''
let externalEntityNameIdMap = {}
Expand Down Expand Up @@ -960,6 +961,7 @@ module.exports = class UserInviteHelper {
user_id: existingUser.id,
organization_id: user.organization_id,
roles: currentRoles,
organization_code: user.organization_code,
},
})
}
Expand All @@ -970,6 +972,8 @@ module.exports = class UserInviteHelper {
user_id: existingUser.id,
new_roles: newRoles,
current_roles: currentRoles,
tenant_code: user.tenant_code,
organization_code: user.organization_code
}
if (isOrgUpdate) requestBody.organization_id = user.organization_id
eventBroadcaster('roleChange', {
Expand Down
7 changes: 5 additions & 2 deletions src/services/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ module.exports = class AdminHelper {
user_id: user.id,
organization_id: organizationId,
roles: roleData.map((r) => r.title),
organization_code: organization.code,
},
})
)
Expand Down Expand Up @@ -714,7 +715,7 @@ module.exports = class AdminHelper {

// Broadcast to end upcoming sessions
eventBroadcaster('deactivateUpcomingSession', {
requestBody: { user_ids: userIds },
requestBody: { user_ids: userIds , tenant_code: tenantCode, organization_code: organizationCode},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the old event, right? Are we not moving to new event structure in this release?

})
}

Expand All @@ -740,7 +741,7 @@ module.exports = class AdminHelper {
* @param {Object} loggedInUserId - logged in user id
* @returns {JSON} - Deactivated user data
*/
static async deactivateUser(bodyData, loggedInUserId) {
static async deactivateUser(bodyData, loggedInUserId, tenantCode, orgCode) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as mentioned as above, the admins org and tenant code might not match with the user he's deactivating as of now.

try {
let filterQuery = {}
for (let item in bodyData) {
Expand Down Expand Up @@ -783,6 +784,8 @@ module.exports = class AdminHelper {
eventBroadcaster('deactivateUpcomingSession', {
requestBody: {
user_ids: userIds,
tenant_code: tenantCode,
organization_code: orgCode
},
})

Expand Down
2 changes: 2 additions & 0 deletions src/services/org-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ module.exports = class OrgAdminHelper {
eventBroadcaster('deactivateUpcomingSession', {
requestBody: {
user_ids: allUserIds,
tenant_code: tokenInformation.tenant_code,
organization_code: tokenInformation.organization_code
},
})

Expand Down
6 changes: 4 additions & 2 deletions src/services/organization.js
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ module.exports = class OrganizationsHelper {
}
}

static async addRelatedOrg(id, relatedOrgs = []) {
static async addRelatedOrg(id, relatedOrgs = [], tenantCode) {
try {
// fetch organization details before update
const orgDetailsBeforeUpdate = await organizationQueries.findOne({ id })
Expand Down Expand Up @@ -553,6 +553,7 @@ module.exports = class OrganizationsHelper {
delta_organization_ids: deltaOrgs,
organization_id: id,
action: 'PUSH',
tenant_code: tenantCode
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, the admin tenant might not match with related orgs tenant.

},
})
}
Expand All @@ -565,7 +566,7 @@ module.exports = class OrganizationsHelper {
throw error
}
}
static async removeRelatedOrg(id, relatedOrgs = []) {
static async removeRelatedOrg(id, relatedOrgs = [], tenantCode) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as addRelatedOrg

try {
// fetch organization details before update
const orgDetailsBeforeUpdate = await organizationQueries.findOne({ id })
Expand Down Expand Up @@ -625,6 +626,7 @@ module.exports = class OrganizationsHelper {
delta_organization_ids: relatedOrgs,
organization_id: id,
action: 'POP',
tenant_code:tenantCode
},
})
}
Expand Down
51 changes: 51 additions & 0 deletions src/services/tenant.js
Original file line number Diff line number Diff line change
Expand Up @@ -784,4 +784,55 @@ module.exports = class tenantHelper {
throw error // Re-throw other errors
}
}

/**
* Get primary domain for tenant
* @method
* @name getDomain
* @param {string} tenantCode - code of the tenant
* @returns {JSON} - tenant domain information
*/
Comment on lines +788 to +794
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A proper doc string would be helpful, including information about the internal access nature of this endpoint.

static async getDomain(tenantCode) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the controlled for this ednpoint ?

try {
// Validate tenant exists
const tenantDetails = await tenantQueries.findOne({
code: tenantCode,
})

if (!tenantDetails) {
return responses.failureResponse({
statusCode: httpStatusCode.not_found,
message: 'TENANT_NOT_FOUND',
responseCode: 'CLIENT_ERROR',
})
}

// Get the first domain (primary domain) for the tenant
const domain = await tenantDomainQueries.findOne({
tenant_code: tenantCode,
verified: true,
})

if (!domain) {
return responses.failureResponse({
statusCode: httpStatusCode.not_found,
message: 'TENANT_DOMAIN_NOT_FOUND',
responseCode: 'CLIENT_ERROR',
})
}

return responses.successResponse({
statusCode: httpStatusCode.ok,
message: 'TENANT_DOMAIN_FETCHED',
result: {
domain: domain.domain,
tenant_code: tenantCode,
verified: domain.verified,
},
})
} catch (error) {
console.log(error)
throw error
}
}
}
3 changes: 3 additions & 0 deletions src/services/userInvite.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ module.exports = class UserInviteHelper {
user_id: existingUser.id,
organization_id: user.organization_id,
roles: currentRoles,
organization_code: user.organization_code
},
})
}
Expand All @@ -380,6 +381,8 @@ module.exports = class UserInviteHelper {
user_id: existingUser.id,
new_roles: newRoles,
current_roles: currentRoles,
tenant_code: user.tenant_code,
organization_code: user.organization_code
Comment on lines +384 to +385
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User invites is no longer used as of now, and might not work as intended.

}
if (isOrgUpdate) requestBody.organization_id = user.organization_id
eventBroadcaster('roleChange', {
Expand Down