Skip to content

Commit 7cc473d

Browse files
authored
Merge pull request #662 from liuliquan/PLAT-3453
PLAT-3453 Stop copilots from paying themselves
2 parents 2501fac + ced91c3 commit 7cc473d

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

src/common/challenge-helper.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ class ChallengeHelper {
105105
}
106106
}
107107

108-
async validateChallengeUpdateRequest(currentUser, challenge, data) {
108+
async validateChallengeUpdateRequest(currentUser, challenge, data, challengeResources) {
109109
if (process.env.LOCAL != "true") {
110-
await helper.ensureUserCanModifyChallenge(currentUser, challenge);
110+
await helper.ensureUserCanModifyChallenge(currentUser, challenge, challengeResources);
111111
}
112112

113113
helper.ensureNoDuplicateOrNullElements(data.tags, "tags");

src/common/helper.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -528,14 +528,17 @@ async function getResourceRoles() {
528528
* Check if a user has full access on a challenge
529529
* @param {String} challengeId the challenge UUID
530530
* @param {String} userId the user ID
531+
* @param {Array} challengeResources the challenge resources
531532
*/
532-
async function userHasFullAccess(challengeId, userId) {
533+
async function userHasFullAccess(challengeId, userId, challengeResources) {
533534
const resourceRoles = await getResourceRoles();
534535
const rolesWithFullAccess = _.map(
535536
_.filter(resourceRoles, (r) => r.fullWriteAccess),
536537
"id"
537538
);
538-
const challengeResources = await getChallengeResources(challengeId);
539+
if (!challengeResources) {
540+
challengeResources = await getChallengeResources(challengeId);
541+
}
539542
return (
540543
_.filter(
541544
challengeResources,
@@ -982,13 +985,14 @@ async function ensureUserCanViewChallenge(currentUser, challenge) {
982985
*
983986
* @param {Object} currentUser the user who perform operation
984987
* @param {Object} challenge the challenge to check
988+
* @param {Array} challengeResources the challenge resources
985989
* @returns {Promise}
986990
*/
987-
async function ensureUserCanModifyChallenge(currentUser, challenge) {
991+
async function ensureUserCanModifyChallenge(currentUser, challenge, challengeResources) {
988992
// check groups authorization
989993
await ensureAccessibleByGroupsAccess(currentUser, challenge);
990994
// check full access
991-
const isUserHasFullAccess = await userHasFullAccess(challenge.id, currentUser.userId);
995+
const isUserHasFullAccess = await userHasFullAccess(challenge.id, currentUser.userId, challengeResources);
992996
if (
993997
!currentUser.isMachine &&
994998
!hasAdminRole(currentUser) &&

src/services/ChallengeService.js

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,10 +1364,9 @@ function isDifferentPrizeSets(prizeSets = [], otherPrizeSets = []) {
13641364
/**
13651365
* Validate the winners array.
13661366
* @param {Array} winners the Winner Array
1367-
* @param {String} winchallengeIdners the challenge ID
1367+
* @param {Array} challengeResources the challenge resources
13681368
*/
1369-
async function validateWinners(winners, challengeId) {
1370-
const challengeResources = await helper.getChallengeResources(challengeId);
1369+
async function validateWinners(winners, challengeResources) {
13711370
const registrants = _.filter(challengeResources, (r) => r.roleId === config.SUBMITTER_ROLE_ID);
13721371
for (const prizeType of _.values(constants.prizeSetTypes)) {
13731372
const filteredWinners = _.filter(winners, (w) => w.type === prizeType);
@@ -1410,6 +1409,48 @@ async function validateWinners(winners, challengeId) {
14101409
}
14111410
}
14121411

1412+
/**
1413+
* Task shouldn't be launched/completed when it is assigned to the current user self.
1414+
* E.g: stop copilots from paying themselves, thus copilots will need to contact manager to launch/complete the task.
1415+
* @param {Object} currentUser the user who perform operation
1416+
* @param {Object} challenge the existing challenge
1417+
* @param {Object} data the new input challenge data
1418+
* @param {Array} challengeResources the challenge resources
1419+
*/
1420+
function validateTaskSelfAssign(currentUser, challenge, data, challengeResources) {
1421+
if (currentUser.isMachine) {
1422+
return;
1423+
}
1424+
1425+
const finalStatus = data.status || challenge.status;
1426+
1427+
// Only validate when launch/complete a task
1428+
const isLaunchCompleteTask =
1429+
_.get(challenge, "legacy.pureV5Task") &&
1430+
(finalStatus === constants.challengeStatuses.Active ||
1431+
finalStatus === constants.challengeStatuses.Completed);
1432+
if (!isLaunchCompleteTask) {
1433+
return;
1434+
}
1435+
1436+
// Whether task is assigned to current user
1437+
const assignedToCurrentUser =
1438+
_.filter(
1439+
challengeResources,
1440+
(r) =>
1441+
r.roleId === config.SUBMITTER_ROLE_ID &&
1442+
_.toString(r.memberId) === _.toString(currentUser.userId)
1443+
).length > 0;
1444+
1445+
if (assignedToCurrentUser) {
1446+
throw new errors.ForbiddenError(
1447+
`You are not allowed to ${
1448+
finalStatus === constants.challengeStatuses.Active ? "lanuch" : "complete"
1449+
} task assigned to yourself. Please contact manager to operate.`
1450+
);
1451+
}
1452+
}
1453+
14131454
/**
14141455
* Update challenge.
14151456
* @param {Object} currentUser the user who perform operation
@@ -1441,7 +1482,10 @@ async function updateChallenge(currentUser, challengeId, data) {
14411482
data = sanitizeData(sanitizeChallenge(data), challenge);
14421483
logger.debug(`Sanitized Data: ${JSON.stringify(data)}`);
14431484

1444-
await validateChallengeUpdateRequest(currentUser, challenge, data);
1485+
const challengeResources = await helper.getChallengeResources(challengeId);
1486+
1487+
await validateChallengeUpdateRequest(currentUser, challenge, data, challengeResources);
1488+
validateTaskSelfAssign(currentUser, challenge, data, challengeResources);
14451489

14461490
let sendActivationEmail = false;
14471491
let sendSubmittedEmail = false;
@@ -1716,7 +1760,7 @@ async function updateChallenge(currentUser, challengeId, data) {
17161760
}
17171761

17181762
if (data.winners && data.winners.length && data.winners.length > 0) {
1719-
await validateWinners(data.winners, challengeId);
1763+
await validateWinners(data.winners, challengeResources);
17201764
}
17211765

17221766
// Only m2m tokens are allowed to modify the `task.*` information on a challenge
@@ -1777,7 +1821,6 @@ async function updateChallenge(currentUser, challengeId, data) {
17771821

17781822
if (_.get(type, "isTask")) {
17791823
if (!_.isEmpty(_.get(data, "task.memberId"))) {
1780-
const challengeResources = await helper.getChallengeResources(challengeId);
17811824
const registrants = _.filter(
17821825
challengeResources,
17831826
(r) => r.roleId === config.SUBMITTER_ROLE_ID

0 commit comments

Comments
 (0)