diff --git a/bubble-server/src/main/java/bubble/dao/account/AccountDAO.java b/bubble-server/src/main/java/bubble/dao/account/AccountDAO.java index be7f00cc..abdf402b 100644 --- a/bubble-server/src/main/java/bubble/dao/account/AccountDAO.java +++ b/bubble-server/src/main/java/bubble/dao/account/AccountDAO.java @@ -170,7 +170,7 @@ public class AccountDAO extends AbstractCRUDDAO implements SqlViewSearc } if (account.hasParent()) { - final AccountInitializer init = new AccountInitializer(account, this, policyDAO, messageDAO, selfNodeService); + final AccountInitializer init = new AccountInitializer(account, this, policyDAO, messageDAO, selfNodeService, configuration); account.setAccountInitializer(init); daemon(init); } diff --git a/bubble-server/src/main/java/bubble/dao/account/AccountInitializer.java b/bubble-server/src/main/java/bubble/dao/account/AccountInitializer.java index a9d7ad99..989f9301 100644 --- a/bubble-server/src/main/java/bubble/dao/account/AccountInitializer.java +++ b/bubble-server/src/main/java/bubble/dao/account/AccountInitializer.java @@ -6,14 +6,15 @@ package bubble.dao.account; import bubble.dao.account.message.AccountMessageDAO; import bubble.model.account.Account; +import bubble.model.account.AccountContact; import bubble.model.account.AccountPolicy; import bubble.model.account.message.AccountAction; import bubble.model.account.message.AccountMessage; import bubble.model.account.message.AccountMessageType; import bubble.model.account.message.ActionTarget; import bubble.model.cloud.BubbleNetwork; +import bubble.server.BubbleConfiguration; import bubble.service.boot.SelfNodeService; -import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.atomic.AtomicBoolean; @@ -23,32 +24,33 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.cobbzilla.util.daemon.ZillaRuntime.die; import static org.cobbzilla.util.system.Sleep.sleep; -@AllArgsConstructor @Slf4j +@Slf4j public class AccountInitializer implements Runnable { public static final int MAX_ACCOUNT_INIT_RETRIES = 3; public static final long COPY_WAIT_TIME = SECONDS.toMillis(2); public static final long SEND_MESSAGE_WAIT_TIME = SECONDS.toMillis(1); - private Account account; - private AccountDAO accountDAO; - private AccountPolicyDAO policyDAO; - private AccountMessageDAO messageDAO; - private SelfNodeService selfNodeService; + private final Account account; + private final AccountDAO accountDAO; + private final AccountPolicyDAO policyDAO; + private final AccountMessageDAO messageDAO; + private final SelfNodeService selfNodeService; + private final BubbleConfiguration configuration; - private AtomicBoolean ready = new AtomicBoolean(false); + private final AtomicBoolean ready = new AtomicBoolean(false); public boolean ready() { return ready.get(); } - private AtomicBoolean canSendAccountMessages = new AtomicBoolean(false); + private final AtomicBoolean canSendAccountMessages = new AtomicBoolean(false); public void setCanSendAccountMessages() { canSendAccountMessages.set(true); } - private AtomicBoolean abort = new AtomicBoolean(false); + private final AtomicBoolean abort = new AtomicBoolean(false); public void setAbort () { abort.set(true); } - private AtomicBoolean completed = new AtomicBoolean(false); + private final AtomicBoolean completed = new AtomicBoolean(false); public boolean completed () { return completed.get(); } - private AtomicReference error = new AtomicReference<>(); + private final AtomicReference error = new AtomicReference<>(); public Exception getError() { return error.get(); } public boolean hasError () { return getError() != null; } @@ -56,12 +58,14 @@ public class AccountInitializer implements Runnable { AccountDAO accountDAO, AccountPolicyDAO policyDAO, AccountMessageDAO messageDAO, - SelfNodeService selfNodeService) { + SelfNodeService selfNodeService, + BubbleConfiguration configuration) { this.account = account; this.accountDAO = accountDAO; this.policyDAO = policyDAO; this.messageDAO = messageDAO; this.selfNodeService = selfNodeService; + this.configuration = configuration; } @Override public void run() { @@ -88,7 +92,19 @@ public class AccountInitializer implements Runnable { } } if (!success) throw lastEx; - if (account.sendWelcomeEmail()) { + + if (selfNodeService.getThisNetwork().local() && !configuration.testMode()) { + // running locally, initial contact is always validated + final String accountUuid = account.getUuid(); + final AccountPolicy policy = policyDAO.findSingleByAccount(accountUuid); + final AccountContact contact = policy != null && policy.hasAccountContacts() ? policy.getAccountContacts()[0] : null; + if (contact == null) { + die("no contact found for welcome message: account="+accountUuid); + } else { + policyDAO.update(policy.verifyContact(contact.getUuid())); + } + + } else if (account.sendWelcomeEmail()) { final BubbleNetwork thisNetwork = selfNodeService.getThisNetwork(); final String accountUuid = account.getUuid(); final AccountPolicy policy = policyDAO.findSingleByAccount(accountUuid); diff --git a/bubble-server/src/main/java/bubble/resources/account/AuthResource.java b/bubble-server/src/main/java/bubble/resources/account/AuthResource.java index c05de6e9..90fca0ba 100644 --- a/bubble-server/src/main/java/bubble/resources/account/AuthResource.java +++ b/bubble-server/src/main/java/bubble/resources/account/AuthResource.java @@ -345,6 +345,12 @@ public class AuthResource { promoEx = e; } } + // When running locally and not in test mode, mark sole contact as verified + // It will be automatically verified in AccountInitializer. + if (configuration.getThisNetwork().local() && !configuration.testMode()) { + final AccountContact firstContact = account.getPolicy().getAccountContacts()[0]; + account.getPolicy().verifyContact(firstContact.getUuid()); + } account.getAccountInitializer().setCanSendAccountMessages(); return ok(newLoginSession(account .waitForAccountInit() diff --git a/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java b/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java index 178b5928..79226ddc 100644 --- a/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java +++ b/bubble-server/src/main/java/bubble/server/BubbleConfiguration.java @@ -86,6 +86,7 @@ public class BubbleConfiguration extends PgRestServerConfiguration public static final String TAG_BUBBLE_NODE = "bubbleNode"; public static final String TAG_NETWORK_UUID = "networkUuid"; public static final String TAG_PAYMENTS_ENABLED = "paymentsEnabled"; + public static final String TAG_LOCAL_NETWORK = "localNetwork"; public static final String TAG_ENTITY_CLASSES = "entityClasses"; public static final String TAG_LOCALES = "locales"; public static final String TAG_CLOUD_CONFIGS = "cloudConfigs"; @@ -363,6 +364,7 @@ public class BubbleConfiguration extends PgRestServerConfiguration {TAG_SAGE_LAUNCHER, thisNetwork == null || isSageLauncher()}, {TAG_BUBBLE_NODE, isSageLauncher() || thisNetwork == null ? null : thisNetwork.node()}, {TAG_PAYMENTS_ENABLED, cloudDAO.paymentsEnabled()}, + {TAG_LOCAL_NETWORK, thisNetwork == null || thisNetwork.local()}, {TAG_PROMO_CODE_POLICY, getPromoCodePolicy().name()}, {TAG_REQUIRE_SEND_METRICS, requireSendMetrics()}, {TAG_ENTITY_CLASSES, getSortedSimpleEntityClassMap()}, diff --git a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties index 2e5ef3ae..677ed7c8 100644 --- a/bubble-server/src/main/resources/META-INF/bubble/bubble.properties +++ b/bubble-server/src/main/resources/META-INF/bubble/bubble.properties @@ -1 +1 @@ -bubble.version=Adventure 1.4.15 +bubble.version=Adventure 1.4.16 diff --git a/bubble-web b/bubble-web index f1ddc152..0224c40d 160000 --- a/bubble-web +++ b/bubble-web @@ -1 +1 @@ -Subproject commit f1ddc1529f36879af5b312263a1d9e6207595d1e +Subproject commit 0224c40d4996e56f5e0809d7b5a1a1a8239b2078