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

Commit e82591b

Browse files
author
fireice.topcoder
committed
Merge branch 'dev' of github.com:cloudspokes/tc-api into dev
2 parents 4af5958 + c56be88 commit e82591b

25 files changed

+600
-84
lines changed

actions/rounds.js

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ var TIME_FILTER_COLUMNS = [
6565

6666
// the sort columns
6767
var SORT_COLUMNS = {
68+
"name": "name",
6869
"registrationPhaseStartTime": "start_time_1",
6970
"registrationPhaseEndTime": "end_time_1",
7071
"codingPhaseStartTime": "start_time_2",
@@ -274,7 +275,7 @@ var getRounds = function (api, connection, dbConnectionMap, next) {
274275
filterCondition = ' r.round_id > 0 ';
275276
if (_.isDefined(params.name)) {
276277
// set name filter
277-
filterCondition = filterCondition + ' AND LOWER(name) LIKE LOWER("%' + decodeURIComponent(params.name) + '%")';
278+
filterCondition = filterCondition + ' AND LOWER(r.name) LIKE LOWER("%' + decodeURIComponent(params.name) + '%")';
278279
}
279280

280281
if (statusCondition !== '') {
@@ -344,7 +345,15 @@ var getRounds = function (api, connection, dbConnectionMap, next) {
344345
"registrationLimit": rounds[i].registration_limit,
345346
"invitationalType": rounds[i].invitational ? rounds[i].invitational.trim() : rounds[i].invitational,
346347
"region": rounds[i].region_name,
347-
"roundSchedule": []
348+
"contestId": rounds[i].contest_id,
349+
"contestName": rounds[i].contest_name,
350+
"contestStatus": rounds[i].contest_status,
351+
"hasProblems": rounds[i].has_problems.trim() === 'true',
352+
"hasTerms": rounds[i].has_terms.trim() === 'true',
353+
"hasSchedule": rounds[i].has_schedule.trim() === 'true',
354+
"hasQuestions": rounds[i].has_questions.trim() === 'true',
355+
"roundSchedule": [],
356+
"languages": []
348357
};
349358

350359
for (j = 1; j <= 7; j++) {
@@ -364,26 +373,43 @@ var getRounds = function (api, connection, dbConnectionMap, next) {
364373

365374
if (idStr !== '') {
366375
sqlParams.roundIdList = idStr;
367-
// get round terms
368-
api.dataAccess.executeQuery("get_round_terms_by_ids",
369-
sqlParams,
370-
dbConnectionMap,
371-
cb);
376+
async.parallel({
377+
languages: function (cbx) {
378+
api.dataAccess.executeQuery("get_round_language_by_ids",
379+
sqlParams,
380+
dbConnectionMap,
381+
cbx);
382+
},
383+
terms: function (cbx) {
384+
api.dataAccess.executeQuery("get_round_terms_by_ids",
385+
sqlParams,
386+
dbConnectionMap,
387+
cbx);
388+
}
389+
}, cb);
372390
} else {
373391
cb(null, null);
374392
}
375393
}, function (results, cb) {
376394
var j;
377395
if (results !== null) {
378-
for (i = 0; i < results.length; i++) {
396+
for (i = 0; i < results.terms.length; i++) {
379397
for (j = 0; j < data.length; j++) {
380398
// only return the first term
381-
if (results[i].round_id === data[j].id && !data[j]["roundTerms"]) {
382-
data[j]["roundTerms"] = results[i].terms_content;
399+
if (results.terms[i].round_id === data[j].id && !data[j]["roundTerms"]) {
400+
data[j]["roundTerms"] = results.terms[i].terms_content;
383401
break;
384402
}
385403
}
386404
}
405+
406+
for (i = 0; i < results.languages.length; i++) {
407+
for (j = 0; j < data.length; j++) {
408+
if (results.languages[i].round_id === data[j].id) {
409+
data[j]["languages"].push({"id": results.languages[i].language_id, "description": results.languages[i].language_name});
410+
}
411+
}
412+
}
387413
}
388414

389415
result.data = data;
@@ -408,7 +434,7 @@ exports.getRounds = {
408434
description: "Get Rounds",
409435
inputs: {
410436
required: [],
411-
optional: ["pageSize", "pageIndex", "sortColumn", "sortOrder"].concat(FILTER_COLUMNS).concat(TIME_FILTER_COLUMNS)
437+
optional: ["pageSize", "pageIndex", "sortColumn", "sortOrder", "name"].concat(FILTER_COLUMNS).concat(TIME_FILTER_COLUMNS)
412438
},
413439
blockedConnectionTypes: [],
414440
outputExample: {},

actions/srmRoundComponentsAndTerms.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function checkDefinedNonNegativeInteger(value, name, error, helper) {
5959
* @param callback the callback method
6060
*/
6161
function checkComponents(api, dbConnectionMap, components, callback) {
62-
var helper = api.helper, error = helper.checkArray(components, "components", false), existingComponentDivisionIds = [];
62+
var helper = api.helper, error = helper.checkArray(components, "components", true), existingComponentDivisionIds = [];
6363
if (error) {
6464
callback(error);
6565
return;
@@ -202,7 +202,7 @@ var setRoundComponents = function (api, connection, dbConnectionMap, next) {
202202
var helper = api.helper,
203203
sqlParams = {},
204204
roundId = Number(connection.params.roundId),
205-
components = connection.params.components;
205+
components = connection.params.components || [];
206206

207207
async.waterfall([
208208
function (cb) {
@@ -348,8 +348,8 @@ exports.setRoundComponents = {
348348
name: "setRoundComponents",
349349
description: "Set Round Components",
350350
inputs: {
351-
required: ['roundId', 'components'],
352-
optional: []
351+
required: ['roundId'],
352+
optional: ['components']
353353
},
354354
blockedConnectionTypes: [],
355355
outputExample: {},

apiary.apib

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6943,31 +6943,35 @@ Request
69436943
"roundId": 6,
69446944
"roundName": "Past Srm Round",
69456945
"divisionDescription": "Unrated Division",
6946-
"levelDescription": "Level 2001"
6946+
"levelDescription": "Level 2001",
6947+
"editorialLink": "http://editlink6"
69476948
},
69486949
{
69496950
"contestId": 3006,
69506951
"contestName": "Contest 3006",
69516952
"roundId": 7,
69526953
"roundName": "Past Tournament Round",
69536954
"divisionDescription": "Division-I",
6954-
"levelDescription": "Level 2001"
6955+
"levelDescription": "Level 2001",
6956+
"editorialLink": "http://editlink7"
69556957
},
69566958
{
69576959
"contestId": 3007,
69586960
"contestName": "Contest 3007",
69596961
"roundId": 8,
69606962
"roundName": "Past Long Round",
69616963
"divisionDescription": "Division-II",
6962-
"levelDescription": "Level 2001"
6964+
"levelDescription": "Level 2001",
6965+
"editorialLink": "http://editlink8"
69636966
},
69646967
{
69656968
"contestId": 3008,
69666969
"contestName": "Contest 3008",
69676970
"roundId": 9,
69686971
"roundName": "Past Event Round",
69696972
"divisionDescription": "No Division Applicable",
6970-
"levelDescription": "Level 2001"
6973+
"levelDescription": "Level 2001",
6974+
"editorialLink": "http://editlink9"
69716975
}
69726976
]
69736977
}
@@ -8297,7 +8301,7 @@ Request
82978301
},
82988302
"languages": {
82998303
"roundId": 40006,
8300-
languages [
8304+
"languages": [
83018305
{
83028306
"id": 1,
83038307
"description": "Java"
@@ -15783,7 +15787,7 @@ Source Code Image Generation APIs
1578315787
+ Parameters
1578415788
+ pageIndex (optional, number, `1`) ... The paging number, 1-based, -1 if no paging. It can be null.
1578515789
+ pageSize (optional, number, `50`) ... The max number of the results, should be set if pageIndex is set.
15786-
+ sortColumn (optional, string, `registrationPhaseStartTime`) ... The column name to sort, can be null. It should be one of registrationPhaseStartTime, registrationPhaseEndTime, codingPhaseStartTime, codingPhaseEndTime, intermissionPhaseStartTime, intermissionPhaseEndTime, challengePhaseStartTime, challengePhaseEndTime, systemTestPhaseStartTime, systemTestPhaseEndTime, roomAssignmentPhaseStartTime, roomAssignmentPhaseEndTime, moderatedChatPhaseStartTime, moderatedChatPhaseEndTime.
15790+
+ sortColumn (optional, string, `registrationPhaseStartTime`) ... The column name to sort, can be null. It should be one of name,registrationPhaseStartTime, registrationPhaseEndTime, codingPhaseStartTime, codingPhaseEndTime, intermissionPhaseStartTime, intermissionPhaseEndTime, challengePhaseStartTime, challengePhaseEndTime, systemTestPhaseStartTime, systemTestPhaseEndTime, roomAssignmentPhaseStartTime, roomAssignmentPhaseEndTime, moderatedChatPhaseStartTime, moderatedChatPhaseEndTime.
1578715791
+ sortOrder (optional, string, `desc`) ... The sort order, can be null. It should be one of desc or asc.
1578815792
+ name (optional, string, `test`) ... The name filter, can be null. It should be encoded in uri format. It's case insensitive and it could be only part of name to filter.
1578915793
+ type (optional, string, `Single%20Round%20Match`) ... The type filter, can be null. It should be encoded in uri format. It's case insensitive. It should be values in round_type_lu table description field. It could use ',' char to connect more than 1 value.
@@ -15838,6 +15842,13 @@ Source Code Image Generation APIs
1583815842
"Registration Limit": 1000,
1583915843
"Invitational Type": "Not",
1584015844
"Region": "Alpha",
15845+
"contestId": 12917,
15846+
"contestName": "Test SRM",
15847+
"contestStatus": "A",
15848+
"hasProblems": true,
15849+
"hasTerms": true,
15850+
"hasSchedule": true,
15851+
"hasQuestions": false,
1584115852
"Round Schedule": [
1584215853
{
1584315854
"Phase Name": "Registration Phase",
@@ -15881,7 +15892,17 @@ Source Code Image Generation APIs
1588115892
"End Time": "2013-12-15T05:50:51.000+05:00",
1588215893
"Status": "Draft"
1588315894
}
15884-
]
15895+
],
15896+
"languages": [
15897+
{
15898+
"id": 1,
15899+
"description": "Java"
15900+
},
15901+
{
15902+
"id": 2,
15903+
"description": "XML"
15904+
}
15905+
]
1588515906
}
1588615907
]
1588715908
}

deploy/development.bat

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,6 @@ set WATERMARK_FILE_PATH=test/test_files/design_image_file_generator/studio_logo_
9090

9191
set WKHTMLTOIMAGE_COMMAND_PATH=/home/ubuntu/tmp/wkhtmltox-0.12.1/static-build/posix-local/wkhtmltox-0.12.1/bin/wkhtmltoimage
9292
set WKHTMLTOIMAGE_IMAGE_WIDTH=1024
93-
set HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css
93+
set HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css
94+
95+
set JWT_TOKEN_COOKIE_KEY="tcjwt_vm"

deploy/development.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,5 @@ export WATERMARK_FILE_PATH=test/test_files/design_image_file_generator/studio_lo
9696
export WKHTMLTOIMAGE_COMMAND_PATH=/home/ubuntu/tmp/wkhtmltox-0.12.1/static-build/posix-local/wkhtmltox-0.12.1/bin/wkhtmltoimage
9797
export WKHTMLTOIMAGE_IMAGE_WIDTH=1024
9898
export HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css
99+
100+
export JWT_TOKEN_COOKIE_KEY="tcjwt_vm"

initializers/middleware.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,27 @@ exports.middleware = function (api, next) {
8181
isCachedReturned,
8282
cacheKey,
8383
socialUserId,
84-
socialProvider;
85-
if (!_.isDefined(authHeader)) {
84+
socialProvider,
85+
cookieToken = api.utils.parseCookies(connection.rawConnection.req)[process.env.JWT_TOKEN_COOKIE_KEY];
86+
87+
if (_.isUndefined(authHeader) && _.isUndefined(cookieToken)) {
8688
connection.caller = {accessLevel: "anon"};
8789
next(connection, true);
8890
return;
8991
}
92+
9093
async.waterfall([
9194
function (cb) {
92-
var reg = /^bearer ([\s\S]+)$/i;
93-
if (!reg.test(authHeader)) {
94-
cb(new IllegalArgumentError("Malformed Auth header"));
95-
return;
95+
if (_.isUndefined(authHeader)) {
96+
cb(null, cookieToken);
97+
} else {
98+
var reg = /^bearer ([\s\S]+)$/i;
99+
if (!reg.test(authHeader)) {
100+
cb(new IllegalArgumentError("Malformed Auth header"));
101+
return;
102+
}
103+
cb(null, reg.exec(authHeader)[1]);
96104
}
97-
cb(null, reg.exec(authHeader)[1]);
98105
}, function (token, cb) {
99106
jwt.verify(token,
100107
api.config.tcConfig.oauthClientSecret,
@@ -107,6 +114,11 @@ exports.middleware = function (api, next) {
107114
return;
108115
}
109116
var split = decoded.sub.split("|");
117+
if (split.length == 1) {
118+
// token.sub should contain "|"
119+
cb(new IllegalArgumentError('Malformed Auth header. token.sub is in bad format!'));
120+
return;
121+
}
110122
try {
111123
socialUserId = (split[split.length-1] || "").trim();
112124
socialProvider = (split[0] || "").trim();
@@ -212,7 +224,8 @@ exports.middleware = function (api, next) {
212224
//error messages returned by jwt.verify(...) method
213225
if (err.message.indexOf('Invalid token') !== -1 ||
214226
String(err.message).startsWith("jwt audience invalid.") ||
215-
err.message === "invalid signature") {
227+
err.message === "invalid signature" ||
228+
err.message === "jwt malformed") {
216229
errorMessage = "Malformed Auth header";
217230
baseError = api.helper.apiCodes.badRequest;
218231
} else if (err.message === "jwt expired") {

queries/get_round_language_by_ids

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
select rl.round_id as round_id, l.language_id as language_id, l.language_name as language_name from round_language rl, language l where rl.language_id = l.language_id and rl.round_id in (@roundIdList@)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name" : "get_round_language_by_ids",
3+
"db" : "informixoltp",
4+
"sqlfile" : "get_round_language_by_ids"
5+
}

queries/get_rounds

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ SELECT
55
r.name as name,
66
r.short_name as short_name,
77
rt.round_type_desc,
8+
c.contest_id as contest_id,
9+
c.name as contest_name,
10+
c.status as contest_status,
811
CASE WHEN (UPPER(r.status) = 'A') THEN
912
'Active'
1013
WHEN (UPPER(r.status) = 'P') THEN
@@ -99,12 +102,31 @@ SELECT
99102
'Draft'
100103
ELSE NULL
101104
END as status_7,
102-
(select segment_desc from segment where segment_id = 7) as name_7
105+
(select segment_desc from segment where segment_id = 7) as name_7,
106+
CASE WHEN ((select count(*) from round_component rc where rc.round_id = r.round_id) > 0) THEN
107+
'true'
108+
ELSE 'false'
109+
END AS has_problems,
110+
CASE WHEN ((select count(*) from round_terms rt where rt.round_id = r.round_id) > 0) THEN
111+
'true'
112+
ELSE 'false'
113+
END AS has_terms,
114+
CASE WHEN ((select count(*) from round_segment rs where rs.round_id = r.round_id) > 0) THEN
115+
'true'
116+
ELSE 'false'
117+
END AS has_schedule,
118+
CASE WHEN ((select count(*) from round_question rq where rq.round_id = r.round_id) > 0) THEN
119+
'true'
120+
ELSE 'false'
121+
END AS has_questions
122+
103123
FROM (round r
104124
LEFT OUTER JOIN round_type_lu rt
105125
ON r.round_type_id=rt.round_type_id
106126
LEFT OUTER JOIN region reg
107127
ON r.region_id=reg.region_id
128+
LEFT OUTER JOIN contest c
129+
ON r.contest_id=c.contest_id
108130
LEFT OUTER JOIN round_segment rs1
109131
ON r.round_id=rs1.round_id and rs1.segment_id = 1
110132
LEFT OUTER JOIN round_segment rs2

queries/get_rounds_for_problem

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ SELECT
44
r.contest_id,
55
(SELECT name FROM contest c WHERE c.contest_id = r.contest_id) AS contest_name,
66
(SELECT division_desc FROM division_lu d WHERE p.division_id = d.division_id) AS division_description,
7-
p.level_desc AS level_description
7+
p.level_desc AS level_description,
8+
r.editorial_link
89
FROM
910
problem p,
1011
round r

0 commit comments

Comments
 (0)