diff --git a/.circleci/config.yml b/.circleci/config.yml index a6ff4b0..c531c3f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -67,6 +67,7 @@ workflows: branches: only: - develop + - feat/create-skill-obj # Production builds are exectuted only on tagged commits to the # master branch. diff --git a/src/controllers/StatisticsController.js b/src/controllers/StatisticsController.js index 2da9466..8729134 100644 --- a/src/controllers/StatisticsController.js +++ b/src/controllers/StatisticsController.js @@ -43,6 +43,16 @@ async function getMemberSkills (req, res) { res.send(result) } +/** + * Create member skills + * @param {Object} req the request + * @param {Object} res the response + */ +async function createMemberSkills (req, res) { + const result = await service.createMemberSkills(req.authUser, req.params.handle, req.body) + res.send(result) +} + /** * Partially update member skills * @param {Object} req the request @@ -58,5 +68,6 @@ module.exports = { getHistoryStats, getMemberStats, getMemberSkills, + createMemberSkills, partiallyUpdateMemberSkills } diff --git a/src/routes.js b/src/routes.js index cfe99ec..732532e 100644 --- a/src/routes.js +++ b/src/routes.js @@ -131,6 +131,12 @@ module.exports = { allowNoToken: true, scopes: [MEMBERS.READ, MEMBERS.ALL] }, + post: { + controller: 'StatisticsController', + method: 'createMemberSkills', + auth: 'jwt', + scopes: [MEMBERS.CREATE, MEMBERS.ALL] + }, patch: { controller: 'StatisticsController', method: 'partiallyUpdateMemberSkills', diff --git a/src/services/MemberService.js b/src/services/MemberService.js index eb8d814..bbf3a59 100644 --- a/src/services/MemberService.js +++ b/src/services/MemberService.js @@ -202,25 +202,21 @@ updateMember.schema = { data: Joi.object().keys({ firstName: Joi.string(), lastName: Joi.string(), - description: Joi.string(), + description: Joi.string().allow(''), otherLangName: Joi.string(), status: Joi.string(), email: Joi.string().email(), addresses: Joi.array().items(Joi.object().keys({ - streetAddr1: Joi.string(), - streetAddr2: Joi.string(), - city: Joi.string(), - zip: Joi.string(), - stateCode: Joi.string(), - type: Joi.string(), - createdAt: Joi.date(), - updatedAt: Joi.date(), - createdBy: Joi.string(), - updatedBy: Joi.string() + streetAddr1: Joi.string().allow(''), + streetAddr2: Joi.string().allow(''), + city: Joi.string().allow(''), + zip: Joi.string().allow(''), + stateCode: Joi.string().allow(''), + type: Joi.string() })), homeCountryCode: Joi.string(), competitionCountryCode: Joi.string(), - photoURL: Joi.string().uri(), + photoURL: Joi.string().uri().allow('').allow(null), tracks: Joi.array().items(Joi.string()) }).required() } diff --git a/src/services/StatisticsService.js b/src/services/StatisticsService.js index adc701d..a48ce0d 100644 --- a/src/services/StatisticsService.js +++ b/src/services/StatisticsService.js @@ -244,6 +244,63 @@ getMemberSkills.schema = { throwError: Joi.boolean() } +async function createMemberSkills (currentUser, handle, data) { + // get member by handle + const member = await helper.getMemberByHandle(handle) + // check authorization + if (!helper.canManageMember(currentUser, member)) { + throw new errors.ForbiddenError('You are not allowed to update the member skills.') + } + // fetch tags data + if (!this.allTags) { + this.allTags = await helper.getAllTags(config.TAGS.TAGS_BASE_URL + config.TAGS.TAGS_API_VERSION + config.TAGS.TAGS_FILTER) + } + let memberEnteredSkill = { + userId: member.userId, + createdAt: new Date().getTime(), + createdBy: currentUser.handle || currentUser.sub, + handleLower: handle, + userHandle: handle, + skills: {} + } + + // merge skills + memberEnteredSkill = helper.mergeSkills(memberEnteredSkill, {}, this.allTags) + // cleanup data + var tempSkill = {} + _.forIn(data, (value, key) => { + var tag = helper.findTagById(this.allTags, Number(key)) + if (tag) { + value.tagName = tag.name + if (!value.hasOwnProperty('hidden')) { + value.hidden = false + } + if (!value.hasOwnProperty('score')) { + value.score = 1 + } + value.sources = [ 'USER_ENTERED' ] + tempSkill[key] = value + } + }) + _.assignIn(memberEnteredSkill.skills, tempSkill) + await helper.create('MemberEnteredSkills', memberEnteredSkill) + + // get skills by member handle + const memberSkill = await this.getMemberSkills(currentUser, handle, {}, true) + return memberSkill +} + +createMemberSkills.schema = { + currentUser: Joi.any(), + handle: Joi.string().required(), + data: Joi.object().min(1).pattern(/.*/, Joi.object().keys({ + tagName: Joi.string(), + hidden: Joi.boolean(), + score: Joi.number().min(0), + sources: Joi.array().items(Joi.string()) + }).required()).required() +} + /** * Partially update member skills. * @param {Object} currentUser the user who performs operation @@ -264,6 +321,7 @@ async function partiallyUpdateMemberSkills (currentUser, handle, data) { } // get member entered skill by member user id let memberEnteredSkill = await helper.getEntityByHashKey(handle, 'MemberEnteredSkills', 'userId', member.userId, true) + // cleanup - convert string to object memberEnteredSkill = helper.convertToObjectSkills(memberEnteredSkill) // cleanup @@ -311,6 +369,7 @@ module.exports = { getHistoryStats, getMemberStats, getMemberSkills, + createMemberSkills, partiallyUpdateMemberSkills }