diff --git a/.gitignore b/.gitignore index fda4d8551..6f4d22e1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +*.iml +*.ipr +*.iws *.log log pids @@ -10,3 +13,5 @@ test/tmp/design_tmp_submissions/*.zip test/tmp/memberPhoto/* .idea .settings +**/jdk-8u51-linux-x64.gz +*.swp diff --git a/actions/admins.js b/actions/admins.js new file mode 100755 index 000000000..3348a70cd --- /dev/null +++ b/actions/admins.js @@ -0,0 +1,272 @@ +/*jslint nomen: true */ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +var _ = require('underscore'); +var async = require('async'); +var DuplicateResourceError = require('../errors/DuplicateResourceError'); + +/** + * This is the function that will actually get all admins. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var getAdmins = function (api, connection, dbConnectionMap, next) { + var helper = api.helper; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.')); + }, function (cb) { + api.dataAccess.executeQuery("get_admins", {}, dbConnectionMap, cb); + }, function (result, cb) { + var ret = {}, i, entity, type, id; + for (i = 0; i < result.length; i = i + 1) { + type = result[i].type.trim(); + id = result[i].user_id; + if (!ret[id]) { + ret[id] = { + id: result[i].user_id, + name: result[i].handle, + adminGroup: false, + adminRole: false, + managerResource: false + }; + } + entity = ret[id]; + if (type === 'Admin Group') { + entity.adminGroup = true; + } else if (type === 'Admin Role') { + entity.adminRole = true; + } else if (type === 'Manager Resource') { + entity.managerResource = true; + } + } + cb(null, { + allAdmins: _.values(ret) + }); + }], function (err, result) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); +}; + +/** + * The API for getting all admins + */ +exports.admins = { + name: "admins", + description: "retrieve all TopCoder admins", + inputs: { + required: [], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'read', // this action is read-only + databases: ['tcs_catalog'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute admins#run", 'debug'); + getAdmins(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; + +/** + * This is the function that will actually create admin. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var createAdmin = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, username = connection.params.username, userId, operatorId, parameters, + result = { + success: true + }; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.')); + }, function (cb) { + operatorId = connection.caller.userId; + helper.validateUserAndGetUserId(username, dbConnectionMap, cb); + }, function (id, cb) { + userId = id; + async.auto({ + nextUserGroupId: function (ca) { + api.dataAccess.executeQuery("get_next_admin_user_group_id", {}, dbConnectionMap, ca); + }, + nextResourceId: function (ca) { + api.dataAccess.executeQuery("get_next_admin_resource_id", {}, dbConnectionMap, ca); + } + }, cb); + }, function (results, cb) { + parameters = { + userId: userId, + userGroupId: results.nextUserGroupId[0].next_id, + operatorId: operatorId, + resourceId: results.nextResourceId[0].next_id + }; + api.dataAccess.executeQuery("insert_admin_group", parameters, dbConnectionMap, function (err) { + if (helper.isDuplicateResourceError(err)) { + cb(new DuplicateResourceError("User " + username + " has already been added to Admin Group", err)); + } else { + cb(err); + } + }); + }, function (cb) { + api.dataAccess.executeQuery("clear_user_rating", parameters, dbConnectionMap, function (err) { + cb(err); + }); + }, function (cb) { + api.dataAccess.executeQuery("get_admin_resource", { + userId: userId + }, dbConnectionMap, cb); + }, function (resourceIds, cb) { + if (!resourceIds || !resourceIds.length) { + api.dataAccess.executeQuery("insert_new_admin_resource", parameters, dbConnectionMap, function (err) { + if (err) { + return cb(err); + } + api.dataAccess.executeQuery("insert_new_admin_resource_info", parameters, dbConnectionMap, function (err) { + cb(err); + }); + }); + } else { + cb(null); + } + }, function (cb) { + api.dataAccess.executeQuery("insert_admin_role", parameters, dbConnectionMap, function (err) { + if (helper.isDuplicateResourceError(err)) { + cb(new DuplicateResourceError("User " + username + " has already been assigned Admin role", err)); + } else { + cb(err); + } + }); + }], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + result.message = username + " has been successfully added as TopCoder Admin"; + connection.response = result; + } + next(connection, true); + }); + +}; + +/** + * The API for creating admin + */ +exports.createAdmin = { + name: "createAdmin", + description: "create TopCoder admin", + inputs: { + required: ['username'], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'write', + databases: ['tcs_catalog', 'common_oltp'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute createAdmin#run", 'debug'); + createAdmin(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; + +/** + * This is the function that will actually remove admin. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var removeAdmin = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, username = connection.params.username, operatorId, parameters, + result = { + success: true + }; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.')); + }, function (cb) { + operatorId = connection.caller.userId; + helper.validateUserAndGetUserId(username, dbConnectionMap, cb); + }, function (userId, cb) { + parameters = { + userId: userId, + operatorId: operatorId + }; + api.dataAccess.executeQuery("remove_admin_group", parameters, dbConnectionMap, function (err) { + cb(err); + }); + }, function (cb) { + api.dataAccess.executeQuery("remove_admin_resource_info", parameters, dbConnectionMap, function (err) { + cb(err); + }); + }, function (cb) { + api.dataAccess.executeQuery("remove_admin_resource", parameters, dbConnectionMap, function (err) { + cb(err); + }); + }, function (cb) { + api.dataAccess.executeQuery("remove_admin_role", parameters, dbConnectionMap, function (err) { + cb(err); + }); + }], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + result.message = "TopCoder Admin: " + username + " has been successfully removed"; + connection.response = result; + } + next(connection, true); + }); + +}; + +/** + * The API for removing admin + */ +exports.removeAdmin = { + name: "removeAdmin", + description: "remove TopCoder admin", + inputs: { + required: ['username'], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'write', + databases: ['tcs_catalog', 'common_oltp'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute removeAdmin#run", 'debug'); + removeAdmin(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; diff --git a/actions/challengeRegistration.js b/actions/challengeRegistration.js index f50077b66..0d558f628 100644 --- a/actions/challengeRegistration.js +++ b/actions/challengeRegistration.js @@ -3,8 +3,8 @@ * * The APIs to register a challenge (studio category or software category) for the current logged-in user. * - * @version 1.7 - * @author ecnu_haozi, xjtufreeman, bugbuka, flytoj2ee, muzehyun + * @version 1.8 + * @author ecnu_haozi, xjtufreeman, bugbuka, flytoj2ee, muzehyun, GFalcon * * changes in 1.1: * Combine Challenge Registration API(BUGR-11058) @@ -27,6 +27,9 @@ * * changes in 1.7: * Avoid reliability info set if there is none for new user. + * + * changes in 1.8: + * Added the verification of the challenge's eligibility */ "use strict"; @@ -401,7 +404,7 @@ var sendNotificationEmail = function (api, componentInfo, userId, activeForumCat if (challengeType === CHALLENGE_TYPE.DEVELOP) { forumURL = api.config.tcConfig.developForumsUrlPrefix + activeForumCategoryId; reviewURL = process.env.TC_SOFTWARE_SERVER_NAME + '/review/actions/ViewProjectDetails?pid=' + challengeId; - submitURL = process.env.TC_ACTIVATION_SERVER_NAME + '/challenge-details/' + challengeId + '/submit/?type=develop'; + submitURL = process.env.TC_WWW_SERVER_NAME + '/challenge-details/' + challengeId + '/submit/?type=develop'; } else if (challengeType === CHALLENGE_TYPE.DESIGN) { forumURL = api.config.tcConfig.studioForumsUrlPrefix + activeForumCategoryId; //submitURL = process.env.TC_STUDIO_SERVER_NAME + '/?module=ViewContestDetails&ct=' + challengeId; @@ -880,19 +883,31 @@ exports.registerChallenge = { } else { api.helper.checkUserActivated(connection.caller.handle, api, connection.dbConnectionMap, function (err, inactive) { var fail = err || inactive; - if (fail) cb(fail); - else api.dataAccess.executeQuery('check_challenge_exists', {challengeId: challengeId}, connection.dbConnectionMap, cb); + if (fail) { + cb(fail); + } else { + api.dataAccess.executeQuery('check_challenge_exists', {challengeId: challengeId}, connection.dbConnectionMap, cb); + } }, "You must activate your account in order to participate. Please check your e-mail in order to complete the activation process, or contact support@topcoder.com if you did not receive an e-mail."); } - }, function (result, cb) { - if (result.length > 0) { - if (result[0].is_studio) { - registerStudioChallengeAction(api, connection, next); - } else { - registerSoftwareChallengeAction(api, connection, next); - } - } else { + }, function(result, cb) { + // If the challenge is not found in the tcs_catalog:project table, + if (result.length === 0) { + // Do nothing, do not register cb(); + return; + } + var isStudio = result[0].is_studio !== 0; + api.challengeHelper.checkUserChallengeEligibility(connection, challengeId, function (err) { + cb(err, isStudio); + }); + }, function (isStudio, cb) { + if (_.isUndefined(isStudio)) { + cb(); + } else if (isStudio) { + registerStudioChallengeAction(api, connection, next); + } else { + registerSoftwareChallengeAction(api, connection, next); } } ], function (err) { diff --git a/actions/challenges.js b/actions/challenges.js index f4c342168..bb4d6ceb9 100755 --- a/actions/challenges.js +++ b/actions/challenges.js @@ -1,9 +1,9 @@ /* * Copyright (C) 2013 - 2014 TopCoder Inc., All Rights Reserved. * - * @version 1.31 + * @version 1.32 * @author Sky_, mekanizumu, TCSASSEMBLER, freegod, Ghost_141, kurtrips, xjtufreeman, ecnu_haozi, hesibo, LazyChild, - * @author isv, muzehyun, bugbuka + * @author isv, muzehyun, bugbuka, GFalcon * @changes from 1.0 * merged with Member Registration API * changes in 1.1: @@ -79,9 +79,12 @@ * - Update challenge type filter. * Changes in 1.31: * - Remove screeningScorecardId and reviewScorecardId from search challenges api. + * Changes in 1.32: + * - validateChallenge, getRegistrants, getChallenge, getSubmissions and getPhases functions now check + * if an user belongs to a group via user_group_xref for old challenges and by calling V3 API for new ones. */ "use strict"; -/*jslint stupid: true, unparam: true, continue: true */ +/*jslint stupid: true, unparam: true, continue: true, nomen: true */ require('datejs'); var fs = require('fs'); @@ -851,7 +854,7 @@ var addFilter = function (sql, filter, isMyChallenges, helper, caller) { * @since 1.10 */ function validateChallenge(api, connection, dbConnectionMap, challengeId, isStudio, callback) { - var error, sqlParams, helper = api.helper; + var error, sqlParams, helper = api.helper, userId = (connection.caller.userId || 0); async.waterfall([ function (cb) { error = helper.checkPositiveInteger(challengeId, 'challengeId') || @@ -862,31 +865,18 @@ function validateChallenge(api, connection, dbConnectionMap, challengeId, isStud } sqlParams = { challengeId: challengeId, - user_id: connection.caller.userId || 0 + user_id: userId }; - async.parallel({ - accessibility: function (cbx) { - api.dataAccess.executeQuery('check_user_challenge_accessibility', sqlParams, dbConnectionMap, cbx); - }, - exists: function (cbx) { - api.dataAccess.executeQuery('check_challenge_exists', sqlParams, dbConnectionMap, cbx); - } - }, cb); + api.dataAccess.executeQuery('check_challenge_exists', sqlParams, dbConnectionMap, cb); }, function (res, cb) { - if (res.exists.length === 0 || Boolean(res.exists[0].is_studio) !== isStudio) { + // If the record with this callengeId doesn't exist in 'project' table + // or there's a studio/software mismatch + if (res.length === 0 || Boolean(res[0].is_studio) !== isStudio) { cb(new NotFoundError("Challenge not found.")); return; } - var access = res.accessibility[0]; - if (access.is_private && !access.has_access && connection.caller.accessLevel !== "admin") { - if (connection.caller.accessLevel === "anon") { - cb(new UnauthorizedError()); - } else { - cb(new ForbiddenError()); - } - return; - } - cb(); + // Check the eligibility + api.challengeHelper.checkUserChallengeEligibility(connection, challengeId, cb); } ], callback); } @@ -1091,19 +1081,20 @@ var getChallenge = function (api, connection, dbConnectionMap, isStudio, next) { }; // Do the private check. + api.challengeHelper.checkUserChallengeEligibility( + connection, + connection.params.challengeId, + cb + ); + }, function (cb) { api.dataAccess.executeQuery('check_is_related_with_challenge', sqlParams, dbConnectionMap, cb); }, function (result, cb) { - if (result[0].is_private && !result[0].has_access) { - cb(new UnauthorizedError('The user is not allowed to visit the challenge.')); - return; - } - if (result[0].is_manager) { isManager = true; } // If the user has the access to the challenge or is a resource for the challenge then he is related with this challenge. - if (result[0].has_access || result[0].is_related || isManager || helper.isAdmin(caller)) { + if (result[0].is_private || result[0].is_related || isManager || helper.isAdmin(caller)) { isRelated = true; } @@ -2237,7 +2228,7 @@ exports.getChallengeTerms = { description: "getChallengeTerms", inputs: { required: ["challengeId"], - optional: ["role"] + optional: ["role", "noauth"] }, blockedConnectionTypes: [], outputExample: {}, @@ -2251,14 +2242,26 @@ exports.getChallengeTerms = { var challengeId = Number(connection.params.challengeId), role = connection.params.role, error; async.waterfall([ function (cb) { - api.challengeHelper.getChallengeTerms( - connection, - challengeId, - role, - true, - connection.dbConnectionMap, - cb - ); + if (connection.params.noauth) { + api.challengeHelper.getChallengeTermsNoAuth( + connection, + challengeId, + role, + true, + connection.dbConnectionMap, + cb + ); + } + else { + api.challengeHelper.getChallengeTerms( + connection, + challengeId, + role, + true, + connection.dbConnectionMap, + cb + ); + } }, function (results, cb) { var res = _.find(results, function (row) { return row.agreeabilityType === 'DocuSignable' && !row.templateId; @@ -3340,33 +3343,32 @@ var getRegistrants = function (api, connection, dbConnectionMap, isStudio, next) }; // Do the private check. - api.dataAccess.executeQuery('check_is_related_with_challenge', sqlParams, dbConnectionMap, cb); - }, function (result, cb) { - if (result[0].is_private && !result[0].has_access) { - cb(new UnauthorizedError('The user is not allowed to visit the challenge.')); - return; - } - + api.challengeHelper.checkUserChallengeEligibility( + connection, + connection.params.challengeId, + cb + ); + }, function (cb) { api.dataAccess.executeQuery('challenge_registrants', sqlParams, dbConnectionMap, cb); }, function (results, cb) { var mapRegistrants = function (results) { - if (!_.isDefined(results)) { - return []; + if (!_.isDefined(results)) { + return []; + } + return _.map(results, function (item) { + var registrant = { + handle: item.handle, + reliability: !_.isDefined(item.reliability) ? "n/a" : item.reliability + "%", + registrationDate: formatDate(item.inquiry_date), + submissionDate: formatDate(item.submission_date) + }; + if (!isStudio) { + registrant.rating = item.rating; + registrant.colorStyle = helper.getColorStyle(item.rating); } - return _.map(results, function (item) { - var registrant = { - handle: item.handle, - reliability: !_.isDefined(item.reliability) ? "n/a" : item.reliability + "%", - registrationDate: formatDate(item.inquiry_date), - submissionDate: formatDate(item.submission_date) - }; - if (!isStudio) { - registrant.rating = item.rating; - registrant.colorStyle = helper.getColorStyle(item.rating); - } - return registrant; - }); - }; + return registrant; + }); + }; registrants = mapRegistrants(results); cb(); } @@ -3438,18 +3440,16 @@ var getSubmissions = function (api, connection, dbConnectionMap, isStudio, next) submission_type: [helper.SUBMISSION_TYPE.challenge.id, helper.SUBMISSION_TYPE.checkpoint.id] }; - async.parallel({ - privateCheck: execQuery("check_is_related_with_challenge"), - challengeStatus: execQuery("get_challenge_status") - }, cb); - }, function (result, cb) { - if (result.privateCheck[0].is_private && !result.privateCheck[0].has_access) { - cb(new UnauthorizedError('The user is not allowed to visit the challenge.')); - return; - } - + api.challengeHelper.checkUserChallengeEligibility( + connection, + connection.params.challengeId, + cb + ); + }, + execQuery("get_challenge_status"), + function (result, cb) { // If the caller is not admin and challenge status is still active. - if (!helper.isAdmin(caller) && result.challengeStatus[0].challenge_status_id === 1) { + if (!helper.isAdmin(caller) && result[0].challenge_status_id === 1) { cb(new BadRequestError("The challenge is not finished.")); return; } @@ -3565,13 +3565,12 @@ var getPhases = function (api, connection, dbConnectionMap, isStudio, next) { }; // Do the private check. - api.dataAccess.executeQuery('check_is_related_with_challenge', sqlParams, dbConnectionMap, cb); - }, function (result, cb) { - if (result[0].is_private && !result[0].has_access) { - cb(new UnauthorizedError('The user is not allowed to visit the challenge.')); - return; - } - + api.challengeHelper.checkUserChallengeEligibility( + connection, + connection.params.challengeId, + cb + ); + }, function (cb) { var execQuery = function (name) { return function (cbx) { api.dataAccess.executeQuery(name, sqlParams, dbConnectionMap, cbx); diff --git a/actions/copilots.js b/actions/copilots.js new file mode 100755 index 000000000..2dc0b68dd --- /dev/null +++ b/actions/copilots.js @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; + +var async = require('async'); +var IllegalArgumentError = require('../errors/IllegalArgumentError'); +var DuplicateResourceError = require('../errors/DuplicateResourceError'); +var NotFoundError = require('../errors/NotFoundError'); + +/** + * This is the function that will actually get all copilots. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var getCopilots = function (api, connection, dbConnectionMap, next) { + var helper = api.helper; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.')); + }, function (cb) { + api.dataAccess.executeQuery("get_copilots", {}, dbConnectionMap, cb); + }, function (result, cb) { + var ret = [], i, entity; + for (i = 0; i < result.length; i = i + 1) { + entity = {}; + entity.id = result[i].user_id; + entity.name = result[i].handle; + entity.softwareCopilot = result[i].is_software_copilot; + entity.studioCopilot = result[i].is_studio_copilot; + ret.push(entity); + } + cb(null, { + allCopilots: ret + }); + }], function (err, result) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); +}; + +/** + * The API for getting all copilots + */ +exports.copilots = { + name: "copilots", + description: "retrieve all copilots", + inputs: { + required: [], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'read', // this action is read-only + databases: ['tcs_catalog'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute copilots#run", 'debug'); + getCopilots(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; + +/** + * This is the function that will actually create copilot. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var createCopilot = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, + username = connection.params.username, + isSoftwareCopilot = connection.params.isSoftwareCopilot, + isStudioCopilot = connection.params.isStudioCopilot, + userId, + operatorId, + parameters, + result = { + success: true + }; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.') + || helper.checkBoolean(isSoftwareCopilot, 'isSoftwareCopilot') + || helper.checkBoolean(isStudioCopilot, 'isStudioCopilot')); + }, function (cb) { + operatorId = connection.caller.userId; + helper.validateUserAndGetUserId(username, dbConnectionMap, cb); + }, function (id, cb) { + userId = id; + if (!isStudioCopilot && !isSoftwareCopilot) { + return cb(new IllegalArgumentError("Studio Copilot and Software Copilot Checkbox should have at least one checked")); + } + helper.getCopilotProfileIdByUserId(userId, dbConnectionMap, cb); + }, function (copilotProfileId, cb) { + if (copilotProfileId > 0) { + return cb(new DuplicateResourceError("The user " + username + " is already added as copilot")); + } + parameters = { + userId: userId, + isSoftwareCopilot: isSoftwareCopilot ? 't' : 'f', + isStudioCopilot: isStudioCopilot ? 't' : 'f', + operatorId: operatorId + }; + api.dataAccess.executeQuery("insert_new_copilot", parameters, dbConnectionMap, cb); + }, function (effectedRows, cb) { + if (effectedRows === 1) { + result.message = "Copilot " + username + " has been successfully added"; + } + cb(null); + }], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); + +}; + +/** + * The API for creating Copilot + */ +exports.createCopilot = { + name: "createCopilot", + description: "create copilot", + inputs: { + required: ['username', 'isSoftwareCopilot', 'isStudioCopilot'], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'write', + databases: ['tcs_catalog', 'common_oltp'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute createCopilot#run", 'debug'); + createCopilot(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; + +/** + * This is the function that will actually remove copilot. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var removeCopilot = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, username = connection.params.username, parameters, + result = { + success: true + }; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.')); + }, function (cb) { + helper.validateUserAndGetUserId(username, dbConnectionMap, cb); + }, function (userId, cb) { + parameters = { + userId: userId + }; + helper.getCopilotProfileIdByUserId(userId, dbConnectionMap, cb); + }, function (copilotProfileId, cb) { + if (copilotProfileId <= 0) { + return cb(new NotFoundError(username + " is not in the copilot pool")); + } + api.dataAccess.executeQuery("remove_copilot", parameters, dbConnectionMap, cb); + }, function (effectedRows, cb) { + if (effectedRows === 1) { + result.message = "Copilot " + username + " has been successfully removed"; + } + cb(null); + }], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); + +}; + +/** + * The API for removing copilot + */ +exports.removeCopilot = { + name: "removeCopilot", + description: "remove copilot", + inputs: { + required: ['username'], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'write', + databases: ['tcs_catalog', 'common_oltp'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute removeCopilot#run", 'debug'); + removeCopilot(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; diff --git a/actions/memberRegistration.js b/actions/memberRegistration.js index cb75d89cf..789bcb61f 100644 --- a/actions/memberRegistration.js +++ b/actions/memberRegistration.js @@ -396,7 +396,7 @@ var registerUser = function (user, api, dbConnectionMap, next) { }, function (callback) { var url; - url = process.env.TC_ACTIVATION_SERVER_NAME + '/reg2/activate.action?code=' + activationCode; + url = process.env.TC_ACTIVATION_SERVER_NAME + '?code=' + activationCode + '&retUrl=https://www.topcoder.com/skill-picker'; if (user.regSource && user.regSource.match(/arena/)) { url += '&destination=http%3A%2F%2Farena.topcoder.com'; } diff --git a/actions/reviewers.js b/actions/reviewers.js old mode 100644 new mode 100755 index a68421aee..2f2891f88 --- a/actions/reviewers.js +++ b/actions/reviewers.js @@ -1,10 +1,35 @@ +/*jslint nomen: true */ /* - * Copyright (C) 2013 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2013-2016 TopCoder Inc., All Rights Reserved. * - * @version 1.0 - * @author Sky_ + * @version 1.1 + * @author Sky_,TCSCODER + * Changes in 1.1: + * - add routes for Reviewer Management API + * - Add Reviewer + * - Remove Reviewer + * - Get All Reviewers */ "use strict"; +var _ = require('underscore'); +var async = require('async'); +var IllegalArgumentError = require('../errors/IllegalArgumentError'); +var NotFoundError = require('../errors/NotFoundError'); +var DuplicateResourceError = require('../errors/DuplicateResourceError'); + +/** + * The project type id for studio (design). + */ +var STUDIO_PROJECT_TYPE_ID = 3; +/** + * The category id of CODE. + */ +var CODE_CATEGORY_ID = 39; + +/** + * The category id of First2Finish. + */ +var F2F_CATEGORY_ID = 38; /** * Sample result from specification for Challenge Reviewers Collection @@ -12,8 +37,8 @@ var sampleReviewers; /** -* The API for getting challenge reviewers collection -*/ + * The API for getting challenge reviewers collection + */ exports.action = { name: "getChallengeReviewers", description: "getChallengeReviewers", @@ -60,4 +85,246 @@ sampleReviewers = { "photo": "4.gif" } ] -}; \ No newline at end of file +}; + +/** + * This is the function that will actually get all reviewers. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var getReviewers = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, categoryId = Number(connection.params.categoryId); + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.') + || helper.checkIdParameter(categoryId, 'categoryId')); + }, function (cb) { + api.dataAccess.executeQuery("get_reviewers", {categoryId: categoryId}, dbConnectionMap, cb); + }, function (result, cb) { + var ret = [], i, entity; + for (i = 0; i < result.length; i = i + 1) { + entity = {}; + entity.id = result[i].user_id; + entity.name = result[i].handle; + entity.projectCategoryId = result[i].project_category_id; + entity.projectCategoryName = result[i].project_category_name; + entity.immune = Number(result[i].immune_ind) === 1; + ret.push(entity); + } + cb(null, { + categoryId: categoryId, + reviewers: ret + }); + }], function (err, result) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); +}; + +/** + * The API for getting all reviewers of review board of a specific challenge category + */ +exports.reviewers = { + name: "reviewers", + description: "retrieve the reviewers of review board of a specific challenge category", + inputs: { + required: ['categoryId'], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'read', // this action is read-only + databases: ['tcs_catalog'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute reviewers#run", 'debug'); + getReviewers(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; + +/** + * This is the function that will actually create reviewer. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var createReviewer = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, + username = connection.params.username, + categoryId = Number(connection.params.categoryId), + immune = connection.params.immune, + userId, + operatorId, + parameters, + result = { + success: true + }; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.') + || helper.checkIdParameter(categoryId, 'categoryId') || + (_.isUndefined(immune) ? null : helper.checkBoolean(immune, 'immune'))); + }, function (cb) { + operatorId = connection.caller.userId; + helper.validateUserAndGetUserId(username, dbConnectionMap, cb); + }, function (id, cb) { + userId = id; + helper.getProjectCategoryByCategoryId(categoryId, dbConnectionMap, cb); + }, function (projectCategory, cb) { + if (!projectCategory) { + return cb(new IllegalArgumentError("Category Id " + categoryId + " is not a valid category ID")); + } + var isImmunity = projectCategory.typeId === STUDIO_PROJECT_TYPE_ID || categoryId === CODE_CATEGORY_ID || categoryId === F2F_CATEGORY_ID; + // will use immune from user input if exist + if (!_.isUndefined(immune)) { + isImmunity = immune; + } + // will use 1 or 0 finally + isImmunity = isImmunity ? 1 : 0; + parameters = { + userId: userId, + operatorId: operatorId, + categoryId: categoryId, + isImmunity: isImmunity + }; + api.dataAccess.executeQuery("insert_reviewer", parameters, dbConnectionMap, function (err, effectedRows) { + if (helper.isDuplicateResourceError(err)) { + cb(new DuplicateResourceError("User " + username + " is in the specific review board", err)); + } else { + if (!err && effectedRows === 1) { + result.message = username + " has been successfully added into " + projectCategory.name + " Review Board"; + } + cb(err); + } + }); + }], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); + +}; + +/** + * The API for creating reviewer + */ +exports.createReviewer = { + name: "createReviewer", + description: "add reviewer", + inputs: { + required: ['username', 'categoryId'], + optional: ['immune'] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'write', + databases: ['tcs_catalog', 'common_oltp'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute createReviewer#run", 'debug'); + createReviewer(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; + +/** + * This is the function that will actually remove reviewer. + * + * @param {Object} api The api object that is used to access the global infrastructure + * @param {Object} connection The connection object for the current request + * @param {Object} dbConnectionMap The database connection map for the current request + * @param {Function} next The callback to be called after this function is done + */ +var removeReviewer = function (api, connection, dbConnectionMap, next) { + var helper = api.helper, + username = connection.params.username, + categoryId = Number(connection.params.categoryId), + parameters, + userId, + projectCategory, + result = { + success: true + }; + async.waterfall([function (cb) { + cb(helper.checkAdmin(connection, "You need to login for this api.", 'You don\'t have access to this api.') + || helper.checkIdParameter(categoryId, 'categoryId')); + }, function (cb) { + helper.validateUserAndGetUserId(username, dbConnectionMap, cb); + }, function (id, cb) { + userId = id; + helper.getProjectCategoryByCategoryId(categoryId, dbConnectionMap, cb); + }, function (projectCategoryResult, cb) { + projectCategory = projectCategoryResult; + if (!projectCategory) { + return cb(new IllegalArgumentError("Category Id " + categoryId + " is not a valid category ID")); + } + parameters = { + userId: userId, + categoryId: categoryId + }; + api.dataAccess.executeQuery("get_reviewer", parameters, dbConnectionMap, cb); + }, function (userIds, cb) { + if (!userIds || !userIds.length) { + return cb(new NotFoundError("There is no reviewer with the username:" + username + " in category: " + projectCategory.name)); + } + api.dataAccess.executeQuery("remove_reviewer", parameters, dbConnectionMap, cb); + }, function (effectedRows, cb) { + if (effectedRows >= 1) { + result.message = username + " has been successfully removed from " + projectCategory.name + " Review Board"; + } + cb(null); + }], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); + +}; + +/** + * The API for removing reviewer + */ +exports.removeReviewer = { + name: "removeReviewer", + description: "remove reviewer", + inputs: { + required: ['username', 'categoryId'], + optional: [] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + cacheEnabled: false, + transaction: 'write', + databases: ['tcs_catalog', 'common_oltp'], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute removeReviewer#run", 'debug'); + removeReviewer(api, connection, connection.dbConnectionMap, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; diff --git a/actions/terms.js b/actions/terms.js index 0baeb0efb..8d3e057c7 100755 --- a/actions/terms.js +++ b/actions/terms.js @@ -49,16 +49,17 @@ function validateTermsOfUseId(connection, helper, sqlParams, callback) { var getTermsOfUse = function (api, connection, dbConnectionMap, next) { var helper = api.helper, sqlParams = {}, - result = {}; + result = {}, + noauth = connection.params.noauth == "true"; //Check if the user is logged-in - if (connection.caller.accessLevel === "anon") { + if (!noauth && connection.caller.accessLevel === "anon") { helper.handleError(api, connection, new UnauthorizedError("Authentication credential was missing.")); next(connection, true); return; } - sqlParams.userId = connection.caller.userId; + sqlParams.userId = connection.caller ? connection.caller.userId || '' : ''; async.waterfall([ function (cb) { @@ -66,7 +67,7 @@ var getTermsOfUse = function (api, connection, dbConnectionMap, next) { validateTermsOfUseId(connection, helper, sqlParams, cb); }, function (cb) { - api.dataAccess.executeQuery("get_terms_of_use", sqlParams, dbConnectionMap, cb); + api.dataAccess.executeQuery(noauth ? "get_terms_of_use_noauth" : "get_terms_of_use", sqlParams, dbConnectionMap, cb); }, function (rows, cb) { if (rows.length === 0) { cb(new NotFoundError('No such terms of use exists.')); @@ -211,7 +212,7 @@ exports.getTermsOfUse = { description: "getTermsOfUse", inputs: { required: ["termsOfUseId"], - optional: [] + optional: ["noauth"] }, blockedConnectionTypes: [], outputExample: {}, diff --git a/actions/tops.js b/actions/tops.js index 7cbc35d5d..329e259a4 100644 --- a/actions/tops.js +++ b/actions/tops.js @@ -560,9 +560,6 @@ exports.getTopTrackMembers = { sqlParams.firstRowIndex = (pageIndex - 1) * pageSize; sqlParams.pageSize = pageSize; - if (trackType === "data") { - sqlParams.pageSize = 2 * pageIndex * pageSize; - } // Retrieves paged and ordered top members for the given track. api.dataAccess.executeQuery('get_top_members_' + trackType, sqlParams, dbConnectionMap, cb); }, function (rows, cb) { diff --git a/actions/user.js b/actions/user.js index 88bece40f..b8f7101f9 100644 --- a/actions/user.js +++ b/actions/user.js @@ -233,7 +233,7 @@ function userActivationEmail(api, connection, next) { toAddress : rs[0].address, fromAddress : process.env.TC_EMAIL_ACCOUNT, senderName : activationEmailSenderName, - url : process.env.TC_ACTIVATION_SERVER_NAME + '/reg2/activate.action?code=' + activationCode, + url : process.env.TC_ACTIVATION_SERVER_NAME + '?code=' + activationCode + '&retUrl=https://www.topcoder.com/skill-picker', userHandle : rs[0].handle }, 'default'); api.cache.save(cacheKey, currentResendTimes + 1, api.config.tcConfig.userActivationCacheLifeTime, diff --git a/apiary-admin.apib b/apiary-admin.apib new file mode 100755 index 000000000..0bdb7b4f3 --- /dev/null +++ b/apiary-admin.apib @@ -0,0 +1,611 @@ +FORMAT: 1A +HOST: http://api.topcoder.com/v2 + +# Reviewer Management API + +We extend the tc-api to provide new endpoints to handle admin / copilot / reviewer related +tasks. + +## Admins Collection [/admin/admins] + +### List All admins [GET] ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "allAdmins": [ + { + "id": 132456, + "name": "heffan", + "adminGroup": true, + "adminRole": true, + "managerResource": true + }] + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +### Create New Admin [POST] ++ Attributes + + username: `dok_tester` (required, string) ... The username + ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "success": true, + "message": "dok_tester has been successfully added as TopCoder Admin" + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 404 (application/json) + + { + "name":"Not Found", + "value":"404", + "description":"The URI requested is invalid or the requested resource does not exist." + } + ++ Response 409 (application/json) + + { + "name":"Duplicate Resource", + "value":"409", + "description":"The request is understood, but has duplicate resource." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +### Remove Admin [DELETE] ++ Attributes + + username: `dok_tester` (required, string) ... The username + ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "success": true, + "message": "TopCoder Admin: dok_tester has been successfully removed" + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 404 (application/json) + + { + "name":"Not Found", + "value":"404", + "description":"The URI requested is invalid or the requested resource does not exist." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +## Copilots Collection [/admin/copilots] + +### List All copilots [GET] ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "allCopilots": [ + { + "id": 20, + "name": "dok_tester", + "softwareCopilot": true, + "studioCopilot": true + } + ] + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +### Create New Copilot [POST] ++ Attributes + + username: `dok_tester` (required, string) ... The username + + isSoftwareCopilot: `true` (required, boolean) ... The isSoftwareCopilot flag + + isStudioCopilot: `true` (required, boolean) ... The isStudioCopilot flag + ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "success": true, + "message": "Copilot dok_tester has been successfully added" + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 404 (application/json) + + { + "name":"Not Found", + "value":"404", + "description":"The URI requested is invalid or the requested resource does not exist." + } + ++ Response 409 (application/json) + + { + "name":"Duplicate Resource", + "value":"409", + "description":"The request is understood, but has duplicate resource." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +### Remove Copilot [DELETE] ++ Attributes + + username: `dok_tester` (required, string) ... The username + ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "success": true, + "message": "Copilot dok_tester has been successfully removed" + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 404 (application/json) + + { + "name":"Not Found", + "value":"404", + "description":"The URI requested is invalid or the requested resource does not exist." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +## Reviewers Collection [/admin/reviewers?categoryId={categoryId}] + +### List All reviewers [GET] ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Parameters + + categoryId (required, number, `7`) ... Project Category Id + ++ Response 200 (application/json) + + { + "categoryId": 7, + "reviewers": [ + { + "id": 20, + "name": "dok_tester", + "projectCategoryId": 7, + "projectCategoryName": "Architecture", + "immune": false + } + ] + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +### Create New Reviewer [POST] ++ Attributes + + username: `dok_tester` (required, string) ... The username + + categoryId: `14` (required, number) ... The project category id, you can use category id in query but recommend to use category in body. + + immune: `true` (optional, boolean) ... The immune_ind flag + ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "success": true, + "message": "dok_tester has been successfully added into Assembly Competition Review Board" + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 404 (application/json) + + { + "name":"Not Found", + "value":"404", + "description":"The URI requested is invalid or the requested resource does not exist." + } + ++ Response 409 (application/json) + + { + "name":"Duplicate Resource", + "value":"409", + "description":"The request is understood, but has duplicate resource." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } + +### Remove Reviewer [DELETE] ++ Attributes + + username: `dok_tester` (required, string) ... The username + + categoryId: `14` (required, number) ... The project category id, you can use category id in query but recommend to use category in body. + ++ Request (application/json) + + + Headers + + Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + ++ Response 200 (application/json) + + { + "success": true, + "message": "dok_tester has been successfully removed from Assembly Competition Review Board" + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + } + ++ Response 403 (application/json) + + { + "name":"Forbidden", + "value":"403", + "description":"The request is understood, but it has been refused or access is not allowed." + } + ++ Response 404 (application/json) + + { + "name":"Not Found", + "value":"404", + "description":"The URI requested is invalid or the requested resource does not exist." + } + ++ Response 500 (application/json) + + { + "name":"Internal Server Error", + "value":"500", + "description":"Unknown server error. Please contact support." + } + ++ Response 503 (application/json) + + { + "name":"Service Unavailable", + "value":"503", + "description":"Servers are up but overloaded. Try again later." + } diff --git a/db_scripts/test_eligibility.delete.sql b/db_scripts/test_eligibility.delete.sql new file mode 100644 index 000000000..5f77f6c44 --- /dev/null +++ b/db_scripts/test_eligibility.delete.sql @@ -0,0 +1,39 @@ +DATABASE common_oltp; + +DELETE FROM user_group_xref WHERE group_id > 3330000 AND group_id < 3330100; +DELETE FROM security_groups WHERE group_id > 3330000 AND group_id < 3330100; +DELETE FROM group_contest_eligibility WHERE contest_eligibility_id > 1110000 AND contest_eligibility_id < 1110100; +DELETE FROM contest_eligibility WHERE contest_eligibility_id > 1110000 AND contest_eligibility_id < 1110100; + +DATABASE informixoltp; + +-- UPDATE coder SET comp_country_code = NULL WHERE user_id = 132458; + +DATABASE tcs_catalog; + +DELETE FROM notification WHERE project_id > 1110000 AND project_id < 1110100; +DELETE FROM project_result WHERE project_id > 1110000 AND project_id < 1110100; +DELETE FROM project_user_audit WHERE project_id > 1110000 AND project_id < 1110100; +DELETE FROM component_inquiry WHERE project_id > 1110000 AND project_id < 1110100; +DELETE FROM resource_info WHERE resource_id IN (SELECT resource_id FROM resource WHERE project_id > 1110000 AND project_id < 1110100); +DELETE FROM resource WHERE project_id > 1110000 AND project_id < 1110100; + +DELETE FROM project_info WHERE project_id > 1110000 AND project_id < 1110100; +DELETE FROM comp_versions WHERE component_id = 3330333; +DELETE FROM comp_catalog WHERE component_id = 3330333; +DELETE FROM project_phase WHERE project_id > 1110000 AND project_id < 1110100; +DELETE FROM project WHERE project_id > 1110000 AND project_id < 1110100; + +DELETE FROM review_item_comment WHERE review_item_comment_id > 7770000 AND review_item_id < 7770100; +DELETE FROM review_item WHERE review_item_id > 5550000 AND review_item_id < 5550100; +DELETE FROM review WHERE review_id > 4440000 AND review_id < 4440100; +DELETE FROM scorecard_question WHERE scorecard_question_id = 3330333; +DELETE FROM scorecard_section WHERE scorecard_section_id = 3330333; +DELETE FROM scorecard_group WHERE scorecard_group_id = 3330333; +DELETE FROM scorecard WHERE scorecard_id = 3330333; +DELETE FROM submission WHERE submission_id > 2220000 AND submission_id < 2220100; +DELETE FROM prize WHERE project_id > 2220000 AND project_id < 2220100; +DELETE FROM upload WHERE project_id > 2220000 AND project_id < 2220100; +DELETE FROM resource WHERE project_id > 2220000 AND project_id < 2220100; +DELETE FROM project_phase WHERE project_id > 2220000 AND project_id < 2220100; +DELETE FROM project WHERE project_id > 2220000 AND project_id < 2220100; diff --git a/db_scripts/test_eligibility.insert.sql b/db_scripts/test_eligibility.insert.sql new file mode 100644 index 000000000..44a286bf0 --- /dev/null +++ b/db_scripts/test_eligibility.insert.sql @@ -0,0 +1,230 @@ +DATABASE tcs_catalog; + +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (2220001, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (2220002, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (2220003, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (2220004, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (2220005, 1, 14, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (7770001, 2220001, 17, 3, CURRENT, CURRENT, 0, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (7770002, 2220002, 17, 3, CURRENT, CURRENT, 0, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (7770003, 2220003, 17, 3, CURRENT, CURRENT, 0, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (7770004, 2220004, 17, 3, CURRENT, CURRENT, 0, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (7770005, 2220005, 17, 3, CURRENT, CURRENT, 0, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO resource (resource_id, resource_role_id, project_id, project_phase_id, user_id, create_user, create_date, modify_user, modify_date) + VALUES (8880001, 20, 2220001, 7770001, 132456, "132456", CURRENT, "132456", CURRENT); +INSERT INTO resource (resource_id, resource_role_id, project_id, project_phase_id, user_id, create_user, create_date, modify_user, modify_date) + VALUES (8880002, 20, 2220002, 7770002, 132456, "132456", CURRENT, "132456", CURRENT); +INSERT INTO resource (resource_id, resource_role_id, project_id, project_phase_id, user_id, create_user, create_date, modify_user, modify_date) + VALUES (8880003, 20, 2220003, 7770003, 132456, "132456", CURRENT, "132456", CURRENT); +INSERT INTO resource (resource_id, resource_role_id, project_id, project_phase_id, user_id, create_user, create_date, modify_user, modify_date) + VALUES (8880004, 20, 2220004, 7770004, 132456, "132456", CURRENT, "132456", CURRENT); +INSERT INTO resource (resource_id, resource_role_id, project_id, project_phase_id, user_id, create_user, create_date, modify_user, modify_date) + VALUES (8880005, 20, 2220005, 7770005, 132456, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO upload (upload_id, project_id, resource_id, upload_type_id, upload_status_id, parameter, create_user, create_date, modify_user, modify_date) + VALUES (9990001, 2220001, 8880001, 1, 1, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO upload (upload_id, project_id, resource_id, upload_type_id, upload_status_id, parameter, create_user, create_date, modify_user, modify_date) + VALUES (9990002, 2220002, 8880002, 1, 1, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO upload (upload_id, project_id, resource_id, upload_type_id, upload_status_id, parameter, create_user, create_date, modify_user, modify_date) + VALUES (9990003, 2220003, 8880003, 1, 1, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO upload (upload_id, project_id, resource_id, upload_type_id, upload_status_id, parameter, create_user, create_date, modify_user, modify_date) + VALUES (9990004, 2220004, 8880004, 1, 1, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO upload (upload_id, project_id, resource_id, upload_type_id, upload_status_id, parameter, create_user, create_date, modify_user, modify_date) + VALUES (9990005, 2220005, 8880005, 1, 1, "---", "132456", CURRENT, "132456", CURRENT); + +INSERT INTO prize (prize_id, project_id, place, prize_amount, prize_type_id, number_of_submissions, create_user, create_date, modify_user, modify_date) + VALUES (1110001, 2220001, 1, 1000, 14, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO prize (prize_id, project_id, place, prize_amount, prize_type_id, number_of_submissions, create_user, create_date, modify_user, modify_date) + VALUES (1110002, 2220002, 1, 1000, 14, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO prize (prize_id, project_id, place, prize_amount, prize_type_id, number_of_submissions, create_user, create_date, modify_user, modify_date) + VALUES (1110003, 2220003, 1, 1000, 14, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO prize (prize_id, project_id, place, prize_amount, prize_type_id, number_of_submissions, create_user, create_date, modify_user, modify_date) + VALUES (1110004, 2220004, 1, 1000, 14, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO prize (prize_id, project_id, place, prize_amount, prize_type_id, number_of_submissions, create_user, create_date, modify_user, modify_date) + VALUES (1110005, 2220005, 1, 1000, 14, 1, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO submission (submission_id, upload_id, submission_status_id, submission_type_id, create_user, create_date, modify_user, modify_date, prize_id) + VALUES (2220001, 9990001, 1, 3, "132456", CURRENT, "132456", CURRENT, 1110001); +INSERT INTO submission (submission_id, upload_id, submission_status_id, submission_type_id, create_user, create_date, modify_user, modify_date, prize_id) + VALUES (2220002, 9990002, 1, 3, "132456", CURRENT, "132456", CURRENT, 1110002); +INSERT INTO submission (submission_id, upload_id, submission_status_id, submission_type_id, create_user, create_date, modify_user, modify_date, prize_id) + VALUES (2220003, 9990003, 1, 3, "132456", CURRENT, "132456", CURRENT, 1110003); +INSERT INTO submission (submission_id, upload_id, submission_status_id, submission_type_id, create_user, create_date, modify_user, modify_date, prize_id) + VALUES (2220004, 9990004, 1, 3, "132456", CURRENT, "132456", CURRENT, 1110004); +INSERT INTO submission (submission_id, upload_id, submission_status_id, submission_type_id, create_user, create_date, modify_user, modify_date, prize_id) + VALUES (2220005, 9990005, 1, 3, "132456", CURRENT, "132456", CURRENT, 1110005); + +INSERT INTO scorecard (scorecard_id, scorecard_status_id, scorecard_type_id, project_category_id, name, version, min_score, max_score, create_user, create_date, modify_user, modify_date, version_number) + VALUES (3330333, 1, 7, 14, "---", "---", 0, 100, "132456", CURRENT, "132456", CURRENT, 1); + +INSERT INTO scorecard_group (scorecard_group_id, scorecard_id, name, weight, sort, create_user, create_date, modify_user, modify_date, version) + VALUES (3330333, 3330333, "---", 100, 1, "132456", CURRENT, "132456", CURRENT, 1); + +INSERT INTO scorecard_section (scorecard_section_id, scorecard_group_id, name, weight, sort, create_user, create_date, modify_user, modify_date, version) + VALUES (3330333, 3330333, "---", 100, 1, "132456", CURRENT, "132456", CURRENT, 1); + +INSERT INTO scorecard_question (scorecard_question_id, scorecard_question_type_id, scorecard_section_id, description, weight, sort, upload_document, upload_document_required, create_user, create_date, modify_user, modify_date, version) + VALUES (3330333, 1, 3330333, '---', 100, 1, 0, 0, "132456", CURRENT, "132456", CURRENT, 1); + +INSERT INTO review (review_id, resource_id, submission_id, project_phase_id, scorecard_id, committed, create_user, create_date, modify_user, modify_date) + VALUES (4440001, 8880001, 2220001, 7770001, 3330333, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review (review_id, resource_id, submission_id, project_phase_id, scorecard_id, committed, create_user, create_date, modify_user, modify_date) + VALUES (4440002, 8880002, 2220002, 7770002, 3330333, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review (review_id, resource_id, submission_id, project_phase_id, scorecard_id, committed, create_user, create_date, modify_user, modify_date) + VALUES (4440003, 8880003, 2220003, 7770003, 3330333, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review (review_id, resource_id, submission_id, project_phase_id, scorecard_id, committed, create_user, create_date, modify_user, modify_date) + VALUES (4440004, 8880004, 2220004, 7770004, 3330333, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review (review_id, resource_id, submission_id, project_phase_id, scorecard_id, committed, create_user, create_date, modify_user, modify_date) + VALUES (4440005, 8880005, 2220005, 7770005, 3330333, 1, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO review_item (review_item_id, review_id, scorecard_question_id, upload_id, answer, sort, create_user, create_date, modify_user, modify_date) + VALUES (5550001, 4440001, 3330333, 9990001, "---", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item (review_item_id, review_id, scorecard_question_id, upload_id, answer, sort, create_user, create_date, modify_user, modify_date) + VALUES (5550002, 4440002, 3330333, 9990002, "---", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item (review_item_id, review_id, scorecard_question_id, upload_id, answer, sort, create_user, create_date, modify_user, modify_date) + VALUES (5550003, 4440003, 3330333, 9990003, "---", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item (review_item_id, review_id, scorecard_question_id, upload_id, answer, sort, create_user, create_date, modify_user, modify_date) + VALUES (5550004, 4440004, 3330333, 9990004, "---", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item (review_item_id, review_id, scorecard_question_id, upload_id, answer, sort, create_user, create_date, modify_user, modify_date) + VALUES (5550005, 4440005, 3330333, 9990005, "---", 1, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO review_item_comment (review_item_comment_id, resource_id, review_item_id, comment_type_id, content, sort, create_user, create_date, modify_user, modify_date) + VALUES (7770001, 8880001, 5550001, 1, "The current user has the right to view this challenge", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item_comment (review_item_comment_id, resource_id, review_item_id, comment_type_id, content, sort, create_user, create_date, modify_user, modify_date) + VALUES (7770002, 8880002, 5550002, 1, "The current user has the right to view this challenge", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item_comment (review_item_comment_id, resource_id, review_item_id, comment_type_id, content, sort, create_user, create_date, modify_user, modify_date) + VALUES (7770003, 8880003, 5550003, 1, "The current user has the right to view this challenge", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item_comment (review_item_comment_id, resource_id, review_item_id, comment_type_id, content, sort, create_user, create_date, modify_user, modify_date) + VALUES (7770004, 8880004, 5550004, 1, "The current user has the right to view this challenge", 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO review_item_comment (review_item_comment_id, resource_id, review_item_id, comment_type_id, content, sort, create_user, create_date, modify_user, modify_date) + VALUES (7770005, 8880005, 5550005, 1, "The current user has the right to view this challenge", 1, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (1110001, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (1110002, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (1110003, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (1110004, 1, 14, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project (project_id, project_status_id, project_category_id, create_user, create_date, modify_user, modify_date) + VALUES (1110005, 1, 14, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (2220001, 1110001, 1, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (2220002, 1110002, 1, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (2220003, 1110003, 1, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (2220004, 1110004, 1, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (2220005, 1110005, 1, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); + +INSERT INTO comp_catalog (component_id, current_version, component_name, status_id, modify_date, public_ind) + VALUES (3330333, 1, "---", 1, CURRENT, 0); + +INSERT INTO comp_versions (comp_vers_id, component_id, version, version_text, phase_id, phase_time, price, modify_date) + VALUES (4440444, 3330333, 1, "1", 113, CURRENT, 1000, CURRENT); + +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110001, 2, "3330333", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110002, 2, "3330333", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110003, 2, "3330333", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110004, 2, "3330333", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110005, 2, "3330333", "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110001, 6, "Not private", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110002, 6, "Old logic - access allowed", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110003, 6, "Old logic - access denied", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110004, 6, "New logic - access allowed", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110005, 6, "New logic - access denied", "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110001, 26, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110002, 26, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110003, 26, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110004, 26, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110005, 26, "---", "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110001, 79, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110002, 79, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110003, 79, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110004, 79, "---", "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_info (project_id, project_info_type_id, value, create_user, create_date, modify_user, modify_date) + VALUES (1110005, 79, "---", "132456", CURRENT, "132456", CURRENT); + +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (3330001, 1110001, 2, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (3330002, 1110002, 2, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (3330003, 1110003, 2, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (3330004, 1110004, 2, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); +INSERT INTO project_phase (project_phase_id, project_id, phase_type_id, phase_status_id, scheduled_start_time, scheduled_end_time, duration, create_user, create_date, modify_user, modify_date) + VALUES (3330005, 1110005, 2, 2, CURRENT, CURRENT, 1, "132456", CURRENT, "132456", CURRENT); + +DATABASE informixoltp; + +UPDATE coder SET comp_country_code = ( + SELECT MIN(country_code) FROM country WHERE country_name = "United States" +) WHERE coder_id = 132458; + +DATABASE common_oltp; + +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110002, 2220002, 0); +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110003, 2220003, 0); +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110004, 2220004, 0); +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110005, 2220005, 0); + +INSERT INTO security_groups (group_id, description, challenge_group_ind) VALUES (3330001, "Eligibility - Old logic - with user", 0); +INSERT INTO security_groups (group_id, description, challenge_group_ind) VALUES (3330002, "Eligibility - Old logic - no users", 0); +INSERT INTO security_groups (group_id, description, challenge_group_ind) VALUES (3330003, "Eligibility - New logic - with user", 1); +INSERT INTO security_groups (group_id, description, challenge_group_ind) VALUES (3330004, "Eligibility - New logic - no users", 1); + +INSERT INTO user_group_xref (user_group_id, login_id, group_id) VALUES (5550001, 132458, 3330001); + +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110002, 3330001); +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110003, 3330002); +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110004, 3330003); +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110005, 3330004); + +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110012, 1110002, 0); +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110013, 1110003, 0); +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110014, 1110004, 0); +INSERT INTO contest_eligibility (contest_eligibility_id, contest_id, is_studio) VALUES (1110015, 1110005, 0); + +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110012, 3330001); +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110013, 3330002); +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110014, 3330003); +INSERT INTO group_contest_eligibility (contest_eligibility_id, group_id) VALUES (1110015, 3330004); diff --git a/deploy/.env.sh.swp b/deploy/.env.sh.swp new file mode 100644 index 000000000..06c490e5c Binary files /dev/null and b/deploy/.env.sh.swp differ diff --git a/deploy/ci.sh b/deploy/ci.sh index a0143cf31..e3cfb2f49 100644 --- a/deploy/ci.sh +++ b/deploy/ci.sh @@ -58,7 +58,8 @@ export TC_EMAIL_PASSWORD=tc_public_email export TC_EMAIL_FROM=tc.ldap.test@gmail.com export TC_EMAIL_TEMPLATE_DIR=mail_templates -export TC_ACTIVATION_SERVER_NAME="https://www.topcoder.com" +export TC_ACTIVATION_SERVER_NAME="https://api.topcoder.com/pub/activation.html" +export TC_WWW_SERVER_NAME="https://www.topcoder.com" export TC_SOFTWARE_SERVER_NAME="https://www.topcoder.com" #export DISABLE_CONSOLE_LOG=true diff --git a/deploy/development.sh b/deploy/development.sh index 11f08580c..7ec784d66 100755 --- a/deploy/development.sh +++ b/deploy/development.sh @@ -60,7 +60,8 @@ export TC_EMAIL_PASSWORD=tc_public_email export TC_EMAIL_FROM=tc.ldap.test.1@gmail.com export TC_EMAIL_TEMPLATE_DIR=mail_templates -export TC_ACTIVATION_SERVER_NAME="https://www.topcoder.com" +export TC_ACTIVATION_SERVER_NAME="https://api.topcoder.com/pub/activation.html" +export TC_WWW_SERVER_NAME="https://www.topcoder.com" export TC_SOFTWARE_SERVER_NAME="https://software.topcoder.com" export TC_FORUMS_SERVER_NAME="http://apps.topcoder.com/forums" diff --git a/deploy/vm.sh b/deploy/vm.sh index 5f75cefe6..a193827d3 100644 --- a/deploy/vm.sh +++ b/deploy/vm.sh @@ -54,7 +54,8 @@ export TC_EMAIL_PASSWORD=tc_public_email export TC_EMAIL_FROM=tc.ldap.test.1@gmail.com export TC_EMAIL_TEMPLATE_DIR=mail_templates -export TC_ACTIVATION_SERVER_NAME="https://www.topcoder.com" +export TC_ACTIVATION_SERVER_NAME="https://api.topcoder.com/pub/activation.html" +export TC_WWW_SERVER_NAME="https://www.topcoder.com" export TC_SOFTWARE_SERVER_NAME="https://software.topcoder.com" export TC_FORUMS_SERVER_NAME="http://apps.topcoder.com/forums" diff --git a/docs/Admin App - TC API Reviewer Management API.md b/docs/Admin App - TC API Reviewer Management API.md new file mode 100755 index 000000000..58b40e995 --- /dev/null +++ b/docs/Admin App - TC API Reviewer Management API.md @@ -0,0 +1,121 @@ +# Admin App - TC API Reviewer Management API +In this challenge, we need to enhance / extend the tc-api to provide new endpoints to handle admin / copilot / reviewer related tasks. + +## Setup +- [nodejs 0.10.x](https://nodejs.org/) +- [Docker](https://docs.docker.com/engine/installation/) +- [docker-compose](https://docs.docker.com/compose/install/) +- java(required by https://github.com/appirio-tech/informix-wrapper) +It will actually use [node-java](https://github.com/joeferner/node-java), if you meet any issues please check there. + +informix docker service +``` +cd test/docker +docker-compose up +``` + +Follow exist wiki to setup application [wiki](https://github.com/appirio-tech/tc-api/wiki), please do not run `npm test` since old tests are broken. +TC_VM_IP could be `127.0.0.1` under linux or `192.168.99.100` under mac or windows using docker tool box. +``` +# follow wiki to start applications(all previous steps are required) +npm start +``` + +mock bridge service +``` +# you must prepare same environment variables as the tc-api https://github.com/appirio-tech/tc-api/wiki/Configure-Environment-Variables +# I assume you have install all dependencies +node test/scripts/bridge +``` +Or you can user real java version using **java8**. +Download tc-api-jdbc-bridge-dev.zip in https://apps.topcoder.com/forums//?module=Thread&threadID=891500&start=0 +unzip and run `mvn clean package` +update `src/main/resources/bridge.yml` as expected +authDomain: topcoder-dev.com +dbStore/dwStore should change to match configurations in `tc-api/deploy/development.bat` or `development.sh` +``` +TC_DB_NAME=informixoltp_tcp +TC_DB_HOST=$VM_IP +TC_DB_PORT=2021 +TC_DB_USER=informix +TC_DB_PASSWORD=1nf0rm1x + +TC_DW_NAME=informixoltp_tcp +TC_DW_HOST=$VM_IP +TC_DW_PORT=2021 +TC_DW_USER=informix +TC_DW_PASSWORD=1nf0rm1x +``` + +## lint +``` +# you may need to add sudo under linux or mac +npm install jslint -g +jslint routes.js +jslint actions/admins.js +jslint actions/copilots.js +jslint actions/reviewers.js +jslint errors/DuplicateResourceError.js + +# exist lint errors in old codes will not fix +jslint initializers/helper.js + +jslint test/scripts/bridge.js + +jslint test/test.admins.js +jslint test/test.createAdmin.js +jslint test/test.removeAdmin.js + +jslint test/test.copilots.js +jslint test/test.createCopilot.js +jslint test/test.removeCopilot.js + +jslint test/test.reviewers.js +jslint test/test.createReviewer.js +jslint test/test.removeReviewer.js +``` + +## Verify by postman +Import postman collection `test/postman/Reviewer_Management_API.json` and environment `test/postman/Reviewer_Management_API_environment.json`. +Make sure tc api is listening `8080` of localhost rightly or url in environment is right for `http://localhost:8080/api/v2`(mocha test will use this url too). +Make sure informix, bridge is also running. +You can verify requests in different folder. +If token is expired please run requests in `login` folder and Log in as admin or ordinary user and update `adminToken`, `userToken` in environment. + +## Verify by mocha +It will run similar requests as postman including failure and success cases. + +Please make sure informix, tc-api, bridge service is running, it is slow to run single test +and easy to occur max connection numbers issues so it is better to test files one by one and restart all applications if meets any error. +``` +# you must prepare same environment variables as the tc-api https://github.com/appirio-tech/tc-api/wiki/Configure-Environment-Variables +# you may need to add sudo under linux or mac +npm install mocha -g +mocha test/test.admins.js +mocha test/test.createAdmin.js +mocha test/test.removeAdmin.js + +mocha test/test.copilots.js +mocha test/test.createCopilot.js +mocha test/test.removeCopilot.js + +mocha test/test.reviewers.js +mocha test/test.createReviewer.js +mocha test/test.removeReviewer.js +``` + +## api doc +Register account in https://apiary.io and create new api and copy document `tc-api/apiary-admin.apib` and validate document, +Save and you can click Documentation tab on top to view api doc. + + +## Max connection number issue +The docker image of informix is limited to have 20 connections.It is very easy to occur **Open Timeout** +or **Timed out without obtaining all DB connections** or **Error: The server experienced an internal error** during test,postman requests. +You should close all services/applications include bridge service and stop and restart informix again with previous steps. +You may change `MAXPOOL` environment variable since it will be shared in tc api, bridge,test applications so use `20` is not proper actually. + +## Pass data to api +when add/remove reviewers you could use categoryId/username in query or body, but I recommend you to send data in body +since category id in query will be ignored if exists categoryId in body +and it could send number directly in body(provide postman requests for category id in query too). \ No newline at end of file diff --git a/docs/Verification_Guide-Improve Challenge Visibility Control.doc b/docs/Verification_Guide-Improve Challenge Visibility Control.doc new file mode 100644 index 000000000..fd53c55cc Binary files /dev/null and b/docs/Verification_Guide-Improve Challenge Visibility Control.doc differ diff --git a/errors/DuplicateResourceError.js b/errors/DuplicateResourceError.js new file mode 100755 index 000000000..909368cde --- /dev/null +++ b/errors/DuplicateResourceError.js @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 TopCoder, Inc. All rights reserved. + */ +"use strict"; + +/** + * This file defines DuplicateResourceError + * + * @author TCSCODER + * @version 1.0 + */ + +/** + * Constructor of DuplicateResourceError + * @param {Object} message the error message + * @param {Object} cause the error cause + */ +var DuplicateResourceError = function (message, cause) { + //captureStackTrace + Error.call(this); + Error.captureStackTrace(this); + this.message = message || "DuplicateResource Error"; + this.cause = cause; +}; + +//use Error as prototype +require('util').inherits(DuplicateResourceError, Error); +DuplicateResourceError.prototype.name = 'DuplicateResource Error'; + +module.exports = DuplicateResourceError; diff --git a/initializers/challengeHelper.js b/initializers/challengeHelper.js index 2622da0b4..a8cc3331c 100644 --- a/initializers/challengeHelper.js +++ b/initializers/challengeHelper.js @@ -1,8 +1,8 @@ /* * Copyright (C) 2013 - 2014 TopCoder Inc., All Rights Reserved. * - * @version 1.4 - * @author ecnu_haozi, bugbuka, Ghost_141, muzehyun + * @version 1.5 + * @author ecnu_haozi, bugbuka, Ghost_141, muzehyun, GFalcon * Refactor common code out from challenge.js. * * changes in 1.1: @@ -13,6 +13,9 @@ * - Avoid undefined if rows[0].copilot_type is null. * Changes in 1.4: * - Add template id to challenge terms of use. + * Changes in 1.5: + * - Add the checkUserChallengeEligibility function + * - Removee the obsolete eligibility check in getChallengeTerms */ "use strict"; @@ -135,11 +138,6 @@ exports.challengeHelper = function (api, next) { return; } - if (!rows[0].no_elgibility_req && !rows[0].user_in_eligible_group) { - cb(new ForbiddenError('You are not part of the groups eligible for this challenge.')); - return; - } - // Update check to use flag. if (requireRegOpen && !rows[0].reg_open) { cb(new ForbiddenError('Registration Phase of this challenge is not open.')); @@ -228,6 +226,158 @@ exports.challengeHelper = function (api, next) { } next(null, result.terms); }); + }, + getChallengeTermsNoAuth : function (connection, challengeId, role, requireRegOpen, dbConnectionMap, next) { + + var helper = api.helper, + sqlParams = {}, + result = {}, + userId = connection.caller.userId; + + async.waterfall([ + function (cb) { + + //Simple validations of the incoming parameters + var error = helper.checkPositiveInteger(challengeId, 'challengeId') || + helper.checkMaxInt(challengeId, 'challengeId'); + + if (error) { + cb(error); + return; + } + + sqlParams.challengeId = challengeId; + + // We are here. So all validations have passed. + // Next we get all roles + api.dataAccess.executeQuery("all_resource_roles", {}, dbConnectionMap, cb); + }, function (rows, cb) { + // Prepare a comma separated string of resource role names that must match + var commaSepRoleIds = "", + compiled = _.template("<%= resource_role_id %>,"), + ctr = 0, + resourceRoleFound; + if (_.isUndefined(role)) { + rows.forEach(function (row) { + commaSepRoleIds += compiled({resource_role_id: row.resource_role_id}); + ctr += 1; + if (ctr === rows.length) { + commaSepRoleIds = commaSepRoleIds.slice(0, -1); + } + }); + } else { + resourceRoleFound = _.find(rows, function (row) { + return (row.name === role); + }); + if (_.isUndefined(resourceRoleFound)) { + //The role passed in is not recognized + cb(new BadRequestError("The role: " + role + " was not found.")); + return; + } + commaSepRoleIds = resourceRoleFound.resource_role_id; + } + + // Get the terms + sqlParams.resourceRoleIds = commaSepRoleIds; + api.dataAccess.executeQuery("challenge_terms_of_use_noauth", sqlParams, dbConnectionMap, cb); + }, function (rows, cb) { + //We could just have down result.data = rows; but we need to change keys to camel case as per requirements + result.terms = []; + _.each(rows, function (row) { + + result.terms.push({ + termsOfUseId: row.terms_of_use_id, + title: row.title, + url: row.url, + agreeabilityType: row.agreeability_type, + agreed: row.agreed, + templateId: row.docusign_template_id + }); + }); + + var ids = {}; + result.terms = result.terms.filter(function(row) { + if (ids[row.termsOfUseId]) { + return false; + } else { + ids[row.termsOfUseId] = true; + return true; + } + }); + + cb(); + } + ], function (err) { + if (err) { + next(err); + return; + } + next(null, result.terms); + }); + }, + /** + * Check if the user currently logged in has the right to access the specified challenge + * + * @param {Object} connection The connection object for the current request + * @param {Number} challengeId The challenge id. + * @param {Function} next The callback that will receive an error + * if the user is not eligible + * + * @since 1.5 + */ + checkUserChallengeEligibility: function (connection, challengeId, next) { + // Admins can access any challenge + if (connection.caller.accessLevel === 'admin') { + next(); + return; + } + // Query the accessibility information + var userId = (connection.caller.userId || 0); + api.dataAccess.executeQuery('get_challenge_accessibility_and_groups', { + challengeId: challengeId, + user_id: userId + }, connection.dbConnectionMap, function (err, res) { + if (err) { + next(err); + return; + } + // If there's no corresponding record in group_contest_eligibility + // then the challenge is available to all users + if (res.length === 0 + || _.isNull(res[0].challenge_group_ind) + || _.isUndefined(res[0].challenge_group_ind)) { + next(); + return; + } + var error = false; + // Look at the groups + async.some(res, function (record, cbx) { + // Old challenges: check by looking up in common_oltp:user_group_xref + if (record.challenge_group_ind === 0) { + cbx(!(_.isNull(record.user_group_xref_found) || _.isUndefined(record.user_group_xref_found))); + } else { + // New challenges: query the V3 API + api.v3client.isUserInGroup(connection, record.group_id, function (err, result) { + if (err) { + error = err; + cbx(true); + } else { + cbx(result); + } + }); + } + }, function (eligible) { + if (error) { + next(error); + } else if (eligible) { + next(); + } else if (connection.caller.accessLevel === "anon") { + next(new UnauthorizedError()); + } else { + next(new ForbiddenError('The user is not allowed to visit the challenge.')); + } + }); + }); } }; diff --git a/initializers/helper.js b/initializers/helper.js old mode 100644 new mode 100755 index 2e53f1cc6..b4ca38b54 --- a/initializers/helper.js +++ b/initializers/helper.js @@ -1,12 +1,12 @@ /*jslint node: true, nomen: true, unparam: true, plusplus: true, bitwise: true */ /** - * Copyright (C) 2013 - 2014 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2013 - 2016 TopCoder Inc., All Rights Reserved. */ /** * This module contains helper functions. * @author Sky_, Ghost_141, muzehyun, kurtrips, isv, LazyChild, hesibo, panoptimum, flytoj2ee, TCSASSEMBLER - * @version 1.42 + * @version 1.43 * changes in 1.1: * - add mapProperties * changes in 1.2: @@ -112,6 +112,12 @@ * - Update apiName2dbNameMap to add entries for srm schedule API. * Changes in 1.42: * - Add checkAdminOrWebArenaSuper to check if user has web arena super role. + * Changes in 1.43: + * - Add validateUserAndGetUserId to validate username and get user id. + * - Add isDuplicateResourceError to check whether error is duplicate resource error + * - Add getCopilotProfileIdByUserId to get copilot profile id by user id + * - Add getProjectCategoryByCategoryId to get project category with type,name by category id + * - Update apiCode, handleError to handle duplicate resource error */ "use strict"; @@ -136,6 +142,7 @@ var BadRequestError = require('../errors/BadRequestError'); var UnauthorizedError = require('../errors/UnauthorizedError'); var ForbiddenError = require('../errors/ForbiddenError'); var RequestTooLargeError = require('../errors/RequestTooLargeError'); +var DuplicateResourceError = require('../errors/DuplicateResourceError'); var helper = {}; var crypto = require("crypto"); var bigdecimal = require('bigdecimal'); @@ -1039,6 +1046,9 @@ helper.consts.ALLOWABLE_DATE_TYPE = [helper.consts.AFTER, helper.consts.AFTER_CU /** * Api codes + * changes in 1.43 + * -add code,value,description for duplicate resource error + * @since 1.43 */ helper.apiCodes = { OK: { @@ -1071,6 +1081,11 @@ helper.apiCodes = { value: 413, description: 'The request is understood, but is larger than the server is willing or able to process.' }, + duplicateResource: { + name: 'Duplicate Resource', + value: 409, + description: 'The request is understood, but has duplicate resource.' + }, notFound: { name: 'Not Found', value: 404, @@ -1089,6 +1104,9 @@ helper.apiCodes = { * @param {Object} api - The api object that is used to access the global infrastructure * @param {Object} connection - The connection object for the current request * @param {Object} err - The error to return + * changes in 1.43 + * -handle duplicate resource error + * @since 1.43 */ helper.handleError = function (api, connection, err) { api.log("Error occurred: " + err + " " + (err.stack || ''), "error"); @@ -1108,6 +1126,9 @@ helper.handleError = function (api, connection, err) { if (err instanceof RequestTooLargeError) { baseError = helper.apiCodes.requestTooLarge; } + if (err instanceof DuplicateResourceError) { + baseError = helper.apiCodes.duplicateResource; + } errdetail = _.clone(baseError); errdetail.details = err.message; connection.rawConnection.responseHttpCode = baseError.value; @@ -1193,9 +1214,23 @@ helper.socialProviders = { "twitter": 3, "github": 4, "salesforce": 5, - "ad": 50 + "dribbble": 10, + "behance": 11, + "stackoverflow": 12, + "linkedin": 13, + "bitbucket": 14, + "ad": 50, + "samlp": 102 }; +helper.isTCADProvider = function (providerId) { + return providerId === helper.socialProviders.ad; +} + +helper.isSSOProvider = function (providerId) { + return providerId === helper.socialProviders.samlp; +} + /** * Retrieve provider information from the provider name. * @@ -1219,15 +1254,34 @@ helper.getProviderId = function (provider, callback) { if (provider.startsWith("salesforce")) { providerId = helper.socialProviders.salesforce; } + if (provider.startsWith("dribbble")) { + providerId = helper.socialProviders.dribbble; + } + if (provider.startsWith("behance")) { + providerId = helper.socialProviders.behance; + } + if (provider.startsWith("stackoverflow")) { + providerId = helper.socialProviders.stackoverflow; + } + if (provider.startsWith("linkedin")) { + providerId = helper.socialProviders.linkedin; + } + if (provider.startsWith("bitbucket")) { + providerId = helper.socialProviders.bitbucket; + } if (provider.startsWith("ad") || provider.startsWith("auth0")) { providerId = helper.socialProviders.ad; } + if (provider.startsWith("samlp") || provider.startsWith("adfs")) { + providerId = helper.socialProviders.samlp; + } if (providerId) { callback(null, providerId); } else { callback(new Error('Social provider: ' + provider + ' is not defined in config')); } }; + /* Encrypt the password using the specified key. After being * encrypted with a Blowfish key, the encrypted byte array is * then encoded with a base 64 encoding, resulting in the String @@ -1980,6 +2034,92 @@ var getCoderIdFromActivationCode = function (activationCode) { helper.getCoderIdFromActivationCode = getCoderIdFromActivationCode; helper.generateActivationCode = generateActivationCode; +/** + * Validate the given user username and get user id. + * @param {String} username - the user username. + * @param {Object} dbConnectionMap - the database connection map + * @param {Function} callback - The callback function. + * @since 1.43 + */ +helper.validateUserAndGetUserId = function (username, dbConnectionMap, callback) { + async.waterfall([ + function (cb) { + cb(helper.checkStringPopulated(username, 'username')); + }, + function (cb) { + helper.api.dataAccess.executeQuery("get_user_id_by_handle", + { handle: username }, dbConnectionMap, cb); + }, function (result, cb) { + if (!result || !result.length) { + return cb(new NotFoundError("User with the username: " + username + " does not exist")); + } + cb(null, result[0].user_id); + } + ], callback); +}; + +/** + * Check whether given error is duplicate resource error. + * @param e the error object + * @returns true if contains duplicate in error message. + * @since 1.43 + */ +helper.isDuplicateResourceError = function (e) { + return e && e.message && e.message.indexOf('duplicate') !== -1; +}; + +/** + * Get copilot profile id by user id. + * @param {Number} userId - the user id. + * @param {Object} dbConnectionMap - the database connection map + * @param {Function} callback - The callback function. + * @since 1.43 + */ +helper.getCopilotProfileIdByUserId = function (userId, dbConnectionMap, callback) { + async.waterfall([ + function (cb) { + cb(helper.checkIdParameter(userId, 'userId')); + }, + function (cb) { + helper.api.dataAccess.executeQuery("get_copilot_profile_id_by_user_id", + { userId: userId }, dbConnectionMap, cb); + }, function (result, cb) { + cb(null, (!result || !result.length) ? 0 : result[0].copilot_profile_id); + } + ], callback); +}; + + +/** + * Gets project category with project type id,name by project category ID. + * @param {Number} categoryId - the project category id. + * @param {Object} dbConnectionMap - the database connection map + * @param {Function} callback - The callback function. + * @since 1.43 + */ +helper.getProjectCategoryByCategoryId = function (categoryId, dbConnectionMap, callback) { + async.waterfall([ + function (cb) { + cb(helper.checkIdParameter(categoryId, 'categoryId')); + }, + function (cb) { + helper.api.dataAccess.executeQuery("get_project_category_by_category_id", + {categoryId: categoryId}, dbConnectionMap, cb); + }, function (result, cb) { + var projectCategory = null; + if (result && result.length) { + projectCategory = { + id: result[0].project_category_id, + name: result[0].name, + typeId: Number(result[0].project_type_id) + }; + } + cb(null, projectCategory); + } + ], callback); +}; + + /** * Expose the "helper" utility. * diff --git a/initializers/middleware.js b/initializers/middleware.js index e41ad3b63..98fb669ce 100644 --- a/initializers/middleware.js +++ b/initializers/middleware.js @@ -2,8 +2,8 @@ /* * Copyright (C) 2013 - 2014 TopCoder Inc., All Rights Reserved. * - * @version 1.3 - * @author vangavroche, TCSASSEMBLER + * @version 1.4 + * @author vangavroche, TCSASSEMBLER, GFalcon * changes in 1.1: * - add cache support (add preCacheProcessor and postCacheProcessor) * changes in 1.2: @@ -12,6 +12,8 @@ * - add authorizationPreProcessor * changes in 1.3: * - add force refresh check for preCacheProcessor + * changes in 1.4: + * - store the authorization token in connection.authToken */ "use strict"; @@ -76,12 +78,14 @@ exports.middleware = function (api, next) { var authHeader = connection.rawConnection.req.headers.authorization, connectionMap = { "common_oltp": api.dataAccess.createConnection("common_oltp") }, isTopcoderAD, + isSSO, cachePrefix = "authorizationPreProcessor::", decoded, isCachedReturned, cacheKey, socialUserId, socialProvider, + authConnection, cookieToken = api.utils.parseCookies(connection.rawConnection.req)[process.env.JWT_TOKEN_COOKIE_KEY]; if (_.isUndefined(authHeader) && _.isUndefined(cookieToken)) { @@ -103,6 +107,7 @@ exports.middleware = function (api, next) { cb(null, reg.exec(authHeader)[1]); } }, function (token, cb) { + connection.authToken = token; jwt.verify(token, api.config.tcConfig.oauthClientSecret, { audience: api.config.tcConfig.oauthClientId }, @@ -113,8 +118,10 @@ exports.middleware = function (api, next) { cb(new IllegalArgumentError('Malformed Auth header. No sub in token!')); return; } + // connection name + authConnection = getAuth0Connection(decoded); var split = decoded.sub.split("|"); - if (split.length === 1) { + if (split.length === 1) { // token.sub should contain "|" cb(new IllegalArgumentError('Malformed Auth header. token.sub is in bad format!')); return; @@ -136,7 +143,8 @@ exports.middleware = function (api, next) { } api.helper.getProviderId(socialProvider, cb); }, function (providerId, cb) { - isTopcoderAD = providerId === api.helper.socialProviders.ad; + isTopcoderAD = api.helper.isTCADProvider(providerId); + isSSO = api.helper.isSSOProvider(providerId); cacheKey = cachePrefix + decoded.sub; api.cache.load(cacheKey, function (err, value) { var userId; @@ -155,6 +163,16 @@ exports.middleware = function (api, next) { cbx(api.helper.checkPositiveInteger(userId, "userId")); return; } + if (isSSO) { + api.dataAccess.executeQuery("get_user_by_sso_login", + { + sso_user_id: socialUserId, + auth_connection: authConnection, + }, + connectionMap, + cbx); + return; + } api.dataAccess.executeQuery("get_user_by_social_login", { social_user_id: socialUserId, @@ -251,6 +269,26 @@ exports.middleware = function (api, next) { } /*jslint */ + /** + * Extract Auth0 connection name from JWT token. + * JWT Example: + * .... + * "identities": [ + * { + * "connection": "sfdc-aspdev", + * "isSocial": false, + * "provider": "samlp", + * "user_id": "user1@asp.appirio.com.dev" + * } + * ] + * sfdc-aspdev is returned. + * + * @param {Object} decoded JWT token issued by Auth0 (v2 token) + */ + function getAuth0Connection(jwt) { + return (jwt && jwt.identities && Array.isArray(jwt.identities) && jwt.identities.length>0 ) ? jwt.identities[0].connection : null; + } + /** * The pre-processor that checks if user is slamming. * diff --git a/initializers/v3client.js b/initializers/v3client.js new file mode 100644 index 000000000..34bab2143 --- /dev/null +++ b/initializers/v3client.js @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2017 TopCoder Inc., All Rights Reserved. + * + * V3 API client + * + * @version 1.0 + * @author GFalcon + */ +"use strict"; +/*jslint nomen: true*/ + +var request = require('request'); +var _ = require('underscore'); +var async = require('async'); +var atob = require('atob'); + +/** + * The URL of the V3 API + */ +var v3url = process.env.TC_API_V3_URL || 'http://localhost:8084/v3/'; + +/** + * Cached V3 API tokens. + * + * This object stores V2 tokens as keys and V3 tokens as values + */ +var tokens = {}; + +/** + * Call the service. It handles both errors and bad response status codes. + * + * @param {Object} params - parameters for a request + * @param {Function} callback - the callback function. + * It will get either an Error object or a response body. + */ +function callService(params, callback) { + params.json = true; + request(params, function (err, response, body) { + if (err) { + callback(err); + return; + } + /*jslint eqeq: true*/ + if (response.statusCode != 200) { + /*jslint eqeq: false*/ + callback(new Error('API ' + params.url + ' returned ' + response.statusCode + ' ' + (response.statusMessage || ''))); + return; + } + callback(null, body); + }); +} + +/** + * Get the V3 API authorization token to use in subsequent calls + * + * @param {Object} connection - the connection object provided by ActionHero + * @param {Function} callback - this function receives either an error, + * a V3 token or nothing at all (if the current connection's user is anonymous) + */ +function getToken(connection, callback) { + // Anonymous + if (_.isUndefined(connection.authToken)) { + callback(); + return; + } + // Cached token + if (!_.isUndefined(tokens[connection.authToken]) && !isTokenExpired(tokens[connection.authToken])) { + callback(null, tokens[connection.authToken]); + return; + } + // Get the token by calling the API + callService({ + url: v3url + 'authorizations', + method: 'POST', + body: { + param: { + externalToken: connection.authToken + } + } + }, function (err, body) { + if (err) { + callback(err); + } else { + tokens[connection.authToken] = body.result.content.token; + callback(null, body.result.content.token); + } + }); +} + + +function urlBase64Decode(str) { + var output = str.replace(/-/g, '+').replace(/_/g, '/'); + + switch (output.length % 4) { + case 0: + break; + + case 2: + output += '=='; + break; + + case 3: + output += '='; + break; + + default: + throw 'Illegal base64url string!' + } + return decodeURIComponent(escape(atob(output)));//polyfill https://github.com/davidchambers/Base64.js +} + +function decodeToken(token) { + var parts = token.split('.'); + + if (parts.length !== 3) { + throw new Error('The token is invalid') + } + + var decoded = urlBase64Decode(parts[1]); + + if (!decoded) { + throw new Error('Cannot decode the token') + } + + return JSON.parse(decoded) +} + +function getTokenExpirationDate(token) { + var decoded = decodeToken(token); + + if(typeof decoded.exp === 'undefined') { + return null + } + + var d = new Date(0);// The 0 here is the key, which sets the date to the epoch + d.setUTCSeconds(decoded.exp); + + return d +} + +function isTokenExpired(token) { + var d = getTokenExpirationDate(token); + + if (d === null) { + return false + } + + // Token expired? + return !(d.valueOf() > (new Date().valueOf())) +} + +/** + * Get IDs of users in the specified group + * + * @param {Object} connection - the connection object provided by ActionHero + * @param {Number} groupId - the group ID + * @param {Function} callback - the callback. Receives either an error + * or the list of group's users an array of numeric IDs + */ +function getGroupMembers(connection, groupId, callback) { + getToken(connection, function (err, token) { + if (err) { + callback(err); + return; + } + callService({ + url: v3url + 'groups/' + groupId + '/members', + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + token + } + }, function (err, body) { + if (err) { + callback(err); + } else { + callback(null, body.result.content.map(function (item) { + return item.memberId; + })); + } + }); + }); +} + +/** + * Get groups that the current user can access. + * + * @param {Object} connection - the connection object provided by ActionHero + * @param {Function} callback - the callback. Receives either an error + * or the list of group's users an array of numeric IDs + */ +function getMemberGroups(connection, callback) { + getToken(connection, function (err, token) { + if (err) { + callback(err); + return; + } + + var userId = (connection.caller.userId || 0); + + // calls + callService({ + url: v3url + 'groups?membershipType=user&memberId=' + userId, + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + token + } + }, function (err, body) { + if (err) { + callback(err); + } else { + var groupIds = body.result.content.map(function (item) { + return item.id; + }); + + var memberGroups = []; + + groupIds.forEach(function(groupId) { + callService({ + url: v3url + 'groups/' + groupId + '/getParentGroup?oneLevel=false', + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + token + } + }, function (err, body) { + var idx = groupIds.indexOf(groupId); + groupIds.splice(idx, 1); + + if (err) { + callback(err); + } else { + var groupResponse = body.result.content; + while(groupResponse) { + memberGroups.push(groupResponse.id); + groupResponse = groupResponse.parentGroup; + } + + if (groupIds.length == 0) { + callback(null, memberGroups); + } + + } + }) + }); + } + }); + }); +} + +exports.v3client = function (api, next) { + api.v3client = { + /** + * Check if the user belongs to the group + * + * @param {Object} connection - the connection object provided by ActionHero + * @param {Number} userId - the user ID + * @param {Number} groupId - the group ID + * @param {Function} callback - the callback. The second parameter + * is boolean which is true if the user has group id in challenge groups. + */ + isUserInGroup: function (connection, groupId, callback) { + getMemberGroups(connection, function (err, groupIds) { + if (err) { + callback(err); + } else { + callback(null, groupIds.indexOf("" + groupId) >= 0); + } + }); + } + }; + next(); +}; diff --git a/local/docker-compose.yml b/local/docker-compose.yml new file mode 100644 index 000000000..d37d536f0 --- /dev/null +++ b/local/docker-compose.yml @@ -0,0 +1,15 @@ +version: '2' +services: + informix: + image: appiriodevops/informix:1.2 + ports: + - 2021:2021 + tc-api: + build: ./node + depends_on: + - informix + ports: + - "8080:8080" + volumes: + - ../:/tc-api + command: /bin/bash -c "cd /tc-api && npm install && source local/env.sh && npm start && tail -f log/forever.log" diff --git a/local/env.sh b/local/env.sh new file mode 100644 index 000000000..2c2556c28 --- /dev/null +++ b/local/env.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# +# Copyright (C) 2013-2014 TopCoder Inc., All Rights Reserved. +# +# Version: 1.3 +# Author: vangavroche, isv, TCASSEMBLER +# changes in 1.1: +# - add JIRA_USERNAME and JIRA_PASSWORD +# changes in 1.2: +# - added RESET_PASSWORD_TOKEN_CACHE_EXPIRY environment variable +# - added RESET_PASSWORD_TOKEN_EMAIL_SUBJECT environment variable +# - added REDIS_HOST environment variable +# - added REDIS_PORT environment variable +# changes in 1.3 +# - added WKHTMLTOIMAGE_COMMAND_PATH environment variable +# - added WKHTMLTOIMAGE_IMAGE_WIDTH environment variable +# - added HIGHLIGHT_STYLE_LINK environment variable +# + +# tests rely on caching being off. But set this to a real value (or remove) while coding. +export CACHE_EXPIRY=-1 + +VM_IP=informix +if [ -n "$TC_VM_IP" ] +then +VM_IP=$TC_VM_IP +fi + +export TC_DB_NAME=informixoltp_tcp +export TC_DB_HOST=$VM_IP +export TC_DB_PORT=2021 +export TC_DB_USER=informix +export TC_DB_PASSWORD=1nf0rm1x + +export TC_DW_NAME=informixoltp_tcp +export TC_DW_HOST=$VM_IP +export TC_DW_PORT=2021 +export TC_DW_USER=informix +export TC_DW_PASSWORD=1nf0rm1x + +# oauth provider +export TC_API_HOST=api.topcoder.com + +# LDAP settings +export TC_LDAP_HOST=$VM_IP +export TC_LDAP_PORT=636 +export TC_LDAP_PASSWORD=secret +export TC_LDAP_MEMBER_BASE_DN="ou=members, dc=topcoder, dc=com" +export TC_BIND_DN="cn=Manager,dc=topcoder,dc=com" + +# Mail settings +export TC_EMAIL_HOST=smtp.gmail.com +export TC_EMAIL_HOST_PORT=465 +export TC_EMAIL_SECURED=true +export TC_EMAIL_ACCOUNT=tc.ldap.test.1@gmail.com +export TC_EMAIL_PASSWORD=tc_public_email +export TC_EMAIL_FROM=tc.ldap.test.1@gmail.com +export TC_EMAIL_TEMPLATE_DIR=mail_templates + +export TC_ACTIVATION_SERVER_NAME="https://api.topcoder.com/pub/activation.html" +export TC_WWW_SERVER_NAME="https://www.topcoder.com" +export TC_SOFTWARE_SERVER_NAME="https://software.topcoder.com" +export TC_FORUMS_SERVER_NAME="http://apps.topcoder.com/forums" + +export PASSWORD_HASH_KEY="ciTHHTSMg6ixffIuPbB30A==" +## JDBC connection pool environment variables - set for all databases +export MINPOOL=1 +export MAXPOOL=20 +export MAXSIZE=0 +export IDLETIMEOUT=3600 +export TIMEOUT=30000 + +# Used in Jira soap service (Bugs API) +export JIRA_USERNAME=api_test +export JIRA_PASSWORD=8CDDp6BHLtUeUdD + +# Forum settings +export STUDIO_FORUMS_SERVER_NAME="http://studio.topcoder.com/forums" +export GRANT_FORUM_ACCESS=false +export DEV_FORUM_JNDI=jnp://env.topcoder.com:1199 + +## The period for expiring the generated tokens for password resetting +export RESET_PASSWORD_TOKEN_EMAIL_SUBJECT=TopCoder Account Password Reset +# Set this to 180000 which is 3 mins. This will help saving time for test. +export RESET_PASSWORD_TOKEN_CACHE_EXPIRY=180000 + +export REDIS_HOST=localhost +export REDIS_PORT=6379 + +export DEVELOP_SUBMISSION_MAX_SIZE=6144 + +export WATERMARK_FILE_PATH=test/test_files/design_image_file_generator/studio_logo_watermark.png + +export WKHTMLTOIMAGE_COMMAND_PATH=/home/ubuntu/tmp/wkhtmltox-0.12.1/static-build/posix-local/wkhtmltox-0.12.1/bin/wkhtmltoimage +export WKHTMLTOIMAGE_IMAGE_WIDTH=1024 +export HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css + +export JWT_TOKEN_COOKIE_KEY="tcjwt_vm" + +export ADMIN_API_KEY=1234567 diff --git a/local/node/Dockerfile b/local/node/Dockerfile new file mode 100644 index 000000000..f94975902 --- /dev/null +++ b/local/node/Dockerfile @@ -0,0 +1,15 @@ +FROM node:0.10 + +COPY jdk-8u51-linux-x64.gz /opt + +RUN cd /opt && \ + tar -xvf jdk-8u51-linux-x64.gz && \ + cd /usr/bin && \ + ln -s /opt/jdk1.8.0_51/bin/java java && \ + ln -s /opt/jdk1.8.0_51/bin/javac javac + +ENV JAVA_HOME=/opt/jdk1.8.0_51 + +RUN npm install -g java + +RUN apt-get install -y net-tools psmisc diff --git a/package.json b/package.json index b9daa5614..d5470d6df 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,11 @@ "bcrypt": "0.7.x", "bigdecimal": "0.6.x", "bignum": "0.6.x", + "body-parser": "^1.17.2", "crypto": "0.0.x", "datejs": "0.0.x", "email-templates": "0.1.x", + "express": "^4.15.3", "forums-wrapper": "git://github.com/cloudspokes/forums-wrapper.git#12b57be495c2e10431173522bc9eff60e0575959", "heapdump": "^0.3.6", "highlight.js": ">= 8.3.0", @@ -46,7 +48,8 @@ "validator": "~3.5.0", "wkhtmltoimage": ">= 0.1.3", "xml2js": "0.2.x", - "xtend": "2.1.x" + "xtend": "2.1.x", + "atob": "2.0.3" }, "devDependencies": { "supertest": "0.8.x", diff --git a/queries/challenge_registration_validations b/queries/challenge_registration_validations index 29fa1a4e8..4bd4a63de 100644 --- a/queries/challenge_registration_validations +++ b/queries/challenge_registration_validations @@ -4,8 +4,6 @@ select (pp_reg_open.project_id IS NOT NULL) as reg_open, (r.project_id IS NOT NULL) as user_registered, (us.user_id IS NOT NULL) as user_suspended, - (ce.contest_eligibility_id IS NULL) as no_elgibility_req, - (ugx.login_id IS NOT NULL) as user_in_eligible_group, (uax.user_id IS NOT NULL OR coder.coder_id IS NOT NULL) as user_country_banned, (coder2.comp_country_code IS NULL OR coder2.comp_country_code = '') as comp_country_is_null, (cop.copilot_profile_id IS NOT NULL) as user_is_copilot, @@ -28,14 +26,6 @@ left join on us.user_id = @userId@ and us.user_status_type_id = 1 and us.user_status_id = 3 --- Check if user meets eligibility requirements -left outer join ( - contest_eligibility ce join ( - group_contest_eligibility gce left outer join user_group_xref ugx - on ugx.group_id = gce.group_id and ugx.login_id = @userId@ - ) - on ce.contest_eligibility_id = gce.contest_eligibility_id -) on p.project_id = ce.contest_id -- Check user's country left outer join ( informixoltp:user_address_xref uax join ( @@ -48,8 +38,10 @@ left outer join ( -- Check coder's country left outer join ( informixoltp:coder coder join informixoltp:country country - on coder.comp_country_code=country.country_code - and country.country_name in ( "Iran", "North Korea", "Cuba", "Sudan", "Syria" ) + on ( + coder.comp_country_code=country.country_code OR + coder.home_country_code=country.country_code + ) and country.country_name in ( "Iran", "North Korea", "Cuba", "Sudan", "Syria" ) ) on coder.coder_id = @userId@ -- Get coder to check comp_country_code left outer join informixoltp:coder coder2 on coder2.coder_id = @userId@ diff --git a/queries/challenge_terms_of_use_noauth b/queries/challenge_terms_of_use_noauth new file mode 100644 index 000000000..e50cacdfa --- /dev/null +++ b/queries/challenge_terms_of_use_noauth @@ -0,0 +1,13 @@ +SELECT tou.terms_of_use_id as terms_of_use_id, + tou.title as title, + tou.url as url, + touat.name as agreeability_type, + dtx.docusign_template_id +FROM project_role_terms_of_use_xref +INNER JOIN terms_of_use tou ON project_role_terms_of_use_xref.terms_of_use_id = tou.terms_of_use_id +INNER JOIN terms_of_use_agreeability_type_lu touat ON touat.terms_of_use_agreeability_type_id = tou.terms_of_use_agreeability_type_id +--LEFT JOIN user_terms_of_use_xref utuox ON utuox.terms_of_use_id = tou.terms_of_use_id +LEFT JOIN terms_of_use_docusign_template_xref dtx ON dtx.terms_of_use_id = project_role_terms_of_use_xref.terms_of_use_id +WHERE project_id = @challengeId@ AND +resource_role_id IN (@resourceRoleIds@) +ORDER BY group_ind, sort_order diff --git a/queries/challenge_terms_of_use_noauth.json b/queries/challenge_terms_of_use_noauth.json new file mode 100644 index 000000000..c5e697f4b --- /dev/null +++ b/queries/challenge_terms_of_use_noauth.json @@ -0,0 +1,5 @@ +{ + "name" : "challenge_terms_of_use_noauth", + "db" : "common_oltp", + "sqlfile" : "challenge_terms_of_use_noauth" +} diff --git a/queries/check_is_related_with_challenge b/queries/check_is_related_with_challenge index 5c18c5bb6..010cb89f3 100644 --- a/queries/check_is_related_with_challenge +++ b/queries/check_is_related_with_challenge @@ -1,22 +1,22 @@ SELECT (SELECT - 1 + max(1) FROM contest_eligibility ce - INNER JOIN group_contest_eligibility gce ON gce.contest_eligibility_id = ce.contest_eligibility_id - INNER JOIN user_group_xref ugx ON ugx.group_id = gce.group_id WHERE ce.contest_id = @challengeId@ - AND ugx.login_id = @user_id@) AS has_access +) AS is_private , (SELECT - 1 - FROM contest_eligibility ce - WHERE ce.contest_id = @challengeId@) AS is_private -, ( - SELECT decode(max(ri.value), null, null, 1) FROM resource r - INNER JOIN resource_info ri ON ri.resource_id = r.resource_id AND ri.resource_info_type_id = 1 + INNER JOIN resource_info ri ON ri.resource_id = r.resource_id AND ri.resource_info_type_id = 1 WHERE r.project_id = @challengeId@ - AND ri.value = @user_id@) AS is_related -, (SELECT max(project_metadata_id) FROM direct_project_metadata m, project p - WHERE metadata_value = @user_id@ AND p.tc_direct_project_id = m.tc_direct_project_id and p.project_id = @challengeId@ AND project_metadata_key_id IN (1, 2, 14)) AS is_manager + AND ri.value = @user_id@ +) AS is_related +, (SELECT + max(project_metadata_id) + FROM direct_project_metadata m, project p + WHERE metadata_value = @user_id@ + AND p.tc_direct_project_id = m.tc_direct_project_id + AND p.project_id = @challengeId@ + AND project_metadata_key_id IN (1, 2, 14) +) AS is_manager FROM dual diff --git a/queries/check_user_challenge_accessibility b/queries/check_user_challenge_accessibility index 4ab12d78a..309258da0 100644 --- a/queries/check_user_challenge_accessibility +++ b/queries/check_user_challenge_accessibility @@ -1,11 +1,11 @@ SELECT (SELECT - 1 + max(1) FROM contest_eligibility ce INNER JOIN group_contest_eligibility gce ON gce.contest_eligibility_id = ce.contest_eligibility_id - INNER JOIN user_group_xref ugx ON ugx.group_id = gce.group_id + LEFT JOIN user_group_xref ugx ON ugx.group_id = gce.group_id WHERE ce.contest_id = @challengeId@ - AND ugx.login_id = @user_id@) AS has_access + AND ((ugx.login_id = @user_id@ AND gce.group_id < 2000000) OR gce.group_id >= 2000000)) AS has_access , (SELECT 1 FROM contest_eligibility ce diff --git a/queries/clear_user_rating b/queries/clear_user_rating new file mode 100755 index 000000000..6a8d7b175 --- /dev/null +++ b/queries/clear_user_rating @@ -0,0 +1 @@ +UPDATE informixoltp:rating SET rating = -1 WHERE coder_id = @userId@ \ No newline at end of file diff --git a/queries/clear_user_rating.json b/queries/clear_user_rating.json new file mode 100755 index 000000000..3f313986a --- /dev/null +++ b/queries/clear_user_rating.json @@ -0,0 +1,5 @@ +{ + "name": "clear_user_rating", + "db": "tcs_catalog", + "sqlfile": "clear_user_rating" +} \ No newline at end of file diff --git a/queries/get_active_challenges b/queries/get_active_challenges index c172d49cc..cd17225db 100644 --- a/queries/get_active_challenges +++ b/queries/get_active_challenges @@ -70,5 +70,5 @@ AND pcl.project_category_id NOT IN (27, 37) --exclude when spec review was a 'co AND pp1.phase_status_id IN (2, 3) AND pi1.project_info_type_id = 1 -- external reference id AND pi1.project_id = p.project_id - +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) -- exclude assigned tasks ORDER BY @sort_column@ @sort_order@ diff --git a/queries/get_admin_resource b/queries/get_admin_resource new file mode 100755 index 000000000..23e22d01a --- /dev/null +++ b/queries/get_admin_resource @@ -0,0 +1 @@ +select resource_id from resource where project_id IS NULL and resource_role_id = 13 and user_id = @userId@ \ No newline at end of file diff --git a/queries/get_admin_resource.json b/queries/get_admin_resource.json new file mode 100755 index 000000000..04bbb3a4d --- /dev/null +++ b/queries/get_admin_resource.json @@ -0,0 +1,5 @@ +{ + "name": "get_admin_resource", + "db": "tcs_catalog", + "sqlfile": "get_admin_resource" +} \ No newline at end of file diff --git a/queries/get_admins b/queries/get_admins new file mode 100755 index 000000000..f654a5770 --- /dev/null +++ b/queries/get_admins @@ -0,0 +1,7 @@ +select t.user_id, t.type, u.handle +FROM (select unique user_id, 'Manager Resource' as type from resource where project_id IS NULL and resource_role_id = 13 +UNION +select unique login_id as user_id, 'Admin Group' as type from user_group_xref where group_id = 2000115 +UNION +select unique login_id as user_id, 'Admin Role' as type from user_role_xref where role_id = 2087) as t, user u +WHERE t.user_id = u.user_id diff --git a/queries/get_admins.json b/queries/get_admins.json new file mode 100755 index 000000000..82ac59fb0 --- /dev/null +++ b/queries/get_admins.json @@ -0,0 +1,5 @@ +{ + "name" : "get_admins", + "db" : "tcs_catalog", + "sqlfile" : "get_admins" +} \ No newline at end of file diff --git a/queries/get_challenge_accessibility_and_groups b/queries/get_challenge_accessibility_and_groups new file mode 100644 index 000000000..6ca557db3 --- /dev/null +++ b/queries/get_challenge_accessibility_and_groups @@ -0,0 +1,21 @@ +SELECT + ce.is_studio, + sg.challenge_group_ind, + ugx.group_id AS user_group_xref_found, + sg.group_id AS group_id +FROM + ( + ( + contest_eligibility ce + LEFT JOIN group_contest_eligibility gce + ON ce.contest_eligibility_id = gce.contest_eligibility_id + ) + LEFT JOIN security_groups sg + ON gce.group_id = sg.group_id + ) + LEFT JOIN ( + SELECT group_id FROM user_group_xref WHERE login_id=@user_id@ + ) ugx + ON ugx.group_id = gce.group_id +WHERE ce.contest_id = @challengeId@ + diff --git a/queries/get_challenge_accessibility_and_groups.json b/queries/get_challenge_accessibility_and_groups.json new file mode 100644 index 000000000..218f37428 --- /dev/null +++ b/queries/get_challenge_accessibility_and_groups.json @@ -0,0 +1,5 @@ +{ + "name" : "get_challenge_accessibility_and_groups", + "db" : "tcs_catalog", + "sqlfile" : "get_challenge_accessibility_and_groups" +} \ No newline at end of file diff --git a/queries/get_copilot_profile_id_by_user_id b/queries/get_copilot_profile_id_by_user_id new file mode 100755 index 000000000..6c98ddce9 --- /dev/null +++ b/queries/get_copilot_profile_id_by_user_id @@ -0,0 +1 @@ +SELECT copilot_profile_id FROM copilot_profile WHERE user_id = @userId@ \ No newline at end of file diff --git a/queries/get_copilot_profile_id_by_user_id.json b/queries/get_copilot_profile_id_by_user_id.json new file mode 100755 index 000000000..0f5e02acc --- /dev/null +++ b/queries/get_copilot_profile_id_by_user_id.json @@ -0,0 +1,5 @@ +{ + "name" : "get_copilot_profile_id_by_user_id", + "db" : "tcs_catalog", + "sqlfile" : "get_copilot_profile_id_by_user_id" +} \ No newline at end of file diff --git a/queries/get_copilots b/queries/get_copilots new file mode 100755 index 000000000..b7076889b --- /dev/null +++ b/queries/get_copilots @@ -0,0 +1,3 @@ +select cp.user_id, handle, is_software_copilot, is_studio_copilot +from copilot_profile cp, user u +where cp.user_id = u.user_id and cp.copilot_profile_status_id = 1 \ No newline at end of file diff --git a/queries/get_copilots.json b/queries/get_copilots.json new file mode 100755 index 000000000..a43d82492 --- /dev/null +++ b/queries/get_copilots.json @@ -0,0 +1,5 @@ +{ + "name" : "get_copilots", + "db" : "tcs_catalog", + "sqlfile" : "get_copilots" +} \ No newline at end of file diff --git a/queries/get_next_admin_resource_id b/queries/get_next_admin_resource_id new file mode 100755 index 000000000..7f59c9ebc --- /dev/null +++ b/queries/get_next_admin_resource_id @@ -0,0 +1 @@ +SELECT (NVL(max(resource_id),0) + 1) as next_id FROM resource WHERE resource_id <5000 \ No newline at end of file diff --git a/queries/get_next_admin_resource_id.json b/queries/get_next_admin_resource_id.json new file mode 100755 index 000000000..a19d8082b --- /dev/null +++ b/queries/get_next_admin_resource_id.json @@ -0,0 +1,5 @@ +{ + "name": "get_next_admin_resource_id", + "db": "tcs_catalog", + "sqlfile": "get_next_admin_resource_id" +} \ No newline at end of file diff --git a/queries/get_next_admin_user_group_id b/queries/get_next_admin_user_group_id new file mode 100755 index 000000000..0b1be8031 --- /dev/null +++ b/queries/get_next_admin_user_group_id @@ -0,0 +1 @@ +SELECT (NVL(MIN(user_group_id), 0) - 1) as next_id FROM user_group_xref \ No newline at end of file diff --git a/queries/get_next_admin_user_group_id.json b/queries/get_next_admin_user_group_id.json new file mode 100755 index 000000000..58b6e863c --- /dev/null +++ b/queries/get_next_admin_user_group_id.json @@ -0,0 +1,5 @@ +{ + "name": "get_next_admin_user_group_id", + "db": "tcs_catalog", + "sqlfile": "get_next_admin_user_group_id" +} \ No newline at end of file diff --git a/queries/get_open_challenges b/queries/get_open_challenges index 47ff4ee5f..7a581d5f9 100644 --- a/queries/get_open_challenges +++ b/queries/get_open_challenges @@ -102,5 +102,6 @@ AND pn.value LIKE ('@challenge_name@') AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) >= @prize_lower_bound@ AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) <= @prize_upper_bound@ AND p.tc_direct_project_id = DECODE(@project_id@, 0, p.tc_direct_project_id, @project_id@) +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) -- exclude assigned tasks ORDER BY @sort_column@ @sort_order@ ) diff --git a/queries/get_open_challenges_count b/queries/get_open_challenges_count index 16798c55a..0b65313d6 100644 --- a/queries/get_open_challenges_count +++ b/queries/get_open_challenges_count @@ -16,7 +16,7 @@ AND p.project_category_id = pcl.project_category_id -- Filter out the challenge that user is not belong to. AND (not exists (select contest_id from contest_eligibility where contest_id = p.project_id) or exists(select contest_id from contest_eligibility ce, group_contest_eligibility gce, user_group_xref x - where x.login_id = @user_id@ AND x.group_id = gce.group_id AND gce.contest_eligibility_id = ce.contest_eligibility_id + where ((gce.group_id < 2000000 AND x.group_id = gce.group_id AND x.login_id = @user_id@) OR gce.group_id >= 2000000) AND gce.contest_eligibility_id = ce.contest_eligibility_id AND ce.contest_id = p.project_id)) AND pcl.project_category_id NOT IN (27, 37) --exclude when spec review was a 'contest.' Also exclude MM, which is in there as a 'software' contest. -- start of parameters @@ -32,3 +32,5 @@ AND pn.value LIKE ('@challenge_name@') AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) >= @prize_lower_bound@ AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) <= @prize_upper_bound@ AND p.tc_direct_project_id = DECODE(@project_id@, 0, p.tc_direct_project_id, @project_id@) +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) + diff --git a/queries/get_past_challenges b/queries/get_past_challenges index 45c1668c2..49ff02fcf 100644 --- a/queries/get_past_challenges +++ b/queries/get_past_challenges @@ -71,5 +71,6 @@ AND LOWER(pn.value) LIKE('@challenge_name@') AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) >= @prize_lower_bound@ AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) <= @prize_upper_bound@ AND p.tc_direct_project_id = DECODE(@project_id@, 0, p.tc_direct_project_id, @project_id@) +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) -- exclude assigned tasks ORDER BY @sort_column@ @sort_order@ ) diff --git a/queries/get_past_challenges_count b/queries/get_past_challenges_count index c3f343bc5..23b07d5eb 100644 --- a/queries/get_past_challenges_count +++ b/queries/get_past_challenges_count @@ -20,9 +20,7 @@ AND pi1.project_info_type_id = 1 and NVL(pp2.actual_end_time, pp2.scheduled_end_time) > '2012-01-01 00:00:00' AND pcl.project_category_id NOT IN (27, 37) --exclude when spec review was a 'contest.' Also exclude MM, which is in there as a 'software' contest. -- start of parameters - AND NVL(pp2.actual_end_time, pp2.scheduled_end_time) BETWEEN TO_DATE('@submission_end_from@ 00:00:00', '%Y-%m-%d %H:%M:%S') AND TO_DATE('@submission_end_to@ 23:59:59', '%Y-%m-%d %H:%M:%S') - AND LOWER(pn.value) LIKE ('@challenge_name@') AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) >= @prize_lower_bound@ AND NVL((SELECT pr.prize_amount FROM prize pr WHERE pr.project_id = p.project_id AND pr.prize_type_id = 15 AND pr.place = 1), 0) <= @prize_upper_bound@ @@ -30,5 +28,6 @@ AND p.tc_direct_project_id = DECODE(@project_id@, 0, p.tc_direct_project_id, @pr -- Filter out the challenge that user is not belong to. AND (not exists (select contest_id from contest_eligibility where contest_id = p.project_id) or exists(select contest_id from contest_eligibility ce, group_contest_eligibility gce, user_group_xref x - where x.login_id = @user_id@ AND x.group_id = gce.group_id AND gce.contest_eligibility_id = ce.contest_eligibility_id + where ((gce.group_id < 2000000 AND x.group_id = gce.group_id AND x.login_id = @user_id@) OR gce.group_id >= 2000000) AND gce.contest_eligibility_id = ce.contest_eligibility_id AND ce.contest_id = p.project_id)) +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) diff --git a/queries/get_project_category_by_category_id b/queries/get_project_category_by_category_id new file mode 100755 index 000000000..2a5585ef5 --- /dev/null +++ b/queries/get_project_category_by_category_id @@ -0,0 +1 @@ +select project_category_id,project_type_id,name from project_category_lu where display = 't' and project_category_id =@categoryId@ diff --git a/queries/get_project_category_by_category_id.json b/queries/get_project_category_by_category_id.json new file mode 100755 index 000000000..a65bcec28 --- /dev/null +++ b/queries/get_project_category_by_category_id.json @@ -0,0 +1,5 @@ +{ + "name" : "get_project_category_by_category_id", + "db" : "tcs_catalog", + "sqlfile" : "get_project_category_by_category_id" +} diff --git a/queries/get_reviewer b/queries/get_reviewer new file mode 100755 index 000000000..d8b55f3b9 --- /dev/null +++ b/queries/get_reviewer @@ -0,0 +1 @@ +SELECT user_id FROM rboard_user WHERE user_id = @userId@ AND project_type_id = @categoryId@ \ No newline at end of file diff --git a/queries/get_reviewer.json b/queries/get_reviewer.json new file mode 100755 index 000000000..dc4d36389 --- /dev/null +++ b/queries/get_reviewer.json @@ -0,0 +1,5 @@ +{ + "name" : "get_reviewer", + "db" : "tcs_catalog", + "sqlfile" : "get_reviewer" +} diff --git a/queries/get_reviewers b/queries/get_reviewers new file mode 100755 index 000000000..d44830348 --- /dev/null +++ b/queries/get_reviewers @@ -0,0 +1,4 @@ +select u.user_id, pcl.project_category_id, u.handle, pcl.name as project_category_name, immune_ind +from rboard_user ru, user u, project_category_lu pcl +where u.user_id = ru.user_id AND ru.project_type_id = pcl.project_category_id AND pcl.project_category_id = @categoryId@ +group by 1,2,3,4,5 \ No newline at end of file diff --git a/queries/get_reviewers.json b/queries/get_reviewers.json new file mode 100755 index 000000000..8b34c5a16 --- /dev/null +++ b/queries/get_reviewers.json @@ -0,0 +1,5 @@ +{ + "name" : "get_reviewers", + "db" : "tcs_catalog", + "sqlfile" : "get_reviewers" +} diff --git a/queries/get_software_studio_challenges_rss b/queries/get_software_studio_challenges_rss index ad49d3bc6..addf73084 100644 --- a/queries/get_software_studio_challenges_rss +++ b/queries/get_software_studio_challenges_rss @@ -16,4 +16,5 @@ AND p.project_status_id IN (@project_status_id@) AND pcl.project_type_id IN (@project_type_id@) AND pp1.phase_status_id IN (@registration_phase_status@) AND p.project_category_id NOT IN (27, 37) +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) -- exclude assigned tasks ORDER BY challenge_id ASC diff --git a/queries/get_terms_of_use_noauth b/queries/get_terms_of_use_noauth new file mode 100644 index 000000000..ee815774e --- /dev/null +++ b/queries/get_terms_of_use_noauth @@ -0,0 +1,10 @@ +SELECT tou.terms_of_use_id as terms_of_use_id, + tou.title as title, + tou.url as url, + tou.terms_text as text, + touat.terms_of_use_agreeability_type_id as agreeability_type_id, + toudtx.docusign_template_id as docusign_template_id +FROM terms_of_use tou +INNER JOIN terms_of_use_agreeability_type_lu touat ON touat.terms_of_use_agreeability_type_id = tou.terms_of_use_agreeability_type_id +LEFT JOIN terms_of_use_docusign_template_xref toudtx ON toudtx.terms_of_use_id = tou.terms_of_use_id +WHERE tou.terms_of_use_id = @termsOfUseId@ diff --git a/queries/get_terms_of_use_noauth.json b/queries/get_terms_of_use_noauth.json new file mode 100644 index 000000000..b00f1ea31 --- /dev/null +++ b/queries/get_terms_of_use_noauth.json @@ -0,0 +1,5 @@ +{ + "name" : "get_terms_of_use_noauth", + "db" : "common_oltp", + "sqlfile" : "get_terms_of_use_noauth" +} diff --git a/queries/get_top_members_data b/queries/get_top_members_data index 7b7ae710c..bf65f0a23 100644 --- a/queries/get_top_members_data +++ b/queries/get_top_members_data @@ -1,5 +1,6 @@ SELECT -FIRST @pageSize@ + SKIP @firstRowIndex@ + FIRST @pageSize@ c.coder_id AS user_id , handle , rating diff --git a/queries/get_upcoming_challenges b/queries/get_upcoming_challenges index 30f5bcaf2..585acf7a7 100644 --- a/queries/get_upcoming_challenges +++ b/queries/get_upcoming_challenges @@ -67,5 +67,5 @@ AND pp1.scheduled_start_time > CURRENT AND pp1.scheduled_start_time < CURRENT + 90 UNITS DAY AND pi1.project_info_type_id = 1 -- external reference id AND pi1.project_id = p.project_id - +AND not exists (select 1 from resource r, project_info pi82 where r.project_id = p.project_id and r.resource_role_id = 1 and p.project_id = pi82.project_id and project_info_type_id = 82 and pi82.value = 1) -- exclude assigned tasks ORDER BY @sort_column@ @sort_order@ diff --git a/queries/get_user_basic_profile_achievements b/queries/get_user_basic_profile_achievements index 33963ae6e..6e8897a74 100644 --- a/queries/get_user_basic_profile_achievements +++ b/queries/get_user_basic_profile_achievements @@ -4,7 +4,8 @@ SELECT , -1 as id FROM user_achievement ua JOIN coder AS c ON c.coder_id = ua.coder_id -WHERE ua.achievement_type_id in (1,4,5,6,7,8,9) AND handle_lower = LOWER('@handle@') AND c.status = 'A' +INNER JOIN achievement_type_lu atl ON atl.achievement_type_id = ua.achievement_type_id +WHERE atl.badge = 1 AND handle_lower = LOWER('@handle@') AND c.status = 'A' UNION SELECT diff --git a/queries/get_user_by_sso_login b/queries/get_user_by_sso_login new file mode 100644 index 000000000..5deb249fa --- /dev/null +++ b/queries/get_user_by_sso_login @@ -0,0 +1,5 @@ +SELECT s.user_id +FROM user_sso_login s +JOIN sso_login_provider p ON s.provider_id = p.sso_login_provider_id +WHERE p.name = '@auth_connection@' +AND lower(s.sso_user_id) = lower('@sso_user_id@') diff --git a/queries/get_user_by_sso_login.json b/queries/get_user_by_sso_login.json new file mode 100644 index 000000000..c73c00aec --- /dev/null +++ b/queries/get_user_by_sso_login.json @@ -0,0 +1,5 @@ +{ + "name" : "get_user_by_sso_login", + "db" : "common_oltp", + "sqlfile" : "get_user_by_sso_login" +} diff --git a/queries/get_user_id_by_handle b/queries/get_user_id_by_handle new file mode 100755 index 000000000..bf5a319c2 --- /dev/null +++ b/queries/get_user_id_by_handle @@ -0,0 +1 @@ +select user_id from user where handle = '@handle@' \ No newline at end of file diff --git a/queries/get_user_id_by_handle.json b/queries/get_user_id_by_handle.json new file mode 100755 index 000000000..f16209326 --- /dev/null +++ b/queries/get_user_id_by_handle.json @@ -0,0 +1,5 @@ +{ + "name": "get_user_id_by_handle", + "db": "common_oltp", + "sqlfile": "get_user_id_by_handle" +} \ No newline at end of file diff --git a/queries/insert_admin_group b/queries/insert_admin_group new file mode 100755 index 000000000..94f91b568 --- /dev/null +++ b/queries/insert_admin_group @@ -0,0 +1 @@ +INSERT INTO user_group_xref VALUES(@userGroupId@, @userId@, 2000115, @operatorId@, 1, current) \ No newline at end of file diff --git a/queries/insert_admin_group.json b/queries/insert_admin_group.json new file mode 100755 index 000000000..fff9f859d --- /dev/null +++ b/queries/insert_admin_group.json @@ -0,0 +1,5 @@ +{ + "name" : "insert_admin_group", + "db" : "tcs_catalog", + "sqlfile" : "insert_admin_group" +} \ No newline at end of file diff --git a/queries/insert_admin_role b/queries/insert_admin_role new file mode 100755 index 000000000..52b9a92d0 --- /dev/null +++ b/queries/insert_admin_role @@ -0,0 +1 @@ +INSERT INTO user_role_xref VALUES ((SELECT NVL(MIN(user_role_id), 0) - 1 FROM user_role_xref), @userId@, 2087, @operatorId@, 1) \ No newline at end of file diff --git a/queries/insert_admin_role.json b/queries/insert_admin_role.json new file mode 100755 index 000000000..24aa65f84 --- /dev/null +++ b/queries/insert_admin_role.json @@ -0,0 +1,5 @@ +{ + "name" : "insert_admin_role", + "db" : "tcs_catalog", + "sqlfile" : "insert_admin_role" +} \ No newline at end of file diff --git a/queries/insert_new_admin_resource b/queries/insert_new_admin_resource new file mode 100755 index 000000000..2d76f63a1 --- /dev/null +++ b/queries/insert_new_admin_resource @@ -0,0 +1,2 @@ +INSERT INTO resource (resource_id, resource_role_id, user_id, create_user, create_date, modify_user, modify_date) +VALUES(@resourceId@, 13, @userId@, @operatorId@, current, @operatorId@, current) \ No newline at end of file diff --git a/queries/insert_new_admin_resource.json b/queries/insert_new_admin_resource.json new file mode 100755 index 000000000..bd2f0b879 --- /dev/null +++ b/queries/insert_new_admin_resource.json @@ -0,0 +1,5 @@ +{ + "name" : "insert_new_admin_resource", + "db" : "tcs_catalog", + "sqlfile" : "insert_new_admin_resource" +} diff --git a/queries/insert_new_admin_resource_info b/queries/insert_new_admin_resource_info new file mode 100755 index 000000000..c9c6a1f6f --- /dev/null +++ b/queries/insert_new_admin_resource_info @@ -0,0 +1,2 @@ +INSERT INTO resource_info (resource_id, resource_info_type_id, value, create_user, create_date, modify_user, modify_date) +VALUES(@resourceId@, 1 , @userId@, @operatorId@, current, @operatorId@, current) \ No newline at end of file diff --git a/queries/insert_new_admin_resource_info.json b/queries/insert_new_admin_resource_info.json new file mode 100755 index 000000000..ae950aa10 --- /dev/null +++ b/queries/insert_new_admin_resource_info.json @@ -0,0 +1,5 @@ +{ + "name" : "insert_new_admin_resource_info", + "db" : "tcs_catalog", + "sqlfile" : "insert_new_admin_resource_info" +} diff --git a/queries/insert_new_copilot b/queries/insert_new_copilot new file mode 100755 index 000000000..120f1919a --- /dev/null +++ b/queries/insert_new_copilot @@ -0,0 +1,6 @@ +INSERT INTO copilot_profile (copilot_profile_id,user_id,copilot_profile_status_id,suspension_count, +reliability,activation_date,show_copilot_earnings,create_user, create_date, +update_user, update_date, is_software_copilot, is_studio_copilot) +VALUES ((select NVL(max(copilot_profile_id), 0) + 1 from copilot_profile), +@userId@,1,0,100.00, current,'t', @operatorId@, +current, @operatorId@, current, '@isSoftwareCopilot@', '@isStudioCopilot@') \ No newline at end of file diff --git a/queries/insert_new_copilot.json b/queries/insert_new_copilot.json new file mode 100755 index 000000000..c66d0a50b --- /dev/null +++ b/queries/insert_new_copilot.json @@ -0,0 +1,5 @@ +{ + "name" : "insert_new_copilot", + "db" : "tcs_catalog", + "sqlfile" : "insert_new_copilot" +} \ No newline at end of file diff --git a/queries/insert_reviewer b/queries/insert_reviewer new file mode 100755 index 000000000..289153270 --- /dev/null +++ b/queries/insert_reviewer @@ -0,0 +1 @@ +INSERT INTO rboard_user VALUES (@userId@, @categoryId@, 4, 100, @isImmunity@) \ No newline at end of file diff --git a/queries/insert_reviewer.json b/queries/insert_reviewer.json new file mode 100755 index 000000000..bd4300485 --- /dev/null +++ b/queries/insert_reviewer.json @@ -0,0 +1,5 @@ +{ + "name" : "insert_reviewer", + "db" : "tcs_catalog", + "sqlfile" : "insert_reviewer" +} diff --git a/queries/remove_admin_group b/queries/remove_admin_group new file mode 100755 index 000000000..bcee9ce54 --- /dev/null +++ b/queries/remove_admin_group @@ -0,0 +1 @@ +DELETE FROM user_group_xref WHERE login_id = @userId@ AND group_id = 2000115 \ No newline at end of file diff --git a/queries/remove_admin_group.json b/queries/remove_admin_group.json new file mode 100755 index 000000000..10ff55e15 --- /dev/null +++ b/queries/remove_admin_group.json @@ -0,0 +1,5 @@ +{ + "name" : "remove_admin_group", + "db" : "tcs_catalog", + "sqlfile" : "remove_admin_group" +} \ No newline at end of file diff --git a/queries/remove_admin_resource b/queries/remove_admin_resource new file mode 100755 index 000000000..90ba7760f --- /dev/null +++ b/queries/remove_admin_resource @@ -0,0 +1 @@ +DELETE FROM resource WHERE resource_role_id = 13 AND project_id IS NULL AND user_id = @userId@ \ No newline at end of file diff --git a/queries/remove_admin_resource.json b/queries/remove_admin_resource.json new file mode 100755 index 000000000..b309c6aa4 --- /dev/null +++ b/queries/remove_admin_resource.json @@ -0,0 +1,5 @@ +{ + "name" : "remove_admin_resource", + "db" : "tcs_catalog", + "sqlfile" : "remove_admin_resource" +} \ No newline at end of file diff --git a/queries/remove_admin_resource_info b/queries/remove_admin_resource_info new file mode 100755 index 000000000..9bbcd7d59 --- /dev/null +++ b/queries/remove_admin_resource_info @@ -0,0 +1 @@ +DELETE FROM resource_info WHERE resource_id IN (SELECT resource_id FROM resource WHERE resource_role_id = 13 AND project_id IS NULL AND user_id = @userId@) \ No newline at end of file diff --git a/queries/remove_admin_resource_info.json b/queries/remove_admin_resource_info.json new file mode 100755 index 000000000..a8d90d387 --- /dev/null +++ b/queries/remove_admin_resource_info.json @@ -0,0 +1,5 @@ +{ + "name" : "remove_admin_resource_info", + "db" : "tcs_catalog", + "sqlfile" : "remove_admin_resource_info" +} \ No newline at end of file diff --git a/queries/remove_admin_role b/queries/remove_admin_role new file mode 100755 index 000000000..8b8e70b3b --- /dev/null +++ b/queries/remove_admin_role @@ -0,0 +1 @@ +DELETE FROM user_role_xref WHERE role_id=2087 AND login_id = @userId@ \ No newline at end of file diff --git a/queries/remove_admin_role.json b/queries/remove_admin_role.json new file mode 100755 index 000000000..13be813dd --- /dev/null +++ b/queries/remove_admin_role.json @@ -0,0 +1,5 @@ +{ + "name" : "remove_admin_role", + "db" : "tcs_catalog", + "sqlfile" : "remove_admin_role" +} \ No newline at end of file diff --git a/queries/remove_copilot b/queries/remove_copilot new file mode 100755 index 000000000..296479222 --- /dev/null +++ b/queries/remove_copilot @@ -0,0 +1 @@ +DELETE FROM copilot_profile WHERE user_id = @userId@ \ No newline at end of file diff --git a/queries/remove_copilot.json b/queries/remove_copilot.json new file mode 100755 index 000000000..685beb670 --- /dev/null +++ b/queries/remove_copilot.json @@ -0,0 +1,5 @@ +{ + "name" : "remove_copilot", + "db" : "tcs_catalog", + "sqlfile" : "remove_copilot" +} \ No newline at end of file diff --git a/queries/remove_reviewer b/queries/remove_reviewer new file mode 100755 index 000000000..27d8b3b9e --- /dev/null +++ b/queries/remove_reviewer @@ -0,0 +1 @@ +DELETE FROM rboard_user WHERE user_id = @userId@ AND project_type_id = @categoryId@ \ No newline at end of file diff --git a/queries/remove_reviewer.json b/queries/remove_reviewer.json new file mode 100755 index 000000000..db152c918 --- /dev/null +++ b/queries/remove_reviewer.json @@ -0,0 +1,5 @@ +{ + "name" : "remove_reviewer", + "db" : "tcs_catalog", + "sqlfile" : "remove_reviewer" +} \ No newline at end of file diff --git a/queries/search_past_software_studio_challenges b/queries/search_past_software_studio_challenges index 660133285..53ba42220 100644 --- a/queries/search_past_software_studio_challenges +++ b/queries/search_past_software_studio_challenges @@ -105,7 +105,7 @@ AND NVL((cmc_task_id.value), '') = DECODE('@cmc@', '', NVL((cmc_task_id.value), -- Filter out the challenge that user is not belong to. AND (not exists (SELECT contest_id FROM contest_eligibility WHERE contest_id = p.project_id) OR exists(SELECT contest_id FROM contest_eligibility ce, group_contest_eligibility gce, user_group_xref x - WHERE x.login_id = @userId@ AND x.group_id = gce.group_id AND gce.contest_eligibility_id = ce.contest_eligibility_id + WHERE ((gce.group_id < 2000000 AND x.group_id = gce.group_id AND x.login_id = @user_id@) OR gce.group_id >= 2000000) AND gce.contest_eligibility_id = ce.contest_eligibility_id AND ce.contest_id = p.project_id)) and pp.actual_end_time > '2012-01-01 00:00:00' diff --git a/queries/search_past_software_studio_challenges_count b/queries/search_past_software_studio_challenges_count index 95151dbe4..81bd29d3b 100644 --- a/queries/search_past_software_studio_challenges_count +++ b/queries/search_past_software_studio_challenges_count @@ -11,7 +11,7 @@ INNER JOIN project_category_lu pcl on pcl.project_category_id = p.project_catego LEFT JOIN project_info pi1 ON pi1.project_id = p.project_id AND pi1.project_info_type_id = 1 WHERE (not exists (SELECT contest_id FROM contest_eligibility WHERE contest_id = p.project_id) OR exists(SELECT contest_id FROM contest_eligibility ce, group_contest_eligibility gce, user_group_xref x - WHERE x.login_id = 22655028 AND x.group_id = gce.group_id AND gce.contest_eligibility_id = ce.contest_eligibility_id + WHERE ((gce.group_id < 2000000 AND x.group_id = gce.group_id AND x.login_id = 22655028) OR gce.group_id >= 2000000) AND gce.contest_eligibility_id = ce.contest_eligibility_id AND ce.contest_id = p.project_id)) AND pcl.project_category_id NOT IN (27, 37) --exclude when spec review was a 'contest.' Also exclude MM, which is in there as a 'software' contest. AND p.project_status_id IN (4, 5, 6, 7, 8, 9, 10, 11) diff --git a/queries/search_software_studio_challenges b/queries/search_software_studio_challenges index 0f148ac57..18c7c1370 100644 --- a/queries/search_software_studio_challenges +++ b/queries/search_software_studio_challenges @@ -104,7 +104,7 @@ FIRST @pageSize@ -- Filter out the challenge that user is not belong to. AND (not exists (select contest_id from contest_eligibility where contest_id = p.project_id) or exists(select contest_id from contest_eligibility ce, group_contest_eligibility gce, user_group_xref x - where x.login_id = @userId@ AND x.group_id = gce.group_id AND gce.contest_eligibility_id = ce.contest_eligibility_id + where ((gce.group_id < 2000000 AND x.group_id = gce.group_id AND x.login_id = 22655028) OR gce.group_id >= 2000000) AND gce.contest_eligibility_id = ce.contest_eligibility_id AND ce.contest_id = p.project_id)) AND pcl.project_category_id NOT IN (27, 37) --exclude when spec review was a 'contest.' Also exclude MM, which is in there as a 'software' contest. -- start of parameters diff --git a/queries/search_software_studio_challenges_count b/queries/search_software_studio_challenges_count index 50a44e649..ca300b02b 100644 --- a/queries/search_software_studio_challenges_count +++ b/queries/search_software_studio_challenges_count @@ -51,7 +51,7 @@ SELECT count(*) AS total -- Filter out the challenge that user is not belong to. AND (not exists (select contest_id from contest_eligibility where contest_id = p.project_id) or exists(select contest_id from contest_eligibility ce, group_contest_eligibility gce, user_group_xref x - where x.login_id = @userId@ AND x.group_id = gce.group_id AND gce.contest_eligibility_id = ce.contest_eligibility_id + where ((gce.group_id < 2000000 AND x.group_id = gce.group_id AND x.login_id = 22655028) OR gce.group_id >= 2000000) AND gce.contest_eligibility_id = ce.contest_eligibility_id AND ce.contest_id = p.project_id)) AND pcl.project_category_id NOT IN (27, 37) --exclude when spec review was a 'contest.' Also exclude MM, which is in there as a 'software' contest. AND pstatus.project_status_id IN (@project_status_id@) diff --git a/queries/tc_direct_facts b/queries/tc_direct_facts index 945edf6bb..88adbf30e 100644 --- a/queries/tc_direct_facts +++ b/queries/tc_direct_facts @@ -1,14 +1,7 @@ SELECT (SELECT count(unique p.project_id) FROM project p - ,project_phase submpp - ,project_phase regpp -WHERE regpp.project_id = p.project_id -AND regpp.phase_type_id = 1 -AND submpp.project_id = p.project_id -AND submpp.phase_type_id = 2 -and p.project_status_id = 1 -AND (regpp.phase_status_id = 2) +WHERE p.project_status_id = 1 AND NOT EXISTS (SELECT 'has_eligibility_constraints' FROM contest_eligibility ce WHERE ce.contest_id = p.project_id) ) + @@ -33,13 +26,13 @@ WHERE ce.contest_id = p.project_id) (select count (unique rur.user_id) from resource rur - , resource_info ri + , resource_info ri , project p where p.project_id = rur.project_id and rur.resource_id = ri.resource_id - and rur.resource_role_id = 1 + and rur.resource_role_id in (1,2,3,4,5,6,7,8,9,14,18,19,20,21) and ri.resource_info_type_id = 1 - and p.project_status_id = 1) AS active_members_count, + and p.project_status_id = 1) AS active_members_count, (SELECT COUNT(*) FROM user u @@ -53,20 +46,11 @@ where exists (select project_id from project where tc_direct_project_id = dp.pro where project_status_id = 4) AS completed_projects_count, nvl((select sum(pr.prize_amount) - - FROM project p - ,project_phase submpp - ,project_phase regpp , project_category_lu pcl , prize pr -WHERE regpp.project_id = p.project_id -AND regpp.phase_type_id = 1 -AND submpp.project_id = p.project_id -AND submpp.phase_type_id = 2 -and pr.project_id = p.project_id +WHERE pr.project_id = p.project_id and p.project_status_id = 1 -AND (regpp.phase_status_id = 2) and pcl.project_category_id = p.project_category_id AND NOT EXISTS (SELECT 'has_eligibility_constraints' FROM contest_eligibility ce WHERE ce.contest_id = p.project_id)), 0) AS prize_purse diff --git a/routes.js b/routes.js index e9d94651f..57af4d99d 100755 --- a/routes.js +++ b/routes.js @@ -1,9 +1,9 @@ /* - * Copyright (C) 2013 - 2014 TopCoder Inc., All Rights Reserved. + * Copyright (C) 2013 - 2016 TopCoder Inc., All Rights Reserved. * - * @version 1.68 + * @version 1.69 * @author vangavroche, Sky_, muzehyun, kurtrips, Ghost_141, ecnu_haozi, hesibo, LazyChild, isv, flytoj2ee, - * @author panoptimum, bugbuka, Easyhard, TCASSEMBLER + * @author panoptimum, bugbuka, Easyhard, TCASSEMBLER,TCSCODER * * Changes in 1.1: * - add routes for search challenges @@ -156,6 +156,18 @@ * - Added get user develop challenges api. * Changed in 1.68: * - Added get rounds api. + * Changed in 1.69: + * - Added routes for reviewer management api: + * - Add Reviewer + * - Remove Reviewer + * - Get All Reviewers + * - Add Copilot + * - Remove Copilot + * - Get All Copilots + * - Create Admin + * - Remove Admin + * - Get All Admins + */ /*jslint node:true, nomen: true */ "use strict"; @@ -361,6 +373,11 @@ exports.routes = { { path: "/:apiVersion/auth0/callback", action: "auth0Callback" }, { path: "/:apiVersion/data/rounds", action: "getRounds" }, + //Admin App - TC API Reviewer Management API + { path: "/:apiVersion/admin/admins", action: "admins" }, + { path: "/:apiVersion/admin/copilots", action: "copilots" }, + { path: "/:apiVersion/admin/reviewers", action: "reviewers" }, + //Stubs APIs { path: "/:apiVersion/data/reviewOpportunities/:id", action: "getAlgorithmsReviewOpportunity" }, { path: "/:apiVersion/data/reviewOpportunities", action: "getAlgorithmsReviewOpportunities" }, @@ -407,7 +424,12 @@ exports.routes = { { path: "/:apiVersion/data/srm/rounds/:roundId/terms", action: "setRoundTerms"}, { path: "/:apiVersion/data/srm/rounds", action: "createSRMContestRound" }, { path: "/:apiVersion/src2image", action: "convertSourceCodeToImage" }, - { path: "/:apiVersion/dump", action: "dumpMemory"} + { path: "/:apiVersion/dump", action: "dumpMemory"}, + + //Admin App - TC API Reviewer Management API + { path: "/:apiVersion/admin/admins", action: "createAdmin" }, + { path: "/:apiVersion/admin/copilots", action: "createCopilot" }, + { path: "/:apiVersion/admin/reviewers", action: "createReviewer" } ], put: [ @@ -418,6 +440,11 @@ exports.routes = { delete: [ { path: "/:apiVersion/data/srm/rounds/:questionId/question", action: "deleteRoundQuestion" }, { path: "/:apiVersion/data/srm/rounds/:roundId", action: "deleteSRMContestRound" }, - { path: "/:apiVersion/data/srm/answer/:answerId", action: "deleteRoundQuestionAnswer" } + { path: "/:apiVersion/data/srm/answer/:answerId", action: "deleteRoundQuestionAnswer" }, + + //Admin App - TC API Reviewer Management API + { path: "/:apiVersion/admin/admins", action: "removeAdmin" }, + { path: "/:apiVersion/admin/copilots", action: "removeCopilot" }, + { path: "/:apiVersion/admin/reviewers", action: "removeReviewer" } ] }; diff --git a/test/docker/docker-compose.yml b/test/docker/docker-compose.yml new file mode 100755 index 000000000..9124c1379 --- /dev/null +++ b/test/docker/docker-compose.yml @@ -0,0 +1,6 @@ +version: '2' +services: + tc-informix: + image: appiriodevops/informix:1b3d4ef + ports: + - "2021:2021" diff --git a/test/postman/New_Challenge_Visibility_Control.postman_collection.json b/test/postman/New_Challenge_Visibility_Control.postman_collection.json new file mode 100644 index 000000000..3c52fb3e4 --- /dev/null +++ b/test/postman/New_Challenge_Visibility_Control.postman_collection.json @@ -0,0 +1,1008 @@ +{ + "id": "ba962be9-0d58-f187-8809-008a39bc2240", + "name": "New Challenge Visibility Control", + "description": "", + "order": [], + "folders": [ + { + "id": "cada5a0c-766f-dde0-3c9f-d001a67eddd4", + "name": "Get challenge", + "description": "", + "order": [ + "c383cab7-3145-145e-9da9-846001755460", + "42b84596-9d5a-50e7-76be-c1ad23f98468", + "3246a996-e8f9-5e60-79b9-8aeffcd5392f", + "bf83e2d2-549b-361e-f5cf-66a40d816f0c", + "1af5c911-4627-ad92-085c-63e6fc7b6d9e" + ], + "owner": "316251" + }, + { + "id": "712ffa63-a959-e4a3-6af9-84d4f236b2f3", + "name": "Get checkpoints", + "description": "", + "order": [ + "7c7643c6-89ab-641e-b67a-32b3ac91e09e", + "d830ec36-eb8e-9586-c546-14af77cec152", + "2af8f0d9-f3e8-c58a-ca3d-1130e4b07371", + "f545bbfc-36d7-6567-25a8-b4d6634575e7", + "a3ae5124-2077-4ff2-4e02-afae7670bbe5" + ], + "owner": "316251" + }, + { + "id": "6b9370a1-5974-a6a6-a961-67e73abaa861", + "name": "Get phases", + "description": "", + "order": [ + "c7d11de6-630a-71bd-4095-cd3c8fb8ab77", + "f5da62a7-9231-5f7a-f44a-f2f14c9ae003", + "d7a050dc-6eaa-f62e-24e4-37d111002d4a", + "c305f2ea-dbfd-f95f-c809-583133af5881", + "0461a7de-3ae1-f873-b667-50d04a43b317" + ], + "owner": "316251", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240" + }, + { + "id": "6a038555-23cd-e79f-1d34-0fb860e305a3", + "name": "Get registrants", + "description": "", + "order": [ + "bcc821a7-0e3a-3454-d900-12af0cc94656", + "70b3453b-1d1a-e411-f8e5-527edb0a2530", + "f73f4e00-c286-d440-ce79-89095d7354dd", + "e97dac4e-c786-27b1-5e4b-fff50b6de93a", + "b3cb44e7-3e5f-897e-5d6f-6179afc52653" + ], + "owner": "316251" + }, + { + "id": "2a873809-800c-ee71-51ad-94f10096709b", + "name": "Get submissions", + "description": "", + "order": [ + "f90179ed-98da-be6d-77ae-9e3aa4199b5c", + "f915c206-b3fe-a4be-1094-bc8a448cb467", + "d3e5ca45-334d-fb54-1fd7-46f8e7b82841", + "f8e9d38f-8d8d-6e63-4978-6e3546f20b7c", + "f8720a5a-5a8b-423c-065f-8d3a3469fbca" + ], + "owner": "316251", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240" + }, + { + "id": "cfbf928f-56b8-9813-f8f3-4ac4e342d965", + "name": "Register for challenges", + "description": "", + "order": [ + "4b64d85a-4c08-8ec2-9c3f-50605bd2e09e", + "5224f722-9f4f-07bb-58e7-351512cc66ea", + "60ae89de-4eb1-c0aa-b866-b28b52436e89", + "843d6759-0cc0-a0c6-9fde-60f893f56eac", + "46cf305a-8251-66aa-391c-46def82773a1" + ], + "owner": "316251" + }, + { + "id": "0eeb693c-c6b6-e23b-156d-cff5f21dbb27", + "name": "login", + "description": "", + "order": [ + "6bed8920-6800-0ae0-e63d-b39b05c7f50c", + "fd4cd936-2d4d-a272-f402-d0f7b6cab82f" + ], + "owner": "316251", + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + } + ], + "timestamp": 1474156790593, + "owner": "316251", + "public": false, + "requests": [ + { + "id": "0461a7de-3ae1-f873-b667-50d04a43b317", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/phases/1110005", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959637871, + "name": "New logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "1af5c911-4627-ad92-085c-63e6fc7b6d9e", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/phases/1110005", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959273575, + "name": "New logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "2af8f0d9-f3e8-c58a-ca3d-1130e4b07371", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/develop/challenges/checkpoint/2220003", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497550652259, + "name": "Old logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [], + "folder": "712ffa63-a959-e4a3-6af9-84d4f236b2f3" + }, + { + "id": "3246a996-e8f9-5e60-79b9-8aeffcd5392f", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110003", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497958076427, + "name": "Old logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "42b84596-9d5a-50e7-76be-c1ad23f98468", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110002", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497957969156, + "name": "Old logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "46cf305a-8251-66aa-391c-46def82773a1", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110005/register", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "POST", + "data": null, + "dataMode": "params", + "version": 2, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497813578982, + "name": "New logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "4b64d85a-4c08-8ec2-9c3f-50605bd2e09e", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110001/register", + "queryParams": [], + "pathVariables": {}, + "pathVariableData": [], + "preRequestScript": null, + "method": "POST", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "data": null, + "dataMode": "params", + "name": "No groups (challenge is not private)", + "description": "", + "descriptionFormat": "html", + "time": 1497813014785, + "version": 2, + "responses": [], + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "folder": "cfbf928f-56b8-9813-f8f3-4ac4e342d965" + }, + { + "id": "5224f722-9f4f-07bb-58e7-351512cc66ea", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110002/register", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "POST", + "data": null, + "dataMode": "params", + "version": 2, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497813399305, + "name": "Old logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "60ae89de-4eb1-c0aa-b866-b28b52436e89", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110003/register", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "POST", + "data": null, + "dataMode": "params", + "version": 2, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497813480606, + "name": "Old logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "6bed8920-6800-0ae0-e63d-b39b05c7f50c", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/auth", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "var authResponse = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"authToken\", authResponse.token);\ntests[\"Status code is 200\"] = responseCode.code === 200;\nvar jsonData = JSON.parse(responseBody);\ntests[\"A valid token is returned\"] = !!jsonData.token;", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474159263289, + "name": "Login as admin user", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [], + "rawModeData": "{\n \"username\": \"heffan\", \n \"password\": \"password\"\n}", + "folder": "0eeb693c-c6b6-e23b-156d-cff5f21dbb27" + }, + { + "id": "70b3453b-1d1a-e411-f8e5-527edb0a2530", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/registrants/1110002", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497934833132, + "name": "Old logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "7c7643c6-89ab-641e-b67a-32b3ac91e09e", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/develop/challenges/checkpoint/2220001", + "queryParams": [], + "pathVariables": {}, + "pathVariableData": [], + "preRequestScript": null, + "method": "GET", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "data": null, + "dataMode": "params", + "name": "No groups (challenge is not private)", + "description": "", + "descriptionFormat": "html", + "time": 1497550504090, + "version": 2, + "responses": [], + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "folder": "712ffa63-a959-e4a3-6af9-84d4f236b2f3" + }, + { + "id": "843d6759-0cc0-a0c6-9fde-60f893f56eac", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110004/register", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "POST", + "data": null, + "dataMode": "params", + "version": 2, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497813524683, + "name": "New logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "a3ae5124-2077-4ff2-4e02-afae7670bbe5", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/develop/challenges/checkpoint/2220005", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497550755372, + "name": "New logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [], + "folder": "712ffa63-a959-e4a3-6af9-84d4f236b2f3" + }, + { + "id": "b3cb44e7-3e5f-897e-5d6f-6179afc52653", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/registrants/1110005", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497935002619, + "name": "New logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "bcc821a7-0e3a-3454-d900-12af0cc94656", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/registrants/1110001", + "queryParams": [], + "pathVariables": {}, + "pathVariableData": [], + "preRequestScript": null, + "method": "GET", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "data": null, + "dataMode": "params", + "name": "No groups (challenge is not private)", + "description": "", + "descriptionFormat": "html", + "time": 1497934405019, + "version": 2, + "responses": [], + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "folder": "6a038555-23cd-e79f-1d34-0fb860e305a3" + }, + { + "id": "bf83e2d2-549b-361e-f5cf-66a40d816f0c", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110004", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497958165136, + "name": "New logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "c305f2ea-dbfd-f95f-c809-583133af5881", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/phases/1110004", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959248881, + "name": "New logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "c383cab7-3145-145e-9da9-846001755460", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/1110001", + "queryParams": [], + "pathVariables": {}, + "pathVariableData": [], + "preRequestScript": null, + "method": "GET", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "data": null, + "dataMode": "params", + "name": "No groups (challenge is not private)", + "description": "", + "descriptionFormat": "html", + "time": 1497957874624, + "version": 2, + "responses": [], + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "folder": "cada5a0c-766f-dde0-3c9f-d001a67eddd4" + }, + { + "id": "c7d11de6-630a-71bd-4095-cd3c8fb8ab77", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/phases/1110001", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "version": 2, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959147405, + "name": "No groups (challenge is not private)", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "d3e5ca45-334d-fb54-1fd7-46f8e7b82841", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/submissions/2220003", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959455425, + "name": "Old logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "d7a050dc-6eaa-f62e-24e4-37d111002d4a", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/phases/1110003", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959220837, + "name": "Old logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "d830ec36-eb8e-9586-c546-14af77cec152", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/develop/challenges/checkpoint/2220002", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497550612717, + "name": "Old logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [], + "folder": "712ffa63-a959-e4a3-6af9-84d4f236b2f3" + }, + { + "id": "e97dac4e-c786-27b1-5e4b-fff50b6de93a", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/registrants/1110004", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497934940451, + "name": "New logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "f545bbfc-36d7-6567-25a8-b4d6634575e7", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/develop/challenges/checkpoint/2220004", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497550705028, + "name": "New logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [], + "folder": "712ffa63-a959-e4a3-6af9-84d4f236b2f3" + }, + { + "id": "f5da62a7-9231-5f7a-f44a-f2f14c9ae003", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/phases/1110002", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959161340, + "name": "Old logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "f73f4e00-c286-d440-ce79-89095d7354dd", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/registrants/1110003", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497934860473, + "name": "Old logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "f8720a5a-5a8b-423c-065f-8d3a3469fbca", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/submissions/2220005", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959508749, + "name": "New logic, access denied", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "f8e9d38f-8d8d-6e63-4978-6e3546f20b7c", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/submissions/2220004", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959483268, + "name": "New logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "f90179ed-98da-be6d-77ae-9e3aa4199b5c", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/submissions/2220001", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "version": 2, + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959423349, + "name": "No groups (challenge is not private)", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "f915c206-b3fe-a4be-1094-bc8a448cb467", + "headers": "Authorization: Bearer {{authToken}}\n", + "headerData": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}", + "description": "", + "enabled": true + } + ], + "url": "{{url}}/challenges/submissions/2220002", + "queryParams": [], + "preRequestScript": null, + "pathVariables": {}, + "pathVariableData": [], + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1497959438513, + "name": "Old logic, access allowed", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [] + }, + { + "id": "fd4cd936-2d4d-a272-f402-d0f7b6cab82f", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/auth", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "var authResponse = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"authToken\", authResponse.token);\ntests[\"Status code is 200\"] = responseCode.code === 200;\nvar jsonData = JSON.parse(responseBody);\ntests[\"A valid token is returned\"] = !!jsonData.token;", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474159245944, + "name": "Log in as ordinary user", + "description": "", + "collectionId": "ba962be9-0d58-f187-8809-008a39bc2240", + "responses": [], + "rawModeData": "{\n \"username\": \"user\", \n \"password\": \"password\"\n}", + "folder": "0eeb693c-c6b6-e23b-156d-cff5f21dbb27" + } + ] +} \ No newline at end of file diff --git a/test/postman/New_Challenge_Visibility_Control.postman_environment.json b/test/postman/New_Challenge_Visibility_Control.postman_environment.json new file mode 100644 index 000000000..143271c12 --- /dev/null +++ b/test/postman/New_Challenge_Visibility_Control.postman_environment.json @@ -0,0 +1,34 @@ +{ + "id": "d761e292-418f-09b5-8b27-9d93eae42f1e", + "name": "New Challenge Visibility Control", + "values": [ + { + "enabled": true, + "key": "url", + "value": "http://localhost:8080/api/v2", + "type": "text" + }, + { + "enabled": true, + "key": "adminToken", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NtYS5hdXRoMC5jb20vIiwic3ViIjoiYWR8MTMyNDU2IiwiYXVkIjoiQ01hQnV3U25ZMFZ1NjhQTHJXYXR2dnUzaUlpR1BoN3QiLCJleHAiOjE1MTAxNTkyNjgsImlhdCI6MTQ3NDE1OTI2OH0.KRgW9TxNOEiEu5YdQnXQO1nKFULIuy7JlzDZdq9QFQY", + "type": "text" + }, + { + "enabled": true, + "key": "userToken", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NtYS5hdXRoMC5jb20vIiwic3ViIjoiYWR8MTMyNDU4IiwiYXVkIjoiQ01hQnV3U25ZMFZ1NjhQTHJXYXR2dnUzaUlpR1BoN3QiLCJleHAiOjE1MTAxNzI0MDgsImlhdCI6MTQ3NDE3MjQwOH0.sIG2FoNiCldizzcTMQ9iAFh-PCigNGBAlicxms6uTkk", + "type": "text" + }, + { + "enabled": true, + "key": "authToken", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NtYS5hdXRoMC5jb20vIiwic3ViIjoiYWR8MTMyNDU4IiwiYXVkIjoiQ01hQnV3U25ZMFZ1NjhQTHJXYXR2dnUzaUlpR1BoN3QiLCJleHAiOjE1MTAyODI4MDMsImlhdCI6MTQ3NDI4MjgwM30.s6q_FRFryMslkWCkR0wPSWwTopkZhHH8g9R_4GPf9m4", + "type": "text" + } + ], + "timestamp": 1497565761064, + "_postman_variable_scope": "environment", + "_postman_exported_at": "2017-06-15T22:29:38.942Z", + "_postman_exported_using": "Postman/5.0.1" +} \ No newline at end of file diff --git a/test/postman/Reviewer_Management_API.json b/test/postman/Reviewer_Management_API.json new file mode 100755 index 000000000..cd7d0837e --- /dev/null +++ b/test/postman/Reviewer_Management_API.json @@ -0,0 +1,2041 @@ +{ + "id": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "name": "Admin App - TC API Reviewer Management API", + "description": "", + "order": [], + "folders": [ + { + "id": "142d5b1b-b304-bced-c1f3-b59e8187d2aa", + "name": "create admin", + "description": "", + "order": [ + "17cd6d9b-17b2-1f5c-a0d8-e0948c718d26", + "fc7d7ac4-d1e1-a441-6717-ecb50b9ad7f6", + "9bccd2a2-8aac-1931-b78e-8b61a99415a4", + "8b843cb6-1fc6-8c0b-1d6d-f54d9470cf76", + "88ae8323-4232-1675-8796-e06c6997f3f9", + "2297e0e7-4871-b68e-6258-b59a1da3acd4", + "59d2ab3f-1ef2-3925-42c4-754eced98658", + "43dbe6f5-32e5-f0f0-5735-42a3a9f08120" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "8052cbf5-e206-af03-0392-e853f3f06bf4", + "name": "create copilot", + "description": "", + "order": [ + "3a87b2a7-3761-5089-38d9-6c7d3796e984", + "2cb65342-ba7f-b473-6afc-8a729da04563", + "e058d344-3c5d-951a-c86e-ebfeba41bab8", + "42fc7559-c2a2-8b85-67e3-3812ae0d5998", + "518db876-c166-6aa7-d484-b8b778297b4e", + "9fb05ea1-f85e-209e-7619-e40450acd7f3", + "79444594-2c40-1e6e-9f71-f22d57828026", + "26e53a5b-bef9-17f2-fb02-34595bf8a8c4", + "9ff114f0-56ca-f56c-08e4-3bb4dcaac10f", + "6727946e-aa76-0996-e734-800bb07cf5c6", + "49c5d6f4-5b86-3e9f-8c82-ef7430411264", + "858050d9-d3f2-900f-79a8-4a56c7ca586b", + "68d189c2-eb05-ded4-1e97-414ebde03ab8", + "34ac4817-1082-2274-ed98-f17b63e62786", + "477195d0-14ca-6a6e-274f-513e7d50a45c" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "7544e9b2-c615-4376-7145-511bb968c906", + "name": "create reviewer", + "description": "", + "order": [ + "ebcf31ae-035b-49ac-41d4-fa4484eff6a1", + "b84bd2e1-cd0b-3489-3c11-917a1624249e", + "4a6e3f4b-cb9e-978d-281f-81a57545b0ac", + "ac18e672-1e47-37fa-1ae8-85eed1beab2d", + "202e4545-829b-f158-372f-206e632d609f", + "8679c69e-e94d-7188-60fd-bbe506b851d1", + "2f652b9b-7dc4-8140-9ac5-e6995f1a3fba", + "a8e7c6c2-1cfb-e3ad-af5c-9c27bd71924b", + "d0a6e94f-3c59-2398-f0f5-a1d54a6f4e15", + "03ce940d-9b2d-b46b-0f84-48da5529615c", + "24bc8058-d1ef-1f33-eb64-ede9b9663f49", + "84cd43c0-c407-365b-f1f4-07929e2876cc", + "8a43eff3-3f9a-83a2-6734-a683e29252c8", + "790064a6-e429-1f9c-24b5-7112ce1fb8b2", + "0865091c-8f04-f18c-f9e5-e5c182bc8ab3", + "9e458d5b-5aa5-05ec-6240-7d171c75cf5e", + "0e55b155-b8b7-ae58-5505-f1ff9ba0eb36", + "a466f2b7-2f9c-4a14-fc0e-eee7981cdb42", + "16044f47-5b3d-2ba2-1787-8e6f7e78af97" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "2964b89d-893b-aada-2e0e-c4136b920508", + "name": "get all admins", + "description": "", + "order": [ + "b0bfa529-5f58-d5a6-e1bc-2099abfa253f", + "b83cdcb1-5abe-0f73-1c9c-b558c0634baf", + "144d7cd5-cedb-1e15-fec5-27c5e56863df", + "e10c59ae-1669-54bd-03bb-4de19d51fb5e", + "828d7e47-ee45-5ed2-fe37-2114815e84f1" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "1a80812c-dfa2-5dc4-aca7-299502bbc807", + "name": "get all copilots", + "description": "", + "order": [ + "67db2b5a-4b85-4e18-2709-5c475849329f", + "2d18170b-9631-3c97-fc68-51d0ed76766c", + "a47c9a54-d12a-6801-02a1-c57c420237cf", + "21bdc1e1-c5b2-d063-fd54-386ab396b224", + "897d4baa-72d5-1eca-ff61-51db0d14408c" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "81516934-d74e-f97d-262f-21d87d5961d1", + "name": "get all reviewers", + "description": "", + "order": [ + "08364378-8daf-8159-547e-fac22ca27847", + "c28b4a81-8ee7-24ba-fc8b-54b1b3642fab", + "8bd1727c-34f8-ced7-eb92-d50cc6e56772", + "fe0a03f9-4969-651a-5eed-01de9398498e", + "ddf839fa-733a-056a-8a2c-a1e56d0e9072", + "ef7fd1f5-a302-b7b6-a772-a43eb3b82062", + "c0db4362-622a-b556-1991-80df568707b7", + "f784d0d8-8645-7633-91c6-54ec81aa95ff", + "c1d0d1a9-a8b9-8ee7-c6e6-e539a52fbf35" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "fedff379-68f7-3322-d2e9-29471d82cc60", + "name": "login", + "description": "", + "order": [ + "f6c44b3f-570d-e48f-3b7e-8419a9ebe9b6", + "a495567b-a450-037f-ca8e-c9da52116890" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea", + "name": "remove admin", + "description": "", + "order": [ + "d2bf20ce-e0ed-a347-69dc-577e34dbefd0", + "07358622-f7d4-9233-8dc1-204acb7b1ccf", + "3f0e98fb-e97a-e6ed-8dc7-e864b1447e03", + "c8075e84-bb8d-7596-ba92-5990705f93bc", + "b8d3fef6-214c-5032-3002-f6c16f3288e2", + "2f633003-2ac7-99ec-e52a-8b1f2e0534d4", + "600d723c-706d-42ca-9ecc-94a32e280063", + "1e4fffd8-a809-e9dc-0659-0df467954407" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "2afb4105-1932-6ef0-866c-43ecb13c0048", + "name": "remove copilot", + "description": "", + "order": [ + "ccc25e86-5365-aaf6-8ce8-9838898142eb", + "85022108-999a-7200-89cd-e6b11f66bcb8", + "357caf52-98e8-90a9-8d13-1bf8d330915e", + "34b27e13-3b96-0a9e-25e6-8a339c517518", + "49952d3d-864a-25ff-3648-abbb79550dc2", + "ad152575-1e23-f242-96d2-f4b49a616c56", + "538a99a4-4701-1ee0-527c-6d2db316dae6", + "19a2adaa-d44b-5fd7-9ee7-a6d3452e4492" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + }, + { + "id": "f11d599f-4472-bcef-b9e3-7c86ac139e35", + "name": "remove reviewer", + "description": "", + "order": [ + "49557532-d98e-55e3-5cc4-4c702b62e3ed", + "3453a16f-6a34-c92c-91ed-d2107b505e7a", + "c3383672-4018-ec1b-2688-515b73987d36", + "636f8c2c-7cc2-4d90-179e-7808ae8bbba1", + "a887c7eb-8b15-90aa-07ef-6d998297bcee", + "e6b6464b-da41-67ee-c2ca-53b1d5ba417d", + "4b8d4933-247c-d204-23c6-3acd8ec2e66a", + "da88d593-5117-3c1f-f56c-47ac74724c79", + "13c71689-cfe5-512d-f5b6-d971fa88129a", + "6fd784f5-bda9-b183-1d85-c30879a47427", + "37b02c2b-7018-6af5-4e3c-57b2abde2b0e", + "05ed43fe-61be-43b3-36c7-0c4a12f98efd", + "12d79b9a-e008-ea3d-6fa4-21c7e72e4e94", + "6fcaeb1e-8611-9adf-319f-92f61ac2d62d" + ], + "owner": 0, + "collectionId": "6369974d-65cc-d819-459b-0026549ddb47" + } + ], + "timestamp": 1474156790593, + "owner": 0, + "public": false, + "published": false, + "hasRequests": true, + "requests": [ + { + "id": "03ce940d-9b2d-b46b-0f84-48da5529615c", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474188017748, + "name": "create reviewer with invalid categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": \"wrong number\"\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "05ed43fe-61be-43b3-36c7-0c4a12f98efd", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189158880, + "name": "remove reviewer with non-integer categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 1.1\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "07358622-f7d4-9233-8dc1-204acb7b1ccf", + "headers": "Authorization: Bearer {{userToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173280471, + "name": "remove admin with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "08364378-8daf-8159-547e-fac22ca27847", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/reviewers?categoryId=7", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474268286128, + "name": "get all reviewers with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "0865091c-8f04-f18c-f9e5-e5c182bc8ab3", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474268192451, + "name": "create reviewer with invalid immune", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"Yoshi\",\n \"categoryId\": 14,\n \"immune\": \"invalid boolean\"\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "0e55b155-b8b7-ae58-5505-f1ff9ba0eb36", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282763352, + "name": "create reviewer with code category id", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"Hung\",\n \"categoryId\": 39\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "12d79b9a-e008-ea3d-6fa4-21c7e72e4e94", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189177783, + "name": "remove reviewer without categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "13c71689-cfe5-512d-f5b6-d971fa88129a", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282495801, + "name": "remove reviewer with not exist username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "144d7cd5-cedb-1e15-fec5-27c5e56863df", + "headers": "", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474174192935, + "name": "get all admins without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "2964b89d-893b-aada-2e0e-c4136b920508" + }, + { + "id": "16044f47-5b3d-2ba2-1787-8e6f7e78af97", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers?categoryId=14", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474284611393, + "name": "create reviewer with categoryId in query and body at same time", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\":7\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "17cd6d9b-17b2-1f5c-a0d8-e0948c718d26", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474168970336, + "name": "create admin with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "19a2adaa-d44b-5fd7-9ee7-a6d3452e4492", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177129491, + "name": "remove copilot with not exist username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "1e4fffd8-a809-e9dc-0659-0df467954407", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173533574, + "name": "remove admin with notexist username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "202e4545-829b-f158-372f-206e632d609f", + "headers": "Authorization: wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474187893955, + "name": "create reviewer without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "21bdc1e1-c5b2-d063-fd54-386ab396b224", + "headers": "Authorization: wrong\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474176769090, + "name": "get all copilots without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "1a80812c-dfa2-5dc4-aca7-299502bbc807" + }, + { + "id": "2297e0e7-4871-b68e-6258-b59a1da3acd4", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474169000065, + "name": "create admin without username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "24bc8058-d1ef-1f33-eb64-ede9b9663f49", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474188046380, + "name": "create reviewer with nagative categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": -1\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "26e53a5b-bef9-17f2-fb02-34595bf8a8c4", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474178883094, + "name": "create copilot without username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "2cb65342-ba7f-b473-6afc-8a729da04563", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179347234, + "name": "create copilot with isSoftwareCopilot false", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": 0,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "2d18170b-9631-3c97-fc68-51d0ed76766c", + "headers": "Authorization: Bearer {{userToken}}\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474176739711, + "name": "get all copilots with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "1a80812c-dfa2-5dc4-aca7-299502bbc807" + }, + { + "id": "2f633003-2ac7-99ec-e52a-8b1f2e0534d4", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173290943, + "name": "remove admin without username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "2f652b9b-7dc4-8140-9ac5-e6995f1a3fba", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474187901930, + "name": "create reviewer without username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "3453a16f-6a34-c92c-91ed-d2107b505e7a", + "headers": "Authorization: Bearer {{userToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189053598, + "name": "remove reviewer with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "34ac4817-1082-2274-ed98-f17b63e62786", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179249694, + "name": "create copilot with invalid isStudioCopilot", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\",\n \"isStudioCopilot\": \"invalid boolean\",\n \"isSoftwareCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "34b27e13-3b96-0a9e-25e6-8a339c517518", + "headers": "Authorization: wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177113168, + "name": "remove copilot without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "357caf52-98e8-90a9-8d13-1bf8d330915e", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177110084, + "name": "remove copilot without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "37b02c2b-7018-6af5-4e3c-57b2abde2b0e", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189145913, + "name": "remove reviewer with negative categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": -1\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "3a87b2a7-3761-5089-38d9-6c7d3796e984", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474272371352, + "name": "create copilot with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "3f0e98fb-e97a-e6ed-8dc7-e864b1447e03", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173276705, + "name": "remove admin without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "42fc7559-c2a2-8b85-67e3-3812ae0d5998", + "headers": "Authorization: Bearer {{userToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177780363, + "name": "create copilot with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "43dbe6f5-32e5-f0f0-5735-42a3a9f08120", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173399023, + "name": "create admin with not exist username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "477195d0-14ca-6a6e-274f-513e7d50a45c", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179290066, + "name": "create copilot with isStudioCopilot/isSoftwareCopilot false", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isStudioCopilot\": false,\n \"isSoftwareCopilot\":false\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "49557532-d98e-55e3-5cc4-4c702b62e3ed", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474266891365, + "name": "remove reviewer with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "49952d3d-864a-25ff-3648-abbb79550dc2", + "headers": "Authorization: Bearer wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177116518, + "name": "remove copilot with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "49c5d6f4-5b86-3e9f-8c82-ef7430411264", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179169639, + "name": "create copilot with empty username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \" \",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "4a6e3f4b-cb9e-978d-281f-81a57545b0ac", + "headers": "Authorization: Bearer {{userToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474187884890, + "name": "create reviewer with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "4b8d4933-247c-d204-23c6-3acd8ec2e66a", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189091821, + "name": "remove reviewer without username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "518db876-c166-6aa7-d484-b8b778297b4e", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474178853689, + "name": "create copilot without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "538a99a4-4701-1ee0-527c-6d2db316dae6", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177126290, + "name": "remove copilot with empty username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \" \"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "59d2ab3f-1ef2-3925-42c4-754eced98658", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474169674465, + "name": "create admin with empty username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \" \"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "600d723c-706d-42ca-9ecc-94a32e280063", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173326368, + "name": "remove admin without empty username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \" \"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "636f8c2c-7cc2-4d90-179e-7808ae8bbba1", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189062608, + "name": "remove reviewer without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "6727946e-aa76-0996-e734-800bb07cf5c6", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189246551, + "name": "create copilot without isStudioCopilot", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "67db2b5a-4b85-4e18-2709-5c475849329f", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474176736874, + "name": "get all copilots with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "1a80812c-dfa2-5dc4-aca7-299502bbc807" + }, + { + "id": "68d189c2-eb05-ded4-1e97-414ebde03ab8", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179220315, + "name": "create copilot with invalid isSoftwareCopilot", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\",\n \"isSoftwareCopilot\": \"invalid boolean\",\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "6fcaeb1e-8611-9adf-319f-92f61ac2d62d", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers?categoryId=14", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474284520276, + "name": "remove reviewer with categoryId in query and body at same time", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\":7\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "6fd784f5-bda9-b183-1d85-c30879a47427", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189135829, + "name": "remove reviewer with invalid categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": \"wrong number\"\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "790064a6-e429-1f9c-24b5-7112ce1fb8b2", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474283473763, + "name": "create reviewer with immune", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"Yoshi\",\n \"categoryId\": 14,\n \"immune\":1\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "79444594-2c40-1e6e-9f71-f22d57828026", + "headers": "Authorization: Bearer wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474178865110, + "name": "create copilot with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "828d7e47-ee45-5ed2-fe37-2114815e84f1", + "headers": "Authorization: Bearer wrong\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474174234342, + "name": "get all admins with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "2964b89d-893b-aada-2e0e-c4136b920508" + }, + { + "id": "84cd43c0-c407-365b-f1f4-07929e2876cc", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474188081763, + "name": "create reviewer with non-integer categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 1.1\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "85022108-999a-7200-89cd-e6b11f66bcb8", + "headers": "Authorization: Bearer {{userToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177106806, + "name": "remove copilot with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "858050d9-d3f2-900f-79a8-4a56c7ca586b", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179176872, + "name": "create copilot with not exist username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "8679c69e-e94d-7188-60fd-bbe506b851d1", + "headers": "Authorization: Bearer wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474187897602, + "name": "create reviewer with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "88ae8323-4232-1675-8796-e06c6997f3f9", + "headers": "Authorization: Bearer wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474168987848, + "name": "create admin with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "897d4baa-72d5-1eca-ff61-51db0d14408c", + "headers": "Authorization: Bearer wrong\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474176766163, + "name": "get all copilots with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "1a80812c-dfa2-5dc4-aca7-299502bbc807" + }, + { + "id": "8a43eff3-3f9a-83a2-6734-a683e29252c8", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189200056, + "name": "create reviewer without categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "8b843cb6-1fc6-8c0b-1d6d-f54d9470cf76", + "headers": "Authorization: wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474168982704, + "name": "create admin without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "8bd1727c-34f8-ced7-eb92-d50cc6e56772", + "headers": "", + "url": "{{url}}/admin/reviewers?categoryId=7", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282217351, + "name": "get all reviewers without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "9bccd2a2-8aac-1931-b78e-8b61a99415a4", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474168977872, + "name": "create admin without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "9e458d5b-5aa5-05ec-6240-7d171c75cf5e", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282760160, + "name": "create reviewer with studio type", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"cartajs\",\n \"categoryId\": 17\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "9fb05ea1-f85e-209e-7619-e40450acd7f3", + "headers": "Authorization: wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474178858906, + "name": "create copilot without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": true,\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "9ff114f0-56ca-f56c-08e4-3bb4dcaac10f", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189226479, + "name": "create copilot without isSoftwareCopilot", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isStudioCopilot\":true\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "a466f2b7-2f9c-4a14-fc0e-eee7981cdb42", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282767080, + "name": "create reviewer with f2f category id", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"liquid_user\",\n \"categoryId\": 38\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "a47c9a54-d12a-6801-02a1-c57c420237cf", + "headers": "", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474176772030, + "name": "get all copilots without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "1a80812c-dfa2-5dc4-aca7-299502bbc807" + }, + { + "id": "a495567b-a450-037f-ca8e-c9da52116890", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/auth", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "var authResponse = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"authToken\", authResponse.token);\ntests[\"Status code is 200\"] = responseCode.code === 200;\nvar jsonData = JSON.parse(responseBody);\ntests[\"A valid token is returned\"] = !!jsonData.token;", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474159245944, + "name": "Log in as ordinary user", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"user\", \n \"password\": \"password\"\n}", + "folder": "fedff379-68f7-3322-d2e9-29471d82cc60" + }, + { + "id": "a887c7eb-8b15-90aa-07ef-6d998297bcee", + "headers": "Authorization: wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189071606, + "name": "remove reviewer without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "a8e7c6c2-1cfb-e3ad-af5c-9c27bd71924b", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282655617, + "name": "create reviewer with empty username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \" \",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "ac18e672-1e47-37fa-1ae8-85eed1beab2d", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474187888883, + "name": "create reviewer without Authorization header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "ad152575-1e23-f242-96d2-f4b49a616c56", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177119734, + "name": "remove copilot without username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "b0bfa529-5f58-d5a6-e1bc-2099abfa253f", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173887249, + "name": "get all admins with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "2964b89d-893b-aada-2e0e-c4136b920508" + }, + { + "id": "b83cdcb1-5abe-0f73-1c9c-b558c0634baf", + "headers": "Authorization: Bearer {{userToken}}\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474174015997, + "name": "get all admins with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "2964b89d-893b-aada-2e0e-c4136b920508" + }, + { + "id": "b84bd2e1-cd0b-3489-3c11-917a1624249e", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers?categoryId=14", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282455411, + "name": "create reviewer with categoryId in query", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "b8d3fef6-214c-5032-3002-f6c16f3288e2", + "headers": "Authorization: Bearer wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173287352, + "name": "remove admin with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "c0db4362-622a-b556-1991-80df568707b7", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/reviewers?categoryId=-4", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474184022183, + "name": "get all reviewers with negative categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "c1d0d1a9-a8b9-8ee7-c6e6-e539a52fbf35", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189283486, + "name": "get all reviewers without categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "c28b4a81-8ee7-24ba-fc8b-54b1b3642fab", + "headers": "Authorization: Bearer {{userToken}}\n", + "url": "{{url}}/admin/reviewers?categoryId=7", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282212758, + "name": "get all reviewers with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "c3383672-4018-ec1b-2688-515b73987d36", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers?categoryId=14", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474273020582, + "name": "remove reviewer with categoryId in query", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "c8075e84-bb8d-7596-ba92-5990705f93bc", + "headers": "Authorization: wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173283865, + "name": "remove admin without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "ccc25e86-5365-aaf6-8ce8-9838898142eb", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474177185914, + "name": "remove copilot with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "2afb4105-1932-6ef0-866c-43ecb13c0048" + }, + { + "id": "d0a6e94f-3c59-2398-f0f5-a1d54a6f4e15", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282659872, + "name": "create reviewer with not exist username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"notexist\",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "d2bf20ce-e0ed-a347-69dc-577e34dbefd0", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474173258538, + "name": "remove admin with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "78aeaf8b-80c8-40df-6ed6-2af5acdbf2ea" + }, + { + "id": "da88d593-5117-3c1f-f56c-47ac74724c79", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282491538, + "name": "remove reviewer with empty username", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \" \",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "ddf839fa-733a-056a-8a2c-a1e56d0e9072", + "headers": "Authorization: Bearer wrong\n", + "url": "{{url}}/admin/reviewers?categoryId=7", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282226901, + "name": "get all reviewers with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "e058d344-3c5d-951a-c86e-ebfeba41bab8", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/copilots", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474179507223, + "name": "create copilot with isStudioCopilot false", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"isSoftwareCopilot\": 1,\n \"isStudioCopilot\":0\n}", + "folder": "8052cbf5-e206-af03-0392-e853f3f06bf4" + }, + { + "id": "e10c59ae-1669-54bd-03bb-4de19d51fb5e", + "headers": "Authorization: wrong\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474174209799, + "name": "get all admins without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "2964b89d-893b-aada-2e0e-c4136b920508" + }, + { + "id": "e6b6464b-da41-67ee-c2ca-53b1d5ba417d", + "headers": "Authorization: Bearer wrong\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "DELETE", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474189083334, + "name": "remove reviewer with wrong Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "f11d599f-4472-bcef-b9e3-7c86ac139e35" + }, + { + "id": "ebcf31ae-035b-49ac-41d4-fa4484eff6a1", + "headers": "Authorization: Bearer {{adminToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/reviewers", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474187872946, + "name": "create reviewer with admin token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\",\n \"categoryId\": 14\n}", + "folder": "7544e9b2-c615-4376-7145-511bb968c906" + }, + { + "id": "ef7fd1f5-a302-b7b6-a772-a43eb3b82062", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/reviewers?categoryId=wrong", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474184004438, + "name": "get all reviewers with invalid categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "f6c44b3f-570d-e48f-3b7e-8419a9ebe9b6", + "headers": "Content-Type: application/json\n", + "url": "{{url}}/auth", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "version": 2, + "tests": "var authResponse = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"authToken\", authResponse.token);\ntests[\"Status code is 200\"] = responseCode.code === 200;\nvar jsonData = JSON.parse(responseBody);\ntests[\"A valid token is returned\"] = !!jsonData.token;", + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474159263289, + "name": "Login as admin user", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"heffan\", \n \"password\": \"password\"\n}", + "folder": "fedff379-68f7-3322-d2e9-29471d82cc60" + }, + { + "id": "f784d0d8-8645-7633-91c6-54ec81aa95ff", + "headers": "Authorization: Bearer {{adminToken}}\n", + "url": "{{url}}/admin/reviewers?categoryId=1.1", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474188155542, + "name": "get all reviewers with non-integer categoryId", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + }, + { + "id": "fc7d7ac4-d1e1-a441-6717-ecb50b9ad7f6", + "headers": "Authorization: Bearer {{userToken}}\nContent-Type: application/json\n", + "url": "{{url}}/admin/admins", + "preRequestScript": null, + "pathVariables": {}, + "method": "POST", + "data": [], + "dataMode": "raw", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474172375481, + "name": "create admin with user token", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "rawModeData": "{\n \"username\": \"dok_tester\"\n}", + "folder": "142d5b1b-b304-bced-c1f3-b59e8187d2aa" + }, + { + "id": "fe0a03f9-4969-651a-5eed-01de9398498e", + "headers": "Authorization: wrong\n", + "url": "{{url}}/admin/reviewers?categoryId=7", + "preRequestScript": null, + "pathVariables": {}, + "method": "GET", + "data": null, + "dataMode": "params", + "tests": null, + "currentHelper": "normal", + "helperAttributes": {}, + "time": 1474282221279, + "name": "get all reviewers without Bearer header", + "description": "", + "collectionId": "b4745ce1-c766-7823-c9cf-fa73e6b9cb2b", + "responses": [], + "folder": "81516934-d74e-f97d-262f-21d87d5961d1" + } + ] +} \ No newline at end of file diff --git a/test/postman/Reviewer_Management_API_environment.json b/test/postman/Reviewer_Management_API_environment.json new file mode 100755 index 000000000..ec4342a23 --- /dev/null +++ b/test/postman/Reviewer_Management_API_environment.json @@ -0,0 +1,34 @@ +{ + "id": "a10333e6-0eac-fbd1-136c-b3c8451c9d29", + "name": "Admin App - TC API Reviewer Management API", + "values": [ + { + "key": "url", + "value": "http://localhost:8080/api/v2", + "type": "text", + "enabled": true + }, + { + "key": "adminToken", + "type": "text", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NtYS5hdXRoMC5jb20vIiwic3ViIjoiYWR8MTMyNDU2IiwiYXVkIjoiQ01hQnV3U25ZMFZ1NjhQTHJXYXR2dnUzaUlpR1BoN3QiLCJleHAiOjE1MTAxNTkyNjgsImlhdCI6MTQ3NDE1OTI2OH0.KRgW9TxNOEiEu5YdQnXQO1nKFULIuy7JlzDZdq9QFQY", + "enabled": true + }, + { + "key": "userToken", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NtYS5hdXRoMC5jb20vIiwic3ViIjoiYWR8MTMyNDU4IiwiYXVkIjoiQ01hQnV3U25ZMFZ1NjhQTHJXYXR2dnUzaUlpR1BoN3QiLCJleHAiOjE1MTAxNzI0MDgsImlhdCI6MTQ3NDE3MjQwOH0.sIG2FoNiCldizzcTMQ9iAFh-PCigNGBAlicxms6uTkk", + "type": "text", + "enabled": true + }, + { + "key": "authToken", + "type": "text", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NtYS5hdXRoMC5jb20vIiwic3ViIjoiYWR8MTMyNDU4IiwiYXVkIjoiQ01hQnV3U25ZMFZ1NjhQTHJXYXR2dnUzaUlpR1BoN3QiLCJleHAiOjE1MTAyODI4MDMsImlhdCI6MTQ3NDI4MjgwM30.s6q_FRFryMslkWCkR0wPSWwTopkZhHH8g9R_4GPf9m4", + "enabled": true + } + ], + "timestamp": 1474282803634, + "_postman_variable_scope": "environment", + "_postman_exported_at": "2016-09-19T11:00:24.778Z", + "_postman_exported_using": "Postman/4.7.1" +} \ No newline at end of file diff --git a/test/scripts/bridge.js b/test/scripts/bridge.js new file mode 100755 index 000000000..7a8d90eb3 --- /dev/null +++ b/test/scripts/bridge.js @@ -0,0 +1,134 @@ +/*jslint nomen: true */ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * This is the simple service that provides a "bridge" between a + * client and the database server. It accepts SQL queries and executes them. + * + * Added just to solve a deployment problem. Can (and probably should) be removed + * when this problem will be fixed + * + * @author TCSCODER + * @version 1.0 + */ +"use strict"; + +var http = require("http"), + async = require("async"), + Jdbc = require("informix-wrapper"), + path = require("path"), + tcConfig = require(path.dirname(path.dirname(__dirname)) + "/config/tc-config.js").tcConfig; + +var connections = {}; + +var server = http.createServer(function (req, res) { + + if (req.method !== "POST" || req.url !== "/bridge") { + res.writeHead(404, "Not found"); + res.end(); + return; + } + + var header = {"Content-Type": "application/json"}, + body = []; + + req.on("data", function (chunk) { + body.push(chunk); + }).on("end", function () { + body = Buffer.concat(body).toString(); + + var query; + try { + query = JSON.parse(body); + query.sql = new Buffer(query.sql, "base64").toString(); + } catch (x) { + res.writeHead(400, "Bad request", header); + res.end(JSON.stringify(x.toString())); + return; + } + + if (!query.db) { + res.writeHead(400, "Bad request", header); + res.end("'db' parameter is required"); + return; + } + if (!query.sql) { + res.writeHead(400, "Bad request", header); + res.end("'sql' parameter is required"); + return; + } + try { + async.waterfall([ + function (next) { + var jdbc, prefix, settings; + + if (connections[query.db] && connections[query.db].isConnected()) { + next(null, connections[query.db]); + } else { + jdbc = connections[query.db]; + + if (!jdbc) { + prefix = tcConfig.databaseMapping[query.db]; + if (!prefix) { + res.writeHead(400, "Bad request", header); + res.end(query.db + "- unknown database"); + return; + } + settings = { + user: process.env[prefix + "_USER"], + host: process.env[prefix + "_HOST"], + port: parseInt(process.env[prefix + "_PORT"], 10), + password: process.env[prefix + "_PASSWORD"], + database: query.db, + server: process.env[prefix + "_NAME"], + minpool: parseInt(process.env.MINPOOL, 10) || 1, + maxpool: parseInt(process.env.MAXPOOL, 10) || 60, + maxsize: parseInt(process.env.MAXSIZE, 10) || 0, + idleTimeout: parseInt(process.env.IDLETIMEOUT, 10) || 3600, + timeout: parseInt(process.env.TIMEOUT, 10) || 30000 + }; + jdbc = connections[query.db] = new Jdbc(settings, console.log).initialize(); + } + jdbc.connect(function (err) { + next(err, jdbc); + }); + } + }, + function (connection, next) { + connection.query(query.sql, next).execute(); + } + ], function (err, rows) { + res.writeHead(200, header); + if (err) { + res.end(JSON.stringify({exception: err.toString()})); + } else { + res.end(JSON.stringify({results: rows})); + } + }); + } catch (x) { + res.writeHead(200, header); + res.end(JSON.stringify({exception: x.toString()})); + } + }); + +}); + +/** + * Close database connection when application exit. + */ +function gracefulShutdown() { + var db, conn; + for (db in connections) { + if (connections.hasOwnProperty(db)) { + conn = connections[db]; + if (conn.isConnected()) { + conn.disconnect(); + } + } + } + process.exit(); +} + +process.on('SIGINT', gracefulShutdown); +process.on('SIGTERM', gracefulShutdown); +server.listen(8082); diff --git a/test/scripts/mock_v3.js b/test/scripts/mock_v3.js new file mode 100644 index 000000000..8df5e8c02 --- /dev/null +++ b/test/scripts/mock_v3.js @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 TopCoder Inc., All Rights Reserved. + * + * This is the REST server that mocks some services from the V3 API + * + * @author GFalcon + * @version 1.0 + */ +"use strict"; + +var express = require('express'); +var bodyParser = require('body-parser'); + +var app = express(); + +app.use(bodyParser.json()); + +/* + * Log all incoming requests + */ +/*jslint unparam: true*/ +app.use(function (req, res, next) { + console.info('V3 Request: ' + JSON.stringify({ + path: req.path, + method: req.method, + headers: req.headers, + body: req.body + }, null, ' ')); + next(); +}); +/*jslint unparam: false*/ + +/* + * Return a fake 'authorization token' + */ +/*jslint unparam: true*/ +app.post('/v3/authorizations', function (req, res) { + res.json({ + result: { + content: { + token: 'FAKE-TOKEN' + } + } + }); +}); +/*jslint unparam: false*/ + +/* + * Get group members. Makes each group consist of one user + * (the user from the sample database whose handle is 'user') + * except one group (id 3330004) that doesn't have any users at all + */ +app.get('/v3/groups/:groupId/members', function (req, res) { + /*jslint eqeq: true*/ + if (req.params.groupId != 3330004) { + /*jslint eqeq: false*/ + res.json({ + result: { + content: [{ + memberId: 132458 + }] + } + }); + } else { + res.json({ + result: { + content: [] + } + }); + } +}); + +app.listen(8084); diff --git a/test/sqls/admins/tcs_catalog__clean b/test/sqls/admins/tcs_catalog__clean new file mode 100755 index 000000000..64ed1e235 --- /dev/null +++ b/test/sqls/admins/tcs_catalog__clean @@ -0,0 +1,4 @@ +DELETE FROM user_group_xref WHERE login_id !=132456 AND group_id = 2000115; +DELETE FROM resource_info WHERE resource_id IN (SELECT resource_id FROM resource WHERE resource_role_id = 13 AND project_id IS NULL AND user_id !=132456); +DELETE FROM resource WHERE resource_role_id = 13 AND project_id IS NULL AND user_id !=132456; +DELETE FROM user_role_xref WHERE role_id=2087 AND login_id !=132456; \ No newline at end of file diff --git a/test/sqls/admins/tcs_catalog__insert_test_data b/test/sqls/admins/tcs_catalog__insert_test_data new file mode 100755 index 000000000..169012497 --- /dev/null +++ b/test/sqls/admins/tcs_catalog__insert_test_data @@ -0,0 +1,15 @@ +INSERT INTO user_group_xref VALUES(100000, 20, 2000115, 132456, 1, current); +UPDATE informixoltp:rating SET rating = -1 WHERE coder_id = 20; +INSERT INTO resource (resource_id, resource_role_id, user_id, create_user, create_date, modify_user, modify_date) +VALUES(100000, 13, 20, 132456, current, 132456, current); +INSERT INTO resource_info (resource_id, resource_info_type_id, value, create_user, create_date, modify_user, modify_date) +VALUES(100000, 1 , 20, 132456, current, 132456, current); +INSERT INTO user_role_xref VALUES ((SELECT NVL(MIN(user_role_id), 0) - 1 FROM user_role_xref), 20, 2087, 132456, 1); + +INSERT INTO resource (resource_id, resource_role_id, user_id, create_user, create_date, modify_user, modify_date) +VALUES(100001, 13, 124856, 132456, current, 132456, current); +INSERT INTO resource_info (resource_id, resource_info_type_id, value, create_user, create_date, modify_user, modify_date) +VALUES(100001, 1 , 124856, 132456, current, 132456, current); + + +INSERT INTO user_role_xref VALUES ((SELECT NVL(MIN(user_role_id), 0) - 1 FROM user_role_xref), 124857, 2087, 132456, 1); diff --git a/test/sqls/copilots/tcs_catalog__clean b/test/sqls/copilots/tcs_catalog__clean new file mode 100755 index 000000000..d3aa9c12d --- /dev/null +++ b/test/sqls/copilots/tcs_catalog__clean @@ -0,0 +1 @@ +DELETE FROM copilot_profile; \ No newline at end of file diff --git a/test/sqls/copilots/tcs_catalog__insert_test_data b/test/sqls/copilots/tcs_catalog__insert_test_data new file mode 100755 index 000000000..c99025668 --- /dev/null +++ b/test/sqls/copilots/tcs_catalog__insert_test_data @@ -0,0 +1,6 @@ +INSERT INTO copilot_profile (copilot_profile_id,user_id,copilot_profile_status_id,suspension_count, +reliability,activation_date,show_copilot_earnings,create_user, create_date, +update_user, update_date, is_software_copilot, is_studio_copilot) +VALUES ((select NVL(max(copilot_profile_id), 0) + 1 from copilot_profile), +20 ,1,0,100.00, current,'t', 132456, +current, 132456, current, 't', 't'); \ No newline at end of file diff --git a/test/sqls/reviewers/tcs_catalog__clean b/test/sqls/reviewers/tcs_catalog__clean new file mode 100755 index 000000000..41655f22e --- /dev/null +++ b/test/sqls/reviewers/tcs_catalog__clean @@ -0,0 +1 @@ +DELETE FROM rboard_user WHERE project_type_id IN (7,17,38, 39); \ No newline at end of file diff --git a/test/sqls/reviewers/tcs_catalog__insert_test_data b/test/sqls/reviewers/tcs_catalog__insert_test_data new file mode 100755 index 000000000..7c97f24de --- /dev/null +++ b/test/sqls/reviewers/tcs_catalog__insert_test_data @@ -0,0 +1 @@ +INSERT INTO rboard_user VALUES (20, 7, 4, 100, 1); \ No newline at end of file diff --git a/test/test.admins.js b/test/test.admins.js new file mode 100755 index 000000000..df930b457 --- /dev/null +++ b/test/test.admins.js @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/admins/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; + + +describe('Get Admins API', function () { + this.timeout(60000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + clearDb(done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @return {Object} request + */ + function createRequest(statusCode, authHeader) { + var url = "/v2/admin/admins", + req = request(API_ENDPOINT) + .get(url) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, errorMessage, done) { + createRequest(statusCode, authHeader) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, file, done) { + createRequest(200, authHeader) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/admins/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, "You need to login for this api.", done); + + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, "You don\'t have access to this api.", done); + }); + + it("should return admins", function (done) { + assertResponse(adminHeader, "expect_get_admins", done); + }); + +}); diff --git a/test/test.copilots.js b/test/test.copilots.js new file mode 100755 index 000000000..e15ffa518 --- /dev/null +++ b/test/test.copilots.js @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/copilots/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; + + +describe('GET copilots API', function () { + this.timeout(60000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @return {Object} request + */ + function createRequest(statusCode, authHeader) { + var url = "/v2/admin/copilots", + req = request(API_ENDPOINT) + .get(url) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, errorMessage, done) { + createRequest(statusCode, authHeader) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, file, done) { + createRequest(200, authHeader) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/copilots/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, "You need to login for this api.", done); + + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, "You don\'t have access to this api.", done); + }); + + it("should return copilots", function (done) { + assertResponse(adminHeader, "expect_get_copilots", done); + }); + +}); diff --git a/test/test.createAdmin.js b/test/test.createAdmin.js new file mode 100755 index 000000000..09bc20d32 --- /dev/null +++ b/test/test.createAdmin.js @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/admins/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var username = 'dok_tester1'; +var testBody = {username: username}; + +describe('Create Admin API', function () { + this.timeout(600000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @return {Object} request + */ + function createRequest(statusCode, authHeader, postData) { + var url = "/v2/admin/admins", + req = request(API_ENDPOINT) + .post(url) + .send(postData) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, postData, errorMessage, done) { + createRequest(statusCode, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, postData, file, done) { + createRequest(200, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/admins/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, testBody, "You need to login for this api.", done); + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, testBody, "You don\'t have access to this api.", done); + }); + + it("should return required error for missing username", function (done) { + assertResponse(adminHeader, {}, "expect_create_admin_with_empty_body", done); + }); + + it("should return validation error for empty username", function (done) { + assertErrorResponse(400, adminHeader, {username: ' \n \t \r'}, + "username should be non-null and non-empty string.", done); + }); + + it("should return validation error for invalid username", function (done) { + assertErrorResponse(400, adminHeader, {username: true}, + "username should be string.", done); + }); + + it("should return not found error if not exist user", function (done) { + assertErrorResponse(404, adminHeader, {username: 'notexist'}, + "User with the username: notexist does not exist", done); + }); + + it("should return already exist error for exist admin username", function (done) { + assertErrorResponse(409, adminHeader, {username: 'dok_tester'}, + "User dok_tester has already been added to Admin Group", done); + }); + + it("should create admin successfully", function (done) { + assertResponse(adminHeader, testBody, "expect_create_admin", done); + }); + + it("should create admin successfully if exist admin resource", function (done) { + assertResponse(adminHeader, {username: 'wyzmo'}, "expect_create_admin_with_exist_admin_resource", done); + }); + + it("should return admin role exist role if exist admin role", function (done) { + assertErrorResponse(409, adminHeader, {username: 'cartajs'}, + "User cartajs has already been assigned Admin role", done); + }); +}); diff --git a/test/test.createCopilot.js b/test/test.createCopilot.js new file mode 100755 index 000000000..86b9fe953 --- /dev/null +++ b/test/test.createCopilot.js @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var _ = require('underscore'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/copilots/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var username = 'dok_tester1'; +var testBody = { + username: username, + isSoftwareCopilot: true, + isStudioCopilot: false +}; + +describe('Create Copilot API', function () { + this.timeout(600000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @return {Object} request + */ + function createRequest(statusCode, authHeader, postData) { + var url = "/v2/admin/copilots", + req = request(API_ENDPOINT) + .post(url) + .send(postData) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, postData, errorMessage, done) { + createRequest(statusCode, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, postData, file, done) { + createRequest(200, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/copilots/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, testBody, "You need to login for this api.", done); + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, testBody, "You don\'t have access to this api.", done); + }); + + it("should return required error for empty body or missing username", function (done) { + assertResponse(adminHeader, {}, "expect_create_copilot_with_empty_body", done); + }); + + + it("should return required error for missing isSoftwareCopilot", function (done) { + assertResponse(adminHeader, _.omit(testBody, 'isSoftwareCopilot'), + "expect_create_copilot_with_missing_isSoftwareCopilot", done); + }); + + it("should return required error for missing isStudioCopilot", function (done) { + assertResponse(adminHeader, _.omit(testBody, 'isStudioCopilot'), + "expect_create_copilot_with_missing_isStudioCopilot", done); + }); + + it("should return validation error for empty username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: ' \n \t \r'}), + "username should be non-null and non-empty string.", done); + }); + + it("should return validation error for invalid username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: true}), + "username should be string.", done); + }); + + it("should return validation error for invalid isStudioCopilot", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {isStudioCopilot: 'invalid boolean'}), + "isStudioCopilot should be 0, 1, true or false.", done); + }); + + it("should return validation error for invalid isSoftwareCopilot", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {isSoftwareCopilot: 'invalid boolean'}), + "isSoftwareCopilot should be 0, 1, true or false.", done); + }); + + it("should return validation error for isSoftwareCopilot/isStudioCopilot false at same time", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), { isStudioCopilot: 0, isSoftwareCopilot: false }), + "Studio Copilot and Software Copilot Checkbox should have at least one checked", done); + }); + + it("should return not found error if not exist user", function (done) { + assertErrorResponse(404, adminHeader, _.extend(_.clone(testBody), {username: 'notexist'}), + "User with the username: notexist does not exist", done); + }); + + it("should return duplicate resource error if exist copilot", function (done) { + assertErrorResponse(409, adminHeader, _.extend(_.clone(testBody), {username: 'dok_tester'}), + "The user dok_tester is already added as copilot", done); + }); + + it("should create copilot successfully", function (done) { + assertResponse(adminHeader, testBody, "expect_create_copilot", done); + }); +}); diff --git a/test/test.createReviewer.js b/test/test.createReviewer.js new file mode 100755 index 000000000..f22b48991 --- /dev/null +++ b/test/test.createReviewer.js @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var _ = require('underscore'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/reviewers/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var username = 'dok_tester1'; +var testBody = { + username: username, + categoryId: 7, + immune: 0 +}; + +describe('Create Reviewer API', function () { + this.timeout(6000000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @return {Object} request + */ + function createRequest(statusCode, authHeader, postData) { + var url = "/v2/admin/reviewers", + req = request(API_ENDPOINT) + .post(url) + .send(postData) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, postData, errorMessage, done) { + createRequest(statusCode, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, postData, file, done) { + createRequest(200, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (file) { + var body = res.body, expected = require("./test_files/reviewers/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + } + done(); + }); + } + + /** + * Create reviewer and validate exist such reviewer with immune = true + * @param {Object} postData - the data post to api. + * @param {Boolean} immune - the immune flag + * @param {Function} done - the callback + */ + function assertCreateAndGetAllResponse(postData, immune, done) { + var authHeader = adminHeader; + assertResponse(adminHeader, postData, null, function (err) { + if (err) { + return done(err); + } + request(API_ENDPOINT) + .get("/v2/admin/reviewers?categoryId=" + postData.categoryId) + .set('Accept', 'application/json') + .set('Authorization', authHeader) + .expect('Content-Type', /json/) + .expect(200) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var reviewer = _.find(res.body.reviewers, function (data) { + return data.name === postData.username; + }); + assert.ok(reviewer); + assert.equal(reviewer.immune, immune); + done(); + }); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, testBody, "You need to login for this api.", done); + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, testBody, "You don\'t have access to this api.", done); + }); + + it("should return required error for empty body or missing username", function (done) { + assertResponse(adminHeader, {}, "expect_create_reviewer_with_empty_body", done); + }); + + + it("should return required error for missing categoryId", function (done) { + assertResponse(adminHeader, _.omit(testBody, 'categoryId'), + "expect_create_reviewer_with_missing_categoryId", done); + }); + + + it("should return validation error for empty username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: ' \n \t \r'}), + "username should be non-null and non-empty string.", done); + }); + + it("should return validation error for invalid username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: true}), + "username should be string.", done); + }); + + it("should return validation error for invalid categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: 'invalid number'}), + "categoryId should be number.", done); + }); + + it("should return validation error for negative categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: -2}), + "categoryId should be positive.", done); + }); + + it("should return validation error for non-integer categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: 1.1}), + "categoryId should be Integer.", done); + }); + + it("should return validation error for invalid immune", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {immune: 'invalid boolean'}), + "immune should be 0, 1, true or false.", done); + }); + + it("should return validation error for not valid categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: 99999}), + "Category Id 99999 is not a valid category ID", done); + }); + + it("should return not found error if not exist user", function (done) { + assertErrorResponse(404, adminHeader, _.extend(_.clone(testBody), {username: 'notexist'}), + "User with the username: notexist does not exist", done); + }); + + it("should return duplicate resource error if exist reviewer", function (done) { + assertErrorResponse(409, adminHeader, _.extend(_.clone(testBody), {username: 'dok_tester'}), + "User dok_tester is in the specific review board", done); + }); + + it("should create reviewer successfully", function (done) { + assertResponse(adminHeader, testBody, "expect_create_reviewer", done); + }); + + it("should create immune=true reviewer successfully with immune=1 in body", function (done) { + assertCreateAndGetAllResponse(_.extend(_.omit(testBody, 'immune'), {username: 'wyzmo', immune: 1}), true, done); + }); + + it("should create immune=false reviewer successfully with immune=0 in body", function (done) { + assertCreateAndGetAllResponse(_.extend(_.omit(testBody, 'immune'), { + username: 'ksmith', + immune: 0 + }), false, done); + }); + + it("should create immune=true reviewer successfully with studio type", function (done) { + // 17 = Web Design = Studio type + assertCreateAndGetAllResponse(_.extend(_.omit(testBody, 'immune'), { + username: 'cartajs', + categoryId: 17 + }), true, done); + }); + + it("should create immune=false reviewer successfully with immune=false in body", function (done) { + assertCreateAndGetAllResponse(_.extend(_.omit(testBody, 'immune'), + {username: 'Yoshi', categoryId: 17, immune: false}), false, done); + }); + + it("should create immune=true reviewer successfully with code category id in body", function (done) { + assertCreateAndGetAllResponse(_.extend(_.omit(testBody, 'immune'), + {username: 'Hung', categoryId: 39}), true, done); + }); + + + it("should create immune=true reviewer successfully with f2f category id in body", function (done) { + assertCreateAndGetAllResponse(_.extend(_.omit(testBody, 'immune'), + {username: 'liquid_user', categoryId: 38}), true, done); + }); + +}); diff --git a/test/test.removeAdmin.js b/test/test.removeAdmin.js new file mode 100755 index 000000000..1904ccb21 --- /dev/null +++ b/test/test.removeAdmin.js @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/admins/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var username = 'dok_tester'; +var testBody = {username: username}; + +describe('Remove Admin API', function () { + this.timeout(600000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @return {Object} request + */ + function createRequest(statusCode, authHeader, postData) { + var url = "/v2/admin/admins", + req = request(API_ENDPOINT) + .del(url) + .send(postData) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, postData, errorMessage, done) { + createRequest(statusCode, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, postData, file, done) { + createRequest(200, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/admins/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, testBody, "You need to login for this api.", done); + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, testBody, "You don\'t have access to this api.", done); + }); + + it("should return required error for missing username", function (done) { + assertResponse(adminHeader, {}, "expect_remove_admin_with_empty_body", done); + }); + + it("should return validation error for empty username", function (done) { + assertErrorResponse(400, adminHeader, {username: ' \n \t \r'}, + "username should be non-null and non-empty string.", done); + }); + + it("should return validation error for invalid username", function (done) { + assertErrorResponse(400, adminHeader, {username: true}, + "username should be string.", done); + }); + + it("should return not found error if not exist user", function (done) { + assertErrorResponse(404, adminHeader, {username: 'notexist'}, + "User with the username: notexist does not exist", done); + }); + + it("should remove admin successfully", function (done) { + assertResponse(adminHeader, testBody, "expect_remove_admin", done); + }); +}); diff --git a/test/test.removeCopilot.js b/test/test.removeCopilot.js new file mode 100755 index 000000000..48ae05c01 --- /dev/null +++ b/test/test.removeCopilot.js @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var _ = require('underscore'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/copilots/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var username = 'dok_tester'; +var testBody = { + username: username, + isSoftwareCopilot: true, + isStudioCopilot: false +}; + +describe('Remove Copilot API', function () { + this.timeout(600000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @return {Object} request + */ + function createRequest(statusCode, authHeader, postData) { + var url = "/v2/admin/copilots", + req = request(API_ENDPOINT) + .del(url) + .send(postData) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, postData, errorMessage, done) { + createRequest(statusCode, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, postData, file, done) { + createRequest(200, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/copilots/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, testBody, "You need to login for this api.", done); + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, testBody, "You don\'t have access to this api.", done); + }); + + it("should return required error for empty body or missing username", function (done) { + assertResponse(adminHeader, {}, "expect_remove_copilot_with_empty_body", done); + }); + + + it("should return validation error for empty username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: ' \n \t \r'}), + "username should be non-null and non-empty string.", done); + }); + + it("should return validation error for invalid username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: true}), + "username should be string.", done); + }); + + it("should return not found error if not exist user", function (done) { + assertErrorResponse(404, adminHeader, _.extend(_.clone(testBody), {username: 'notexist'}), + "User with the username: notexist does not exist", done); + }); + + it("should return not found error if not exist copilot", function (done) { + assertErrorResponse(404, adminHeader, _.extend(_.clone(testBody), {username: 'user'}), + "user is not in the copilot pool", done); + }); + + + it("should remove copilot successfully", function (done) { + assertResponse(adminHeader, testBody, "expect_remove_copilot", done); + }); +}); diff --git a/test/test.removeReviewer.js b/test/test.removeReviewer.js new file mode 100755 index 000000000..1290fd1aa --- /dev/null +++ b/test/test.removeReviewer.js @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var _ = require('underscore'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/reviewers/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var testBody = { + username: 'dok_tester', + categoryId: 7 +}; + +describe('Remove Reviewer API', function () { + this.timeout(6000000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @return {Object} request + */ + function createRequest(statusCode, authHeader, postData) { + var url = "/v2/admin/reviewers", + req = request(API_ENDPOINT) + .del(url) + .send(postData) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, postData, errorMessage, done) { + createRequest(statusCode, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {Object} postData - the data post to api. + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, postData, file, done) { + createRequest(200, authHeader, postData) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (file) { + var body = res.body, expected = require("./test_files/reviewers/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + } + done(); + }); + } + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, testBody, "You need to login for this api.", done); + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, testBody, "You don\'t have access to this api.", done); + }); + + it("should return required error for empty body or missing username", function (done) { + assertResponse(adminHeader, {}, "expect_remove_reviewer_with_empty_body", done); + }); + + + it("should return required error for missing categoryId", function (done) { + assertResponse(adminHeader, _.omit(testBody, 'categoryId'), + "expect_remove_reviewer_with_missing_categoryId", done); + }); + + + it("should return validation error for empty username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: ' \n \t \r'}), + "username should be non-null and non-empty string.", done); + }); + + it("should return validation error for invalid username", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {username: true}), + "username should be string.", done); + }); + + it("should return validation error for invalid categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: 'invalid number'}), + "categoryId should be number.", done); + }); + + it("should return validation error for negative categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: -2}), + "categoryId should be positive.", done); + }); + + it("should return validation error for non-integer categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: 1.1}), + "categoryId should be Integer.", done); + }); + + + it("should return validation error for not valid categoryId", function (done) { + assertErrorResponse(400, adminHeader, _.extend(_.clone(testBody), {categoryId: 99999}), + "Category Id 99999 is not a valid category ID", done); + }); + + it("should return not found error if not exist user", function (done) { + assertErrorResponse(404, adminHeader, _.extend(_.clone(testBody), {username: 'notexist'}), + "User with the username: notexist does not exist", done); + }); + + it("should return not found error if not reviewer", function (done) { + assertErrorResponse(404, adminHeader, _.extend(_.clone(testBody), {username: 'user'}), + "There is no reviewer with the username:user in category: Architecture", done); + }); + + it("should remove reviewer successfully", function (done) { + assertResponse(adminHeader, testBody, "expect_remove_reviewer", done); + }); +}); diff --git a/test/test.reviewers.js b/test/test.reviewers.js new file mode 100755 index 000000000..e17af97c2 --- /dev/null +++ b/test/test.reviewers.js @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSCODER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach */ +/*jslint nomen: true */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var request = require('supertest'); +var assert = require('chai').assert; +var async = require("async"); + +var testHelper = require('./helpers/testHelper'); +var SQL_DIR = __dirname + "/sqls/reviewers/"; +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; + + +describe('Get Reviewers API', function () { + this.timeout(60000); // The api with testing remote db could be quit slow + var adminHeader, memberHeader; + + /** + * Create authorization header before each test + * @param {Function} done the callback + */ + beforeEach(function (done) { + adminHeader = "Bearer " + testHelper.getAdminJwt(); + memberHeader = "Bearer " + testHelper.getMemberJwt(); + done(); + }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__clean", "tcs_catalog", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + function (cb) { + clearDb(cb); + }, function (cb) { + testHelper.runSqlFile(SQL_DIR + "tcs_catalog__insert_test_data", "tcs_catalog", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @return {Object} request + */ + function createRequest(statusCode, authHeader) { + var url = "/v2/admin/reviewers?categoryId=7", + req = request(API_ENDPOINT) + .get(url) + .set('Accept', 'application/json'); + if (authHeader) { + req = req.set('Authorization', authHeader); + } + return req.expect('Content-Type', /json/).expect(statusCode); + } + + /** + * Get response and assert it + * @param {Number} statusCode the expected status code + * @param {String} authHeader the Authorization header. Optional + * @param {String} errorMessage the expected error message header. Optional + * @param {Function} done the callback + */ + function assertErrorResponse(statusCode, authHeader, errorMessage, done) { + createRequest(statusCode, authHeader) + .end(function (err, res) { + if (err) { + done(err); + return; + } + if (errorMessage) { + assert.ok(res.body); + assert.ok(res.body.error); + if (statusCode === 200) { + assert.equal(res.body.error, errorMessage); + } else { + assert.equal(res.body.error.details, errorMessage); + } + } + done(); + }); + } + + /** + * Make request to checkpoint API and compare response with given file + * @param {String} authHeader the Authorization header. Optional + * @param {String} file - the file which contains expected response + * @param {Function} done - the callback + */ + function assertResponse(authHeader, file, done) { + createRequest(200, authHeader) + .end(function (err, res) { + if (err) { + done(err); + return; + } + var body = res.body, expected = require("./test_files/reviewers/" + file); + delete body.serverInformation; + delete body.requesterInformation; + assert.deepEqual(body, expected, "Invalid response"); + done(); + }); + } + + + it("should return unauthorized error for missing Authorization header", function (done) { + assertErrorResponse(401, null, "You need to login for this api.", done); + + }); + + it("should return forbidden error for not admin token", function (done) { + assertErrorResponse(403, memberHeader, "You don\'t have access to this api.", done); + }); + + it("should return reviewers", function (done) { + assertResponse(adminHeader, "expect_get_reviewers", done); + }); + +}); diff --git a/test/test_files/admins/expect_create_admin.json b/test/test_files/admins/expect_create_admin.json new file mode 100755 index 000000000..6f0dbd086 --- /dev/null +++ b/test/test_files/admins/expect_create_admin.json @@ -0,0 +1,4 @@ +{ + "success": true, + "message": "dok_tester1 has been successfully added as TopCoder Admin" +} \ No newline at end of file diff --git a/test/test_files/admins/expect_create_admin_with_empty_body.json b/test/test_files/admins/expect_create_admin_with_empty_body.json new file mode 100755 index 000000000..cfaebe23c --- /dev/null +++ b/test/test_files/admins/expect_create_admin_with_empty_body.json @@ -0,0 +1,3 @@ +{ + "error": "Error: username is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/admins/expect_create_admin_with_exist_admin_resource.json b/test/test_files/admins/expect_create_admin_with_exist_admin_resource.json new file mode 100755 index 000000000..9653f022b --- /dev/null +++ b/test/test_files/admins/expect_create_admin_with_exist_admin_resource.json @@ -0,0 +1,4 @@ +{ + "success": true, + "message": "wyzmo has been successfully added as TopCoder Admin" +} \ No newline at end of file diff --git a/test/test_files/admins/expect_get_admins.json b/test/test_files/admins/expect_get_admins.json new file mode 100755 index 000000000..2e3c7cdb5 --- /dev/null +++ b/test/test_files/admins/expect_get_admins.json @@ -0,0 +1,11 @@ +{ + "allAdmins": [ + { + "adminGroup": true, + "adminRole": true, + "id": 132456, + "managerResource": true, + "name": "heffan" + } + ] +} \ No newline at end of file diff --git a/test/test_files/admins/expect_remove_admin.json b/test/test_files/admins/expect_remove_admin.json new file mode 100755 index 000000000..b07185a05 --- /dev/null +++ b/test/test_files/admins/expect_remove_admin.json @@ -0,0 +1,4 @@ +{ + "success": true, + "message": "TopCoder Admin: dok_tester has been successfully removed" +} \ No newline at end of file diff --git a/test/test_files/admins/expect_remove_admin_with_empty_body.json b/test/test_files/admins/expect_remove_admin_with_empty_body.json new file mode 100755 index 000000000..cfaebe23c --- /dev/null +++ b/test/test_files/admins/expect_remove_admin_with_empty_body.json @@ -0,0 +1,3 @@ +{ + "error": "Error: username is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_create_copilot.json b/test/test_files/copilots/expect_create_copilot.json new file mode 100755 index 000000000..4a17102f0 --- /dev/null +++ b/test/test_files/copilots/expect_create_copilot.json @@ -0,0 +1,4 @@ +{ + "message": "Copilot dok_tester1 has been successfully added", + "success": true +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_create_copilot_with_empty_body.json b/test/test_files/copilots/expect_create_copilot_with_empty_body.json new file mode 100755 index 000000000..cfaebe23c --- /dev/null +++ b/test/test_files/copilots/expect_create_copilot_with_empty_body.json @@ -0,0 +1,3 @@ +{ + "error": "Error: username is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_create_copilot_with_missing_isSoftwareCopilot.json b/test/test_files/copilots/expect_create_copilot_with_missing_isSoftwareCopilot.json new file mode 100755 index 000000000..a043993ba --- /dev/null +++ b/test/test_files/copilots/expect_create_copilot_with_missing_isSoftwareCopilot.json @@ -0,0 +1,3 @@ +{ + "error": "Error: isSoftwareCopilot is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_create_copilot_with_missing_isStudioCopilot.json b/test/test_files/copilots/expect_create_copilot_with_missing_isStudioCopilot.json new file mode 100755 index 000000000..756831d32 --- /dev/null +++ b/test/test_files/copilots/expect_create_copilot_with_missing_isStudioCopilot.json @@ -0,0 +1,3 @@ +{ + "error": "Error: isStudioCopilot is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_get_copilots.json b/test/test_files/copilots/expect_get_copilots.json new file mode 100755 index 000000000..4a83f8652 --- /dev/null +++ b/test/test_files/copilots/expect_get_copilots.json @@ -0,0 +1,10 @@ +{ + "allCopilots": [ + { + "id": 20, + "name": "dok_tester", + "softwareCopilot": true, + "studioCopilot": true + } + ] +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_remove_copilot.json b/test/test_files/copilots/expect_remove_copilot.json new file mode 100755 index 000000000..7939ccf6e --- /dev/null +++ b/test/test_files/copilots/expect_remove_copilot.json @@ -0,0 +1,4 @@ +{ + "success": true, + "message": "Copilot dok_tester has been successfully removed" +} \ No newline at end of file diff --git a/test/test_files/copilots/expect_remove_copilot_with_empty_body.json b/test/test_files/copilots/expect_remove_copilot_with_empty_body.json new file mode 100755 index 000000000..cfaebe23c --- /dev/null +++ b/test/test_files/copilots/expect_remove_copilot_with_empty_body.json @@ -0,0 +1,3 @@ +{ + "error": "Error: username is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_create_reviewer.json b/test/test_files/reviewers/expect_create_reviewer.json new file mode 100755 index 000000000..c209e8f5e --- /dev/null +++ b/test/test_files/reviewers/expect_create_reviewer.json @@ -0,0 +1,4 @@ +{ + "message": "dok_tester1 has been successfully added into Architecture Review Board", + "success": true +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_create_reviewer_with_empty_body.json b/test/test_files/reviewers/expect_create_reviewer_with_empty_body.json new file mode 100755 index 000000000..cfaebe23c --- /dev/null +++ b/test/test_files/reviewers/expect_create_reviewer_with_empty_body.json @@ -0,0 +1,3 @@ +{ + "error": "Error: username is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_create_reviewer_with_missing_categoryId.json b/test/test_files/reviewers/expect_create_reviewer_with_missing_categoryId.json new file mode 100755 index 000000000..1763c9a49 --- /dev/null +++ b/test/test_files/reviewers/expect_create_reviewer_with_missing_categoryId.json @@ -0,0 +1,3 @@ +{ + "error": "Error: categoryId is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_get_reviewers.json b/test/test_files/reviewers/expect_get_reviewers.json new file mode 100755 index 000000000..2e9e8b631 --- /dev/null +++ b/test/test_files/reviewers/expect_get_reviewers.json @@ -0,0 +1,12 @@ +{ + "categoryId":7, + "reviewers": [ + { + "id": 20, + "name": "dok_tester", + "projectCategoryId": 7, + "projectCategoryName": "Architecture", + "immune": true + } + ] +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_remove_reviewer.json b/test/test_files/reviewers/expect_remove_reviewer.json new file mode 100755 index 000000000..4eaad6ebc --- /dev/null +++ b/test/test_files/reviewers/expect_remove_reviewer.json @@ -0,0 +1,4 @@ +{ + "success": true, + "message": "dok_tester has been successfully removed from Architecture Review Board" +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_remove_reviewer_with_empty_body.json b/test/test_files/reviewers/expect_remove_reviewer_with_empty_body.json new file mode 100755 index 000000000..cfaebe23c --- /dev/null +++ b/test/test_files/reviewers/expect_remove_reviewer_with_empty_body.json @@ -0,0 +1,3 @@ +{ + "error": "Error: username is a required parameter for this action" +} \ No newline at end of file diff --git a/test/test_files/reviewers/expect_remove_reviewer_with_missing_categoryId.json b/test/test_files/reviewers/expect_remove_reviewer_with_missing_categoryId.json new file mode 100755 index 000000000..1763c9a49 --- /dev/null +++ b/test/test_files/reviewers/expect_remove_reviewer_with_missing_categoryId.json @@ -0,0 +1,3 @@ +{ + "error": "Error: categoryId is a required parameter for this action" +} \ No newline at end of file