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

Commit 9318c0f

Browse files
1 parent 057d492 commit 9318c0f

File tree

11 files changed

+132
-26
lines changed

11 files changed

+132
-26
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ The following parameters can be set in config files or in env variables:
4747
- ES.USER_ATTRIBUTE_PROPERTY_NAME: the user property name of attribute, default value is 'attributes',
4848
- ES.USER_ROLE_PROPERTY_NAME: the user property name of role, default value is 'roles',
4949
- ES.USER_SKILL_PROPERTY_NAME: the user property name of skill, default value is 'skills'
50+
- ES.ORGANIZATION_SKILLPROVIDER_PROPERTY_NAME: the org property name of org skill providers, default value is 'skillProviders'
5051

5152
There is a `/health` endpoint that checks for the health of the app. This sets up an expressjs server and listens on the environment variable `PORT`. It's not part of the configuration file and needs to be passed as an environment variable
5253

config/default.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ module.exports = {
4343
USER_EXTERNALPROFILE_PROPERTY_NAME: process.env.USER_EXTERNALPROFILE_PROPERTY_NAME || 'externalProfiles',
4444
USER_ATTRIBUTE_PROPERTY_NAME: process.env.USER_ATTRIBUTE_PROPERTY_NAME || 'attributes',
4545
USER_ROLE_PROPERTY_NAME: process.env.USER_ROLE_PROPERTY_NAME || 'roles',
46-
USER_SKILL_PROPERTY_NAME: process.env.USER_SKILL_PROPERTY_NAME || 'skills'
46+
USER_SKILL_PROPERTY_NAME: process.env.USER_SKILL_PROPERTY_NAME || 'skills',
47+
48+
ORGANIZATION_SKILLPROVIDER_PROPERTY_NAME: process.env.ORGANIZATION_SKILLPROVIDER_PROPERTY_NAME || 'skillProviders'
4749
}
4850
}

config/test.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44

55
module.exports = {
66
WAIT_TIME: 1500,
7-
ES: {
8-
ACHIEVEMENT_PROVIDER_INDEX: process.env.ACHIEVEMENT_PROVIDER_INDEX || 'achievement_provider_test',
9-
ATTRIBUTE_INDEX: process.env.ATTRIBUTE_INDEX || 'attribute_test',
10-
ATTRIBUTE_GROUP_INDEX: process.env.ATTRIBUTE_GROUP_INDEX || 'attribute_group_test',
11-
ORGANIZATION_INDEX: process.env.ORGANIZATION_INDEX || 'organization_test',
12-
ROLE_INDEX: process.env.ROLE_INDEX || 'role_test',
13-
SKILL_INDEX: process.env.SKILL_INDEX || 'skill_test',
14-
SKILL_PROVIDER_INDEX: process.env.SKILL_PROVIDER_INDEX || 'skill_provider_test',
15-
USER_INDEX: process.env.USER_INDEX || 'user_test'
16-
}
7+
// ES: {
8+
// ACHIEVEMENT_PROVIDER_INDEX: process.env.ACHIEVEMENT_PROVIDER_INDEX || 'achievement_provider_test',
9+
// ATTRIBUTE_INDEX: process.env.ATTRIBUTE_INDEX || 'attribute_test',
10+
// ATTRIBUTE_GROUP_INDEX: process.env.ATTRIBUTE_GROUP_INDEX || 'attribute_group_test',
11+
// ORGANIZATION_INDEX: process.env.ORGANIZATION_INDEX || 'organization_test',
12+
// ROLE_INDEX: process.env.ROLE_INDEX || 'role_test',
13+
// SKILL_INDEX: process.env.SKILL_INDEX || 'skill_test',
14+
// SKILL_PROVIDER_INDEX: process.env.SKILL_PROVIDER_INDEX || 'skill_provider_test',
15+
// USER_INDEX: process.env.USER_INDEX || 'user_test'
16+
// }
1717
}

docker-kafka-es/docker-compose.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ services:
1414
KAFKA_ADVERTISED_HOST_NAME: localhost
1515
KAFKA_CREATE_TOPICS: "u-bahn.action.create:1:1,u-bahn.action.update:1:1,u-bahn.action.delete:1:1"
1616
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
17-
esearch:
18-
image: docker.elastic.co/elasticsearch/elasticsearch:6.8.0
19-
container_name: ubahn-data-processor-es_es
20-
ports:
21-
- "9200:9200"
17+
# esearch:
18+
# image: docker.elastic.co/elasticsearch/elasticsearch:7.4.2
19+
# container_name: ubahn-data-processor-es_es
20+
# ports:
21+
# - "9200:9200"

src/common/constants.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ const userResources = {
7070
}
7171
}
7272

73+
const organizationResources = {
74+
organizationskillprovider: {
75+
propertyName: config.get('ES.ORGANIZATION_SKILLPROVIDER_PROPERTY_NAME'),
76+
relateKey: 'skillProviderId',
77+
validate: payload => validProperties(payload, ['organizationId', 'skillProviderId'])
78+
}
79+
}
80+
7381
module.exports = {
74-
topResources, userResources
82+
topResources, userResources, organizationResources
7583
}

src/common/helper.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,32 @@ async function updateUser (userId, body) {
9494
})
9595
}
9696

97+
/**
98+
* Function to get org from es
99+
* @param {String} organizationId
100+
* @returns {Object} organization
101+
*/
102+
async function getOrg (organizationId) {
103+
const client = await getESClient()
104+
return client.getSource({ index: config.get('ES.ORGANIZATION_INDEX'), type: config.get('ES.ORGANIZATION_TYPE'), id: organizationId })
105+
}
106+
107+
/**
108+
* Function to update es organization
109+
* @param {String} organizationId
110+
* @param {Object} body
111+
*/
112+
async function updateOrg (organizationId, body) {
113+
const client = await getESClient()
114+
await client.update({
115+
index: config.get('ES.ORGANIZATION_INDEX'),
116+
type: config.get('ES.ORGANIZATION_TYPE'),
117+
id: organizationId,
118+
body: { doc: body },
119+
refresh: 'true'
120+
})
121+
}
122+
97123
/**
98124
* Fuction to get an Error with statusCode property
99125
* @param {String} message error message
@@ -112,5 +138,7 @@ module.exports = {
112138
validProperties,
113139
getUser,
114140
updateUser,
141+
getOrg,
142+
updateOrg,
115143
getErrorWithStatus
116144
}

src/services/ProcessorService.js

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ const _ = require('lodash')
66
const Joi = require('@hapi/joi')
77
const logger = require('../common/logger')
88
const helper = require('../common/helper')
9-
const { topResources, userResources } = require('../common/constants')
9+
const {
10+
topResources,
11+
userResources,
12+
organizationResources
13+
} = require('../common/constants')
1014

1115
/**
1216
* Process create entity message
@@ -43,8 +47,26 @@ async function processCreate (message) {
4347
user[userResource.propertyName].push(_.omit(message.payload, 'resource'))
4448
await helper.updateUser(message.payload.userId, user)
4549
}
50+
} else if (_.includes(_.keys(organizationResources), resource)) {
51+
// process org resources such as org skill provider
52+
const orgResources = organizationResources[resource]
53+
orgResources.validate(message.payload)
54+
const org = await helper.getOrg(message.payload.organizationId)
55+
const relateId = message.payload[orgResources.relateKey]
56+
if (!org[orgResources.propertyName]) {
57+
org[orgResources.propertyName] = []
58+
}
59+
60+
// check the resource does not exist
61+
if (_.some(org[orgResources.propertyName], [orgResources.relateKey, relateId])) {
62+
logger.error(`Can't create existing ${resource} with the ${orgResources.relateKey}: ${relateId}, organizationId: ${message.payload.organizationId}`)
63+
throw helper.getErrorWithStatus('[version_conflict_engine_exception]', 409)
64+
} else {
65+
org[orgResources.propertyName].push(_.omit(message.payload, 'resource'))
66+
await helper.updateOrg(message.payload.organizationId, org)
67+
}
4668
} else {
47-
logger.info(`Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources))}]`)
69+
logger.info(`Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources), _.keys(organizationResources))}]`)
4870
}
4971
}
5072

@@ -90,8 +112,24 @@ async function processUpdate (message) {
90112
user[userResource.propertyName].splice(updateIndex, 1, _.omit(message.payload, 'resource'))
91113
await helper.updateUser(message.payload.userId, user)
92114
}
115+
} else if (_.includes(_.keys(organizationResources), resource)) {
116+
// process org resources such as org skill providers
117+
const orgResource = organizationResources[resource]
118+
orgResource.validate(message.payload)
119+
const org = await helper.getOrg(message.payload.organizationId)
120+
const relateId = message.payload[orgResource.relateKey]
121+
122+
// check the resource exist
123+
if (!org[orgResource.propertyName] || !_.some(org[orgResource.propertyName], [orgResource.relateKey, relateId])) {
124+
logger.error(`The ${resource} with the ${orgResource.relateKey}: ${relateId}, organizationId: ${message.payload.organizationId} not exist`)
125+
throw helper.getErrorWithStatus('[resource_not_found_exception]', 404)
126+
} else {
127+
const updateIndex = _.findIndex(org[orgResource.propertyName], [orgResource.relateKey, relateId])
128+
org[orgResource.propertyName].splice(updateIndex, 1, _.omit(message.payload, 'resource'))
129+
await helper.updateOrg(message.payload.organizationId, org)
130+
}
93131
} else {
94-
logger.info(`Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources))}]`)
132+
logger.info(`Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources), _.keys(organizationResources))}]`)
95133
}
96134
}
97135

@@ -138,8 +176,23 @@ async function processDelete (message) {
138176
_.remove(user[userResource.propertyName], [userResource.relateKey, relateId])
139177
await helper.updateUser(message.payload.userId, user)
140178
}
179+
} else if (_.includes(_.keys(organizationResources), resource)) {
180+
// process user resources such as org skill provider
181+
const orgResource = organizationResources[resource]
182+
orgResource.validate(message.payload)
183+
const org = await helper.getOrg(message.payload.organizationId)
184+
const relateId = message.payload[orgResource.relateKey]
185+
186+
// check the resource exist
187+
if (!org[orgResource.propertyName] || !_.some(org[orgResource.propertyName], [orgResource.relateKey, relateId])) {
188+
logger.error(`The ${resource} with the ${orgResource.relateKey}: ${relateId}, organizationId: ${message.payload.organizationId} not exist`)
189+
throw helper.getErrorWithStatus('[resource_not_found_exception]', 404)
190+
} else {
191+
_.remove(org[orgResource.propertyName], [orgResource.relateKey, relateId])
192+
await helper.updateOrg(message.payload.organizationId, org)
193+
}
141194
} else {
142-
logger.info(`Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources))}]`)
195+
logger.info(`Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources), _.keys(organizationResources))}]`)
143196
}
144197
}
145198

test/common/init-es.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* !OBSOLETE SCRIPT. Use the one from ubahn-api instead
3+
* !( https://github.com/topcoder-platform/u-bahn-api )
4+
*/
5+
16
/**
27
* Initialize elastic search.
38
* It will create configured index in elastic search if it is not present.

test/common/testHelper.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44
const _ = require('lodash')
55
const helper = require('../../src/common/helper')
6-
const { topResources, userResources } = require('../../src/common/constants')
6+
const { topResources, userResources, organizationResources } = require('../../src/common/constants')
77

88
var client
99
(async function () {
@@ -22,6 +22,15 @@ async function getESRecord (payload) {
2222
type: topResources[payload.resource].type,
2323
id: payload.id
2424
})
25+
} else if (organizationResources[payload.resource]) {
26+
const orgResource = organizationResources[payload.resource]
27+
const org = await helper.getOrg(payload.organizationId)
28+
if (!org || !org[orgResource.propertyName] || !_.some(org[orgResource.propertyName], [orgResource.relateKey, payload[orgResource.relateKey]])) {
29+
const err = Error('[resource_not_found_exception]')
30+
err.statusCode = 404
31+
throw err
32+
}
33+
return _.find(org[orgResource.propertyName], [orgResource.relateKey, payload[orgResource.relateKey]])
2534
} else {
2635
const userResource = userResources[payload.resource]
2736
const user = await helper.getUser(payload.userId)

test/e2e/test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ process.env.NODE_ENV = 'test'
77
const _ = require('lodash')
88
const config = require('config')
99
const helper = require('../../src/common/helper')
10-
const { topResources, userResources } = require('../../src/common/constants')
10+
const { topResources, userResources, organizationResources } = require('../../src/common/constants')
1111
const request = require('superagent')
1212
const Kafka = require('no-kafka')
1313
const should = require('should')
@@ -284,7 +284,7 @@ describe('UBahn - Elasticsearch Data Processor E2E Test', () => {
284284
await sendMessage(message)
285285
await waitJob()
286286

287-
should.equal(_.last(infoLogs), `Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources))}]`)
287+
should.equal(_.last(infoLogs), `Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources), _.keys(organizationResources))}]`)
288288
})
289289
}
290290
})

test/unit/test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ global.Promise = require('bluebird')
77
const _ = require('lodash')
88
const should = require('should')
99
const logger = require('../../src/common/logger')
10-
const { topResources, userResources } = require('../../src/common/constants')
10+
const { topResources, userResources, organizationResources } = require('../../src/common/constants')
1111
const service = require('../../src/services/ProcessorService')
1212
const { fields, testTopics } = require('../common/testData')
1313
const { getESRecord } = require('../common/testHelper')
@@ -174,7 +174,7 @@ describe('UBahn - Elasticsearch Data Processor Unit Test', () => {
174174
const message = _.cloneDeep(testTopics[op][0])
175175
message.payload.resource = 'invalid'
176176
await service[`process${op}`](message)
177-
should.equal(_.last(infoLogs), `Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources))}]`)
177+
should.equal(_.last(infoLogs), `Ignore this message since resource is not in [${_.union(_.keys(topResources), _.keys(userResources), _.keys(organizationResources))}]`)
178178
})
179179
}
180180
})

0 commit comments

Comments
 (0)