Skip to content

Commit

Permalink
feat(migrate-legalhold-database-to-support-qualified-ids)
Browse files Browse the repository at this point in the history
* Update LegalHold version to v1.1.0
* Update Dropwizard version to 2.1.12
* Adjust EventsDAO and AccessDAO queries to use ID and Domain
* Adjust DAO query usages on ConversationResource and EventsResource
* Change HoldWireClient to receive QualifiedID instead of UUID
* From MessageHandler persist correct values of Conversation and User with qualified Ids
  • Loading branch information
alexandreferris committed Oct 14, 2024
1 parent c908614 commit 95156e4
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 100 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.wire.bots</groupId>
<artifactId>hold</artifactId>
<version>1.0.7</version>
<version>1.1.0</version>

<name>Legal Hold</name>
<description>Legal Hold Service For Wire</description>
Expand All @@ -26,7 +26,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<dropwizard.version>2.1.2</dropwizard.version>
<dropwizard.version>2.1.12</dropwizard.version>
<openhtml.version>1.0.10</openhtml.version>
<prometheus.version>0.16.0</prometheus.version>
</properties>
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/wire/bots/hold/DAO/EventsDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,22 @@
import java.util.UUID;

public interface EventsDAO {
@SqlUpdate("INSERT INTO Events (eventId, conversationId, userId, type, payload, time) " +
"VALUES (:eventId, :conversationId, :userId, :type, to_jsonb(:payload)::json, CURRENT_TIMESTAMP) " +
@SqlUpdate("INSERT INTO Events (eventId, conversationId, conversationDomain, userId, userDomain, type, payload, time) " +
"VALUES (:eventId, :conversationId, :conversationDomain, :userId, :userDomain, :type, to_jsonb(:payload)::json, CURRENT_TIMESTAMP) " +
"ON CONFLICT (eventId) DO NOTHING")
int insert(@Bind("eventId") UUID eventId,
@Bind("conversationId") UUID conversationId,
@Bind("conversationDomain") String conversationDomain,
@Bind("userId") UUID userId,
@Bind("userDomain") String userDomain,
@Bind("type") String type,
@Bind("payload") String payload);

@SqlQuery("SELECT * FROM Events WHERE eventId = :eventId")
@RegisterColumnMapper(EventsResultSetMapper.class)
Event get(@Bind("eventId") UUID eventId);

@SqlQuery("SELECT * FROM Events WHERE conversationId = :conversationId AND (conversationDomain is NULL OR conversationDomain = :conversationDomain) ORDER BY time DESC")
@SqlQuery("SELECT * FROM Events WHERE conversationId = :conversationId AND (conversationDomain IS NULL OR conversationDomain = :conversationDomain) ORDER BY time DESC")
@RegisterColumnMapper(EventsResultSetMapper.class)
List<Event> listAllDefaultDomain(@Bind("conversationId") UUID conversationId,
@Bind("conversationDomain") String conversationDomain);
Expand All @@ -37,7 +39,7 @@ List<Event> listAllDefaultDomain(@Bind("conversationId") UUID conversationId,
List<Event> listAll(@Bind("conversationId") UUID conversationId,
@Bind("conversationDomain") String conversationDomain);

@SqlQuery("SELECT * FROM Events WHERE conversationId = :conversationId AND (conversationDomain is NULL OR conversationDomain = :conversationDomain) ORDER BY time ASC")
@SqlQuery("SELECT * FROM Events WHERE conversationId = :conversationId AND (conversationDomain IS NULL OR conversationDomain = :conversationDomain) ORDER BY time ASC")
@RegisterColumnMapper(EventsResultSetMapper.class)
List<Event> listAllDefaultDomainAsc(@Bind("conversationId") UUID conversationId,
@Bind("conversationDomain") String conversationDomain);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public Event map(ResultSet rs, int columnNumber, StatementContext ctx) throws SQ
Event event = new Event();
event.eventId = (UUID) rs.getObject("eventId");
event.conversationId = getUuid(rs, "conversationId");
event.conversationDomain = rs.getString("conversationDomain");
event.userId = getUuid(rs, "userId");
event.userDomain = rs.getString("userDomain");
event.time = rs.getString("time");
event.type = rs.getString("type");
event.payload = getPayload(rs);
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/wire/bots/hold/HoldMessageResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.wire.xenon.MessageResourceBase;
import com.wire.xenon.WireClient;
import com.wire.xenon.backend.models.Payload;
import com.wire.xenon.backend.models.QualifiedId;
import com.wire.xenon.exceptions.MissingStateException;
import com.wire.xenon.tools.Logger;

Expand All @@ -19,12 +20,11 @@ public HoldMessageResource(MessageHandlerBase handler, HoldClientRepo repo) {
this.repo = repo;
}

protected WireClient getWireClient(UUID userId, Payload payload) throws CryptoException {
protected WireClient getWireClient(QualifiedId userId, Payload payload) throws CryptoException {
return repo.getClient(userId, payload.data.recipient, payload.conversation);
}

public boolean onNewMessage(UUID userId, UUID id, Payload payload) {

public boolean onNewMessage(QualifiedId userId, UUID id, Payload payload) {
try (WireClient client = getWireClient(userId, payload)) {
handleMessage(id, payload, client);
} catch (CryptoException | MissingStateException e) {
Expand Down
68 changes: 29 additions & 39 deletions src/main/java/com/wire/bots/hold/MessageHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.wire.xenon.WireClient;
import com.wire.xenon.backend.models.QualifiedId;
import com.wire.xenon.backend.models.SystemMessage;
import com.wire.xenon.backend.models.User;
import com.wire.xenon.models.*;
import com.wire.xenon.tools.Logger;
import org.jdbi.v3.core.Jdbi;
Expand All @@ -28,80 +29,72 @@ public class MessageHandler extends MessageHandlerBase {
public void onNewConversation(WireClient client, SystemMessage msg) {
UUID eventId = msg.id;
QualifiedId conversationId = msg.conversation.id;
UUID userId = client.getId();
String type = msg.type;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onConversationRename(WireClient client, SystemMessage msg) {
UUID eventId = msg.id;
QualifiedId conversationId = msg.conversation.id;
UUID userId = client.getId();
String type = Const.CONVERSATION_RENAME;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onMemberJoin(WireClient client, SystemMessage msg) {
UUID eventId = msg.id;
QualifiedId conversationId = msg.conversation.id;
UUID userId = client.getId();
String type = msg.type;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onMemberLeave(WireClient client, SystemMessage msg) {
UUID eventId = msg.id;
QualifiedId conversationId = msg.conversation.id;
UUID userId = client.getId();
String type = msg.type;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onText(WireClient client, TextMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_NEW_TEXT;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onText(WireClient client, EphemeralTextMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_NEW_TEXT;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onEditText(WireClient client, EditedTextMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_EDIT_TEXT;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onPhotoPreview(WireClient client, PhotoPreviewMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_IMAGE_PREVIEW;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);

assetsDAO.insert(msg.getMessageId(), msg.getMimeType());
}
Expand All @@ -110,10 +103,9 @@ public void onPhotoPreview(WireClient client, PhotoPreviewMessage msg) {
public void onFilePreview(WireClient client, FilePreviewMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_FILE_PREVIEW;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);

assetsDAO.insert(msg.getMessageId(), msg.getMimeType());
}
Expand All @@ -122,10 +114,9 @@ public void onFilePreview(WireClient client, FilePreviewMessage msg) {
public void onAudioPreview(WireClient client, AudioPreviewMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_AUDIO_PREVIEW;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);

assetsDAO.insert(msg.getMessageId(), msg.getMimeType());
}
Expand All @@ -134,10 +125,9 @@ public void onAudioPreview(WireClient client, AudioPreviewMessage msg) {
public void onVideoPreview(WireClient client, VideoPreviewMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_VIDEO_PREVIEW;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);

assetsDAO.insert(msg.getMessageId(), msg.getMimeType());
}
Expand All @@ -146,15 +136,14 @@ public void onVideoPreview(WireClient client, VideoPreviewMessage msg) {
public void onAssetData(WireClient client, RemoteMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_ASSET_DATA;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);

try {
final byte[] assetData = client.downloadAsset(
msg.getAssetId(),
null, // TODO(WPB-11287): Change null to default domain
msg.getUserId().domain,
msg.getAssetToken(),
msg.getSha256(),
msg.getOtrKey()
Expand All @@ -169,29 +158,26 @@ public void onAssetData(WireClient client, RemoteMessage msg) {
public void onDelete(WireClient client, DeletedTextMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_DELETE_TEXT;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
public void onCalling(WireClient client, CallingMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_CALL;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

public void onReaction(WireClient client, ReactionMessage msg) {
UUID eventId = msg.getEventId();
QualifiedId conversationId = msg.getConversationId();
UUID userId = client.getId();
String type = Const.CONVERSATION_OTR_MESSAGE_ADD_REACTION;

persist(eventId, conversationId.id, userId, type, msg);
persist(eventId, conversationId, client, type, msg);
}

@Override
Expand All @@ -204,16 +190,20 @@ public void validatePreKeys(WireClient client, int size) {

}

private void persist(UUID eventId, UUID convId, UUID userId, String type, Object msg) {
private void persist(UUID eventId, QualifiedId conversationId, WireClient client, String type, Object msg) {
try {
User user = client.getSelf();
String payload = mapper.writeValueAsString(msg);
eventsDAO.insert(eventId, convId, userId, type, payload);
} catch (Exception e) {
Logger.exception(e, "%s: conv: %s, user: %s, id: %s, e: %s",
type,
convId,
userId,
eventId);

eventsDAO.insert(eventId, conversationId.id, conversationId.domain, user.id.id, user.id.domain, type, payload);
} catch (Exception exception) {
Logger.exception(
exception,
"%s: conversation: %s, event: %s, e: %s",
type,
conversationId,
eventId
);
}
}
}
31 changes: 13 additions & 18 deletions src/main/java/com/wire/bots/hold/NotificationProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.wire.helium.models.Event;
import com.wire.helium.models.NotificationList;
import com.wire.xenon.backend.models.Payload;
import com.wire.xenon.backend.models.QualifiedId;
import com.wire.xenon.exceptions.AuthException;
import com.wire.xenon.exceptions.HttpException;
import com.wire.xenon.tools.Logger;
Expand Down Expand Up @@ -53,12 +54,8 @@ private Access getAccess(Cookie cookie) throws HttpException {
}

private void process(LHAccess device) {
UUID userId = device.userId;

try {
final API api = new API(client, null, device.token);

Logger.debug("`GET /notifications`: user: %s, last: %s", userId, device.last);
Logger.debug("`GET /notifications`: user: %s, last: %s", device.userId, device.last);

String cookieValue = device.cookie;

Expand All @@ -67,32 +64,33 @@ private void process(LHAccess device) {
Access access = getAccess(cookie);

if (access.getCookie() != null) {
Logger.info("Set-Cookie: user: %s", userId);
Logger.info("Set-Cookie: user: %s", device.userId);
cookieValue = access.getCookie().value;
}

accessDAO.update(userId, access.getAccessToken(), cookieValue);
accessDAO.update(device.userId.id, device.userId.domain, access.getAccessToken(), cookieValue);

device.token = access.getAccessToken();

final API api = new API(client, null, device.token);
NotificationList notificationList = api.retrieveNotifications(
device.clientId,
device.last,
DEFAULT_NOTIFICATION_SIZE
);

process(userId, notificationList);
process(device.userId, notificationList);
} catch (AuthException e) {
accessDAO.disable(userId);
Logger.info("Disabled LH device for user: %s, error: %s", userId, e.getMessage());
accessDAO.disable(device.userId.id, device.userId.domain);
Logger.exception(e, "NotificationProcessor: Disabled LH device for user: %s, error: %s", device.userId, e.getMessage());
} catch (HttpException e) {
Logger.exception(e, "NotificationProcessor: Couldn't retrieve notifications, error: %s", e.getMessage());
} catch (Exception e) {
Logger.exception(e, "NotificationProcessor: user: %s, last: %s, error: %s", userId, device.last, e.getMessage());
Logger.exception(e, "NotificationProcessor: user: %s, last: %s, error: %s", device.userId, device.last, e.getMessage());
}
}

private void process(UUID userId, NotificationList notificationList) {
private void process(QualifiedId userId, NotificationList notificationList) {
for (Event event : notificationList.notifications) {
for (Payload payload : event.payload) {
if (!process(userId, payload, event.id)) {
Expand All @@ -106,17 +104,14 @@ private void process(UUID userId, NotificationList notificationList) {
}
}

accessDAO.updateLast(userId, event.id);
accessDAO.updateLast(userId.id, userId.domain, event.id);
}
}

private boolean process(UUID userId, Payload payload, UUID id) {
private boolean process(QualifiedId userId, Payload payload, UUID id) {
trace(payload);

Logger.debug("Payload: %s %s, from: %s",
payload.type,
userId,
payload.from);
Logger.debug("Payload: %s %s, from: %s", payload.type, userId, payload.from);

if (payload.from == null || payload.data == null) return true;

Expand Down
Loading

0 comments on commit 95156e4

Please sign in to comment.