From 6e4a6a88144179665a9cc257d8d3cda9171568dd Mon Sep 17 00:00:00 2001 From: blavenie <benoit.lavenier@e-is.pro> Date: Wed, 7 Dec 2016 08:47:42 +0100 Subject: [PATCH] - ES: Move some POJO to es-user - ES: simplify UserEvent management --- .../client/model/elasticsearch/Event.java | 78 ------- .../client/model/elasticsearch/Record.java | 10 + .../model/elasticsearch/UserProfile.java | 38 +++ .../core/client/service/HttpServiceImpl.java | 3 - .../rest/security/RestSecurityAuthAction.java | 5 +- .../service/AbstractService.java | 63 ++++- .../elasticsearch/threadpool/ThreadPool.java | 10 + .../elasticsearch/gchange/PluginInit.java | 4 - .../gchange/service/MarketService.java | 21 +- .../gchange/service/RegistryService.java | 11 +- .../elasticsearch/user/PluginInit.java | 8 +- .../elasticsearch/user/model/UserEvent.java | 217 ++++++++++++++++++ .../event => model}/UserEventCodes.java | 2 +- .../event => model}/UserEventLink.java | 33 ++- .../elasticsearch/user/model/UserProfile.java | 74 ++++++ .../user/service/ServiceModule.java | 1 - .../service/{event => }/UserEventService.java | 146 +++++++----- .../user/service/UserService.java | 1 - .../user/service/event/UserEvent.java | 96 -------- .../user/service/event/UserEventListener.java | 7 - .../user/service/event/UserEventUtils.java | 84 ------- .../websocket/WebsocketUserEventEndPoint.java | 10 +- 22 files changed, 538 insertions(+), 384 deletions(-) delete mode 100644 duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Event.java create mode 100644 duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEvent.java rename duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/{service/event => model}/UserEventCodes.java (94%) rename duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/{service/event => model}/UserEventLink.java (65%) create mode 100644 duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java rename duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/{event => }/UserEventService.java (68%) delete mode 100644 duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEvent.java delete mode 100644 duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventListener.java delete mode 100644 duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventUtils.java diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Event.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Event.java deleted file mode 100644 index ffb926ef..00000000 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Event.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.duniter.core.client.model.elasticsearch; - -/* - * #%L - * Duniter4j :: Core Client API - * %% - * 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.nuiton.i18n.I18n; - -import java.util.Locale; - -/** - * Created by blavenie on 29/11/16. - */ -public class Event extends Record { - - public static final String PROPERTY_TYPE="type"; - public static final String PROPERTY_CODE="code"; - public static final String PROPERTY_MESSAGE="message"; - public static final String PROPERTY_PARAMS="params"; - - private String type; - - private String code; - - private String message; - - private String[] params; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getCode() { - return code; - } - - public void setCode(String code) { - this.code = code; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public String[] getParams() { - return params; - } - - public void setParams(String[] params) { - this.params = params; - } -} diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Record.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Record.java index ad56aeb6..67d8cf86 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Record.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/Record.java @@ -37,6 +37,16 @@ public class Record { private String signature; private Integer time; + public Record() { + } + + public Record(Record another) { + this.issuer = another.getIssuer(); + this.hash = another.getHash(); + this.signature = another.getSignature(); + this.time = another.getTime(); + } + public String getIssuer() { return issuer; } diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java index e5fd532c..e9efcdc4 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/elasticsearch/UserProfile.java @@ -30,5 +30,43 @@ public class UserProfile extends Record { public static final String PROPERTY_TITLE = "title"; public static final String PROPERTY_DESCRIPTION="description"; public static final String PROPERTY_CITY="city"; + public static final String PROPERTY_EMAIL="email"; + public static final String PROPERTY_LOCALE="locale"; + private String title; + private String description; + private String email; + private String locale; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getLocale() { + return locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } } diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java index dd92996d..07480993 100644 --- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java +++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java @@ -25,8 +25,6 @@ package org.duniter.core.client.service; import com.google.common.base.Joiner; import com.google.gson.Gson; import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.HttpHostConnectException; -import org.apache.http.entity.mime.content.InputStreamBody; import org.duniter.core.beans.InitializingBean; import org.duniter.core.client.config.Configuration; import org.duniter.core.client.model.bma.Error; @@ -52,7 +50,6 @@ import java.io.*; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.net.URI; -import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; /** diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/security/RestSecurityAuthAction.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/security/RestSecurityAuthAction.java index b62408e8..300e5d92 100644 --- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/security/RestSecurityAuthAction.java +++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/security/RestSecurityAuthAction.java @@ -22,6 +22,7 @@ package org.duniter.elasticsearch.rest.security; * #L% */ +import com.google.gson.Gson; import org.duniter.core.client.model.bma.gson.GsonUtils; import org.duniter.core.client.service.ServiceLocator; import org.duniter.core.util.StringUtils; @@ -44,6 +45,7 @@ public class RestSecurityAuthAction extends BaseRestHandler { private ChallengeMessageStore challengeMessageStore; private SecurityTokenStore securityTokenStore; + private Gson gson; @Inject public RestSecurityAuthAction(Settings settings, RestController controller, Client client, @@ -53,6 +55,7 @@ public class RestSecurityAuthAction extends BaseRestHandler { super(settings, controller, client); this.challengeMessageStore = challengeMessageStore; this.securityTokenStore = securityTokenStore; + this.gson = GsonUtils.newBuilder().create(); controller.registerHandler(POST, "/auth", this); securityController.allow(POST, "/auth"); } @@ -60,7 +63,7 @@ public class RestSecurityAuthAction extends BaseRestHandler { @Override protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception { - AuthData authData = GsonUtils.newBuilder().create().fromJson(request.content().toUtf8(), AuthData.class); + AuthData authData = gson.fromJson(request.content().toUtf8(), AuthData.class); // TODO Authorization: Basic instead ? diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java index f00a564b..905328c9 100644 --- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java +++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/AbstractService.java @@ -23,6 +23,7 @@ package org.duniter.elasticsearch.service; */ +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Joiner; @@ -34,6 +35,7 @@ import org.duniter.core.beans.Bean; import org.duniter.core.client.model.elasticsearch.Record; import org.duniter.core.exception.TechnicalException; import org.duniter.core.service.CryptoService; +import org.duniter.core.util.CollectionUtils; import org.duniter.core.util.StringUtils; import org.duniter.elasticsearch.PluginSettings; import org.duniter.elasticsearch.exception.AccessDeniedException; @@ -60,6 +62,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.SearchHitField; import org.nuiton.i18n.I18n; import java.io.*; @@ -104,6 +107,7 @@ public abstract class AbstractService implements Bean { this.pluginSettings = pluginSettings; this.cryptoService = cryptoService; this.objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); this.retryCount = pluginSettings.getNodeRetryCount(); this.retryWaitDuration = pluginSettings.getNodeRetryWaitDuration(); } @@ -263,23 +267,15 @@ public abstract class AbstractService implements Bean { // Read query result SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit searchHit : searchHits) { - if (searchHit.source() != null) { - JsonNode source = objectMapper.readTree(searchHit.source()); - for(String fieldName: fieldNames) { - result.put(fieldName, getMandatoryField(source, fieldName)); - } - - } - else { - for(String fieldName: fieldNames) { - result.put(fieldName, searchHit.getFields().get(fieldName).getValue()); - } + Map<String, SearchHitField> hitFields = searchHit.getFields(); + for(String fieldName: hitFields.keySet()) { + result.put(fieldName, hitFields.get(fieldName).getValue()); } break; } return result; } - catch(SearchPhaseExecutionException | JsonSyntaxException | IOException e) { + catch(SearchPhaseExecutionException | JsonSyntaxException e) { // Failed or no item on index throw new TechnicalException(String.format("[%s/%s] Unable to retrieve fields [%s] for document [%s]", index, type, @@ -302,6 +298,49 @@ public abstract class AbstractService implements Bean { return result.get(fieldName); } + /** + * Retrieve a document by id + * @param docId + * @return + */ + public <T extends Object> T getSourceById(String index, String type, String docId, Class<T> classOfT, String... fieldNames) { + + // Prepare request + SearchRequestBuilder searchRequest = client + .prepareSearch(index) + .setTypes(type) + .setSearchType(SearchType.DFS_QUERY_THEN_FETCH); + + searchRequest.setQuery(QueryBuilders.matchQuery("_id", docId)); + if (CollectionUtils.isNotEmpty(fieldNames)) { + searchRequest.setFetchSource(fieldNames, null); + } + else { + searchRequest.setFetchSource(true); // full source + } + + // Execute query + try { + SearchResponse response = searchRequest.execute().actionGet(); + + // Read query result + SearchHit[] searchHits = response.getHits().getHits(); + for (SearchHit searchHit : searchHits) { + if (searchHit.source() != null) { + return objectMapper.readValue(searchHit.source(), classOfT); + } + break; + } + return null; + } + catch(SearchPhaseExecutionException | JsonSyntaxException | IOException e) { + // Failed to get source + throw new TechnicalException(String.format("[%s/%s] Error while getting [%s]", + index, type, + docId), e); + } + } + protected void bulkFromClasspathFile(String classpathFile, String indexName, String indexType) { bulkFromClasspathFile(classpathFile, indexName, indexType, null); } diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/threadpool/ThreadPool.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/threadpool/ThreadPool.java index 85944904..0be7bc3a 100644 --- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/threadpool/ThreadPool.java +++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/threadpool/ThreadPool.java @@ -126,6 +126,16 @@ public class ThreadPool extends AbstractLifecycleComponent<ThreadPool> { }); } + /** + * Schedules an rest that runs on the scheduler thread, when possible (0 delay). + * + * @param command the rest to take + * @return a ScheduledFuture who's get will return when the task is complete and throw an exception if it is canceled + */ + public ScheduledFuture<?> schedule(Runnable command) { + return scheduler.schedule(new LoggingRunnable(command), 0, TimeUnit.MILLISECONDS); + } + /** * Schedules an rest that runs on the scheduler thread, after a delay. * diff --git a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/PluginInit.java b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/PluginInit.java index e148805a..51b73d86 100644 --- a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/PluginInit.java +++ b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/PluginInit.java @@ -26,10 +26,6 @@ import org.duniter.elasticsearch.gchange.service.MarketService; import org.duniter.elasticsearch.gchange.service.RegistryService; import org.duniter.elasticsearch.gchange.service.SynchroService; import org.duniter.elasticsearch.threadpool.ThreadPool; -import org.duniter.elasticsearch.user.service.event.UserEvent; -import org.duniter.elasticsearch.user.service.event.UserEventCodes; -import org.duniter.elasticsearch.user.service.event.UserEventService; -import org.elasticsearch.client.Client; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; diff --git a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/MarketService.java b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/MarketService.java index 95b97aaf..1236558c 100644 --- a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/MarketService.java +++ b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/MarketService.java @@ -35,10 +35,9 @@ import org.duniter.elasticsearch.gchange.PluginSettings; import org.duniter.elasticsearch.gchange.model.MarketRecord; import org.duniter.elasticsearch.gchange.model.event.GchangeEventCodes; import org.duniter.elasticsearch.service.AbstractService; +import org.duniter.elasticsearch.user.model.UserEvent; import org.duniter.elasticsearch.user.service.UserService; -import org.duniter.elasticsearch.user.service.event.UserEvent; -import org.duniter.elasticsearch.user.service.event.UserEventLink; -import org.duniter.elasticsearch.user.service.event.UserEventService; +import org.duniter.elasticsearch.user.service.UserEventService; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexResponse; @@ -432,15 +431,15 @@ public class MarketService extends AbstractService { String recordTitle = recordFields.get(MarketRecord.PROPERTY_TITLE).toString(); if (!issuer.equals(recordIssuer)) { - userEventService.notifyUser(recordIssuer, - new UserEvent(UserEvent.EventType.INFO, - GchangeEventCodes.NEW_COMMENT.name(), - new UserEventLink(INDEX, RECORD_TYPE, recordId), - I18n.n(isNewComment ? "duniter.market.event.newComment": "duniter.market.event.updateComment"), + userEventService.notifyUser( + UserEvent.newBuilder(UserEvent.EventType.INFO, GchangeEventCodes.NEW_COMMENT.name()) + .setMessage( + isNewComment ? I18n.n("duniter.market.event.newComment") : I18n.n("duniter.market.event.updateComment"), issuerTitle != null ? issuerTitle : issuer.substring(0, 8), - recordTitle - ) - ); + recordTitle) + .setRecipient(recordIssuer) + .setLink(INDEX, RECORD_TYPE, recordId) + .build()); } } diff --git a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/RegistryService.java b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/RegistryService.java index 7505b8f4..8792b19d 100644 --- a/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/RegistryService.java +++ b/duniter4j-es-gchange/src/main/java/org/duniter/elasticsearch/gchange/service/RegistryService.java @@ -25,20 +25,13 @@ package org.duniter.elasticsearch.gchange.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.gson.Gson; -import org.apache.commons.collections4.MapUtils; import org.duniter.core.client.model.bma.gson.GsonUtils; -import org.duniter.core.client.model.elasticsearch.RecordComment; import org.duniter.core.client.service.bma.BlockchainRemoteService; import org.duniter.core.exception.TechnicalException; import org.duniter.core.service.CryptoService; -import org.duniter.elasticsearch.exception.DocumentNotFoundException; import org.duniter.elasticsearch.gchange.PluginSettings; -import org.duniter.elasticsearch.gchange.model.MarketRecord; -import org.duniter.elasticsearch.gchange.model.event.GchangeEventCodes; import org.duniter.elasticsearch.service.AbstractService; -import org.duniter.elasticsearch.user.service.event.UserEvent; -import org.duniter.elasticsearch.user.service.event.UserEventLink; -import org.duniter.elasticsearch.user.service.event.UserEventService; +import org.duniter.elasticsearch.user.service.UserEventService; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexResponse; @@ -46,10 +39,8 @@ import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.nuiton.i18n.I18n; import java.io.IOException; -import java.util.Map; /** * Created by Benoit on 30/03/2015. 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 aeb251d9..1b9f5303 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,15 +24,13 @@ package org.duniter.elasticsearch.user; import org.duniter.elasticsearch.PluginSettings; import org.duniter.elasticsearch.threadpool.ThreadPool; +import org.duniter.elasticsearch.user.model.UserEvent; import org.duniter.elasticsearch.user.service.HistoryService; import org.duniter.elasticsearch.user.service.MessageService; import org.duniter.elasticsearch.user.service.SynchroService; import org.duniter.elasticsearch.user.service.UserService; -import org.duniter.elasticsearch.user.service.event.UserEvent; -import org.duniter.elasticsearch.user.service.event.UserEventCodes; -import org.duniter.elasticsearch.user.service.event.UserEventService; -import org.duniter.elasticsearch.user.websocket.WebsocketUserEventEndPoint; -import org.duniter.elasticsearch.websocket.WebSocketServer; +import org.duniter.elasticsearch.user.model.UserEventCodes; +import org.duniter.elasticsearch.user.service.UserEventService; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEvent.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEvent.java new file mode 100644 index 00000000..5e8e4921 --- /dev/null +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEvent.java @@ -0,0 +1,217 @@ +package org.duniter.elasticsearch.user.model; + +/* + * #%L + * Duniter4j :: Core Client API + * %% + * 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 com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.duniter.core.client.model.elasticsearch.Record; +import org.duniter.core.exception.TechnicalException; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * Created by blavenie on 29/11/16. + */ +public class UserEvent extends Record { + + public enum EventType { + INFO, + WARN, + ERROR + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Builder newBuilder(UserEvent.EventType type, String code) { + return new Builder(type, code, null, null); + } + + public static Builder newBuilder(UserEvent.EventType type, String code, String message, String... params) { + return new Builder(type, code, message, params); + } + + public static final String PROPERTY_TYPE="type"; + public static final String PROPERTY_CODE="code"; + public static final String PROPERTY_MESSAGE="message"; + public static final String PROPERTY_PARAMS="params"; + public static final String PROPERTY_LINK="link"; + public static final String PROPERTY_RECIPIENT="recipient"; + + + private EventType type; + + private String recipient; + + private String code; + + private String message; + + private String[] params; + + private UserEventLink link; + + public UserEvent() { + super(); + } + + public UserEvent(EventType type, String code, String message, String... params) { + super(); + this.type = type; + this.code = code; + this.message = message; + this.params = params; + setTime(getDefaultTime()); + } + + public UserEvent(UserEvent another) { + super(another); + this.type = another.getType(); + this.code = another.getCode(); + this.params = another.getParams(); + this.link = (another.getLink() != null) ? new UserEventLink(another.getLink()) : null; + this.message = another.getMessage(); + this.recipient = another.getRecipient(); + } + + public EventType getType() { + return type; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } + + public String[] getParams() { + return params; + } + + public UserEventLink getLink() { + return link; + } + + public String getLocalizedMessage(Locale locale) { + return I18n.l(locale, this.message, this.params); + } + + public void setType(EventType type) { + this.type = type; + } + + public void setCode(String code) { + this.code = code; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setParams(String[] params) { + this.params = params; + } + + public void setLink(UserEventLink link) { + this.link = link; + } + + public String getRecipient() { + return recipient; + } + + public void setRecipient(String recipient) { + this.recipient = recipient; + } + + @JsonIgnore + public String toJson() { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(this); + } catch(Exception e) { + throw new TechnicalException(e); + } + } + + @JsonIgnore + public String toJson(Locale locale) { + UserEvent copy = new UserEvent(this); + copy.setMessage(getLocalizedMessage(locale)); + return copy.toJson(); + } + + public static class Builder { + + private UserEvent result; + + private Builder() { + result = new UserEvent(); + } + + public Builder(UserEvent.EventType type, String code, String message, String... params) { + result = new UserEvent(type, code, message, params); + } + + public Builder setMessage(String message, String... params) { + result.setMessage(message); + result.setParams(params); + return this; + } + + public Builder setRecipient(String recipient) { + result.setRecipient(recipient); + return this; + } + + public Builder setIssuer(String issuer) { + result.setIssuer(issuer); + return this; + } + + public Builder setLink(String index, String type, String id) { + result.setLink(new UserEventLink(index, type, id)); + return this; + } + + public Builder setLink(String index, String type, String id, String anchor) { + result.setLink(new UserEventLink(index, type, id, anchor)); + return this; + } + + public UserEvent build() { + if (result.getTime() == null) { + result.setTime(getDefaultTime()); + } + return new UserEvent(result); + } + } + + private static int getDefaultTime() { + return Math.round(1f * System.currentTimeMillis() / 1000); + } +} diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventCodes.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java similarity index 94% rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventCodes.java rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java index 6c334ef9..39e4d4e0 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventCodes.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventCodes.java @@ -1,4 +1,4 @@ -package org.duniter.elasticsearch.user.service.event; +package org.duniter.elasticsearch.user.model; /* * #%L diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventLink.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventLink.java similarity index 65% rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventLink.java rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventLink.java index 23e1c87b..fb03cd71 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventLink.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserEventLink.java @@ -1,4 +1,4 @@ -package org.duniter.elasticsearch.user.service.event; +package org.duniter.elasticsearch.user.model; /* * #%L @@ -22,25 +22,38 @@ package org.duniter.elasticsearch.user.service.event; * #L% */ -import org.nuiton.i18n.I18n; - -import java.util.Locale; - /** * Created by blavenie on 29/11/16. */ public class UserEventLink { - private final String index; + private String index; + + private String type; - private final String type; + private String id; - private final String id; + private String anchor; + + public UserEventLink() { + } public UserEventLink(String index, String type, String id) { + this(index, type, id, null); + } + + public UserEventLink(String index, String type, String id, String anchor) { this.index = index; this.type = type; this.id = id; + this.anchor = anchor; + } + + public UserEventLink(UserEventLink another) { + this.index = another.getIndex(); + this.type = another.getType(); + this.id = another.getId(); + this.anchor = another.getAnchor(); } public String getIndex() { @@ -54,4 +67,8 @@ public class UserEventLink { public String getId() { return id; } + + public String getAnchor() { + return anchor; + } } diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java new file mode 100644 index 00000000..54608f00 --- /dev/null +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java @@ -0,0 +1,74 @@ +package org.duniter.elasticsearch.user.model; + +/* + * #%L + * Duniter4j :: Core Client API + * %% + * 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.client.model.elasticsearch.Record; + +/** + * Created by blavenie on 01/03/16. + */ +public class UserProfile extends Record { + + public static final String PROPERTY_TITLE = "title"; + public static final String PROPERTY_DESCRIPTION="description"; + public static final String PROPERTY_CITY="city"; + public static final String PROPERTY_EMAIL="email"; + public static final String PROPERTY_LOCALE="locale"; + + private String title; + private String description; + private String email; + private String locale; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getLocale() { + return locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } +} diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/ServiceModule.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/ServiceModule.java index a24ab24b..30e1b815 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/ServiceModule.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/ServiceModule.java @@ -22,7 +22,6 @@ package org.duniter.elasticsearch.user.service; * #L% */ -import org.duniter.elasticsearch.user.service.event.UserEventService; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.Module; diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java similarity index 68% rename from duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventService.java rename to duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java index 6d412001..1f002846 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventService.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserEventService.java @@ -1,4 +1,4 @@ -package org.duniter.elasticsearch.user.service.event; +package org.duniter.elasticsearch.user.service; /* * #%L @@ -25,25 +25,21 @@ package org.duniter.elasticsearch.user.service.event; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.base.Preconditions; import org.duniter.core.exception.TechnicalException; import org.duniter.core.service.CryptoService; import org.duniter.core.service.MailService; -import org.duniter.core.util.CollectionUtils; import org.duniter.core.util.StringUtils; import org.duniter.core.util.crypto.CryptoUtils; import org.duniter.core.util.crypto.KeyPair; import org.duniter.elasticsearch.PluginSettings; import org.duniter.elasticsearch.service.AbstractService; -import org.duniter.elasticsearch.service.changes.ChangeEvent; -import org.duniter.elasticsearch.service.changes.ChangeListener; -import org.duniter.elasticsearch.service.changes.ChangeService; -import org.duniter.elasticsearch.service.changes.ChangeUtils; import org.duniter.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; +import org.duniter.elasticsearch.user.model.UserEvent; +import org.duniter.elasticsearch.user.model.UserProfile; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; @@ -59,16 +55,26 @@ import java.util.Map; */ public class UserEventService extends AbstractService { + public interface UserEventListener { + String getId(); + String getPubkey(); + void onEvent(UserEvent event); + } + public static final String INDEX = "user"; public static final String EVENT_TYPE = "event"; private static final Map<String, UserEventListener> LISTENERS = new HashMap<>(); public static void registerListener(UserEventListener listener) { - LISTENERS.put(listener.getId(), listener); + synchronized (LISTENERS) { + LISTENERS.put(listener.getId(), listener); + } } - public static void unregisterListener(UserEventListener listener) { - LISTENERS.remove(listener.getId()); + public static synchronized void unregisterListener(UserEventListener listener) { + synchronized (LISTENERS) { + LISTENERS.remove(listener.getId()); + } } private final MailService mailService; @@ -78,7 +84,8 @@ public class UserEventService extends AbstractService { public final boolean mailEnable; @Inject - public UserEventService(Client client, PluginSettings settings, CryptoService cryptoService, MailService mailService, + public UserEventService(Client client, PluginSettings settings, CryptoService cryptoService, + MailService mailService, ThreadPool threadPool) { super("duniter.event." + INDEX, client, settings, cryptoService); this.mailService = mailService; @@ -95,20 +102,28 @@ public class UserEventService extends AbstractService { * Notify cluster admin */ public void notifyAdmin(UserEvent event) { - Locale locale = I18n.getDefaultLocale(); // TODO get locale from admin - // Add new event to index + UserProfile adminProfile; if (StringUtils.isNotBlank(nodePubkey)) { - indexEvent(nodePubkey, locale, event); + adminProfile = getUserProfile(nodePubkey, UserProfile.PROPERTY_EMAIL, UserProfile.PROPERTY_LOCALE); + } + else { + adminProfile = new UserProfile(); } - // Retrieve admin email - String adminEmail = pluginSettings.getMailAdmin(); - if (StringUtils.isBlank(adminEmail) && StringUtils.isNotBlank(nodePubkey)) { - adminEmail = getEmailByPk(nodePubkey); + // Add new event to index + Locale locale = StringUtils.isNotBlank(adminProfile.getLocale()) ? + new Locale(adminProfile.getLocale()) : + I18n.getDefaultLocale(); + if (StringUtils.isNotBlank(nodePubkey)) { + event.setRecipient(nodePubkey); + indexEvent(locale, event); } // Send email to admin + String adminEmail = StringUtils.isNotBlank(adminProfile.getEmail()) ? + adminProfile.getEmail() : + pluginSettings.getMailAdmin(); if (StringUtils.isNotBlank(adminEmail)) { String subjectPrefix = pluginSettings.getMailSubjectPrefix(); sendEmail(adminEmail, @@ -120,31 +135,43 @@ public class UserEventService extends AbstractService { /** * Notify a user */ - public void notifyUser(String recipient, UserEvent event) { + public void notifyUser(UserEvent event) { // Notify user threadPool.schedule(() -> { - doNotifyUser(recipient, event); + doNotifyUser(event); }, TimeValue.timeValueMillis(100)); } - public String indexEvent(String recipient, Locale locale, UserEvent event) { + public String indexEvent(Locale locale, UserEvent event) { + Preconditions.checkNotNull(event.getRecipient()); + Preconditions.checkNotNull(event.getType()); + Preconditions.checkNotNull(event.getCode()); + // Generate json String eventJson; if (StringUtils.isNotBlank(nodePubkey)) { - eventJson = UserEventUtils.toJson(nodePubkey, recipient, locale, event, null); - String signature = cryptoService.sign(eventJson, nodeKeyPair.getSecKey()); - eventJson = UserEventUtils.toJson(nodePubkey, recipient, locale, event, signature); + UserEvent signedEvent = new UserEvent(event); + signedEvent.setMessage(event.getLocalizedMessage(locale)); + // set issuer, hash, signature + signedEvent.setIssuer(nodePubkey); + String hash = cryptoService.hash(toJson(signedEvent)); + signedEvent.setHash(hash); + String signature = cryptoService.sign(toJson(signedEvent), nodeKeyPair.getSecKey()); + signedEvent.setSignature(signature); + eventJson = toJson(signedEvent); } else { - // Node has not keyring : TODO no issuer ? - eventJson = UserEventUtils.toJson(recipient, recipient, locale, event, null); + // Node has not keyring: do NOT sign it + // TODO : autogen a key pair ? + eventJson = event.toJson(locale); } if (logger.isDebugEnabled()) { - logger.debug(String.format("Indexing a event to recipient [%s]", recipient.substring(0, 8))); + logger.debug(String.format("Indexing a event to recipient [%s]", event.getRecipient().substring(0, 8))); } // do indexation return indexEvent(eventJson, false /*checkSignature*/); + } public String indexEvent(String eventJson) { @@ -155,7 +182,7 @@ public class UserEventService extends AbstractService { if (checkSignature) { JsonNode jsonNode = readAndVerifyIssuerSignature(eventJson); - String recipient = jsonNode.get(org.duniter.core.client.model.elasticsearch.Event.PROPERTY_ISSUER).asText(); + String recipient = getMandatoryField(jsonNode, UserEvent.PROPERTY_ISSUER).asText(); if (logger.isDebugEnabled()) { logger.debug(String.format("Indexing a event to recipient [%s]", recipient.substring(0, 8))); } @@ -248,15 +275,6 @@ public class UserEventService extends AbstractService { } } - private String getEmailByPk(String issuerPk) { - // TODO get it from user profile ? - return pluginSettings.getMailAdmin(); - } - - private String getEmailSubject(Locale locale, UserEvent event) { - - return I18n.l(locale, "duniter4j.event.subject."+event.getType().name()); - } /** * Send email @@ -278,8 +296,6 @@ public class UserEventService extends AbstractService { } } - - private KeyPair getNodeKeyPairOrNull(PluginSettings pluginSettings) { if (StringUtils.isNotBlank(pluginSettings.getKeyringSalt()) && @@ -299,27 +315,45 @@ public class UserEventService extends AbstractService { /** * Notify a user */ - private void doNotifyUser(String recipient, UserEvent event) { + private void doNotifyUser(final UserEvent event) { + Preconditions.checkNotNull(event.getRecipient()); - String email = getEmailByPk(recipient); - Locale locale = I18n.getDefaultLocale(); // TODO get locale + // Get user profile locale + UserProfile userProfile = getUserProfile(event.getRecipient(), + UserProfile.PROPERTY_EMAIL, UserProfile.PROPERTY_TITLE, UserProfile.PROPERTY_LOCALE); - // Add new event to index - indexEvent(recipient, locale, event); + Locale locale = userProfile.getLocale() != null ? new Locale(userProfile.getLocale()) : null; - // Send email to user - // TODO : group email by day ? - if (StringUtils.isNotBlank(email)) { - String subjectPrefix = pluginSettings.getMailSubjectPrefix(); - sendEmail(email, - I18n.l(locale, "duniter4j.event.subject."+event.getType().name(), subjectPrefix), - event.getLocalizedMessage(locale)); - } + // Add new event to index + indexEvent(locale, event); - for (UserEventListener listener: LISTENERS.values()) { - if (recipient.equals(listener.getPubkey())) { - listener.onEvent(event); + // Notify listeners + threadPool.schedule(() -> { + synchronized (LISTENERS) { + for (UserEventListener listener : LISTENERS.values()) { + if (event.getRecipient().equals(listener.getPubkey())) { + listener.onEvent(event); + } + } } + }); + } + + private UserProfile getUserProfile(String pubkey, String... fieldnames) { + UserProfile result = getSourceById(UserService.INDEX, UserService.PROFILE_TYPE, pubkey, UserProfile.class, fieldnames); + if (result == null) result = new UserProfile(); + return result; + } + + private UserProfile getUserProfileOrNull(String pubkey, String... fieldnames) { + return getSourceById(UserService.INDEX, UserService.PROFILE_TYPE, pubkey, UserProfile.class, fieldnames); + } + + private String toJson(UserEvent userEvent) { + try { + return objectMapper.writeValueAsString(userEvent); + } catch(JsonProcessingException e) { + throw new TechnicalException("Unable to serialize UserEvent object", e); } } } 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 cad585fd..0cfbf566 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 @@ -32,7 +32,6 @@ import org.duniter.core.service.MailService; import org.duniter.elasticsearch.PluginSettings; import org.duniter.elasticsearch.exception.AccessDeniedException; import org.duniter.elasticsearch.service.AbstractService; -import org.duniter.elasticsearch.user.service.event.UserEventService; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.update.UpdateResponse; diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEvent.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEvent.java deleted file mode 100644 index e58ccbd2..00000000 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEvent.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.duniter.elasticsearch.user.service.event; - -/* - * #%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.nuiton.i18n.I18n; - -import java.util.Locale; - -/** - * Created by blavenie on 29/11/16. - */ -public class UserEvent { - - private final EventType type; - - private final String code; - - private final long time; - - private final String message; - - private final String[] params; - - private final UserEventLink link; - - public UserEvent(EventType type, String code) { - this(type, code, null, "duniter.event." + code, null); - } - - public UserEvent(EventType type, String code, String message, String... params) { - this(type, code, null, message, params); - } - - public UserEvent(EventType type, String code, UserEventLink link, String message, String... params) { - this.type = type; - this.code = code; - this.params = params; - this.link = link; - this.message = message; - this.time = Math.round(1d * System.currentTimeMillis() / 1000); - } - - public EventType getType() { - return type; - } - - public String getCode() { - return code; - } - - public String getMessage() { - return message; - } - - public String getLocalizedMessage(Locale locale) { - return I18n.l(locale, message, params); - } - - public String[] getParams() { - return params; - } - - public long getTime() { - return time; - } - - public UserEventLink getLink() { - return link; - } - - public enum EventType { - INFO, - WARN, - ERROR - } -} diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventListener.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventListener.java deleted file mode 100644 index 9238e4a8..00000000 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.duniter.elasticsearch.user.service.event; - -public interface UserEventListener { - String getId(); - String getPubkey(); - void onEvent(UserEvent event); -} \ No newline at end of file diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventUtils.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventUtils.java deleted file mode 100644 index 20f2ed4d..00000000 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/event/UserEventUtils.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.duniter.elasticsearch.user.service.event; - -import org.duniter.core.exception.TechnicalException; -import org.duniter.core.util.CollectionUtils; -import org.duniter.core.util.StringUtils; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; - -import java.io.IOException; -import java.util.Locale; - -/** - * Created by blavenie on 02/12/16. - */ -public abstract class UserEventUtils { - - public static String toJson(String issuer, String recipient, Locale locale, UserEvent event, String signature) { - try { - XContentBuilder eventObject = XContentFactory.jsonBuilder().startObject() - .field("type", event.getType().name()) - .field("issuer", issuer) // TODO isuer = node pubkey - .field("recipient", recipient) - .field("time", event.getTime()) - .field("code", event.getCode()) - .field("message", event.getLocalizedMessage(locale)); - if (CollectionUtils.isNotEmpty(event.getParams())) { - eventObject.array("params", event.getParams()); - } - - // Link - UserEventLink link = event.getLink(); - if (link != null) { - eventObject.startObject("link") - .field("index", link.getIndex()) - .field("type", link.getType()); - if (StringUtils.isNotBlank(link.getId())) { - eventObject.field("id", link.getId()); - } - eventObject.endObject(); - } - - if (StringUtils.isNotBlank(signature)) { - eventObject.field("signature", signature); - } - eventObject.endObject(); - return eventObject.string(); - } - catch(IOException e) { - throw new TechnicalException(e); - } - - } - - public static String toJson(Locale locale, UserEvent event) { - try { - XContentBuilder eventObject = XContentFactory.jsonBuilder().startObject() - .field("type", event.getType().name()) - .field("time", event.getTime()) - .field("code", event.getCode()) - .field("message", event.getLocalizedMessage(locale)); - if (CollectionUtils.isNotEmpty(event.getParams())) { - eventObject.array("params", event.getParams()); - } - - // Link - UserEventLink link = event.getLink(); - if (link != null) { - eventObject.startObject("link") - .field("index", link.getIndex()) - .field("type", link.getType()); - if (StringUtils.isNotBlank(link.getId())) { - eventObject.field("id", link.getId()); - } - eventObject.endObject(); - } - eventObject.endObject(); - return eventObject.string(); - } - catch(IOException e) { - throw new TechnicalException(e); - } - - } -} diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/websocket/WebsocketUserEventEndPoint.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/websocket/WebsocketUserEventEndPoint.java index 2c01b7ef..5037ac3e 100644 --- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/websocket/WebsocketUserEventEndPoint.java +++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/websocket/WebsocketUserEventEndPoint.java @@ -40,10 +40,8 @@ package org.duniter.elasticsearch.user.websocket; import org.duniter.core.client.model.bma.Constants; import org.duniter.core.util.StringUtils; -import org.duniter.elasticsearch.user.service.event.UserEvent; -import org.duniter.elasticsearch.user.service.event.UserEventListener; -import org.duniter.elasticsearch.user.service.event.UserEventService; -import org.duniter.elasticsearch.user.service.event.UserEventUtils; +import org.duniter.elasticsearch.user.model.UserEvent; +import org.duniter.elasticsearch.user.service.UserEventService; import org.duniter.elasticsearch.websocket.WebSocketServer; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.logging.ESLogger; @@ -57,7 +55,7 @@ import java.util.Locale; import java.util.regex.Pattern; @ServerEndpoint(value = "/event/user/{pubkey}/{locale}") -public class WebsocketUserEventEndPoint implements UserEventListener { +public class WebsocketUserEventEndPoint implements UserEventService.UserEventListener { public static class Init { @@ -97,7 +95,7 @@ public class WebsocketUserEventEndPoint implements UserEventListener { @Override public void onEvent(UserEvent event) { - session.getAsyncRemote().sendText(UserEventUtils.toJson(locale, event)); + session.getAsyncRemote().sendText(event.toJson(locale)); } @Override -- GitLab