Skip to content

Commit

Permalink
eventuate-clients#9: Enhancing the Eventuate Java Client According GD…
Browse files Browse the repository at this point in the history
…PR. Reworking structure.
  • Loading branch information
dartartem committed Apr 18, 2018
1 parent b54df70 commit aa69058
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import io.eventuate.*;
import io.eventuate.encryption.EncryptedEventData;
import io.eventuate.encryption.EventDataEncryptor;
import io.eventuate.encryption.NoEncryptionKeyProvidedException;
import io.eventuate.encryption.EventEncryptor;
import io.eventuate.encryption.NoEventEncryptorProvidedException;
import io.eventuate.javaclient.commonimpl.schemametadata.EmptyEventSchemaMetadataManager;
import io.eventuate.javaclient.commonimpl.schemametadata.EventSchemaMetadataManager;

Expand All @@ -29,7 +29,7 @@ public class EventuateAggregateStoreImpl implements EventuateAggregateStore {
private SerializedEventDeserializer serializedEventDeserializer = new DefaultSerializedEventDeserializer();
private MissingApplyEventMethodStrategy missingApplyEventMethodStrategy;
private EventSchemaMetadataManager eventSchemaMetadataManager = new EmptyEventSchemaMetadataManager();
private EventDataEncryptor eventDataEncryptor = new EventDataEncryptor();
private Optional<EventEncryptor> eventEncryptor = Optional.empty();

public EventuateAggregateStoreImpl(AggregateCrud aggregateCrud, AggregateEvents aggregateEvents, SnapshotManager snapshotManager, MissingApplyEventMethodStrategy missingApplyEventMethodStrategy) {
this.aggregateCrud = aggregateCrud;
Expand All @@ -38,6 +38,10 @@ public EventuateAggregateStoreImpl(AggregateCrud aggregateCrud, AggregateEvents
this.missingApplyEventMethodStrategy = missingApplyEventMethodStrategy;
}

public void setEventEncryptor(Optional<EventEncryptor> eventEncryptor) {

This comment has been minimized.

Copy link
@cer

cer Apr 18, 2018

No point in setEventEncryptor() taking an Optional.
if there is no eventEncryptor then the app wouldn't call setEventEncryptor()

This comment has been minimized.

Copy link
@dartartem

dartartem Apr 18, 2018

Author Owner

ok

this.eventEncryptor = eventEncryptor;
}

public void setSerializedEventDeserializer(SerializedEventDeserializer serializedEventDeserializer) {
this.serializedEventDeserializer = serializedEventDeserializer;
}
Expand All @@ -55,16 +59,20 @@ public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> save(Class
@Override
public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> save(Class<T> clasz, List<Event> events, Optional<SaveOptions> saveOptions) {
Optional<String> serializedMetadata = saveOptions.flatMap(so -> withSchemaMetadata(clasz, so.getEventMetadata())).map(JSonMapper::toJson);

List<EventTypeAndData> serializedEvents = events
.stream()
.map(event ->
toEventTypeAndData(event,
serializedMetadata,
json -> saveOptions
.flatMap(SaveOptions::getEncryptionKey)
.map(k -> new EncryptedEventData(k.getId(), eventDataEncryptor.encrypt(k, json)).asString())
json -> eventEncryptor

This comment has been minimized.

Copy link
@cer

cer Apr 18, 2018

AGAIN Please write simple code that, for example, does not mapping over Option<.. EncryptionKey... >

List<EventTypeAndData> serializedEvents = events
        .stream()
        .map(event ->
                toEventTypeAndData(event,
                        serializedMetadata,
                        json -> saveOptions
                                .flatMap(SaveOptions::getEncryptionKey)
                                .map(k -> new EncryptedEventData(k.getId(), eventDataEncryptor.encrypt(k, json)).asString())
                                .orElse(json)))

=>

Option encryptionKey = saveOptions.flatMap(SaveOptions::getEncryptionKey);
List serializedEvents = events
.stream()
.map(event ->
toEventTypeAndData(event,
serializedMetadata,
json -> encyptIfNeccessary(encryptionKey, json)

This comment has been minimized.

Copy link
@dartartem

dartartem Apr 18, 2018

Author Owner

Chris, I am sorry, but I wrote in the report that fix it tomorrow.

.map(encryptor -> saveOptions
.flatMap(SaveOptions::getEncryptionKeyId)
.map(keyId -> new EncryptedEventData(keyId, encryptor.encrypt(keyId, json)).asString())
.orElse(json))
.orElse(json)))
.collect(Collectors.toList());

CompletableFuture<EntityIdVersionAndEventIds> outcome = aggregateCrud.save(clasz.getName(), serializedEvents, AggregateCrudMapping.toAggregateCrudSaveOptions(saveOptions));
if (activityLogger.isDebugEnabled())
return CompletableFutureUtil.tap(outcome, (result, throwable) -> {
Expand Down Expand Up @@ -123,17 +131,16 @@ public <T extends Aggregate<T>> CompletableFuture<EntityWithMetadata<T>> find(Cl
.upcastEvents(clasz, le.getEvents())
.stream()
.map(event ->
AggregateCrudMapping.toEventWithMetadata(event, json -> findOptions
.flatMap(FindOptions::getEncryptionKey)
.map(k -> EncryptedEventData.isEventDataStringEncrypted(json) ?
eventDataEncryptor.decrypt(k, EncryptedEventData.fromEventDataString(json).getData()) :
json)
.orElseGet(() -> {
if (EncryptedEventData.isEventDataStringEncrypted(json)) {
throw new NoEncryptionKeyProvidedException(EncryptedEventData.fromEventDataString(json));
}
return json;
})))
AggregateCrudMapping.toEventWithMetadata(event, json -> {

This comment has been minimized.

Copy link
@cer

cer Apr 18, 2018

AGAIN - please write simple code.

if (EncryptedEventData.isEventDataStringEncrypted(json)) {
EncryptedEventData encryptedEventData = EncryptedEventData.fromEventDataString(json);
return eventEncryptor
.map(e -> e.decrypt(encryptedEventData.getEncryptionKeyId(), encryptedEventData.getData()))
.orElseThrow(() -> new NoEventEncryptorProvidedException(encryptedEventData));
} else {
return json;
}
}))
.collect(Collectors.toList());

List<Event> events = eventsWithIds.stream().map(EventWithMetadata::getEvent).collect(Collectors.toList());
Expand Down Expand Up @@ -164,14 +171,17 @@ public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> update(Cla
@Override
public <T extends Aggregate<T>> CompletableFuture<EntityIdAndVersion> update(Class<T> clasz, EntityIdAndVersion entityIdAndVersion, List<Event> events, Optional<UpdateOptions> updateOptions) {
Optional<String> serializedMetadata = updateOptions.flatMap(UpdateOptions::getEventMetadata).map(JSonMapper::toJson);

List<EventTypeAndData> serializedEvents = events
.stream()
.map(event ->
toEventTypeAndData(event,
serializedMetadata,
json -> updateOptions
.flatMap(UpdateOptions::getEncryptionKey)
.map(k -> new EncryptedEventData(k.getId(), eventDataEncryptor.encrypt(k, json)).asString())
json -> eventEncryptor

This comment has been minimized.

Copy link
@cer

cer Apr 18, 2018

AGAIN. PLEASE WRITE SIMPLE CODE

.map(encryptor -> updateOptions
.flatMap(UpdateOptions::getEncryptionKeyId)
.map(keyId -> new EncryptedEventData(keyId, encryptor.encrypt(keyId, json)).asString())
.orElse(json))
.orElse(json)))
.collect(Collectors.toList());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
import io.eventuate.SubscriberOptions;
import io.eventuate.UpdateOptions;
import io.eventuate.encryption.EncryptedEventData;
import io.eventuate.encryption.NoEncryptionKeyProvidedException;
import io.eventuate.encryption.EventEncryptor;
import io.eventuate.encryption.NoEventEncryptorProvidedException;
import io.eventuate.javaclient.commonimpl.*;
import io.eventuate.encryption.EventDataEncryptor;
import io.eventuate.sync.EventuateAggregateStore;

import java.util.List;
Expand All @@ -40,7 +40,8 @@ public class EventuateAggregateStoreImpl implements EventuateAggregateStore {
private SnapshotManager snapshotManager;
private SerializedEventDeserializer serializedEventDeserializer = new DefaultSerializedEventDeserializer();
private MissingApplyEventMethodStrategy missingApplyEventMethodStrategy;
private EventDataEncryptor eventDataEncryptor = new EventDataEncryptor();
private Optional<EventEncryptor> eventEncryptor;


public EventuateAggregateStoreImpl(AggregateCrud aggregateCrud, AggregateEvents aggregateEvents, SnapshotManager snapshotManager, MissingApplyEventMethodStrategy missingApplyEventMethodStrategy) {
this.aggregateCrud = aggregateCrud;
Expand All @@ -49,6 +50,10 @@ public EventuateAggregateStoreImpl(AggregateCrud aggregateCrud, AggregateEvents
this.missingApplyEventMethodStrategy = missingApplyEventMethodStrategy;
}

public void setEventEncryptor(Optional<EventEncryptor> eventEncryptor) {
this.eventEncryptor = eventEncryptor;
}

public void setSerializedEventDeserializer(SerializedEventDeserializer serializedEventDeserializer) {
this.serializedEventDeserializer = serializedEventDeserializer;
}
Expand All @@ -66,14 +71,17 @@ public <T extends Aggregate<T>> EntityIdAndVersion save(Class<T> clasz, List<Eve
@Override
public <T extends Aggregate<T>> EntityIdAndVersion save(Class<T> clasz, List<Event> events, Optional<SaveOptions> saveOptions) {
Optional<String> serializedMetadata = saveOptions.flatMap(SaveOptions::getEventMetadata).map(JSonMapper::toJson);

List<EventTypeAndData> serializedEvents = events
.stream()
.map(event ->
toEventTypeAndData(event,
serializedMetadata,
json -> saveOptions
.flatMap(SaveOptions::getEncryptionKey)
.map(k -> new EncryptedEventData(k.getId(), eventDataEncryptor.encrypt(k, json)).asString())
json -> eventEncryptor
.map(encryptor -> saveOptions
.flatMap(SaveOptions::getEncryptionKeyId)
.map(keyId -> new EncryptedEventData(keyId, encryptor.encrypt(keyId, json)).asString())
.orElse(json))
.orElse(json)))
.collect(Collectors.toList());
try {
Expand Down Expand Up @@ -104,23 +112,23 @@ public <T extends Aggregate<T>> EntityWithMetadata<T> find(Class<T> clasz, Strin
LoadedEvents le = aggregateCrud.find(clasz.getName(), entityId, toAggregateCrudFindOptions(findOptions));
if (activityLogger.isDebugEnabled())
activityLogger.debug("Loaded entity: {} {} {}", clasz.getName(), entityId, le.getEvents());

List<EventWithMetadata> eventsWithIds = le
.getEvents()
.stream()
.map(event ->
AggregateCrudMapping.toEventWithMetadata(event, json ->
findOptions
.flatMap(FindOptions::getEncryptionKey)
.map(k -> EncryptedEventData.isEventDataStringEncrypted(json) ?
eventDataEncryptor.decrypt(k, EncryptedEventData.fromEventDataString(json).getData()) :
json)
.orElseGet(() -> {
if (EncryptedEventData.isEventDataStringEncrypted(json)) {
throw new NoEncryptionKeyProvidedException(EncryptedEventData.fromEventDataString(json));
}
return json;
})))
AggregateCrudMapping.toEventWithMetadata(event, json -> {
if (EncryptedEventData.isEventDataStringEncrypted(json)) {
EncryptedEventData encryptedEventData = EncryptedEventData.fromEventDataString(json);
return eventEncryptor
.map(e -> e.decrypt(encryptedEventData.getEncryptionKeyId(), encryptedEventData.getData()))
.orElseThrow(() -> new NoEventEncryptorProvidedException(encryptedEventData));
} else {
return json;
}
}))
.collect(Collectors.toList());

List<Event> events = eventsWithIds.stream().map(EventWithMetadata::getEvent).collect(Collectors.toList());
return new EntityWithMetadata<T>(
new EntityIdAndVersion(entityId,
Expand Down Expand Up @@ -152,16 +160,20 @@ public <T extends Aggregate<T>> EntityIdAndVersion update(Class<T> clasz, Entity
public <T extends Aggregate<T>> EntityIdAndVersion update(Class<T> clasz, EntityIdAndVersion entityIdAndVersion, List<Event> events, Optional<UpdateOptions> updateOptions) {
try {
Optional<String> serializedEventMetadata = updateOptions.flatMap(UpdateOptions::getEventMetadata).map(JSonMapper::toJson);

List<EventTypeAndData> serializedEvents = events
.stream()
.map(event ->
toEventTypeAndData(event,
serializedEventMetadata,
json -> updateOptions
.flatMap(UpdateOptions::getEncryptionKey)
.map(k -> new EncryptedEventData(k.getId(), eventDataEncryptor.encrypt(k, json)).asString())
json -> eventEncryptor
.map(encryptor -> updateOptions
.flatMap(UpdateOptions::getEncryptionKeyId)
.map(keyId -> new EncryptedEventData(keyId, encryptor.encrypt(keyId, json)).asString())
.orElse(json))
.orElse(json)))
.collect(Collectors.toList());

EntityIdVersionAndEventIds result = aggregateCrud.update(new EntityIdAndType(entityIdAndVersion.getEntityId(), clasz.getName()),
entityIdAndVersion.getEntityVersion(),
serializedEvents,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import io.eventuate.EntityIdAndType;
import io.eventuate.javaclient.commonimpl.*;
import io.eventuate.encryption.EncryptedEventData;
import io.eventuate.encryption.EncryptionKey;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
package io.eventuate.javaclient.spring.autoconfiguration;

import io.eventuate.*;
import io.eventuate.encryption.EncryptionKey;
import io.eventuate.encryption.EventDataEncryptor;
import io.eventuate.encryption.NoEncryptionKeyProvidedException;
import io.eventuate.encryption.*;
import io.vertx.core.json.Json;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.Optional;

public abstract class AbstractEventuateAggregateStoreEncryptionTest {

private static String hexRegExp = "^[0-9a-fA-F]+$";

private static final String idKey = "1";
protected static final String keyId = "1";
private static final String key = "Super strong password";
private static final String salt = "47b4033642e911e8842f0ed5f89f718b";

private static final String testEventData = "Some secret data";
private static final String testEventDataUpdated = "Some secret data (Updated)";

protected static final EncryptionKey encryptionKey = new EncryptionKey(idKey, key, salt);
protected static final EventEncryptionKey eventEncryptionKey = new EventEncryptionKey(keyId, key, salt);

protected EventEncryptor eventEncryptor = new DefaultEventEncryptor(keyId -> {
if (AbstractEventuateAggregateStoreEncryptionTest.keyId.equals(keyId)) {
return eventEncryptionKey;
}

protected static final EventDataEncryptor eventDataEncryptor = new EventDataEncryptor();
throw new IllegalArgumentException("No encryption key found!");
});

@Before
public void initEventEncryptor() {
setEventEncryptor(Optional.of(eventEncryptor));
}

@Test
public void testSaveEncrypted() throws Exception {
EntityIdAndVersion entityIdAndVersion = save(testEventData);

NoEncryptionKeyProvidedException noEncryptionKeyProvidedException = null;
NoEventEncryptorProvidedException noEventEncryptorProvidedException = null;

try {
find(entityIdAndVersion, false);
} catch (NoEncryptionKeyProvidedException e) {
noEncryptionKeyProvidedException = e;
setEventEncryptor(Optional.empty());
find(entityIdAndVersion);
} catch (NoEventEncryptorProvidedException e) {
noEventEncryptorProvidedException = e;
}

Assert.assertNotNull(noEncryptionKeyProvidedException);
Assert.assertNotNull(noEventEncryptorProvidedException);

String data = noEncryptionKeyProvidedException.getEncryptedEventData().getData();
String data = noEventEncryptorProvidedException.getEncryptedEventData().getData();

Assert.assertNotNull(data);
Assert.assertFalse(data.trim().isEmpty());
Assert.assertTrue(data.matches(hexRegExp));
Assert.assertEquals(Json.encode(new SomeEvent(testEventData)), eventDataEncryptor.decrypt(encryptionKey, data));
Assert.assertEquals(Json.encode(new SomeEvent(testEventData)), eventEncryptor.decrypt(keyId, data));

Assert.assertFalse(testEventData.matches(hexRegExp));
}
Expand All @@ -51,7 +64,7 @@ public void testSaveEncrypted() throws Exception {
public void testSaveAndFind() throws Exception {
EntityIdAndVersion entityIdAndVersion = save(testEventData);

EntityWithMetadata<SomeAggregate> entityEntityWithMetadata = find(entityIdAndVersion, true);
EntityWithMetadata<SomeAggregate> entityEntityWithMetadata = find(entityIdAndVersion);

Assert.assertEquals(1, entityEntityWithMetadata.getEvents().size());
Assert.assertEquals(testEventData, ((SomeEvent)entityEntityWithMetadata.getEvents().get(0).getEvent()).getData());
Expand All @@ -63,7 +76,7 @@ public void testUpdateAndFind() throws Exception {

entityIdAndVersion = update(entityIdAndVersion, testEventDataUpdated);

EntityWithMetadata<SomeAggregate> entityEntityWithMetadata = find(entityIdAndVersion, true);
EntityWithMetadata<SomeAggregate> entityEntityWithMetadata = find(entityIdAndVersion);

Assert.assertEquals(2, entityEntityWithMetadata.getEvents().size());
Assert.assertEquals(testEventDataUpdated,
Expand All @@ -72,7 +85,8 @@ public void testUpdateAndFind() throws Exception {

protected abstract EntityIdAndVersion save(String data) throws Exception;
protected abstract EntityIdAndVersion update(EntityIdAndVersion entityIdAndVersion, String data) throws Exception;
protected abstract EntityWithMetadata<SomeAggregate> find(EntityIdAndVersion entityIdAndVersion, boolean encrypted) throws Exception;
protected abstract EntityWithMetadata<SomeAggregate> find(EntityIdAndVersion entityIdAndVersion) throws Exception;
protected abstract void setEventEncryptor(Optional<EventEncryptor> eventEncryptor);

public static class SomeAggregate implements Aggregate<SomeAggregate> {
@Override
Expand Down
Loading

0 comments on commit aa69058

Please sign in to comment.