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.")); + } + } }