Add notification handling in editObject and utility functions
Some checks failed
farmcontrol/farmcontrol-ws/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-ws/pipeline/head There was a failure building this commit
- Introduced notification functionality in the editObject method to notify users of changes when editing objects, enhancing user awareness of updates. - Added utility functions for creating and managing notifications, including omitSensitive for filtering sensitive data and notificationUserFromOwner for user retrieval based on owner type. - Updated SocketHost to support the new notify parameter, ensuring notifications can be triggered during object edits.
This commit is contained in:
parent
6e74e0dfec
commit
c36765cc47
@ -3,6 +3,7 @@ import {
|
|||||||
deleteAuditLog,
|
deleteAuditLog,
|
||||||
expandObjectIds,
|
expandObjectIds,
|
||||||
editAuditLog,
|
editAuditLog,
|
||||||
|
editNotification,
|
||||||
distributeUpdate,
|
distributeUpdate,
|
||||||
newAuditLog,
|
newAuditLog,
|
||||||
distributeNew,
|
distributeNew,
|
||||||
@ -423,7 +424,8 @@ export const editObject = async ({
|
|||||||
owner = undefined,
|
owner = undefined,
|
||||||
ownerType = undefined,
|
ownerType = undefined,
|
||||||
populate = [],
|
populate = [],
|
||||||
auditLog = true
|
auditLog = true,
|
||||||
|
notify = true
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
// Determine parentType from model name
|
// Determine parentType from model name
|
||||||
@ -464,6 +466,24 @@ export const editObject = async ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
notify == true &&
|
||||||
|
owner != undefined &&
|
||||||
|
ownerType != undefined &&
|
||||||
|
parentType !== 'notification' &&
|
||||||
|
parentType !== 'auditLog' &&
|
||||||
|
parentType !== 'userNotifier'
|
||||||
|
) {
|
||||||
|
await editNotification(
|
||||||
|
previousExpandedObject,
|
||||||
|
newExpandedObject,
|
||||||
|
id,
|
||||||
|
parentType,
|
||||||
|
owner,
|
||||||
|
ownerType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Distribute update
|
// Distribute update
|
||||||
await distributeUpdate(updateData, id, parentType);
|
await distributeUpdate(updateData, id, parentType);
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,51 @@
|
|||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
import { auditLogModel } from './schemas/management/auditlog.schema.js';
|
import { auditLogModel } from './schemas/management/auditlog.schema.js';
|
||||||
|
import { notificationModel } from './schemas/misc/notification.schema.js';
|
||||||
|
import { userNotifierModel } from './schemas/misc/usernotifier.schema.js';
|
||||||
|
import { models } from './schemas/models.js';
|
||||||
import { natsServer } from './nats.js';
|
import { natsServer } from './nats.js';
|
||||||
|
|
||||||
import { customAlphabet } from 'nanoid';
|
import { customAlphabet } from 'nanoid';
|
||||||
|
|
||||||
|
const NOTIFICATION_EXCLUDED_MODELS = ['notification', 'userNotifier', 'auditLog'];
|
||||||
|
const SENSITIVE_KEYS = ['secret'];
|
||||||
|
|
||||||
|
function omitSensitive(obj) {
|
||||||
|
if (obj == null || typeof obj !== 'object') return obj;
|
||||||
|
if (Array.isArray(obj)) return obj.map(omitSensitive);
|
||||||
|
const result = {};
|
||||||
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
if (SENSITIVE_KEYS.includes(key)) continue;
|
||||||
|
result[key] = omitSensitive(value);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModelEntryByType(parentType) {
|
||||||
|
return Object.values(models).find(
|
||||||
|
entry => entry.type === parentType || entry.model?.modelName === parentType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function notificationUserFromOwner(owner, ownerType) {
|
||||||
|
if (!owner) return null;
|
||||||
|
if (ownerType === 'user') {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
if (ownerType === 'host') {
|
||||||
|
return {
|
||||||
|
_id: owner._id,
|
||||||
|
firstName: owner.name ?? 'unknown',
|
||||||
|
lastName: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
_id: owner._id,
|
||||||
|
firstName: owner.name ?? owner.firstName ?? 'unknown',
|
||||||
|
lastName: owner.lastName ?? ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||||
export const generateId = () => {
|
export const generateId = () => {
|
||||||
// 10 characters
|
// 10 characters
|
||||||
@ -444,6 +486,86 @@ async function distributeNew(id, type) {
|
|||||||
await natsServer.publish(`${type}s.new`, id);
|
await natsServer.publish(`${type}s.new`, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function editNotification(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
parentId,
|
||||||
|
parentType,
|
||||||
|
owner,
|
||||||
|
ownerType
|
||||||
|
) {
|
||||||
|
if (NOTIFICATION_EXCLUDED_MODELS.includes(parentType)) return;
|
||||||
|
|
||||||
|
const modelEntry = getModelEntryByType(parentType);
|
||||||
|
const user = notificationUserFromOwner(owner, ownerType);
|
||||||
|
const objectName =
|
||||||
|
oldValue?.name ?? newValue?.name ?? modelEntry?.label ?? parentType;
|
||||||
|
const changedOldValues = omitSensitive(getChangedValues(oldValue, newValue, true));
|
||||||
|
const changedNewValues = omitSensitive(getChangedValues(oldValue, newValue, false));
|
||||||
|
|
||||||
|
if (
|
||||||
|
Object.keys(changedOldValues).length === 0 ||
|
||||||
|
Object.keys(changedNewValues).length === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await notfiyObjectUserNotifiers(
|
||||||
|
parentId,
|
||||||
|
parentType,
|
||||||
|
`${objectName} edited by ${user?.firstName ?? 'unknown'} ${user?.lastName ?? ''}`,
|
||||||
|
`The ${parentType} ${parentId} has been updated.`,
|
||||||
|
'editObject',
|
||||||
|
{
|
||||||
|
old: changedOldValues,
|
||||||
|
new: changedNewValues,
|
||||||
|
objectType: parentType,
|
||||||
|
object: { _id: String(parentId ?? '') },
|
||||||
|
user: {
|
||||||
|
_id: String(user?._id ?? ''),
|
||||||
|
firstName: user?.firstName,
|
||||||
|
lastName: user?.lastName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function notfiyObjectUserNotifiers(
|
||||||
|
id,
|
||||||
|
objectType,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
type = 'info',
|
||||||
|
metadata
|
||||||
|
) {
|
||||||
|
const userNotifiers = await userNotifierModel
|
||||||
|
.find({ object: id, objectType })
|
||||||
|
.populate('user');
|
||||||
|
for (const userNotifier of userNotifiers) {
|
||||||
|
await createNotification(
|
||||||
|
userNotifier.user._id,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
type,
|
||||||
|
metadata
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createNotification(user, title, message, type = 'info', metadata) {
|
||||||
|
const notification = new notificationModel({
|
||||||
|
user,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
type,
|
||||||
|
metadata: omitSensitive(metadata ?? {})
|
||||||
|
});
|
||||||
|
await notification.save();
|
||||||
|
const value = notification.toJSON ? notification.toJSON() : notification;
|
||||||
|
await natsServer.publish(`notifications.${user._id ?? user}`, value);
|
||||||
|
return notification;
|
||||||
|
}
|
||||||
|
|
||||||
function flatternObjectIds(object) {
|
function flatternObjectIds(object) {
|
||||||
if (!object || typeof object !== 'object') {
|
if (!object || typeof object !== 'object') {
|
||||||
return object;
|
return object;
|
||||||
@ -546,6 +668,9 @@ export {
|
|||||||
distributeUpdate,
|
distributeUpdate,
|
||||||
distributeNew,
|
distributeNew,
|
||||||
distributeStats,
|
distributeStats,
|
||||||
|
editNotification,
|
||||||
|
notfiyObjectUserNotifiers,
|
||||||
|
createNotification,
|
||||||
getFilter, // <-- add here
|
getFilter, // <-- add here
|
||||||
convertPropertiesString
|
convertPropertiesString
|
||||||
};
|
};
|
||||||
|
|||||||
@ -172,7 +172,8 @@ export class SocketHost {
|
|||||||
populate: data.populate,
|
populate: data.populate,
|
||||||
owner: this.host,
|
owner: this.host,
|
||||||
ownerType: 'host',
|
ownerType: 'host',
|
||||||
auditLog: data?.auditLog
|
auditLog: data?.auditLog,
|
||||||
|
notify: data?.notify
|
||||||
});
|
});
|
||||||
callback(object);
|
callback(object);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user