Skip to content

Commit eb99b14

Browse files
committed
fix: avoid exposing project details to users apart from PMs and Admins
1 parent a8c2751 commit eb99b14

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

src/routes/copilotOpportunity/get.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { USER_ROLE } from '../../constants';
12
import models from '../../models';
23
import util from '../../util';
34

@@ -8,9 +9,10 @@ module.exports = [
89
return util.handleError('Invalid opportunity ID', null, req, next, 400);
910
}
1011

12+
const isAdminOrManager = util.hasRoles(req, [USER_ROLE.CONNECT_ADMIN, USER_ROLE.TOPCODER_ADMIN, USER_ROLE.PROJECT_MANAGER]);
1113
return models.CopilotOpportunity.findOne({
1214
where: { id },
13-
include: [
15+
include: isAdminOrManager ? [
1416
{
1517
model: models.CopilotRequest,
1618
as: 'copilotRequest',
@@ -27,24 +29,34 @@ module.exports = [
2729
},
2830
]
2931
},
32+
]: [
33+
{
34+
model: models.CopilotRequest,
35+
as: 'copilotRequest',
36+
},
3037
],
3138
})
3239
.then((copilotOpportunity) => {
3340
const plainOpportunity = copilotOpportunity.get({ plain: true });
34-
const memberIds = plainOpportunity.project.members && plainOpportunity.project.members.map((member) => member.userId);
41+
const memberIds = (plainOpportunity.project && plainOpportunity.project.members && plainOpportunity.project.members.map((member) => member.userId)) || [];
3542
let canApplyAsCopilot = false;
3643
if (req.authUser) {
3744
canApplyAsCopilot = !memberIds.includes(req.authUser.userId)
3845
}
39-
// This shouldn't be exposed to the clientside
40-
delete plainOpportunity.project.members;
46+
if (plainOpportunity.project) {
47+
// This shouldn't be exposed to the clientside
48+
delete plainOpportunity.project.members;
49+
}
4150
const formattedOpportunity = Object.assign({
4251
members: memberIds,
4352
canApplyAsCopilot,
4453
}, plainOpportunity,
4554
plainOpportunity.copilotRequest ? plainOpportunity.copilotRequest.data : {},
4655
{ copilotRequest: undefined },
4756
);
57+
if (!isAdminOrManager) {
58+
delete formattedOpportunity.projectId;
59+
}
4860
res.json(formattedOpportunity);
4961
})
5062
.catch((err) => {

src/routes/copilotOpportunity/list.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import _ from 'lodash';
22

33
import models from '../../models';
44
import util from '../../util';
5-
import DEFAULT_PAGE_SIZE from '../../constants';
5+
import DEFAULT_PAGE_SIZE, { USER_ROLE } from '../../constants';
66

77
module.exports = [
88
(req, res, next) => {
@@ -15,6 +15,7 @@ module.exports = [
1515
return util.handleError('Invalid sort criteria', null, req, next);
1616
}
1717
const sortParams = sort.split(' ');
18+
const isAdminOrManager = util.hasRoles(req, [USER_ROLE.CONNECT_ADMIN, USER_ROLE.TOPCODER_ADMIN, USER_ROLE.PROJECT_MANAGER]);
1819

1920
// Extract pagination parameters
2021
const page = parseInt(req.query.page, 10) || 1;
@@ -42,7 +43,7 @@ module.exports = [
4243
baseOrder.push([sortParams[0], sortParams[1]]);
4344

4445
return models.CopilotOpportunity.findAll({
45-
include: [
46+
include: isAdminOrManager ? [
4647
{
4748
model: models.CopilotRequest,
4849
as: 'copilotRequest',
@@ -52,6 +53,11 @@ module.exports = [
5253
as: 'project',
5354
attributes: ['name'],
5455
},
56+
] : [
57+
{
58+
model: models.CopilotRequest,
59+
as: 'copilotRequest',
60+
},
5561
],
5662
order: baseOrder,
5763
limit,
@@ -60,10 +66,17 @@ module.exports = [
6066
.then((copilotOpportunities) => {
6167
const formattedOpportunities = copilotOpportunities.map((opportunity) => {
6268
const plainOpportunity = opportunity.get({ plain: true });
63-
return Object.assign({}, plainOpportunity,
69+
const formatted = Object.assign({}, plainOpportunity,
6470
plainOpportunity.copilotRequest ? plainOpportunity.copilotRequest.data : {},
6571
{ copilotRequest: undefined },
6672
);
73+
74+
// For users who are not admin or manager, we dont want to expose
75+
// the project id
76+
if (!isAdminOrManager) {
77+
delete formatted.projectId;
78+
}
79+
return ;
6780
});
6881
return util.setPaginationHeaders(req, res, {
6982
count: copilotOpportunities.count,

src/routes/copilotRequest/list.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Op, Sequelize } from 'sequelize';
44
import models from '../../models';
55
import util from '../../util';
66
import { PERMISSION } from '../../permissions/constants';
7-
import { DEFAULT_PAGE_SIZE } from '../../constants';
7+
import { DEFAULT_PAGE_SIZE, USER_ROLE } from '../../constants';
88

99
module.exports = [
1010
(req, res, next) => {
@@ -17,6 +17,7 @@ module.exports = [
1717
return next(err);
1818
}
1919

20+
const isAdminOrManager = util.hasRoles(req, [USER_ROLE.CONNECT_ADMIN, USER_ROLE.TOPCODER_ADMIN, USER_ROLE.PROJECT_MANAGER]);
2021
const page = parseInt(req.query.page, 10) || 1;
2122
const pageSize = parseInt(req.query.pageSize, 10) || DEFAULT_PAGE_SIZE;
2223
const offset = (page - 1) * pageSize;
@@ -46,7 +47,7 @@ module.exports = [
4647
let order = [[sortParams[0], sortParams[1]]];
4748
const relationBasedSortParams = ['projectName'];
4849
const jsonBasedSortParams = ['opportunityTitle', 'projectType'];
49-
if (relationBasedSortParams.includes(sortParams[0])) {
50+
if (relationBasedSortParams.includes(sortParams[0]) && isAdminOrManager) {
5051
order = [
5152
[{model: models.Project, as: 'project'}, 'name', sortParams[1]],
5253
['id', 'DESC']
@@ -64,9 +65,11 @@ module.exports = [
6465

6566
return models.CopilotRequest.findAndCountAll({
6667
where: whereCondition,
67-
include: [
68+
include: isAdminOrManager ? [
6869
{ model: models.CopilotOpportunity, as: 'copilotOpportunity', required: false },
6970
{ model: models.Project, as: 'project', required: false },
71+
] : [
72+
{ model: models.CopilotOpportunity, as: 'copilotOpportunity', required: false },
7073
],
7174
order,
7275
limit: pageSize,

0 commit comments

Comments
 (0)