-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(api): notifications feed filtering by partial payload object #3939
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { Injectable, BadRequestException } from '@nestjs/common'; | ||
import { ActorTypeEnum, ChannelTypeEnum } from '@novu/shared'; | ||
import { | ||
AnalyticsService, | ||
|
@@ -21,6 +21,18 @@ export class GetNotificationsFeed { | |
private subscriberRepository: SubscriberRepository | ||
) {} | ||
|
||
private getPayloadObject(payload?: string): object | undefined { | ||
if (!payload) { | ||
return; | ||
} | ||
|
||
try { | ||
return JSON.parse(Buffer.from(payload, 'base64').toString()); | ||
} catch (e) { | ||
throw new BadRequestException('Invalid payload, the JSON object should be encoded to base64 string.'); | ||
} | ||
} | ||
Comment on lines
+24
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. convert the base64 string payload to the JS object |
||
|
||
@CachedQuery({ | ||
builder: ({ environmentId, subscriberId, ...command }: GetNotificationsFeedCommand) => | ||
buildFeedKey().cache({ | ||
|
@@ -30,6 +42,8 @@ export class GetNotificationsFeed { | |
}), | ||
}) | ||
async execute(command: GetNotificationsFeedCommand): Promise<MessagesResponseDto> { | ||
const payload = this.getPayloadObject(command.payload); | ||
|
||
const subscriber = await this.fetchSubscriber({ | ||
_environmentId: command.environmentId, | ||
subscriberId: command.subscriberId, | ||
|
@@ -47,7 +61,7 @@ export class GetNotificationsFeed { | |
command.environmentId, | ||
subscriber._id, | ||
ChannelTypeEnum.IN_APP, | ||
{ feedId: command.feedId, seen: command.query.seen, read: command.query.read }, | ||
{ feedId: command.feedId, seen: command.query.seen, read: command.query.read, payload }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pass the payload to the repository |
||
{ | ||
limit: command.limit, | ||
skip: command.page * command.limit, | ||
|
@@ -80,6 +94,7 @@ export class GetNotificationsFeed { | |
feedId: command.feedId, | ||
seen: command.query.seen, | ||
read: command.query.read, | ||
payload, | ||
}, | ||
{ limit: command.limit + 1, skip } | ||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,15 @@ import { EnforceEnvId } from '../../types/enforce'; | |
|
||
type MessageQuery = FilterQuery<MessageDBModel>; | ||
|
||
const getEntries = (obj: object, prefix = '') => | ||
Object.entries(obj).flatMap(([key, value]) => | ||
Object(value) === value ? getEntries(value, `${prefix}${key}.`) : [[`${prefix}${key}`, value]] | ||
); | ||
|
||
const getFlatObject = (obj: object) => { | ||
return Object.fromEntries(getEntries(obj)); | ||
}; | ||
|
||
export class MessageRepository extends BaseRepository<MessageDBModel, MessageEntity, EnforceEnvId> { | ||
private message: SoftDeleteModel; | ||
private feedRepository = new FeedRepository(); | ||
|
@@ -23,9 +32,9 @@ export class MessageRepository extends BaseRepository<MessageDBModel, MessageEnt | |
environmentId: string, | ||
subscriberId: string, | ||
channel: ChannelTypeEnum, | ||
query: { feedId?: string[]; seen?: boolean; read?: boolean } = {} | ||
query: { feedId?: string[]; seen?: boolean; read?: boolean; payload?: object } = {} | ||
): Promise<MessageQuery & EnforceEnvId> { | ||
const requestQuery: MessageQuery & EnforceEnvId = { | ||
let requestQuery: MessageQuery & EnforceEnvId = { | ||
_environmentId: environmentId, | ||
_subscriberId: subscriberId, | ||
channel, | ||
|
@@ -62,14 +71,21 @@ export class MessageRepository extends BaseRepository<MessageDBModel, MessageEnt | |
requestQuery.read = { $in: [true, false] }; | ||
} | ||
|
||
if (query.payload) { | ||
requestQuery = { | ||
...requestQuery, | ||
...getFlatObject({ payload: query.payload }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if the |
||
}; | ||
} | ||
Comment on lines
+74
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the payload object is passed, then prepare the flat object out of it, like if the payload is
Which is passed then to the find query. |
||
|
||
return requestQuery; | ||
} | ||
|
||
async findBySubscriberChannel( | ||
environmentId: string, | ||
subscriberId: string, | ||
channel: ChannelTypeEnum, | ||
query: { feedId?: string[]; seen?: boolean; read?: boolean } = {}, | ||
query: { feedId?: string[]; seen?: boolean; read?: boolean; payload?: object } = {}, | ||
options: { limit: number; skip?: number } = { limit: 10 } | ||
) { | ||
const requestQuery = await this.getFilterQueryForMessage(environmentId, subscriberId, channel, query); | ||
|
@@ -90,13 +106,14 @@ export class MessageRepository extends BaseRepository<MessageDBModel, MessageEnt | |
environmentId: string, | ||
subscriberId: string, | ||
channel: ChannelTypeEnum, | ||
query: { feedId?: string[]; seen?: boolean; read?: boolean } = {}, | ||
query: { feedId?: string[]; seen?: boolean; read?: boolean; payload?: object } = {}, | ||
options: { limit: number; skip?: number } = { limit: 100, skip: 0 } | ||
) { | ||
const requestQuery = await this.getFilterQueryForMessage(environmentId, subscriberId, channel, { | ||
feedId: query.feedId, | ||
seen: query.seen, | ||
read: query.read, | ||
payload: query.payload, | ||
}); | ||
|
||
return this.MongooseModel.countDocuments(requestQuery, options).read('secondaryPreferred'); | ||
|
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.
The two feed endpoints now do take the payload query param which is the base64 encoded string of the partial payload JSON object. Check the description for more info.