Add internal pre-alpha support for usernames.

This commit is contained in:
Greyson Parrelli
2019-10-28 20:16:11 -04:00
parent fb49efa34d
commit 608815a69b
54 changed files with 2385 additions and 86 deletions
@@ -453,6 +453,14 @@ public class SignalServiceAccountManager {
this.pushServiceSocket.setProfileAvatar(profileAvatarData);
}
public void setUsername(String username) throws IOException {
this.pushServiceSocket.setUsername(username);
}
public void deleteUsername() throws IOException {
this.pushServiceSocket.deleteUsername();
}
public void setSoTimeoutMillis(long soTimeoutMillis) {
this.pushServiceSocket.setSoTimeoutMillis(soTimeoutMillis);
}
@@ -116,6 +116,12 @@ public class SignalServiceMessageReceiver {
return socket.retrieveProfile(address, unidentifiedAccess);
}
public SignalServiceProfile retrieveProfileByUsername(String username, Optional<UnidentifiedAccess> unidentifiedAccess)
throws IOException
{
return socket.retrieveProfileByUsername(username, unidentifiedAccess);
}
public InputStream retrieveProfileAvatar(String path, File destination, byte[] profileKey, int maxSizeBytes)
throws IOException
{
@@ -2,6 +2,12 @@ package org.whispersystems.signalservice.api.profiles;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.whispersystems.signalservice.internal.util.JsonUtil;
import java.util.UUID;
public class SignalServiceProfile {
@@ -23,6 +29,14 @@ public class SignalServiceProfile {
@JsonProperty
private Capabilities capabilities;
@JsonProperty
private String username;
@JsonProperty
@JsonSerialize(using = JsonUtil.UuidSerializer.class)
@JsonDeserialize(using = JsonUtil.UuidDeserializer.class)
private UUID uuid;
public SignalServiceProfile() {}
public String getIdentityKey() {
@@ -49,6 +63,14 @@ public class SignalServiceProfile {
return capabilities;
}
public String getUsername() {
return username;
}
public UUID getUuid() {
return uuid;
}
public static class Capabilities {
@JsonProperty
private boolean uuid;
@@ -0,0 +1,4 @@
package org.whispersystems.signalservice.api.push.exceptions;
public class UsernameMalformedException extends NonSuccessfulResponseCodeException {
}
@@ -0,0 +1,4 @@
package org.whispersystems.signalservice.api.push.exceptions;
public class UsernameTakenException extends NonSuccessfulResponseCodeException {
}
@@ -34,6 +34,8 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
import org.whispersystems.signalservice.api.push.exceptions.RemoteAttestationResponseExpiredException;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException;
import org.whispersystems.signalservice.api.util.CredentialsProvider;
import org.whispersystems.signalservice.api.util.Tls12SocketFactory;
import org.whispersystems.signalservice.api.util.UuidUtil;
@@ -108,6 +110,8 @@ public class PushServiceSocket {
private static final String PIN_PATH = "/v1/accounts/pin/";
private static final String REQUEST_PUSH_CHALLENGE = "/v1/accounts/fcm/preauth/%s/%s";
private static final String WHO_AM_I = "/v1/accounts/whoami";
private static final String SET_USERNAME_PATH = "/v1/accounts/username/%s";
private static final String DELETE_USERNAME_PATH = "/v1/accounts/username";
private static final String PREKEY_METADATA_PATH = "/v2/keys/";
private static final String PREKEY_PATH = "/v2/keys/%s";
@@ -128,6 +132,7 @@ public class PushServiceSocket {
private static final String ATTACHMENT_PATH = "/v2/attachments/form/upload";
private static final String PROFILE_PATH = "/v1/profile/%s";
private static final String PROFILE_USERNAME_PATH = "/v1/profile/username/%s";
private static final String SENDER_CERTIFICATE_LEGACY_PATH = "/v1/certificate/delivery";
private static final String SENDER_CERTIFICATE_PATH = "/v1/certificate/delivery?includeUuid=true";
@@ -491,8 +496,22 @@ public class PushServiceSocket {
public SignalServiceProfile retrieveProfile(SignalServiceAddress target, Optional<UnidentifiedAccess> unidentifiedAccess)
throws NonSuccessfulResponseCodeException, PushNetworkException
{
String response = makeServiceRequest(String.format(PROFILE_PATH, target.getIdentifier()), "GET", null, NO_HEADERS, unidentifiedAccess);
try {
return JsonUtil.fromJson(response, SignalServiceProfile.class);
} catch (IOException e) {
Log.w(TAG, e);
throw new NonSuccessfulResponseCodeException("Unable to parse entity");
}
}
public SignalServiceProfile retrieveProfileByUsername(String username, Optional<UnidentifiedAccess> unidentifiedAccess)
throws NonSuccessfulResponseCodeException, PushNetworkException
{
String response = makeServiceRequest(String.format(PROFILE_USERNAME_PATH, username), "GET", null, NO_HEADERS, unidentifiedAccess);
try {
String response = makeServiceRequest(String.format(PROFILE_PATH, target.getIdentifier()), "GET", null, NO_HEADERS, unidentifiedAccess);
return JsonUtil.fromJson(response, SignalServiceProfile.class);
} catch (IOException e) {
Log.w(TAG, e);
@@ -533,6 +552,22 @@ public class PushServiceSocket {
}
}
public void setUsername(String username) throws IOException {
makeServiceRequest(String.format(SET_USERNAME_PATH, username), "PUT", "", NO_HEADERS, new ResponseCodeHandler() {
@Override
public void handle(int responseCode) throws NonSuccessfulResponseCodeException {
switch (responseCode) {
case 400: throw new UsernameMalformedException();
case 409: throw new UsernameTakenException();
}
}
}, Optional.<UnidentifiedAccess>absent());
}
public void deleteUsername() throws IOException {
makeServiceRequest(DELETE_USERNAME_PATH, "DELETE", null);
}
public List<ContactTokenDetails> retrieveDirectory(Set<String> contactTokens)
throws NonSuccessfulResponseCodeException, PushNetworkException
{
@@ -20,9 +20,11 @@ import com.fasterxml.jackson.databind.SerializerProvider;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.logging.Log;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.util.Base64;
import java.io.IOException;
import java.util.UUID;
public class JsonUtil {
@@ -69,5 +71,19 @@ public class JsonUtil {
}
}
public static class UuidSerializer extends JsonSerializer<UUID> {
@Override
public void serialize(UUID value, JsonGenerator gen, SerializerProvider serializers)
throws IOException
{
gen.writeString(value.toString());
}
}
public static class UuidDeserializer extends JsonDeserializer<UUID> {
@Override
public UUID deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return UuidUtil.parseOrNull(p.getValueAsString());
}
}
}