Skip to content

Commit aa1042a

Browse files
author
Dushyant Bhalgami
committed
chenges to add universal member to groups
1 parent 0d0ecdd commit aa1042a

File tree

4 files changed

+142
-33
lines changed

4 files changed

+142
-33
lines changed

config/default.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ module.exports = {
3737
KAFKA_GROUP_DELETE_TOPIC: process.env.KAFKA_GROUP_DELETE_TOPIC || 'groups.notification.delete',
3838
KAFKA_GROUP_MEMBER_ADD_TOPIC: process.env.KAFKA_GROUP_MEMBER_ADD_TOPIC || 'groups.notification.member.add',
3939
KAFKA_GROUP_MEMBER_DELETE_TOPIC: process.env.KAFKA_GROUP_MEMBER_DELETE_TOPIC || 'groups.notification.member.delete',
40+
KAFKA_GROUP_UNIVERSAL_MEMBER_ADD_TOPIC: process.env.KAFKA_GROUP_UNIVERSAL_MEMBER_ADD_TOPIC || 'groups.notification.universalmember.add',
41+
KAFKA_GROUP_UNIVERSAL_MEMBER_DELETE_TOPIC: process.env.KAFKA_GROUP_UNIVERSAL_MEMBER_DELETE_TOPIC || 'groups.notification.universalmember.delete',
4042

4143
USER_ROLES: {
4244
Admin: 'Administrator',

src/common/helper.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,36 +74,36 @@ async function ensureExists(tx, model, id, isAdmin = false) {
7474
if (model === 'Group') {
7575
if (validate(id, 4)) {
7676
if (!isAdmin) {
77-
res = await tx.run(`MATCH (e:${model} {id: {id}, status: '${constants.GroupStatus.Active}'}) RETURN e`, {
78-
id
79-
})
77+
res = await tx.run(`MATCH (e:${model} {id: {id}, status: '${constants.GroupStatus.Active}'}) RETURN e`, {id})
8078
} else {
81-
res = await tx.run(`MATCH (e:${model} {id: {id}}) RETURN e`, {
82-
id
83-
})
79+
res = await tx.run(`MATCH (e:${model} {id: {id}}) RETURN e`, {id})
8480
}
8581
} else {
8682
if (!isAdmin) {
8783
res = await tx.run(`MATCH (e:${model} {oldId: {id}, status: '${constants.GroupStatus.Active}'}) RETURN e`, {
8884
id
8985
})
9086
} else {
91-
res = await tx.run(`MATCH (e:${model} {oldId: {id}}) RETURN e`, {
92-
id
93-
})
87+
res = await tx.run(`MATCH (e:${model} {oldId: {id}}) RETURN e`, {id})
9488
}
9589
}
9690

9791
if (res && res.records.length === 0) {
9892
throw new errors.NotFoundError(`Not found ${model} of id ${id}`)
9993
}
10094
} else if (model === 'User') {
101-
res = await tx.run(`MATCH (e:${model} {id: {id}}) RETURN e`, {
102-
id
103-
})
95+
if (validate(id, 4)) {
96+
res = await tx.run(`MATCH (e:${model} {universalUID: {id}}) RETURN e`, {id})
10497

105-
if (res && res.records.length === 0) {
106-
res = await tx.run(`CREATE (user:User {id: {id}}) RETURN user`, { id })
98+
if (res && res.records.length === 0) {
99+
res = await tx.run(`CREATE (user:User {id: '00000000', universalUID: {id}}) RETURN user`, {id})
100+
}
101+
} else {
102+
res = await tx.run(`MATCH (e:${model} {id: {id}}) RETURN e`, {id})
103+
104+
if (res && res.records.length === 0) {
105+
res = await tx.run(`CREATE (user:User {id: {id}, universalUID: '00000000'}) RETURN user`, {id})
106+
}
107107
}
108108
}
109109

@@ -123,7 +123,7 @@ async function ensureGroupMember(session, groupId, userId) {
123123
try {
124124
const memberCheckRes = await session.run(
125125
'MATCH (g:Group {id: {groupId}})-[r:GroupContains {type: {membershipType}}]->(u:User {id: {userId}}) RETURN r',
126-
{ groupId, membershipType: config.MEMBERSHIP_TYPES.User, userId }
126+
{groupId, membershipType: config.MEMBERSHIP_TYPES.User, userId}
127127
)
128128
if (memberCheckRes.records.length === 0) {
129129
throw new errors.ForbiddenError(`User is not member of the group`)
@@ -143,7 +143,7 @@ async function getChildGroups(session, groupId) {
143143
try {
144144
const res = await session.run(
145145
'MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(c:Group) RETURN c ORDER BY c.oldId',
146-
{ groupId }
146+
{groupId}
147147
)
148148
return _.map(res.records, (record) => record.get(0).properties)
149149
} catch (error) {
@@ -161,7 +161,7 @@ async function getParentGroups(session, groupId) {
161161
try {
162162
const res = await session.run(
163163
'MATCH (g:Group)-[r:GroupContains]->(c:Group {id: {groupId}}) RETURN g ORDER BY g.oldId',
164-
{ groupId }
164+
{groupId}
165165
)
166166
return _.map(res.records, (record) => record.get(0).properties)
167167
} catch (error) {
@@ -176,7 +176,7 @@ async function getParentGroups(session, groupId) {
176176
* @returns {String} link for the page
177177
*/
178178
function getPageLink(req, page) {
179-
const q = _.assignIn({}, req.query, { page })
179+
const q = _.assignIn({}, req.query, {page})
180180
return `${req.protocol}://${req.get('Host')}${req.baseUrl}${req.path}?${querystring.stringify(q)}`
181181
}
182182

src/controllers/GroupMembershipController.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,21 @@ async function getGroupMembers(req, res) {
2525
* @param res the response
2626
*/
2727
async function addGroupMember(req, res) {
28-
const result = await service.addGroupMember(
29-
req.authUser.isMachine ? 'M2M' : req.authUser,
30-
req.params.groupId,
31-
req.body
32-
)
33-
res.send(result)
28+
if(req.body.universalUID) {
29+
const result = await service.addUniversalMember(
30+
req.authUser.isMachine ? 'M2M' : req.authUser,
31+
req.params.groupId,
32+
req.body
33+
)
34+
res.send(result)
35+
} else {
36+
const result = await service.addGroupMember(
37+
req.authUser.isMachine ? 'M2M' : req.authUser,
38+
req.params.groupId,
39+
req.body
40+
)
41+
res.send(result)
42+
}
3443
}
3544

3645
/**

src/services/GroupMembershipService.js

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ async function addGroupMember(currentUser, groupId, data) {
6767
const targetObjectType = data.membershipType === config.MEMBERSHIP_TYPES.Group ? 'Group' : 'User'
6868
const memberCheckRes = await tx.run(
6969
`MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(o:${targetObjectType} {id: {memberId}}) RETURN o`,
70-
{ groupId, memberId: data.memberId }
70+
{groupId, memberId: data.memberId}
7171
)
7272
if (memberCheckRes.records.length > 0) {
7373
throw new errors.ConflictError('The member is already in the group')
@@ -77,7 +77,7 @@ async function addGroupMember(currentUser, groupId, data) {
7777
if (data.membershipType === config.MEMBERSHIP_TYPES.Group) {
7878
const pathRes = await tx.run(
7979
'MATCH p=shortestPath( (g1:Group {id: {fromId}})-[*]->(g2:Group {id: {toId}}) ) RETURN p',
80-
{ fromId: data.memberId, toId: groupId }
80+
{fromId: data.memberId, toId: groupId}
8181
)
8282
if (pathRes.records.length > 0) {
8383
throw new errors.ConflictError('There is cyclical group reference')
@@ -107,9 +107,9 @@ async function addGroupMember(currentUser, groupId, data) {
107107
oldId: data.oldId,
108108
name: group.name,
109109
createdAt,
110-
...(currentUser === 'M2M' ? {} : { createdBy: currentUser.userId }),
110+
...(currentUser === 'M2M' ? {} : {createdBy: currentUser.userId}),
111111
memberId: data.memberId,
112-
...(data.memberOldId ? { memberOldId: data.memberOldId } : {}),
112+
...(data.memberOldId ? {memberOldId: data.memberOldId} : {}),
113113
membershipType: data.membershipType
114114
}
115115

@@ -174,7 +174,7 @@ async function deleteGroupMember(currentUser, groupId, memberId) {
174174

175175
// delete membership
176176
const query = 'MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(o {id: {memberId}}) DELETE r'
177-
await tx.run(query, { groupId, memberId })
177+
await tx.run(query, {groupId, memberId})
178178

179179
if (validate(memberId, 4)) {
180180
const getMember = await helper.ensureExists(tx, 'Group', memberId)
@@ -210,6 +210,103 @@ deleteGroupMember.schema = {
210210
memberId: Joi.id()
211211
}
212212

213+
/**
214+
* Add universal member.
215+
* @param {Object} currentUser the current user
216+
* @param {String} groupId the id of group to add member
217+
* @param {Object} data the data to add member
218+
* @returns {Object} the added group membership
219+
*/
220+
async function addUniversalMember(currentUser, groupId, data) {
221+
logger.debug(`Enter in addGroupMember - Group = ${groupId} Criteria = ${data}`)
222+
let session = helper.createDBSession()
223+
let tx = session.beginTransaction()
224+
225+
try {
226+
logger.debug(`Check for groupId ${groupId} exist or not`)
227+
const group = await helper.ensureExists(
228+
tx,
229+
'Group',
230+
groupId,
231+
currentUser !== 'M2M' && helper.hasAdminRole(currentUser)
232+
)
233+
data.oldId = group.oldId
234+
groupId = group.id
235+
data.membershipType = config.MEMBERSHIP_TYPES.User
236+
237+
if (currentUser !== 'M2M' && !helper.hasAdminRole(currentUser)) {
238+
throw new errors.ForbiddenError('You are not allowed to perform this action!')
239+
}
240+
241+
logger.debug(`Check for memberId ${data.universalUID} exist or not`)
242+
await helper.ensureExists(tx, 'User', data.universalUID)
243+
244+
logger.debug(`check member ${data.universalUID} is part of group ${groupId}`)
245+
const memberCheckRes = await tx.run(
246+
`MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(o:User {universalUID: {universalUID}}) RETURN o`,
247+
{groupId, universalUID: data.universalUID}
248+
)
249+
if (memberCheckRes.records.length > 0) {
250+
throw new errors.ConflictError('The member is already in the group')
251+
}
252+
253+
// add membership
254+
const membershipId = uuid()
255+
const createdAt = new Date().toISOString()
256+
const query = `MATCH (g:Group {id: {groupId}}) MATCH (o:User {universalUID: {universalUID}}) CREATE (g)-[r:GroupContains {universalUID: {universalUID}, type: {membershipType}, createdAt: {createdAt}, createdBy: {createdBy}}]->(o) RETURN r`
257+
258+
const params = {
259+
groupId,
260+
universalUID: data.universalUID,
261+
membershipId,
262+
membershipType: data.membershipType,
263+
createdAt,
264+
createdBy: currentUser === 'M2M' ? '00000000' : currentUser.userId
265+
}
266+
267+
logger.debug(`quey for adding membership ${query} with params ${JSON.stringify(params)}`)
268+
await tx.run(query, params)
269+
270+
const result = {
271+
id: membershipId,
272+
groupId,
273+
oldId: data.oldId,
274+
name: group.name,
275+
createdAt,
276+
...(currentUser === 'M2M' ? {} : {createdBy: currentUser.userId}),
277+
memberId: '00000000',
278+
universalUID: data.universalUID,
279+
handle: data.handle,
280+
...(data.memberOldId ? {memberOldId: data.memberOldId} : {}),
281+
membershipType: data.membershipType
282+
}
283+
284+
logger.debug(`sending message ${JSON.stringify(result)} to kafka topic ${config.KAFKA_GROUP_MEMBER_ADD_TOPIC}`)
285+
await helper.postBusEvent(config.KAFKA_GROUP_MEMBER_ADD_TOPIC, result)
286+
287+
await tx.commit()
288+
return result
289+
} catch (error) {
290+
logger.error(error)
291+
logger.debug('Transaction Rollback')
292+
await tx.rollback()
293+
throw error
294+
} finally {
295+
logger.debug('Session Close')
296+
await session.close()
297+
}
298+
}
299+
300+
addUniversalMember.schema = {
301+
currentUser: Joi.any(),
302+
groupId: Joi.id(), // defined in app-bootstrap
303+
data: Joi.object()
304+
.keys({
305+
universalUID: Joi.id(),
306+
handle: Joi.string().required()
307+
})
308+
.required()
309+
}
213310
/**
214311
* Get group members
215312
* @param {Object} currentUser the current user
@@ -235,7 +332,7 @@ async function getGroupMembers(currentUser, groupId, criteria) {
235332
}
236333

237334
const matchClause = 'MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(o)'
238-
const params = { groupId }
335+
const params = {groupId}
239336

240337
// query total record count
241338
const totalRes = await session.run(`${matchClause} RETURN COUNT(o)`, params)
@@ -299,7 +396,7 @@ async function getGroupMemberWithSession(session, groupId, memberId) {
299396
groupId = group.id
300397

301398
const query = 'MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(o {id: {memberId}}) RETURN r'
302-
const membershipRes = await session.run(query, { groupId, memberId })
399+
const membershipRes = await session.run(query, {groupId, memberId})
303400
if (membershipRes.records.length === 0) {
304401
throw new errors.NotFoundError('The member is not in the group')
305402
}
@@ -375,9 +472,9 @@ async function getGroupMembersCount(groupId, query) {
375472
queryToExecute = 'MATCH (g:Group {id: {groupId}})-[r:GroupContains]->(o:User) RETURN COUNT(o) AS count'
376473
}
377474

378-
const res = await session.run(queryToExecute, { groupId })
475+
const res = await session.run(queryToExecute, {groupId})
379476

380-
return { count: res.records[0]._fields[0].low }
477+
return {count: res.records[0]._fields[0].low}
381478
} catch (error) {
382479
logger.error(error)
383480
throw error
@@ -426,6 +523,7 @@ getMemberGroups.schema = {
426523
module.exports = {
427524
getGroupMembers,
428525
addGroupMember,
526+
addUniversalMember,
429527
getGroupMember,
430528
deleteGroupMember,
431529
getGroupMembersCount,

0 commit comments

Comments
 (0)