From: AsamK Date: Sat, 2 Oct 2021 16:40:36 +0000 (+0200) Subject: Don't repeatedly try to refetch group info if permission was denied X-Git-Tag: v0.9.1~31 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/8b83992e95dbd0f888ec71ee751613a77ec00820 Don't repeatedly try to refetch group info if permission was denied i.e. if the user is no longer a member of that group --- diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 3ddd6edd..62f4f111 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -145,7 +145,10 @@ public class GroupHelper { groupMasterKey); } if (group == null) { - group = groupV2Helper.getDecryptedGroup(groupSecretParams); + try { + group = groupV2Helper.getDecryptedGroup(groupSecretParams); + } catch (NotAGroupMemberException ignored) { + } } if (group != null) { storeProfileKeysFromMembers(group); @@ -348,10 +351,20 @@ public class GroupHelper { private GroupInfo getGroup(GroupId groupId, boolean forceUpdate) { final var group = account.getGroupStore().getGroup(groupId); - if (group instanceof GroupInfoV2 && (forceUpdate || ((GroupInfoV2) group).getGroup() == null)) { - final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(((GroupInfoV2) group).getMasterKey()); - ((GroupInfoV2) group).setGroup(groupV2Helper.getDecryptedGroup(groupSecretParams), recipientResolver); - account.getGroupStore().updateGroup(group); + if (group instanceof GroupInfoV2) { + final var groupInfoV2 = (GroupInfoV2) group; + if (forceUpdate || (!groupInfoV2.isPermissionDenied() && groupInfoV2.getGroup() == null)) { + final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); + DecryptedGroup decryptedGroup; + try { + decryptedGroup = groupV2Helper.getDecryptedGroup(groupSecretParams); + } catch (NotAGroupMemberException e) { + groupInfoV2.setPermissionDenied(true); + decryptedGroup = null; + } + groupInfoV2.setGroup(decryptedGroup, recipientResolver); + account.getGroupStore().updateGroup(group); + } } return group; } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java index 3187fca1..746af2f9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java @@ -6,6 +6,7 @@ import org.asamk.signal.manager.groups.GroupLinkPassword; import org.asamk.signal.manager.groups.GroupLinkState; import org.asamk.signal.manager.groups.GroupPermission; import org.asamk.signal.manager.groups.GroupUtils; +import org.asamk.signal.manager.groups.NotAGroupMemberException; import org.asamk.signal.manager.storage.groups.GroupInfoV2; import org.asamk.signal.manager.storage.recipients.Profile; import org.asamk.signal.manager.storage.recipients.RecipientId; @@ -35,6 +36,7 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException; import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.File; @@ -78,10 +80,16 @@ public class GroupV2Helper { this.addressResolver = addressResolver; } - public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) { + public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) throws NotAGroupMemberException { try { final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams); return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString); + } catch (NonSuccessfulResponseCodeException e) { + if (e.getCode() == 403) { + throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null); + } + logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage()); + return null; } catch (IOException | VerificationFailedException | InvalidGroupStateException e) { logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage()); return null; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV2.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV2.java index f86dcb04..a06b83df 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV2.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV2.java @@ -22,16 +22,23 @@ public class GroupInfoV2 extends GroupInfo { private boolean blocked; private DecryptedGroup group; // stored as a file with hexadecimal groupId as name private RecipientResolver recipientResolver; + private boolean permissionDenied; public GroupInfoV2(final GroupIdV2 groupId, final GroupMasterKey masterKey) { this.groupId = groupId; this.masterKey = masterKey; } - public GroupInfoV2(final GroupIdV2 groupId, final GroupMasterKey masterKey, final boolean blocked) { + public GroupInfoV2( + final GroupIdV2 groupId, + final GroupMasterKey masterKey, + final boolean blocked, + final boolean permissionDenied + ) { this.groupId = groupId; this.masterKey = masterKey; this.blocked = blocked; + this.permissionDenied = permissionDenied; } @Override @@ -44,6 +51,9 @@ public class GroupInfoV2 extends GroupInfo { } public void setGroup(final DecryptedGroup group, final RecipientResolver recipientResolver) { + if (group != null) { + this.permissionDenied = false; + } this.group = group; this.recipientResolver = recipientResolver; } @@ -151,4 +161,12 @@ public class GroupInfoV2 extends GroupInfo { public boolean isAnnouncementGroup() { return this.group != null && this.group.getIsAnnouncementGroup() == EnabledState.ENABLED; } + + public void setPermissionDenied(final boolean permissionDenied) { + this.permissionDenied = permissionDenied; + } + + public boolean isPermissionDenied() { + return permissionDenied; + } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java index 4adc413a..fe8f85a6 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java @@ -104,7 +104,7 @@ public class GroupStore { throw new AssertionError("Invalid master key for group " + groupId.toBase64()); } - return new GroupInfoV2(groupId, masterKey, g2.blocked); + return new GroupInfoV2(groupId, masterKey, g2.blocked, g2.permissionDenied); }).collect(Collectors.toMap(GroupInfo::getGroupId, g -> g)); return new GroupStore(groupCachePath, groups, recipientResolver, saver); @@ -268,13 +268,13 @@ public class GroupStore { final var g2 = (GroupInfoV2) g; return new Storage.GroupV2(g2.getGroupId().toBase64(), Base64.getEncoder().encodeToString(g2.getMasterKey().serialize()), - g2.isBlocked()); + g2.isBlocked(), + g2.isPermissionDenied()); }).collect(Collectors.toList())); } public static class Storage { - // @JsonSerialize(using = GroupsSerializer.class) @JsonDeserialize(using = GroupsDeserializer.class) public List groups; @@ -408,46 +408,24 @@ public class GroupStore { public String groupId; public String masterKey; public boolean blocked; + public boolean permissionDenied; // For deserialization private GroupV2() { } - public GroupV2(final String groupId, final String masterKey, final boolean blocked) { + public GroupV2( + final String groupId, final String masterKey, final boolean blocked, final boolean permissionDenied + ) { this.groupId = groupId; this.masterKey = masterKey; this.blocked = blocked; + this.permissionDenied = permissionDenied; } } } - // private static class GroupsSerializer extends JsonSerializer> { -// -// @Override -// public void serialize( -// final List groups, final JsonGenerator jgen, final SerializerProvider provider -// ) throws IOException { -// jgen.writeStartArray(groups.size()); -// for (var group : groups) { -// if (group instanceof GroupInfoV1) { -// jgen.writeObject(group); -// } else if (group instanceof GroupInfoV2) { -// final var groupV2 = (GroupInfoV2) group; -// jgen.writeStartObject(); -// jgen.writeStringField("groupId", groupV2.getGroupId().toBase64()); -// jgen.writeStringField("masterKey", -// Base64.getEncoder().encodeToString(groupV2.getMasterKey().serialize())); -// jgen.writeBooleanField("blocked", groupV2.isBlocked()); -// jgen.writeEndObject(); -// } else { -// throw new AssertionError("Unknown group version"); -// } -// } -// jgen.writeEndArray(); -// } -// } -// private static class GroupsDeserializer extends JsonDeserializer> { @Override