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; ...@@ -28,10 +28,12 @@ package org.duniter.core.client.model.elasticsearch;
public class MessageRecord extends Record { public class MessageRecord extends Record {
public static final String PROPERTY_TIME="time"; 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 Integer time;
private String message; private String content;
private String recipient;
public Integer getTime() { public Integer getTime() {
return time; return time;
...@@ -41,11 +43,19 @@ public class MessageRecord extends Record { ...@@ -41,11 +43,19 @@ public class MessageRecord extends Record {
this.time = time; this.time = time;
} }
public String getMessage() { public String getContent() {
return message; return content;
} }
public void setMessage(String message) { public void setContent(String content) {
this.message = message; 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> { ...@@ -209,6 +209,22 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> {
return peer; 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 methods */
protected void initI18n() throws IOException { 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; ...@@ -28,6 +28,7 @@ import org.duniter.elasticsearch.action.market.RestMarketCommentIndexAction;
import org.duniter.elasticsearch.action.market.RestMarketCommentUpdateAction; import org.duniter.elasticsearch.action.market.RestMarketCommentUpdateAction;
import org.duniter.elasticsearch.action.market.RestMarketRecordIndexAction; import org.duniter.elasticsearch.action.market.RestMarketRecordIndexAction;
import org.duniter.elasticsearch.action.market.RestMarketRecordUpdateAction; 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.RestRegistryRecordIndexAction;
import org.duniter.elasticsearch.action.registry.RestRegistryRecordUpdateAction; import org.duniter.elasticsearch.action.registry.RestRegistryRecordUpdateAction;
import org.duniter.elasticsearch.action.security.RestSecurityAuthAction; import org.duniter.elasticsearch.action.security.RestSecurityAuthAction;
...@@ -66,6 +67,9 @@ public class RestModule extends AbstractModule implements Module { ...@@ -66,6 +67,9 @@ public class RestModule extends AbstractModule implements Module {
// History // History
bind(RestHistoryDeleteIndexAction.class).asEagerSingleton(); bind(RestHistoryDeleteIndexAction.class).asEagerSingleton();
// Message
bind(RestMessageIndexAction.class).asEagerSingleton();
// Cesium // Cesium
bind(RestCesiumConfigAction.class).asEagerSingleton(); 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 { ...@@ -175,23 +175,26 @@ public abstract class AbstractService implements Bean {
} }
protected void checkSameDocumentIssuer(String index, String type, String id, String expectedIssuer) throws ElasticsearchException { 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) GetResponse response = client.prepareGet(index, type, id)
.setFields(Record.PROPERTY_ISSUER) .setFields(fieldName)
.execute().actionGet(); .execute().actionGet();
boolean failed = !response.isExists(); boolean failed = !response.isExists();
if (failed) { if (failed) {
throw new NotFoundException(String.format("Document [%s/%s/%s] not exists.", index, type, id)); throw new NotFoundException(String.format("Document [%s/%s/%s] not exists.", index, type, id));
} else { } else {
String docIssuer = (String)response.getFields().get(Record.PROPERTY_ISSUER).getValue(); String docValue = (String)response.getFields().get(fieldName).getValue();
if (!Objects.equals(expectedIssuer, docIssuer)) { if (!Objects.equals(expectedvalue, docValue)) {
throw new AccessDeniedException(String.format("Could not delete this document: not issuer.")); throw new AccessDeniedException(String.format("Could not delete this document: not same [%s].", fieldName));
} }
} }
} }
protected String getIssuer(JsonNode actualObj) { protected String getIssuer(JsonNode actualObj) {
return actualObj.get(Record.PROPERTY_ISSUER).asText(); return actualObj.get(Record.PROPERTY_ISSUER).asText();
} }
......
...@@ -26,6 +26,7 @@ package org.duniter.elasticsearch.service; ...@@ -26,6 +26,7 @@ package org.duniter.elasticsearch.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import org.duniter.core.client.model.elasticsearch.DeleteRecord; 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.exception.TechnicalException;
import org.duniter.core.service.CryptoService; import org.duniter.core.service.CryptoService;
import org.duniter.elasticsearch.PluginSettings; import org.duniter.elasticsearch.PluginSettings;
...@@ -116,8 +117,14 @@ public class HistoryService extends AbstractService { ...@@ -116,8 +117,14 @@ public class HistoryService extends AbstractService {
throw new NotFoundException(String.format("Index [%s] not exists.", index)); 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 // Check document issuer
checkSameDocumentIssuer(index, type, id, issuer); checkSameDocumentIssuer(index, type, id, issuer);
}
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("Deleting document [%s/%s/%s] - issuer [%s]", index, type, id, issuer.substring(0, 8))); 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 { ...@@ -282,6 +282,11 @@ public class MarketService extends AbstractService {
.field("analyzer", stringAnalyzer) .field("analyzer", stringAnalyzer)
.endObject() .endObject()
// creationTime
.startObject("creationTime")
.field("type", "integer")
.endObject()
// time // time
.startObject("time") .startObject("time")
.field("type", "integer") .field("type", "integer")
......
...@@ -25,17 +25,10 @@ package org.duniter.elasticsearch.service; ...@@ -25,17 +25,10 @@ package org.duniter.elasticsearch.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; 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.exception.TechnicalException;
import org.duniter.core.service.CryptoService; import org.duniter.core.service.CryptoService;
import org.duniter.elasticsearch.PluginSettings; 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.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
...@@ -44,7 +37,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder; ...@@ -44,7 +37,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import java.io.IOException; import java.io.IOException;
import java.util.Set;
/** /**
* Created by Benoit on 30/03/2015. * Created by Benoit on 30/03/2015.
...@@ -54,8 +46,6 @@ public class MessageService extends AbstractService { ...@@ -54,8 +46,6 @@ public class MessageService extends AbstractService {
public static final String INDEX = "message"; public static final String INDEX = "message";
public static final String RECORD_TYPE = "record"; 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 @Inject
public MessageService(Client client, PluginSettings settings, CryptoService cryptoService) { public MessageService(Client client, PluginSettings settings, CryptoService cryptoService) {
...@@ -118,7 +108,7 @@ public class MessageService extends AbstractService { ...@@ -118,7 +108,7 @@ public class MessageService extends AbstractService {
String issuer = getIssuer(actualObj); String issuer = getIssuer(actualObj);
if (logger.isDebugEnabled()) { 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) IndexResponse response = client.prepareIndex(INDEX, RECORD_TYPE)
...@@ -144,56 +134,27 @@ public class MessageService extends AbstractService { ...@@ -144,56 +134,27 @@ public class MessageService extends AbstractService {
.field("index", "not_analyzed") .field("index", "not_analyzed")
.endObject() .endObject()
// recipient
.startObject("recipient")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
// time // time
.startObject("time") .startObject("time")
.field("type", "integer") .field("type", "integer")
.endObject() .endObject()
// message // nonce
.startObject("message") .startObject("nonce")
.field("type", "string") .field("type", "string")
.field("analyzer", stringAnalyzer) .field("index", "not_analyzed")
.endObject() .endObject()
// pictures // content
.startObject("pictures") .startObject("content")
.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("type", "string")
.field("store", "yes") .field("index", "not_analyzed")
.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")
.endObject() .endObject()
.endObject() .endObject()
......
...@@ -385,6 +385,11 @@ public class RegistryService extends AbstractService { ...@@ -385,6 +385,11 @@ public class RegistryService extends AbstractService {
.field("analyzer", stringAnalyzer) .field("analyzer", stringAnalyzer)
.endObject() .endObject()
// creationTime
.startObject("creationTime")
.field("type", "integer")
.endObject()
// time // time
.startObject("time") .startObject("time")
.field("type", "integer") .field("type", "integer")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment