Skip to content

fix(PM-1273): Send canApplyAsCopilot to check if the user can apply for the opportunity #824

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

Merged
merged 10 commits into from
Jun 19, 2025
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ workflows:
context : org-global
filters:
branches:
only: ['develop', 'migration-setup', 'pm-1356']
only: ['develop', 'migration-setup', 'pm-1273']
- deployProd:
context : org-global
filters:
Expand Down
4 changes: 4 additions & 0 deletions src/models/projectMember.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ module.exports = function defineProjectMember(sequelize, DataTypes) {
],
});

ProjectMember.associate = (models) => {
ProjectMember.belongsTo(models.Project, { foreignKey: 'projectId' });
};

Choose a reason for hiding this comment

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

Consider adding validation or error handling for the association to ensure that the projectId foreign key is valid and exists in the Project model. This can help prevent potential runtime errors if the association is used with invalid data.


ProjectMember.getProjectIdsForUser = userId => ProjectMember.findAll({
where: {
deletedAt: { $eq: null },
Expand Down
20 changes: 19 additions & 1 deletion src/routes/copilotOpportunity/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,30 @@ module.exports = [
model: models.Project,
as: 'project',
attributes: ['name'],

Choose a reason for hiding this comment

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

The attributes array on line 22 originally included 'members', which has now been moved to a separate include block. Ensure that this change aligns with the intended data structure and that the 'members' attribute is correctly populated in the response.

include: [
{
model: models.ProjectMember,
as: 'members',
attributes: ['id', 'userId', 'role'],
},
]
},
],
})
.then((copilotOpportunity) => {
const plainOpportunity = copilotOpportunity.get({ plain: true });
const formattedOpportunity = Object.assign({}, plainOpportunity,
req.log.info("authUser", req.authUser);

Choose a reason for hiding this comment

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

Logging sensitive information such as authUser can pose security risks if it contains personal or sensitive data. Consider reviewing what information is being logged and ensure it complies with security best practices.

const memberIds = plainOpportunity.project.members && plainOpportunity.project.members.map((member) => member.userId);

Choose a reason for hiding this comment

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

Consider adding a null check for plainOpportunity.project before accessing members to prevent potential runtime errors if project is undefined.

let canApplyAsCopilot = false;
if (req.authUser) {
canApplyAsCopilot = !memberIds.includes(req.authUser.userId)

Choose a reason for hiding this comment

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

Ensure memberIds is properly initialized before calling includes to avoid errors if plainOpportunity.project.members is null or undefined.

}
// This shouldn't be exposed to the clientside

Choose a reason for hiding this comment

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

The comment on line 40 suggests that plainOpportunity.project.members should not be exposed to the client-side. Ensure that this deletion is handled securely and that no sensitive information is inadvertently exposed elsewhere in the code.

delete plainOpportunity.project.members;

Choose a reason for hiding this comment

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

Consider adding a check to ensure plainOpportunity.project exists before attempting to delete plainOpportunity.project.members to prevent potential errors if project is undefined.

const formattedOpportunity = Object.assign({
members: memberIds,
canApplyAsCopilot,
}, plainOpportunity,
plainOpportunity.copilotRequest ? plainOpportunity.copilotRequest.data : {},
{ copilotRequest: undefined },
);
Expand Down
7 changes: 6 additions & 1 deletion src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ const jwtAuth = require('tc-core-library-js').middleware.jwtAuthenticator;
router.all(
RegExp(`\\/${apiVersion}\\/(copilots|projects|timelines|orgConfig|customer-payments)(?!\\/health).*`),
(req, res, next) => {
if (publicRoutes.some(routeRegex => routeRegex.test(req.path))) {
let token
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
token = req.headers.authorization.split(' ')[1]
}
if (publicRoutes.some(routeRegex => routeRegex.test(req.path)) && !token) {
return next();
}
req.log.info("token available", token);
// JWT authentication
return jwtAuth(config)(req, res, next);
},
Expand Down