Skip to content
Snippets Groups Projects
Commit df18627d authored by Benoit Lavenier's avatar Benoit Lavenier
Browse files

- Upgrade message index, to store recipient

 - Clean code to avoid duplication, in REST action
 - Settings: Add keyring properties
 - Allow message deletion by recipient
parent d8d22dd0
No related branches found
No related tags found
No related merge requests found
Showing
with 197 additions and 65 deletions
......@@ -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;
}
}
......@@ -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 {
......
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
......@@ -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();
......
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
......@@ -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();
}
......
......@@ -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));
}
// 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)));
......
......@@ -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")
......
......@@ -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()
......
......@@ -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")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment