diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserGroup.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserGroup.java
index 459530739ab90f0f5583035ee6cfaad1979e4dcd..5a0fc2ea9da2902d0a685f019b06d3ef39285471 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserGroup.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserGroup.java
@@ -33,12 +33,12 @@ public class UserGroup extends Record {
     public static final String PROPERTY_TITLE="title";
     public static final String PROPERTY_DESCRIPTION="description";
     public static final String PROPERTY_CREATION_TIME="creationTime";
-    public static final String PROPERTY_THUMBNAIL="thumbnail";
+    public static final String PROPERTY_AVATAR="avatar";
 
     private String title;
     private String description;
     private Long creationTime;
-    private Map<String, String> thumbnail = new HashMap<>();
+    private Map<String, String> avatar = new HashMap<>();
 
     public String getTitle() {
         return title;
@@ -64,12 +64,12 @@ public class UserGroup extends Record {
         this.creationTime = creationTime;
     }
 
-    public Map<String, String> getThumbnail() {
-        return thumbnail;
+    public Map<String, String> getAvatar() {
+        return avatar;
     }
 
-    public void setThumbnail(Map<String, String> thumbnail) {
-        this.thumbnail = thumbnail;
+    public void setAvatar(Map<String, String> avatar) {
+        this.avatar = avatar;
     }
 
 }
diff --git a/duniter4j-es-assembly/src/test/misc/udByPeriods.sh b/duniter4j-es-assembly/src/test/misc/udByPeriods.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7eac90e70b8bf21eda9c2668e1c795b1b9131b43
--- /dev/null
+++ b/duniter4j-es-assembly/src/test/misc/udByPeriods.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+curl -XPOST 'http://localhost:9200/g1/block/_search?pretty' -d '
+   {
+     "size": 1000,
+     query: {
+          filtered: {
+            filter: {
+
+              bool: {
+                must: [
+                  {
+                    exists: {
+                      field: "dividend"
+                    }
+                  },
+                  {
+                    range: {
+                        medianTime: {
+                        from: 1506837759, to: 201507961583
+                        }
+                    }
+                  }
+                ]
+              }
+            }
+          }
+        },
+        _source: ["medianTime", "number", "dividend", "monetaryMass", "membersCount", "unitbase"],
+          sort: {
+            "medianTime" : "asc"
+          }
+   }'
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginInit.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginInit.java
index 02c7acdbfcd4add40ea637c66acf3d9a81f156a5..697c1de15174007daf466761a5aea0e76095ba89 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginInit.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginInit.java
@@ -24,12 +24,15 @@ package org.duniter.elasticsearch.user;
 
 import org.duniter.elasticsearch.service.DocStatService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
-import org.duniter.elasticsearch.user.dao.page.RegistryCommentDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.group.GroupCommentDao;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.group.GroupRecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageCommentDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.duniter.elasticsearch.user.model.UserEvent;
-import org.duniter.elasticsearch.user.service.*;
 import org.duniter.elasticsearch.user.model.UserEventCodes;
+import org.duniter.elasticsearch.user.service.*;
 import org.elasticsearch.common.component.AbstractLifecycleComponent;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.inject.Injector;
@@ -154,9 +157,10 @@ public class PluginInit extends AbstractLifecycleComponent<PluginInit> {
                     .registerIndex(MessageService.INDEX, MessageService.OUTBOX_TYPE)
                     .registerIndex(UserInvitationService.INDEX, UserInvitationService.CERTIFICATION_TYPE)
                     .registerIndex(UserEventService.INDEX, UserEventService.EVENT_TYPE)
-                    .registerIndex(RegistryIndexDao.INDEX, RegistryRecordDao.TYPE)
-                    .registerIndex(RegistryIndexDao.INDEX, RegistryCommentDao.TYPE)
-                    .registerIndex(GroupService.INDEX, GroupService.RECORD_TYPE)
+                    .registerIndex(PageIndexDao.INDEX, PageRecordDao.TYPE)
+                    .registerIndex(PageIndexDao.INDEX, PageCommentDao.TYPE)
+                    .registerIndex(GroupIndexDao.INDEX, GroupRecordDao.TYPE)
+                    .registerIndex(GroupIndexDao.INDEX, GroupCommentDao.TYPE)
                     .registerIndex(HistoryService.INDEX, HistoryService.DELETE_TYPE)
             ;
         }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/AbstractRecordDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/AbstractRecordDaoImpl.java
index 7968b475f23c83eaaf295157d77aca62328e84b7..13a4bc99aca5d9d844204d9f830025a31301727e 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/AbstractRecordDaoImpl.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/AbstractRecordDaoImpl.java
@@ -41,8 +41,16 @@ public class AbstractRecordDaoImpl<T extends AbstractRecordDaoImpl> extends Abst
 
     protected PluginSettings pluginSettings;
 
+    private boolean isPubkeyFieldEnable = false;
+    private boolean isNestedPicturesEnable = false;
+    private boolean isNestedCategoryEnable = false;
+
     public AbstractRecordDaoImpl(String index, PluginSettings pluginSettings) {
-        super(index, RecordDao.TYPE);
+        this(index, RecordDao.TYPE, pluginSettings);
+    }
+
+    public AbstractRecordDaoImpl(String index, String type, PluginSettings pluginSettings) {
+        super(index, type);
         this.pluginSettings = pluginSettings;
     }
 
@@ -84,18 +92,24 @@ public class AbstractRecordDaoImpl<T extends AbstractRecordDaoImpl> extends Abst
                     .endObject()
 
                     // time
-                    .startObject("time")
+                    .startObject(Record.PROPERTY_TIME)
                     .field("type", "integer")
                     .endObject()
 
                     // issuer
-                    .startObject("issuer")
+                    .startObject(Record.PROPERTY_ISSUER)
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+
+                    // hash
+                    .startObject(Record.PROPERTY_HASH)
                     .field("type", "string")
                     .field("index", "not_analyzed")
                     .endObject()
 
-                    // pubkey
-                    .startObject("pubkey")
+                    // signature
+                    .startObject(Record.PROPERTY_SIGNATURE)
                     .field("type", "string")
                     .field("index", "not_analyzed")
                     .endObject()
@@ -116,89 +130,117 @@ public class AbstractRecordDaoImpl<T extends AbstractRecordDaoImpl> extends Abst
                     .field("type", "geo_point")
                     .endObject()
 
-                    // thumbnail
-                    .startObject("thumbnail")
-                    .field("type", "attachment")
-                        .startObject("fields") // src
-                        .startObject("content") // title
-                            .field("index", "no")
+                    // avatar
+                    .startObject("avatar")
+                        .field("type", "attachment")
+                        .startObject("fields") // fields
+                            .startObject("content") // content
+                                .field("index", "no")
+                            .endObject()
+                            .startObject("title") // title
+                                .field("type", "string")
+                                .field("store", "no")
+                            .endObject()
+                            .startObject("author") // author
+                                .field("store", "no")
+                            .endObject()
+                            .startObject("content_type") // content_type
+                                .field("store", "yes")
+                            .endObject()
                         .endObject()
-                        .startObject("title") // title
-                            .field("type", "string")
-                            .field("store", "no")
+                    .endObject()
+
+                    // social networks
+                    .startObject("socials")
+                        .field("type", "nested")
+                        .field("dynamic", "false")
+                        .startObject("properties")
+                        .startObject("type") // type
+                        .field("type", "string")
+                        .field("index", "not_analyzed")
                         .endObject()
-                        .startObject("author") // title
-                            .field("store", "no")
+                        .startObject("url") // url
+                        .field("type", "string")
+                        .field("index", "not_analyzed")
                         .endObject()
-                        .startObject("content_type") // title
-                            .field("store", "yes")
                         .endObject()
-                    .endObject()
-                    .endObject()
+                        .endObject()
+
+                    // tags
+                    .startObject("tags")
+                        .field("type", "completion")
+                        .field("search_analyzer", "simple")
+                        .field("analyzer", "simple")
+                        .field("preserve_separators", "false")
+                    .endObject();
+
+            // pubkey
+            if (isPubkeyFieldEnable) {
+                mapping.startObject("pubkey")
+                        .field("type", "string")
+                        .field("index", "not_analyzed")
+                        .endObject();
+            }
 
-                    // pictures
-                    .startObject("pictures")
-                    .field("type", "nested")
-                    .field("dynamic", "false")
+            // pictures
+            if (isNestedPicturesEnable) {
+                mapping.startObject("pictures")
+                        .field("type", "nested")
+                        .field("dynamic", "false")
                         .startObject("properties")
-                            .startObject("file") // file
-                                .field("type", "attachment")
-                                .startObject("fields")
-                                    .startObject("content") // content
-                                        .field("index", "no")
-                                    .endObject()
-                                    .startObject("title") // title
-                                        .field("type", "string")
-                                        .field("store", "yes")
-                                        .field("analyzer", stringAnalyzer)
-                                    .endObject()
-                                    .startObject("author") // author
-                                        .field("type", "string")
-                                        .field("store", "no")
-                                    .endObject()
-                                    .startObject("content_type") // content_type
-                                        .field("store", "yes")
-                                    .endObject()
-                                .endObject()
-                            .endObject()
+                        .startObject("file") // file
+                        .field("type", "attachment")
+                        .startObject("fields")
+                        .startObject("content") // content
+                        .field("index", "no")
+                        .endObject()
+                        .startObject("title") // title
+                        .field("type", "string")
+                        .field("store", "yes")
+                        .field("analyzer", stringAnalyzer)
+                        .endObject()
+                        .startObject("author") // author
+                        .field("type", "string")
+                        .field("store", "no")
+                        .endObject()
+                        .startObject("content_type") // content_type
+                        .field("store", "yes")
+                        .endObject()
+                        .endObject()
+                        .endObject()
+                        .endObject()
                         .endObject()
-                    .endObject()
-
-                    // picturesCount
-                    .startObject("picturesCount")
-                    .field("type", "integer")
-                    .endObject()
 
-                    // category
-                    .startObject("category")
-                    .field("type", "nested")
-                    .field("dynamic", "false")
-                    .startObject("properties")
-                    .startObject("id") // id
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-                    .startObject("parent") // parent
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-                    .startObject("name") // name
-                    .field("type", "string")
-                    .field("analyzer", stringAnalyzer)
-                    .endObject()
-                    .endObject()
-                    .endObject()
+                        // picturesCount
+                        .startObject("picturesCount")
+                        .field("type", "integer")
+                        .endObject();
+            }
 
-                    // tags
-                    .startObject("tags")
-                    .field("type", "completion")
-                    .field("search_analyzer", "simple")
-                    .field("analyzer", "simple")
-                    .field("preserve_separators", "false")
-                    .endObject()
+            // category
+            if (isNestedCategoryEnable) {
+                mapping.startObject("category")
+                        .field("type", "nested")
+                        .field("dynamic", "false")
+                        .startObject("properties")
+                        .startObject("id") // id
+                        .field("type", "string")
+                        .field("index", "not_analyzed")
+                        .endObject()
+                        .startObject("parent") // parent
+                        .field("type", "string")
+                        .field("index", "not_analyzed")
+                        .endObject()
+                        .startObject("name") // name
+                        .field("type", "string")
+                        .field("analyzer", stringAnalyzer)
+                        .endObject()
+                        .endObject()
+                        .endObject();
+            }
 
-                    .endObject()
-                    .endObject().endObject();
+            mapping.endObject()
+                .endObject().endObject();
 
             return mapping;
         }
@@ -206,4 +248,18 @@ public class AbstractRecordDaoImpl<T extends AbstractRecordDaoImpl> extends Abst
             throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", getIndex(), getType(), ioe.getMessage()), ioe);
         }
     }
+
+    /* -- protected methods -- */
+
+    protected void setNestedPicturesEnable(boolean isPicturesEnable) {
+        this.isNestedPicturesEnable = isPicturesEnable;
+    }
+
+    protected void setNestedCategoryEnable(boolean isNestedCategoryEnable) {
+        this.isNestedCategoryEnable = isNestedCategoryEnable;
+    }
+
+    protected void setPubkeyFieldEnable(boolean isPubkeyFieldEnable) {
+        this.isPubkeyFieldEnable = isPubkeyFieldEnable;
+    }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/DaoModule.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/DaoModule.java
index a8319944e50e8865fea6e5c1bd7f621fc37a4374..c0431f7dd58f12c071762cd81877961c9450e044 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/DaoModule.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/DaoModule.java
@@ -22,7 +22,9 @@ package org.duniter.elasticsearch.user.dao;
  * #L%
  */
 
+import org.duniter.elasticsearch.user.dao.group.*;
 import org.duniter.elasticsearch.user.dao.page.*;
+import org.duniter.elasticsearch.user.dao.profile.*;
 import org.elasticsearch.common.inject.AbstractModule;
 import org.elasticsearch.common.inject.Module;
 
@@ -30,10 +32,20 @@ public class DaoModule extends AbstractModule implements Module {
 
     @Override protected void configure() {
 
+        // User
+        bind(UserIndexDao.class).to(UserIndexDaoImpl.class).asEagerSingleton();
+        bind(UserProfileDao.class).to(UserProfileDaoImpl.class).asEagerSingleton();
+        bind(UserSettingsDao.class).to(UserSettingsDaoImpl.class).asEagerSingleton();
+
         // Page
-        bind(RegistryIndexDao.class).to(RegistryIndexDaoImpl.class).asEagerSingleton();
-        bind(RegistryCommentDao.class).to(RegistryCommentDaoImpl.class).asEagerSingleton();
-        bind(RegistryRecordDao.class).to(RegistryRecordDaoImpl.class).asEagerSingleton();
+        bind(PageIndexDao.class).to(PageIndexDaoImpl.class).asEagerSingleton();
+        bind(PageCommentDao.class).to(PageCommentDaoImpl.class).asEagerSingleton();
+        bind(PageRecordDao.class).to(PageRecordDaoImpl.class).asEagerSingleton();
+
+        // Group
+        bind(GroupIndexDao.class).to(GroupIndexDaoImpl.class).asEagerSingleton();
+        bind(GroupCommentDao.class).to(GroupCommentDaoImpl.class).asEagerSingleton();
+        bind(GroupRecordDao.class).to(GroupRecordDaoImpl.class).asEagerSingleton();
 
     }
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/RecordDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/RecordDao.java
index 8af2a0e01252dacbaddcf2be6a1db0b177599d5e..aebfefeb36f35318831bf0480f803a184acbe87f 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/RecordDao.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/RecordDao.java
@@ -32,6 +32,8 @@ public interface RecordDao<T extends RecordDao> extends IndexTypeDao<T> {
 
     String TYPE = "record";
 
+    String PROPERTY_AVATAR = "avatar";
+
     String create(final String json);
 
     void update(final String id, final String json);
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupCommentDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupCommentDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..6dc51a5a7ade5c83274f4fee6143a855c2f6f528
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupCommentDao.java
@@ -0,0 +1,31 @@
+package org.duniter.elasticsearch.user.dao.group;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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.user.dao.CommentDao;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public interface GroupCommentDao extends CommentDao {
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupCommentDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupCommentDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a94256941e606d033133f5a151afeaec38fc3a9
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupCommentDaoImpl.java
@@ -0,0 +1,39 @@
+package org.duniter.elasticsearch.user.dao.group;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.AbstractCommentDaoImpl;
+import org.elasticsearch.common.inject.Inject;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public class GroupCommentDaoImpl extends AbstractCommentDaoImpl implements GroupCommentDao {
+
+
+    @Inject
+    public GroupCommentDaoImpl(PluginSettings pluginSettings) {
+        super(GroupIndexDao.INDEX, pluginSettings);
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupIndexDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupIndexDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..98fb10308ee3abb4a8a7bb387d97ae3765a18b79
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupIndexDao.java
@@ -0,0 +1,33 @@
+package org.duniter.elasticsearch.user.dao.group;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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.dao.IndexDao;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public interface GroupIndexDao extends IndexDao<GroupIndexDao> {
+    String INDEX = "group";
+    String CATEGORY_TYPE = "category";
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupIndexDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupIndexDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..662ad6ae27b7083c4dd874892cecb89b0c7e59e0
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupIndexDaoImpl.java
@@ -0,0 +1,74 @@
+package org.duniter.elasticsearch.user.dao.group;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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 com.fasterxml.jackson.core.JsonProcessingException;
+import org.duniter.core.exception.TechnicalException;
+import org.duniter.elasticsearch.dao.AbstractIndexDao;
+import org.duniter.elasticsearch.dao.handler.AddSequenceAttributeHandler;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.CommentDao;
+import org.duniter.elasticsearch.user.dao.RecordDao;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+
+import java.io.IOException;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public class GroupIndexDaoImpl extends AbstractIndexDao<GroupIndexDao> implements GroupIndexDao {
+
+
+    private PluginSettings pluginSettings;
+    private RecordDao recordDao;
+    private CommentDao commentDao;
+
+    @Inject
+    public GroupIndexDaoImpl(PluginSettings pluginSettings, GroupRecordDao recordDao, GroupCommentDao commentDao) {
+        super(INDEX);
+
+        this.pluginSettings = pluginSettings;
+        this.commentDao = commentDao;
+        this.recordDao = recordDao;
+    }
+
+    @Override
+    protected void createIndex() throws JsonProcessingException {
+        logger.info(String.format("Creating index [%s]", getIndex()));
+
+        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(getIndex());
+        org.elasticsearch.common.settings.Settings indexSettings = org.elasticsearch.common.settings.Settings.settingsBuilder()
+                .put("number_of_shards", 3)
+                .put("number_of_replicas", 1)
+                //.put("analyzer", createDefaultAnalyzer())
+                .build();
+        createIndexRequestBuilder.setSettings(indexSettings);
+        createIndexRequestBuilder.addMapping(recordDao.getType(), recordDao.createTypeMapping());
+        createIndexRequestBuilder.addMapping(commentDao.getType(), commentDao.createTypeMapping());
+        createIndexRequestBuilder.execute().actionGet();
+    }
+
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupRecordDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupRecordDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0e2a553f78744c9e68181a24d8fe73b68b16fc0
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupRecordDao.java
@@ -0,0 +1,33 @@
+package org.duniter.elasticsearch.user.dao.group;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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.user.dao.RecordDao;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public interface GroupRecordDao extends RecordDao {
+
+    String create(String id, String json);
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupRecordDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupRecordDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..79fa981f55b11ebb6c56269cbd82910dd6cba98a
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/group/GroupRecordDaoImpl.java
@@ -0,0 +1,53 @@
+package org.duniter.elasticsearch.user.dao.group;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.AbstractRecordDaoImpl;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.common.inject.Inject;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public class GroupRecordDaoImpl extends AbstractRecordDaoImpl implements GroupRecordDao {
+
+    @Inject
+    public GroupRecordDaoImpl(PluginSettings pluginSettings) {
+        super(GroupIndexDao.INDEX, pluginSettings);
+
+        setNestedPicturesEnable(true);
+        setNestedCategoryEnable(false); // no category
+        setPubkeyFieldEnable(false); // no pubkey (only issuer)
+    }
+
+    public String create(String id, String json) {
+
+        IndexResponse response = client.prepareIndex(getIndex(), getType())
+                .setSource(json)
+                .setId(id)
+                .setRefresh(false)
+                .execute().actionGet();
+        return response.getId();
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryCommentDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageCommentDao.java
similarity index 94%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryCommentDao.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageCommentDao.java
index b3ccb8522e85d52b3fb5f2d697fdcb89d2635f46..5ebb33e017508f987667cb6b6bd21c6b67d592f8 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryCommentDao.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageCommentDao.java
@@ -27,5 +27,5 @@ import org.duniter.elasticsearch.user.dao.CommentDao;
 /**
  * Created by blavenie on 03/04/17.
  */
-public interface RegistryCommentDao extends CommentDao {
+public interface PageCommentDao extends CommentDao {
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryCommentDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageCommentDaoImpl.java
similarity index 82%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryCommentDaoImpl.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageCommentDaoImpl.java
index 049ab0ee4491d071526c317e7aa41ca49929d847..05ccd5df775256d7f220cae0d204670d2f34b7ed 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryCommentDaoImpl.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageCommentDaoImpl.java
@@ -29,11 +29,11 @@ import org.elasticsearch.common.inject.Inject;
 /**
  * Created by blavenie on 03/04/17.
  */
-public class RegistryCommentDaoImpl extends AbstractCommentDaoImpl implements RegistryCommentDao {
+public class PageCommentDaoImpl extends AbstractCommentDaoImpl implements PageCommentDao {
 
 
     @Inject
-    public RegistryCommentDaoImpl(PluginSettings pluginSettings) {
-        super(RegistryIndexDao.INDEX, pluginSettings);
+    public PageCommentDaoImpl(PluginSettings pluginSettings) {
+        super(PageIndexDao.INDEX, pluginSettings);
     }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryIndexDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageIndexDao.java
similarity index 93%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryIndexDao.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageIndexDao.java
index d8d3b3fca18b5d2b4d7ec9461ebb98ad1cd9ee4c..9cea7936678e616b1c66b9f1de07958517de7e02 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryIndexDao.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageIndexDao.java
@@ -27,7 +27,7 @@ import org.duniter.elasticsearch.dao.IndexDao;
 /**
  * Created by blavenie on 03/04/17.
  */
-public interface RegistryIndexDao extends IndexDao<RegistryIndexDao> {
+public interface PageIndexDao extends IndexDao<PageIndexDao> {
     String INDEX = "page";
     String CATEGORY_TYPE = "category";
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryIndexDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageIndexDaoImpl.java
similarity index 85%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryIndexDaoImpl.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageIndexDaoImpl.java
index b2ae5e979784b5f9de2f6f39ec9b0e36757365d4..1d69e5b32ccf18f31f4db2a011cee3a836d1f070 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryIndexDaoImpl.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageIndexDaoImpl.java
@@ -39,7 +39,7 @@ import java.io.IOException;
 /**
  * Created by blavenie on 03/04/17.
  */
-public class RegistryIndexDaoImpl extends AbstractIndexDao<RegistryIndexDao> implements RegistryIndexDao {
+public class PageIndexDaoImpl extends AbstractIndexDao<PageIndexDao> implements PageIndexDao {
 
 
     private static final String CATEGORIES_BULK_CLASSPATH_FILE = "page-categories-bulk-insert.json";
@@ -49,8 +49,8 @@ public class RegistryIndexDaoImpl extends AbstractIndexDao<RegistryIndexDao> imp
     private CommentDao commentDao;
 
     @Inject
-    public RegistryIndexDaoImpl(PluginSettings pluginSettings, RegistryRecordDao recordDao, RegistryCommentDao commentDao) {
-        super(RegistryIndexDao.INDEX);
+    public PageIndexDaoImpl(PluginSettings pluginSettings, PageRecordDao recordDao, PageCommentDao commentDao) {
+        super(INDEX);
 
         this.pluginSettings = pluginSettings;
         this.commentDao = commentDao;
@@ -60,9 +60,9 @@ public class RegistryIndexDaoImpl extends AbstractIndexDao<RegistryIndexDao> imp
 
     @Override
     protected void createIndex() throws JsonProcessingException {
-        logger.info(String.format("Creating index [%s]", INDEX));
+        logger.info(String.format("Creating index [%s]", getIndex()));
 
-        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(INDEX);
+        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(getIndex());
         org.elasticsearch.common.settings.Settings indexSettings = org.elasticsearch.common.settings.Settings.settingsBuilder()
                 .put("number_of_shards", 3)
                 .put("number_of_replicas", 1)
@@ -71,7 +71,7 @@ public class RegistryIndexDaoImpl extends AbstractIndexDao<RegistryIndexDao> imp
         createIndexRequestBuilder.setSettings(indexSettings);
         createIndexRequestBuilder.addMapping(recordDao.getType(), recordDao.createTypeMapping());
         createIndexRequestBuilder.addMapping(commentDao.getType(), commentDao.createTypeMapping());
-        createIndexRequestBuilder.addMapping(RegistryIndexDao.CATEGORY_TYPE, createCategoryTypeMapping());
+        createIndexRequestBuilder.addMapping(PageIndexDao.CATEGORY_TYPE, createCategoryTypeMapping());
         createIndexRequestBuilder.execute().actionGet();
 
         // Fill categories
@@ -80,13 +80,13 @@ public class RegistryIndexDaoImpl extends AbstractIndexDao<RegistryIndexDao> imp
 
     public void fillRecordCategories() {
         if (logger.isDebugEnabled()) {
-            logger.debug(String.format("[%s/%s] Fill data", INDEX, RegistryIndexDao.CATEGORY_TYPE));
+            logger.debug(String.format("[%s/%s] Fill data", getIndex(), PageIndexDao.CATEGORY_TYPE));
         }
 
         // Insert categories
         client.bulkFromClasspathFile(CATEGORIES_BULK_CLASSPATH_FILE,
-                RegistryIndexDao.INDEX,
-                RegistryIndexDao.CATEGORY_TYPE,
+                getIndex(),
+                PageIndexDao.CATEGORY_TYPE,
                 // Add order attribute
                 new AddSequenceAttributeHandler("order", "\\{.*\"name\".*\\}", 1));
     }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryRecordDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageRecordDao.java
similarity index 94%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryRecordDao.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageRecordDao.java
index 87543aa7c370614427c47c3093ae2a0307bba9d9..6217dfe00a326bc7f3c827a44c398ed196f84328 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryRecordDao.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageRecordDao.java
@@ -27,5 +27,5 @@ import org.duniter.elasticsearch.user.dao.RecordDao;
 /**
  * Created by blavenie on 03/04/17.
  */
-public interface RegistryRecordDao extends RecordDao {
+public interface PageRecordDao extends RecordDao {
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryRecordDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageRecordDaoImpl.java
similarity index 76%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryRecordDaoImpl.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageRecordDaoImpl.java
index 602fa3f27adbb60c624dfdf03ce9edcbe17c71aa..468ceb4f3673710aa2d9993f61919118772c25c8 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/RegistryRecordDaoImpl.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/page/PageRecordDaoImpl.java
@@ -29,10 +29,14 @@ import org.elasticsearch.common.inject.Inject;
 /**
  * Created by blavenie on 03/04/17.
  */
-public class RegistryRecordDaoImpl extends AbstractRecordDaoImpl implements RegistryRecordDao {
+public class PageRecordDaoImpl extends AbstractRecordDaoImpl implements PageRecordDao {
 
     @Inject
-    public RegistryRecordDaoImpl(PluginSettings pluginSettings) {
-        super(RegistryIndexDao.INDEX, pluginSettings);
+    public PageRecordDaoImpl(PluginSettings pluginSettings) {
+        super(PageIndexDao.INDEX, pluginSettings);
+
+        setNestedPicturesEnable(true);
+        setNestedCategoryEnable(true);
+        setPubkeyFieldEnable(true);
     }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserIndexDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserIndexDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..77dd8933f3947c578ab728aebf2fc4d3fcb80954
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserIndexDao.java
@@ -0,0 +1,32 @@
+package org.duniter.elasticsearch.user.dao.profile;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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.dao.IndexDao;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public interface UserIndexDao extends IndexDao<UserIndexDao> {
+    String INDEX = "user";
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserIndexDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserIndexDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..8858df1b958387352fc64bd8688d8ccce49e1042
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserIndexDaoImpl.java
@@ -0,0 +1,70 @@
+package org.duniter.elasticsearch.user.dao.profile;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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 com.fasterxml.jackson.core.JsonProcessingException;
+import org.duniter.elasticsearch.dao.AbstractIndexDao;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.service.UserEventService;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
+import org.elasticsearch.common.inject.Inject;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public class UserIndexDaoImpl extends AbstractIndexDao<UserIndexDao> implements UserIndexDao {
+
+
+    private PluginSettings pluginSettings;
+    private UserProfileDao profileDao;
+    private UserSettingsDao settingsDao;
+
+    @Inject
+    public UserIndexDaoImpl(PluginSettings pluginSettings, UserProfileDao profileDao, UserSettingsDao settingsDao) {
+        super(INDEX);
+
+        this.pluginSettings = pluginSettings;
+        this.settingsDao = settingsDao;
+        this.profileDao = profileDao;
+    }
+
+    /**
+     * Create index for mail
+     * @throws JsonProcessingException
+     */
+    public void createIndex() throws JsonProcessingException {
+        logger.info(String.format("Creating index [%s]", getIndex()));
+
+        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(getIndex());
+        org.elasticsearch.common.settings.Settings indexSettings = org.elasticsearch.common.settings.Settings.settingsBuilder()
+                .put("number_of_shards", 3)
+                .put("number_of_replicas", 1)
+                //.put("analyzer", createDefaultAnalyzer())
+                .build();
+        createIndexRequestBuilder.setSettings(indexSettings);
+        createIndexRequestBuilder.addMapping(profileDao.getType(), profileDao.createTypeMapping());
+        createIndexRequestBuilder.addMapping(settingsDao.getType(), settingsDao.createTypeMapping());
+        createIndexRequestBuilder.addMapping(UserEventService.EVENT_TYPE, UserEventService.createEventType());
+        createIndexRequestBuilder.execute().actionGet();
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserProfileDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserProfileDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..928714925550eac8706b4a37b886c52b0ab2d537
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserProfileDao.java
@@ -0,0 +1,10 @@
+package org.duniter.elasticsearch.user.dao.profile;
+
+import org.duniter.elasticsearch.user.dao.RecordDao;
+
+public interface UserProfileDao<T extends UserProfileDao> extends RecordDao<T> {
+
+    String TYPE = "profile";
+
+    String create(final String issuer, final String json);
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserProfileDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserProfileDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ce2f972d66cfb705ba3a78ddbd0a718f8469036
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserProfileDaoImpl.java
@@ -0,0 +1,190 @@
+package org.duniter.elasticsearch.user.dao.profile;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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 com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.duniter.core.client.model.elasticsearch.Record;
+import org.duniter.core.exception.TechnicalException;
+import org.duniter.core.util.ObjectUtils;
+import org.duniter.core.util.Preconditions;
+import org.duniter.elasticsearch.dao.AbstractIndexTypeDao;
+import org.duniter.elasticsearch.exception.InvalidFormatException;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+
+import java.io.IOException;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public class UserProfileDaoImpl extends AbstractIndexTypeDao<UserProfileDaoImpl> implements UserProfileDao<UserProfileDaoImpl> {
+
+    private PluginSettings pluginSettings;
+
+    @Inject
+    public UserProfileDaoImpl(PluginSettings pluginSettings) {
+        super(UserIndexDao.INDEX, UserProfileDao.TYPE);
+        this.pluginSettings = pluginSettings;
+    }
+
+    @Override
+    protected void createIndex() throws JsonProcessingException {
+        throw new TechnicalException("not implemented");
+    }
+
+    @Override
+    public void checkSameDocumentIssuer(String id, String expectedIssuer) {
+        String issuer = getMandatoryFieldsById(id, Record.PROPERTY_ISSUER).get(Record.PROPERTY_ISSUER).toString();
+        if (!ObjectUtils.equals(expectedIssuer, issuer)) {
+            throw new TechnicalException("Not same issuer");
+        }
+    }
+
+    @Override
+    public String create(final String json) {
+        try {
+            JsonNode actualObj = getObjectMapper().readTree(json);
+            String issuer = actualObj.get(Record.PROPERTY_ISSUER).asText();
+
+            return create(issuer, json);
+        }
+        catch(IOException e) {
+            throw new InvalidFormatException("Invalid record JSON: " + e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public String create(final String issuer, final String json) {
+
+        IndexResponse response = client.prepareIndex(getIndex(), getType())
+                .setSource(json)
+                .setId(issuer) // always use the issuer pubkey as id
+                .setRefresh(false)
+                .execute().actionGet();
+        return response.getId();
+    }
+
+    @Override
+    public XContentBuilder createTypeMapping() {
+        String stringAnalyzer = pluginSettings.getDefaultStringAnalyzer();
+
+        try {
+            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(getType())
+                    .startObject("properties")
+
+                    // title
+                    .startObject("title")
+                    .field("type", "string")
+                    .field("analyzer", stringAnalyzer)
+                    .endObject()
+
+                    // description
+                    .startObject("description")
+                    .field("type", "string")
+                    .field("analyzer", stringAnalyzer)
+                    .endObject()
+
+                    // time
+                    .startObject("time")
+                    .field("type", "integer")
+                    .endObject()
+
+                    // issuer
+                    .startObject("issuer")
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+
+                    // city
+                    .startObject("city")
+                    .field("type", "string")
+                    .endObject()
+
+                    // address
+                    .startObject("address")
+                    .field("type", "string")
+                    .endObject()
+
+                    // geoPoint
+                    .startObject("geoPoint")
+                    .field("type", "geo_point")
+                    .endObject()
+
+                    // avatar
+                    .startObject("avatar")
+                    .field("type", "attachment")
+                    .startObject("fields") // fields
+                    .startObject("content") // content
+                    .field("index", "no")
+                    .endObject()
+                    .startObject("title") // title
+                    .field("type", "string")
+                    .field("store", "no")
+                    .endObject()
+                    .startObject("author") // author
+                    .field("store", "no")
+                    .endObject()
+                    .startObject("content_type") // content_type
+                    .field("store", "yes")
+                    .endObject()
+                    .endObject()
+                    .endObject()
+
+                    // social networks
+                    .startObject("socials")
+                    .field("type", "nested")
+                    .field("dynamic", "false")
+                    .startObject("properties")
+                    .startObject("type") // type
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+                    .startObject("url") // url
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+                    .endObject()
+                    .endObject()
+
+                    // tags
+                    .startObject("tags")
+                    .field("type", "completion")
+                    .field("search_analyzer", "simple")
+                    .field("analyzer", "simple")
+                    .field("preserve_separators", "false")
+                    .endObject()
+
+                    .endObject()
+                    .endObject().endObject();
+
+            return mapping;
+        }
+        catch(IOException ioe) {
+            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", getIndex(), getType(), ioe.getMessage()), ioe);
+        }
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserSettingsDao.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserSettingsDao.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f267f86bc1cb559a05a0ff98e5b368ce210fae0
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserSettingsDao.java
@@ -0,0 +1,10 @@
+package org.duniter.elasticsearch.user.dao.profile;
+
+import org.duniter.elasticsearch.user.dao.RecordDao;
+
+public interface UserSettingsDao<T extends UserSettingsDao> extends RecordDao<T> {
+
+    String TYPE = "settings";
+
+    String create(final String issuer, final String json);
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserSettingsDaoImpl.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserSettingsDaoImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..77e6c09668d9a8b6da071f001d75deb32594e376
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/dao/profile/UserSettingsDaoImpl.java
@@ -0,0 +1,127 @@
+package org.duniter.elasticsearch.user.dao.profile;
+
+/*
+ * #%L
+ * Äžchange Pod :: ElasticSearch plugin
+ * %%
+ * Copyright (C) 2014 - 2017 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 com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.duniter.core.client.model.elasticsearch.Record;
+import org.duniter.core.exception.TechnicalException;
+import org.duniter.core.util.ObjectUtils;
+import org.duniter.elasticsearch.dao.AbstractIndexTypeDao;
+import org.duniter.elasticsearch.exception.InvalidFormatException;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+
+import java.io.IOException;
+
+/**
+ * Created by blavenie on 03/04/17.
+ */
+public class UserSettingsDaoImpl extends AbstractIndexTypeDao<UserSettingsDaoImpl>
+        implements UserSettingsDao<UserSettingsDaoImpl> {
+
+    @Inject
+    public UserSettingsDaoImpl() {
+        super(UserIndexDao.INDEX, UserSettingsDao.TYPE);
+    }
+
+    @Override
+    protected void createIndex() throws JsonProcessingException {
+        throw new TechnicalException("not implemented");
+    }
+
+    @Override
+    public void checkSameDocumentIssuer(String id, String expectedIssuer) {
+        String issuer = getMandatoryFieldsById(id, Record.PROPERTY_ISSUER).get(Record.PROPERTY_ISSUER).toString();
+        if (!ObjectUtils.equals(expectedIssuer, issuer)) {
+            throw new TechnicalException("Not same issuer");
+        }
+    }
+
+    @Override
+    public String create(final String json) {
+        try {
+            JsonNode actualObj = getObjectMapper().readTree(json);
+            String issuer = actualObj.get(Record.PROPERTY_ISSUER).asText();
+
+            return create(issuer, json);
+        }
+        catch(IOException e) {
+            throw new InvalidFormatException("Invalid record JSON: " + e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public String create(final String issuer, final String json) {
+
+        IndexResponse response = client.prepareIndex(getIndex(), getType())
+                .setSource(json)
+                .setId(issuer) // always use the issuer pubkey as id
+                .setRefresh(false)
+                .execute().actionGet();
+        return response.getId();
+    }
+
+    @Override
+    public XContentBuilder createTypeMapping() {
+
+        try {
+            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(getType())
+                    .startObject("properties")
+
+                    // time
+                    .startObject("time")
+                    .field("type", "integer")
+                    .endObject()
+
+                    // issuer
+                    .startObject("issuer")
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+
+                    // nonce
+                    .startObject("nonce")
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+
+                    // content
+                    .startObject("content")
+                    .field("type", "string")
+                    .field("index", "not_analyzed")
+                    .endObject()
+
+                    .endObject()
+                    .endObject().endObject();
+
+            return mapping;
+        }
+        catch(IOException ioe) {
+            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", getIndex(), getType(), ioe.getMessage()), ioe);
+        }
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java
index 5af0224d844c433f1f997b111763c74784100208..1422b77c0aac986165ae788fa60932df524ed010 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java
@@ -22,9 +22,7 @@ package org.duniter.elasticsearch.user.rest;
  * #L%
  */
 
-import org.duniter.elasticsearch.user.rest.group.RestGroupImageAction;
-import org.duniter.elasticsearch.user.rest.group.RestGroupIndexAction;
-import org.duniter.elasticsearch.user.rest.group.RestGroupUpdateAction;
+import org.duniter.elasticsearch.user.rest.group.*;
 import org.duniter.elasticsearch.user.rest.history.RestHistoryDeleteIndexAction;
 import org.duniter.elasticsearch.user.rest.invitation.RestInvitationCertificationIndexAction;
 import org.duniter.elasticsearch.user.rest.message.RestMessageInboxIndexAction;
@@ -56,6 +54,8 @@ public class RestModule extends AbstractModule implements Module {
         // Group
         bind(RestGroupIndexAction.class).asEagerSingleton();
         bind(RestGroupUpdateAction.class).asEagerSingleton();
+        bind(RestGroupCommentIndexAction.class).asEagerSingleton();
+        bind(RestGroupCommentUpdateAction.class).asEagerSingleton();
         bind(RestGroupImageAction.class).asEagerSingleton();
 
         // History
@@ -70,12 +70,12 @@ public class RestModule extends AbstractModule implements Module {
         bind(RestInvitationCertificationIndexAction.class).asEagerSingleton();
 
         // Page
-        bind(RestRegistryRecordIndexAction.class).asEagerSingleton();
-        bind(RestRegistryRecordUpdateAction.class).asEagerSingleton();
-        bind(RestRegistryCommentIndexAction.class).asEagerSingleton();
-        bind(RestRegistryCommentUpdateAction.class).asEagerSingleton();
-        bind(RestRegistryCategoryAction.class).asEagerSingleton();
-        bind(RestRegistryImageAction.class).asEagerSingleton();
+        bind(RestPageRecordIndexAction.class).asEagerSingleton();
+        bind(RestPageRecordUpdateAction.class).asEagerSingleton();
+        bind(RestPageCommentIndexAction.class).asEagerSingleton();
+        bind(RestPageCommentUpdateAction.class).asEagerSingleton();
+        bind(RestPageCategoryAction.class).asEagerSingleton();
+        bind(RestPageImageAction.class).asEagerSingleton();
 
         // Mixed search
         bind(RestMixedSearchAction.class).asEagerSingleton();
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupCommentIndexAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupCommentIndexAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..cab09d101cad130111d6431a9e67955466b759c3
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupCommentIndexAction.java
@@ -0,0 +1,45 @@
+package org.duniter.elasticsearch.user.rest.group;
+
+/*
+ * #%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.rest.AbstractRestPostIndexAction;
+import org.duniter.elasticsearch.rest.security.RestSecurityController;
+import org.duniter.elasticsearch.user.dao.group.GroupCommentDao;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.service.GroupService;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestController;
+
+public class RestGroupCommentIndexAction extends AbstractRestPostIndexAction {
+
+    @Inject
+    public RestGroupCommentIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                       GroupService service) {
+        super(settings, controller, client, securityController,
+                GroupIndexDao.INDEX, GroupCommentDao.TYPE,
+                json -> service.indexCommentFromJson(json));
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupCommentUpdateAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupCommentUpdateAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..873c19535d765aa2ba8937ce72c943c247e695b8
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupCommentUpdateAction.java
@@ -0,0 +1,45 @@
+package org.duniter.elasticsearch.user.rest.group;
+
+/*
+ * #%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.rest.AbstractRestPostUpdateAction;
+import org.duniter.elasticsearch.rest.security.RestSecurityController;
+import org.duniter.elasticsearch.user.dao.group.GroupCommentDao;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.service.GroupService;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestController;
+
+public class RestGroupCommentUpdateAction extends AbstractRestPostUpdateAction {
+
+    @Inject
+    public RestGroupCommentUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                        GroupService service) {
+        super(settings, controller, client, securityController,
+                GroupIndexDao.INDEX, GroupCommentDao.TYPE,
+                (id, json) -> service.updateCommentFromJson(id, json));
+    }
+
+}
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupImageAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupImageAction.java
index d235e85346925be17e679e38049e31ba653d280a..7649db196b6ed05808b43d6df208ef71fadb491f 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupImageAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupImageAction.java
@@ -24,7 +24,8 @@ package org.duniter.elasticsearch.user.rest.group;
 
 import org.duniter.core.client.model.elasticsearch.UserGroup;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
-import org.duniter.elasticsearch.user.service.GroupService;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.group.GroupRecordDao;
 import org.elasticsearch.common.inject.Inject;
 
 public class RestGroupImageAction {
@@ -32,9 +33,8 @@ public class RestGroupImageAction {
     @Inject
     public RestGroupImageAction(RestSecurityController securityController) {
 
-        // Allow to get thumbnail
-        securityController.allowImageAttachment(GroupService.INDEX, GroupService.RECORD_TYPE, UserGroup.PROPERTY_THUMBNAIL);
+        // Allow to get avatar
+        securityController.allowImageAttachment(GroupIndexDao.INDEX, GroupRecordDao.TYPE, UserGroup.PROPERTY_AVATAR);
 
-        // TODO : allow to get pictures
     }
 }
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupIndexAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupIndexAction.java
index 6055efe7e84f575de1880ef89b8a0ce92b700cfd..ef33347a059e4003777b83c862e67732725840c1 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupIndexAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupIndexAction.java
@@ -24,6 +24,8 @@ package org.duniter.elasticsearch.user.rest.group;
 
 import org.duniter.elasticsearch.rest.AbstractRestPostIndexAction;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.group.GroupRecordDao;
 import org.duniter.elasticsearch.user.service.GroupService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
@@ -37,8 +39,8 @@ public class RestGroupIndexAction extends AbstractRestPostIndexAction {
                                 RestSecurityController securityController,
                                 GroupService service) {
         super(settings, controller, client, securityController,
-                GroupService.INDEX,
-                GroupService.RECORD_TYPE,
+                GroupIndexDao.INDEX,
+                GroupRecordDao.TYPE,
                 json -> service.indexRecordProfileFromJson(json));
     }
 }
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupUpdateAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupUpdateAction.java
index b9b89b2129e55e880a52de6a2e6fc94b687efbc4..6aaf9d24c5bd6cba158fad666ef00a684b3bd88c 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupUpdateAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/group/RestGroupUpdateAction.java
@@ -24,8 +24,9 @@ package org.duniter.elasticsearch.user.rest.group;
 
 import org.duniter.elasticsearch.rest.AbstractRestPostUpdateAction;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.group.GroupRecordDao;
 import org.duniter.elasticsearch.user.service.GroupService;
-import org.duniter.elasticsearch.user.service.UserService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
@@ -38,8 +39,8 @@ public class RestGroupUpdateAction extends AbstractRestPostUpdateAction {
                                  RestSecurityController securityController,
                                  GroupService service) {
         super(settings, controller, client, securityController,
-                GroupService.INDEX,
-                GroupService.RECORD_TYPE,
+                GroupIndexDao.INDEX,
+                GroupRecordDao.TYPE,
                 (id, json) -> service.updateRecordFromJson(id, json));
     }
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/mixed/RestMixedSearchAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/mixed/RestMixedSearchAction.java
index 5d7a7421388669a261a3f143ce1c44a9ad74d0c6..26b4b4e3ba34e9a3b6b840632463de6c2cb7f9c4 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/mixed/RestMixedSearchAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/mixed/RestMixedSearchAction.java
@@ -23,8 +23,9 @@ package org.duniter.elasticsearch.user.rest.mixed;
  */
 
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.duniter.elasticsearch.user.service.GroupService;
 import org.duniter.elasticsearch.user.service.UserService;
 import org.elasticsearch.common.inject.Inject;
@@ -41,13 +42,13 @@ public class RestMixedSearchAction {
         String[] paths = {
             // Allow search on profile + page + group
             String.format("/%s,%s,%s/%s,%s/_search",
-                UserService.INDEX, RegistryIndexDao.INDEX, GroupService.INDEX,
-                UserService.PROFILE_TYPE, RegistryRecordDao.TYPE),
+                UserService.INDEX, PageIndexDao.INDEX, GroupIndexDao.INDEX,
+                UserService.PROFILE_TYPE, PageRecordDao.TYPE),
 
             // Allow search on profile + page
             String.format("/%s,%s/%s,%s/_search",
-                    UserService.INDEX, RegistryIndexDao.INDEX,
-                    UserService.PROFILE_TYPE, RegistryRecordDao.TYPE)
+                    UserService.INDEX, PageIndexDao.INDEX,
+                    UserService.PROFILE_TYPE, PageRecordDao.TYPE)
         };
 
         for(String path: paths) {
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCategoryAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCategoryAction.java
similarity index 81%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCategoryAction.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCategoryAction.java
index e4e901a35aa948bb6701f5131e1536d5e92043f1..7e9cd624ad22890ade37011e4f73b5027660786f 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCategoryAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCategoryAction.java
@@ -22,17 +22,17 @@ package org.duniter.elasticsearch.user.rest.page;
  * #L%
  */
 
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.rest.RestRequest;
 
-public class RestRegistryCategoryAction {
+public class RestPageCategoryAction {
 
     @Inject
-    public RestRegistryCategoryAction(RestSecurityController securityController) {
+    public RestPageCategoryAction(RestSecurityController securityController) {
         // Add security rule for category
-        securityController.allowIndexType(RestRequest.Method.GET, RegistryIndexDao.INDEX, RegistryIndexDao.CATEGORY_TYPE);
+        securityController.allowIndexType(RestRequest.Method.GET, PageIndexDao.INDEX, PageIndexDao.CATEGORY_TYPE);
     }
 
 }
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCommentIndexAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCommentIndexAction.java
similarity index 73%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCommentIndexAction.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCommentIndexAction.java
index 31b830d43878e95a9d27f0a4b13f893027fb85f3..e228eca78a8cffdb6d7d984ae30e6ca11fe36fda 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCommentIndexAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCommentIndexAction.java
@@ -22,8 +22,8 @@ package org.duniter.elasticsearch.user.rest.page;
  * #L%
  */
 
-import org.duniter.elasticsearch.user.dao.page.RegistryCommentDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageCommentDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
 import org.duniter.elasticsearch.user.service.PageService;
 import org.duniter.elasticsearch.rest.AbstractRestPostIndexAction;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
@@ -32,13 +32,13 @@ import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.rest.RestController;
 
-public class RestRegistryCommentIndexAction extends AbstractRestPostIndexAction {
+public class RestPageCommentIndexAction extends AbstractRestPostIndexAction {
 
     @Inject
-    public RestRegistryCommentIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
-                                          PageService service) {
+    public RestPageCommentIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                      PageService service) {
         super(settings, controller, client, securityController,
-                RegistryIndexDao.INDEX, RegistryCommentDao.TYPE,
+                PageIndexDao.INDEX, PageCommentDao.TYPE,
                 json -> service.indexCommentFromJson(json));
     }
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCommentUpdateAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCommentUpdateAction.java
similarity index 73%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCommentUpdateAction.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCommentUpdateAction.java
index ff4c84b0d5a1a4d81de71e8140970a1ad9a98e82..119605cb242f6d770867660f66992ed998b10356 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryCommentUpdateAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageCommentUpdateAction.java
@@ -22,8 +22,8 @@ package org.duniter.elasticsearch.user.rest.page;
  * #L%
  */
 
-import org.duniter.elasticsearch.user.dao.page.RegistryCommentDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageCommentDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
 import org.duniter.elasticsearch.user.service.PageService;
 import org.duniter.elasticsearch.rest.AbstractRestPostUpdateAction;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
@@ -32,13 +32,13 @@ import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.rest.RestController;
 
-public class RestRegistryCommentUpdateAction extends AbstractRestPostUpdateAction {
+public class RestPageCommentUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestRegistryCommentUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
-                                           PageService service) {
+    public RestPageCommentUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                       PageService service) {
         super(settings, controller, client, securityController,
-                RegistryIndexDao.INDEX, RegistryCommentDao.TYPE,
+                PageIndexDao.INDEX, PageCommentDao.TYPE,
                 (id, json) -> service.updateCommentFromJson(id, json));
     }
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryImageAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageImageAction.java
similarity index 64%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryImageAction.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageImageAction.java
index 426ef33455b50524cfec40df979ba4cbb7b02db0..73fcfa7f75e2248c8bccfb42e5951181625ddfab 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryImageAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageImageAction.java
@@ -22,20 +22,18 @@ package org.duniter.elasticsearch.user.rest.page;
  * #L%
  */
 
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.RecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
-import org.duniter.elasticsearch.user.model.page.RegistryRecord;
 import org.elasticsearch.common.inject.Inject;
 
-public class RestRegistryImageAction {
+public class RestPageImageAction {
 
     @Inject
-    public RestRegistryImageAction(RestSecurityController securityController) {
+    public RestPageImageAction(RestSecurityController securityController) {
 
-        // Allow to get thumbnail
-        securityController.allowImageAttachment(RegistryIndexDao.INDEX, RegistryRecordDao.TYPE, RegistryRecord.PROPERTY_THUMBNAIL);
-
-        // TODO : allow to get pictures
+        // Allow to get avatar
+        securityController.allowImageAttachment(PageIndexDao.INDEX, PageRecordDao.TYPE, RecordDao.PROPERTY_AVATAR);
     }
 }
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryRecordIndexAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageRecordIndexAction.java
similarity index 73%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryRecordIndexAction.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageRecordIndexAction.java
index 1d60e71baeb4a08fdfa785c0d6bb8d15dc20ca96..89c015bb6bfd0f5880464577a2cf844349569685 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryRecordIndexAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageRecordIndexAction.java
@@ -22,8 +22,8 @@ package org.duniter.elasticsearch.user.rest.page;
  * #L%
  */
 
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.duniter.elasticsearch.user.service.PageService;
 import org.duniter.elasticsearch.rest.AbstractRestPostIndexAction;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
@@ -32,14 +32,14 @@ import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.rest.RestController;
 
-public class RestRegistryRecordIndexAction extends AbstractRestPostIndexAction {
+public class RestPageRecordIndexAction extends AbstractRestPostIndexAction {
 
 
     @Inject
-    public RestRegistryRecordIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
-                                         PageService service) {
+    public RestPageRecordIndexAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                     PageService service) {
         super(settings, controller, client, securityController,
-                RegistryIndexDao.INDEX, RegistryRecordDao.TYPE,
+                PageIndexDao.INDEX, PageRecordDao.TYPE,
                 json -> service.indexRecordFromJson(json));
     }
 }
\ No newline at end of file
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryRecordUpdateAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageRecordUpdateAction.java
similarity index 73%
rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryRecordUpdateAction.java
rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageRecordUpdateAction.java
index 45f69c05486f64f32fcbad7a5dc3dbb24ab9e064..cbc02e493ec047369c62a450b8f6645c2a8caa23 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestRegistryRecordUpdateAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageRecordUpdateAction.java
@@ -24,21 +24,21 @@ package org.duniter.elasticsearch.user.rest.page;
 
 import org.duniter.elasticsearch.rest.AbstractRestPostUpdateAction;
 import org.duniter.elasticsearch.rest.security.RestSecurityController;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.duniter.elasticsearch.user.service.PageService;
 import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.rest.RestController;
 
-public class RestRegistryRecordUpdateAction extends AbstractRestPostUpdateAction {
+public class RestPageRecordUpdateAction extends AbstractRestPostUpdateAction {
 
     @Inject
-    public RestRegistryRecordUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
-                                          PageService service) {
+    public RestPageRecordUpdateAction(Settings settings, RestController controller, Client client, RestSecurityController securityController,
+                                      PageService service) {
         super(settings, controller, client, securityController,
-                RegistryIndexDao.INDEX, RegistryRecordDao.TYPE,
+                PageIndexDao.INDEX, PageRecordDao.TYPE,
                 (id, json) -> service.updateRecordFromJson(id, json));
     }
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/GroupService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/GroupService.java
index 2feed095309cf68d09b140306eebc4016b495546..e5a36f9909c5c143d020775624a45c97f2e78bda 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/GroupService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/GroupService.java
@@ -23,29 +23,22 @@ package org.duniter.elasticsearch.user.service;
  */
 
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import org.apache.commons.collections4.MapUtils;
+import org.duniter.core.client.model.elasticsearch.RecordComment;
 import org.duniter.core.client.model.elasticsearch.UserGroup;
-import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
-import org.duniter.elasticsearch.exception.AccessDeniedException;
-import org.duniter.elasticsearch.user.service.AbstractService;
+import org.duniter.elasticsearch.exception.NotFoundException;
+import org.duniter.elasticsearch.user.dao.group.GroupCommentDao;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.group.GroupRecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
 import org.duniter.elasticsearch.user.PluginSettings;
-import org.elasticsearch.action.ListenableActionFuture;
-import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
-import org.elasticsearch.action.index.IndexResponse;
-import org.elasticsearch.action.update.UpdateResponse;
-import org.elasticsearch.client.Client;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
 
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -53,69 +46,48 @@ import java.util.Set;
  */
 public class GroupService extends AbstractService {
 
-    public static final String INDEX = "group";
-    public static final String RECORD_TYPE = "record";
+    private GroupIndexDao indexDao;
+    private GroupCommentDao commentDao;
+    private GroupRecordDao recordDao;
+    private HistoryService historyService;
 
     @Inject
     public GroupService(Duniter4jClient client,
                         PluginSettings settings,
-                        CryptoService cryptoService) {
-        super("duniter." + INDEX, client, settings, cryptoService);
+                        CryptoService cryptoService,
+                        GroupIndexDao indexDao,
+                        GroupCommentDao commentDao,
+                        GroupRecordDao recordDao,
+                        HistoryService historyService) {
+        super("duniter.group", client, settings, cryptoService);
+        this.indexDao = indexDao;
+        this.commentDao = commentDao;
+        this.recordDao = recordDao;
+        this.historyService = historyService;
     }
 
     /**
-     * Create index need for blockchain mail, if need
+     * Create index need for blockchain registry, if need
      */
     public GroupService createIndexIfNotExists() {
-        try {
-            if (!client.existsIndex(INDEX)) {
-                createIndex();
-            }
-        }
-        catch(JsonProcessingException e) {
-            throw new TechnicalException(String.format("Error while creating index [%s]", INDEX));
-        }
-        return this;
-    }
-
-    /**
-     * Create index for mail
-     * @throws JsonProcessingException
-     */
-    public GroupService createIndex() throws JsonProcessingException {
-        logger.info(String.format("Creating index [%s]", INDEX));
-
-        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(INDEX);
-        org.elasticsearch.common.settings.Settings indexSettings = org.elasticsearch.common.settings.Settings.settingsBuilder()
-                .put("number_of_shards", 3)
-                .put("number_of_replicas", 1)
-                //.put("analyzer", createDefaultAnalyzer())
-                .build();
-        createIndexRequestBuilder.setSettings(indexSettings);
-        createIndexRequestBuilder.addMapping(RECORD_TYPE, createRecordType());
-        createIndexRequestBuilder.execute().actionGet();
-
+        indexDao.createIndexIfNotExists();
         return this;
     }
 
     public GroupService deleteIndex() {
-        client.deleteIndexIfExists(INDEX);
+        indexDao.deleteIndex();
         return this;
     }
 
-    public boolean existsIndex() {
-        return client.existsIndex(INDEX);
-    }
-
     /**
      *
      * Index an record
-     * @param profileJson
+     * @param json
      * @return the record id
      */
-    public String indexRecordProfileFromJson(String profileJson) {
+    public String indexRecordProfileFromJson(String json) {
 
-        JsonNode actualObj = readAndVerifyIssuerSignature(profileJson);
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
         String title = getTitle(actualObj);
         String id = computeIdFromTitle(title);
         String issuer = getIssuer(actualObj);
@@ -127,44 +99,76 @@ public class GroupService extends AbstractService {
             logger.debug(String.format("Indexing group [%s] from issuer [%s]", id, issuer.substring(0, 8)));
         }
 
-        IndexResponse response = client.prepareIndex(INDEX, RECORD_TYPE)
-                .setSource(profileJson)
-                .setId(id)
-                .setRefresh(false)
-                .execute().actionGet();
-        return response.getId();
+        return recordDao.create(id, json);
     }
 
     /**
      * Update a record
-     * @param recordJson
+     * @param json
      */
-    public ListenableActionFuture<UpdateResponse> updateRecordFromJson(String id, String recordJson) {
+    public void updateRecordFromJson(String id, String json) {
+
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
+        String issuer = getIssuer(actualObj);
+
+        // Check same document issuer
+        recordDao.checkSameDocumentIssuer(id, issuer);
+
+        // Check time is valid - fix #27
+        verifyTimeForUpdate(recordDao.getIndex(), recordDao.getType(), id, actualObj);
 
-        JsonNode actualObj = readAndVerifyIssuerSignature(recordJson);
+        if (logger.isDebugEnabled()) {
+            logger.debug(String.format("Updating %s [%s] from issuer [%s]", recordDao.getType(), id, issuer.substring(0, 8)));
+        }
+
+        recordDao.update(id, json);
+    }
+
+    public String indexCommentFromJson(String json) {
+        JsonNode commentObj = readAndVerifyIssuerSignature(json);
+        String issuer = getMandatoryField(commentObj, RecordComment.PROPERTY_ISSUER).asText();
+
+        // Check the record document exists
+        String recordId = getMandatoryField(commentObj, RecordComment.PROPERTY_RECORD).asText();
+        checkRecordExistsOrDeleted(recordId);
+
+        // Check time is valid - fix #27
+        verifyTimeForInsert(commentObj);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(String.format("[%s] Indexing new %s, issuer {%s}", PageIndexDao.INDEX, commentDao.getType(), issuer.substring(0, 8)));
+        }
+        return commentDao.create(json);
+    }
+
+    public void updateCommentFromJson(String id, String json) {
+        JsonNode commentObj = readAndVerifyIssuerSignature(json);
+
+        // Check the record document exists
+        String recordId = getMandatoryField(commentObj, RecordComment.PROPERTY_RECORD).asText();
+        checkRecordExistsOrDeleted(recordId);
 
         // Check time is valid - fix #27
-        verifyTimeForUpdate(INDEX, RECORD_TYPE, id, actualObj);
+        verifyTimeForUpdate(commentDao.getIndex(), commentDao.getType(), id, commentObj);
 
         if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Updating group [%s]", id));
+            String issuer = getMandatoryField(commentObj, RecordComment.PROPERTY_ISSUER).asText();
+            logger.debug(String.format("[%s] Updating existing %s {%s}, issuer {%s}", PageIndexDao.INDEX, commentDao.getType(), id, issuer.substring(0, 8)));
         }
 
-        return client.prepareUpdate(INDEX, RECORD_TYPE, id)
-                .setDoc(recordJson)
-                .execute();
+        commentDao.update(id, json);
     }
 
     public String getTitleById(String id) {
 
-        Object title = client.getFieldById(INDEX, RECORD_TYPE, id, UserGroup.PROPERTY_TITLE);
+        Object title = client.getFieldById(recordDao.getIndex(), recordDao.getType(), id, UserGroup.PROPERTY_TITLE);
         if (title == null) return null;
         return title.toString();
     }
 
     public Map<String, String> getTitlesByNames(Set<String> ids) {
 
-        Map<String, Object> titles = client.getFieldByIds(INDEX, RECORD_TYPE, ids, UserGroup.PROPERTY_TITLE);
+        Map<String, Object> titles = client.getFieldByIds(recordDao.getIndex(), recordDao.getType(), ids, UserGroup.PROPERTY_TITLE);
         if (MapUtils.isEmpty(titles)) return null;
         Map<String, String> result = new HashMap<>();
         titles.entrySet().forEach((entry) -> result.put(entry.getKey(), entry.getValue().toString()));
@@ -185,145 +189,29 @@ public class GroupService extends AbstractService {
     protected String computeIdFromTitle(String title, int counter) {
 
         String id = title.replaceAll("\\s+", "");
-        id  = id.replaceAll("[^a-zA−Z_-]+", "");
+        id  = id.replaceAll("[^a-zA−Z0-9_-]+", "");
         if (counter > 0) {
             id += "_" + counter;
         }
 
-        if (!client.isDocumentExists(INDEX, RECORD_TYPE, id)) {
+        if (!recordDao.isExists(id)) {
             return id;
         }
 
         return computeIdFromTitle(title, counter+1);
     }
 
-    public XContentBuilder createRecordType() {
-        String stringAnalyzer = pluginSettings.getDefaultStringAnalyzer();
-
+    // Check the record document exists (or has been deleted)
+    private void checkRecordExistsOrDeleted(String id) {
+        boolean recordExists;
         try {
-            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(RECORD_TYPE)
-                    .startObject("properties")
-
-                    // title
-                    .startObject("title")
-                    .field("type", "string")
-                    .field("analyzer", stringAnalyzer)
-                    .endObject()
-
-                    // description
-                    .startObject("description")
-                    .field("type", "string")
-                    .field("analyzer", stringAnalyzer)
-                    .endObject()
-
-                    // creationTime
-                    .startObject("creationTime")
-                    .field("type", "integer")
-                    .endObject()
-
-                    // time
-                    .startObject("time")
-                    .field("type", "integer")
-                    .endObject()
-
-                    // issuer
-                    .startObject("issuer")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    // hash
-                    .startObject("hash")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    // signature
-                    .startObject("signature")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    // thumbnail
-                    .startObject("thumbnail")
-                    .field("type", "attachment")
-                    .startObject("fields") // src
-                    .startObject("content") // title
-                    .field("index", "no")
-                    .endObject()
-                    .startObject("title") // title
-                    .field("type", "string")
-                    .field("store", "no")
-                    .endObject()
-                    .startObject("author") // title
-                    .field("store", "no")
-                    .endObject()
-                    .startObject("content_type") // title
-                    .field("store", "yes")
-                    .endObject()
-                    .endObject()
-                    .endObject()
-
-                    // pictures
-                    .startObject("pictures")
-                    .field("type", "nested")
-                    .field("dynamic", "false")
-                    .startObject("properties")
-                    .startObject("file") // file
-                    .field("type", "attachment")
-                    .startObject("fields")
-                    .startObject("content") // content
-                    .field("index", "no")
-                    .endObject()
-                    .startObject("title") // title
-                    .field("type", "string")
-                    .field("store", "yes")
-                    .field("analyzer", stringAnalyzer)
-                    .endObject()
-                    .startObject("author") // author
-                    .field("type", "string")
-                    .field("store", "no")
-                    .endObject()
-                    .startObject("content_type") // content_type
-                    .field("store", "yes")
-                    .endObject()
-                    .endObject()
-                    .endObject()
-                    .endObject()
-                    .endObject()
-
-                    // social networks
-                    .startObject("socials")
-                        .field("type", "nested")
-                        .field("dynamic", "false")
-                        .startObject("properties")
-                            .startObject("type") // type
-                                .field("type", "string")
-                                .field("index", "not_analyzed")
-                            .endObject()
-                            .startObject("url") // url
-                                .field("type", "string")
-                                .field("index", "not_analyzed")
-                            .endObject()
-                        .endObject()
-                    .endObject()
-
-                    // tags
-                    .startObject("tags")
-                        .field("type", "completion")
-                        .field("search_analyzer", "simple")
-                        .field("analyzer", "simple")
-                        .field("preserve_separators", "false")
-                    .endObject()
-
-                    .endObject()
-                    .endObject().endObject();
-
-            return mapping;
+            recordExists = recordDao.isExists(id);
+        } catch (NotFoundException e) {
+            // Check if exists in delete history
+            recordExists = historyService.existsInDeleteHistory(recordDao.getIndex(), recordDao.getType(), id);
         }
-        catch(IOException ioe) {
-            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", INDEX, RECORD_TYPE, ioe.getMessage()), ioe);
+        if (!recordExists) {
+            throw new NotFoundException(String.format("Comment refers a non-existent document [%s/%s/%s].", recordDao.getIndex(), recordDao.getType(), id));
         }
     }
-
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java
index 6e3e941f061d7e715950316ba04b8c67661babbe..fdb7b6172e48ddcf7060100b3c566697af0791c8 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java
@@ -29,9 +29,9 @@ import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
 import org.duniter.elasticsearch.exception.NotFoundException;
 import org.duniter.elasticsearch.user.PluginSettings;
-import org.duniter.elasticsearch.user.dao.page.RegistryCommentDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageCommentDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.elasticsearch.common.inject.Inject;
 
 /**
@@ -39,9 +39,9 @@ import org.elasticsearch.common.inject.Inject;
  */
 public class PageService extends AbstractService {
 
-    private RegistryIndexDao indexDao;
-    private RegistryRecordDao recordDao;
-    private RegistryCommentDao commentDao;
+    private PageIndexDao indexDao;
+    private PageRecordDao recordDao;
+    private PageCommentDao commentDao;
     private HistoryService historyService;
 
     @Inject
@@ -49,11 +49,11 @@ public class PageService extends AbstractService {
                        PluginSettings settings,
                        CryptoService cryptoService,
                        HistoryService historyService,
-                       RegistryIndexDao registryIndexDao,
-                       RegistryCommentDao commentDao,
-                       RegistryRecordDao recordDao) {
+                       PageIndexDao indexDao,
+                       PageCommentDao commentDao,
+                       PageRecordDao recordDao) {
         super("duniter.page", client, settings, cryptoService);
-        this.indexDao = registryIndexDao;
+        this.indexDao = indexDao;
         this.commentDao = commentDao;
         this.recordDao = recordDao;
         this.historyService = historyService;
@@ -115,7 +115,7 @@ public class PageService extends AbstractService {
         verifyTimeForInsert(commentObj);
 
         if (logger.isDebugEnabled()) {
-            logger.debug(String.format("[%s] Indexing new %s, issuer {%s}", RegistryIndexDao.INDEX, commentDao.getType(), issuer.substring(0, 8)));
+            logger.debug(String.format("[%s] Indexing new %s, issuer {%s}", PageIndexDao.INDEX, commentDao.getType(), issuer.substring(0, 8)));
         }
         return commentDao.create(json);
     }
@@ -132,7 +132,7 @@ public class PageService extends AbstractService {
 
         if (logger.isDebugEnabled()) {
             String issuer = getMandatoryField(commentObj, RecordComment.PROPERTY_ISSUER).asText();
-            logger.debug(String.format("[%s] Updating existing %s {%s}, issuer {%s}", RegistryIndexDao.INDEX, commentDao.getType(), id, issuer.substring(0, 8)));
+            logger.debug(String.format("[%s] Updating existing %s {%s}, issuer {%s}", PageIndexDao.INDEX, commentDao.getType(), id, issuer.substring(0, 8)));
         }
 
         commentDao.update(id, json);
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java
index b1b698a276cd23a4d0c9f36535d6f38f3130c42d..0df9f69d6329cce0bdc4ec950fe1159ad200c1a1 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java
@@ -23,31 +23,21 @@ package org.duniter.elasticsearch.user.service;
  */
 
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
-import org.duniter.core.client.model.elasticsearch.Record;
 import org.duniter.core.util.Preconditions;
 import org.apache.commons.collections4.MapUtils;
 import org.duniter.core.client.model.ModelUtils;
 import org.duniter.core.client.model.elasticsearch.UserProfile;
-import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
-import org.duniter.elasticsearch.exception.InvalidFormatException;
 import org.duniter.elasticsearch.user.PluginSettings;
 import org.duniter.elasticsearch.exception.AccessDeniedException;
 import org.duniter.elasticsearch.service.AbstractService;
-import org.elasticsearch.action.ActionWriteResponse;
-import org.elasticsearch.action.ListenableActionFuture;
-import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
-import org.elasticsearch.action.index.IndexResponse;
-import org.elasticsearch.action.update.UpdateResponse;
-import org.elasticsearch.client.Client;
+import org.duniter.elasticsearch.user.dao.profile.UserIndexDao;
+import org.duniter.elasticsearch.user.dao.profile.UserProfileDao;
+import org.duniter.elasticsearch.user.dao.profile.UserSettingsDao;
 import org.elasticsearch.common.inject.Inject;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
 
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -58,6 +48,11 @@ import java.util.Set;
  */
 public class UserService extends AbstractService {
 
+
+    private UserIndexDao indexDao;
+    private UserProfileDao profileDao;
+    private UserSettingsDao settingsDao;
+
     public static final String INDEX = "user";
     public static final String PROFILE_TYPE = "profile";
     public static final String SETTINGS_TYPE = "settings";
@@ -65,22 +60,21 @@ public class UserService extends AbstractService {
     @Inject
     public UserService(Duniter4jClient client,
                        PluginSettings settings,
-                       CryptoService cryptoService) {
+                       CryptoService cryptoService,
+                       UserIndexDao indexDao,
+                       UserProfileDao profileDao,
+                       UserSettingsDao settingsDao) {
         super("duniter." + INDEX, client, settings.getDelegate(), cryptoService);
+        this.indexDao = indexDao;
+        this.profileDao = profileDao;
+        this.settingsDao = settingsDao;
     }
 
     /**
      * Create index need for blockchain mail, if need
      */
     public UserService createIndexIfNotExists() {
-        try {
-            if (!client.existsIndex(INDEX)) {
-                createIndex();
-            }
-        }
-        catch(JsonProcessingException e) {
-            throw new TechnicalException(String.format("Error while creating index [%s]", INDEX));
-        }
+        indexDao.createIndexIfNotExists();
         return this;
     }
 
@@ -88,33 +82,11 @@ public class UserService extends AbstractService {
      * Create index need for blockchain mail, if need
      */
     public boolean isIndexExists() {
-        return client.existsIndex(INDEX);
-    }
-
-    /**
-     * Create index for mail
-     * @throws JsonProcessingException
-     */
-    public UserService createIndex() throws JsonProcessingException {
-        logger.info(String.format("Creating index [%s]", INDEX));
-
-        CreateIndexRequestBuilder createIndexRequestBuilder = client.admin().indices().prepareCreate(INDEX);
-        org.elasticsearch.common.settings.Settings indexSettings = org.elasticsearch.common.settings.Settings.settingsBuilder()
-                .put("number_of_shards", 3)
-                .put("number_of_replicas", 1)
-                //.put("analyzer", createDefaultAnalyzer())
-                .build();
-        createIndexRequestBuilder.setSettings(indexSettings);
-        createIndexRequestBuilder.addMapping(PROFILE_TYPE, createProfileType());
-        createIndexRequestBuilder.addMapping(SETTINGS_TYPE, createSettingsType());
-        createIndexRequestBuilder.addMapping(UserEventService.EVENT_TYPE, UserEventService.createEventType());
-        createIndexRequestBuilder.execute().actionGet();
-
-        return this;
+        return indexDao.existsIndex();
     }
 
     public UserService deleteIndex() {
-        client.deleteIndexIfExists(INDEX);
+        indexDao.deleteIndex();
         return this;
     }
 
@@ -124,65 +96,60 @@ public class UserService extends AbstractService {
      * @param profileJson
      * @return the profile id
      */
-    public String indexProfileFromJson(String profileJson) {
+    public String indexProfileFromJson(String json) {
+        Preconditions.checkNotNull(json);
 
-        JsonNode actualObj = readAndVerifyIssuerSignature(profileJson);
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
         String issuer = getIssuer(actualObj);
 
         // Check time is valid - fix #27
         verifyTimeForInsert(actualObj);
 
         if (logger.isDebugEnabled()) {
-            logger.debug(String.format("Indexing a user profile from issuer [%s]", issuer.substring(0, 8)));
+            logger.debug(String.format("Indexing a %s from issuer [%s]", profileDao.getType(), issuer.substring(0, 8)));
         }
 
-        IndexResponse response = client.prepareIndex(INDEX, PROFILE_TYPE)
-                .setSource(profileJson)
-                .setId(issuer) // always use the issuer pubkey as id
-                .setRefresh(false)
-                .execute().actionGet();
-        return response.getId();
+        return profileDao.create(issuer, json);
     }
 
     /**
      * Update an user profile
-     * @param profileJson
+     * @param id
+     * @param json
      */
-    public ListenableActionFuture<? extends ActionWriteResponse> updateProfileFromJson(String id, String profileJson) {
+    public void updateProfileFromJson(String id, String json) {
+        Preconditions.checkNotNull(id);
+        Preconditions.checkNotNull(json);
 
-        JsonNode actualObj = readAndVerifyIssuerSignature(profileJson);
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
         String issuer = getIssuer(actualObj);
 
         if (!Objects.equals(issuer, id)) {
             throw new AccessDeniedException(String.format("Could not update this document: only the issuer can update."));
         }
 
+        // Check same document issuer
+        profileDao.checkSameDocumentIssuer(id, issuer);
+
         // Check time is valid - fix #27
-        verifyTimeForUpdate(INDEX, PROFILE_TYPE, id, actualObj);
+        verifyTimeForUpdate(profileDao.getIndex(), profileDao.getType(), id, actualObj);
 
         if (logger.isDebugEnabled()) {
             logger.debug(String.format("Updating a user profile from issuer [%s]", issuer.substring(0, 8)));
         }
 
-        // First delete
-        client.prepareDelete(INDEX, PROFILE_TYPE, issuer)
-                .execute().actionGet();
-
-        // Then re-create
-        return client.prepareIndex(INDEX, PROFILE_TYPE, issuer)
-                .setSource(profileJson)
-                .execute();
+        profileDao.update(id, json);
     }
 
     /**
      *
      * Index an user settings
-     * @param settingsJson settings, as JSON string
+     * @param json settings, as JSON string
      * @return the settings id (=the issuer pubkey)
      */
-    public String indexSettingsFromJson(String settingsJson) {
+    public String indexSettingsFromJson(String json) {
 
-        JsonNode actualObj = readAndVerifyIssuerSignature(settingsJson);
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
         String issuer = getIssuer(actualObj);
 
         // Check time is valid - fix #27
@@ -192,21 +159,17 @@ public class UserService extends AbstractService {
             logger.debug(String.format("Indexing a user settings from issuer [%s]", issuer.substring(0, 8)));
         }
 
-        IndexResponse response = client.prepareIndex(INDEX, SETTINGS_TYPE)
-                .setSource(settingsJson)
-                .setId(issuer) // always use the issuer pubkey as id
-                .setRefresh(false)
-                .execute().actionGet();
-        return response.getId();
+        return settingsDao.create(issuer, json);
     }
 
     /**
      * Update user settings
-     * @param settingsJson settings, as JSON string
+     * @param id the doc id (should be =issuer)
+     * @param json settings, as JSON string
      */
-    public ListenableActionFuture<UpdateResponse> updateSettingsFromJson(String id, String settingsJson) {
+    public void updateSettingsFromJson(String id, String json) {
 
-        JsonNode actualObj = readAndVerifyIssuerSignature(settingsJson);
+        JsonNode actualObj = readAndVerifyIssuerSignature(json);
         String issuer = getIssuer(actualObj);
 
         if (!Objects.equals(issuer, id)) {
@@ -220,9 +183,7 @@ public class UserService extends AbstractService {
             logger.debug(String.format("Indexing a user settings from issuer [%s]", issuer.substring(0, 8)));
         }
 
-        return client.prepareUpdate(INDEX, SETTINGS_TYPE, issuer)
-                .setDoc(settingsJson)
-                .execute();
+        settingsDao.update(issuer, json);
     }
 
 
@@ -267,136 +228,4 @@ public class UserService extends AbstractService {
 
     /* -- Internal methods -- */
 
-    public XContentBuilder createProfileType() {
-        String stringAnalyzer = pluginSettings.getDefaultStringAnalyzer();
-
-        try {
-            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(PROFILE_TYPE)
-                    .startObject("properties")
-
-                    // title
-                    .startObject("title")
-                    .field("type", "string")
-                    .field("analyzer", stringAnalyzer)
-                    .endObject()
-
-                    // description
-                    .startObject("description")
-                    .field("type", "string")
-                    .field("analyzer", stringAnalyzer)
-                    .endObject()
-
-                    // time
-                    .startObject("time")
-                    .field("type", "integer")
-                    .endObject()
-
-                    // issuer
-                    .startObject("issuer")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    // location
-                    .startObject("location")
-                    .field("type", "string")
-                    .endObject()
-
-                    // geoPoint
-                    .startObject("geoPoint")
-                    .field("type", "geo_point")
-                    .endObject()
-
-                    // avatar
-                    .startObject("avatar")
-                        .field("type", "attachment")
-                        .startObject("fields") // fields
-                            .startObject("content") // content
-                                .field("index", "no")
-                            .endObject()
-                            .startObject("title") // title
-                                .field("type", "string")
-                                .field("store", "no")
-                            .endObject()
-                                .startObject("author") // author
-                                .field("store", "no")
-                            .endObject()
-                            .startObject("content_type") // content_type
-                                .field("store", "yes")
-                            .endObject()
-                        .endObject()
-                    .endObject()
-
-                    // social networks
-                    .startObject("socials")
-                        .field("type", "nested")
-                        .field("dynamic", "false")
-                        .startObject("properties")
-                            .startObject("type") // type
-                                .field("type", "string")
-                                .field("index", "not_analyzed")
-                            .endObject()
-                            .startObject("url") // url
-                                .field("type", "string")
-                                .field("index", "not_analyzed")
-                            .endObject()
-                        .endObject()
-                    .endObject()
-
-                    // tags
-                    .startObject("tags")
-                        .field("type", "completion")
-                        .field("search_analyzer", "simple")
-                        .field("analyzer", "simple")
-                        .field("preserve_separators", "false")
-                    .endObject()
-
-                    .endObject()
-                    .endObject().endObject();
-
-            return mapping;
-        }
-        catch(IOException ioe) {
-            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", INDEX, PROFILE_TYPE, ioe.getMessage()), ioe);
-        }
-    }
-
-    public XContentBuilder createSettingsType() {
-
-        try {
-            XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(SETTINGS_TYPE)
-                    .startObject("properties")
-
-                    // time
-                    .startObject("time")
-                    .field("type", "integer")
-                    .endObject()
-
-                    // issuer
-                    .startObject("issuer")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    // nonce
-                    .startObject("nonce")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    // content
-                    .startObject("content")
-                    .field("type", "string")
-                    .field("index", "not_analyzed")
-                    .endObject()
-
-                    .endObject()
-                    .endObject().endObject();
-
-            return mapping;
-        }
-        catch(IOException ioe) {
-            throw new TechnicalException(String.format("Error while getting mapping for index [%s/%s]: %s", INDEX, SETTINGS_TYPE, ioe.getMessage()), ioe);
-        }
-    }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/SynchroModule.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/SynchroModule.java
index 63e7419283072a49d74451288847685b77f5af70..981f1fd835b0d388636de55954fcde19b80b9a30 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/SynchroModule.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/SynchroModule.java
@@ -25,6 +25,7 @@ package org.duniter.elasticsearch.user.synchro;
 import org.duniter.core.client.model.bma.EndpointApi;
 import org.duniter.elasticsearch.service.PeerService;
 import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.synchro.group.SynchroGroupCommentAction;
 import org.duniter.elasticsearch.user.synchro.group.SynchroGroupRecordAction;
 import org.duniter.elasticsearch.user.synchro.history.SynchroHistoryIndexAction;
 import org.duniter.elasticsearch.user.synchro.invitation.SynchroInvitationCertificationIndexAction;
@@ -67,11 +68,14 @@ public class SynchroModule extends AbstractModule implements Module {
         bind(SynchroMessageInboxIndexAction.class).asEagerSingleton();
         bind(SynchroMessageOutboxIndexAction.class).asEagerSingleton();
 
-        // Page and Group
-        bind(SynchroGroupRecordAction.class).asEagerSingleton();
+        // Page
         bind(SynchroPageRecordAction.class).asEagerSingleton();
         bind(SynchroPageCommentAction.class).asEagerSingleton();
 
+        // Group
+        bind(SynchroGroupRecordAction.class).asEagerSingleton();
+        bind(SynchroGroupCommentAction.class).asEagerSingleton();
+
         // Invitation
         bind(SynchroInvitationCertificationIndexAction.class).asEagerSingleton();
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupCommentAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupCommentAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f6bb899319a7479ad90b4c9833cedb5c3fc7398
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupCommentAction.java
@@ -0,0 +1,28 @@
+package org.duniter.elasticsearch.user.synchro.group;
+
+import org.duniter.core.service.CryptoService;
+import org.duniter.elasticsearch.client.Duniter4jClient;
+import org.duniter.elasticsearch.synchro.AbstractSynchroAction;
+import org.duniter.elasticsearch.synchro.SynchroService;
+import org.duniter.elasticsearch.threadpool.ThreadPool;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.group.GroupCommentDao;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.elasticsearch.common.inject.Inject;
+
+public class SynchroGroupCommentAction extends AbstractSynchroAction {
+
+    @Inject
+    public SynchroGroupCommentAction(Duniter4jClient client,
+                                     PluginSettings pluginSettings,
+                                     CryptoService cryptoService,
+                                     ThreadPool threadPool,
+                                     SynchroService synchroService) {
+        super(GroupIndexDao.INDEX, GroupCommentDao.TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
+
+        setEnableUpdate(true); // with update
+
+        synchroService.register(this);
+    }
+
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupRecordAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupRecordAction.java
index d870b6b9774dcfdcb312296a33c725149b8b7ed4..8a787bdada00f327e42dea2b049d9878a6f870e1 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupRecordAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/group/SynchroGroupRecordAction.java
@@ -5,6 +5,8 @@ import org.duniter.elasticsearch.client.Duniter4jClient;
 import org.duniter.elasticsearch.synchro.SynchroService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
 import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.group.GroupIndexDao;
+import org.duniter.elasticsearch.user.dao.group.GroupRecordDao;
 import org.duniter.elasticsearch.user.service.GroupService;
 import org.duniter.elasticsearch.synchro.AbstractSynchroAction;
 import org.elasticsearch.common.inject.Inject;
@@ -17,7 +19,7 @@ public class SynchroGroupRecordAction extends AbstractSynchroAction {
                                     CryptoService cryptoService,
                                     ThreadPool threadPool,
                                     SynchroService synchroService) {
-        super(GroupService.INDEX, GroupService.RECORD_TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
+        super(GroupIndexDao.INDEX, GroupRecordDao.TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
 
         setEnableUpdate(true); // with update
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageCommentAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageCommentAction.java
index b774cb35b4e0c21ed7e644c3dbe675601ec624ae..b7c9818d586c751e410b5c13183d4bf2a7ca7c11 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageCommentAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageCommentAction.java
@@ -5,8 +5,8 @@ import org.duniter.elasticsearch.client.Duniter4jClient;
 import org.duniter.elasticsearch.synchro.SynchroService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
 import org.duniter.elasticsearch.user.PluginSettings;
-import org.duniter.elasticsearch.user.dao.page.RegistryCommentDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageCommentDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
 import org.duniter.elasticsearch.synchro.AbstractSynchroAction;
 import org.elasticsearch.common.inject.Inject;
 
@@ -18,7 +18,7 @@ public class SynchroPageCommentAction extends AbstractSynchroAction {
                                     CryptoService cryptoService,
                                     ThreadPool threadPool,
                                     SynchroService synchroService) {
-        super(RegistryIndexDao.INDEX, RegistryCommentDao.TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
+        super(PageIndexDao.INDEX, PageCommentDao.TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
 
         setEnableUpdate(true); // with update
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageRecordAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageRecordAction.java
index de3982fcf7f6225ac7ea868fcb925dd28ceb1a0e..b8a283dffc9af865cc2520da62a6fa846fa2260b 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageRecordAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/page/SynchroPageRecordAction.java
@@ -5,8 +5,8 @@ import org.duniter.elasticsearch.client.Duniter4jClient;
 import org.duniter.elasticsearch.synchro.SynchroService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
 import org.duniter.elasticsearch.user.PluginSettings;
-import org.duniter.elasticsearch.user.dao.page.RegistryIndexDao;
-import org.duniter.elasticsearch.user.dao.page.RegistryRecordDao;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
 import org.duniter.elasticsearch.synchro.AbstractSynchroAction;
 import org.elasticsearch.common.inject.Inject;
 
@@ -18,7 +18,7 @@ public class SynchroPageRecordAction extends AbstractSynchroAction {
                                    CryptoService cryptoService,
                                    ThreadPool threadPool,
                                    SynchroService synchroService) {
-        super(RegistryIndexDao.INDEX, RegistryRecordDao.TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
+        super(PageIndexDao.INDEX, PageRecordDao.TYPE, client, pluginSettings.getDelegate(), cryptoService, threadPool);
 
         setEnableUpdate(true); // with update
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserProfileAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserProfileAction.java
index e3c0b90240c18c5547a344b672592c43c584f307..9f5dedf8bf59c14a6f5ac3060a6ef948b439fd79 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserProfileAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserProfileAction.java
@@ -1,7 +1,10 @@
 package org.duniter.elasticsearch.user.synchro.user;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
+import org.duniter.elasticsearch.exception.AccessDeniedException;
+import org.duniter.elasticsearch.synchro.SynchroActionResult;
 import org.duniter.elasticsearch.synchro.SynchroService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
 import org.duniter.elasticsearch.user.PluginSettings;
@@ -9,6 +12,8 @@ import org.duniter.elasticsearch.user.service.UserService;
 import org.duniter.elasticsearch.synchro.AbstractSynchroAction;
 import org.elasticsearch.common.inject.Inject;
 
+import java.util.Objects;
+
 public class SynchroUserProfileAction extends AbstractSynchroAction {
 
     @Inject
@@ -21,7 +26,17 @@ public class SynchroUserProfileAction extends AbstractSynchroAction {
 
         setEnableUpdate(true); // with update
 
+        addValidationListener(this::onValidate);
+
         synchroService.register(this);
     }
 
+
+    protected void onValidate(String id, JsonNode source, SynchroActionResult result) {
+
+        String issuer = getIssuer(source);
+        if (!Objects.equals(issuer, id)) {
+            throw new AccessDeniedException(String.format("Could not save this document: id must be equals to issuer."));
+        }
+    }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserSettingsAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserSettingsAction.java
index a1b7baa32c22a6d175407b6f717508971f92827d..180b1bc7793f9e5022100f3ac01a616694d7aba5 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserSettingsAction.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/synchro/user/SynchroUserSettingsAction.java
@@ -1,14 +1,21 @@
 package org.duniter.elasticsearch.user.synchro.user;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
+import org.duniter.elasticsearch.exception.AccessDeniedException;
+import org.duniter.elasticsearch.exception.NotFoundException;
+import org.duniter.elasticsearch.synchro.SynchroActionResult;
 import org.duniter.elasticsearch.synchro.SynchroService;
 import org.duniter.elasticsearch.threadpool.ThreadPool;
 import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.profile.UserSettingsDao;
 import org.duniter.elasticsearch.user.service.UserService;
 import org.duniter.elasticsearch.synchro.AbstractSynchroAction;
 import org.elasticsearch.common.inject.Inject;
 
+import java.util.Objects;
+
 public class SynchroUserSettingsAction extends AbstractSynchroAction {
 
     @Inject
@@ -21,7 +28,16 @@ public class SynchroUserSettingsAction extends AbstractSynchroAction {
 
         setEnableUpdate(true); // with update
 
+        addValidationListener(this::onValidate);
+
         synchroService.register(this);
     }
 
+    protected void onValidate(String id, JsonNode source, SynchroActionResult result) {
+
+        String issuer = getIssuer(source);
+        if (!Objects.equals(issuer, id)) {
+            throw new AccessDeniedException(String.format("Could not save this document: id must be equals to issuer."));
+        }
+    }
 }