diff --git a/.gitignore b/.gitignore index fda4d8551..d5f8cf869 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,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/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/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/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/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/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/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/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/.dataAccess.js.swp b/initializers/.dataAccess.js.swp new file mode 100644 index 000000000..542d73f7e Binary files /dev/null and b/initializers/.dataAccess.js.swp differ diff --git a/initializers/helper.js b/initializers/helper.js old mode 100644 new mode 100755 index 2e53f1cc6..7170bd95d --- 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; @@ -1980,6 +2001,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/local/docker-compose.yml b/local/docker-compose.yml index 986dbdedb..d37d536f0 100644 --- a/local/docker-compose.yml +++ b/local/docker-compose.yml @@ -1,6 +1,15 @@ version: '2' services: + informix: + image: appiriodevops/informix:1.2 + ports: + - 2021:2021 tc-api: - image: "node" + build: ./node + depends_on: + - informix ports: - - "7777:7777" + - "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..ac4e6ab9c --- /dev/null +++ b/local/env.sh @@ -0,0 +1,100 @@ +#!/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://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.org b/package.json.org new file mode 100644 index 000000000..2306e2aeb --- /dev/null +++ b/package.json.org @@ -0,0 +1,62 @@ +{ + "author": "TCASSEMBLER", + "name": "tcapi", + "description": "", + "version": "0.0.1", + "homepage": "", + "repository": { + "type": "", + "url": "" + }, + "keywords": "", + "engines": { + "node": ">=0.8.0" + }, + "dependencies": { + "actionhero": "8.0.x", + "xml2js": "0.2.x", + "async": "0.2.x", + "underscore": "1.5.x", + "datejs": "0.0.x", + "string": "1.6.x", + "ldapjs": "0.7.x", + "nodemailer": "0.5.x", + "email-templates": "0.1.x", + "bcrypt": "0.7.x", + "bigdecimal": "0.6.x", + "bignum": "0.6.x", + "java": "0.3.x", + "informix-wrapper": "git://github.com/cloudspokes/informix-wrapper.git#469300dbd4913c5d467b6957bc4610d95c3923ed", + "forums-wrapper": "git://github.com/cloudspokes/forums-wrapper.git#12b57be495c2e10431173522bc9eff60e0575959", + "asn1": "*", + "crypto": "0.0.x", + "jsonwebtoken": "0.4.x", + "request": "~2.33.0", + "soap": "~0.3.2", + "moment-timezone": "0.0.x", + "moment": "~2.5.1", + "mime": "~1.2.11", + "xtend": "2.1.x", + "validator": "~3.5.0", + "adm-zip": "0.4.x", + "mkdirp": "0.3.x", + "archiver": "~0.6.1", + "redis": "0.10.x", + "temp": "0.7.0", + "ssha": "*" + }, + "devDependencies": { + "supertest": "0.8.x", + "mocha": "1.x", + "chai": "1.8.x", + "fakeredis": "0.1.x", + "should": ">= 3.0.0" + }, + "scripts": { + "start": "node ./node_modules/.bin/actionhero start &", + "test": "node_modules/.bin/mocha --recursive ./test", + "startCluster": "node ./node_modules/.bin/actionhero startCluster", + "actionHero": "node ./node_modules/.bin/actionhero", + "help": "node ./node_modules/.bin/actionhero help" + } +} 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_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_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_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_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_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/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/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/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