From 35d9b442866f4001b87b19eb225d84280ded758e Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Mon, 9 Jan 2017 15:52:14 +0100
Subject: [PATCH]  - User Event: do not propagate event updates, if just a
 "mark as read" update  - Security: fix security rule for /_read URL  - Add
 missing i18n resource files (in gchange plugin)

---
 .../src/license/THIRD-PARTY.properties        | 22 +++++++++++++++
 .../src/license/THIRD-PARTY.properties        | 20 +++++++++++++
 .../websocket/WebsocketClientEndpoint.java    |  2 +-
 .../src/license/THIRD-PARTY.properties        | 26 +++++++++++++++++
 .../main/assembly/config/elasticsearch.yml    |  7 ++++-
 .../src/test/es-home/config/elasticsearch.yml |  5 ++--
 .../AbstractRestPostMarkAsReadAction.java     |  2 +-
 .../service/AbstractSynchroService.java       |  4 +--
 .../duniter4j-es-gchange_en_GB.properties     | 12 ++++++++
 .../duniter4j-es-gchange_fr_FR.properties     | 12 ++++++++
 .../user/RestUserEventMarkAsReadAction.java   |  4 +--
 .../user/service/UserEventService.java        | 28 ++++++++++++++++---
 12 files changed, 130 insertions(+), 14 deletions(-)
 create mode 100644 duniter4j-core-client/src/license/THIRD-PARTY.properties
 create mode 100644 duniter4j-core-shared/src/license/THIRD-PARTY.properties
 create mode 100644 duniter4j-es-assembly/src/license/THIRD-PARTY.properties
 create mode 100644 duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_en_GB.properties
 create mode 100644 duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_fr_FR.properties

diff --git a/duniter4j-core-client/src/license/THIRD-PARTY.properties b/duniter4j-core-client/src/license/THIRD-PARTY.properties
new file mode 100644
index 00000000..2258c131
--- /dev/null
+++ b/duniter4j-core-client/src/license/THIRD-PARTY.properties
@@ -0,0 +1,22 @@
+# Generated by org.codehaus.mojo.license.AddThirdPartyMojo
+#-------------------------------------------------------------------------------
+# Already used licenses in project :
+# - BSD License
+# - CDDL+GPL
+# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+# - Dual license consisting of the CDDL v1.1 and GPL v2
+# - Eclipse Public License 1.0
+# - General Public License (GPL) v3
+# - Indiana University Extreme! Lab Software License, vesion 1.1.1
+# - Lesser General Public License (LGPL) v 3.0
+# - Lesser General Public License (LPGL)
+# - Lesser General Public License (LPGL) v 2.1
+# - MIT License
+# - New BSD License
+# - The Apache Software License, Version 2.0
+#-------------------------------------------------------------------------------
+# Please fill the missing licenses for dependencies :
+#
+#
+#Wed Nov 16 11:35:31 CET 2016
+commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0
diff --git a/duniter4j-core-shared/src/license/THIRD-PARTY.properties b/duniter4j-core-shared/src/license/THIRD-PARTY.properties
new file mode 100644
index 00000000..7a2eb6f8
--- /dev/null
+++ b/duniter4j-core-shared/src/license/THIRD-PARTY.properties
@@ -0,0 +1,20 @@
+# Generated by org.codehaus.mojo.license.AddThirdPartyMojo
+#-------------------------------------------------------------------------------
+# Already used licenses in project :
+# - BSD License
+# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+# - Dual license consisting of the CDDL v1.1 and GPL v2
+# - Eclipse Public License 1.0
+# - Indiana University Extreme! Lab Software License, vesion 1.1.1
+# - Lesser General Public License (LGPL) v 3.0
+# - Lesser General Public License (LPGL)
+# - Lesser General Public License (LPGL) v 2.1
+# - MIT License
+# - New BSD License
+# - The Apache Software License, Version 2.0
+#-------------------------------------------------------------------------------
+# Please fill the missing licenses for dependencies :
+#
+#
+#Wed Nov 16 11:35:28 CET 2016
+commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0
diff --git a/duniter4j-core-shared/src/main/java/org/duniter/core/util/websocket/WebsocketClientEndpoint.java b/duniter4j-core-shared/src/main/java/org/duniter/core/util/websocket/WebsocketClientEndpoint.java
index 27733427..3f2bea6e 100644
--- a/duniter4j-core-shared/src/main/java/org/duniter/core/util/websocket/WebsocketClientEndpoint.java
+++ b/duniter4j-core-shared/src/main/java/org/duniter/core/util/websocket/WebsocketClientEndpoint.java
@@ -195,7 +195,7 @@ public class WebsocketClientEndpoint implements Closeable {
             } catch (Exception e) {
                 notifyConnectionError(e);
                 if (!this.autoReconnect) throw new TechnicalException(e);
-                log.warn(String.format("[%s] Unable to connect. Retrying in 10s...", endpointURI.toString()));
+                log.warn(String.format("[%s] Unable to connect [%s]. Retrying in 10s...", endpointURI.toString(), e.getMessage()));
             }
 
             // wait 10s, then try again
diff --git a/duniter4j-es-assembly/src/license/THIRD-PARTY.properties b/duniter4j-es-assembly/src/license/THIRD-PARTY.properties
new file mode 100644
index 00000000..8610ec5b
--- /dev/null
+++ b/duniter4j-es-assembly/src/license/THIRD-PARTY.properties
@@ -0,0 +1,26 @@
+# Generated by org.codehaus.mojo.license.AddThirdPartyMojo
+#-------------------------------------------------------------------------------
+# Already used licenses in project :
+# - ASL, version 2
+# - Apache License 2.0
+# - Apache License Version 2.0
+# - BSD License
+# - CC0 1.0 Universal
+# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+# - Eclipse Public License 1.0
+# - General Public License (GPL) v3
+# - Indiana University Extreme! Lab Software License, vesion 1.1.1
+# - LGPL, version 2.1
+# - Lesser General Public License (LGPL) v 3.0
+# - Lesser General Public License (LPGL)
+# - Lesser General Public License (LPGL) v 2.1
+# - MIT License
+# - New BSD License
+# - Public Domain, per Creative Commons CC0
+# - The Apache Software License, Version 2.0
+#-------------------------------------------------------------------------------
+# Please fill the missing licenses for dependencies :
+#
+#
+#Tue Jan 05 15:24:57 CET 2016
+commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0
diff --git a/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml b/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
index f63204e1..ad6f799d 100644
--- a/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
+++ b/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
@@ -114,7 +114,7 @@ security.manager.enabled: false
 # Reset and reload all Duniter4j data at startup - DO SET to true in production
 #
 # duniter.indices.reload: true
-#
+#:
 # Default string analyzer
 #
 duniter.string.analyzer: french
@@ -130,6 +130,11 @@ duniter.port: 9330
 #
 # ---------------------------------- Duniter4j security -------------------------
 #
+# Allow admin actions
+#
+#duniter.keyring.salt:
+#duniter.keyring.password:
+#
 # Enable security, to disable HTTP access to the default ES admin API
 #
 duniter.security.enable: true
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 8e0079e2..cfc87eed 100644
--- a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
+++ b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
@@ -128,7 +128,8 @@ duniter.blockchain.sync.enable: true
 #
 #duniter.host: cgeek.fr
 #duniter.port: 9330
-duniter.host: test-net.duniter.fr
+#duniter.host: test-net.duniter.fr
+duniter.host: 192.168.0.5
 duniter.port: 9201
 #duniter.host: 192.168.0.28
 #duniter.port: 21378
@@ -141,7 +142,7 @@ duniter.keyring.password: def
 # Enable security, to disable HTTP access to the default ES admin API
 #
 #duniter.security.enable: false
-duniter.security.enable: false
+duniter.security.enable: true
 #
 # Security token prefix (default: 'duniter-')
 #
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/AbstractRestPostMarkAsReadAction.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/AbstractRestPostMarkAsReadAction.java
index 7be26a52..122f1120 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/AbstractRestPostMarkAsReadAction.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/AbstractRestPostMarkAsReadAction.java
@@ -50,7 +50,7 @@ public abstract class AbstractRestPostMarkAsReadAction extends BaseRestHandler {
         controller.registerHandler(POST,
                 String.format("/%s/%s/{id}/_read", indexName, typeName),
                 this);
-        securityController.allowIndexType(POST, indexName, typeName);
+        securityController.allow(POST, String.format("/%s/%s/[^/]+/_read", indexName, typeName));
         log = ESLoggerFactory.getLogger(String.format("[%s]", indexName));
         this.updater = updater;
     }
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java
index 4a82e385..5ebf469a 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractSynchroService.java
@@ -189,8 +189,8 @@ public abstract class AbstractSynchroService extends AbstractService {
 
         node = node.get("hits");
         int total = node == null ? 0 : node.get("total").asInt(0);
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("[%s] [%s/%s] total to update: %s", peer, toIndex, toType, total));
+        if (logger.isDebugEnabled() && offset == 0) {
+            logger.debug(String.format("[%s] [%s/%s] Rows to update: %s", peer, toIndex, toType, total));
         }
 
         boolean debug = logger.isTraceEnabled();
diff --git a/duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_en_GB.properties b/duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_en_GB.properties
new file mode 100644
index 00000000..dd29729a
--- /dev/null
+++ b/duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_en_GB.properties
@@ -0,0 +1,12 @@
+duniter.event.NODE_BMA_DOWN=
+duniter.event.NODE_BMA_UP=
+duniter.market.error.comment.recordNotFound=Ad [%s] referenced by comment not found
+duniter.market.event.newComment=
+duniter.market.event.newReplyComment=
+duniter.market.event.updateComment=
+duniter.market.event.updateReplyComment=
+duniter.registry.error.comment.recordNotFound=Record [%s] referenced by comment not found
+duniter.registry.event.newComment=
+duniter.registry.event.newReplyComment=
+duniter.registry.event.updateComment=
+duniter.registry.event.updateReplyComment=
diff --git a/duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_fr_FR.properties b/duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_fr_FR.properties
new file mode 100644
index 00000000..40d7fb34
--- /dev/null
+++ b/duniter4j-es-gchange/src/main/resources/i18n/duniter4j-es-gchange_fr_FR.properties
@@ -0,0 +1,12 @@
+duniter.event.NODE_BMA_DOWN=
+duniter.event.NODE_BMA_UP=
+duniter.market.error.comment.recordNotFound=L'annonce [%s] référencée par le commentaire n'existe pas.
+duniter.market.event.newComment=%2$s a commenté votre annonce '%3$s'
+duniter.market.event.newReplyComment=%2$s a répondu à votre commentaire sur l'annonce '%3$s'
+duniter.market.event.updateComment=%2$s a mise à jour son commentaire sur votre annonce '%3$s'
+duniter.market.event.updateReplyComment=%2$s a modifié sa réponse à votre commentaire, sur l'annonce '%3$s'
+duniter.registry.error.comment.recordNotFound=Le référencement [%s] référencée par le commentaire n'existe pas.
+duniter.registry.event.newComment=%2$s a commenté votre référencement '%3$s'
+duniter.registry.event.newReplyComment=%2$s a répondu à votre commentaire sur le référencement '%3$s'
+duniter.registry.event.updateComment=%2$s a modifié son commentaire sur votre référencement '%3$s'
+duniter.registry.event.updateReplyComment=%2$s a modifié sa réponse à votre commentaire, sur le référencement '%3$s'
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserEventMarkAsReadAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserEventMarkAsReadAction.java
index 3dad8d61..a2d545d8 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserEventMarkAsReadAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserEventMarkAsReadAction.java
@@ -37,8 +37,6 @@ public class RestUserEventMarkAsReadAction extends AbstractRestPostMarkAsReadAct
                                          RestSecurityController securityController,
                                          UserEventService userEventService) {
         super(settings, controller, client, securityController, UserEventService.INDEX, UserEventService.EVENT_TYPE,
-                (id, signature) -> {
-                    userEventService.markEventAsRead(id, signature);
-                });
+                (id, signature) -> userEventService.markEventAsRead(id, signature));
     }
 }
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java
index ec6d857d..66f71249 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java
@@ -63,6 +63,7 @@ import org.nuiton.i18n.I18n;
 
 import java.io.IOException;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Created by Benoit on 30/03/2015.
@@ -100,6 +101,7 @@ public class UserEventService extends AbstractService implements ChangeService.C
     public final KeyPair nodeKeyPair;
     public final String nodePubkey;
     public final boolean mailEnable;
+    public final boolean trace;
 
     @Inject
     public UserEventService(final Client client,
@@ -113,7 +115,8 @@ public class UserEventService extends AbstractService implements ChangeService.C
         this.nodeKeyPair = getNodeKeyPairOrNull(pluginSettings);
         this.nodePubkey = getNodePubKey(nodeKeyPair);
         this.mailEnable = pluginSettings.getMailEnable();
-        if (!this.mailEnable && logger.isTraceEnabled()) {
+        this.trace = logger.isTraceEnabled();
+        if (!this.mailEnable && this.trace) {
             logger.trace("Mail disable");
         }
 
@@ -486,12 +489,18 @@ public class UserEventService extends AbstractService implements ChangeService.C
 
             switch (change.getOperation()) {
                 // on create
+                case CREATE:
+                    if (change.getSource() != null) {
+                        UserEvent event = objectMapper.readValue(change.getSource().streamInput(), UserEvent.class);
+                        processEventCreate(change.getId(), event);
+                    }
+                    break;
+
                 // on update
                 case INDEX:
-                case CREATE: // create
                     if (change.getSource() != null) {
                         UserEvent event = objectMapper.readValue(change.getSource().streamInput(), UserEvent.class);
-                        processEventCreateOrUpdate(change.getId(), event);
+                        processEventUpdate(change.getId(), event);
                     }
                     break;
 
@@ -509,7 +518,7 @@ public class UserEventService extends AbstractService implements ChangeService.C
 
     }
 
-    private void processEventCreateOrUpdate(final String eventId, final UserEvent event) {
+    private void processEventCreate(final String eventId, final UserEvent event) {
 
         event.setId(eventId);
 
@@ -526,4 +535,15 @@ public class UserEventService extends AbstractService implements ChangeService.C
 
     }
 
+    private void processEventUpdate(final String eventId, final UserEvent event) {
+
+        // Skip if user has already read the event
+        if (StringUtils.isNotBlank(event.getReadSignature())) {
+            if (this.trace) logger.trace("Updated event already read: Skip propagation to listeners");
+            return;
+        }
+
+        processEventCreate(eventId, event);
+    }
+
 }
-- 
GitLab