diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index af5f29754..160d069ce 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -538,20 +538,36 @@ private fun MessageReceiver.handleGroupUpdated(message: GroupUpdated, closedGrou inner.hasInviteResponse() -> handleInviteResponse(message, closedGroup!!) inner.hasPromoteMessage() -> handlePromotionMessage(message) inner.hasInfoChangeMessage() -> handleGroupInfoChange(message, closedGroup!!) + inner.hasMemberChangeMessage() -> handleMemberChange(message, closedGroup!!) + inner.hasMemberLeftMessage() -> handleMemberLeft(message, closedGroup!!) } } +private fun handleMemberChange(message: GroupUpdated, closedGroup: SessionId) { + val storage = MessagingModuleConfiguration.shared.storage + val memberChange = message.inner.memberChangeMessage + val type = memberChange.type.name + val timestamp = message.sentTimestamp!! + verifyAdminSignature(closedGroup, memberChange.adminSignature.toByteArray(), + "MEMBER_CHANGE$type$timestamp" + ) + storage.insertGroupInfoChange(message, closedGroup) +} + +private fun handleMemberLeft(message: GroupUpdated, closedGroup: SessionId) { + val storage = MessagingModuleConfiguration.shared.storage + storage.insertGroupInfoChange(message, closedGroup) +} + private fun handleGroupInfoChange(message: GroupUpdated, closedGroup: SessionId) { - val sender = message.sender!! val storage = MessagingModuleConfiguration.shared.storage val inner = message.inner val infoChanged = inner.infoChangeMessage ?: return if (!infoChanged.hasAdminSignature()) return Log.e("GroupUpdated", "Info changed message doesn't contain admin signature") val adminSignature = infoChanged.adminSignature val type = infoChanged.type.name - verifyAdminSignature(closedGroup, adminSignature.toByteArray(), "INFO_CHANGE"+type+message.sentTimestamp!!) - val newName = if (infoChanged.hasUpdatedName()) infoChanged.updatedName else null - val newExpiration = if (infoChanged.hasUpdatedExpiration()) infoChanged.updatedExpiration else null + val timestamp = message.sentTimestamp!! + verifyAdminSignature(closedGroup, adminSignature.toByteArray(), "INFO_CHANGE$type$timestamp") storage.insertGroupInfoChange(message, closedGroup) } @@ -559,6 +575,7 @@ private fun handlePromotionMessage(message: GroupUpdated) { val sender = message.sender!! val storage = MessagingModuleConfiguration.shared.storage val inner = message.inner + // TODO: set ourselves as admin and overwrite the auth data for group } private fun MessageReceiver.handleInviteResponse(message: GroupUpdated, closedGroup: SessionId) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageData.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageData.kt index 72415d7a4..bd35541e8 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageData.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageData.kt @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo import com.fasterxml.jackson.core.JsonParseException import org.session.libsession.messaging.messages.control.GroupUpdated import org.session.libsignal.messages.SignalServiceGroup +import org.session.libsignal.protos.SignalServiceProtos.DataMessage.GroupUpdateInfoChangeMessage import org.session.libsignal.protos.SignalServiceProtos.DataMessage.GroupUpdateMemberChangeMessage.Type import org.session.libsignal.utilities.JsonUtil import org.session.libsignal.utilities.Log @@ -18,19 +19,23 @@ class UpdateMessageData () { //the annotations below are required for serialization. Any new Kind class MUST be declared as JsonSubTypes as well @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) @JsonSubTypes( - JsonSubTypes.Type(Kind.GroupCreation::class, name = "GroupCreation"), - JsonSubTypes.Type(Kind.GroupNameChange::class, name = "GroupNameChange"), - JsonSubTypes.Type(Kind.GroupMemberAdded::class, name = "GroupMemberAdded"), - JsonSubTypes.Type(Kind.GroupMemberRemoved::class, name = "GroupMemberRemoved"), - JsonSubTypes.Type(Kind.GroupMemberLeft::class, name = "GroupMemberLeft"), - JsonSubTypes.Type(Kind.OpenGroupInvitation::class, name = "OpenGroupInvitation"), - JsonSubTypes.Type(Kind.GroupAvatarUpdated::class, name = "GroupAvatarUpdated") + JsonSubTypes.Type(Kind.GroupCreation::class, name = "GroupCreation"), + JsonSubTypes.Type(Kind.GroupNameChange::class, name = "GroupNameChange"), + JsonSubTypes.Type(Kind.GroupDescriptionChange::class, name = "GroupDescriptionChange"), + JsonSubTypes.Type(Kind.GroupMemberAdded::class, name = "GroupMemberAdded"), + JsonSubTypes.Type(Kind.GroupMemberRemoved::class, name = "GroupMemberRemoved"), + JsonSubTypes.Type(Kind.GroupMemberLeft::class, name = "GroupMemberLeft"), + JsonSubTypes.Type(Kind.OpenGroupInvitation::class, name = "OpenGroupInvitation"), + JsonSubTypes.Type(Kind.GroupAvatarUpdated::class, name = "GroupAvatarUpdated"), + JsonSubTypes.Type(Kind.GroupMemberUpdated::class, name = "GroupMemberUpdated"), + JsonSubTypes.Type(Kind.GroupExpirationUpdated::class, name = "GroupExpirationUpdated") ) sealed class Kind { data object GroupCreation: Kind() class GroupNameChange(val name: String): Kind() { constructor(): this("") //default constructor required for json serialization } + data class GroupDescriptionChange @JvmOverloads constructor(val description: String = ""): Kind() class GroupMemberAdded(val updatedMembers: Collection): Kind() { constructor(): this(Collections.emptyList()) } @@ -42,7 +47,7 @@ class UpdateMessageData () { constructor(): this(emptyList(), null) } data object GroupAvatarUpdated: Kind() - class GroupExpiryUpdated @JvmOverloads constructor(val newExpiry: Int = 0): Kind() + data class GroupExpirationUpdated(val updatedExpiration: Int = 0): Kind() class OpenGroupInvitation(val groupUrl: String, val groupName: String): Kind() { constructor(): this("", "") } @@ -81,6 +86,7 @@ class UpdateMessageData () { Type.ADDED -> MemberUpdateType.ADDED Type.PROMOTED -> MemberUpdateType.PROMOTED Type.REMOVED -> MemberUpdateType.REMOVED + null -> null } val members = memberChange.memberSessionIdsList UpdateMessageData(Kind.GroupMemberUpdated(members, type)) @@ -88,13 +94,14 @@ class UpdateMessageData () { inner.hasInfoChangeMessage() -> { val infoChange = inner.infoChangeMessage val type = infoChange.type - TODO() -// when (type) { -// GroupUpdateInfoChangeMessage.Type.NAME -> Kind.GroupNameChange(infoChange.updatedName) -// GroupUpdateInfoChangeMessage.Type.AVATAR -> Kind.GroupAvatarUpdated -// // GroupUpdateInfoChangeMessage.Type.DISAPPEARING_MESSAGES -> Kind.GroupExpirationUpdated(infoChange.updatedExpiration) -// } + when (type) { + GroupUpdateInfoChangeMessage.Type.NAME -> Kind.GroupNameChange(infoChange.updatedName) + GroupUpdateInfoChangeMessage.Type.AVATAR -> Kind.GroupAvatarUpdated + GroupUpdateInfoChangeMessage.Type.DISAPPEARING_MESSAGES -> Kind.GroupExpirationUpdated(infoChange.updatedExpiration) + else -> null + }?.let { UpdateMessageData(it) } } + inner.hasMemberLeftMessage() -> UpdateMessageData(Kind.GroupMemberLeft) else -> null } }