From 4347d54a4b15c9311fa839f48fcad4e3ac297981 Mon Sep 17 00:00:00 2001 From: blavenie <benoit.lavenier@e-is.pro> Date: Wed, 18 Oct 2017 16:45:06 +0200 Subject: [PATCH] [enh] Allow node admin to remove some data --- .../src/test/es-home/config/elasticsearch.yml | 1 + .../duniter/elasticsearch/PluginSettings.java | 8 ++++ .../elasticsearch/synchro/SynchroService.java | 12 +++++- .../elasticsearch/user/PluginSettings.java | 5 +++ .../user/service/HistoryService.java | 38 ++++++++++++++----- 5 files changed, 52 insertions(+), 12 deletions(-) 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 f21eee21..589d5d48 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 caf1240d..62e193b4 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 2639e01d..5ecb5611 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 3e880d35..22370ad4 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 5d644792..15bff0ac 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 -- GitLab