diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java index 660ea84985b7be84c54bcd04315a4b39a2f688cf..b58b05ad9e8943104d416b4b846ba410f6185cfa 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/MessageRecord.java @@ -28,10 +28,12 @@ package org.duniter.core.client.model.elasticsearch; public class MessageRecord extends Record { public static final String PROPERTY_TIME="time"; - public static final String PROPERTY_MESSAGE="message"; + public static final String PROPERTY_CONTENT="content"; + public static final String PROPERTY_RECIPIENT="recipient"; private Integer time; - private String message; + private String content; + private String recipient; public Integer getTime() { return time; @@ -41,11 +43,19 @@ public class MessageRecord extends Record { this.time = time; } - public String getMessage() { - return message; + public String getContent() { + return content; } - public void setMessage(String message) { - this.message = message; + public void setContent(String content) { + this.content = content; + } + + public String getRecipient() { + return recipient; + } + + public void setRecipient(String recipient) { + this.recipient = recipient; } } diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java index 9590391789b7eeadd6c7c4b44b293802a72ba436..904c834a02c07352811e61d0dc3d94420adf80cb 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/PluginSettings.java @@ -209,6 +209,22 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> { return peer; } + public String getKeyringSalt() { + return settings.get("duniter.keyring.salt"); + } + + public String getKeyringPassword() { + return settings.get("duniter.keyring.password"); + } + + public String getKeyringPublicKey() { + return settings.get("duniter.keyring.pub"); + } + + public String getKeyringSecretKey() { + return settings.get("duniter.keyring.sec"); + } + /* protected methods */ protected void initI18n() throws IOException { diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostAction.java new file mode 100644 index 0000000000000000000000000000000000000000..00cd50e9a3f8a8752a2addae977acdc930ff3fdb --- /dev/null +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/AbstractRestPostAction.java @@ -0,0 +1,80 @@ +package org.duniter.elasticsearch.action; + +/* + * #%L + * duniter4j-elasticsearch-plugin + * %% + * Copyright (C) 2014 - 2016 EIS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.duniter.core.exception.BusinessException; +import org.duniter.elasticsearch.exception.DuniterElasticsearchException; +import org.duniter.elasticsearch.rest.XContentThrowableRestResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.ESLoggerFactory; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.rest.*; + +import static org.elasticsearch.rest.RestRequest.Method.POST; +import static org.elasticsearch.rest.RestStatus.OK; + +public abstract class AbstractRestPostAction extends BaseRestHandler { + + private static ESLogger log = null; + + private final JsonIndexer indexer; + + + public AbstractRestPostAction(Settings settings, RestController controller, Client client, + String indexName, + String typeName, + JsonIndexer indexer) { + super(settings, controller, client); + controller.registerHandler(POST, + String.format("/%s/%s", indexName, typeName), + this); + log = ESLoggerFactory.getLogger(String.format("[%s]", indexName)); + this.indexer = indexer; + } + + @Override + protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception { + + try { + String recordId = indexer.handleJson(request.content().toUtf8()); + + restChannel.sendResponse(new BytesRestResponse(OK, recordId)); + } + catch(DuniterElasticsearchException | BusinessException e) { + log.error(e.getMessage(), e); + restChannel.sendResponse(new XContentThrowableRestResponse(request, e)); + } + catch(Exception e) { + log.error(e.getMessage(), e); + } + } + + + public interface JsonIndexer { + String handleJson(String json) throws DuniterElasticsearchException, BusinessException; + } + + + +} \ No newline at end of file diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java index 3c674400803e00f930f18153f4492996d80291c4..c9b3bca0fc7c45ff05a9268f1e4a7edee815ff57 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/RestModule.java @@ -28,6 +28,7 @@ import org.duniter.elasticsearch.action.market.RestMarketCommentIndexAction; import org.duniter.elasticsearch.action.market.RestMarketCommentUpdateAction; import org.duniter.elasticsearch.action.market.RestMarketRecordIndexAction; import org.duniter.elasticsearch.action.market.RestMarketRecordUpdateAction; +import org.duniter.elasticsearch.action.message.RestMessageIndexAction; import org.duniter.elasticsearch.action.registry.RestRegistryRecordIndexAction; import org.duniter.elasticsearch.action.registry.RestRegistryRecordUpdateAction; import org.duniter.elasticsearch.action.security.RestSecurityAuthAction; @@ -66,6 +67,9 @@ public class RestModule extends AbstractModule implements Module { // History bind(RestHistoryDeleteIndexAction.class).asEagerSingleton(); + // Message + bind(RestMessageIndexAction.class).asEagerSingleton(); + // Cesium bind(RestCesiumConfigAction.class).asEagerSingleton(); diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java new file mode 100644 index 0000000000000000000000000000000000000000..045bf1a285d2ab796f0a8859f743da8afd69b720 --- /dev/null +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/action/message/RestMessageIndexAction.java @@ -0,0 +1,41 @@ +package org.duniter.elasticsearch.action.message; + +/* + * #%L + * duniter4j-elasticsearch-plugin + * %% + * Copyright (C) 2014 - 2016 EIS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import org.duniter.elasticsearch.action.AbstractRestPostAction; +import org.duniter.elasticsearch.service.MessageService; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.rest.RestController; + +public class RestMessageIndexAction extends AbstractRestPostAction { + + @Inject + public RestMessageIndexAction(Settings settings, RestController controller, Client client, final MessageService service) { + super(settings, controller, client, + MessageService.INDEX, + MessageService.RECORD_TYPE, + json -> service.indexRecordFromJson(json)); + } +} \ No newline at end of file diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java index ab820f0760d1c97daaa325f75e622332d1eaa7f9..75ae513c1a84b8d4fbee60068b8a9a267724b2f9 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/AbstractService.java @@ -175,23 +175,26 @@ public abstract class AbstractService implements Bean { } protected void checkSameDocumentIssuer(String index, String type, String id, String expectedIssuer) throws ElasticsearchException { + checkSameDocumentField(index, type, id, Record.PROPERTY_ISSUER, expectedIssuer); + } + + protected void checkSameDocumentField(String index, String type, String id, String fieldName, String expectedvalue) throws ElasticsearchException { GetResponse response = client.prepareGet(index, type, id) - .setFields(Record.PROPERTY_ISSUER) + .setFields(fieldName) .execute().actionGet(); boolean failed = !response.isExists(); if (failed) { throw new NotFoundException(String.format("Document [%s/%s/%s] not exists.", index, type, id)); } else { - String docIssuer = (String)response.getFields().get(Record.PROPERTY_ISSUER).getValue(); - if (!Objects.equals(expectedIssuer, docIssuer)) { - throw new AccessDeniedException(String.format("Could not delete this document: not issuer.")); + String docValue = (String)response.getFields().get(fieldName).getValue(); + if (!Objects.equals(expectedvalue, docValue)) { + throw new AccessDeniedException(String.format("Could not delete this document: not same [%s].", fieldName)); } } } - protected String getIssuer(JsonNode actualObj) { return actualObj.get(Record.PROPERTY_ISSUER).asText(); } diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/HistoryService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/HistoryService.java index 06e9b37ac67eaed43b1d3e67d416bad5fbb3fe5e..fc3f0e4368b1c4c9bfd757e71a9711f01f2caedf 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/HistoryService.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/HistoryService.java @@ -26,6 +26,7 @@ package org.duniter.elasticsearch.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import org.duniter.core.client.model.elasticsearch.DeleteRecord; +import org.duniter.core.client.model.elasticsearch.MessageRecord; import org.duniter.core.exception.TechnicalException; import org.duniter.core.service.CryptoService; import org.duniter.elasticsearch.PluginSettings; @@ -116,8 +117,14 @@ public class HistoryService extends AbstractService { throw new NotFoundException(String.format("Index [%s] not exists.", index)); } - // Check document issuer - checkSameDocumentIssuer(index, type, id, issuer); + // Special case for message: check if issuer is recipient + if (MessageService.INDEX.equals(index)) { + checkSameDocumentField(index, type, id, MessageRecord.PROPERTY_RECIPIENT, issuer); + } + else { + // Check document issuer + checkSameDocumentIssuer(index, type, id, issuer); + } if (logger.isDebugEnabled()) { logger.debug(String.format("Deleting document [%s/%s/%s] - issuer [%s]", index, type, id, issuer.substring(0, 8))); diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java index 08a8e0ac569e7b14f2d974d466ffd3a1c48e4e27..5aa804185f4fc89a0b3ff7153e0b1afe02c1924f 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MarketService.java @@ -282,6 +282,11 @@ public class MarketService extends AbstractService { .field("analyzer", stringAnalyzer) .endObject() + // creationTime + .startObject("creationTime") + .field("type", "integer") + .endObject() + // time .startObject("time") .field("type", "integer") diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MessageService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MessageService.java index 632702c8a65ece046693d472979cac25d369b308..3dd902f50ab960bfad652d015a4fb6acf950ab70 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MessageService.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/MessageService.java @@ -25,17 +25,10 @@ package org.duniter.elasticsearch.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.Sets; -import com.google.gson.JsonSyntaxException; -import org.duniter.core.client.model.elasticsearch.MessageRecord; -import org.duniter.core.client.service.bma.WotRemoteService; import org.duniter.core.exception.TechnicalException; import org.duniter.core.service.CryptoService; import org.duniter.elasticsearch.PluginSettings; -import org.duniter.elasticsearch.exception.InvalidFormatException; -import org.duniter.elasticsearch.exception.InvalidSignatureException; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; -import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; @@ -44,7 +37,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import java.io.IOException; -import java.util.Set; /** * Created by Benoit on 30/03/2015. @@ -54,8 +46,6 @@ public class MessageService extends AbstractService { public static final String INDEX = "message"; public static final String RECORD_TYPE = "record"; - private static final String JSON_STRING_PROPERTY_REGEX = "[,]?[\"\\s\\n\\r]*%s[\"]?[\\s\\n\\r]*:[\\s\\n\\r]*\"[^\"]+\""; - @Inject public MessageService(Client client, PluginSettings settings, CryptoService cryptoService) { @@ -118,7 +108,7 @@ public class MessageService extends AbstractService { String issuer = getIssuer(actualObj); if (logger.isDebugEnabled()) { - logger.debug(String.format("Indexing a record from issuer [%s]", issuer.substring(0, 8))); + logger.debug(String.format("Indexing a message from issuer [%s]", issuer.substring(0, 8))); } IndexResponse response = client.prepareIndex(INDEX, RECORD_TYPE) @@ -144,56 +134,27 @@ public class MessageService extends AbstractService { .field("index", "not_analyzed") .endObject() + // recipient + .startObject("recipient") + .field("type", "string") + .field("index", "not_analyzed") + .endObject() + // time .startObject("time") .field("type", "integer") .endObject() - // message - .startObject("message") + // nonce + .startObject("nonce") .field("type", "string") - .field("analyzer", stringAnalyzer) + .field("index", "not_analyzed") .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 + // content + .startObject("content") .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() - - // picturesCount - .startObject("picturesCount") - .field("type", "integer") - .endObject() - - // tags - .startObject("tags") - .field("type", "completion") - .field("search_analyzer", "simple") - .field("analyzer", "simple") - .field("preserve_separators", "false") + .field("index", "not_analyzed") .endObject() .endObject() diff --git a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java index 826c7efe2e39f95c84e7b8b5714cf02bb646a50d..90cab8e2360b41e0d8adb6a7aaf8caa904aeb91b 100644 --- a/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java +++ b/duniter4j-elasticsearch/src/main/java/org/duniter/elasticsearch/service/RegistryService.java @@ -385,6 +385,11 @@ public class RegistryService extends AbstractService { .field("analyzer", stringAnalyzer) .endObject() + // creationTime + .startObject("creationTime") + .field("type", "integer") + .endObject() + // time .startObject("time") .field("type", "integer")