Skip to content

feat(api-service): inbox bulk update preferences #8292

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

Merged
merged 2 commits into from
May 13, 2025

Conversation

LetItRock
Copy link
Contributor

What changed? Why was the change needed?

Inbox bulk update preferences endpoint: PATCH /inbox/preferences/bulk.
Improved the current update single preferences endpoint to accept a workflow Mongo ID or identifier.

Screenshots

Screenshot 2025-05-12 at 15 12 12
Screenshot 2025-05-12 at 15 55 01

@LetItRock LetItRock self-assigned this May 12, 2025
Copy link

linear bot commented May 12, 2025

Copy link

netlify bot commented May 12, 2025

Deploy Preview for dashboard-v2-novu-staging canceled.

Name Link
🔨 Latest commit 990ad3a
🔍 Latest deploy log https://app.netlify.com/sites/dashboard-v2-novu-staging/deploys/682223aa24d93200089dea7b

@@ -313,10 +316,26 @@ export class InboxController {
}

@UseGuards(AuthGuard('subscriberJwt'))
@Patch('/preferences/:workflowId')
@Patch('/preferences/bulk')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the order matters, this one should be before the PATCH /preferences/:workflowIdOrIdentifier, otherwise the latter will handle the call

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's maybe add an in-code comment for this?

async updateWorkflowPreference(
@SubscriberSession() subscriberSession: SubscriberEntity,
@Param('workflowId') workflowId: string,
@Param('workflowIdOrIdentifier') workflowIdOrIdentifier: string,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

improved this one to allow using the workflow Mongo id or identifier

Comment on lines 42 to 49
const allWorkflowIds = command.preferences.map((preference) => preference.workflowIdOrInternalId);
const workflowInternalIds = allWorkflowIds.filter((id) => BaseRepository.isInternalId(id));
const workflowIdentifiers = allWorkflowIds.filter((id) => !BaseRepository.isInternalId(id));

const dbWorkflows = await this.notificationTemplateRepository.find({
_environmentId: command.environmentId,
$or: [{ _id: { $in: workflowInternalIds } }, { 'triggers.identifier': { $in: workflowIdentifiers } }],
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split the mongo ids from the identifiers, this ensures that we don't get the mongo casting error to ObjectId

Comment on lines +62 to +65
const invalidWorkflowIds = allWorkflowIds.filter((id) => !allValidWorkflowsMap.has(id));
if (invalidWorkflowIds.length > 0) {
throw new NotFoundException(`Workflows with ids: ${invalidWorkflowIds.join(', ')} not found`);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw 404 if some of the workflows are not found

Comment on lines +67 to +71
const criticalWorkflows = dbWorkflows.filter((workflow) => workflow.critical);
if (criticalWorkflows.length > 0) {
const criticalWorkflowIds = criticalWorkflows.map((workflow) => workflow._id);
throw new BadRequestException(`Critical workflows with ids: ${criticalWorkflowIds.join(', ')} cannot be updated`);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't allow updating preferences for critical workflows

Comment on lines 74 to 80
const workflowPreferencesMap = new Map<string, BulkUpdatePreferenceItemDto>();
for (const preference of command.preferences) {
const workflow = allValidWorkflowsMap.get(preference.workflowIdOrInternalId);
if (workflow) {
workflowPreferencesMap.set(workflow._id, preference);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deduplicate workflows; the user can send in the request either id or identifier, but both can be pointing to the same mongo document, so we would like to deduplicate in that case

Comment on lines +48 to +54
const workflow = await this.getWorkflowByIdsUsecase.execute(
GetWorkflowByIdsCommand.create({
environmentId: command.environmentId,
organizationId: command.organizationId,
workflowIdOrInternalId: command.workflowIdOrIdentifier,
})
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the existing usecase to find by id or identifier

Copy link
Contributor

@scopsy scopsy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

One note I have, is that I feel like the workflowIdOrInternalId is not really needed, and I would just stick to the workflowId (not the internal one) as it seems like it can reduce some of the complexity around the implementation.

I'm not too strong on this, but do we have any other place that follows this pattern?

export class BulkUpdatePreferenceItemDto extends UpdatePreferencesRequestDto {
@IsDefined()
@IsString()
readonly workflowIdOrInternalId: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have this pattern in other places? wonder if it's better to just stick to workflowId, it's hard for me to see if anyone will ever user the internal id for this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scopsy the workflow controller uses workflowId as the path param, so I'll stick to that name

@@ -313,10 +316,26 @@ export class InboxController {
}

@UseGuards(AuthGuard('subscriberJwt'))
@Patch('/preferences/:workflowId')
@Patch('/preferences/bulk')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's maybe add an in-code comment for this?

@@ -313,10 +316,26 @@ export class InboxController {
}

@UseGuards(AuthGuard('subscriberJwt'))
@Patch('/preferences/:workflowId')
@Patch('/preferences/bulk')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason for PATCH vs POST? because of the partial preference object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it's partial update and to align with the existing single update

@LetItRock LetItRock merged commit cfb3bc5 into next May 13, 2025
25 checks passed
@LetItRock LetItRock deleted the nv-5921-inbox-bulk-update-preferences branch May 13, 2025 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants