Skip to content

Commit

Permalink
Sign IIds
Browse files Browse the repository at this point in the history
Add IIdCodecFlag to parametrize IdCodec-calls. The IdCodec will add a
signature to the unqualified ids during serialization and asserts the
signature's validity during deserialization.
Add annotation IdSignature which can be used to exclude IIds from
signature creation during serialization/deserialization in the IdCodec.
Pass ScoutDataObjectModuleContext to all IId-serializers/deserializers
and use it to compute the IIdCodecFlags for each call to IdCodec.
Add IIdSignatureDataObjectMapper/JacksonIdSignatureDataObjectMapper
that uses signatures during serializing/deserializing and use it in JSON
layer.
Add rest.jersey.server-module to inject reader/writer that uses
signatures and IIdCodecFlags to param converters.
Add IdSignatureRestClientFilter to inject writer/reader that uses
signatures.

340299, 373060
  • Loading branch information
fschinkel committed May 24, 2024
1 parent cda8e39 commit 45e8dee
Show file tree
Hide file tree
Showing 63 changed files with 2,581 additions and 213 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
package org.eclipse.scout.rt.dataobject.fixture;

import org.eclipse.scout.rt.dataobject.id.AbstractRootId;
import org.eclipse.scout.rt.dataobject.id.IdTypeName;

@IdTypeName("scout.FixtureIntegerId")
public final class FixtureIntegerId extends AbstractRootId<Integer> {
private static final long serialVersionUID = 1L;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
* Copyright (c) 2010, 2024 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -11,9 +11,12 @@

import static org.junit.Assert.*;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

import org.eclipse.scout.rt.dataobject.fixture.FixtureCompositeId;
Expand All @@ -22,11 +25,17 @@
import org.eclipse.scout.rt.dataobject.fixture.FixtureStringId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureUuId;
import org.eclipse.scout.rt.dataobject.fixture.FixtureWrapperCompositeId;
import org.eclipse.scout.rt.dataobject.id.IdCodec.IdCodecFlag;
import org.eclipse.scout.rt.platform.BEANS;
import org.eclipse.scout.rt.platform.BeanMetaData;
import org.eclipse.scout.rt.platform.IBean;
import org.eclipse.scout.rt.platform.exception.PlatformException;
import org.eclipse.scout.rt.platform.util.Assertions.AssertionException;
import org.eclipse.scout.rt.platform.util.StringUtility;
import org.eclipse.scout.rt.platform.util.date.IDateProvider;
import org.eclipse.scout.rt.testing.platform.BeanTestingHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
Expand All @@ -40,6 +49,22 @@ public abstract class AbstractIdCodecTest {
protected static final String TEST_STRING_2 = "bazäöl";
protected static final Date TEST_DATE = new Date(123456789);

protected IBean<?> m_codecBean;

@Before
public void before() {
m_codecBean = BeanTestingHelper.get().registerBean(new BeanMetaData(getCodecReplacementType()).withReplace(true));
}

@After
public void after() {
BeanTestingHelper.get().unregisterBean(m_codecBean);
}

protected Class<? extends IdCodec> getCodecReplacementType() {
return P_IdCodec.class;
}

/**
* @return IdCodec instance used for tests
*/
Expand Down Expand Up @@ -571,13 +596,13 @@ public void testFromQualified_UnsupportedWrappedType() {
@Test
public void testFromQualifiedLenient_Default() {
FixtureUuId id = FixtureUuId.of(TEST_UUID);
IId id2 = getCodec().fromQualifiedLenient("scout.FixtureUuId:" + TEST_UUID);
IId id2 = getCodec().fromQualified("scout.FixtureUuId:" + TEST_UUID, IdCodecFlag.LENIENT);
assertEquals(id, id2);
}

@Test
public void testFromQualifiedLenient_UnknownType() {
IId id = getCodec().fromQualifiedLenient("DoesNotExist:" + TEST_UUID);
IId id = getCodec().fromQualified("DoesNotExist:" + TEST_UUID, IdCodecFlag.LENIENT);
assertTrue(id instanceof UnknownId);
UnknownId uid = (UnknownId) id;
assertEquals("DoesNotExist", uid.getIdTypeName());
Expand All @@ -589,7 +614,7 @@ public void testFromQualifiedLenient_UnknownType() {

@Test
public void testFromQualifiedLenient_CompositeUnknownType() {
IId id = getCodec().fromQualifiedLenient("DoesNotExist:abc;123");
IId id = getCodec().fromQualified("DoesNotExist:abc;123", IdCodecFlag.LENIENT);
assertTrue(id instanceof UnknownId);
UnknownId uid = (UnknownId) id;
assertEquals("DoesNotExist", uid.getIdTypeName());
Expand All @@ -601,7 +626,7 @@ public void testFromQualifiedLenient_CompositeUnknownType() {

@Test
public void testFromQualifiedLenient_WrongFormat() {
IId id = getCodec().fromQualifiedLenient("Does:Not:Exist:" + TEST_UUID);
IId id = getCodec().fromQualified("Does:Not:Exist:" + TEST_UUID, IdCodecFlag.LENIENT);
assertTrue(id instanceof UnknownId);
UnknownId uid = (UnknownId) id;
assertEquals("Does", uid.getIdTypeName());
Expand All @@ -613,7 +638,7 @@ public void testFromQualifiedLenient_WrongFormat() {

@Test
public void testFromQualifiedLenient_NoIdTypeName() {
IId id = getCodec().fromQualifiedLenient("Foo" + TEST_UUID);
IId id = getCodec().fromQualified("Foo" + TEST_UUID, IdCodecFlag.LENIENT);
assertTrue(id instanceof UnknownId);
UnknownId uid = (UnknownId) id;
assertNull(uid.getIdTypeName());
Expand All @@ -625,7 +650,7 @@ public void testFromQualifiedLenient_NoIdTypeName() {

@Test
public void testFromQualifiedLenient_CompositeWrongCardinalityToSmall() {
IId id = getCodec().fromQualifiedLenient("scout.FixtureCompositeId:" + TEST_UUID);
IId id = getCodec().fromQualified("scout.FixtureCompositeId:" + TEST_UUID, IdCodecFlag.LENIENT);
assertTrue(id instanceof UnknownId);
UnknownId uid = (UnknownId) id;
assertEquals("scout.FixtureCompositeId", uid.getIdTypeName());
Expand All @@ -637,7 +662,7 @@ public void testFromQualifiedLenient_CompositeWrongCardinalityToSmall() {

@Test
public void testFromQualifiedLenient_CompositeWrongCardinalityToHigh() {
IId id = getCodec().fromQualifiedLenient("scout.FixtureCompositeId:" + "a;b;c");
IId id = getCodec().fromQualified("scout.FixtureCompositeId:" + "a;b;c", IdCodecFlag.LENIENT);
assertTrue(id instanceof UnknownId);
UnknownId uid = (UnknownId) id;
assertEquals("scout.FixtureCompositeId", uid.getIdTypeName());
Expand All @@ -654,6 +679,89 @@ public void testRegisterTypeMapper() {
assertThrows(AssertionException.class, () -> getCodec().registerRawTypeMapper(String.class, x -> x, null));
}

@Test
public void testQualifiedSignature() {
var ids = new HashSet<IId>();
collectSignatureIds(ids);
ids.forEach(id -> {
String serialized = getCodec().toQualified(id, IdCodecFlag.SIGNATURE);
IId deserialized = getCodec().fromQualified(serialized, IdCodecFlag.SIGNATURE);
assertQualifiedSignature(id, serialized, deserialized);

serialized = getCodec().toQualified(id, Set.of(IdCodecFlag.SIGNATURE));
deserialized = getCodec().fromQualified(serialized, Set.of(IdCodecFlag.SIGNATURE));
assertQualifiedSignature(id, serialized, deserialized);
});
}

@Test
public void testUnqualifiedSignature() {
var ids = new HashSet<IId>();
collectSignatureIds(ids);
ids.forEach(id -> {
String serialized = getCodec().toUnqualified(id, IdCodecFlag.SIGNATURE);
IId deserialized = getCodec().fromUnqualified(id.getClass(), serialized, IdCodecFlag.SIGNATURE);
assertUnqualifiedSignature(id, serialized, deserialized);

serialized = getCodec().toUnqualified(id, Set.of(IdCodecFlag.SIGNATURE));
deserialized = getCodec().fromUnqualified(id.getClass(), serialized, Set.of(IdCodecFlag.SIGNATURE));
assertUnqualifiedSignature(id, serialized, deserialized);
});
}

protected void assertQualifiedSignature(IId id, String serialized, IId deserialized) {
assertSignature(id, serialized, deserialized);
}

protected void assertUnqualifiedSignature(IId id, String serialized, IId deserialized) {
assertSignature(id, serialized, deserialized);
}

protected void assertSignature(IId id, String serialized, IId deserialized) {
assertEquals(id, deserialized);
}

protected void collectSignatureIds(Set<IId> ids) {
ids.add(FixtureUuId.of(TEST_UUID));
ids.add(FixtureStringId.of(TEST_STRING));
ids.add(FixtureDateId.of(TEST_DATE));
ids.add(FixtureLocaleId.of(Locale.ITALY));
ids.add(FixtureCompositeId.of(TEST_STRING, TEST_UUID));
ids.add(FixtureWrapperCompositeId.of(TEST_STRING, TEST_UUID, TEST_STRING_2));
ids.add(FixtureCompositeWithNullValuesId.of(null, UUID.fromString("711dc5d6-0a42-4f54-b79c-50110b9e742a")));
ids.add(FixtureCompositeWithNullStringValuesId.of("foo", ""));
ids.add(FixtureCompositeWithNullStringValuesId.of("", "bar"));
ids.add(FixtureCompositeWithAllTypesId.of("foo", null, null, null, null, null));
ids.add(FixtureCompositeWithAllTypesId.of(null, TEST_UUID, null, null, null, null));
ids.add(FixtureCompositeWithAllTypesId.of(null, null, 42L, null, null, null));
ids.add(FixtureCompositeWithAllTypesId.of(null, null, null, 43, null, null));
ids.add(FixtureCompositeWithAllTypesId.of(null, null, null, null, TEST_DATE, null));
ids.add(FixtureCompositeWithAllTypesId.of(null, null, null, null, null, Locale.GERMANY));
}

@Test
public void testEmptyIdWithSignature() {
assertThrows(AssertionException.class, () -> getCodec().fromQualified("scout.FixtureIntegerId:###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE));
assertThrows(AssertionException.class, () -> getCodec().fromUnqualified(FixtureIntegerId.class, "###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE));
}

@Test
public void testSignatureIdWithoutPassword() {
BeanTestingHelper.get().unregisterBean(m_codecBean);

var stringId = FixtureStringId.of("some");
assertEquals("scout.FixtureStringId:some", getCodec().toQualified(stringId, IdCodecFlag.SIGNATURE));
assertEquals("some", getCodec().toUnqualified(stringId, IdCodecFlag.SIGNATURE));
assertEquals(stringId, getCodec().fromQualified("scout.FixtureStringId:some", IdCodecFlag.SIGNATURE));
assertEquals(stringId, getCodec().fromUnqualified(FixtureStringId.class, "some", IdCodecFlag.SIGNATURE));

var integerId = FixtureIntegerId.of(42);
assertThrows(AssertionException.class, () -> getCodec().toQualified(integerId, IdCodecFlag.SIGNATURE));
assertThrows(AssertionException.class, () -> getCodec().toUnqualified(integerId, IdCodecFlag.SIGNATURE));
assertThrows(AssertionException.class, () -> getCodec().fromQualified("scout.FixtureIntegerId:42###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE));
assertThrows(AssertionException.class, () -> getCodec().fromUnqualified(FixtureIntegerId.class, "42###CNCgkNhEN4PEpNkWvRPY/jEIwn49f1xGLgmXyi6SdlI=", IdCodecFlag.SIGNATURE));
}

@IdTypeName("scout.FixtureDateId")
protected static final class FixtureDateId extends AbstractRootId<Date> {
private static final long serialVersionUID = 1L;
Expand Down Expand Up @@ -812,4 +920,12 @@ public static FixtureCustomComparableRawDataId of(CustomComparableRawDataType da
return new FixtureCustomComparableRawDataId(date);
}
}

protected static class P_IdCodec extends IdCodec {

@Override
protected byte[] getIdSignaturePassword() {
return "42".getBytes(StandardCharsets.UTF_8);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,8 @@
*/
public class IdCodecTest extends AbstractIdCodecTest {

protected IdCodec m_idCodec;

public IdCodecTest() {
m_idCodec = BEANS.get(IdCodec.class);
}

@Override
protected IdCodec getCodec() {
return m_idCodec;
return BEANS.get(IdCodec.class);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
* Copyright (c) 2010, 2024 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -59,6 +59,19 @@ public void testRegisterIdTypeName() {
assertThrows(AssertionException.class, () -> m_inventory.registerIdTypeName("scout.FixtureMockId", FixtureMockId.class));
}

@Test
public void testIdSignature() {
assertTrue(m_inventory.isIdSignature(ExplicitlyOverriddenSignedId.class));
assertTrue(m_inventory.isIdSignature(ImplicitlyOverriddenSignedId.class));
assertTrue(m_inventory.isIdSignature(ExplicitlySignedId.class));
assertTrue(m_inventory.isIdSignature(ImplicitlySignedId.class));

assertFalse(m_inventory.isIdSignature(ImplicitlyUnsignedId.class));
assertFalse(m_inventory.isIdSignature(ExplicitlyUnsignedId.class));
assertFalse(m_inventory.isIdSignature(ImplicitlyOverriddenUnsignedId.class));
assertFalse(m_inventory.isIdSignature(ExplicitlyOverriddenUnsignedId.class));
}

@IgnoreBean
protected static final class FixtureMockId extends AbstractStringId {
private static final long serialVersionUID = 1L;
Expand All @@ -67,4 +80,116 @@ private FixtureMockId(String id) {
super(id);
}
}

@IdSignature
protected abstract static class AbstractImplicitlySignedId extends AbstractStringId {
private static final long serialVersionUID = 1L;

protected AbstractImplicitlySignedId(String id) {
super(id);
}
}

@IgnoreBean
protected static class ImplicitlySignedId extends AbstractImplicitlySignedId {
private static final long serialVersionUID = 1L;

protected ImplicitlySignedId(String id) {
super(id);
}
}

@IgnoreBean
@IdSignature
protected static class ExplicitlySignedId extends AbstractStringId {
private static final long serialVersionUID = 1L;

protected ExplicitlySignedId(String id) {
super(id);
}
}

@IdSignature(false)
protected abstract static class AbstractImplicitlyUnsignedId extends AbstractStringId {
private static final long serialVersionUID = 1L;

protected AbstractImplicitlyUnsignedId(String id) {
super(id);
}
}

@IgnoreBean
protected static class ImplicitlyUnsignedId extends AbstractImplicitlyUnsignedId {
private static final long serialVersionUID = 1L;

protected ImplicitlyUnsignedId(String id) {
super(id);
}
}

@IgnoreBean
@IdSignature(false)
protected static class ExplicitlyUnsignedId extends AbstractStringId {
private static final long serialVersionUID = 1L;

protected ExplicitlyUnsignedId(String id) {
super(id);
}
}

@IdSignature
protected abstract static class AbstractImplicitlyOverriddenSignedId extends AbstractImplicitlyUnsignedId {
private static final long serialVersionUID = 1L;

protected AbstractImplicitlyOverriddenSignedId(String id) {
super(id);
}
}

@IgnoreBean
protected static class ImplicitlyOverriddenSignedId extends AbstractImplicitlyOverriddenSignedId {
private static final long serialVersionUID = 1L;

protected ImplicitlyOverriddenSignedId(String id) {
super(id);
}
}

@IgnoreBean
@IdSignature
protected static class ExplicitlyOverriddenSignedId extends AbstractImplicitlyUnsignedId {
private static final long serialVersionUID = 1L;

protected ExplicitlyOverriddenSignedId(String id) {
super(id);
}
}

@IdSignature(false)
protected abstract static class AbstractImplicitlyOverriddenUnsignedId extends AbstractImplicitlySignedId {
private static final long serialVersionUID = 1L;

protected AbstractImplicitlyOverriddenUnsignedId(String id) {
super(id);
}
}

@IgnoreBean
protected static class ImplicitlyOverriddenUnsignedId extends AbstractImplicitlyOverriddenUnsignedId {
private static final long serialVersionUID = 1L;

protected ImplicitlyOverriddenUnsignedId(String id) {
super(id);
}
}

@IgnoreBean
@IdSignature(false)
protected static class ExplicitlyOverriddenUnsignedId extends AbstractImplicitlySignedId {
private static final long serialVersionUID = 1L;

protected ExplicitlyOverriddenUnsignedId(String id) {
super(id);
}
}
}

0 comments on commit 45e8dee

Please sign in to comment.