in source/packages/services/assetlibrary/src/devices/devices.full.service.ts [724:827]
public async attachToGroup(
deviceId: string,
relationship: string,
direction: RelationDirection,
groupPath: string
): Promise<void> {
logger.debug(
`device.full.service attachToGroup: in: deviceId:${deviceId}, relationship:${relationship}, direction:${direction}, groupPath:${groupPath}`
);
ow(deviceId, 'deviceId', ow.string.nonEmpty);
ow(relationship, 'relationship', ow.string.nonEmpty);
ow(direction, 'direction', ow.string.oneOf(['in', 'out']));
ow(groupPath, 'groupPath', ow.string.nonEmpty);
// any ids need to be lowercase
deviceId = deviceId.toLowerCase();
relationship = relationship.toLowerCase();
groupPath = groupPath.toLowerCase();
await this.authServiceFull.authorizationCheck([deviceId], [groupPath], ClaimAccess.U);
// fetch the existing device / group
const deviceFuture = this.get(deviceId, false, [], true);
const groupFuture = this.groupsService.get(groupPath, false);
const [device, group] = await Promise.all([deviceFuture, groupFuture]);
// make sure they exist
if (device === undefined) {
throw new DeviceNotFoundError(deviceId);
}
if (group === undefined) {
throw new GroupNotFoundError(groupPath);
}
// if the relation already exists, there's no need to continue
if (device.groups?.[direction]?.[relationship]?.find((e) => e.id === groupPath)) {
logger.debug(`device.full.service attachToGroup: relation already exits:`);
return;
}
// ensure that the group relation is allowed
const relatedGroup: DirectionToRelatedEntityArrayMap = {
[direction]: {
[relationship]: [
{
id: groupPath,
},
],
},
};
const template = await this.typesService.get(
device.templateId,
TypeCategory.Device,
TypeDefinitionStatus.published
);
const validateRelationships = await this.validator.validateRelationshipsByIds(
template,
relatedGroup,
undefined
);
if (!validateRelationships.isValid) {
throw new RelationValidationError(validateRelationships);
}
// if fgac is enabled, we need to ensure any relations configured as identifying auth in its template are flagged to be saved as so
let isAuthCheck = true;
if (this.isAuthzEnabled) {
const authRelations =
direction === 'in'
? template.schema.relations.incomingAuthRelations()
: template.schema.relations.outgoingAuthRelations();
this.authServiceFull.updateRelsIdentifyingAuth(
relatedGroup[direction],
validateRelationships.groupLabels,
authRelations
);
isAuthCheck = relatedGroup[direction][relationship][0].isAuthCheck ?? false;
}
// Save to datastore
await this.devicesDao.attachToGroup(
deviceId,
relationship,
direction,
groupPath,
isAuthCheck
);
// fire event
await this.eventEmitter.fire({
objectId: deviceId,
type: Type.device,
event: Event.modify,
attributes: {
deviceId,
attachedToGroup: groupPath,
relationship,
},
});
logger.debug(`device.full.service attachToGroup: exit:`);
}