Allow max device limit to be configurable per-user

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-02-26 16:41:36 -08:00
parent 507d457900
commit 3d2f8a7ddb
5 changed files with 73 additions and 10 deletions

View File

@ -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<TestDeviceConfiguration> testDevices = new LinkedList<>();
@Valid
@NotNull
@JsonProperty
private List<MaxDeviceConfiguration> maxDevices = new LinkedList<>();
@Valid
@JsonProperty
private FederationConfiguration federation = new FederationConfiguration();
@ -178,4 +184,15 @@ public class WhisperServerConfiguration extends Configuration {
return results;
}
public Map<String, Integer> getMaxDevices() {
Map<String, Integer> results = new HashMap<>();
for (MaxDeviceConfiguration maxDeviceConfiguration : maxDevices) {
results.put(maxDeviceConfiguration.getNumber(),
maxDeviceConfiguration.getCount());
}
return results;
}
}

View File

@ -212,7 +212,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
environment.jersey().register(new AuthValueFactoryProvider.Binder());
environment.jersey().register(new AccountController(pendingAccountsManager, accountsManager, rateLimiters, smsSender, messagesManager, new TimeProvider(), authorizationKey, turnTokenGenerator, config.getTestDevices()));
environment.jersey().register(new DeviceController(pendingDevicesManager, accountsManager, messagesManager, rateLimiters));
environment.jersey().register(new DeviceController(pendingDevicesManager, accountsManager, messagesManager, rateLimiters, config.getMaxDevices()));
environment.jersey().register(new DirectoryController(rateLimiters, directory));
environment.jersey().register(new FederationControllerV1(accountsManager, attachmentController, messageController));
environment.jersey().register(new FederationControllerV2(accountsManager, attachmentController, messageController, keysControllerV2));

View File

@ -0,0 +1,27 @@
package org.whispersystems.textsecuregcm.configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
public class MaxDeviceConfiguration {
@JsonProperty
@NotEmpty
private String number;
@JsonProperty
@NotNull
private int count;
public String getNumber() {
return number;
}
public int getCount() {
return count;
}
}

View File

@ -54,6 +54,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import io.dropwizard.auth.Auth;
@ -68,16 +69,19 @@ public class DeviceController {
private final AccountsManager accounts;
private final MessagesManager messages;
private final RateLimiters rateLimiters;
private final Map<String, Integer> maxDeviceConfiguration;
public DeviceController(PendingDevicesManager pendingDevices,
AccountsManager accounts,
MessagesManager messages,
RateLimiters rateLimiters)
RateLimiters rateLimiters,
Map<String, Integer> 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);
}

View File

@ -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<String, Integer> 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<String, Integer> deviceConfiguration = new HashMap<String, Integer>() {{
}};
@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();