Added admins to groups.

Only process group updates if an admin sent it.
This commit is contained in:
Mikunj
2019-12-13 10:25:53 +11:00
parent 23a5fa7580
commit b6d2717286
11 changed files with 139 additions and 42 deletions

View File

@@ -55,11 +55,12 @@ public class GroupManager {
@NonNull Set<Recipient> members,
@Nullable Bitmap avatar,
@Nullable String name,
boolean mms)
boolean mms,
@NonNull Set<Recipient> admins)
{
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
String id = GroupUtil.getEncodedId(database.allocateGroupId(), mms);
return createGroup(id, context, members, avatar, name, mms);
return createGroup(id, context, members, avatar, name, mms, admins);
}
public static @NonNull GroupActionResult createGroup(@NonNull String id,
@@ -67,21 +68,23 @@ public class GroupManager {
@NonNull Set<Recipient> members,
@Nullable Bitmap avatar,
@Nullable String name,
boolean mms)
boolean mms,
@NonNull Set<Recipient> admins)
{
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final String groupId = GroupUtil.getEncodedId(id.getBytes(), mms);
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
final Set<Address> memberAddresses = getMemberAddresses(members);
final Set<Address> adminAddresses = getMemberAddresses(admins);
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses));
if (!mms) {
groupDatabase.updateAvatar(groupId, avatarBytes);
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true);
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes);
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
} else {
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
return new GroupActionResult(groupRecipient, threadId);
@@ -117,7 +120,7 @@ public class GroupManager {
final Set<Address> memberAddresses = new HashSet<>();
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>());
groupDatabase.updateAvatar(groupId, avatarBytes);
@@ -129,20 +132,23 @@ public class GroupManager {
@NonNull String groupId,
@NonNull Set<Recipient> members,
@Nullable Bitmap avatar,
@Nullable String name)
@Nullable String name,
@NonNull Set<Recipient> admins)
throws InvalidNumberException
{
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
final Set<Address> memberAddresses = getMemberAddresses(members);
final Set<Address> adminAddresses = getMemberAddresses(admins);
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
groupDatabase.updateAdmins(groupId, new LinkedList<>(adminAddresses));
groupDatabase.updateTitle(groupId, name);
groupDatabase.updateAvatar(groupId, avatarBytes);
if (!GroupUtil.isMmsGroup(groupId)) {
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes);
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
} else {
Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
@@ -154,7 +160,8 @@ public class GroupManager {
@NonNull String groupId,
@NonNull Set<Address> members,
@Nullable String groupName,
@Nullable byte[] avatar)
@Nullable byte[] avatar,
@NonNull Set<Address> admins)
{
try {
Attachment avatarAttachment = null;
@@ -162,15 +169,20 @@ public class GroupManager {
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
List<String> numbers = new LinkedList<>();
for (Address member : members) {
numbers.add(member.serialize());
}
List<String> adminNumbers = new LinkedList<>();
for (Address admin : admins) {
adminNumbers.add(admin.serialize());
}
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
.setType(GroupContext.Type.UPDATE)
.addAllMembers(numbers);
.addAllMembers(numbers)
.addAllAdmins(adminNumbers);
if (groupName != null) groupContextBuilder.setName(groupName);
GroupContext groupContext = groupContextBuilder.build();

View File

@@ -25,12 +25,15 @@ import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
import org.whispersystems.signalservice.api.messages.SignalServiceGroup.Type;
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
import java.util.Collections;
import java.util.HashSet;
@@ -87,6 +90,7 @@ public class GroupMessageProcessor {
SignalServiceAttachment avatar = group.getAvatar().orNull();
List<Address> members = group.getMembers().isPresent() ? new LinkedList<Address>() : null;
List<Address> admins = group.getAdmins().isPresent() ? new LinkedList<>() : null;
if (group.getMembers().isPresent()) {
for (String member : group.getMembers().get()) {
@@ -94,8 +98,22 @@ public class GroupMessageProcessor {
}
}
// We should only create the group if we are part of the member list
String masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
String hexEncodedPublicKey = masterHexEncodedPublicKey != null ? masterHexEncodedPublicKey : TextSecurePreferences.getLocalNumber(context);
if (members == null || !members.contains(Address.fromSerialized(hexEncodedPublicKey))) {
Log.d("Loki - Group Message", "Received a group create message which doesn't include us in the member list. Ignoring.");
return null;
}
if (group.getAdmins().isPresent()) {
for (String admin : group.getAdmins().get()) {
admins.add(Address.fromExternal(context, admin));
}
}
database.create(id, group.getName().orNull(), members,
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null);
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null, admins);
return storeMessage(context, content, group, builder.build(), outgoing);
}
@@ -110,6 +128,21 @@ public class GroupMessageProcessor {
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
String id = GroupUtil.getEncodedId(group);
// Only update group if admin sent the message
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
String sender = content.getSender();
String hexEncodedPublicKey = sender;
try {
String primaryDevice = PromiseUtil.timeout(LokiStorageAPI.shared.getPrimaryDevicePublicKey(sender), 5000).get();
if (primaryDevice != null) { hexEncodedPublicKey = primaryDevice; }
} catch (Exception e) { }
if (!groupRecord.getAdmins().contains(Address.fromSerialized(hexEncodedPublicKey))) {
Log.d("Loki - Group Message", "Received a group update message from a non-admin user for " + id +". Ignoring.");
return null;
}
}
Set<Address> recordMembers = new HashSet<>(groupRecord.getMembers());
Set<Address> messageMembers = new HashSet<>();
@@ -262,6 +295,10 @@ public class GroupMessageProcessor {
builder.addAllMembers(group.getMembers().get());
}
if (group.getAdmins().isPresent()) {
builder.addAllAdmins(group.getAdmins().get());
}
return builder;
}