Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit 89e9f97

Browse files
committed
merge
2 parents fd08d91 + 3e535dd commit 89e9f97

File tree

264 files changed

+14130
-1310
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

264 files changed

+14130
-1310
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ pids
44
deploy/prod.sh
55
node_modules
66
test/tmp/submissions/*.zip
7+
test/tmp/design_submissions/*.zip
8+
test/tmp/design_tmp_submissions/*.zip
9+

actions/challengeRegistration.js

Lines changed: 128 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,32 @@
33
*
44
* The APIs to register a challenge (studio category or software category) for the current logged-in user.
55
*
6-
* @version 1.1
7-
* @author ecnu_haozi, xjtufreeman
6+
* @version 1.3
7+
* @author ecnu_haozi, xjtufreeman, bugbuka
88
*
99
* changes in 1.1:
1010
* Combine Challenge Registration API(BUGR-11058)
11+
*
12+
* changes in 1.2:
13+
* Integrate the forums operation(Module Assembly - Integrating Forums Wrapper with Challenge Registration API)
14+
*
15+
* changes in 1.3:
16+
* move common function getForumWrapper, aduitResourceAddition to challengeHelper.js
1117
*/
1218
"use strict";
1319

1420
var async = require('async');
1521
var _ = require('underscore');
1622
var moment = require('moment');
23+
var ForumWrapper = require("forum-connector").ForumWrapper;
1724
var NotFoundError = require('../errors/NotFoundError');
1825
var ForbiddenError = require('../errors/ForbiddenError');
1926

27+
/**
28+
* The forum wrapper instance
29+
*/
30+
var forumWrapper = null;
31+
2032
//constants
2133
var DESIGN_PROJECT_TYPE = 1,
2234
DEVELOPMENT_PROJECT_TYPE = 2,
@@ -125,7 +137,7 @@ var persistResource = function (api, resourceId, userId, challengeId, dbConnecti
125137
modifyUser: '"' + userId + '"'
126138
},
127139
dbConnectionMap,
128-
function (err, result) {
140+
function (err) {
129141
if (err) {
130142
next(err);
131143
} else {
@@ -134,28 +146,6 @@ var persistResource = function (api, resourceId, userId, challengeId, dbConnecti
134146
});
135147
};
136148

137-
/**
138-
* Audit the challenge registration on table 'tcs_catalog.project_user_audit'.
139-
*
140-
* @param {Object} api The api object that is used to access the infrastructure.
141-
* @param {Number} resourceId The resource id.
142-
* @param {Number} userId The current logged-in user's id.
143-
* @param {Number} challengeId The id of the challenge to register.
144-
* @param {Object} dbConnectionMap The database connection map for the current request.
145-
* @param {Function<err, data>} next The callback to be called after this function is done.
146-
*/
147-
var aduitResourceAddition = function (api, userId, challengeId, dbConnectionMap, next) {
148-
api.dataAccess.executeQuery("audit_challenge_registration", {
149-
projectId: challengeId,
150-
resourceUserId: userId,
151-
resourceRoleId: SUBMITTER_RESOURCE_ROLE_ID,
152-
auditActionTypeId: PROJECT_USER_AUDIT_CREATE_TYPE,
153-
actionUserId: userId
154-
},
155-
dbConnectionMap,
156-
next);
157-
};
158-
159149
/**
160150
* Check if the rating suit for software category contests.
161151
* The code logic is duplicated from server-side java code.
@@ -212,8 +202,9 @@ var prepareProjectResult = function (api, rating, userId, challengeId, phaseId,
212202
*
213203
* @param {Object} api The api object that is used to access the infrastructure.
214204
* @param {Number} resourceId The resource id.
215-
* @param {Number} userId The current logged-in user's id.
216-
* @param {Number} challengeId The id of the challenge to register.
205+
* @param {Number} propertyId The property id.
206+
* @param {String} propertyValue The property value.
207+
* @param {Number} userId The user id.
217208
* @param {Object} dbConnectionMap The database connection map for the current request.
218209
* @param {Function<err, data>} next The callback to be called after this function is done..
219210
*/
@@ -254,7 +245,7 @@ var projectTrack = function (api, userId, challengeId, componentInfo, dbConnecti
254245
function (resourceId, callback) {
255246
async.parallel([
256247
function (cb) {
257-
aduitResourceAddition(api, userId, challengeId, dbConnectionMap, cb);
248+
api.challengeHelper.aduitResourceAddition(api, userId, challengeId, SUBMITTER_RESOURCE_ROLE_ID, PROJECT_USER_AUDIT_CREATE_TYPE, dbConnectionMap, cb);
258249
},
259250
function (cb) {
260251
prepareProjectResult(
@@ -346,12 +337,13 @@ var projectTrack = function (api, userId, challengeId, componentInfo, dbConnecti
346337
* Send email to notify the user registration succeeded.
347338
*
348339
* @param {Object} api The api object that is used to access the infrastructure.
349-
* @param {Number} userId The current logged-in user's id.
350340
* @param {Object} componentInfo The component info object generated from method <code>registerComponentInquiry</code>.
341+
* @param {Number} userId The current logged-in user's id.
342+
* @param {Number} activeForumCategoryId The active forum category id.
351343
* @param {Object} dbConnectionMap The database connection map for the current request.
352344
* @param {Function<err, data>} next The callback to be called after this function is done.
353345
*/
354-
var sendNotificationEmail = function (api, componentInfo, userId, dbConnectionMap, next) {
346+
var sendNotificationEmail = function (api, componentInfo, userId, activeForumCategoryId, dbConnectionMap, next) {
355347
async.waterfall([
356348
function (cb) {
357349
api.dataAccess.executeQuery("get_user_email_and_handle", {
@@ -363,7 +355,7 @@ var sendNotificationEmail = function (api, componentInfo, userId, dbConnectionMa
363355
cb(new NotFoundError("user's email and handle not found"));
364356
return;
365357
}
366-
var user, projectName, documentationDetails, submitURL, activeForumCategoryId, forumURL, umlToolInfo;
358+
var user, projectName, documentationDetails, submitURL, forumURL, umlToolInfo;
367359

368360
user = result[0];
369361
projectName = componentInfo.project_name + api.helper.getPhaseName(componentInfo.phase_id) + ' Contest';
@@ -378,7 +370,7 @@ var sendNotificationEmail = function (api, componentInfo, userId, dbConnectionMa
378370

379371
if (componentInfo.phase_id === 112 || componentInfo.phase_id === 113) {
380372
umlToolInfo = "You can read more about our UML tool and download it at\n" +
381-
"http://www.topcoder.com/tc?module=Static&d1=dev&d2=umltool&d3=description\n\n";
373+
"http://www.topcoder.com/tc?module=Static&d1=dev&d2=umltool&d3=description\n\n";
382374
}
383375

384376
//NOTE : forumURL is out of scope, here use a mock value instead. See http://apps.topcoder.com/forums/?module=Thread&threadID=811696&start=0
@@ -403,6 +395,80 @@ var sendNotificationEmail = function (api, componentInfo, userId, dbConnectionMa
403395
], next);
404396
};
405397

398+
/*
399+
* Get the active forum category id of the specified challenge.
400+
*
401+
* @param {Object} api The api object that is used to access the infrastructure.
402+
* @param {Object} componentInfo The component info object generated from method <code>registerComponentInquiry</code>.
403+
* @param {Number} challengeId The challenge id.
404+
* @param {Object} dbConnectionMap The database connection map for the current request.
405+
* @param {Function<err, data>} next The callback to be called after this function is done.
406+
*/
407+
var getActiveForumCategoryId = function (api, componentInfo, challengeId, dbConnectionMap, next) {
408+
async.waterfall([
409+
function (cb) {
410+
if (componentInfo.component_id === null) {
411+
api.log('Could not find component for challenge ' + challengeId, 'error');
412+
next(new Error('Could not find component for challenge ' + challengeId));
413+
return;
414+
}
415+
api.dataAccess.executeQuery("get_active_forum_category", {componentId: componentInfo.component_id}, dbConnectionMap, cb);
416+
},
417+
function (result, cb) {
418+
if (result.length === 0) {
419+
api.log('Could not find forum for challenge ' + challengeId, 'debug');
420+
cb(null, null);
421+
return;
422+
}
423+
424+
cb(null, result[0].jive_category_id);
425+
}
426+
], next);
427+
};
428+
429+
/*
430+
* Grant user forum access
431+
*
432+
* @param {Object} api The api object that is used to access the infrastructure.
433+
* @param {Number} userId The current logged-in user's id.
434+
* @param {Number} challengeId The challenge id.
435+
* @param {Function<err, data>} next The callback to be called after this function is done.
436+
*/
437+
var grantForumAccess = function (api, userId, activeForumCategoryId, next) {
438+
439+
if (api.config.general.grantForumAccess !== true) {
440+
next();
441+
return;
442+
}
443+
444+
if (activeForumCategoryId === null) {
445+
api.log('Could not find forum category ' + activeForumCategoryId, 'error');
446+
next(new Error('Could not find forum category ' + activeForumCategoryId));
447+
return;
448+
}
449+
450+
api.log('start to grant user ' + userId + ' forum category ' + activeForumCategoryId + ' access.');
451+
async.waterfall([
452+
function (cb) {
453+
api.challengeHelper.getForumWrapper(api, cb);
454+
}, function (forumWrapper, cb) {
455+
forumWrapper.assignRole(userId, "Software_Users_" + activeForumCategoryId, function (err) {
456+
if (err) {
457+
api.log('Failed to grant user ' + userId + ' forum category ' + activeForumCategoryId + ' access:' + err + " " + (err.stack || ''), 'error');
458+
cb(new Error('Failed to grant user ' + userId + ' forum category ' + activeForumCategoryId + ' access'));
459+
}
460+
cb();
461+
});
462+
}
463+
], function (err) {
464+
if (err) {
465+
next(err);
466+
return;
467+
}
468+
next();
469+
});
470+
};
471+
406472
/**
407473
* Register a development (software) challenge for the current logged-in user.
408474
*
@@ -430,10 +496,24 @@ var registerSoftwareChallenge = function (api, userId, challengeId, dbConnection
430496
cb(err);
431497
});
432498
},
499+
433500
function (cb) {
434-
//Send notification mail
435-
sendNotificationEmail(api, componentInfo, userId, dbConnectionMap, cb);
501+
getActiveForumCategoryId(api, componentInfo, challengeId, dbConnectionMap, cb);
502+
},
503+
504+
function (activeForumCategoryId, cb) {
505+
async.waterfall([
506+
function (cbx) {
507+
// Grant forum access
508+
grantForumAccess(api, userId, activeForumCategoryId, cbx);
509+
},
510+
function (cbx) {
511+
// Send notification mail
512+
sendNotificationEmail(api, componentInfo, userId, activeForumCategoryId, dbConnectionMap, cbx);
513+
}
514+
], cb);
436515
}
516+
437517
], next);
438518
};
439519

@@ -484,7 +564,7 @@ var persistStudioChallengeResouce = function (api, userId, challengeId, dbConnec
484564
},
485565
function (cb) {
486566
//Registration time
487-
persistResourceInfo(api, resourceId, 6, moment().format("MM.dd.yyyy hh:mm aa"), userId, dbConnectionMap, cb);
567+
persistResourceInfo(api, resourceId, 6, moment().format("MM.DD.YYYY hh:mm A"), userId, dbConnectionMap, cb);
488568
},
489569
function (cb) {
490570
//payments.
@@ -528,6 +608,8 @@ var timelineNotification = function (api, userId, challengeId, dbConnectionMap,
528608
},
529609
dbConnectionMap,
530610
cb);
611+
} else {
612+
cb(null);
531613
}
532614
}
533615
], next);
@@ -566,23 +648,23 @@ var registerSoftwareChallengeAction = function (api, connection, next) {
566648
if (connection.dbConnectionMap) {
567649
api.log("Execute registerSoftwareChallengeAction#run", 'debug');
568650

569-
var challengeId = Number(connection.params.challengeId);
570-
var sqlParams = {
571-
challengeId: challengeId,
572-
user_id: connection.caller.userId
573-
};
574-
var execQuery = function (name) {
575-
return function (cbx) {
576-
api.dataAccess.executeQuery(name, sqlParams, connection.dbConnectionMap, cbx);
651+
var challengeId = Number(connection.params.challengeId),
652+
sqlParams = {
653+
challengeId: challengeId,
654+
user_id: connection.caller.userId
655+
},
656+
execQuery = function (name) {
657+
return function (cbx) {
658+
api.dataAccess.executeQuery(name, sqlParams, connection.dbConnectionMap, cbx);
659+
};
577660
};
578-
};
579661
async.waterfall([
580-
function(cb) {
662+
function (cb) {
581663
async.parallel({
582664
isCopilotPosting: execQuery('check_challenge_is_copilot_posting'),
583665
isCopilot: execQuery('check_is_copilot')
584666
}, cb);
585-
}, function(res, cb) {
667+
}, function (res, cb) {
586668
if (res.isCopilotPosting.length > 0 && res.isCopilotPosting[0].challenge_is_copilot) {
587669
if (res.isCopilot.length === 0 || !res.isCopilot[0].user_is_copilot) {
588670
cb(new ForbiddenError('You should be a copilot before register a copilot posting.'));

0 commit comments

Comments
 (0)