Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge pull request from GHSA-2w3m-ppfg-hg62
fix(core): Improve ephemeral message handling
  • Loading branch information
comawill committed Jan 27, 2022
2 parents 980bde4 + f5a2759 commit 42c9a1e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 7 deletions.
27 changes: 24 additions & 3 deletions src/script/conversation/ConversationRepository.ts
Expand Up @@ -327,6 +327,8 @@ export class ConversationRepository {
this.deleteConversationFromRepository(conversationEntity);
}
});

this.cleanupEphemeralMessages();
}

//##############################################################################
Expand Down Expand Up @@ -2747,17 +2749,29 @@ export class ConversationRepository {
}

/**
* Convert multiple JSON events into entities and add them to a given conversation.
* Convert multiple JSON events into entities and validate them
*
* @param events Event data
* @param conversationEntity Conversation entity the events will be added to
* @param prepend Should existing messages be prepended
* @returns Resolves with an array of mapped messages
*/
private async addEventsToConversation(events: EventRecord[], conversationEntity: Conversation, prepend = true) {
private async validateMessages(events: EventRecord[], conversationEntity: Conversation) {
const mappedEvents = await this.event_mapper.mapJsonEvents(events, conversationEntity);
const updatedEvents = (await this.updateMessagesUserEntities(mappedEvents)) as ContentMessage[];
const validatedMessages = (await this.ephemeralHandler.validateMessages(updatedEvents)) as ContentMessage[];
return validatedMessages;
}

/**
* Convert multiple JSON events into entities, validate and add them to a given conversation.
*
* @param events Event data
* @param conversationEntity Conversation entity the events will be added to
* @param prepend Should existing messages be prepended
* @returns Resolves with an array of mapped messages
*/
private async addEventsToConversation(events: EventRecord[], conversationEntity: Conversation, prepend = true) {
const validatedMessages = await this.validateMessages(events, conversationEntity);
if (prepend && conversationEntity.messages().length) {
conversationEntity.prependMessages(validatedMessages);
} else {
Expand Down Expand Up @@ -2887,4 +2901,11 @@ export class ConversationRepository {

return false;
}

public async cleanupEphemeralMessages(): Promise<void> {
this.conversationState.conversations().forEach(async conversationEntity => {
const messages = (await this.eventService.loadEphemeralEvents(conversationEntity.id)) as EventRecord[];
this.validateMessages(messages, conversationEntity);
});
}
}
9 changes: 5 additions & 4 deletions src/script/conversation/ConversationService.ts
Expand Up @@ -476,12 +476,13 @@ export class ConversationService {
* @param query will be checked in against all text messages
* @returns Resolves with the matching events
*/
searchInConversation(conversation_id: string, query: string): Promise<any> {
async searchInConversation(conversation_id: string, query: string): Promise<any> {
const category_min = MessageCategory.TEXT;
const category_max = MessageCategory.TEXT | MessageCategory.LINK | MessageCategory.LINK_PREVIEW;

return this.eventService.loadEventsWithCategory(conversation_id, category_min, category_max).then(events => {
return events.filter(({data: event_data}: any) => fullTextSearch(event_data.content, query));
});
const events = await this.eventService.loadEventsWithCategory(conversation_id, category_min, category_max);
return events
.filter(record => record.ephemeral_expires !== true)
.filter(({data: event_data}: any) => fullTextSearch(event_data.content, query));
}
}
38 changes: 38 additions & 0 deletions src/script/event/EventService.ts
Expand Up @@ -87,6 +87,34 @@ export class EventService {
}
}

async loadEphemeralEvents(conversationId: string): Promise<EventRecord[]> {
if (!conversationId) {
this.logger.error(`Cannot get ephemeral events in conversation '${conversationId}' without ID`);
throw new ConversationError(BASE_ERROR_TYPE.MISSING_PARAMETER, BaseError.MESSAGE.MISSING_PARAMETER);
}

try {
if (this.storageService.db) {
const events = await this.storageService.db
.table(StorageSchemata.OBJECT_STORE.EVENTS)
.where('conversation')
.equals(conversationId)
.and(record => !!record.ephemeral_expires)
.toArray();
return events;
}

const records = (await this.storageService.getAll(StorageSchemata.OBJECT_STORE.EVENTS)) as EventRecord[];
return records
.filter(record => record.conversation === conversationId && !!record.ephemeral_expires)
.sort(compareEventsById);
} catch (error) {
const logMessage = `Failed to get ephemeral events for conversation '${conversationId}': ${error.message}`;
this.logger.error(logMessage, error);
throw error;
}
}

/**
* Load event from database.
*
Expand Down Expand Up @@ -134,11 +162,20 @@ export class EventService {
categoryMin: MessageCategory,
categoryMax = MessageCategory.LIKED,
): Promise<DBEvents> {
const filterExpired = (record: EventRecord) => {
if (typeof record.ephemeral_expires !== 'undefined') {
return +record.ephemeral_expires - Date.now() > 0;
}

return true;
};

if (this.storageService.db) {
const events = await this.storageService.db
.table(StorageSchemata.OBJECT_STORE.EVENTS)
.where('[conversation+category]')
.between([conversationId, categoryMin], [conversationId, categoryMax], true, true)
.and(filterExpired)
.sortBy('time');
return events;
}
Expand All @@ -149,6 +186,7 @@ export class EventService {
record =>
record.conversation === conversationId && record.category >= categoryMin && record.category <= categoryMax,
)
.filter(filterExpired)
.sort(compareEventsByTime);
}

Expand Down

0 comments on commit 42c9a1e

Please sign in to comment.