farmcontrol-ws/src/utils.js

90 lines
2.5 KiB
JavaScript

import { editObject } from './database/database.js';
import { hostModel } from './database/schemas/management/host.schema.js';
import crypto from 'crypto';
import { nanoid } from 'nanoid';
import canonicalize from 'canonical-json';
import { models } from './database/schemas/models.js';
import { loadConfig } from './config.js';
const config = loadConfig();
const authCodeLength = 64;
const modelList = Object.values(models)
.map(model => model.model)
.filter(model => model != null);
export async function generateHostOTP(id) {
const otp = crypto.randomInt(0, 1000000).toString().padStart(6, '0'); // 0 to 999999
const expiresAt = new Date(
Date.now() + (config.otpExpiryMins || 2) * 60 * 1000
); // 2 minutes in ms
const otpHost = await editObject({
model: hostModel,
id: id,
updateData: { otp: otp, otpExpiresAt: expiresAt }
});
return otpHost;
}
export function generateAuthCode() {
return nanoid(authCodeLength);
}
export function generateEtcId() {
return nanoid(24);
}
export function getChangedValues(oldObj, newObj, old = false) {
const changes = {};
// Check all keys in the new object
for (const key in newObj) {
// Skip if the key is _id or timestamps
if (key === '_id' || key === 'createdAt' || key === 'updatedAt') continue;
const oldVal = oldObj ? oldObj[key] : undefined;
const newVal = newObj[key];
// If both values are objects (but not arrays or null), recurse
if (
oldVal &&
newVal &&
typeof oldVal === 'object' &&
typeof newVal === 'object' &&
!Array.isArray(oldVal) &&
!Array.isArray(newVal) &&
oldVal !== null &&
newVal !== null
) {
const nestedChanges = this.getChangedValues(oldVal, newVal, old);
if (Object.keys(nestedChanges).length > 0) {
changes[key] = nestedChanges;
}
} else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
// If the old value is different from the new value, include it
changes[key] = old ? oldVal : newVal;
}
}
return changes;
}
export function getModelByName(modelName) {
return modelList.filter(model => model.modelName == modelName)[0];
}
export function getQueryToCacheKey({ model, id, populate }) {
const populateKey = [];
for (const pop of populate) {
if (typeof pop === 'string') {
populateKey.push(pop);
} else if (typeof pop === 'object') {
populateKey.push(pop.path);
}
}
return `${model}:${id?.toString()}-${populateKey.join(',')}`;
}