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); groupMasterKey);
} }
if (group == null) { if (group == null) {
group = groupV2Helper.getDecryptedGroup(groupSecretParams); try {
group = groupV2Helper.getDecryptedGroup(groupSecretParams);
} catch (NotAGroupMemberException ignored) {
}
} }
if (group != null) { if (group != null) {
storeProfileKeysFromMembers(group); storeProfileKeysFromMembers(group);
@ -348,10 +351,20 @@ public class GroupHelper {
private GroupInfo getGroup(GroupId groupId, boolean forceUpdate) { private GroupInfo getGroup(GroupId groupId, boolean forceUpdate) {
final var group = account.getGroupStore().getGroup(groupId); final var group = account.getGroupStore().getGroup(groupId);
if (group instanceof GroupInfoV2 && (forceUpdate || ((GroupInfoV2) group).getGroup() == null)) { if (group instanceof GroupInfoV2) {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(((GroupInfoV2) group).getMasterKey()); final var groupInfoV2 = (GroupInfoV2) group;
((GroupInfoV2) group).setGroup(groupV2Helper.getDecryptedGroup(groupSecretParams), recipientResolver); if (forceUpdate || (!groupInfoV2.isPermissionDenied() && groupInfoV2.getGroup() == null)) {
account.getGroupStore().updateGroup(group); 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; 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.GroupLinkState;
import org.asamk.signal.manager.groups.GroupPermission; import org.asamk.signal.manager.groups.GroupPermission;
import org.asamk.signal.manager.groups.GroupUtils; 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.groups.GroupInfoV2;
import org.asamk.signal.manager.storage.recipients.Profile; import org.asamk.signal.manager.storage.recipients.Profile;
import org.asamk.signal.manager.storage.recipients.RecipientId; 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.InvalidGroupStateException;
import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException; import org.whispersystems.signalservice.api.groupsv2.NotAbleToApplyGroupV2ChangeException;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.File; import java.io.File;
@ -78,10 +80,16 @@ public class GroupV2Helper {
this.addressResolver = addressResolver; this.addressResolver = addressResolver;
} }
public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) { public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) throws NotAGroupMemberException {
try { try {
final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams); final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams);
return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString); 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) { } catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage()); logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage());
return null; return null;

View file

@ -22,16 +22,23 @@ public class GroupInfoV2 extends GroupInfo {
private boolean blocked; private boolean blocked;
private DecryptedGroup group; // stored as a file with hexadecimal groupId as name private DecryptedGroup group; // stored as a file with hexadecimal groupId as name
private RecipientResolver recipientResolver; private RecipientResolver recipientResolver;
private boolean permissionDenied;
public GroupInfoV2(final GroupIdV2 groupId, final GroupMasterKey masterKey) { public GroupInfoV2(final GroupIdV2 groupId, final GroupMasterKey masterKey) {
this.groupId = groupId; this.groupId = groupId;
this.masterKey = masterKey; 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.groupId = groupId;
this.masterKey = masterKey; this.masterKey = masterKey;
this.blocked = blocked; this.blocked = blocked;
this.permissionDenied = permissionDenied;
} }
@Override @Override
@ -44,6 +51,9 @@ public class GroupInfoV2 extends GroupInfo {
} }
public void setGroup(final DecryptedGroup group, final RecipientResolver recipientResolver) { public void setGroup(final DecryptedGroup group, final RecipientResolver recipientResolver) {
if (group != null) {
this.permissionDenied = false;
}
this.group = group; this.group = group;
this.recipientResolver = recipientResolver; this.recipientResolver = recipientResolver;
} }
@ -151,4 +161,12 @@ public class GroupInfoV2 extends GroupInfo {
public boolean isAnnouncementGroup() { public boolean isAnnouncementGroup() {
return this.group != null && this.group.getIsAnnouncementGroup() == EnabledState.ENABLED; 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()); 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)); }).collect(Collectors.toMap(GroupInfo::getGroupId, g -> g));
return new GroupStore(groupCachePath, groups, recipientResolver, saver); return new GroupStore(groupCachePath, groups, recipientResolver, saver);
@ -268,13 +268,13 @@ public class GroupStore {
final var g2 = (GroupInfoV2) g; final var g2 = (GroupInfoV2) g;
return new Storage.GroupV2(g2.getGroupId().toBase64(), return new Storage.GroupV2(g2.getGroupId().toBase64(),
Base64.getEncoder().encodeToString(g2.getMasterKey().serialize()), Base64.getEncoder().encodeToString(g2.getMasterKey().serialize()),
g2.isBlocked()); g2.isBlocked(),
g2.isPermissionDenied());
}).collect(Collectors.toList())); }).collect(Collectors.toList()));
} }
public static class Storage { public static class Storage {
// @JsonSerialize(using = GroupsSerializer.class)
@JsonDeserialize(using = GroupsDeserializer.class) @JsonDeserialize(using = GroupsDeserializer.class)
public List<Storage.Group> groups; public List<Storage.Group> groups;
@ -408,46 +408,24 @@ public class GroupStore {
public String groupId; public String groupId;
public String masterKey; public String masterKey;
public boolean blocked; public boolean blocked;
public boolean permissionDenied;
// For deserialization // For deserialization
private GroupV2() { 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.groupId = groupId;
this.masterKey = masterKey; this.masterKey = masterKey;
this.blocked = blocked; 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>> { private static class GroupsDeserializer extends JsonDeserializer<List<Storage.Group>> {
@Override @Override