Add metric to track newly-locked accounts.
This commit is contained in:
parent
2c9c50711f
commit
1d1e3ba79d
|
@ -130,6 +130,8 @@ public class AccountController {
|
||||||
|
|
||||||
private static final String NONSTANDARD_USERNAME_COUNTER_NAME = name(AccountController.class, "nonStandardUsername");
|
private static final String NONSTANDARD_USERNAME_COUNTER_NAME = name(AccountController.class, "nonStandardUsername");
|
||||||
|
|
||||||
|
private static final String LOCKED_ACCOUNT_COUNTER_NAME = name(AccountController.class, "lockedAccount");
|
||||||
|
|
||||||
private static final String CHALLENGE_PRESENT_TAG_NAME = "present";
|
private static final String CHALLENGE_PRESENT_TAG_NAME = "present";
|
||||||
private static final String CHALLENGE_MATCH_TAG_NAME = "matches";
|
private static final String CHALLENGE_MATCH_TAG_NAME = "matches";
|
||||||
private static final String COUNTRY_CODE_TAG_NAME = "countryCode";
|
private static final String COUNTRY_CODE_TAG_NAME = "countryCode";
|
||||||
|
@ -142,6 +144,8 @@ public class AccountController {
|
||||||
private static final String REGION_CODE_TAG_NAME = "regionCode";
|
private static final String REGION_CODE_TAG_NAME = "regionCode";
|
||||||
private static final String VERIFICATION_TRANSPORT_TAG_NAME = "transport";
|
private static final String VERIFICATION_TRANSPORT_TAG_NAME = "transport";
|
||||||
private static final String SCORE_TAG_NAME = "score";
|
private static final String SCORE_TAG_NAME = "score";
|
||||||
|
private static final String LOCK_REASON_TAG_NAME = "lockReason";
|
||||||
|
private static final String ALREADY_LOCKED_TAG_NAME = "alreadyLocked";
|
||||||
|
|
||||||
|
|
||||||
private final StoredVerificationCodeManager pendingAccounts;
|
private final StoredVerificationCodeManager pendingAccounts;
|
||||||
|
@ -812,11 +816,25 @@ public class AccountController {
|
||||||
|
|
||||||
if (!existingRegistrationLock.verify(clientRegistrationLock)) {
|
if (!existingRegistrationLock.verify(clientRegistrationLock)) {
|
||||||
// At this point, the client verified ownership of the phone number but doesn’t have the reglock PIN.
|
// At this point, the client verified ownership of the phone number but doesn’t have the reglock PIN.
|
||||||
// Freezing the existing account credentials will definitively start the reglock timeout. Until the timeout, the current reglock can still be supplied,
|
// Freezing the existing account credentials will definitively start the reglock timeout.
|
||||||
|
// Until the timeout, the current reglock can still be supplied,
|
||||||
// along with phone number verification, to restore access.
|
// along with phone number verification, to restore access.
|
||||||
final Account updatedAccount = accounts.update(existingAccount, Account::lockAuthenticationCredentials);
|
boolean alreadyLocked = existingAccount.hasLockedCredentials();
|
||||||
|
Metrics.counter(LOCKED_ACCOUNT_COUNTER_NAME,
|
||||||
|
LOCK_REASON_TAG_NAME, "verifiedNumberFailedReglock",
|
||||||
|
ALREADY_LOCKED_TAG_NAME, Boolean.toString(alreadyLocked))
|
||||||
|
.increment();
|
||||||
|
|
||||||
|
final Account updatedAccount;
|
||||||
|
if (!alreadyLocked) {
|
||||||
|
updatedAccount = accounts.update(existingAccount, Account::lockAuthenticationCredentials);
|
||||||
|
} else {
|
||||||
|
updatedAccount = existingAccount;
|
||||||
|
}
|
||||||
|
|
||||||
List<Long> deviceIds = updatedAccount.getDevices().stream().map(Device::getId).toList();
|
List<Long> deviceIds = updatedAccount.getDevices().stream().map(Device::getId).toList();
|
||||||
clientPresenceManager.disconnectAllPresences(updatedAccount.getUuid(), deviceIds);
|
clientPresenceManager.disconnectAllPresences(updatedAccount.getUuid(), deviceIds);
|
||||||
|
|
||||||
throw new WebApplicationException(Response.status(423)
|
throw new WebApplicationException(Response.status(423)
|
||||||
.entity(new RegistrationLockFailure(existingRegistrationLock.getTimeRemaining(),
|
.entity(new RegistrationLockFailure(existingRegistrationLock.getTimeRemaining(),
|
||||||
existingRegistrationLock.needsFailureCredentials() ? existingBackupCredentials : null))
|
existingRegistrationLock.needsFailureCredentials() ? existingBackupCredentials : null))
|
||||||
|
|
|
@ -472,6 +472,18 @@ public class Account {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Have all this account's devices been manually locked?
|
||||||
|
*
|
||||||
|
* @see Device#hasLockedCredentials
|
||||||
|
*
|
||||||
|
* @return true if all the account's devices were locked, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean hasLockedCredentials() {
|
||||||
|
return devices.stream().allMatch(Device::hasLockedCredentials);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock account by invalidating authentication tokens.
|
* Lock account by invalidating authentication tokens.
|
||||||
*
|
*
|
||||||
|
|
|
@ -149,6 +149,19 @@ public class Device {
|
||||||
this.salt = credentials.getSalt();
|
this.salt = credentials.getSalt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has this device been manually locked?
|
||||||
|
*
|
||||||
|
* We lock a device by prepending "!" to its token.
|
||||||
|
* This character cannot normally appear in valid tokens.
|
||||||
|
*
|
||||||
|
* @return true if the credential was locked, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean hasLockedCredentials() {
|
||||||
|
AuthenticationCredentials auth = getAuthenticationCredentials();
|
||||||
|
return auth.getHashedAuthenticationToken().startsWith("!");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock device by invalidating authentication tokens.
|
* Lock device by invalidating authentication tokens.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue