From 4d931e5b86384087dc2dca1074737d73714e81f8 Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Wed, 12 Oct 2016 21:38:09 +0200
Subject: [PATCH] - Add security filter - Remove embedded Cesium (no more
 plugin site) - refactoring on RestActions

---
 duniter4j-elasticsearch/pom.xml               |  37 -----
 .../plugin-descriptor.properties              |   2 +-
 .../duniter/elasticsearch/PluginSettings.java |   4 +
 .../action/AbstractRestPostIndexAction.java   |   5 +
 .../action/AbstractRestPostUpdateAction.java  |   3 +
 .../elasticsearch/action/RestModule.java      |  22 +--
 .../history/RestHistoryDeleteIndexAction.java |  44 ++----
 .../market/RestMarketCategoryAction.java      |  38 +++++
 .../market/RestMarketCommentIndexAction.java  |  45 ++----
 .../market/RestMarketCommentUpdateAction.java |  44 ++----
 .../market/RestMarketRecordIndexAction.java   |  45 ++----
 .../market/RestMarketRecordUpdateAction.java  |  43 ++----
 .../message/RestMessageIndexAction.java       |   7 +-
 .../registry/RestRegistryCategoryAction.java  |  38 +++++
 .../RestRegistryCommentIndexAction.java       |  43 ++++++
 .../RestRegistryRecordIndexAction.java        |  45 ++----
 .../RestRegistryRecordUpdateAction.java       |  44 ++----
 .../RestregistryCommentUpdateAction.java      |  44 ++++++
 .../security/RestSecurityAuthAction.java      |   2 +
 .../security/RestSecurityController.java      |  85 +++++++++++
 .../action/security/RestSecurityFilter.java   |  64 +++++++++
 .../action/site/RestCesiumConfigAction.java   | 134 ------------------
 .../user/RestUserProfileIndexAction.java      |   7 +-
 .../user/RestUserProfileUpdateAction.java     |   7 +-
 .../user/RestUserSettingsIndexAction.java     |   7 +-
 .../user/RestUserSettingsUpdateAction.java    |   7 +-
 .../service/AbstractService.java              |  35 +++++
 .../elasticsearch/service/MarketService.java  |  72 ++--------
 .../service/RegistryService.java              |  44 ++----
 .../elasticsearch/service/ServiceModule.java  |  10 +-
 .../src/test/es-home/config/elasticsearch.yml |   2 +-
 .../src/test/es-home/config/logging.yml       |   2 +
 pom.xml                                       |   2 -
 33 files changed, 491 insertions(+), 542 deletions(-)
 create mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCategoryAction.java
 create mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCategoryAction.java
 create mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCommentIndexAction.java
 create mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestregistryCommentUpdateAction.java
 create mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityController.java
 create mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityFilter.java
 delete mode 100644 duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/site/RestCesiumConfigAction.java

diff --git a/duniter4j-elasticsearch/pom.xml b/duniter4j-elasticsearch/pom.xml
index a4237f89..7f15f534 100644
--- a/duniter4j-elasticsearch/pom.xml
+++ b/duniter4j-elasticsearch/pom.xml
@@ -27,7 +27,6 @@
     <duniter4j-elasticsearch.config>${project.basedir}/src/test/resources/duniter4j-elasticsearch-test.properties</duniter4j-elasticsearch.config>
 
     <assembly.skip>false</assembly.skip>
-    <cesium.download.url>https://github.com/duniter/cesium/releases/download/v${cesium.version}/cesium-v${cesium.version}-web.zip</cesium.download.url>
   </properties>
 
   <dependencies>
@@ -191,42 +190,6 @@
         </executions>
       </plugin>
 
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-antrun-plugin</artifactId>
-        <dependencies>
-          <dependency>
-            <groupId>ant-contrib</groupId>
-            <artifactId>ant-contrib</artifactId>
-            <version>1.0b3</version>
-            <exclusions>
-              <exclusion>
-                <groupId>ant</groupId>
-                <artifactId>ant</artifactId>
-              </exclusion>
-            </exclusions>
-          </dependency>
-        </dependencies>
-        <executions>
-          <execution>
-            <id>download-cesium</id>
-            <phase>prepare-package</phase>
-            <goals>
-              <goal>run</goal>
-            </goals>
-            <configuration>
-              <target>
-
-                <!-- download cesium -->
-                <get src="${cesium.download.url}" dest="${project.build.directory}/cesium-web-${cesium.version}.zip" verbose="false" usetimestamp="true" />
-                <unzip src="${project.build.directory}/cesium-web-${cesium.version}.zip" dest="${project.build.directory}/elasticsearch-${elasticsearch.version}/plugins/${project.artifactId}/_site" overwrite="true">
-                </unzip>
-              </target>
-              <skip>${assembly.skip}</skip>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
       <plugin>
         <artifactId>maven-assembly-plugin</artifactId>
         <executions>
diff --git a/duniter4j-elasticsearch/src/main/filtered-resources/plugin-descriptor.properties b/duniter4j-elasticsearch/src/main/filtered-resources/plugin-descriptor.properties
index b801687d..1ab4c6e9 100644
--- a/duniter4j-elasticsearch/src/main/filtered-resources/plugin-descriptor.properties
+++ b/duniter4j-elasticsearch/src/main/filtered-resources/plugin-descriptor.properties
@@ -1,7 +1,7 @@
 name=duniter4j-elasticsearch
 description=Plugin for Duniter node indexation
 version=${project.version}
-site=true
+site=false
 jvm=true
 classname=org.duniter.elasticsearch.Plugin
 java.version=1.7
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java
index 904c834a..5ca82c34 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java
@@ -225,6 +225,10 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> {
         return settings.get("duniter.keyring.sec");
     }
 
+    public boolean enableSecurity() {
+        return settings.getAsBoolean("duniter.security.enable", true);
+    }
+
     /* protected methods */
 
     protected void initI18n() throws IOException {
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostIndexAction.java
index a40081e5..9b2eb4d6 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostIndexAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action;
  */
 
 import org.duniter.core.exception.BusinessException;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
 import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
 import org.elasticsearch.client.Client;
@@ -31,6 +32,7 @@ import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.rest.*;
 
+import static org.elasticsearch.rest.RestRequest.Method.GET;
 import static org.elasticsearch.rest.RestRequest.Method.POST;
 import static org.elasticsearch.rest.RestStatus.OK;
 
@@ -42,6 +44,7 @@ public abstract class AbstractRestPostIndexAction extends BaseRestHandler {
 
 
     public AbstractRestPostIndexAction(Settings settings, RestController controller, Client client,
+                                       RestSecurityController securityController,
                                        String indexName,
                                        String typeName,
                                        JsonIndexer indexer) {
@@ -49,6 +52,8 @@ public abstract class AbstractRestPostIndexAction extends BaseRestHandler {
         controller.registerHandler(POST,
                 String.format("/%s/%s", indexName, typeName),
                 this);
+        securityController.allowIndexType(POST, indexName, typeName);
+        securityController.allowIndexType(GET, indexName, typeName);
         log = ESLoggerFactory.getLogger(String.format("[%s]", indexName));
         this.indexer = indexer;
     }
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostUpdateAction.java
index ad1039b9..ee02158a 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostUpdateAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostUpdateAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action;
  */
 
 import org.duniter.core.exception.BusinessException;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
 import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
 import org.elasticsearch.client.Client;
@@ -42,6 +43,7 @@ public abstract class AbstractRestPostUpdateAction extends BaseRestHandler {
 
 
     public AbstractRestPostUpdateAction(Settings settings, RestController controller, Client client,
+                                        RestSecurityController securityController,
                                         String indexName,
                                         String typeName,
                                         JsonUpdater updater) {
@@ -49,6 +51,7 @@ public abstract class AbstractRestPostUpdateAction extends BaseRestHandler {
         controller.registerHandler(POST,
                 String.format("/%s/%s/{id}/_update", indexName, typeName),
                 this);
+        securityController.allowIndexType(POST, indexName, typeName);
         log = ESLoggerFactory.getLogger(String.format("[%s]", indexName));
         this.updater = updater;
     }
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java
index 19f6062d..8057d6ab 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java
@@ -24,16 +24,13 @@ package org.duniter.elasticsearch.action;
 
 import org.duniter.elasticsearch.action.currency.RestCurrencyIndexAction;
 import org.duniter.elasticsearch.action.history.RestHistoryDeleteIndexAction;
-import org.duniter.elasticsearch.action.market.RestMarketCommentIndexAction;
-import org.duniter.elasticsearch.action.market.RestMarketCommentUpdateAction;
-import org.duniter.elasticsearch.action.market.RestMarketRecordIndexAction;
-import org.duniter.elasticsearch.action.market.RestMarketRecordUpdateAction;
+import org.duniter.elasticsearch.action.market.*;
 import org.duniter.elasticsearch.action.message.RestMessageIndexAction;
-import org.duniter.elasticsearch.action.registry.RestRegistryRecordIndexAction;
-import org.duniter.elasticsearch.action.registry.RestRegistryRecordUpdateAction;
+import org.duniter.elasticsearch.action.registry.*;
 import org.duniter.elasticsearch.action.security.RestSecurityAuthAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
+import org.duniter.elasticsearch.action.security.RestSecurityFilter;
 import org.duniter.elasticsearch.action.security.RestSecurityGetChallengeAction;
-import org.duniter.elasticsearch.action.site.RestCesiumConfigAction;
 import org.duniter.elasticsearch.action.user.RestUserProfileIndexAction;
 import org.duniter.elasticsearch.action.user.RestUserProfileUpdateAction;
 import org.duniter.elasticsearch.action.user.RestUserSettingsIndexAction;
@@ -53,10 +50,14 @@ public class RestModule extends AbstractModule implements Module {
         bind(RestMarketRecordUpdateAction.class).asEagerSingleton();
         bind(RestMarketCommentIndexAction.class).asEagerSingleton();
         bind(RestMarketCommentUpdateAction.class).asEagerSingleton();
+        bind(RestMarketCategoryAction.class).asEagerSingleton();
 
         // Registry
         bind(RestRegistryRecordIndexAction.class).asEagerSingleton();
         bind(RestRegistryRecordUpdateAction.class).asEagerSingleton();
+        bind(RestRegistryCommentIndexAction.class).asEagerSingleton();
+        bind(RestregistryCommentUpdateAction.class).asEagerSingleton();
+        bind(RestRegistryCategoryAction.class).asEagerSingleton();
 
         // User
         bind(RestUserProfileIndexAction.class).asEagerSingleton();
@@ -64,9 +65,11 @@ public class RestModule extends AbstractModule implements Module {
         bind(RestUserSettingsIndexAction.class).asEagerSingleton();
         bind(RestUserSettingsUpdateAction.class).asEagerSingleton();
 
-        // Authentication
+        // Authentication & Security
         bind(RestSecurityGetChallengeAction.class).asEagerSingleton();
         bind(RestSecurityAuthAction.class).asEagerSingleton();
+        bind(RestSecurityFilter.class).asEagerSingleton();
+        bind(RestSecurityController.class).asEagerSingleton();
 
         // History
         bind(RestHistoryDeleteIndexAction.class).asEagerSingleton();
@@ -74,8 +77,5 @@ public class RestModule extends AbstractModule implements Module {
         // Message
         bind(RestMessageIndexAction.class).asEagerSingleton();
 
-        // Cesium
-        bind(RestCesiumConfigAction.class).asEagerSingleton();
-
     }
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/history/RestHistoryDeleteIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/history/RestHistoryDeleteIndexAction.java
index faea221d..79936a4e 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/history/RestHistoryDeleteIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/history/RestHistoryDeleteIndexAction.java
@@ -22,50 +22,26 @@ package org.duniter.elasticsearch.action.history;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.HistoryService;
-import org.duniter.elasticsearch.service.MarketService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.logging.ESLogger;
 import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestHistoryDeleteIndexAction extends BaseRestHandler {
+public class RestHistoryDeleteIndexAction extends AbstractRestPostIndexAction {
 
     private static final ESLogger log = ESLoggerFactory.getLogger(RestHistoryDeleteIndexAction.class.getName());
 
-    private HistoryService service;
-
     @Inject
-    public RestHistoryDeleteIndexAction(Settings settings, RestController controller, Client client, HistoryService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/history/delete", this);
-        this.service = service;
+    public RestHistoryDeleteIndexAction(Settings settings, RestController controller, Client client,
+                                        RestSecurityController securityController, HistoryService service) {
+        super(settings, controller, client, securityController,
+                HistoryService.INDEX,
+                HistoryService.DELETE_TYPE,
+                json -> service.indexDeleteFromJson(json));
     }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-
-        try {
-            String recordId = service.indexDeleteFromJson(request.content().toUtf8());
-
-            restChannel.sendResponse(new BytesRestResponse(OK, recordId));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
-    }
-
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCategoryAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCategoryAction.java
new file mode 100644
index 00000000..6ece1150
--- /dev/null
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCategoryAction.java
@@ -0,0 +1,38 @@
+package org.duniter.elasticsearch.action.market;
+
+/*
+ * #%L
+ * duniter4j-elasticsearch-plugin
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.elasticsearch.action.security.RestSecurityController;
+import org.duniter.elasticsearch.service.MarketService;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.rest.RestRequest;
+
+public class RestMarketCategoryAction {
+
+    @Inject
+    public RestMarketCategoryAction(RestSecurityController securityController) {
+        // Add security rule for category
+        securityController.allowIndexType(RestRequest.Method.GET, MarketService.INDEX, MarketService.RECORD_CATEGORY_TYPE);
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentIndexAction.java
index 28ff0a9c..08452ec8 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentIndexAction.java
@@ -22,49 +22,22 @@ package org.duniter.elasticsearch.action.market;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.MarketService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestMarketCommentIndexAction extends BaseRestHandler {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketCommentIndexAction.class.getName());
-
-    private MarketService service;
+public class RestMarketCommentIndexAction extends AbstractRestPostIndexAction {
 
     @Inject
-    public RestMarketCommentIndexAction(Settings settings, RestController controller, Client client, MarketService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/market/comment", this);
-        this.service = service;
-    }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-
-        try {
-            String recordId = service.indexCommentFromJson(request.content().toUtf8());
-
-            restChannel.sendResponse(new BytesRestResponse(OK, recordId));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
+    public RestMarketCommentIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                        MarketService service) {
+        super(settings, controller, client, securityController,
+                MarketService.INDEX, MarketService.RECORD_COMMENT_TYPE,
+                json -> service.indexCommentFromJson(json));
     }
 
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentUpdateAction.java
index 213198cc..b1840100 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentUpdateAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketCommentUpdateAction.java
@@ -22,48 +22,22 @@ package org.duniter.elasticsearch.action.market;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.action.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.MarketService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestMarketCommentUpdateAction extends BaseRestHandler {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketCommentUpdateAction.class.getName());
-
-    private MarketService service;
+public class RestMarketCommentUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestMarketCommentUpdateAction(Settings settings, RestController controller, Client client, MarketService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/market/comment/{id}/_update", this);
-        this.service = service;
-    }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-
-        String id = request.param("id");
-        try {
-            service.updateCommentFromJson(request.content().toUtf8(), id);
-            restChannel.sendResponse(new BytesRestResponse(OK, id));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
+    public RestMarketCommentUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                         MarketService service) {
+        super(settings, controller, client, securityController,
+                MarketService.INDEX, MarketService.RECORD_COMMENT_TYPE,
+                (json, id) -> service.updateCommentFromJson(json, id));
     }
 
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordIndexAction.java
index bcc4bb2b..2d2b8d56 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordIndexAction.java
@@ -22,49 +22,22 @@ package org.duniter.elasticsearch.action.market;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.MarketService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestMarketRecordIndexAction extends BaseRestHandler {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketRecordIndexAction.class.getName());
-
-    private MarketService service;
+public class RestMarketRecordIndexAction extends AbstractRestPostIndexAction {
 
     @Inject
-    public RestMarketRecordIndexAction(Settings settings, RestController controller, Client client, MarketService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/market/record", this);
-        this.service = service;
-    }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-
-        try {
-            String recordId = service.indexRecordFromJson(request.content().toUtf8());
-
-            restChannel.sendResponse(new BytesRestResponse(OK, recordId));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
+    public RestMarketRecordIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                       MarketService service) {
+        super(settings, controller, client, securityController,
+                MarketService.INDEX, MarketService.RECORD_TYPE,
+                json -> service.indexRecordFromJson(json));
     }
 
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordUpdateAction.java
index bde8c3dd..9b1b99da 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordUpdateAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/market/RestMarketRecordUpdateAction.java
@@ -22,47 +22,22 @@ package org.duniter.elasticsearch.action.market;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.action.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.MarketService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestMarketRecordUpdateAction extends BaseRestHandler {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestMarketRecordUpdateAction.class.getName());
-
-    private MarketService service;
+public class RestMarketRecordUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestMarketRecordUpdateAction(Settings settings, RestController controller, Client client, MarketService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/market/record/{id}/_update", this);
-        this.service = service;
-    }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-        String id = request.param("id");
-        try {
-            service.updateRecordFromJson(request.content().toUtf8(), id);
-            restChannel.sendResponse(new BytesRestResponse(OK, id));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
+    public RestMarketRecordUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                        MarketService service) {
+        super(settings, controller, client, securityController,
+                MarketService.INDEX, MarketService.RECORD_TYPE,
+                (json, id) -> service.updateRecordFromJson(json, id));
     }
 
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java
index 0db480ef..90e944a3 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action.message;
  */
 
 import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.MessageService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
@@ -32,8 +33,10 @@ import org.elasticsearch.rest.RestController;
 public class RestMessageIndexAction extends AbstractRestPostIndexAction {
 
     @Inject
-    public RestMessageIndexAction(Settings settings, RestController controller, Client client, final MessageService service) {
-        super(settings, controller, client,
+    public RestMessageIndexAction(Settings settings, RestController controller, Client client,
+                                  RestSecurityController securityController,
+                                  final MessageService service) {
+        super(settings, controller, client, securityController,
                 MessageService.INDEX,
                 MessageService.RECORD_TYPE,
                 json -> service.indexRecordFromJson(json));
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCategoryAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCategoryAction.java
new file mode 100644
index 00000000..7bfdf238
--- /dev/null
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCategoryAction.java
@@ -0,0 +1,38 @@
+package org.duniter.elasticsearch.action.registry;
+
+/*
+ * #%L
+ * duniter4j-elasticsearch-plugin
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.elasticsearch.action.security.RestSecurityController;
+import org.duniter.elasticsearch.service.RegistryService;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.rest.RestRequest;
+
+public class RestRegistryCategoryAction {
+
+    @Inject
+    public RestRegistryCategoryAction(RestSecurityController securityController) {
+        // Add security rule for category
+        securityController.allowIndexType(RestRequest.Method.GET, RegistryService.INDEX, RegistryService.RECORD_CATEGORY_TYPE);
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCommentIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCommentIndexAction.java
new file mode 100644
index 00000000..1c112ce4
--- /dev/null
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryCommentIndexAction.java
@@ -0,0 +1,43 @@
+package org.duniter.elasticsearch.action.registry;
+
+/*
+ * #%L
+ * duniter4j-elasticsearch-plugin
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
+import org.duniter.elasticsearch.service.RegistryService;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestController;
+
+public class RestRegistryCommentIndexAction extends AbstractRestPostIndexAction {
+
+    @Inject
+    public RestRegistryCommentIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                          RegistryService service) {
+        super(settings, controller, client, securityController,
+                RegistryService.INDEX, RegistryService.RECORD_COMMENT_TYPE,
+                json -> service.indexCommentFromJson(json));
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordIndexAction.java
index 92e2d6de..1d3c5768 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordIndexAction.java
@@ -22,49 +22,22 @@ package org.duniter.elasticsearch.action.registry;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.RegistryService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.BAD_REQUEST;
-import static org.elasticsearch.rest.RestStatus.OK;
+public class RestRegistryRecordIndexAction extends AbstractRestPostIndexAction {
 
-public class RestRegistryRecordIndexAction extends BaseRestHandler {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestRegistryRecordIndexAction.class.getName());
-
-    private RegistryService service;
 
     @Inject
-    public RestRegistryRecordIndexAction(Settings settings, RestController controller, Client client, RegistryService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/registry/record", this);
-        this.service = service;
+    public RestRegistryRecordIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                         RegistryService service) {
+        super(settings, controller, client, securityController,
+                RegistryService.INDEX, RegistryService.RECORD_TYPE,
+                json -> service.indexRecordFromJson(json));
     }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-
-        try {
-            String recordId = service.indexRecordFromJson(request.content().toUtf8());
-
-            restChannel.sendResponse(new BytesRestResponse(OK, recordId));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
-    }
-
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordUpdateAction.java
index 45c480c1..dcfba5eb 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordUpdateAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestRegistryRecordUpdateAction.java
@@ -22,48 +22,22 @@ package org.duniter.elasticsearch.action.registry;
  * #L%
  */
 
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
-import org.duniter.elasticsearch.service.MarketService;
+import org.duniter.elasticsearch.action.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.RegistryService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.rest.*;
+import org.elasticsearch.rest.RestController;
 
-import static org.elasticsearch.rest.RestRequest.Method.POST;
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestRegistryRecordUpdateAction extends BaseRestHandler {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestRegistryRecordUpdateAction.class.getName());
-
-    private RegistryService service;
+public class RestRegistryRecordUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestRegistryRecordUpdateAction(Settings settings, RestController controller, Client client, RegistryService service) {
-        super(settings, controller, client);
-        controller.registerHandler(POST, "/registry/record/{id}/_update", this);
-        this.service = service;
-    }
-
-    @Override
-    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
-        String id = request.param("id");
-        try {
-            service.updateRecordFromJson(request.content().toUtf8(), id);
-            restChannel.sendResponse(new BytesRestResponse(OK, id));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
+    public RestRegistryRecordUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                          RegistryService service) {
+        super(settings, controller, client, securityController,
+                RegistryService.INDEX, RegistryService.RECORD_TYPE,
+                (json, id) -> service.updateRecordFromJson(json, id));
     }
 
 }
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestregistryCommentUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestregistryCommentUpdateAction.java
new file mode 100644
index 00000000..6137eacb
--- /dev/null
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/registry/RestregistryCommentUpdateAction.java
@@ -0,0 +1,44 @@
+package org.duniter.elasticsearch.action.registry;
+
+/*
+ * #%L
+ * duniter4j-elasticsearch-plugin
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.elasticsearch.action.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
+import org.duniter.elasticsearch.service.MarketService;
+import org.duniter.elasticsearch.service.RegistryService;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestController;
+
+public class RestregistryCommentUpdateAction extends AbstractRestPostUpdateAction {
+
+    @Inject
+    public RestregistryCommentUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                           RegistryService service) {
+        super(settings, controller, client, securityController,
+                RegistryService.INDEX, RegistryService.RECORD_COMMENT_TYPE,
+                (json, id) -> service.updateCommentFromJson(json, id));
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityAuthAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityAuthAction.java
index 26c63f63..945e8dce 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityAuthAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityAuthAction.java
@@ -47,12 +47,14 @@ public class RestSecurityAuthAction extends BaseRestHandler {
 
     @Inject
     public RestSecurityAuthAction(Settings settings, RestController controller, Client client,
+                                  RestSecurityController securityController,
                                   ChallengeMessageStore challengeMessageStore,
                                   SecurityTokenStore securityTokenStore) {
         super(settings, controller, client);
         this.challengeMessageStore = challengeMessageStore;
         this.securityTokenStore = securityTokenStore;
         controller.registerHandler(POST, "/auth", this);
+        securityController.allow(POST, "/auth");
     }
 
     @Override
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityController.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityController.java
new file mode 100644
index 00000000..a7729e5b
--- /dev/null
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityController.java
@@ -0,0 +1,85 @@
+package org.duniter.elasticsearch.action.security;
+
+import org.duniter.elasticsearch.PluginSettings;
+import org.elasticsearch.common.component.AbstractLifecycleComponent;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.logging.ESLogger;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestRequest;
+
+import java.util.*;
+
+/**
+ * Created by blavenie on 11/10/16.
+ */
+public class RestSecurityController extends AbstractLifecycleComponent<RestSecurityController> {
+
+    private static final ESLogger log = ESLoggerFactory.getLogger("security");
+
+    private boolean enable;
+
+    private Map<RestRequest.Method, Set<String>> allowRulesByMethod;
+
+    @Inject
+    public RestSecurityController(Settings settings, PluginSettings pluginSettings) {
+        super(settings);
+        this.enable = pluginSettings.enableSecurity();
+        this.allowRulesByMethod = new HashMap<>();
+    }
+
+    public RestSecurityController allowIndexType(RestRequest.Method method, String index, String type) {
+        return allow(method, String.format("/%s/%s", index, type));
+    }
+
+    public RestSecurityController allow(RestRequest.Method method, String path) {
+        Set<String> allowRules = allowRulesByMethod.get(method);
+        if (allowRules == null) {
+            allowRules = new TreeSet<>();
+            allowRulesByMethod.put(method, allowRules);
+        }
+        allowRules.add(path);
+        return this;
+    }
+
+    public boolean isAllow(RestRequest request) {
+        RestRequest.Method method = request.method();
+        if (log.isTraceEnabled()) {
+            log.trace(String.format("Checking rules for %s request [%s]...", method, request.path()));
+        }
+
+        Set<String> allowRules = allowRulesByMethod.get(request.method());
+        String path = request.path();
+        if (allowRules != null) {
+            for (String allowRule : allowRules) {
+                if (path.startsWith(allowRule)) {
+                    if (log.isTraceEnabled()) {
+                        log.trace(String.format("Find matching rule [%s] for %s request [%s]: allow", allowRule, method, path));
+                    }
+                    return true;
+                }
+            }
+        }
+
+        log.trace(String.format("No matching rules for %s request [%s]: reject", method, path));
+        return false;
+    }
+
+    @Override
+    protected void doStart() {
+
+    }
+
+    @Override
+    protected void doStop() {
+
+    }
+
+    @Override
+    protected void doClose() {
+
+    }
+
+    /* -- Internal method -- */
+
+}
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityFilter.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityFilter.java
new file mode 100644
index 00000000..87fdac97
--- /dev/null
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/security/RestSecurityFilter.java
@@ -0,0 +1,64 @@
+package org.duniter.elasticsearch.action.security;
+
+/*
+ * #%L
+ * duniter4j-elasticsearch-plugin
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.elasticsearch.PluginSettings;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.logging.ESLogger;
+import org.elasticsearch.common.logging.ESLoggerFactory;
+import org.elasticsearch.rest.*;
+
+import static org.elasticsearch.rest.RestStatus.FORBIDDEN;
+
+public class RestSecurityFilter extends RestFilter {
+
+    private static final ESLogger log = ESLoggerFactory.getLogger("security");
+
+    private RestSecurityController securityController;
+
+    @Inject
+    public RestSecurityFilter(PluginSettings pluginSettings, RestController controller, RestSecurityController securityController) {
+        super();
+        if (pluginSettings.enableSecurity()) {
+            controller.registerFilter(this);
+        }
+        this.securityController = securityController;
+    }
+
+    @Override
+    public void process(RestRequest request, RestChannel channel, RestFilterChain filterChain) throws Exception {
+
+        if (securityController.isAllow(request)) {
+            if (log.isDebugEnabled()) {
+                log.debug(String.format("Allow %s request [%s]", request.method().name(), request.path()));
+            }
+            filterChain.continueProcessing(request, channel);
+        }
+
+        else {
+            log.warn(String.format("Refused %s request to [%s]", request.method().name(), request.path()));
+            channel.sendResponse(new BytesRestResponse(FORBIDDEN));
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/site/RestCesiumConfigAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/site/RestCesiumConfigAction.java
deleted file mode 100644
index 7b48885e..00000000
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/site/RestCesiumConfigAction.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package org.duniter.elasticsearch.action.site;
-
-/*
- * #%L
- * duniter4j-elasticsearch-plugin
- * %%
- * Copyright (C) 2014 - 2016 EIS
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, either version 3 of the 
- * License, or (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public 
- * License along with this program.  If not, see
- * <http://www.gnu.org/licenses/gpl-3.0.html>.
- * #L%
- */
-
-import org.duniter.core.exception.BusinessException;
-import org.duniter.elasticsearch.PluginSettings;
-import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
-import org.duniter.elasticsearch.exception.NodeConfigException;
-import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
-import org.duniter.elasticsearch.service.RegistryService;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.logging.ESLogger;
-import org.elasticsearch.common.logging.ESLoggerFactory;
-import org.elasticsearch.common.network.NetworkAddress;
-import org.elasticsearch.common.network.NetworkService;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.BoundTransportAddress;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.http.HttpChannel;
-import org.elasticsearch.http.HttpServerTransport;
-import org.elasticsearch.index.translog.TranslogService;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.rest.*;
-import org.elasticsearch.transport.TransportService;
-
-import java.io.IOException;
-import java.net.InetAddress;
-
-import static org.elasticsearch.rest.RestStatus.OK;
-
-public class RestCesiumConfigAction extends RestFilter {
-
-    private static final ESLogger log = ESLoggerFactory.getLogger(RestCesiumConfigAction.class.getName());
-
-    private static final String CONFIG_FILE_PATH = "/_plugin/duniter4j-elasticsearch/config.js";
-    private NetworkService networkService;
-    private HttpServerTransport transport;
-    private PluginSettings pluginSettings;
-
-    private String configJsContent;
-
-    @Inject
-    public RestCesiumConfigAction(RestController controller, PluginSettings pluginSettings, NetworkService networkService,
-                                  HttpServerTransport transport) {
-        controller.registerFilter(this);
-        this.networkService = networkService;
-        this.pluginSettings = pluginSettings;
-        this.transport = transport;
-    }
-
-    @Override
-    public void process(final RestRequest request, RestChannel restChannel, RestFilterChain restFilterChain) throws Exception {
-        // If path = config file: send content
-        if (CONFIG_FILE_PATH.equalsIgnoreCase(request.path())) {
-            handleRequest(request, restChannel);
-        }
-        else {
-            // Continue
-            restFilterChain.continueProcessing(request, restChannel);
-        }
-    }
-
-    protected void handleRequest(final RestRequest request, RestChannel restChannel) throws Exception {
-
-        try {
-            restChannel.sendResponse(new BytesRestResponse(OK, getCesiumConfigJs()));
-        }
-        catch(DuniterElasticsearchException | BusinessException e) {
-            log.error(e.getMessage(), e);
-            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
-        }
-        catch(Exception e) {
-            log.error(e.getMessage(), e);
-        }
-    }
-
-    protected String getCesiumConfigJs() throws DuniterElasticsearchException {
-        if (configJsContent != null) {
-            return configJsContent;
-        }
-
-        // Get ES node address
-        BoundTransportAddress host = transport.boundAddress();
-        TransportAddress esNodeAddress = host.publishAddress();
-
-        // Compute the config file content
-        configJsContent = String.format("angular.module(\"cesium.config\", [])\n" +
-                        ".constant(\"csConfig\", {\n" +
-                        "                \"node\": {\n" +
-                        "                    \"host\": \"%s\",\n" +
-                        "                    \"port\": \"%s\"\n" +
-                        "                },\n" +
-                        "                \"plugins\": {\n" +
-                        "                  \"es\": {\n" +
-                        "                    \"enable\": \"true\",\n" +
-                        "                    \"host\": \"%s\",\n" +
-                        "                    \"port\": \"%s\"\n" +
-                        "                  },\n" +
-                        "                },\n" +
-                        "                \"newIssueUrl\": \"https://github.com/duniter/cesium/issues/new?labels=bug\",\n" +
-                        "                \"time\": 4000,\n" +
-                        "                \"version\": \"0.2.1\",\n" +
-                        "             });",
-                pluginSettings.getNodeBmaHost(),
-                pluginSettings.getNodeBmaPort(),
-                esNodeAddress.getHost(),
-                esNodeAddress.getPort()
-                );
-
-        return configJsContent;
-    }
-
-}
\ No newline at end of file
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileIndexAction.java
index a305415c..9e738f86 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileIndexAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action.user;
  */
 
 import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.UserService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
@@ -32,8 +33,10 @@ import org.elasticsearch.rest.RestController;
 public class RestUserProfileIndexAction extends AbstractRestPostIndexAction {
 
     @Inject
-    public RestUserProfileIndexAction(Settings settings, RestController controller, Client client, UserService service) {
-        super(settings, controller, client,
+    public RestUserProfileIndexAction(Settings settings, RestController controller, Client client,
+                                      RestSecurityController securityController,
+                                      UserService service) {
+        super(settings, controller, client, securityController,
                 UserService.INDEX,
                 UserService.PROFILE_TYPE,
                 json -> service.indexProfileFromJson(json));
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileUpdateAction.java
index 2c978fb5..e6d60417 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileUpdateAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserProfileUpdateAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action.user;
  */
 
 import org.duniter.elasticsearch.action.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.UserService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
@@ -32,8 +33,10 @@ import org.elasticsearch.rest.RestController;
 public class RestUserProfileUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestUserProfileUpdateAction(Settings settings, RestController controller, Client client, UserService service) {
-        super(settings, controller, client,
+    public RestUserProfileUpdateAction(Settings settings, RestController controller, Client client,
+                                       RestSecurityController securityController,
+                                       UserService service) {
+        super(settings, controller, client, securityController,
                 UserService.INDEX,
                 UserService.PROFILE_TYPE,
                 (json, id) -> service.updateProfileFromJson(json, id));
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsIndexAction.java
index 179216d9..cb9f7c75 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsIndexAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsIndexAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action.user;
  */
 
 import org.duniter.elasticsearch.action.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.UserService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
@@ -32,8 +33,10 @@ import org.elasticsearch.rest.RestController;
 public class RestUserSettingsIndexAction extends AbstractRestPostIndexAction {
 
     @Inject
-    public RestUserSettingsIndexAction(Settings settings, RestController controller, Client client, final UserService service) {
-        super(settings, controller, client,
+    public RestUserSettingsIndexAction(Settings settings, RestController controller, Client client,
+                                       RestSecurityController securityController,
+                                       final UserService service) {
+        super(settings, controller, client, securityController,
                 UserService.INDEX,
                 UserService.SETTINGS_TYPE,
                 json -> service.indexSettingsFromJson(json));
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsUpdateAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsUpdateAction.java
index 5174ad11..3cf36bae 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsUpdateAction.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/user/RestUserSettingsUpdateAction.java
@@ -23,6 +23,7 @@ package org.duniter.elasticsearch.action.user;
  */
 
 import org.duniter.elasticsearch.action.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.action.security.RestSecurityController;
 import org.duniter.elasticsearch.service.UserService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
@@ -32,8 +33,10 @@ import org.elasticsearch.rest.RestController;
 public class RestUserSettingsUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestUserSettingsUpdateAction(Settings settings, RestController controller, Client client, final UserService service) {
-        super(settings, controller, client,
+    public RestUserSettingsUpdateAction(Settings settings, RestController controller, Client client,
+                                        RestSecurityController securityController,
+                                        final UserService service) {
+        super(settings, controller, client,  securityController,
                 UserService.INDEX,
                 UserService.SETTINGS_TYPE,
                 (json, id) -> service.updateSettingsFromJson(json, id));
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
index 75ae513c..e417f1e0 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java
@@ -45,6 +45,7 @@ import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsReques
 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
 import org.elasticsearch.action.bulk.BulkRequest;
 import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.index.IndexResponse;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.client.Requests;
 import org.elasticsearch.common.bytes.BytesArray;
@@ -118,6 +119,40 @@ public abstract class AbstractService implements Bean {
         deleteIndexRequestBuilder.execute().actionGet();
     }
 
+    protected String checkIssuerAndIndexDocumentFromJson(String index, String type, String json) {
+
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
+        String issuer = getIssuer(actualObj);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(String.format("Indexing a %s from issuer [%s]", type, issuer.substring(0, 8)));
+        }
+
+        IndexResponse response = client.prepareIndex(index, type)
+                .setSource(json)
+                .setRefresh(false)
+                .execute().actionGet();
+        return response.getId();
+    }
+
+    protected void checkIssuerAndUpdateDocumentFromJson(String index, String type, String json, String id) {
+
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
+        String issuer = getIssuer(actualObj);
+
+        // Check same document issuer
+        checkSameDocumentIssuer(index, type, id, issuer);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(String.format("Updating %s [%s] from issuer [%s]", type, id, issuer.substring(0, 8)));
+        }
+
+        // Execute indexBlocksFromNode
+        client.prepareUpdate(index, type, id)
+                .setDoc(json)
+                .execute().actionGet();
+    }
+
     protected XContentBuilder createDefaultAnalyzer() {
         try {
             XContentBuilder analyzer = XContentFactory.jsonBuilder().startObject().startObject("analyzer")
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java
index 64c5c38c..d82ac728 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java
@@ -24,7 +24,6 @@ package org.duniter.elasticsearch.service;
 
 
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
 import org.duniter.core.client.service.bma.WotRemoteService;
 import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
@@ -55,7 +54,8 @@ public class MarketService extends AbstractService {
     private WotRemoteService wotRemoteService;
 
     @Inject
-    public MarketService(Client client, PluginSettings settings, CryptoService cryptoService, WotRemoteService wotRemoteService) {
+    public MarketService(Client client, PluginSettings settings,
+                         CryptoService cryptoService, WotRemoteService wotRemoteService) {
         super("gchange." + INDEX, client, settings, cryptoService);
         this.wotRemoteService = wotRemoteService;
     }
@@ -137,72 +137,20 @@ public class MarketService extends AbstractService {
         return response.getId();
     }
 
-    public String indexRecordFromJson(String recordJson) {
-
-        JsonNode actualObj = readAndVerifyIssuerSignature(recordJson);
-        String issuer = getIssuer(actualObj);
-
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Indexing market record from issuer [%s]", issuer.substring(0, 8)));
-        }
-
-        IndexResponse response = client.prepareIndex(INDEX, RECORD_TYPE)
-                .setSource(recordJson)
-                .setRefresh(false)
-                .execute().actionGet();
-
-        return response.getId();
+    public String indexRecordFromJson(String json) {
+        return checkIssuerAndIndexDocumentFromJson(INDEX, RECORD_TYPE, json);
     }
 
-    public void updateRecordFromJson(String recordJson, String id) {
-
-        JsonNode actualObj = readAndVerifyIssuerSignature(recordJson);
-        String issuer = getIssuer(actualObj);
-
-        // Check same document issuer
-        checkSameDocumentIssuer(INDEX, RECORD_TYPE, id, issuer);
-
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Updating market record [%s] from issuer [%s]", id, issuer.substring(0, 8)));
-        }
-
-        client.prepareUpdate(INDEX, RECORD_TYPE, id)
-                .setDoc(recordJson)
-                .execute().actionGet();
+    public void updateRecordFromJson(String json, String id) {
+        checkIssuerAndUpdateDocumentFromJson(INDEX, RECORD_TYPE, json, id);
     }
 
-    public String indexCommentFromJson(String commentJson) {
-
-        JsonNode actualObj = readAndVerifyIssuerSignature(commentJson);
-        String issuer = getIssuer(actualObj);
-
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Indexing a comment from issuer [%s]", issuer.substring(0, 8)));
-        }
-
-        IndexResponse response = client.prepareIndex(INDEX, RECORD_COMMENT_TYPE)
-                .setSource(commentJson)
-                .setRefresh(false)
-                .execute().actionGet();
-        return response.getId();
+    public String indexCommentFromJson(String json) {
+        return checkIssuerAndIndexDocumentFromJson(INDEX, RECORD_COMMENT_TYPE, json);
     }
 
-    public void updateCommentFromJson(String commentJson, String id) {
-
-        JsonNode actualObj = readAndVerifyIssuerSignature(commentJson);
-        String issuer = getIssuer(actualObj);
-
-        // Check same document issuer
-        checkSameDocumentIssuer(INDEX, RECORD_COMMENT_TYPE, id, issuer);
-
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Updating comment [%s] from issuer [%s]", id, issuer.substring(0, 8)));
-        }
-
-        // Execute indexBlocksFromNode
-        client.prepareUpdate(INDEX, RECORD_COMMENT_TYPE, id)
-                .setDoc(commentJson)
-                .execute().actionGet();
+    public void updateCommentFromJson(String json, String id) {
+        checkIssuerAndUpdateDocumentFromJson(INDEX, RECORD_COMMENT_TYPE, json, id);
     }
 
     public MarketService fillRecordCategories() {
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java
index 90cab8e2..d25b7541 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java
@@ -88,7 +88,7 @@ public class RegistryService extends AbstractService {
                            CryptoService cryptoService,
                            BlockchainRemoteService blockchainRemoteService) {
         super("gchange." + INDEX, client, settings, cryptoService);
-        gson = GsonUtils.newBuilder().create();
+        this.gson = GsonUtils.newBuilder().create();
         this.blockchainRemoteService = blockchainRemoteService;
     }
 
@@ -159,42 +159,20 @@ public class RegistryService extends AbstractService {
         return !StringUtils.isEmpty(pubkey);
     }
 
-    /**
-     *
-     * @param recordJson
-     * @return the record id
-     */
-    public String indexRecordFromJson(String recordJson) {
-
-        JsonNode actualObj = readAndVerifyIssuerSignature(recordJson);
-        String issuer = getIssuer(actualObj);
-
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Indexing a registry record from issuer [%s]", issuer.substring(0, 8)));
-        }
-
-        IndexResponse response = client.prepareIndex(INDEX, RECORD_TYPE)
-                .setSource(recordJson)
-                .setRefresh(false)
-                .execute().actionGet();
-        return response.getId();
+    public String indexRecordFromJson(String json) {
+        return checkIssuerAndIndexDocumentFromJson(INDEX, RECORD_TYPE, json);
     }
 
-    public void updateRecordFromJson(String recordJson, String id) {
-
-        JsonNode actualObj = readAndVerifyIssuerSignature(recordJson);
-        String issuer = getIssuer(actualObj);
-
-        // Check same document issuer
-        checkSameDocumentIssuer(INDEX, RECORD_TYPE, id, issuer);
+    public void updateRecordFromJson(String json, String id) {
+        checkIssuerAndUpdateDocumentFromJson(INDEX, RECORD_TYPE, json, id);
+    }
 
-        if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Updating market record [%s] from issuer [%s]", id, issuer.substring(0, 8)));
-        }
+    public String indexCommentFromJson(String json) {
+        return checkIssuerAndIndexDocumentFromJson(INDEX, RECORD_COMMENT_TYPE, json);
+    }
 
-        client.prepareUpdate(INDEX, RECORD_TYPE, id)
-                .setDoc(recordJson)
-                .execute().actionGet();
+    public void updateCommentFromJson(String json, String id) {
+        checkIssuerAndUpdateDocumentFromJson(INDEX, RECORD_COMMENT_TYPE, json, id);
     }
 
     public void insertRecordFromBulkFile(File bulkFile) {
diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/ServiceModule.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/ServiceModule.java
index 0342ebce..c9b604ad 100644
--- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/ServiceModule.java
+++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/ServiceModule.java
@@ -45,11 +45,11 @@ public class ServiceModule extends AbstractModule implements Module {
 
         // ES service
         bind(PluginSettings.class).asEagerSingleton();
-        bind(RegistryService.class);
-        bind(MarketService.class);
-        bind(BlockchainService.class);
-        bind(MessageService.class);
-        bind(HistoryService.class);
+        bind(RegistryService.class).asEagerSingleton();
+        bind(MarketService.class).asEagerSingleton();
+        bind(BlockchainService.class).asEagerSingleton();
+        bind(MessageService.class).asEagerSingleton();
+        bind(HistoryService.class).asEagerSingleton();
 
         // Duniter Client API beans
         bindWithLocator(BlockchainRemoteService.class);
diff --git a/duniter4j-elasticsearch/src/test/es-home/config/elasticsearch.yml b/duniter4j-elasticsearch/src/test/es-home/config/elasticsearch.yml
index 71fef2db..605f3d2e 100644
--- a/duniter4j-elasticsearch/src/test/es-home/config/elasticsearch.yml
+++ b/duniter4j-elasticsearch/src/test/es-home/config/elasticsearch.yml
@@ -110,7 +110,7 @@ security.manager.enabled: false
 #duniter.port: 9330
 
 duniter.host: 192.168.0.5
-duniter.port: 9201
+duniter.port: 9602
 #duniter.host: 192.168.0.28
 #duniter.port: 9202
 
diff --git a/duniter4j-elasticsearch/src/test/es-home/config/logging.yml b/duniter4j-elasticsearch/src/test/es-home/config/logging.yml
index c6d7f5a0..3642d94c 100644
--- a/duniter4j-elasticsearch/src/test/es-home/config/logging.yml
+++ b/duniter4j-elasticsearch/src/test/es-home/config/logging.yml
@@ -20,6 +20,8 @@ logger:
 
   org.duniter.elasticsearch: DEBUG
 
+  security: DEBUG
+
   org.nuiton.i18n: WARN
   org.nuiton.config: WARN
 
diff --git a/pom.xml b/pom.xml
index aa8bb823..8b55c6b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,8 +27,6 @@
     <jna.version>4.1.0</jna.version>
     <tyrus.version>1.12</tyrus.version>
 
-    <cesium.version>0.2.12</cesium.version>
-
     <nuitonConfigVersion>3.0-rc-4</nuitonConfigVersion>
     <nuitonI18nVersion>3.5</nuitonI18nVersion>
 
-- 
GitLab