diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java index bfa78ef3c..8761cb9e4 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerConfiguration.java @@ -19,6 +19,7 @@ package org.whispersystems.textsecuregcm; import com.fasterxml.jackson.annotation.JsonProperty; import org.whispersystems.textsecuregcm.configuration.FederationConfiguration; import org.whispersystems.textsecuregcm.configuration.GraphiteConfiguration; +import org.whispersystems.textsecuregcm.configuration.MaxDeviceConfiguration; import org.whispersystems.textsecuregcm.configuration.PushConfiguration; import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration; import org.whispersystems.textsecuregcm.configuration.RedPhoneConfiguration; @@ -77,6 +78,11 @@ public class WhisperServerConfiguration extends Configuration { @JsonProperty private List testDevices = new LinkedList<>(); + @Valid + @NotNull + @JsonProperty + private List maxDevices = new LinkedList<>(); + @Valid @JsonProperty private FederationConfiguration federation = new FederationConfiguration(); @@ -178,4 +184,15 @@ public class WhisperServerConfiguration extends Configuration { return results; } + + public Map getMaxDevices() { + Map results = new HashMap<>(); + + for (MaxDeviceConfiguration maxDeviceConfiguration : maxDevices) { + results.put(maxDeviceConfiguration.getNumber(), + maxDeviceConfiguration.getCount()); + } + + return results; + } } diff --git a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java index 6b21ca3a4..6ae5dcc2e 100644 --- a/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java +++ b/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java @@ -212,7 +212,7 @@ public class WhisperServerService extends Application maxDeviceConfiguration; public DeviceController(PendingDevicesManager pendingDevices, AccountsManager accounts, MessagesManager messages, - RateLimiters rateLimiters) + RateLimiters rateLimiters, + Map maxDeviceConfiguration) { - this.pendingDevices = pendingDevices; - this.accounts = accounts; - this.messages = messages; - this.rateLimiters = rateLimiters; + this.pendingDevices = pendingDevices; + this.accounts = accounts; + this.messages = messages; + this.rateLimiters = rateLimiters; + this.maxDeviceConfiguration = maxDeviceConfiguration; } @Timed @@ -116,7 +120,13 @@ public class DeviceController { { rateLimiters.getAllocateDeviceLimiter().validate(account.getNumber()); - if (account.getActiveDeviceCount() >= MAX_DEVICES) { + int maxDeviceLimit = MAX_DEVICES; + + if (maxDeviceConfiguration.containsKey(account.getNumber())) { + maxDeviceLimit = maxDeviceConfiguration.get(account.getNumber()); + } + + if (account.getActiveDeviceCount() >= maxDeviceLimit) { throw new DeviceLimitExceededException(account.getDevices().size(), MAX_DEVICES); } diff --git a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java index b8ffd44b0..c3836784d 100644 --- a/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java +++ b/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java @@ -40,6 +40,9 @@ import javax.ws.rs.client.Entity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.util.HashMap; +import java.util.Map; + import io.dropwizard.jersey.validation.ConstraintViolationExceptionMapper; import io.dropwizard.testing.junit.ResourceTestRule; import static org.assertj.core.api.Assertions.assertThat; @@ -52,9 +55,10 @@ public class DeviceControllerTest { public DumbVerificationDeviceController(PendingDevicesManager pendingDevices, AccountsManager accounts, MessagesManager messages, - RateLimiters rateLimiters) + RateLimiters rateLimiters, + Map deviceConfiguration) { - super(pendingDevices, accounts, messages, rateLimiters); + super(pendingDevices, accounts, messages, rateLimiters, deviceConfiguration); } @Override @@ -71,6 +75,10 @@ public class DeviceControllerTest { private Account account = mock(Account.class ); private Account maxedAccount = mock(Account.class); + private Map deviceConfiguration = new HashMap() {{ + + }}; + @Rule public final ResourceTestRule resources = ResourceTestRule.builder() .addProvider(AuthHelper.getAuthFilter()) @@ -81,7 +89,8 @@ public class DeviceControllerTest { .addResource(new DumbVerificationDeviceController(pendingDevicesManager, accountsManager, messagesManager, - rateLimiters)) + rateLimiters, + deviceConfiguration)) .build();