Skip to content

Commit

Permalink
Merge pull request #4069 from airqo-platform/hf-prefs-updates
Browse files Browse the repository at this point in the history
fixing runtime when upserting prefereces
  • Loading branch information
Baalmart authored Dec 13, 2024
2 parents 0b7e24d + 666c098 commit 05a9f5e
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 56 deletions.
69 changes: 40 additions & 29 deletions src/auth-service/models/Preference.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ PreferenceSchema.pre(
const processObjectId = (id) => {
if (!id) return null;
if (id instanceof mongoose.Types.ObjectId) return id;
if (typeof id === "string" && id.trim() === "") return null;
try {
return mongoose.Types.ObjectId(id);
} catch (error) {
Expand All @@ -242,37 +243,43 @@ PreferenceSchema.pre(
}
};

// Comprehensive ID fields processing
const idFieldsToProcess = [
// Define field categories
const singleIdFields = [
"user_id",
"group_id",
"airqloud_id",
"airqloud_ids",
"grid_id",
"grid_ids",
"cohort_id",
"cohort_ids",
"network_id",
];
const arrayIdFields = [
"airqloud_ids",
"grid_ids",
"cohort_ids",
"network_ids",
"group_id",
"group_ids",
"site_ids",
"device_ids",
"group_ids",
];
const selectedArrayFields = [
"selected_sites",
"selected_grids",
"selected_devices",
"selected_cohorts",
"selected_airqlouds",
];

idFieldsToProcess.forEach((field) => {
// Process single ID fields
singleIdFields.forEach((field) => {
if (updateData[field]) {
if (Array.isArray(updateData[field])) {
updateData[field] = updateData[field].map(processObjectId);
} else {
updateData[field] = processObjectId(updateData[field]);
}
updateData[field] = processObjectId(updateData[field]);
}
});

// Validate user_id
if (!updateData.user_id) {
return next(new Error("user_id is required"));
}
updateData.user_id = processObjectId(updateData.user_id);

// Set default values if not provided
const defaultFields = [
Expand Down Expand Up @@ -393,29 +400,33 @@ PreferenceSchema.pre(
};

// Process selected arrays
Object.keys(selectedArrayProcessors).forEach((field) => {
selectedArrayFields.forEach((field) => {
if (updateData[field]) {
updateData[field] = updateData[field].map(
selectedArrayProcessors[field]
);

// Use $addToSet for selected arrays
updateData.$addToSet = {
...updateData.$addToSet,
[field]: {
$each: updateData[field],
},
};
delete updateData[field];
}
});

// Prepare $addToSet for array fields to prevent duplicates
const arrayFieldsToAddToSet = [
...idFieldsToProcess,
"selected_sites",
"selected_grids",
"selected_devices",
"selected_cohorts",
"selected_airqlouds",
];

arrayFieldsToAddToSet.forEach((field) => {
// Process array ID fields
arrayIdFields.forEach((field) => {
if (updateData[field]) {
updateData.$addToSet = updateData.$addToSet || {};
updateData.$addToSet[field] = {
$each: updateData[field],
updateData.$addToSet = {
...updateData.$addToSet,
[field]: {
$each: Array.isArray(updateData[field])
? updateData[field].map(processObjectId)
: [processObjectId(updateData[field])],
},
};
delete updateData[field];
}
Expand Down
95 changes: 68 additions & 27 deletions src/auth-service/utils/create-preference.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,38 @@ const validateUserAndGroup = async (tenant, userId, groupId, next) => {
const prepareUpdate = (body, fieldsToUpdate, fieldsToAddToSet) => {
const update = { ...body };

// Handle fields that should be added to set (array fields)
fieldsToAddToSet.forEach((field) => {
if (update[field]) {
update["$addToSet"] = { [field]: { $each: update[field] } };
update["$addToSet"] = update["$addToSet"] || {};
update["$addToSet"][field] = {
$each: Array.isArray(update[field]) ? update[field] : [update[field]],
};
delete update[field];
}
});

// Handle fields that need special processing (with createdAt)
fieldsToUpdate.forEach((field) => {
if (update[field]) {
update[field] = update[field].map((item) => ({
...item,
createdAt: item.createdAt || new Date(),
}));

update["$addToSet"] = { [field]: { $each: update[field] } };
update["$addToSet"] = update["$addToSet"] || {};
update["$addToSet"][field] = { $each: update[field] };
delete update[field];
}
});

// Remove simple ObjectId fields from being processed by $addToSet
const singleObjectIdFields = ["user_id", "group_id"];
singleObjectIdFields.forEach((field) => {
if (update[field]) {
}
});

return update;
};

Expand Down Expand Up @@ -111,13 +124,7 @@ const preferences = {
logObject("the body", body);

// Validate user and group
const validationError = await validateUserAndGroup(
tenant,
body.user_id,
body.group_id,
next
);
if (validationError) return;
await validateUserAndGroup(tenant, body.user_id, body.group_id, next);

const filterResponse = generateFilter.preferences(request, next);
if (isEmpty(filterResponse) || isEmpty(filterResponse.user_id)) {
Expand Down Expand Up @@ -169,8 +176,29 @@ const preferences = {
body,
} = request;

const filterResponse = generateFilter.preferences(request, next);
if (isEmpty(filterResponse) || isEmpty(filterResponse.user_id)) {
// Validate user and group
await validateUserAndGroup(tenant, body.user_id, body.group_id, next);

const fieldsToUpdate = [
"selected_sites",
"selected_grids",
"selected_cohorts",
"selected_devices",
"selected_airqlouds",
];

const fieldsToAddToSet = [
"airqloud_ids",
"device_ids",
"cohort_ids",
"grid_ids",
"site_ids",
"network_ids",
"group_ids",
];

const filter = generateFilter.preferences(request, next);
if (isEmpty(filter) || isEmpty(filter.user_id)) {
next(
new HttpError(
"Internal Server Error",
Expand All @@ -183,21 +211,7 @@ const preferences = {
);
}

const PreferenceDetails = await PreferenceModel(tenant)
.findOne(filterResponse)
.select("_id")
.lean();

if (isEmpty(PreferenceDetails)) {
next(
new HttpError("Bad Request Errors", httpStatus.BAD_REQUEST, {
message: `No existing preferences for the provided User ID: ${filterResponse.user_id.toString()}`,
})
);
}

const filter = PreferenceDetails;
const update = body;
const update = prepareUpdate(body, fieldsToUpdate, fieldsToAddToSet);

const modifyResponse = await PreferenceModel(tenant).modify(
{
Expand Down Expand Up @@ -305,6 +319,33 @@ const preferences = {
body,
} = request;

// Validate user and group
const validationError = await validateUserAndGroup(
tenant,
body.user_id,
body.group_id,
next
);
if (validationError) return;

const fieldsToUpdate = [
"selected_sites",
"selected_grids",
"selected_cohorts",
"selected_devices",
"selected_airqlouds",
];

const fieldsToAddToSet = [
"airqloud_ids",
"device_ids",
"cohort_ids",
"grid_ids",
"site_ids",
"network_ids",
"group_ids",
];

logText("Replace the existing selected_ids....");

const filterResponse = generateFilter.preferences(request, next);
Expand All @@ -320,7 +361,7 @@ const preferences = {
};
}

const update = body;
const update = prepareUpdate(body, fieldsToUpdate, fieldsToAddToSet);
const options = { upsert: true, new: true };

const modifyResponse = await PreferenceModel(tenant).findOneAndUpdate(
Expand Down

0 comments on commit 05a9f5e

Please sign in to comment.