Commit 394c022f authored by Daniel Gultsch's avatar Daniel Gultsch
Browse files

apply google java format

parent e4a05b35
......@@ -4,11 +4,10 @@ import com.google.gson.GsonBuilder;
import de.gultsch.xmpp.addr.adapter.gson.JidDeserializer;
import de.gultsch.xmpp.addr.adapter.gson.JidSerializer;
import de.gultsch.xmpp.addr.adapter.sql2o.JidConverter;
import java.util.Map;
import org.sql2o.converters.Converter;
import rocks.xmpp.addr.Jid;
import java.util.Map;
public class Adapter {
public static void register(GsonBuilder gsonBuilder) {
......@@ -16,7 +15,6 @@ public class Adapter {
gsonBuilder.registerTypeAdapter(Jid.class, new JidSerializer());
}
public static void register(Map<Class, Converter> converters) {
final JidConverter jidConverter = new JidConverter();
converters.put(Jid.class, jidConverter);
......@@ -26,5 +24,4 @@ public class Adapter {
throw new AssertionError(e);
}
}
}
......@@ -4,14 +4,17 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import rocks.xmpp.addr.Jid;
import java.lang.reflect.Type;
import rocks.xmpp.addr.Jid;
public class JidDeserializer implements JsonDeserializer<Jid> {
public Jid deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
public Jid deserialize(
JsonElement jsonElement,
Type type,
JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException {
String jid = jsonElement.getAsString();
return Jid.ofEscaped(jid);
}
}
\ No newline at end of file
}
package de.gultsch.xmpp.addr.adapter.gson;
import com.google.gson.*;
import rocks.xmpp.addr.Jid;
import java.lang.reflect.Type;
import rocks.xmpp.addr.Jid;
public class JidSerializer implements JsonSerializer<Jid> {
public JsonElement serialize(Jid jid, Type type, JsonSerializationContext jsonSerializationContext) {
public JsonElement serialize(
Jid jid, Type type, JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(jid.toEscapedString());
}
}
......@@ -17,7 +17,8 @@ public class JidConverter implements Converter<Jid> {
throw new ConverterException("Unable to convert " + o.toString(), e);
}
} else {
throw new ConverterException("can not convert object of type " + o.getClass().getName() + " to Jid");
throw new ConverterException(
"can not convert object of type " + o.getClass().getName() + " to Jid");
}
}
......@@ -25,4 +26,4 @@ public class JidConverter implements Converter<Jid> {
public Object toDatabaseParam(Jid jid) {
return jid.asBareJid().toString();
}
}
\ No newline at end of file
}
......@@ -16,10 +16,14 @@
package im.quicksy.server;
import static spark.Spark.*;
import im.quicksy.server.configuration.Configuration;
import im.quicksy.server.controller.*;
import im.quicksy.server.xmpp.synchronization.Entry;
import im.quicksy.server.xmpp.synchronization.PhoneBook;
import java.io.FileNotFoundException;
import java.util.Properties;
import org.apache.commons.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -36,11 +40,6 @@ import spark.TemplateEngine;
import spark.template.freemarker.FreeMarkerEngine;
import sun.misc.Signal;
import java.io.FileNotFoundException;
import java.util.Properties;
import static spark.Spark.*;
public class Main {
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
......@@ -92,22 +91,23 @@ public class Main {
properties.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");
}
Signal.handle(new Signal("HUP"), signal -> {
try {
if (Configuration.reload()) {
LOGGER.info("reloaded config");
logConfigurationInfo();
} else {
LOGGER.error("unable to reload config. config file has moved");
}
} catch (RuntimeException e) {
LOGGER.error("Unable to load config file - " + e.getMessage());
}
});
Signal.handle(
new Signal("HUP"),
signal -> {
try {
if (Configuration.reload()) {
LOGGER.info("reloaded config");
logConfigurationInfo();
} else {
LOGGER.error("unable to reload config. config file has moved");
}
} catch (RuntimeException e) {
LOGGER.error("Unable to load config file - " + e.getMessage());
}
});
setupWebServer();
setupXmppComponent(commandLine.hasOption("x"));
}
private static void printHelp() {
......@@ -116,10 +116,18 @@ public class Main {
}
private static void logConfigurationInfo() {
LOGGER.info("validating phone numbers: " + Boolean.toString(Configuration.getInstance().isValidatePhoneNumbers()));
LOGGER.info("prevent registration when logged in with another device: " + Boolean.toString(Configuration.getInstance().isPreventRegistration()));
LOGGER.info("minimum client version: " + Configuration.getInstance().getMinVersion().toString());
LOGGER.info("treat accounts as inactive after: " + Configuration.getInstance().getAccountInactivity());
LOGGER.info(
"validating phone numbers: "
+ Boolean.toString(Configuration.getInstance().isValidatePhoneNumbers()));
LOGGER.info(
"prevent registration when logged in with another device: "
+ Boolean.toString(Configuration.getInstance().isPreventRegistration()));
LOGGER.info(
"minimum client version: "
+ Configuration.getInstance().getMinVersion().toString());
LOGGER.info(
"treat accounts as inactive after: "
+ Configuration.getInstance().getAccountInactivity());
}
private static void setupWebServer() {
......@@ -128,41 +136,55 @@ public class Main {
final TemplateEngine templateEngine = new FreeMarkerEngine();
path("/api", () -> {
get("/", BaseController.index);
path("/password", () -> {
before("", BaseController.versionCheck);
before("", PasswordController.throttleIp);
post("", PasswordController.setPassword);
});
path("/authentication", () -> {
before("/*", BaseController.versionCheck);
before("/*", AuthenticationController.throttleIp);
get("/:phoneNumber", AuthenticationController.getAuthentication);
});
});
path("enter", () -> {
get("/", EnterController.intro, templateEngine);
get("/send-jabber-verification/", EnterController.getSendJabberVerification, templateEngine);
post("/send-jabber-verification/", EnterController.postSendJabberVerification);
get("/verify-jabber/", EnterController.getVerifyJabber, templateEngine);
post("/verify-jabber/", EnterController.postVerifyJabber);
get("/make-payment/", EnterController.getMakePayment, templateEngine);
get("/voucher/", EnterController.getVoucher, templateEngine);
post("/voucher/", EnterController.postVoucher);
get("/send-number-verification/", EnterController.getSendSmsVerification, templateEngine);
post("/send-number-verification/", EnterController.postSendSmsVerification);
get("/verify-number/", EnterController.getVerifyNumber, templateEngine);
post("/verify-number/", EnterController.postVerifyNumber);
get("/finished/", EnterController.getFinished, templateEngine);
get("/reset/", EnterController.getReset);
get("/confirm-reset/", EnterController.getConfirmReset, templateEngine);
get("/confirm-delete/", EnterController.getConfirmDelete, templateEngine);
get("/delete/", EnterController.getDelete, templateEngine);
post("/checkout/", EnterController.postCheckout);
get("/paypal/:status/:uuid/", EnterController.getPayPalResult);
get("/payment-received/", EnterController.getPaymentReceived, templateEngine);
});
path(
"/api",
() -> {
get("/", BaseController.index);
path(
"/password",
() -> {
before("", BaseController.versionCheck);
before("", PasswordController.throttleIp);
post("", PasswordController.setPassword);
});
path(
"/authentication",
() -> {
before("/*", BaseController.versionCheck);
before("/*", AuthenticationController.throttleIp);
get("/:phoneNumber", AuthenticationController.getAuthentication);
});
});
path(
"enter",
() -> {
get("/", EnterController.intro, templateEngine);
get(
"/send-jabber-verification/",
EnterController.getSendJabberVerification,
templateEngine);
post("/send-jabber-verification/", EnterController.postSendJabberVerification);
get("/verify-jabber/", EnterController.getVerifyJabber, templateEngine);
post("/verify-jabber/", EnterController.postVerifyJabber);
get("/make-payment/", EnterController.getMakePayment, templateEngine);
get("/voucher/", EnterController.getVoucher, templateEngine);
post("/voucher/", EnterController.postVoucher);
get(
"/send-number-verification/",
EnterController.getSendSmsVerification,
templateEngine);
post("/send-number-verification/", EnterController.postSendSmsVerification);
get("/verify-number/", EnterController.getVerifyNumber, templateEngine);
post("/verify-number/", EnterController.postVerifyNumber);
get("/finished/", EnterController.getFinished, templateEngine);
get("/reset/", EnterController.getReset);
get("/confirm-reset/", EnterController.getConfirmReset, templateEngine);
get("/confirm-delete/", EnterController.getConfirmDelete, templateEngine);
get("/delete/", EnterController.getDelete, templateEngine);
post("/checkout/", EnterController.postCheckout);
get("/paypal/:status/:uuid/", EnterController.getPayPalResult);
get("/payment-received/", EnterController.getPaymentReceived, templateEngine);
});
}
private static void setupXmppComponent(final boolean debug) {
......@@ -173,21 +195,23 @@ public class Main {
builder.extensions(Extension.of(Entry.class, PhoneBook.class));
final ExternalComponent externalComponent = ExternalComponent.create(
Configuration.getInstance().getXmpp().getJid().toEscapedString(),
Configuration.getInstance().getXmpp().getSecret(),
builder.build(),
Configuration.getInstance().getXmpp().getHost(),
Configuration.getInstance().getXmpp().getPort()
);
final ExternalComponent externalComponent =
ExternalComponent.create(
Configuration.getInstance().getXmpp().getJid().toEscapedString(),
Configuration.getInstance().getXmpp().getSecret(),
builder.build(),
Configuration.getInstance().getXmpp().getHost(),
Configuration.getInstance().getXmpp().getPort());
ServiceDiscoveryManager serviceDiscoveryManager = externalComponent.getManager(ServiceDiscoveryManager.class);
ServiceDiscoveryManager serviceDiscoveryManager =
externalComponent.getManager(ServiceDiscoveryManager.class);
serviceDiscoveryManager.addFeature(PhoneBook.NAMESPACE);
serviceDiscoveryManager.addIdentity(Identity.storeGeneric());
externalComponent.disableFeature(Muc.NAMESPACE);
externalComponent.disableFeature(Socks5ByteStream.NAMESPACE);
externalComponent.addIQHandler(PhoneBook.class, SynchronizationController.synchronize, true);
externalComponent.addIQHandler(
PhoneBook.class, SynchronizationController.synchronize, true);
connectAndKeepRetrying(externalComponent);
}
......@@ -204,5 +228,4 @@ public class Main {
Utils.sleep(RETRY_INTERVAL);
}
}
}
......@@ -31,6 +31,10 @@ public class Utils {
}
public static Jid jidOf(Phonenumber.PhoneNumber phoneNumber) {
return Jid.of(PhoneNumberUtil.getInstance().format(phoneNumber,PhoneNumberUtil.PhoneNumberFormat.E164), Configuration.getInstance().getDomain(),null);
return Jid.of(
PhoneNumberUtil.getInstance()
.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164),
Configuration.getInstance().getDomain(),
null);
}
}
......@@ -16,7 +16,6 @@
package im.quicksy.server.configuration;
import com.github.zafarkhaja.semver.Version;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
......@@ -26,14 +25,13 @@ import de.gultsch.xmpp.addr.adapter.Adapter;
import im.quicksy.server.json.DurationDeserializer;
import im.quicksy.server.json.PatternDeserializer;
import im.quicksy.server.json.VersionDeserializer;
import rocks.xmpp.addr.Jid;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.time.Duration;
import java.util.*;
import java.util.regex.Pattern;
import rocks.xmpp.addr.Jid;
public class Configuration {
......@@ -54,13 +52,12 @@ public class Configuration {
private boolean validatePhoneNumbers = true;
private boolean preventRegistration = true;
private Configuration() {
private Configuration() {}
}
public synchronized static void setFilename(String filename) throws FileNotFoundException {
public static synchronized void setFilename(String filename) throws FileNotFoundException {
if (INSTANCE != null) {
throw new IllegalStateException("Unable to set filename after instance has been created");
throw new IllegalStateException(
"Unable to set filename after instance has been created");
}
Configuration.FILE = new File(filename);
if (!Configuration.FILE.exists()) {
......@@ -68,7 +65,7 @@ public class Configuration {
}
}
public synchronized static Configuration getInstance() {
public static synchronized Configuration getInstance() {
if (INSTANCE == null) {
INSTANCE = load();
}
......@@ -93,7 +90,7 @@ public class Configuration {
}
}
public synchronized static boolean reload() {
public static synchronized boolean reload() {
if (Configuration.FILE.exists()) {
final Configuration newConfig = load();
if (!newConfig.check()) {
......@@ -107,7 +104,15 @@ public class Configuration {
}
public boolean check() {
return domain != null && minVersion != null && web != null && xmpp != null && xmpp.check() && db != null && db.size() == 2 && payPal != null && payPal.check();
return domain != null
&& minVersion != null
&& web != null
&& xmpp != null
&& xmpp.check()
&& db != null
&& db.size() == 2
&& payPal != null
&& payPal.check();
}
public Duration getAccountInactivity() {
......@@ -131,7 +136,10 @@ public class Configuration {
}
public DatabaseConfigurationBundle getDatabaseConfigurationBundle() {
return new DatabaseConfigurationBundle.Builder().setEjabberdConfiguration(db.get("ejabberd")).setQuicksyConfiguration(db.get("quicksy")).build();
return new DatabaseConfigurationBundle.Builder()
.setEjabberdConfiguration(db.get("ejabberd"))
.setQuicksyConfiguration(db.get("quicksy"))
.build();
}
public Optional<String> getCimAuthToken() {
......@@ -220,7 +228,6 @@ public class Configuration {
}
}
public static class ProviderConfiguration {
private Map<String, String> parameter;
private List<Integer> deny;
......
......@@ -23,9 +23,7 @@ public class DatabaseConfiguration {
private String password;
private int poolSize = 1;
private DatabaseConfiguration() {
}
private DatabaseConfiguration() {}
public String getUsername() {
return username;
......@@ -66,4 +64,4 @@ public class DatabaseConfiguration {
return configuration;
}
}
}
\ No newline at end of file
}
......@@ -21,9 +21,7 @@ public class DatabaseConfigurationBundle {
private DatabaseConfiguration ejabberd;
private DatabaseConfiguration quicksy;
private DatabaseConfigurationBundle() {
}
private DatabaseConfigurationBundle() {}
public DatabaseConfiguration getEjabberdConfiguration() {
return ejabberd;
......@@ -33,7 +31,6 @@ public class DatabaseConfigurationBundle {
return quicksy;
}
public static class Builder {
private final DatabaseConfigurationBundle bundle = new DatabaseConfigurationBundle();
......@@ -51,6 +48,5 @@ public class DatabaseConfigurationBundle {
public DatabaseConfigurationBundle build() {
return bundle;
}
}
}
......@@ -16,11 +16,13 @@
package im.quicksy.server.controller;
import static spark.Spark.halt;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import im.quicksy.server.configuration.Configuration;
import im.quicksy.server.Utils;
import im.quicksy.server.configuration.Configuration;
import im.quicksy.server.ejabberd.MyEjabberdApi;
import im.quicksy.server.pojo.Device;
import im.quicksy.server.throttle.RateLimiter;
......@@ -28,19 +30,16 @@ import im.quicksy.server.throttle.Strategy;
import im.quicksy.server.verification.RequestFailedException;
import im.quicksy.server.verification.TwilioVerificationProvider;
import im.quicksy.server.verification.VerificationProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rocks.xmpp.addr.Jid;
import spark.Filter;
import spark.Route;
import java.net.InetAddress;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import static spark.Spark.halt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rocks.xmpp.addr.Jid;
import spark.Filter;
import spark.Route;
public class AuthenticationController extends BaseController {
......@@ -48,85 +47,100 @@ public class AuthenticationController extends BaseController {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationController.class);
private static final RateLimiter<InetAddress> PER_IP_RATE_LIMITER = RateLimiter.of(
Strategy.of(Duration.ofMinutes(5), 5),
Strategy.of(Duration.ofDays(1), 100)
);
private static final RateLimiter<Phonenumber.PhoneNumber> PER_PHONE_NUMBER_LIMITER = RateLimiter.of(
Strategy.of(Duration.ofMinutes(2), 1),
Strategy.of(Duration.ofHours(8), 2)
);
private static final RateLimiter<Device> PER_DEVICE_LIMITER = RateLimiter.of(
Strategy.of(Duration.ofDays(1), 3)
);
public static Route getAuthentication = (request, response) -> {
final String userSuppliedPhoneNumber = request.params("phoneNumber");
final String installationId = request.headers("Installation-Id");
final String userSuppliedLanguage = request.headers("Accept-Language");
if (!E164_PATTERN.matcher(userSuppliedPhoneNumber).matches()) {
return halt(400, "phone number is not formatted to E164");
}
if (installationId == null || !UUID_PATTERN.matcher(installationId).matches() || userSuppliedLanguage == null) {
return halt(400, "Missing installation id");
}
final Phonenumber.PhoneNumber phoneNumber;
try {
phoneNumber = PhoneNumberUtil.getInstance().parse(userSuppliedPhoneNumber, "DE");
} catch (NumberParseException e) {
return halt(400, "Unable to parse phone number");
}
if (Configuration.getInstance().isValidatePhoneNumbers() && !PhoneNumberUtil.getInstance().isValidNumber(phoneNumber)) {
LOGGER.info("libphonenumber reported " + phoneNumber + " as invalid");
return halt(400);
}
final Jid jid = Utils.jidOf(phoneNumber);
if (Configuration.getInstance().isPreventRegistration() && MyEjabberdApi.getInstance().getUserResources(jid.getEscapedLocal(), jid.getDomain()).size() > 0) {
return halt(409);
}
try {
PER_PHONE_NUMBER_LIMITER.attempt(phoneNumber);
PER_DEVICE_LIMITER.attempt(new Device(installationId));
} catch (RateLimiter.RetryInException e) {
response.header("Retry-After", String.valueOf(e.getInterval().getSeconds()));
LOGGER.info(e.getMessage());
return halt(429, e.getMessage());
}
final String language;
if (AVAILABLE_LANGUAGES.contains(userSuppliedLanguage.toLowerCase())) {
language = userSuppliedLanguage.toLowerCase();
} else {
language = null;
}
try {
VERIFICATION_PROVIDER.request(phoneNumber, VerificationProvider.Method.SMS, language);
} catch (RequestFailedException e) {
if (e.getCode() == TwilioVerificationProvider.PHONE_NUMBER_IS_INVALID) {
LOGGER.info("verification provider said " + phoneNumber + " is invalid");
return halt(400);
}
LOGGER.warn("unable to send SMS verification message to " + phoneNumber + " (" + e.getMessage() + ", code=" + e.getCode() + ")");
halt(500);
}
return "";
};
public static Filter throttleIp = (request, response) -> {
try {
PER_IP_RATE_LIMITER.attempt(getClientIp(request));
} catch (RateLimiter.RetryInException e) {
LOGGER.info(e.getMessage());
response.header("Retry-After", String.valueOf(e.getInterval().getSeconds()));
halt(429, e.getMessage());
}
};
private static final RateLimiter<InetAddress> PER_IP_RATE_LIMITER =
RateLimiter.of(
Strategy.of(Duration.ofMinutes(5), 5), Strategy.of(Duration.ofDays(1), 100));
private static final RateLimiter<Phonenumber.PhoneNumber> PER_PHONE_NUMBER_LIMITER =
RateLimiter.of(
Strategy.of(Duration.ofMinutes(2), 1), Strategy.of(Duration.ofHours(8), 2));
private static final RateLimiter<Device> PER_DEVICE_LIMITER =
RateLimiter.of(Strategy.of(Duration.ofDays(1), 3));
public static Route getAuthentication =
(request, response) -> {