tuain-ecosystem-lib
Version:
Servicio de gestión mensajería instantanea de la plataforma Tuain
308 lines (293 loc) • 13.1 kB
JavaScript
const { ObjectId } = require('mongodb');
const { v4: uuidv4 } = require('uuid');
const forge = require('node-forge');
const {
dbQueries: { groups: groupQueries },
collections: { genericGroups: groupsColl, genericGroupMembers: groupMembersColl, stores: storesColl },
} = require('../../config');
const modErrs = {
createGroup: {
alreadyExist: ['01', 'Ya existe grupo con parámetros similares'],
},
getGroup: {
missingData: ['01', 'Información insuficiente para localizar grupo'],
missingOwner: ['02', 'Propietario y tipo necesario para localizar grupo'],
notFound: ['03', 'No se encontro grupo con los ids especificados'],
},
getGroups: {
missingIds: ['01', 'Se requiere listado de identificadores para localizar grupos'],
notFound: ['02', 'No se encontraron grupos con los ids especificados'],
},
getMemberGroups: {
missingData: ['01', 'Datos insuficientes para localizar los grupos de un miembro'],
},
};
class GroupManager {
constructor(getDb, logger, errMgr, options) {
this.options = options;
this.getDb = getDb;
this.logger = logger;
this.errMgr = errMgr;
this.errMgr.addModuleSet('lib-groups', modErrs);
}
async createGroup(groupData) {
const { ownerType, memberType, groupType, name, ownerId } = groupData;
const groupCol = this.getDb().collection(groupsColl);
const groupDetail = await groupCol.findOne(groupQueries.findGroup(null, ownerType, memberType, groupType, name, ownerId));
if (groupDetail) {
const errorDetail = `Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} ya existe para el propietario ${ownerId}`;
const errorObj = this.errMgr.get(modErrs.createGroup.alreadyExist, errorDetail);
return [errorObj, null];
}
const newGroupData = groupQueries.newGroup(ownerType, memberType, groupType, name, ownerId);
const actionResult = await groupCol.insertOne(newGroupData);
const groupId = actionResult?.insertedId;
this.logger.debug(`Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} creado con id ${groupId}`);
return [null, { groupId }];
}
async getGroup(reqData) {
const { groupId, ownerType, memberType, groupType, name, ownerId } = reqData;
if (!groupId && !(ownerType && memberType && groupType && name && ownerId)) {
const errorObj = this.errMgr.get(modErrs.getGroup.missingData);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groupDetail = await groupCol.findOne(groupQueries.findGroup(groupId, ownerType, memberType, groupType, name, ownerId));
if (!groupDetail) {
const errorDetail = groupId
? `Grupo ${groupId} no fue encontrado`
: `Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} perteneciente a ${ownerId} no encontrato`;
const errorObj = this.errMgr.get(modErrs.findGroup.notFound, errorDetail);
return [errorObj, null];
}
return [null, groupDetail];
}
async getGroupsByOwner(groupData) {
const { ownerId, ownerType, memberType, groupType, name } = groupData;
if (!ownerId || !ownerType) {
const errorObj = this.errMgr.get(modErrs.getGroup.missingOwner);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groups = await groupCol.find(groupQueries.findGroupByParams(ownerId, ownerType, memberType, groupType, name)).toArray();
if (!groups || groups.length < 1) {
const errorDetail = `No se encontraron grupos con dueño ${ownerId}`;
const errorObj = this.errMgr.get(modErrs.findGroup.notFound, errorDetail);
return [errorObj, null];
}
return [null, { groups }];
}
async getGroupsByIds(groupIdsData) {
const { groupIds } = groupIdsData;
if (!groupIds || !Array.isArray(groupIds) || groupIds.length < 1) {
const errorObj = this.errMgr.get(modErrs.getGroups.missingIds);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groups = await groupCol.find(groupQueries.findGroupByIds(groupIds)).toArray();
if (!groups || groups.length < 1) {
const errorObj = this.errMgr.get(modErrs.getGroups.notFound);
return [errorObj, null];
}
return [null, { groups }];
}
async obtainGroupMember(reqData) {
const { groupId, ownerType, memberType, groupType, name, ownerId, memberId } = reqData;
if (!groupId && !(ownerType && memberType && groupType && name && ownerId)) {
const errorObj = this.errMgr.get(modErrs.getGroup.missingData);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groupDetail = await groupCol.findOne(groupQueries.findGroup(groupId, ownerType, memberType, groupType, name, ownerId));
if (!groupDetail) {
const errorDetail = groupId
? `Grupo ${groupId} no fue encontrado`
: `Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} perteneciente a ${ownerId} no encontrato`;
const errorObj = this.errMgr.get(modErrs.findGroup.notFound, errorDetail);
return [errorObj, null];
}
const {
_id: foundGroupId,
ownerType: foundOwnerType,
memberType: foundMemberType,
groupType: foundGroupType,
name: foundName,
ownerId: foundOwnerId,
} = groupDetail ?? {};
const membersCol = this.getDb().collection(groupMembersColl);
const membership = await membersCol.findOne(groupQueries.findGroupMember(foundGroupId, memberId));
return [
null,
{
_id: foundGroupId,
ownerType: foundOwnerType,
memberType: foundMemberType,
groupType: foundGroupType,
name: foundName,
ownerId: foundOwnerId,
membership,
},
];
}
async addGroupMember(reqData) {
const { groupId, ownerType, memberType, groupType, name, ownerId, memberId } = reqData;
const [memberErrorObj, groupMember] = await this.obtainGroupMember({
groupId,
ownerType,
memberType,
groupType,
name,
ownerId,
memberId,
});
if (memberErrorObj) {
return [memberErrorObj, null];
}
const {
_id: foundGroupId,
ownerType: foundOwnerType,
memberType: foundMemberType,
groupType: foundGroupType,
name: foundName,
ownerId: foundOwnerId,
membership,
} = groupMember ?? {};
if (membership) {
const errorDetail = `Grupo ${foundName} de tipo ${foundGroupType} entre ${foundOwnerType} y ${foundMemberType} para el propietario ${foundOwnerId} ya contiene a ${memberId}`;
const errorObj = this.errMgr.get(modErrs.createGroup.alreadyExist, errorDetail);
return [errorObj, null];
}
const newMembershipData = groupQueries.newMembership(foundGroupId, memberId);
const membersCol = this.getDb().collection(groupMembersColl);
const actionResult = await membersCol.insertOne(newMembershipData);
const membershipId = actionResult?.insertedId;
this.logger.debug(`Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} creado con id ${foundGroupId}`);
return [null, { membershipId }];
}
async addGroupMembers(reqData) {
const { groupId, ownerType, memberType, groupType, name, ownerId, memberIds } = reqData;
if (!groupId && !(ownerType && memberType && groupType && name && ownerId)) {
const errorObj = this.errMgr.get(modErrs.getGroup.missingData);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groupDetail = await groupCol.findOne(groupQueries.findGroup(groupId, ownerType, memberType, groupType, name, ownerId));
if (!groupDetail) {
const errorDetail = groupId
? `Grupo ${groupId} no fue encontrado`
: `Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} perteneciente a ${ownerId} no encontrato`;
const errorObj = this.errMgr.get(modErrs.findGroup.notFound, errorDetail);
return [errorObj, null];
}
const {
_id: foundGroupId,
ownerType: foundOwnerType,
memberType: foundMemberType,
groupType: foundGroupType,
name: foundName,
ownerId: foundOwnerId,
} = groupDetail ?? {};
const membersCol = this.getDb().collection(groupMembersColl);
const memberships = await membersCol.find(groupQueries.checkGroupMembers(foundGroupId, memberIds)).toArray();
if (memberships?.length > 0) {
const foundMemberList = memberships.map((membership) => `${membership.memberId}`).join(', ');
const errorDetail = `Grupo ${foundName} de tipo ${foundGroupType} entre ${foundOwnerType} y ${foundMemberType} para el propietario ${foundOwnerId} ya contiene algunos miembros: ${foundMemberList}`;
const errorObj = this.errMgr.get(modErrs.createGroup.alreadyExist, errorDetail);
return [errorObj, null];
}
const membershipArray = groupQueries.newMemberships(foundGroupId, memberIds);
const actionResult = await membersCol.insertMany(membershipArray);
console.log('addGroupMembers');
console.log(actionResult);
return [null, { membersAdded: memberIds.length }];
}
async removeAllMemberships(reqData) {
const { memberId } = reqData;
if (memberId) {
const membersCol = this.getDb().collection(groupMembersColl);
const actionResult = await membersCol.deleteMany({ memberId: ObjectId(memberId) });
const result = actionResult?.result?.n > 0;
return [null, { result }];
}
return [null, null];
}
async removeMemberFromGroup(reqData) {
const { groupId, ownerType, memberType, groupType, name, ownerId, memberId } = reqData;
const [memberErrorObj, groupMember] = await this.obtainGroupMember({
groupId,
ownerType,
memberType,
groupType,
name,
ownerId,
memberId,
});
if (memberErrorObj) {
return [memberErrorObj, null];
}
const {
// _id: foundGroupId,
ownerType: foundOwnerType,
memberType: foundMemberType,
groupType: foundGroupType,
name: foundName,
ownerId: foundOwnerId,
membership,
} = groupMember ?? {};
if (!membership) {
const errorDetail = `Grupo ${foundName} de tipo ${foundGroupType} entre ${foundOwnerType} y ${foundMemberType} para el propietario ${foundOwnerId} NO contiene a ${memberId}`;
const errorObj = this.errMgr.get(modErrs.createGroup.alreadyExist, errorDetail);
return [errorObj, null];
}
const membershipId = membership?._id;
let result = false;
if (membershipId) {
const membersCol = this.getDb().collection(groupMembersColl);
const actionResult = await membersCol.deleteOne(groupQueries.findById(membershipId));
result = actionResult?.result?.n > 0;
}
return [null, { result }];
}
async getGroupMembers(reqData) {
const { groupId, ownerType, memberType, groupType, name, ownerId } = reqData;
if (!groupId && !(ownerType && memberType && groupType && name && ownerId)) {
const errorObj = this.errMgr.get(modErrs.getGroup.missingData);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groupDetail = await groupCol.findOne(groupQueries.findGroup(groupId, ownerType, memberType, groupType, name, ownerId));
if (!groupDetail) {
const errorDetail = groupId
? `Grupo ${groupId} no fue encontrado`
: `Grupo ${name} de tipo ${groupType} entre ${ownerType} y ${memberType} perteneciente a ${ownerId} no encontrato`;
const errorObj = this.errMgr.get(modErrs.getGroup.notFound, errorDetail);
return [errorObj, null];
}
const foundGroupId = groupDetail?._id;
const membersCol = this.getDb().collection(groupMembersColl);
const memberships = await membersCol.find(groupQueries.findGroupMembers(foundGroupId)).toArray();
const members = memberships.map((membership) => membership.memberId);
return [null, { group: groupDetail, members }];
}
async getGroupsByMember(reqData) {
const { memberId, memberType, ownerType, groupType } = reqData;
if (!memberId || !memberType) {
const errorObj = this.errMgr.get(modErrs.getMemberGroups.missingData);
return [errorObj, null];
}
const membersCol = this.getDb().collection(groupMembersColl);
const memberships = await membersCol
.find(groupQueries.findMemberGroups(memberId), { projection: { groupId: 1, _id: 0 } })
.toArray();
const groupIds = memberships?.map((membership) => membership.groupId) ?? [];
if (!memberships || memberships.length < 1) {
const errorDetail = `No se encontraron grupos con miembro ${memberId} de tipo ${memberType}`;
const errorObj = this.errMgr.get(modErrs.findGroup.notFound, errorDetail);
return [errorObj, null];
}
const groupCol = this.getDb().collection(groupsColl);
const groups = await groupCol.find(groupQueries.findGroupsByIdsAndData(groupIds, memberType, ownerType, groupType)).toArray();
return [null, { groups }];
}
}
module.exports = GroupManager;