-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ensuring that each preference is unique for each GROUP #4060
Conversation
📝 Walkthrough📝 WalkthroughWalkthroughThe changes in this pull request introduce significant enhancements to the Changes
Possibly related PRs
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## staging #4060 +/- ##
========================================
Coverage 11.81% 11.81%
========================================
Files 115 115
Lines 15482 15482
Branches 319 319
========================================
Hits 1829 1829
Misses 13653 13653 |
Auth-service changes in this PR available for preview here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (2)
src/auth-service/utils/create-preference.js (2)
Line range hint
439-459
: Remove Unreachable Code After Return Statement in 'delete' MethodIn the
delete
method (lines 439~ to 459~), there's areturn
statement at the beginning of thetry
block. This means all the code that follows within thetry
block is unreachable and will never be executed.Consider removing the unreachable code or restructuring the method if the subsequent code is intended to be executed.
async (request, next) => { try { return { success: false, message: "Service Temporarily Unavailable", errors: { message: "Service Temporarily Unavailable", }, status: httpStatus.SERVICE_UNAVAILABLE, }; - const { - query: { tenant }, - body, - } = request; - const filterResponse = generateFilter.preferences(request, next); - // ... additional code that is unreachable } catch (error) { // Error handling remains unchanged } }
Line range hint
253-286
: Avoid Mutating Request Body DirectlyIn the
upsert
method,update
is assigned frombody
using a shallow copy (const update = { ...body };
). Subsequent mutations toupdate
may inadvertently affectrequest.body
if there are nested objects.To prevent unintended side effects, consider performing a deep clone of
body
or use a utility function to create an entirely new object.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/auth-service/models/Preference.js
(1 hunks)src/auth-service/utils/create-preference.js
(3 hunks)src/auth-service/utils/generate-filter.js
(1 hunks)
🔇 Additional comments (1)
src/auth-service/utils/generate-filter.js (1)
315-330
: Inclusion of 'group_id' in Preferences Filter Is Appropriate
The addition of group_id
to the preferences
filter allows the system to retrieve preferences specific to a user-group combination, which aligns with the PR objectives.
if (isEmpty(filterResponse) || isEmpty(filterResponse.user_id)) { | ||
return { | ||
success: false, | ||
message: "Internal Server Error", | ||
errors: { | ||
message: | ||
"Unable to obtain the corresponding identifier associated with this preference --- please reach out to [email protected]", | ||
}, | ||
status: httpStatus.INTERNAL_SERVER_ERROR, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Ensure Consistent Error Handling Using 'next()'
In the create
and upsert
methods, the error handling is inconsistent. Some errors are passed to the next middleware using next()
, while others are returned directly as objects. For example, in lines 77~ to 86~ and 193~ to 201~, errors are returned instead of using next()
.
To maintain a uniform error-handling mechanism and ensure that all errors are processed by the middleware chain, it's advisable to consistently use next()
to pass errors.
Apply the following changes:
// In the 'create' method
-if (isEmpty(filterResponse) || isEmpty(filterResponse.user_id)) {
- return {
- success: false,
- message: "Internal Server Error",
- errors: {
- message:
- "Unable to obtain the corresponding identifier associated with this preference --- please reach out to [email protected]",
- },
- status: httpStatus.INTERNAL_SERVER_ERROR,
- };
+if (isEmpty(filterResponse) || isEmpty(filterResponse.user_id)) {
+ next(
+ new HttpError(
+ "Internal Server Error",
+ httpStatus.INTERNAL_SERVER_ERROR,
+ {
+ message:
+ "Unable to obtain the corresponding identifier associated with this preference --- please reach out to [email protected]",
+ }
+ )
+ );
+ return;
}
// In the 'upsert' method
-if (isEmpty(user_id) || isEmpty(user)) {
- return {
- success: false,
- message: "Internal Server Error",
- errors: {
- message: "The provided User does not exist",
- },
- status: httpStatus.INTERNAL_SERVER_ERROR,
- };
+if (isEmpty(user_id) || isEmpty(user)) {
+ next(
+ new HttpError(
+ "Internal Server Error",
+ httpStatus.INTERNAL_SERVER_ERROR,
+ { message: "The provided User does not exist" }
+ )
+ );
+ return;
}
Also applies to: 189-201
const userBelongsToGroup = user.group_roles.some( | ||
(role) => role.group.toString() === group_id | ||
); | ||
|
||
if (!userBelongsToGroup) { | ||
return next( | ||
new HttpError("Bad Request Error", httpStatus.BAD_REQUEST, { | ||
message: "User does not belong to the specified group", | ||
}) | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle Potential 'user' Undefined Scenario When Checking Group Membership
In both the create
and upsert
methods, when checking if the user belongs to a specified group, the code assumes that user
is defined and has a property group_roles
. If user
is undefined (e.g., if the user does not exist), accessing user.group_roles
will result in a runtime error.
To ensure robustness, add a check to confirm that user
exists before accessing its properties.
// Before accessing user.group_roles
if (!isEmpty(group_id)) {
+ if (user && user.group_roles) {
const userBelongsToGroup = user.group_roles.some(
(role) => role.group.toString() === group_id
);
if (!userBelongsToGroup) {
return next(
new HttpError("Bad Request Error", httpStatus.BAD_REQUEST, {
message: "User does not belong to the specified group",
})
);
}
+ } else {
+ return next(
+ new HttpError("Bad Request Error", httpStatus.BAD_REQUEST, {
+ message: "User not found or invalid user data",
+ })
+ );
}
}
Also applies to: 205-219
const group_id = body.group_id; | ||
|
||
if (!isEmpty(user_id)) { | ||
const user = await UserModel(tenant).findById(user_id).lean(); | ||
if (isEmpty(user_id) || isEmpty(user)) { | ||
next( | ||
new HttpError("Bad Request Error", httpStatus.BAD_REQUEST, { | ||
message: "The provided User does not exist", | ||
value: user_id, | ||
}) | ||
); | ||
} | ||
} | ||
|
||
// Check if user belongs to the specified group | ||
if (!isEmpty(group_id)) { | ||
const userBelongsToGroup = user.group_roles.some( | ||
(role) => role.group.toString() === group_id | ||
); | ||
|
||
if (!userBelongsToGroup) { | ||
return next( | ||
new HttpError("Bad Request Error", httpStatus.BAD_REQUEST, { | ||
message: "User does not belong to the specified group", | ||
}) | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Refactor to Eliminate Duplicate Validation Logic
The validation logic for user_id
and group_id
in the create
and upsert
methods is almost identical. Duplicated code can make maintenance more challenging and increase the risk of inconsistencies.
Extract the common validation steps into a separate helper function that both methods can call. This will improve code readability and maintainability.
Also applies to: 186-219
]; | ||
stringFields.forEach((field) => { | ||
if (processedSite[field]) { | ||
processedSite[field] = String(processedSite[field]).trim(); | ||
} | ||
}); | ||
|
||
// Ensure boolean fields | ||
processedSite.isFeatured = !!site.isFeatured; | ||
|
||
return processedSite; | ||
}, | ||
selected_grids: (grid) => ({ | ||
_id: processObjectId(grid._id), | ||
name: String(grid.name).trim(), | ||
createdAt: grid.createdAt || new Date(), | ||
}), | ||
selected_cohorts: (cohort) => ({ | ||
_id: processObjectId(cohort._id), | ||
name: String(cohort.name).trim(), | ||
createdAt: cohort.createdAt || new Date(), | ||
}), | ||
selected_devices: (device) => ({ | ||
_id: processObjectId(device._id), | ||
name: String(device.name).trim(), | ||
createdAt: device.createdAt || new Date(), | ||
}), | ||
selected_airqlouds: (airqloud) => ({ | ||
_id: processObjectId(airqloud._id), | ||
name: String(airqloud.name).trim(), | ||
createdAt: airqloud.createdAt || new Date(), | ||
}), | ||
}; | ||
|
||
// Process selected arrays | ||
Object.keys(selectedArrayProcessors).forEach((field) => { | ||
if (updateData[field]) { | ||
updateData[field] = updateData[field].map( | ||
selectedArrayProcessors[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) => { | ||
if (updateData[field]) { | ||
updateData.$addToSet = updateData.$addToSet || {}; | ||
updateData.$addToSet[field] = { | ||
$each: updateData[field], | ||
}; | ||
delete updateData[field]; | ||
} | ||
}); | ||
|
||
// Optional: Add comprehensive logging | ||
console.log( | ||
`Preprocessing preference document: ${isNew ? "New" : "Update"}`, | ||
{ | ||
user_id: updateData.user_id, | ||
pollutant: updateData.pollutant, | ||
startDate: updateData.startDate, | ||
endDate: updateData.endDate, | ||
} | ||
); | ||
} | ||
}); | ||
|
||
const fieldsToAddToSet = [ | ||
"airqloud_ids", | ||
"device_ids", | ||
"cohort_ids", | ||
"grid_ids", | ||
"site_ids", | ||
"network_ids", | ||
"group_ids", | ||
]; | ||
|
||
fieldsToAddToSet.forEach((field) => { | ||
if (this[field]) { | ||
this[field] = Array.from(new Set(this[field].map((id) => id.toString()))); | ||
} | ||
}); | ||
|
||
return next(); | ||
}); | ||
next(); | ||
} catch (error) { | ||
console.error("Error in Preference pre-hook:", error); | ||
return next(error); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate Document and Query Middleware in Pre-Hook
The pre-hook (lines 218~ to 436~) is attempting to handle both document middleware (like save
) and query middleware (like updateOne
) within the same function. In Mongoose, this
refers to the document in document middleware and the query in query middleware. Using this.isNew
and modifying updateData
directly may not behave as intended in query middleware.
It's advisable to separate the pre-hooks for document and query operations to handle their contexts appropriately. This ensures that validations and transformations are correctly applied in each scenario.
PreferenceSchema.index({ user_id: 1, group_id: 1 }, { unique: true }); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjust Unique Index to Handle Optional 'group_id'
An index is added to enforce uniqueness on { user_id: 1, group_id: 1 }
. If group_id
can be null or optional, multiple documents with the same user_id
and a null group_id
will violate this uniqueness constraint because MongoDB considers all null values as equal in unique indexes.
Consider making group_id
required if uniqueness is essential, or modify the index to be a partial index that excludes documents where group_id
is null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (2)
src/auth-service/models/Preference.js (2)
420-427
: Replace console.log with loggerThe code uses
console.log
for debugging, which is inconsistent with the logger usage elsewhere in the file.- console.log( + logger.debug( `Preprocessing preference document: ${isNew ? "New" : "Update"}`, { user_id: updateData.user_id, pollutant: updateData.pollutant, startDate: updateData.startDate, endDate: updateData.endDate, } );
227-436
: Consider using transactions for atomic updatesThe pre-hook performs multiple updates without transaction support. If any operation fails, it could leave the database in an inconsistent state.
Consider wrapping the operations in a transaction:
PreferenceSchema.pre(["save"], async function(next) { const session = await mongoose.startSession(); session.startTransaction(); try { // Existing pre-hook logic here await session.commitTransaction(); next(); } catch (error) { await session.abortTransaction(); next(error); } finally { session.endSession(); } });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/auth-service/models/Preference.js
(1 hunks)
🔇 Additional comments (2)
src/auth-service/models/Preference.js (2)
215-216
: Consider partial index for handling optional group_id
The unique compound index on { user_id: 1, group_id: 1 }
might cause issues if group_id
is optional, as MongoDB treats all null values as equal in unique indexes.
Consider using a partial index to exclude documents where group_id
is null:
-PreferenceSchema.index({ user_id: 1, group_id: 1 }, { unique: true });
+PreferenceSchema.index(
+ { user_id: 1, group_id: 1 },
+ {
+ unique: true,
+ partialFilterExpression: { group_id: { $exists: true, $ne: null } }
+ }
+);
217-226
:
Separate document and query middleware
The pre-hook combines both document middleware (save
, create
) and query middleware (update
, findByIdAndUpdate
, etc.) operations. This can lead to context-related issues as this
refers to different objects in each type of middleware.
Consider separating the middleware:
-PreferenceSchema.pre(
- [
- "save",
- "create",
- "update",
- "findByIdAndUpdate",
- "updateMany",
- "updateOne",
- "findOneAndUpdate",
- ],
- async function (next) {
+// Document middleware
+PreferenceSchema.pre(["save", "create"], async function(next) {
+ // Handle document operations where `this` is the document
+});
+
+// Query middleware
+PreferenceSchema.pre(
+ [
+ "update",
+ "findByIdAndUpdate",
+ "updateMany",
+ "updateOne",
+ "findOneAndUpdate"
+ ],
+ async function(next) {
+ // Handle query operations where `this` is the query
+});
const processObjectId = (id) => { | ||
return id instanceof mongoose.Types.ObjectId | ||
? id | ||
: mongoose.Types.ObjectId(id); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance ObjectId validation
The processObjectId
function could be more robust by adding type checking and error handling.
const processObjectId = (id) => {
+ if (!id) return null;
+ if (id instanceof mongoose.Types.ObjectId) return id;
+ try {
+ return mongoose.Types.ObjectId(id);
+ } catch (error) {
+ logger.error(`Invalid ObjectId: ${id}`);
+ throw new Error(`Invalid ObjectId: ${id}`);
+ }
- return id instanceof mongoose.Types.ObjectId
- ? id
- : mongoose.Types.ObjectId(id);
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const processObjectId = (id) => { | |
return id instanceof mongoose.Types.ObjectId | |
? id | |
: mongoose.Types.ObjectId(id); | |
}; | |
const processObjectId = (id) => { | |
if (!id) return null; | |
if (id instanceof mongoose.Types.ObjectId) return id; | |
try { | |
return mongoose.Types.ObjectId(id); | |
} catch (error) { | |
logger.error(`Invalid ObjectId: ${id}`); | |
throw new Error(`Invalid ObjectId: ${id}`); | |
} | |
}; |
Auth-service changes in this PR available for preview here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
src/auth-service/utils/create-preference.js (3)
17-52
: Simplify user and group validation logic.The nested conditionals in
validateUserAndGroup
can be simplified using optional chaining and early returns for better readability.Consider this refactoring:
const validateUserAndGroup = async (tenant, userId, groupId, next) => { - if (!isEmpty(userId)) { - const user = await UserModel(tenant).findById(userId).lean(); - if (isEmpty(userId) || isEmpty(user)) { - return handleError( - next, - "Bad Request Error", - httpStatus.BAD_REQUEST, - "The provided User does not exist" - ); - } + if (isEmpty(userId)) { + return; + } + const user = await UserModel(tenant).findById(userId).lean(); + if (isEmpty(user)) { + return handleError( + next, + "Bad Request Error", + httpStatus.BAD_REQUEST, + "The provided User does not exist" + ); + } - if (!isEmpty(groupId)) { - if (user && user.group_roles) { - const userBelongsToGroup = user.group_roles.some( - (role) => role.group.toString() === groupId - ); - if (!userBelongsToGroup) { - return handleError( - next, - "Bad Request Error", - httpStatus.BAD_REQUEST, - "User does not belong to the specified group" - ); - } - } else { - return handleError( - next, - "Bad Request Error", - httpStatus.BAD_REQUEST, - "User not found or invalid user data" - ); - } + if (!isEmpty(groupId)) { + if (!user?.group_roles) { + return handleError( + next, + "Bad Request Error", + httpStatus.BAD_REQUEST, + "User not found or invalid user data" + ); } + const userBelongsToGroup = user.group_roles.some( + (role) => role.group.toString() === groupId + ); + if (!userBelongsToGroup) { + return handleError( + next, + "Bad Request Error", + httpStatus.BAD_REQUEST, + "User does not belong to the specified group" + ); + } } };🧰 Tools
🪛 Biome (1.9.4)
[error] 30-30: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
54-77
: Consider immutability in prepareUpdate function.The function mutates the input object directly, which could lead to unexpected side effects.
Consider this more immutable approach:
const prepareUpdate = (body, fieldsToUpdate, fieldsToAddToSet) => { - const update = { ...body }; + const update = {}; + const addToSet = {}; fieldsToAddToSet.forEach((field) => { if (update[field]) { - update["$addToSet"] = { [field]: { $each: update[field] } }; - delete update[field]; + addToSet[field] = { $each: body[field] }; } }); fieldsToUpdate.forEach((field) => { - if (update[field]) { - update[field] = update[field].map((item) => ({ + if (body[field]) { + const mappedField = body[field].map((item) => ({ ...item, createdAt: item.createdAt || new Date(), })); - update["$addToSet"] = { [field]: { $each: update[field] } }; - delete update[field]; + addToSet[field] = { $each: mappedField }; } }); - return update; + return { + ...body, + $addToSet: addToSet + }; };
Line range hint
365-371
: Critical: Remove or comment out the early return statement.The early return statement makes all subsequent code unreachable, effectively disabling the delete functionality. This appears to be unintentional as there's implementation code after it.
Either:
- Remove the early return if the service should be available:
- return { - success: false, - message: "Service Temporarily Unavailable", - errors: { - message: "Service Temporarily Unavailable", - }, - status: httpStatus.SERVICE_UNAVAILABLE, - };
- Or comment out the implementation if the service should be temporarily disabled:
return { success: false, message: "Service Temporarily Unavailable", errors: { message: "Service Temporarily Unavailable", }, status: httpStatus.SERVICE_UNAVAILABLE, }; - const { - query: { tenant }, - body, - } = request; - // ... rest of the implementation🧰 Tools
🪛 Biome (1.9.4)
[error] 30-30: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/auth-service/utils/create-preference.js
(5 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/auth-service/utils/create-preference.js
[error] 30-30: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (3)
src/auth-service/utils/create-preference.js (3)
13-15
: LGTM! Good abstraction of error handling.
The handleError
utility function effectively standardizes error handling across the codebase, promoting consistency and reducing code duplication.
113-141
: LGTM! Robust validation for unique preferences.
The changes effectively implement the PR objective by:
- Validating user and group membership
- Checking for existing preferences to prevent duplicates
- Using consistent error handling
Line range hint 229-287
: LGTM! Consistent implementation with create method.
The upsert method effectively mirrors the validation logic from the create method while adding proper update preparation logic.
Auth-service changes in this PR available for preview here |
… and error handling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
src/auth-service/models/Preference.js (3)
233-276
: Enhance ObjectId processing with batch validationThe current implementation processes ObjectIds individually. Consider batching the validation for better performance.
-idFieldsToProcess.forEach((field) => { - if (updateData[field]) { - if (Array.isArray(updateData[field])) { - updateData[field] = updateData[field].map(processObjectId); - } else { - updateData[field] = processObjectId(updateData[field]); - } - } -}); +const batchProcessObjectIds = (fields, data) => { + return Object.entries(data) + .filter(([field]) => fields.includes(field)) + .reduce((acc, [field, value]) => ({ + ...acc, + [field]: Array.isArray(value) + ? value.map(processObjectId) + : processObjectId(value) + }), {}); +}; + +Object.assign(updateData, batchProcessObjectIds(idFieldsToProcess, updateData));
404-422
: Optimize array deduplication strategyThe current implementation using
$addToSet
for all array fields might not be the most efficient approach, especially for large arrays.Consider these optimizations:
- Use bulk operations for better performance
- Implement client-side deduplication for smaller arrays
- Consider using MongoDB's aggregation pipeline for complex transformations
435-440
: Enhance error handling and loggingThe error handling in the pre-hook could be more informative and structured.
- } catch (error) { - console.error("Error in Preference pre-hook:", error); - return next(error); + } catch (error) { + const enhancedError = new Error(`Preference pre-hook error: ${error.message}`); + enhancedError.code = error.code; + enhancedError.originalError = error; + logger.error("Preference pre-hook error", { + error: error.message, + stack: error.stack, + context: { + isNew, + user_id: updateData.user_id, + operation: this.op + } + }); + return next(enhancedError); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/auth-service/models/Preference.js
(1 hunks)
🔇 Additional comments (2)
src/auth-service/models/Preference.js (2)
215-216
: Consider handling null group_id values in the unique index
The unique compound index on { user_id: 1, group_id: 1 }
effectively ensures unique preferences per group. However, be cautious with null group_id
values as MongoDB treats all null values as equal in unique indexes.
#!/bin/bash
# Check if there are any existing preferences with null group_id
ast-grep --pattern 'group_id: { type: ObjectId, required: false }'
217-232
:
Separate document and query middleware contexts
The pre-hook attempts to handle both document middleware (like save
) and query middleware (like updateOne
) within the same function. This can lead to inconsistent behavior as this
refers to different contexts.
Consider splitting into separate hooks:
-PreferenceSchema.pre(
- [
- "save",
- "create",
- "update",
- "findByIdAndUpdate",
- "updateMany",
- "updateOne",
- "findOneAndUpdate",
- ],
+// Document middleware
+PreferenceSchema.pre(["save", "create"], async function(next) {
+ // Handle document operations
+});
+
+// Query middleware
+PreferenceSchema.pre(
+ ["update", "findByIdAndUpdate", "updateMany", "updateOne", "findOneAndUpdate"],
+ async function(next) {
+ // Handle query operations
+});
Likely invalid or redundant comment.
Auth-service changes in this PR available for preview here |
Description
ensuring that each preference is unique for each GROUP
Changes Made
Testing
Affected Services
Endpoints Ready for Testing
API Documentation Updated?
Additional Notes
ensuring that each preference is unique for each GROUP
Summary by CodeRabbit
New Features
group_id
filtering capability in preference queries.Bug Fixes