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
This commit is contained in:
AsamK 2021-10-02 18:40:36 +02:00
parent 778adacb80
commit 8b83992e95
4 changed files with 54 additions and 37 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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<Storage.Group> 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<List<Storage.Group>> {
//
// @Override
// public void serialize(
// final List<Storage.Group> 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<List<Storage.Group>> {
@Override