Use Google's libphonenumber to perform more robust phone number validation and to convert all phone numbers to E164 before storing them. Closes #45
This commit is contained in:
parent
628c8d656b
commit
5f322824ac
5
pom.xml
5
pom.xml
@ -101,6 +101,11 @@
|
|||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.7</version>
|
<version>2.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.libphonenumber</groupId>
|
||||||
|
<artifactId>libphonenumber</artifactId>
|
||||||
|
<version>7.4.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Mongo -->
|
<!-- Mongo -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -7,6 +7,7 @@ import fr.javatic.mongo.jacksonCodec.objectId.Id;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.frozenorb.apiv3.APIv3;
|
import net.frozenorb.apiv3.APIv3;
|
||||||
|
import net.frozenorb.apiv3.util.PhoneUtils;
|
||||||
import net.frozenorb.apiv3.util.SyncUtils;
|
import net.frozenorb.apiv3.util.SyncUtils;
|
||||||
import net.frozenorb.apiv3.util.ZangUtils;
|
import net.frozenorb.apiv3.util.ZangUtils;
|
||||||
import net.frozenorb.apiv3.zang.ZangResult;
|
import net.frozenorb.apiv3.zang.ZangResult;
|
||||||
@ -31,32 +32,50 @@ public final class PhoneIntel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void findById(String id, SingleResultCallback<PhoneIntel> callback) {
|
public static void findById(String id, SingleResultCallback<PhoneIntel> callback) {
|
||||||
phoneIntelCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
|
String e164Phone = PhoneUtils.toE164(id);
|
||||||
|
|
||||||
|
if (e164Phone == null) {
|
||||||
|
callback.onResult(null, null);
|
||||||
|
} else {
|
||||||
|
phoneIntelCollection.find(new Document("_id", id)).first(SyncUtils.vertxWrap(callback));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void findOrCreateById(String id, SingleResultCallback<PhoneIntel> callback) {
|
public static void findOrCreateById(String id, SingleResultCallback<PhoneIntel> callback) {
|
||||||
findById(id, (existingPhoneIntel, error) -> {
|
String e164Phone = PhoneUtils.toE164(id);
|
||||||
|
|
||||||
|
if (e164Phone == null) {
|
||||||
|
callback.onResult(null, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
findById(e164Phone, (existingPhoneIntel, error) -> {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
callback.onResult(null, error);
|
callback.onResult(null, error);
|
||||||
} else if (existingPhoneIntel != null) {
|
return;
|
||||||
callback.onResult(existingPhoneIntel, null);
|
|
||||||
} else {
|
|
||||||
ZangUtils.getCarrierInfo(id, (zangResult, error2) -> {
|
|
||||||
if (error2 != null) {
|
|
||||||
callback.onResult(null, error2);
|
|
||||||
} else {
|
|
||||||
PhoneIntel newPhoneIntel = new PhoneIntel(id, zangResult);
|
|
||||||
|
|
||||||
phoneIntelCollection.insertOne(newPhoneIntel, SyncUtils.vertxWrap((ignored, error3) -> {
|
|
||||||
if (error3 != null) {
|
|
||||||
callback.onResult(null, error3);
|
|
||||||
} else {
|
|
||||||
callback.onResult(newPhoneIntel, null);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (existingPhoneIntel != null) {
|
||||||
|
callback.onResult(existingPhoneIntel, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZangUtils.getCarrierInfo(e164Phone, (zangResult, error2) -> {
|
||||||
|
if (error2 != null) {
|
||||||
|
callback.onResult(null, error2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhoneIntel newPhoneIntel = new PhoneIntel(e164Phone, zangResult);
|
||||||
|
|
||||||
|
phoneIntelCollection.insertOne(newPhoneIntel, SyncUtils.vertxWrap((ignored, error3) -> {
|
||||||
|
if (error3 != null) {
|
||||||
|
callback.onResult(null, error3);
|
||||||
|
} else {
|
||||||
|
callback.onResult(newPhoneIntel, null);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,10 +117,16 @@ public final class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void findByPhone(String phoneNumber, SingleResultCallback<User> callback) {
|
public static void findByPhone(String phoneNumber, SingleResultCallback<User> callback) {
|
||||||
usersCollection.find(new Document("$or", ImmutableList.of(
|
String e164Phone = PhoneUtils.toE164(phoneNumber);
|
||||||
new Document("phone", phoneNumber),
|
|
||||||
new Document("pendingPhone", phoneNumber)
|
if (e164Phone == null) {
|
||||||
))).first(SyncUtils.vertxWrap(callback));
|
callback.onResult(null, null);
|
||||||
|
} else {
|
||||||
|
usersCollection.find(new Document("$or", ImmutableList.of(
|
||||||
|
new Document("phone", phoneNumber),
|
||||||
|
new Document("pendingPhone", phoneNumber)
|
||||||
|
))).first(SyncUtils.vertxWrap(callback));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void findByEmail(String email, SingleResultCallback<User> callback) {
|
public static void findByEmail(String email, SingleResultCallback<User> callback) {
|
||||||
@ -536,7 +542,11 @@ public final class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startPhoneRegistration(String phoneNumber) {
|
public void startPhoneRegistration(String phoneNumber) {
|
||||||
this.pendingPhone = phoneNumber;
|
String e164Phone = PhoneUtils.toE164(phoneNumber);
|
||||||
|
|
||||||
|
if (e164Phone == null) return;
|
||||||
|
|
||||||
|
this.pendingPhone = e164Phone;
|
||||||
this.pendingPhoneToken = String.valueOf(new Random().nextInt(999999 - 100000) + 100000);
|
this.pendingPhoneToken = String.valueOf(new Random().nextInt(999999 - 100000) + 100000);
|
||||||
this.pendingPhoneTokenSetAt = Instant.now();
|
this.pendingPhoneTokenSetAt = Instant.now();
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,31 @@
|
|||||||
package net.frozenorb.apiv3.util;
|
package net.frozenorb.apiv3.util;
|
||||||
|
|
||||||
|
import com.google.i18n.phonenumbers.NumberParseException;
|
||||||
|
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||||
|
import com.google.i18n.phonenumbers.Phonenumber;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class PhoneUtils {
|
public class PhoneUtils {
|
||||||
|
|
||||||
private static final Pattern VALID_PHONE_PATTERN = Pattern.compile(
|
public static final String DEFAULT_COUNTRY_CODE = "US";
|
||||||
"^\\+?[1-9]\\d{1,14}$",
|
private static final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
|
||||||
Pattern.CASE_INSENSITIVE
|
|
||||||
);
|
|
||||||
|
|
||||||
public static boolean isValidPhone(String phoneNumber) {
|
public static boolean isValidPhone(String phoneNumber) {
|
||||||
return phoneNumber != null && VALID_PHONE_PATTERN.matcher(phoneNumber).matches();
|
try {
|
||||||
|
return phoneNumber != null && phoneUtil.isValidNumber(phoneUtil.parse(phoneNumber, DEFAULT_COUNTRY_CODE));
|
||||||
|
} catch (NumberParseException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toE164(String phoneNumber) {
|
||||||
|
try {
|
||||||
|
Phonenumber.PhoneNumber number = phoneUtil.parse(phoneNumber, DEFAULT_COUNTRY_CODE);
|
||||||
|
return phoneUtil.format(number, PhoneNumberUtil.PhoneNumberFormat.E164);
|
||||||
|
} catch (NumberParseException ex) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user