Explorar el Código

speed up account creation, ensure necessary templates are created before returning account

tags/v0.1.6
Jonathan Cobb hace 5 años
padre
commit
c980adf1bd
Se han modificado 13 ficheros con 169 adiciones y 104 borrados
  1. +10
    -2
      bubble-server/src/main/java/bubble/ApiConstants.java
  2. +50
    -46
      bubble-server/src/main/java/bubble/dao/account/AccountDAO.java
  3. +14
    -3
      bubble-server/src/main/java/bubble/dao/account/AccountInitializer.java
  4. +31
    -1
      bubble-server/src/main/java/bubble/model/account/Account.java
  5. +1
    -1
      bubble-server/src/main/java/bubble/resources/account/AccountsResource.java
  6. +51
    -1
      bubble-server/src/main/java/bubble/resources/account/AuthResource.java
  7. +0
    -43
      bubble-server/src/main/java/bubble/resources/account/MeResource.java
  8. +5
    -4
      bubble-server/src/main/java/bubble/resources/notify/InboundNotifyResource.java
  9. +3
    -0
      bubble-server/src/main/java/bubble/service/cloud/GeoService.java
  10. +1
    -0
      bubble-server/src/main/resources/message_templates/server/en_US/pre_auth/ResourceMessages.properties
  11. +1
    -1
      bubble-web
  12. +1
    -1
      utils/cobbzilla-utils
  13. +1
    -1
      utils/cobbzilla-wizard

+ 10
- 2
bubble-server/src/main/java/bubble/ApiConstants.java Ver fichero

@@ -4,6 +4,7 @@ import bubble.model.cloud.BubbleNode;
import com.fasterxml.jackson.databind.JsonNode;
import com.warrenstrange.googleauth.GoogleAuthenticator;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.cobbzilla.util.io.FileUtil;
import org.glassfish.grizzly.http.server.Request;
@@ -24,8 +25,10 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.io.FileUtil.abs;
import static org.cobbzilla.util.io.StreamUtil.stream2string;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.util.network.NetworkUtil.*;
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx;

@Slf4j
public class ApiConstants {

@Getter(lazy=true) private static final String bubbleDefaultDomain = initDefaultDomain();
@@ -172,8 +175,13 @@ public class ApiConstants {
}

public static String getRemoteHost(Request req) {
final String remoteHost = req.getHeader("X-Forwarded-For");
return remoteHost == null ? req.getRemoteAddr() : remoteHost;
final String xff = req.getHeader("X-Forwarded-For");
final String remoteHost = xff == null ? req.getRemoteAddr() : xff;
if (isPublicIpv4(remoteHost)) return remoteHost;
final String publicIp = getFirstPublicIpv4();
if (publicIp != null) return publicIp;
final String externalIp = getExternalIp();
return isPublicIpv4(externalIp) ? externalIp : remoteHost;
}

public static String getUserAgent(ContainerRequest ctx) { return ctx.getHeaderString(USER_AGENT); }


+ 50
- 46
bubble-server/src/main/java/bubble/dao/account/AccountDAO.java Ver fichero

@@ -1,18 +1,18 @@
package bubble.dao.account;

import bubble.dao.account.message.AccountMessageDAO;
import bubble.dao.app.*;
import bubble.dao.cloud.AnsibleRoleDAO;
import bubble.dao.cloud.BubbleDomainDAO;
import bubble.dao.cloud.BubbleFootprintDAO;
import bubble.dao.cloud.CloudServiceDAO;
import bubble.dao.device.DeviceDAO;
import bubble.dao.app.*;
import bubble.model.account.*;
import bubble.model.app.*;
import bubble.model.cloud.BubbleDomain;
import bubble.model.cloud.BubbleNode;
import bubble.model.cloud.CloudCredentials;
import bubble.model.cloud.CloudService;
import bubble.model.app.*;
import bubble.server.BubbleConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.wizard.dao.AbstractCRUDDAO;
@@ -25,6 +25,7 @@ import javax.transaction.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import static bubble.ApiConstants.getRemoteHost;
import static bubble.model.account.AccountTemplate.copyTemplateObjects;
@@ -86,9 +87,10 @@ public class AccountDAO extends AbstractCRUDDAO<Account> {
deviceDAO.ensureSpareDevice(accountUuid, thisNode.getNetwork(), true);
}

// copy drivers, keep map of old uuid to new driver so we can map rules below
if (account.hasParent()) {
daemon(new AccountInitializer(this, account, messageDAO));
final AccountInitializer init = new AccountInitializer(account, this, messageDAO);
account.setAccountInitializer(init);
daemon(init);
}

return super.postCreate(account, context);
@@ -103,11 +105,53 @@ public class AccountDAO extends AbstractCRUDDAO<Account> {
return super.postUpdate(account, context);
}

public void copyTemplates(Account account) {
public void copyTemplates(Account account, AtomicBoolean ready) {
final String parent = account.getParent();
final Map<String, RuleDriver> drivers = new HashMap<>();
final String acct = account.getUuid();

final Map<String, CloudService> clouds = new HashMap<>();
copyTemplateObjects(acct, parent, cloudDAO, new AccountTemplate.CopyTemplate<>() {
@Override public CloudService preCreate(CloudService parentEntity, CloudService accountEntity) {
return accountEntity.setDelegated(parentEntity.getUuid())
.setCredentials(CloudCredentials.delegate(configuration.getThisNode(), configuration))
.setTemplate(false);
}
@Override public void postCreate(CloudService parentEntity, CloudService accountEntity) {
clouds.put(parentEntity.getUuid(), accountEntity);
}
});

copyTemplateObjects(acct, parent, footprintDAO);

//noinspection Convert2Diamond -- compilation breaks with <>
copyTemplateObjects(acct, parent, domainDAO, new AccountTemplate.CopyTemplate<BubbleDomain>() {
@Override public BubbleDomain preCreate(BubbleDomain parentEntity, BubbleDomain accountEntity) {
final CloudService publicDns = findDnsCloudService(parentEntity, parentEntity.getPublicDns());
if (publicDns == null) return null;
return accountEntity
.setDelegated(parentEntity.getUuid())
.setPublicDns(publicDns.getUuid());
}

public CloudService findDnsCloudService(BubbleDomain parentEntity, String cloudDnsUuid) {
final CloudService dns = clouds.get(cloudDnsUuid);
if (dns == null) {
log.error("DNS service "+ cloudDnsUuid +" could not be found for domain "+parentEntity.getUuid());
return null;
}
final CloudService acctPublicDns = cloudDAO.findByAccountAndName(acct, dns.getName());
if (acctPublicDns == null) {
log.error("DNS service not found under account "+acct+": "+dns.getName());
return null;
}
return dns;
}
});
ready.set(true);

copyTemplateObjects(acct, parent, roleDAO);

final Map<String, RuleDriver> drivers = new HashMap<>();
copyTemplateObjects(acct, parent, driverDAO, new AccountTemplate.CopyTemplate<>() {
@Override public void postCreate(RuleDriver parentEntity, RuleDriver accountEntity) {
drivers.put(parentEntity.getUuid(), accountEntity);
@@ -162,46 +206,6 @@ public class AccountDAO extends AbstractCRUDDAO<Account> {
}
});

final Map<String, CloudService> clouds = new HashMap<>();

copyTemplateObjects(acct, parent, cloudDAO, new AccountTemplate.CopyTemplate<>() {
@Override public CloudService preCreate(CloudService parentEntity, CloudService accountEntity) {
return accountEntity.setDelegated(parentEntity.getUuid())
.setCredentials(CloudCredentials.delegate(configuration.getThisNode(), configuration))
.setTemplate(false);
}
@Override public void postCreate(CloudService parentEntity, CloudService accountEntity) {
clouds.put(parentEntity.getUuid(), accountEntity);
}
});

copyTemplateObjects(acct, parent, roleDAO);
copyTemplateObjects(acct, parent, footprintDAO);

//noinspection Convert2Diamond -- compilation breaks with <>
copyTemplateObjects(acct, parent, domainDAO, new AccountTemplate.CopyTemplate<BubbleDomain>() {
@Override public BubbleDomain preCreate(BubbleDomain parentEntity, BubbleDomain accountEntity) {
final CloudService publicDns = findDnsCloudService(parentEntity, parentEntity.getPublicDns());
if (publicDns == null) return null;
return accountEntity
.setDelegated(parentEntity.getUuid())
.setPublicDns(publicDns.getUuid());
}

public CloudService findDnsCloudService(BubbleDomain parentEntity, String cloudDnsUuid) {
final CloudService dns = clouds.get(cloudDnsUuid);
if (dns == null) {
log.error("DNS service "+ cloudDnsUuid +" could not be found for domain "+parentEntity.getUuid());
return null;
}
final CloudService acctPublicDns = cloudDAO.findByAccountAndName(acct, dns.getName());
if (acctPublicDns == null) {
log.error("DNS service not found under account "+acct+": "+dns.getName());
return null;
}
return dns;
}
});
log.info("copyTemplates completed: "+acct);
}



+ 14
- 3
bubble-server/src/main/java/bubble/dao/account/AccountInitializer.java Ver fichero

@@ -9,6 +9,8 @@ import bubble.model.account.message.ActionTarget;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicBoolean;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.system.Sleep.sleep;
@@ -17,11 +19,20 @@ import static org.cobbzilla.util.system.Sleep.sleep;
public class AccountInitializer implements Runnable {

public static final int MAX_ACCOUNT_INIT_RETRIES = 3;
public static final long COPY_WAIT_TIME = SECONDS.toMillis(3);
public static final long COPY_WAIT_TIME = SECONDS.toMillis(2);

private AccountDAO accountDAO;
private Account account;
private AccountDAO accountDAO;
private AccountMessageDAO messageDAO;
private AtomicBoolean ready = new AtomicBoolean(false);

public AccountInitializer(Account account, AccountDAO accountDAO, AccountMessageDAO messageDAO) {
this.account = account;
this.accountDAO = accountDAO;
this.messageDAO = messageDAO;
}

public boolean ready() { return ready.get(); }

@Override public void run() {
try {
@@ -30,7 +41,7 @@ public class AccountInitializer implements Runnable {
for (int i=0; i<MAX_ACCOUNT_INIT_RETRIES; i++) {
try {
sleep(COPY_WAIT_TIME, "waiting before copyTemplates");
accountDAO.copyTemplates(account);
accountDAO.copyTemplates(account, ready);

if (account.hasPolicy() && account.getPolicy().hasAccountContacts()) {
messageDAO.sendVerifyRequest(account.getRemoteHost(), account, account.getPolicy().getAccountContacts()[0]);


+ 31
- 1
bubble-server/src/main/java/bubble/model/account/Account.java Ver fichero

@@ -1,5 +1,6 @@
package bubble.model.account;

import bubble.dao.account.AccountInitializer;
import bubble.model.app.AppData;
import bubble.model.app.BubbleApp;
import bubble.model.cloud.*;
@@ -10,6 +11,7 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ArrayUtil;
import org.cobbzilla.wizard.filters.auth.TokenPrincipal;
import org.cobbzilla.wizard.model.HashedPassword;
@@ -28,9 +30,15 @@ import javax.validation.constraints.Size;
import java.util.Arrays;
import java.util.List;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.now;
import static org.cobbzilla.util.reflect.ReflectionUtil.copy;
import static org.cobbzilla.util.system.Sleep.sleep;
import static org.cobbzilla.util.time.TimeUtil.formatDuration;
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENCRYPTED_STRING;
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_PAD;
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx;

@ECType(root=true) @ECTypeURIs(listFields={"name", "url", "description", "admin", "suspended"}, isDeleteDefined=false)
@ECTypeFields(list={"name", "url", "description", "admin", "suspended"})
@@ -45,7 +53,7 @@ import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_PAD;
@ECTypeChild(type=BubbleNode.class, backref="account"),
@ECTypeChild(type=SentNotification.class, backref="account")
})
@Entity @NoArgsConstructor @Accessors(chain=true)
@Entity @NoArgsConstructor @Accessors(chain=true) @Slf4j
public class Account extends IdentifiableBase implements TokenPrincipal {

public static final String[] UPDATE_FIELDS = {"url", "description", "autoUpdatePolicy"};
@@ -121,6 +129,28 @@ public class Account extends IdentifiableBase implements TokenPrincipal {
public boolean wantsAppUpdates() { return autoUpdatePolicy != null && autoUpdatePolicy.appUpdates(); }
public boolean wantsDataUpdates() { return autoUpdatePolicy != null && autoUpdatePolicy.dataUpdates(); }

public static final long INIT_WAIT_INTERVAL = MILLISECONDS.toMillis(250);
public static final long INIT_WAIT_TIMEOUT = SECONDS.toMillis(60);

@Transient @JsonIgnore @Getter @Setter private transient AccountInitializer accountInitializer;
public boolean hasAccountInitializer () { return accountInitializer != null; }

public Account waitForAccountInit () {
if (!hasAccountInitializer()) {
log.warn("waitForAccountInit: accountInitializer was not set");
return this;
}
final long start = now();
while (!accountInitializer.ready() && now() - start < INIT_WAIT_TIMEOUT) {
sleep(INIT_WAIT_INTERVAL, "postCreate: waiting for AccountInitializer.ready");
}
if (now() - start > INIT_WAIT_TIMEOUT && !accountInitializer.ready()) {
throw invalidEx("err.accountInit.timeout");
}
log.info("waitForAccountInit: ready in "+formatDuration(now() - start));
return this;
}

@Transient @Getter @Setter private transient String apiToken;

@Transient public String getToken() { return getApiToken(); }


+ 1
- 1
bubble-server/src/main/java/bubble/resources/account/AccountsResource.java Ver fichero

@@ -84,7 +84,7 @@ public class AccountsResource {
.setRemoteHost(getRemoteHost(req))
.setVerifyContact(true);
final Account created = accountDAO.newAccount(req, reg, parent);
return ok(created);
return ok(created.waitForAccountInit());
}

@GET @Path("/{id}"+EP_DOWNLOAD)


+ 51
- 1
bubble-server/src/main/java/bubble/resources/account/AuthResource.java Ver fichero

@@ -1,5 +1,6 @@
package bubble.resources.account;

import bubble.cloud.geoLocation.GeoLocation;
import bubble.dao.SessionDAO;
import bubble.dao.account.AccountDAO;
import bubble.dao.account.AccountPolicyDAO;
@@ -17,12 +18,15 @@ import bubble.service.account.StandardAccountMessageService;
import bubble.service.backup.RestoreService;
import bubble.service.boot.ActivationService;
import bubble.service.boot.SageHelloService;
import bubble.service.cloud.GeoService;
import bubble.service.notify.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.NameAndValue;
import org.cobbzilla.util.string.LocaleUtil;
import org.cobbzilla.wizard.auth.LoginRequest;
import org.cobbzilla.wizard.stream.FileSendableResource;
import org.cobbzilla.wizard.validation.ConstraintViolationBean;
import org.cobbzilla.wizard.validation.SimpleViolationException;
import org.cobbzilla.wizard.validation.ValidationResult;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.jersey.server.ContainerRequest;
@@ -34,7 +38,9 @@ import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static bubble.ApiConstants.*;
@@ -44,6 +50,7 @@ import static bubble.model.cloud.BubbleNetwork.TAG_PARENT_ACCOUNT;
import static bubble.model.cloud.notify.NotificationType.retrieve_backup;
import static bubble.server.BubbleServer.getRestoreKey;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.http.HttpHeaders.ACCEPT_LANGUAGE;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.daemon.ZillaRuntime.now;
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON;
@@ -66,6 +73,7 @@ public class AuthResource {
@Autowired private AccountMessageDAO accountMessageDAO;
@Autowired private StandardAccountMessageService messageService;
@Autowired private BubbleNodeDAO nodeDAO;
@Autowired private GeoService geoService;
@Autowired private BubbleConfiguration configuration;

@GET @Path(EP_CONFIGS)
@@ -181,7 +189,7 @@ public class AuthResource {
if (parent == null) return invalid("err.parent.notFound", "Parent account does not exist: "+parentUuid);

final Account account = accountDAO.newAccount(req, request, parent);
return ok(account.setToken(sessionDAO.create(account)));
return ok(account.waitForAccountInit().setToken(sessionDAO.create(account)));
}

@POST @Path(EP_LOGIN)
@@ -342,4 +350,46 @@ public class AuthResource {
return ok_empty();
}

@GET @Path("/detect/locale")
public Response detectLocale(@Context Request req,
@Context ContainerRequest ctx) {
final Map<String, String> locales = new HashMap<>();

final String langHeader = normalizeLangHeader(req);
if (langHeader != null) locales.put(ACCEPT_LANGUAGE, langHeader);

final String remoteHost = getRemoteHost(req);
try {
final Account caller = userPrincipal(ctx);
final GeoLocation loc = geoService.locate(caller.getUuid(), remoteHost);
if (loc != null) {
final List<String> found = LocaleUtil.getDefaultLocales(loc.getCountry());
for (int i=0; i<found.size(); i++) {
locales.put("geolocation_"+i, found.get(i));
}
}
} catch (SimpleViolationException e) {
return invalid(e);

} catch (Exception e) {
log.warn("detectLocale: "+e);
}
return ok(locales.values());
}

@GET @Path("/detect/timezone")
public Response detectTimezone(@Context Request req,
@Context ContainerRequest ctx) {
final String remoteHost = getRemoteHost(req);
try {
return ok(geoService.getTimeZone(optionalUserPrincipal(ctx), remoteHost));

} catch (SimpleViolationException e) {
return invalid(e);

} catch (Exception e) {
return invalid("err.timezone.unknown", e.getMessage());
}
}

}

+ 0
- 43
bubble-server/src/main/java/bubble/resources/account/MeResource.java Ver fichero

@@ -1,6 +1,5 @@
package bubble.resources.account;

import bubble.cloud.geoLocation.GeoLocation;
import bubble.dao.SessionDAO;
import bubble.dao.account.AccountDAO;
import bubble.dao.account.AccountPolicyDAO;
@@ -20,11 +19,9 @@ import bubble.resources.notify.SentNotificationsResource;
import bubble.server.BubbleConfiguration;
import bubble.service.account.StandardAccountMessageService;
import bubble.service.account.download.AccountDownloadService;
import bubble.service.cloud.GeoService;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.string.LocaleUtil;
import org.cobbzilla.wizard.auth.ChangePasswordRequest;
import org.cobbzilla.wizard.client.ApiClientBase;
import org.cobbzilla.wizard.client.script.ApiRunner;
@@ -41,12 +38,8 @@ import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static bubble.ApiConstants.*;
import static org.apache.http.HttpHeaders.ACCEPT_LANGUAGE;
import static org.cobbzilla.util.daemon.ZillaRuntime.errorString;
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON;
import static org.cobbzilla.util.http.HttpContentTypes.TEXT_PLAIN;
@@ -62,7 +55,6 @@ public class MeResource {
@Autowired private AccountDAO accountDAO;
@Autowired private AccountPolicyDAO policyDAO;
@Autowired private SessionDAO sessionDAO;
@Autowired private GeoService geoService;
@Autowired private AccountDownloadService downloadService;
@Autowired private BubbleConfiguration configuration;

@@ -76,41 +68,6 @@ public class MeResource {
}
}

@GET @Path("/detect/locale")
public Response detectLocale(@Context Request req,
@Context ContainerRequest ctx) {
final Map<String, String> locales = new HashMap<>();

final String langHeader = normalizeLangHeader(req);
if (langHeader != null) locales.put(ACCEPT_LANGUAGE, langHeader);

final String remoteHost = getRemoteHost(req);
try {
final Account caller = userPrincipal(ctx);
final GeoLocation loc = geoService.locate(caller.getUuid(), remoteHost);
if (loc != null) {
final List<String> found = LocaleUtil.getDefaultLocales(loc.getCountry());
for (int i=0; i<found.size(); i++) {
locales.put("geolocation_"+i, found.get(i));
}
}
} catch (Exception e) {
log.warn("detectLocale: "+e);
}
return ok(locales);
}

@GET @Path("/detect/timezone")
public Response detectTimezone(@Context Request req,
@Context ContainerRequest ctx) {
final String remoteHost = getRemoteHost(req);
try {
return ok(geoService.getTimeZone(userPrincipal(ctx), remoteHost));
} catch (Exception e) {
return invalid("err.timezone.unknown", e.getMessage());
}
}

@POST @Path(EP_CHANGE_PASSWORD)
public Response changePassword(@Context ContainerRequest ctx,
ChangePasswordRequest request) {


+ 5
- 4
bubble-server/src/main/java/bubble/resources/notify/InboundNotifyResource.java Ver fichero

@@ -13,13 +13,12 @@ import bubble.model.cloud.notify.ReceivedNotification;
import bubble.model.cloud.notify.SentNotification;
import bubble.notify.storage.StorageStreamRequest;
import bubble.server.BubbleConfiguration;
import bubble.service.notify.NotificationService;
import bubble.service.backup.RestoreService;
import bubble.service.cloud.StorageStreamService;
import bubble.service.notify.NotificationService;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.network.NetworkUtil;
import org.cobbzilla.util.security.RsaMessage;
import org.cobbzilla.util.string.StringUtil;
import org.glassfish.grizzly.http.server.Request;
@@ -42,6 +41,8 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON;
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_OCTET_STREAM;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.util.network.NetworkUtil.configuredIpsAndExternalIp;
import static org.cobbzilla.util.network.NetworkUtil.isLocalHost;
import static org.cobbzilla.util.string.StringUtil.truncate;
import static org.cobbzilla.util.time.TimeUtil.formatDuration;
import static org.cobbzilla.wizard.resources.ResourceUtil.*;
@@ -61,7 +62,7 @@ public class InboundNotifyResource {
@Autowired private StorageStreamService storageStreamService;
@Autowired private RestoreService restoreService;

@Getter(lazy=true) private final Set<String> localIps = NetworkUtil.configuredIps();
@Getter(lazy=true) private final Set<String> localIps = configuredIpsAndExternalIp();

@POST
public Response receiveNotification(@Context Request req,
@@ -150,7 +151,7 @@ public class InboundNotifyResource {
if (fromKey != null) {
if (!fromKey.getRemoteHost().equals(remoteHost)) {
// if request is from 127.0.0.1, check to see if fromKey is for a local address
if (remoteHost.equals("127.0.0.1") && getLocalIps().contains(fromKey.getRemoteHost())) {
if (isLocalHost(remoteHost) && getLocalIps().contains(fromKey.getRemoteHost())) {
log.debug("findFromKey: request from 127.0.0.1 is OK, key is local: "+fromKey.getRemoteHost()+ " (ips="+ StringUtil.toString(getLocalIps())+")");
} else {
log.warn("findFromKey: remoteHost for for node " + fromNodeUuid + " (key=" + fromKeyUuid + ", remoteHost=" + fromKey.getRemoteHost() + ") does not match request: " + remoteHost+ " (ips="+ StringUtil.toString(getLocalIps())+")");


+ 3
- 0
bubble-server/src/main/java/bubble/service/cloud/GeoService.java Ver fichero

@@ -8,6 +8,7 @@ import bubble.cloud.geoCode.GeoCodeResult;
import bubble.cloud.geoCode.GeoCodeServiceDriver;
import bubble.cloud.geoLocation.GeoLocation;
import bubble.cloud.geoTime.GeoTimeZone;
import bubble.dao.account.AccountDAO;
import bubble.dao.cloud.BubbleFootprintDAO;
import bubble.dao.cloud.CloudServiceDAO;
import bubble.model.account.Account;
@@ -37,6 +38,7 @@ public class GeoService {
// todo: move to config?
public static final int LOC_MAX_DISTANCE = 50000;

@Autowired private AccountDAO accountDAO;
@Autowired private CloudServiceDAO cloudDAO;
@Autowired private BubbleFootprintDAO footprintDAO;
@Autowired private BubbleConfiguration configuration;
@@ -112,6 +114,7 @@ public class GeoService {

public GeoTimeZone getTimeZone (Account account, String ip) {

if (account == null) account = accountDAO.findFirstAdmin();
final List<CloudService> geoServices = cloudDAO.findByAccountAndType(account.getUuid(), CloudServiceType.geoTime);
if (geoServices.isEmpty()) throw new SimpleViolationException("err.geoTimeService.notFound");
geoServices.sort(SORT_PRIORITY);


+ 1
- 0
bubble-server/src/main/resources/message_templates/server/en_US/pre_auth/ResourceMessages.properties Ver fichero

@@ -26,6 +26,7 @@ err.phone.invalid=SMS Phone is invalid
err.phone.length=SMS Phone is too long
err.country.invalid=Country is invalid
err.parent.notFound=Parent account does not exist
err.accountInit.timeout=Timeout initializing new account

# Login/Registration form
form_label_title_login=Login


+ 1
- 1
bubble-web

@@ -1 +1 @@
Subproject commit b500db5e9c4a0e621833e788dc4e6cf5fae5e2ee
Subproject commit 0cf7321e714801118c7ab13ca2202a68936c0dea

+ 1
- 1
utils/cobbzilla-utils

@@ -1 +1 @@
Subproject commit 862c6282b7ecdf9b1146f4ecb005cf38be1c4e86
Subproject commit 51b557f242ea52ed339ac6469adbc42b8873a3e9

+ 1
- 1
utils/cobbzilla-wizard

@@ -1 +1 @@
Subproject commit 86a153ecc2531008afab4e3bfed471f9d957dab7
Subproject commit 54c08985284f4f81dad3200b04e93384cbdffb12

Cargando…
Cancelar
Guardar