diff --git a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml index f21eee21fc2574230bf956ef0deb16cfa60aa6c4..589d5d4817561d3aa9c37a59b7e2711f27b3e9d6 100644 --- a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml +++ b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml @@ -188,6 +188,7 @@ duniter.p2p.discovery.enable: false duniter.p2p.includes.pubkeys: [ "38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE" ] +#duniter.p2p.fullResyncAtStartup: true # # ---------------------------------- Duniter4j Mail module ----------------------- # diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java index caf1240db1574517eeaa70cb1028d713b48be99a..62e193b4c3ba886a955c055fc3ca2fac8529773e 100644 --- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java +++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java @@ -226,6 +226,10 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> { return settings.getAsBoolean("duniter.p2p.ws.enable", true); } + public boolean fullResyncAtStartup() { + return settings.getAsBoolean("duniter.p2p.fullResyncAtStartup", false); + } + public int getSynchroTimeOffset() { return settings.getAsInt("duniter.p2p.peerTimeOffset", 60*60/*=1hour*/); } @@ -298,6 +302,10 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> { return settings.getAsInt("duniter.document.time.maxFutureDelta", 600); // in seconds = 10min } + public boolean allowDocumentDeletionByAdmin() { + return settings.getAsBoolean("duniter.document.allowAdminDeletion", true); // + } + public String getWebSocketHost() { return settings.get("network.host", "locahost"); } diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/synchro/SynchroService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/synchro/SynchroService.java index 2639e01daa960b0d2ebbc5c2465b8d9eeb387571..5ecb5611df1c7c3d11d0e8bef4f25fc13c120a5c 100644 --- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/synchro/SynchroService.java +++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/synchro/SynchroService.java @@ -75,6 +75,7 @@ public class SynchroService extends AbstractService { private final SynchroExecutionDao synchroExecutionDao; private List<WebsocketClientEndpoint> wsClientEndpoints = Lists.newArrayList(); private List<SynchroAction> actions = Lists.newArrayList(); + private boolean forceFullResync = false; @Inject public SynchroService(Duniter4jClient client, @@ -124,7 +125,12 @@ public class SynchroService extends AbstractService { // If can be launched now: do it if (launchAtStartup) { + + forceFullResync = pluginSettings.fullResyncAtStartup(); + synchronize(); + + forceFullResync = false; } // Schedule next execution, to 5 min before each hour @@ -185,7 +191,8 @@ public class SynchroService extends AbstractService { } else { logger.info(String.format("[%s] [%s] Synchronization [OK] - no endpoint to synchronize", currencyId, peerApiFilter.name())); } - })); + } + )); } public SynchroResult synchronizePeer(final Peer peer, boolean enableSynchroWebsocket) { @@ -203,7 +210,7 @@ public class SynchroService extends AbstractService { // Get the last execution time (or 0 is never synchronized) // If not the first synchro, add a delay to last execution time // to avoid missing data because incorrect clock configuration - long lastExecutionTime = getLastExecutionTime(peer); + long lastExecutionTime = forceFullResync ? 0 : getLastExecutionTime(peer); if (logger.isDebugEnabled() && lastExecutionTime > 0) { logger.debug(String.format("[%s] [%s] Found last synchronization execution at {%s}. Will apply time offset of {-%s ms}", peer.getCurrency(), peer, DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM) @@ -213,6 +220,7 @@ public class SynchroService extends AbstractService { final long fromTime = lastExecutionTime > 0 ? lastExecutionTime - pluginSettings.getSynchroTimeOffset() : 0; + if (logger.isInfoEnabled()) { if (fromTime == 0) { logger.info(String.format("[%s] [%s] Synchronization {ALL}...", peer.getCurrency(), peer)); diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java index 3e880d3503677fae1bfded1dbcd754777b3c784c..22370ad4701b9175ade08ec97b1ff47d6783ee81 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java @@ -185,6 +185,9 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> { return delegate.getKeyringSecretKey(); } + public boolean allowDocumentDeletionByAdmin() { + return delegate.allowDocumentDeletionByAdmin(); + } public void addI18nBundleName(String bundleName) { delegate.addI18nBundleName(bundleName); @@ -210,6 +213,8 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> { } + + /* -- protected methods -- */ protected String getI18nBundleName() { diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java index 5d6447927780b7b9f852acf9efe880bb9d7fe181..15bff0acec758cc2c6c8900dc6cb04baf72b0386 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/HistoryService.java @@ -29,6 +29,7 @@ import org.duniter.core.client.model.elasticsearch.DeleteRecord; import org.duniter.core.exception.TechnicalException; import org.duniter.core.service.CryptoService; import org.duniter.elasticsearch.client.Duniter4jClient; +import org.duniter.elasticsearch.exception.AccessDeniedException; import org.duniter.elasticsearch.exception.NotFoundException; import org.duniter.elasticsearch.user.PluginSettings; import org.duniter.elasticsearch.user.model.Message; @@ -46,6 +47,7 @@ import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import java.io.IOException; +import java.util.Objects; /** * Created by Benoit on 30/03/2015. @@ -147,17 +149,33 @@ public class HistoryService extends AbstractService { throw new NotFoundException(String.format("Index [%s] not exists.", index)); } - // Message: check if deletion issuer is the message recipient - if (MessageService.INDEX.equals(index) && MessageService.INBOX_TYPE.equals(type)) { - client.checkSameDocumentField(index, type, id, Message.PROPERTY_RECIPIENT, issuer); - } - // Invitation: check if deletion issuer is the invitation recipient - else if (UserInvitationService.INDEX.equals(index)) { - client.checkSameDocumentField(index, type, id, Message.PROPERTY_RECIPIENT, issuer); + try { + // Message: check if deletion issuer is the message recipient + if (MessageService.INDEX.equals(index) && MessageService.INBOX_TYPE.equals(type)) { + client.checkSameDocumentField(index, type, id, Message.PROPERTY_RECIPIENT, issuer); + } + // Invitation: check if deletion issuer is the invitation recipient + else if (UserInvitationService.INDEX.equals(index)) { + + client.checkSameDocumentField(index, type, id, Message.PROPERTY_RECIPIENT, issuer); + + } + else { + // Check same document issuer + client.checkSameDocumentIssuer(index, type, id, issuer); + } } - else { - // Check same document issuer - client.checkSameDocumentIssuer(index, type, id, issuer); + catch(AccessDeniedException e) { + // Check if admin ask the deletion + // If deletion done by admin: continue if allow in settings + if (!pluginSettings.isRandomNodeKeypair() + && pluginSettings.allowDocumentDeletionByAdmin() + && Objects.equals(issuer, pluginSettings.getNodePubkey())) { + logger.warn(String.format("[%s/%s] Deletion forced by admin, on doc [%s]", index, type, id)); + } + else { + throw e; + } } // Check time is valid - fix #27