From 073f77e9fda20d304424f6e788def728a580b88c Mon Sep 17 00:00:00 2001 From: Linus Gasser Date: Fri, 28 Aug 2020 09:01:23 +0200 Subject: [PATCH] Linting all files --- .github/workflows/pre-commit.yaml | 17 + .pre-commit-config.yaml | 5 + GenerateKeyPair.java | 44 +- GenerateKeyPairEC.java | 82 +- .../backend/sdk/data/DPPPTDataService.java | 85 +- .../backend/sdk/data/ExposeeRowMapper.java | 19 +- .../sdk/data/JDBCDPPPTDataServiceImpl.java | 177 +- .../sdk/data/JDBCRedeemDataServiceImpl.java | 74 +- .../backend/sdk/data/RedeemDataService.java | 27 +- .../sdk/data/gaen/DebugGAENDataService.java | 33 +- .../gaen/DebugGaenKeyResultSetExtractor.java | 38 +- .../gaen/DebugJDBCGAENDataServiceImpl.java | 98 +- .../backend/sdk/data/gaen/FakeKeyService.java | 117 +- .../sdk/data/gaen/GAENDataService.java | 85 +- .../sdk/data/gaen/GaenKeyRowMapper.java | 24 +- .../data/gaen/JDBCGAENDataServiceImpl.java | 239 +- .../sdk/data/DPPPTDataServiceTest.java | 203 +- .../data/PostgresDPPPTDataServiceTest.java | 262 +- .../data/config/DPPPTDataServiceConfig.java | 76 +- .../backend/sdk/data/config/FlyWayConfig.java | 65 +- .../sdk/data/config/PostgresDataConfig.java | 38 +- .../data/config/RedeemDataServiceConfig.java | 17 +- .../sdk/data/config/StandaloneDataConfig.java | 23 +- .../backend/sdk/data/config/TestConfig.java | 17 +- .../sdk/data/gaen/GaenDataServiceTest.java | 74 +- .../gaen/PostgresGaenDataServiceTest.java | 435 +-- .../data/util/SingletonPostgresContainer.java | 117 +- .../dpppt/backend/sdk/model/Application.java | 115 +- .../backend/sdk/model/AuthDataMethod.java | 4 +- .../dpppt/backend/sdk/model/BucketList.java | 29 +- .../dpppt/backend/sdk/model/ExposedKey.java | 35 +- .../backend/sdk/model/ExposedOverview.java | 37 +- .../org/dpppt/backend/sdk/model/Exposee.java | 50 +- .../backend/sdk/model/ExposeeAuthData.java | 14 +- .../backend/sdk/model/ExposeeRequest.java | 61 +- .../backend/sdk/model/ExposeeRequestList.java | 33 +- .../backend/sdk/model/gaen/DayBuckets.java | 91 +- .../dpppt/backend/sdk/model/gaen/GaenKey.java | 162 +- .../backend/sdk/model/gaen/GaenRequest.java | 74 +- .../backend/sdk/model/gaen/GaenSecondDay.java | 19 +- .../backend/sdk/model/gaen/GaenUnit.java | 73 +- .../sdk/model/gaen/proto/FileProto.java | 1433 +++++---- .../proto/TemporaryExposureKeyFormat.java | 2775 +++++++++-------- .../sdk/model/keycloak/KeyCloakPublicKey.java | 103 +- .../backend/sdk/model/proto/Exposed.java | 879 +++--- .../org/dpppt/backend/sdk/semver/Version.java | 468 +-- .../dpppt/backend/sdk/utils/UTCInstant.java | 410 ++- .../org/dpppt/backend/sdk/ws/Application.java | 12 +- .../sdk/ws/config/ActuatorSecurity.java | 140 +- .../sdk/ws/config/MultipleJWTConfig.java | 283 +- .../sdk/ws/config/TestingCloudDevConfig.java | 78 +- .../backend/sdk/ws/config/WSBaseConfig.java | 576 ++-- .../sdk/ws/config/WSCloudAbnConfig.java | 51 +- .../sdk/ws/config/WSCloudBaseConfig.java | 92 +- .../sdk/ws/config/WSCloudDevConfig.java | 51 +- .../sdk/ws/config/WSCloudProdConfig.java | 51 +- .../sdk/ws/config/WSCloudTestConfig.java | 51 +- .../backend/sdk/ws/config/WSDevConfig.java | 108 +- .../backend/sdk/ws/config/WSProdConfig.java | 292 +- .../configbeans/ActuatorSecurityConfig.java | 26 +- .../sdk/ws/controller/DPPPTController.java | 493 +-- .../sdk/ws/controller/DebugController.java | 202 +- .../sdk/ws/controller/GaenController.java | 568 ++-- .../sdk/ws/filter/ResponseWrapperFilter.java | 109 +- .../sdk/ws/insertmanager/InsertException.java | 9 +- .../sdk/ws/insertmanager/InsertManager.java | 214 +- .../backend/sdk/ws/insertmanager/OSType.java | 23 +- .../insertionfilters/Base64Filter.java | 77 +- .../insertionfilters/KeyInsertionFilter.java | 49 +- .../KeysMatchingJWTFilter.java | 93 +- .../insertionfilters/NonFakeKeysFilter.java | 32 +- ...tartNumberAfterDayAfterTomorrowFilter.java | 43 +- ...ingStartNumberInRetentionPeriodFilter.java | 53 +- .../ValidRollingPeriodFilter.java | 33 +- .../IOSLegacyProblemRPLT144Modifier.java | 36 +- .../KeyInsertionModifier.java | 49 +- .../OldAndroid0RPModifier.java | 60 +- .../sdk/ws/interceptor/HeaderInjector.java | 31 +- .../sdk/ws/security/DPPTJwtDecoder.java | 86 +- .../sdk/ws/security/JWTClaimSetConverter.java | 26 +- .../sdk/ws/security/JWTValidateRequest.java | 122 +- .../backend/sdk/ws/security/JWTValidator.java | 48 +- .../backend/sdk/ws/security/KeyVault.java | 420 ++- .../sdk/ws/security/NoValidateRequest.java | 87 +- .../sdk/ws/security/ValidateRequest.java | 47 +- .../ws/security/gaen/JWTValidateRequest.java | 96 +- .../ws/security/signature/ProtoSignature.java | 443 +-- .../signature/SignatureResponseWrapper.java | 341 +- .../dpppt/backend/sdk/ws/util/KeyHelper.java | 23 +- .../backend/sdk/ws/util/ValidationUtils.java | 266 +- .../backend/sdk/ws/config/TestConfig.java | 17 +- .../BaseControllerNoSecurityTest.java | 66 +- .../sdk/ws/controller/BaseControllerTest.java | 252 +- .../ws/controller/CloudControllerTestPEM.java | 116 +- .../GaenControllerNoFilledZipsTest.java | 57 +- .../sdk/ws/controller/GaenControllerTest.java | 2501 ++++++++------- .../GaenControllerTestNotThreadSafe.java | 319 +- .../sdk/ws/controller/TestApplication.java | 4 +- .../ws/insertmanager/InsertManagerTest.java | 198 +- .../sdk/ws/insertmanager/MockDataSource.java | 49 +- .../backend/sdk/ws/security/KeyVaultTest.java | 110 +- .../SignatureResponseWrapperTest.java | 339 +- .../backend/sdk/ws/util/GaenUnitTest.java | 15 +- .../backend/sdk/ws/util/SemverTests.java | 213 +- .../backend/sdk/ws/util/TestJDBCGaen.java | 176 +- .../sdk/ws/util/ValidationUtilsTest.java | 33 +- 106 files changed, 10428 insertions(+), 9383 deletions(-) create mode 100644 .github/workflows/pre-commit.yaml create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 00000000..2a72cce0 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,17 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [develop] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - uses: actions/setup-java@v1 + with: + java-version: '11' + - uses: pre-commit/action@v2.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..533f3dc7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: +- repo: https://github.com/c4dt/google-style-precommit-hook + rev: v1.0 + hooks: + - id: google-style-java diff --git a/GenerateKeyPair.java b/GenerateKeyPair.java index d8334a82..9b918008 100644 --- a/GenerateKeyPair.java +++ b/GenerateKeyPair.java @@ -1,34 +1,30 @@ /** - * This file only serves as an example on how to get keys in the right encoding. - * This outputs the keys in the PKCS8 format for the private key and the X509 format for the publickey - * - * DO NOT USE THEM IN PRODUCTION UNLESS THE KEYSPECS ARE OK FOR YOU + * This file only serves as an example on how to get keys in the right encoding. This outputs the + * keys in the PKCS8 format for the private key and the X509 format for the publickey + * + *

DO NOT USE THEM IN PRODUCTION UNLESS THE KEYSPECS ARE OK FOR YOU */ import java.io.FileOutputStream; -import java.io.IOException; -import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.Security; import java.util.Base64; -import java.security.Security; +public class GenerateKeyPair { + public static void main(String[] args) throws Exception { + Security.setProperty("crypto.policy", "unlimited"); + KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); + KeyPair pair = generator.genKeyPair(); + PrivateKey privateKey = pair.getPrivate(); + PublicKey publicKey = pair.getPublic(); + FileOutputStream outputStream = new FileOutputStream("generated_pub.pem"); + outputStream.write(Base64.getEncoder().encode(publicKey.getEncoded())); + outputStream.close(); -public class GenerateKeyPair{ - public static void main(String[] args) throws Exception { - Security.setProperty("crypto.policy", "unlimited"); - KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); - KeyPair pair = generator.genKeyPair(); - PrivateKey privateKey = pair.getPrivate(); - PublicKey publicKey = pair.getPublic(); - FileOutputStream outputStream = new FileOutputStream("generated_pub.pem"); - outputStream.write(Base64.getEncoder().encode(publicKey.getEncoded())); - outputStream.close(); - - outputStream = new FileOutputStream("generated_private.pem"); - outputStream.write(Base64.getEncoder().encode(privateKey.getEncoded())); - outputStream.close(); - } -} \ No newline at end of file + outputStream = new FileOutputStream("generated_private.pem"); + outputStream.write(Base64.getEncoder().encode(privateKey.getEncoded())); + outputStream.close(); + } +} diff --git a/GenerateKeyPairEC.java b/GenerateKeyPairEC.java index 9d909a50..29c8f618 100644 --- a/GenerateKeyPairEC.java +++ b/GenerateKeyPairEC.java @@ -1,59 +1,51 @@ /** - * This file only serves as an example on how to get keys in the right encoding. - * In order to use it you need BouncyCastle on the classpath! - * - * DO NOT USE THEM IN PRODUCTION UNLESS THE KEYSPECS ARE OK FOR YOU + * This file only serves as an example on how to get keys in the right encoding. In order to use it + * you need BouncyCastle on the classpath! + * + *

DO NOT USE THEM IN PRODUCTION UNLESS THE KEYSPECS ARE OK FOR YOU */ import java.io.FileOutputStream; -import java.io.IOException; -import java.security.Key; +import java.io.StringWriter; import java.security.KeyPair; import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; -import java.util.Base64; -import java.security.spec.ECGenParameterSpec; -import java.io.StringWriter; - import java.security.Security; +import java.security.spec.ECGenParameterSpec; +import java.util.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.util.io.pem.PemWriter; import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemWriter; + +public class GenerateKeyPairEC { + public static void main(String[] args) throws Exception { + Security.addProvider(new BouncyCastleProvider()); + Security.setProperty("crypto.policy", "unlimited"); + KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "BC"); + ECGenParameterSpec spec = new ECGenParameterSpec("secp256r1"); + generator.initialize(spec); + KeyPair pair = generator.genKeyPair(); + PrivateKey privateKey = pair.getPrivate(); + PublicKey publicKey = pair.getPublic(); -public class GenerateKeyPairEC{ - public static void main(String[] args) throws Exception { - Security.addProvider(new BouncyCastleProvider()); - Security.setProperty("crypto.policy", "unlimited"); - KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", "BC"); - ECGenParameterSpec spec = new ECGenParameterSpec("secp256r1"); - generator.initialize(spec); - KeyPair pair = generator.genKeyPair(); - PrivateKey privateKey = pair.getPrivate(); - PublicKey publicKey = pair.getPublic(); + StringWriter privateKeyWriter = new StringWriter(); + PemWriter privateKeyPemWriter = new PemWriter(privateKeyWriter); + privateKeyPemWriter.writeObject(new PemObject("PRIVATE KEY", privateKey.getEncoded())); + privateKeyPemWriter.flush(); + privateKeyPemWriter.close(); - StringWriter privateKeyWriter = new StringWriter(); - PemWriter privateKeyPemWriter = new PemWriter(privateKeyWriter); - privateKeyPemWriter.writeObject(new PemObject("PRIVATE KEY", privateKey.getEncoded())); - privateKeyPemWriter.flush(); - privateKeyPemWriter.close(); + StringWriter publicKeyWriter = new StringWriter(); + PemWriter publicKeyPemWriter = new PemWriter(publicKeyWriter); + publicKeyPemWriter.writeObject(new PemObject("PUBLIC KEY", publicKey.getEncoded())); + publicKeyPemWriter.flush(); + publicKeyPemWriter.close(); - StringWriter publicKeyWriter = new StringWriter(); - PemWriter publicKeyPemWriter = new PemWriter(publicKeyWriter); - publicKeyPemWriter.writeObject(new PemObject("PUBLIC KEY", publicKey.getEncoded())); - publicKeyPemWriter.flush(); - publicKeyPemWriter.close(); + FileOutputStream outputStream = new FileOutputStream("generated_pub.pem"); + outputStream.write(Base64.getEncoder().encode(publicKeyWriter.toString().getBytes())); + outputStream.close(); - FileOutputStream outputStream = new FileOutputStream("generated_pub.pem"); - outputStream.write(Base64.getEncoder().encode( - publicKeyWriter.toString().getBytes() - )); - outputStream.close(); - - outputStream = new FileOutputStream("generated_private.pem"); - outputStream.write(Base64.getEncoder().encode( - privateKeyWriter.toString().getBytes() - )); - outputStream.close(); - } -} \ No newline at end of file + outputStream = new FileOutputStream("generated_private.pem"); + outputStream.write(Base64.getEncoder().encode(privateKeyWriter.toString().getBytes())); + outputStream.close(); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/DPPPTDataService.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/DPPPTDataService.java index 97708eb3..50da1ec8 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/DPPPTDataService.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/DPPPTDataService.java @@ -12,50 +12,51 @@ import java.time.Duration; import java.util.List; - import org.dpppt.backend.sdk.model.Exposee; public interface DPPPTDataService { - /** - * Upserts (Update or Inserts) the given exposee - * - * @param exposee the exposee to upsert - * @param appSource the app name - */ - void upsertExposee(Exposee exposee, String appSource); - - /** - * Upserts (Update or Inserts) the given exposees (if keys cannot be derived from one master key) - * - * @param exposees the list of exposees to upsert - * @param appSource the app name - */ - void upsertExposees(List exposees, String appSource); - - /** - * Returns the maximum id of the stored exposed entries fo the given batch. - * - * @param batchReleaseTime in milliseconds since the start of the Unix Epoch, must be a multiple of - * @param releaseBucketDuration in milliseconds - * @return the maximum id of the stored exposed entries fo the given batch - */ - int getMaxExposedIdForBatchReleaseTime(long batchReleaseTime, long releaseBucketDuration); - - /** - * Returns all exposees for the given batch. - * - * @param batchReleaseTime in milliseconds since the start of the Unix Epoch, must be a multiple of - * @param releaseBucketDuration in milliseconds - * @return all exposees for the given batch - */ - List getSortedExposedForBatchReleaseTime(long batchReleaseTime, long releaseBucketDuration); - - /** - * deletes entries older than retentionperiod - * - * @param retentionPeriod duration of retention period for exposed keys - */ - void cleanDB(Duration retentionPeriod); - + /** + * Upserts (Update or Inserts) the given exposee + * + * @param exposee the exposee to upsert + * @param appSource the app name + */ + void upsertExposee(Exposee exposee, String appSource); + + /** + * Upserts (Update or Inserts) the given exposees (if keys cannot be derived from one master key) + * + * @param exposees the list of exposees to upsert + * @param appSource the app name + */ + void upsertExposees(List exposees, String appSource); + + /** + * Returns the maximum id of the stored exposed entries fo the given batch. + * + * @param batchReleaseTime in milliseconds since the start of the Unix Epoch, must be a multiple + * of + * @param releaseBucketDuration in milliseconds + * @return the maximum id of the stored exposed entries fo the given batch + */ + int getMaxExposedIdForBatchReleaseTime(long batchReleaseTime, long releaseBucketDuration); + + /** + * Returns all exposees for the given batch. + * + * @param batchReleaseTime in milliseconds since the start of the Unix Epoch, must be a multiple + * of + * @param releaseBucketDuration in milliseconds + * @return all exposees for the given batch + */ + List getSortedExposedForBatchReleaseTime( + long batchReleaseTime, long releaseBucketDuration); + + /** + * deletes entries older than retentionperiod + * + * @param retentionPeriod duration of retention period for exposed keys + */ + void cleanDB(Duration retentionPeriod); } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/ExposeeRowMapper.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/ExposeeRowMapper.java index 05a6feab..90ee5234 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/ExposeeRowMapper.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/ExposeeRowMapper.java @@ -12,17 +12,16 @@ import java.sql.ResultSet; import java.sql.SQLException; - import org.dpppt.backend.sdk.model.Exposee; import org.springframework.jdbc.core.RowMapper; public class ExposeeRowMapper implements RowMapper { - @Override - public Exposee mapRow(ResultSet rs, int rowNum) throws SQLException { - Exposee exposee = new Exposee(); - exposee.setKey(rs.getString("key")); - exposee.setId(rs.getInt("pk_exposed_id")); - exposee.setKeyDate(rs.getTimestamp("key_date").getTime()); - return exposee; - } -} \ No newline at end of file + @Override + public Exposee mapRow(ResultSet rs, int rowNum) throws SQLException { + Exposee exposee = new Exposee(); + exposee.setKey(rs.getString("key")); + exposee.setId(rs.getInt("pk_exposed_id")); + exposee.setKeyDate(rs.getTimestamp("key_date").getTime()); + return exposee; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCDPPPTDataServiceImpl.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCDPPPTDataServiceImpl.java index cb8b7533..85926662 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCDPPPTDataServiceImpl.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCDPPPTDataServiceImpl.java @@ -13,9 +13,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.model.Exposee; import org.dpppt.backend.sdk.utils.UTCInstant; import org.slf4j.Logger; @@ -26,89 +24,104 @@ public class JDBCDPPPTDataServiceImpl implements DPPPTDataService { - private static final Logger logger = LoggerFactory.getLogger(JDBCDPPPTDataServiceImpl.class); - private static final String PGSQL = "pgsql"; - private final String dbType; - private final NamedParameterJdbcTemplate jt; + private static final Logger logger = LoggerFactory.getLogger(JDBCDPPPTDataServiceImpl.class); + private static final String PGSQL = "pgsql"; + private final String dbType; + private final NamedParameterJdbcTemplate jt; + + public JDBCDPPPTDataServiceImpl(String dbType, DataSource dataSource) { + this.dbType = dbType; + this.jt = new NamedParameterJdbcTemplate(dataSource); + } - public JDBCDPPPTDataServiceImpl(String dbType, DataSource dataSource) { - this.dbType = dbType; - this.jt = new NamedParameterJdbcTemplate(dataSource); - } + @Override + @Transactional(readOnly = false) + public void upsertExposee(Exposee exposee, String appSource) { + String sql = null; + if (dbType.equals(PGSQL)) { + sql = + "insert into t_exposed (key, key_date, app_source) values (:key, :key_date, :app_source)" + + " on conflict on constraint key do nothing"; + } else { + sql = + "merge into t_exposed using (values(cast(:key as varchar(10000)), cast(:key_date as" + + " date), cast(:app_source as varchar(50)))) as vals(key, key_date, app_source) on" + + " t_exposed.key = vals.key when not matched then insert (key, key_date," + + " app_source) values (vals.key, vals.key_date, vals.app_source)"; + } + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("key", exposee.getKey()); + params.addValue("app_source", appSource); + params.addValue("key_date", UTCInstant.ofEpochMillis(exposee.getKeyDate()).getDate()); + jt.update(sql, params); + } - @Override - @Transactional(readOnly = false) - public void upsertExposee(Exposee exposee, String appSource) { - String sql = null; - if (dbType.equals(PGSQL)) { - sql = "insert into t_exposed (key, key_date, app_source) values (:key, :key_date, :app_source)" - + " on conflict on constraint key do nothing"; - } else { - sql = "merge into t_exposed using (values(cast(:key as varchar(10000)), cast(:key_date as date), cast(:app_source as varchar(50))))" - + " as vals(key, key_date, app_source) on t_exposed.key = vals.key" - + " when not matched then insert (key, key_date, app_source) values (vals.key, vals.key_date, vals.app_source)"; - } - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("key", exposee.getKey()); - params.addValue("app_source", appSource); - params.addValue("key_date", UTCInstant.ofEpochMillis(exposee.getKeyDate()).getDate()); - jt.update(sql, params); - } - @Override - @Transactional(readOnly = false) - public void upsertExposees(List exposees, String appSource) { - String sql = null; - if (dbType.equals(PGSQL)) { - sql = "insert into t_exposed (key, key_date, app_source) values (:key, :key_date, :app_source)" - + " on conflict on constraint key do nothing"; - } else { - sql = "merge into t_exposed using (values(cast(:key as varchar(10000)), cast(:key_date as date), cast(:app_source as varchar(50))))" - + " as vals(key, key_date, app_source) on t_exposed.key = vals.key" - + " when not matched then insert (key, key_date, app_source) values (vals.key, vals.key_date, vals.app_source)"; - } - var parameterList = new ArrayList(); - for(var exposee : exposees) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("key", exposee.getKey()); - params.addValue("app_source", appSource); - params.addValue("key_date", UTCInstant.ofEpochMillis(exposee.getKeyDate()).getDate()); - parameterList.add(params); - } - jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); - } + @Override + @Transactional(readOnly = false) + public void upsertExposees(List exposees, String appSource) { + String sql = null; + if (dbType.equals(PGSQL)) { + sql = + "insert into t_exposed (key, key_date, app_source) values (:key, :key_date, :app_source)" + + " on conflict on constraint key do nothing"; + } else { + sql = + "merge into t_exposed using (values(cast(:key as varchar(10000)), cast(:key_date as" + + " date), cast(:app_source as varchar(50)))) as vals(key, key_date, app_source) on" + + " t_exposed.key = vals.key when not matched then insert (key, key_date," + + " app_source) values (vals.key, vals.key_date, vals.app_source)"; + } + var parameterList = new ArrayList(); + for (var exposee : exposees) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("key", exposee.getKey()); + params.addValue("app_source", appSource); + params.addValue("key_date", UTCInstant.ofEpochMillis(exposee.getKeyDate()).getDate()); + parameterList.add(params); + } + jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); + } - @Override - @Transactional(readOnly = true) - public int getMaxExposedIdForBatchReleaseTime(long batchReleaseTime, long releaseBucketDuration) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("batchReleaseTime", UTCInstant.ofEpochMillis(batchReleaseTime).getDate()); - params.addValue("startBatch", UTCInstant.ofEpochMillis(batchReleaseTime - releaseBucketDuration).getDate()); - String sql = "select max(pk_exposed_id) from t_exposed where received_at >= :startBatch and received_at < :batchReleaseTime"; - Integer maxId = jt.queryForObject(sql, params, Integer.class); - if (maxId == null) { - return 0; - } else { - return maxId; - } - } + @Override + @Transactional(readOnly = true) + public int getMaxExposedIdForBatchReleaseTime(long batchReleaseTime, long releaseBucketDuration) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("batchReleaseTime", UTCInstant.ofEpochMillis(batchReleaseTime).getDate()); + params.addValue( + "startBatch", UTCInstant.ofEpochMillis(batchReleaseTime - releaseBucketDuration).getDate()); + String sql = + "select max(pk_exposed_id) from t_exposed where received_at >= :startBatch and received_at" + + " < :batchReleaseTime"; + Integer maxId = jt.queryForObject(sql, params, Integer.class); + if (maxId == null) { + return 0; + } else { + return maxId; + } + } - @Override - @Transactional(readOnly = true) - public List getSortedExposedForBatchReleaseTime(long batchReleaseTime, long releaseBucketDuration) { - String sql = "select pk_exposed_id, key, key_date from t_exposed where received_at >= :startBatch and received_at < :batchReleaseTime order by pk_exposed_id desc"; - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("batchReleaseTime", UTCInstant.ofEpochMillis(batchReleaseTime).getDate()); - params.addValue("startBatch", UTCInstant.ofEpochMillis(batchReleaseTime - releaseBucketDuration).getDate()); - return jt.query(sql, params, new ExposeeRowMapper()); - } + @Override + @Transactional(readOnly = true) + public List getSortedExposedForBatchReleaseTime( + long batchReleaseTime, long releaseBucketDuration) { + String sql = + "select pk_exposed_id, key, key_date from t_exposed where received_at >= :startBatch and" + + " received_at < :batchReleaseTime order by pk_exposed_id desc"; + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("batchReleaseTime", UTCInstant.ofEpochMillis(batchReleaseTime).getDate()); + params.addValue( + "startBatch", UTCInstant.ofEpochMillis(batchReleaseTime - releaseBucketDuration).getDate()); + return jt.query(sql, params, new ExposeeRowMapper()); + } - @Override - @Transactional(readOnly = false) - public void cleanDB(Duration retentionPeriod) { - var retentionTime = UTCInstant.now().minus(retentionPeriod); - logger.info("Cleanup DB entries before: " + retentionTime); - MapSqlParameterSource params = new MapSqlParameterSource("retention_time", retentionTime.getDate()); - String sqlExposed = "delete from t_exposed where received_at < :retention_time"; - jt.update(sqlExposed, params); - } + @Override + @Transactional(readOnly = false) + public void cleanDB(Duration retentionPeriod) { + var retentionTime = UTCInstant.now().minus(retentionPeriod); + logger.info("Cleanup DB entries before: " + retentionTime); + MapSqlParameterSource params = + new MapSqlParameterSource("retention_time", retentionTime.getDate()); + String sqlExposed = "delete from t_exposed where received_at < :retention_time"; + jt.update(sqlExposed, params); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCRedeemDataServiceImpl.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCRedeemDataServiceImpl.java index 3b95311b..1bd7bfd9 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCRedeemDataServiceImpl.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/JDBCRedeemDataServiceImpl.java @@ -12,7 +12,6 @@ import java.time.Duration; import javax.sql.DataSource; - import org.dpppt.backend.sdk.utils.UTCInstant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,43 +22,46 @@ public class JDBCRedeemDataServiceImpl implements RedeemDataService { - private static final Logger logger = LoggerFactory.getLogger(JDBCRedeemDataServiceImpl.class); + private static final Logger logger = LoggerFactory.getLogger(JDBCRedeemDataServiceImpl.class); - private final NamedParameterJdbcTemplate jt; - private final SimpleJdbcInsert reedemUUIDInsert; + private final NamedParameterJdbcTemplate jt; + private final SimpleJdbcInsert reedemUUIDInsert; - public JDBCRedeemDataServiceImpl(DataSource dataSource) { - this.jt = new NamedParameterJdbcTemplate(dataSource); - this.reedemUUIDInsert = new SimpleJdbcInsert(dataSource).withTableName("t_redeem_uuid") - .usingGeneratedKeyColumns("pk_redeem_uuid_id"); - } + public JDBCRedeemDataServiceImpl(DataSource dataSource) { + this.jt = new NamedParameterJdbcTemplate(dataSource); + this.reedemUUIDInsert = + new SimpleJdbcInsert(dataSource) + .withTableName("t_redeem_uuid") + .usingGeneratedKeyColumns("pk_redeem_uuid_id"); + } - @Override - @Transactional(readOnly = false) - public boolean checkAndInsertPublishUUID(String uuid) { - String sql = "select count(1) from t_redeem_uuid where uuid = :uuid"; - MapSqlParameterSource params = new MapSqlParameterSource("uuid", uuid); - Integer count = jt.queryForObject(sql, params, Integer.class); - if (count > 0) { - return false; - } else { - // set the received_at to the next day, with no time information - // it will stay longer in the DB but we mitigate the risk that the JWT - // can be used twice (c.f. testTokensArentDeletedBeforeExpire). - var startOfTomorrow = UTCInstant.today().plusDays(1); - params.addValue("received_at", startOfTomorrow.getDate()); - reedemUUIDInsert.execute(params); - return true; - } - } + @Override + @Transactional(readOnly = false) + public boolean checkAndInsertPublishUUID(String uuid) { + String sql = "select count(1) from t_redeem_uuid where uuid = :uuid"; + MapSqlParameterSource params = new MapSqlParameterSource("uuid", uuid); + Integer count = jt.queryForObject(sql, params, Integer.class); + if (count > 0) { + return false; + } else { + // set the received_at to the next day, with no time information + // it will stay longer in the DB but we mitigate the risk that the JWT + // can be used twice (c.f. testTokensArentDeletedBeforeExpire). + var startOfTomorrow = UTCInstant.today().plusDays(1); + params.addValue("received_at", startOfTomorrow.getDate()); + reedemUUIDInsert.execute(params); + return true; + } + } - @Override - @Transactional(readOnly = false) - public void cleanDB(Duration retentionPeriod) { - var retentionTime = UTCInstant.now().minus(retentionPeriod); - logger.info("Cleanup DB entries before: " + retentionTime); - MapSqlParameterSource params = new MapSqlParameterSource("retention_time", retentionTime.getDate()); - String sqlRedeem = "delete from t_redeem_uuid where received_at < :retention_time"; - jt.update(sqlRedeem, params); - } + @Override + @Transactional(readOnly = false) + public void cleanDB(Duration retentionPeriod) { + var retentionTime = UTCInstant.now().minus(retentionPeriod); + logger.info("Cleanup DB entries before: " + retentionTime); + MapSqlParameterSource params = + new MapSqlParameterSource("retention_time", retentionTime.getDate()); + String sqlRedeem = "delete from t_redeem_uuid where received_at < :retention_time"; + jt.update(sqlRedeem, params); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/RedeemDataService.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/RedeemDataService.java index ce283e34..5823ed82 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/RedeemDataService.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/RedeemDataService.java @@ -14,19 +14,18 @@ public interface RedeemDataService { - /** - * Checks and inserts a publish uuid. - * - * @param uuid - * @return return true if the uuid has been inserted. if the uuid is not valid, - * returns false. - */ - boolean checkAndInsertPublishUUID(String uuid); + /** + * Checks and inserts a publish uuid. + * + * @param uuid + * @return return true if the uuid has been inserted. if the uuid is not valid, returns false. + */ + boolean checkAndInsertPublishUUID(String uuid); - /** - * Clean up db and remove entries older than the retention days. - * - * @param retentionPeriod - */ - void cleanDB(Duration retentionPeriod); + /** + * Clean up db and remove entries older than the retention days. + * + * @param retentionPeriod + */ + void cleanDB(Duration retentionPeriod); } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGAENDataService.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGAENDataService.java index 046f54af..b1f0ef3a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGAENDataService.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGAENDataService.java @@ -12,26 +12,25 @@ import java.util.List; import java.util.Map; - import org.dpppt.backend.sdk.model.gaen.GaenKey; public interface DebugGAENDataService { - /** - * Upserts (Update or Inserts) the given list of exposed keys in the debug store - * - * @param deviceName name of the device - * @param keys the list of exposed keys to upsert - */ - void upsertExposees(String deviceName, List keys); - - /** - * Returns all exposed keys for the given batch from the debug store. - * - * @param batchReleaseTime in milliseconds since the beginning of the Unix epoch (1970-01-01) - * @param releaseBucketDuration in milliseconds - * @return all exposed keys for the given batch from the debug store - */ - Map> getSortedExposedForBatchReleaseTime(Long batchReleaseTime, long releaseBucketDuration); + /** + * Upserts (Update or Inserts) the given list of exposed keys in the debug store + * + * @param deviceName name of the device + * @param keys the list of exposed keys to upsert + */ + void upsertExposees(String deviceName, List keys); + /** + * Returns all exposed keys for the given batch from the debug store. + * + * @param batchReleaseTime in milliseconds since the beginning of the Unix epoch (1970-01-01) + * @param releaseBucketDuration in milliseconds + * @return all exposed keys for the given batch from the debug store + */ + Map> getSortedExposedForBatchReleaseTime( + Long batchReleaseTime, long releaseBucketDuration); } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGaenKeyResultSetExtractor.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGaenKeyResultSetExtractor.java index 92ff1bfa..df1b5f69 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGaenKeyResultSetExtractor.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugGaenKeyResultSetExtractor.java @@ -6,28 +6,28 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; -public class DebugGaenKeyResultSetExtractor implements ResultSetExtractor>> { - - @Override - public Map> extractData(ResultSet rs) throws SQLException, DataAccessException { - Map> result = new HashMap>(); - GaenKeyRowMapper gaenKeyRowMapper = new GaenKeyRowMapper(); - while (rs.next()) { - String deviceName = rs.getString("device_name"); - List keysForDevice = result.get(deviceName); - if (keysForDevice == null) { - keysForDevice = new ArrayList<>(); - result.put(deviceName, keysForDevice); - } - GaenKey gaenKey = gaenKeyRowMapper.mapRow(rs, rs.getRow()); - keysForDevice.add(gaenKey); - } - return result; - } +public class DebugGaenKeyResultSetExtractor + implements ResultSetExtractor>> { + @Override + public Map> extractData(ResultSet rs) + throws SQLException, DataAccessException { + Map> result = new HashMap>(); + GaenKeyRowMapper gaenKeyRowMapper = new GaenKeyRowMapper(); + while (rs.next()) { + String deviceName = rs.getString("device_name"); + List keysForDevice = result.get(deviceName); + if (keysForDevice == null) { + keysForDevice = new ArrayList<>(); + result.put(deviceName, keysForDevice); + } + GaenKey gaenKey = gaenKeyRowMapper.mapRow(rs, rs.getRow()); + keysForDevice.add(gaenKey); + } + return result; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugJDBCGAENDataServiceImpl.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugJDBCGAENDataServiceImpl.java index b2b8653a..344fd881 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugJDBCGAENDataServiceImpl.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/DebugJDBCGAENDataServiceImpl.java @@ -13,9 +13,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.utils.UTCInstant; import org.slf4j.Logger; @@ -26,50 +24,62 @@ public class DebugJDBCGAENDataServiceImpl implements DebugGAENDataService { - private static final Logger logger = LoggerFactory.getLogger(DebugJDBCGAENDataServiceImpl.class); - - private static final String PGSQL = "pgsql"; - private final String dbType; - private final NamedParameterJdbcTemplate jt; + private static final Logger logger = LoggerFactory.getLogger(DebugJDBCGAENDataServiceImpl.class); - public DebugJDBCGAENDataServiceImpl(String dbType, DataSource dataSource) { - this.dbType = dbType; - this.jt = new NamedParameterJdbcTemplate(dataSource); - } + private static final String PGSQL = "pgsql"; + private final String dbType; + private final NamedParameterJdbcTemplate jt; - @Override - @Transactional(readOnly = false) - public void upsertExposees(String deviceName, List gaenKeys) { - String sql = null; - if (dbType.equals(PGSQL)) { - sql = "insert into t_debug_gaen_exposed (device_name, key, rolling_start_number, rolling_period, transmission_risk_level) values (:device_name, :key, :rolling_start_number, :rolling_period, :transmission_risk_level)" - + " on conflict on constraint debug_gaen_exposed_key do nothing"; - } else { - sql = "merge into t_debug_gaen_exposed using (values(cast(:device_name as varchar(200)), cast(:key as varchar(24)), :rolling_start_number, :rolling_period, :transmission_risk_level))" - + " as vals(device_name, key, rolling_start_number, rolling_period, transmission_risk_level) on t_gaen_exposed.key = vals.key" - + " when not matched then insert (device_name, key, rolling_start_number, rolling_period, transmission_risk_level) values (vals.device_name, vals.key, vals.rolling_start_number, vals.rolling_period, transmission_risk_level)"; - } - var parameterList = new ArrayList(); - for (var gaenKey : gaenKeys) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("device_name", deviceName); - params.addValue("key", gaenKey.getKeyData()); - params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); - params.addValue("rolling_period", gaenKey.getRollingPeriod()); - params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); - parameterList.add(params); - } - jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); - } + public DebugJDBCGAENDataServiceImpl(String dbType, DataSource dataSource) { + this.dbType = dbType; + this.jt = new NamedParameterJdbcTemplate(dataSource); + } - @Override - @Transactional(readOnly = true) - public Map> getSortedExposedForBatchReleaseTime(Long batchReleaseTime, long releaseBucketDuration) { - String sql = "select pk_exposed_id, device_name, key, rolling_start_number, rolling_period, transmission_risk_level from t_debug_gaen_exposed where received_at >= :startBatch and received_at < :batchReleaseTime order by pk_exposed_id desc"; - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("batchReleaseTime", UTCInstant.ofEpochMillis(batchReleaseTime).getDate()); - params.addValue("startBatch", UTCInstant.ofEpochMillis(batchReleaseTime - releaseBucketDuration).getDate()); - return jt.query(sql, params, new DebugGaenKeyResultSetExtractor()); - } + @Override + @Transactional(readOnly = false) + public void upsertExposees(String deviceName, List gaenKeys) { + String sql = null; + if (dbType.equals(PGSQL)) { + sql = + "insert into t_debug_gaen_exposed (device_name, key, rolling_start_number," + + " rolling_period, transmission_risk_level) values (:device_name, :key," + + " :rolling_start_number, :rolling_period, :transmission_risk_level) on conflict on" + + " constraint debug_gaen_exposed_key do nothing"; + } else { + sql = + "merge into t_debug_gaen_exposed using (values(cast(:device_name as varchar(200))," + + " cast(:key as varchar(24)), :rolling_start_number, :rolling_period," + + " :transmission_risk_level)) as vals(device_name, key, rolling_start_number," + + " rolling_period, transmission_risk_level) on t_gaen_exposed.key = vals.key when" + + " not matched then insert (device_name, key, rolling_start_number, rolling_period," + + " transmission_risk_level) values (vals.device_name, vals.key," + + " vals.rolling_start_number, vals.rolling_period, transmission_risk_level)"; + } + var parameterList = new ArrayList(); + for (var gaenKey : gaenKeys) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("device_name", deviceName); + params.addValue("key", gaenKey.getKeyData()); + params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); + params.addValue("rolling_period", gaenKey.getRollingPeriod()); + params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); + parameterList.add(params); + } + jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); + } + @Override + @Transactional(readOnly = true) + public Map> getSortedExposedForBatchReleaseTime( + Long batchReleaseTime, long releaseBucketDuration) { + String sql = + "select pk_exposed_id, device_name, key, rolling_start_number, rolling_period," + + " transmission_risk_level from t_debug_gaen_exposed where received_at >= :startBatch" + + " and received_at < :batchReleaseTime order by pk_exposed_id desc"; + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("batchReleaseTime", UTCInstant.ofEpochMillis(batchReleaseTime).getDate()); + params.addValue( + "startBatch", UTCInstant.ofEpochMillis(batchReleaseTime - releaseBucketDuration).getDate()); + return jt.query(sql, params, new DebugGaenKeyResultSetExtractor()); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/FakeKeyService.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/FakeKeyService.java index 4ef86ec9..cf79e266 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/FakeKeyService.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/FakeKeyService.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.Base64; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.utils.UTCInstant; import org.slf4j.Logger; @@ -14,64 +13,70 @@ public class FakeKeyService { - private final GAENDataService dataService; - private final Integer minNumOfKeys; - private final SecureRandom random; - private final Integer keySize; - private final Duration retentionPeriod; - private final boolean isEnabled; + private final GAENDataService dataService; + private final Integer minNumOfKeys; + private final SecureRandom random; + private final Integer keySize; + private final Duration retentionPeriod; + private final boolean isEnabled; - private static final Logger logger = LoggerFactory.getLogger(FakeKeyService.class); + private static final Logger logger = LoggerFactory.getLogger(FakeKeyService.class); - public FakeKeyService(GAENDataService dataService, Integer minNumOfKeys, Integer keySize, Duration retentionPeriod, - boolean isEnabled) throws NoSuchAlgorithmException { - this.dataService = dataService; - this.minNumOfKeys = minNumOfKeys; - this.random = new SecureRandom(); - this.keySize = keySize; - this.retentionPeriod = retentionPeriod; - this.isEnabled = isEnabled; - this.updateFakeKeys(); - } + public FakeKeyService( + GAENDataService dataService, + Integer minNumOfKeys, + Integer keySize, + Duration retentionPeriod, + boolean isEnabled) + throws NoSuchAlgorithmException { + this.dataService = dataService; + this.minNumOfKeys = minNumOfKeys; + this.random = new SecureRandom(); + this.keySize = keySize; + this.retentionPeriod = retentionPeriod; + this.isEnabled = isEnabled; + this.updateFakeKeys(); + } - public void updateFakeKeys() { - deleteAllKeys(); - var currentKeyDate = UTCInstant.now(); - var tmpDate = currentKeyDate.minusDays(retentionPeriod.toDays()); - logger.debug("Fill Fake keys. Start: " + currentKeyDate + " End: " + tmpDate); - do { - var keys = new ArrayList(); - for (int i = 0; i < minNumOfKeys; i++) { - byte[] keyData = new byte[keySize]; - random.nextBytes(keyData); - var keyGAENTime = (int) tmpDate.get10MinutesSince1970(); - var key = new GaenKey(Base64.getEncoder().encodeToString(keyData), keyGAENTime, 144, 0); - keys.add(key); - } - //TODO: Check if currentKeyDate is indeed intended here - this.dataService.upsertExposees(keys, currentKeyDate); - tmpDate = tmpDate.plusDays(1); - } while (tmpDate.isBeforeDateOf(currentKeyDate)); - } + public void updateFakeKeys() { + deleteAllKeys(); + var currentKeyDate = UTCInstant.now(); + var tmpDate = currentKeyDate.minusDays(retentionPeriod.toDays()); + logger.debug("Fill Fake keys. Start: " + currentKeyDate + " End: " + tmpDate); + do { + var keys = new ArrayList(); + for (int i = 0; i < minNumOfKeys; i++) { + byte[] keyData = new byte[keySize]; + random.nextBytes(keyData); + var keyGAENTime = (int) tmpDate.get10MinutesSince1970(); + var key = new GaenKey(Base64.getEncoder().encodeToString(keyData), keyGAENTime, 144, 0); + keys.add(key); + } + // TODO: Check if currentKeyDate is indeed intended here + this.dataService.upsertExposees(keys, currentKeyDate); + tmpDate = tmpDate.plusDays(1); + } while (tmpDate.isBeforeDateOf(currentKeyDate)); + } - private void deleteAllKeys() { - logger.debug("Delete all fake keys"); - this.dataService.cleanDB(Duration.ofDays(0)); - } + private void deleteAllKeys() { + logger.debug("Delete all fake keys"); + this.dataService.cleanDB(Duration.ofDays(0)); + } - public List fillUpKeys(List keys, Long publishedafter, Long keyDate) { - if (!isEnabled) { - return keys; - } - var today = UTCInstant.today(); - var keyLocalDate = UTCInstant.ofEpochMillis(keyDate).atStartOfDay(); - if (today.hasSameDateAs(keyLocalDate)) { - return keys; - } - var fakeKeys = this.dataService.getSortedExposedForKeyDate(keyDate, publishedafter, - UTCInstant.today().plusDays(1).getTimestamp()); + public List fillUpKeys(List keys, Long publishedafter, Long keyDate) { + if (!isEnabled) { + return keys; + } + var today = UTCInstant.today(); + var keyLocalDate = UTCInstant.ofEpochMillis(keyDate).atStartOfDay(); + if (today.hasSameDateAs(keyLocalDate)) { + return keys; + } + var fakeKeys = + this.dataService.getSortedExposedForKeyDate( + keyDate, publishedafter, UTCInstant.today().plusDays(1).getTimestamp()); - keys.addAll(fakeKeys); - return keys; - } -} \ No newline at end of file + keys.addAll(fakeKeys); + return keys; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GAENDataService.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GAENDataService.java index fa734fe1..939d9829 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GAENDataService.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GAENDataService.java @@ -12,51 +12,52 @@ import java.time.Duration; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.utils.UTCInstant; public interface GAENDataService { - /** - * Upserts (Update or Inserts) the given list of exposed keys - * - * @param keys the list of exposed keys to upsert - */ - void upsertExposees(List keys, UTCInstant now); - - /** - * Upserts (Update or Inserts) the given list of exposed keys, with delayed release of same day TEKs - * - * @param keys the list of exposed keys to upsert - * @param delayedReceivedAt the timestamp to use for the delayed release (if null use now rounded to next bucket) - */ - void upsertExposeesDelayed(List keys, UTCInstant delayedReceivedAt, UTCInstant now); - - /** - * Returns the maximum id of the stored exposed entries for the given batch. - * - * @param keyDate in milliseconds since Unix epoch (1970-01-01) - * @param publishedAfter in milliseconds since Unix epoch - * @param publishedUntil in milliseconds since Unix epoch - * @return the maximum id of the stored exposed entries for the given batch - */ - int getMaxExposedIdForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil); - - /** - * Returns all exposeed keys for the given batch. - * - * @param keyDate in milliseconds since Unix epoch (1970-01-01) - * @param publishedAfter in milliseconds since Unix epoch - * @param publishedUntil in milliseconds since Unix epoch - * @return all exposeed keys for the given batch - */ - List getSortedExposedForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil); - - /** - * deletes entries older than retentionperiod - * - * @param retentionPeriod in milliseconds - */ - void cleanDB(Duration retentionPeriod); + /** + * Upserts (Update or Inserts) the given list of exposed keys + * + * @param keys the list of exposed keys to upsert + */ + void upsertExposees(List keys, UTCInstant now); + + /** + * Upserts (Update or Inserts) the given list of exposed keys, with delayed release of same day + * TEKs + * + * @param keys the list of exposed keys to upsert + * @param delayedReceivedAt the timestamp to use for the delayed release (if null use now rounded + * to next bucket) + */ + void upsertExposeesDelayed(List keys, UTCInstant delayedReceivedAt, UTCInstant now); + + /** + * Returns the maximum id of the stored exposed entries for the given batch. + * + * @param keyDate in milliseconds since Unix epoch (1970-01-01) + * @param publishedAfter in milliseconds since Unix epoch + * @param publishedUntil in milliseconds since Unix epoch + * @return the maximum id of the stored exposed entries for the given batch + */ + int getMaxExposedIdForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil); + + /** + * Returns all exposeed keys for the given batch. + * + * @param keyDate in milliseconds since Unix epoch (1970-01-01) + * @param publishedAfter in milliseconds since Unix epoch + * @param publishedUntil in milliseconds since Unix epoch + * @return all exposeed keys for the given batch + */ + List getSortedExposedForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil); + + /** + * deletes entries older than retentionperiod + * + * @param retentionPeriod in milliseconds + */ + void cleanDB(Duration retentionPeriod); } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GaenKeyRowMapper.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GaenKeyRowMapper.java index 404b71df..ae9c01c4 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GaenKeyRowMapper.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/GaenKeyRowMapper.java @@ -2,20 +2,18 @@ import java.sql.ResultSet; import java.sql.SQLException; - -import org.springframework.jdbc.core.RowMapper; import org.dpppt.backend.sdk.model.gaen.GaenKey; +import org.springframework.jdbc.core.RowMapper; public class GaenKeyRowMapper implements RowMapper { - @Override - public GaenKey mapRow(ResultSet rs, int rowNum) throws SQLException { - var gaenKey = new GaenKey(); - gaenKey.setKeyData(rs.getString("key")); - gaenKey.setRollingStartNumber(rs.getInt("rolling_start_number")); - gaenKey.setRollingPeriod(rs.getInt("rolling_period")); - gaenKey.setTransmissionRiskLevel(rs.getInt("transmission_risk_level")); - return gaenKey; - } - -} \ No newline at end of file + @Override + public GaenKey mapRow(ResultSet rs, int rowNum) throws SQLException { + var gaenKey = new GaenKey(); + gaenKey.setKeyData(rs.getString("key")); + gaenKey.setRollingStartNumber(rs.getInt("rolling_start_number")); + gaenKey.setRollingPeriod(rs.getInt("rolling_period")); + gaenKey.setTransmissionRiskLevel(rs.getInt("transmission_risk_level")); + return gaenKey; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/JDBCGAENDataServiceImpl.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/JDBCGAENDataServiceImpl.java index b824b19f..675b9006 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/JDBCGAENDataServiceImpl.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/main/java/org/dpppt/backend/sdk/data/gaen/JDBCGAENDataServiceImpl.java @@ -13,9 +13,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.utils.UTCInstant; import org.slf4j.Logger; @@ -26,111 +24,134 @@ public class JDBCGAENDataServiceImpl implements GAENDataService { - private static final Logger logger = LoggerFactory.getLogger(JDBCGAENDataServiceImpl.class); - - private static final String PGSQL = "pgsql"; - private final String dbType; - private final NamedParameterJdbcTemplate jt; - private final Duration releaseBucketDuration; - - public JDBCGAENDataServiceImpl(String dbType, DataSource dataSource, Duration releaseBucketDuration) { - this.dbType = dbType; - this.jt = new NamedParameterJdbcTemplate(dataSource); - this.releaseBucketDuration = releaseBucketDuration; - } - - @Override - @Transactional(readOnly = false) - public void upsertExposees(List gaenKeys, UTCInstant now) { - upsertExposeesDelayed(gaenKeys, null, now); - } - - @Override - public void upsertExposeesDelayed(List gaenKeys, UTCInstant delayedReceivedAt, UTCInstant now) { - - String sql = null; - if (dbType.equals(PGSQL)) { - sql = "insert into t_gaen_exposed (key, rolling_start_number, rolling_period, transmission_risk_level, received_at) values (:key, :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at)" - + " on conflict on constraint gaen_exposed_key do nothing"; - } else { - sql = "merge into t_gaen_exposed using (values(cast(:key as varchar(24)), :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at))" - + " as vals(key, rolling_start_number, rolling_period, transmission_risk_level, received_at) on t_gaen_exposed.key = vals.key" - + " when not matched then insert (key, rolling_start_number, rolling_period, transmission_risk_level, received_at) values (vals.key, vals.rolling_start_number, vals.rolling_period, transmission_risk_level, vals.received_at)"; - } - var parameterList = new ArrayList(); - //if delayedReceivedAt is supplied use it - var receivedAt = delayedReceivedAt == null? (now.getTimestamp()/releaseBucketDuration.toMillis() + 1) * releaseBucketDuration.toMillis() - 1 : delayedReceivedAt.getTimestamp(); - for (var gaenKey : gaenKeys) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("key", gaenKey.getKeyData()); - params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); - params.addValue("rolling_period", gaenKey.getRollingPeriod()); - params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); - params.addValue("received_at", UTCInstant.ofEpochMillis(receivedAt).getDate()); - - parameterList.add(params); - } - jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); - } - - @Override - @Transactional(readOnly = true) - public int getMaxExposedIdForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("rollingPeriodStartNumberStart", UTCInstant.ofEpochMillis(keyDate).get10MinutesSince1970()); - params.addValue("rollingPeriodStartNumberEnd", UTCInstant.ofEpochMillis(keyDate).plusDays(1).get10MinutesSince1970()); - params.addValue("publishedUntil", UTCInstant.ofEpochMillis(publishedUntil).getDate()); - - String sql = "select max(pk_exposed_id) from t_gaen_exposed where" - + " rolling_start_number >= :rollingPeriodStartNumberStart" - + " and rolling_start_number < :rollingPeriodStartNumberEnd" - + " and received_at < :publishedUntil"; - - if (publishedAfter != null) { - params.addValue("publishedAfter", UTCInstant.ofEpochMillis(publishedAfter).getDate()); - sql += " and received_at >= :publishedAfter"; - } - - Integer maxId = jt.queryForObject(sql, params, Integer.class); - if (maxId == null) { - return 0; - } else { - return maxId; - } - } - - @Override - @Transactional(readOnly = true) - public List getSortedExposedForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("rollingPeriodStartNumberStart", UTCInstant.ofEpochMillis(keyDate).get10MinutesSince1970()); - params.addValue("rollingPeriodStartNumberEnd", UTCInstant.ofEpochMillis(keyDate).plusDays(1).get10MinutesSince1970()); - params.addValue("publishedUntil", UTCInstant.ofEpochMillis(publishedUntil).getDate()); - - String sql = "select pk_exposed_id, key, rolling_start_number, rolling_period, transmission_risk_level from t_gaen_exposed where" - + " rolling_start_number >= :rollingPeriodStartNumberStart" - + " and rolling_start_number < :rollingPeriodStartNumberEnd" - + " and received_at < :publishedUntil"; - - if (publishedAfter != null) { - params.addValue("publishedAfter", UTCInstant.ofEpochMillis(publishedAfter).getDate()); - sql += " and received_at >= :publishedAfter"; - } - - sql += " order by pk_exposed_id desc"; - - return jt.query(sql, params, new GaenKeyRowMapper()); - } - - @Override - @Transactional(readOnly = false) - public void cleanDB(Duration retentionPeriod) { - var retentionTime = UTCInstant.now().minus(retentionPeriod); - logger.info("Cleanup DB entries before: " + retentionTime); - MapSqlParameterSource params = new MapSqlParameterSource("retention_time", - retentionTime.getDate()); - String sqlExposed = "delete from t_gaen_exposed where received_at < :retention_time"; - jt.update(sqlExposed, params); - } - + private static final Logger logger = LoggerFactory.getLogger(JDBCGAENDataServiceImpl.class); + + private static final String PGSQL = "pgsql"; + private final String dbType; + private final NamedParameterJdbcTemplate jt; + private final Duration releaseBucketDuration; + + public JDBCGAENDataServiceImpl( + String dbType, DataSource dataSource, Duration releaseBucketDuration) { + this.dbType = dbType; + this.jt = new NamedParameterJdbcTemplate(dataSource); + this.releaseBucketDuration = releaseBucketDuration; + } + + @Override + @Transactional(readOnly = false) + public void upsertExposees(List gaenKeys, UTCInstant now) { + upsertExposeesDelayed(gaenKeys, null, now); + } + + @Override + public void upsertExposeesDelayed( + List gaenKeys, UTCInstant delayedReceivedAt, UTCInstant now) { + + String sql = null; + if (dbType.equals(PGSQL)) { + sql = + "insert into t_gaen_exposed (key, rolling_start_number, rolling_period," + + " transmission_risk_level, received_at) values (:key, :rolling_start_number," + + " :rolling_period, :transmission_risk_level, :received_at) on conflict on" + + " constraint gaen_exposed_key do nothing"; + } else { + sql = + "merge into t_gaen_exposed using (values(cast(:key as varchar(24))," + + " :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at))" + + " as vals(key, rolling_start_number, rolling_period, transmission_risk_level," + + " received_at) on t_gaen_exposed.key = vals.key when not matched then insert (key," + + " rolling_start_number, rolling_period, transmission_risk_level, received_at)" + + " values (vals.key, vals.rolling_start_number, vals.rolling_period," + + " transmission_risk_level, vals.received_at)"; + } + var parameterList = new ArrayList(); + // if delayedReceivedAt is supplied use it + var receivedAt = + delayedReceivedAt == null + ? (now.getTimestamp() / releaseBucketDuration.toMillis() + 1) + * releaseBucketDuration.toMillis() + - 1 + : delayedReceivedAt.getTimestamp(); + for (var gaenKey : gaenKeys) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("key", gaenKey.getKeyData()); + params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); + params.addValue("rolling_period", gaenKey.getRollingPeriod()); + params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); + params.addValue("received_at", UTCInstant.ofEpochMillis(receivedAt).getDate()); + + parameterList.add(params); + } + jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); + } + + @Override + @Transactional(readOnly = true) + public int getMaxExposedIdForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue( + "rollingPeriodStartNumberStart", UTCInstant.ofEpochMillis(keyDate).get10MinutesSince1970()); + params.addValue( + "rollingPeriodStartNumberEnd", + UTCInstant.ofEpochMillis(keyDate).plusDays(1).get10MinutesSince1970()); + params.addValue("publishedUntil", UTCInstant.ofEpochMillis(publishedUntil).getDate()); + + String sql = + "select max(pk_exposed_id) from t_gaen_exposed where" + + " rolling_start_number >= :rollingPeriodStartNumberStart" + + " and rolling_start_number < :rollingPeriodStartNumberEnd" + + " and received_at < :publishedUntil"; + + if (publishedAfter != null) { + params.addValue("publishedAfter", UTCInstant.ofEpochMillis(publishedAfter).getDate()); + sql += " and received_at >= :publishedAfter"; + } + + Integer maxId = jt.queryForObject(sql, params, Integer.class); + if (maxId == null) { + return 0; + } else { + return maxId; + } + } + + @Override + @Transactional(readOnly = true) + public List getSortedExposedForKeyDate( + Long keyDate, Long publishedAfter, Long publishedUntil) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue( + "rollingPeriodStartNumberStart", UTCInstant.ofEpochMillis(keyDate).get10MinutesSince1970()); + params.addValue( + "rollingPeriodStartNumberEnd", + UTCInstant.ofEpochMillis(keyDate).plusDays(1).get10MinutesSince1970()); + params.addValue("publishedUntil", UTCInstant.ofEpochMillis(publishedUntil).getDate()); + + String sql = + "select pk_exposed_id, key, rolling_start_number, rolling_period, transmission_risk_level" + + " from t_gaen_exposed where rolling_start_number >= :rollingPeriodStartNumberStart" + + " and rolling_start_number < :rollingPeriodStartNumberEnd and received_at <" + + " :publishedUntil"; + + if (publishedAfter != null) { + params.addValue("publishedAfter", UTCInstant.ofEpochMillis(publishedAfter).getDate()); + sql += " and received_at >= :publishedAfter"; + } + + sql += " order by pk_exposed_id desc"; + + return jt.query(sql, params, new GaenKeyRowMapper()); + } + + @Override + @Transactional(readOnly = false) + public void cleanDB(Duration retentionPeriod) { + var retentionTime = UTCInstant.now().minus(retentionPeriod); + logger.info("Cleanup DB entries before: " + retentionTime); + MapSqlParameterSource params = + new MapSqlParameterSource("retention_time", retentionTime.getDate()); + String sqlExposed = "delete from t_gaen_exposed where received_at < :retention_time"; + jt.update(sqlExposed, params); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/DPPPTDataServiceTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/DPPPTDataServiceTest.java index b845e535..0d4df36a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/DPPPTDataServiceTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/DPPPTDataServiceTest.java @@ -18,7 +18,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; - import org.dpppt.backend.sdk.data.config.DPPPTDataServiceConfig; import org.dpppt.backend.sdk.data.config.FlyWayConfig; import org.dpppt.backend.sdk.data.config.RedeemDataServiceConfig; @@ -36,102 +35,112 @@ import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { StandaloneDataConfig.class, - FlyWayConfig.class, DPPPTDataServiceConfig.class, RedeemDataServiceConfig.class, TestConfig.class }) -@ActiveProfiles({ "hsqldb", "test-config"}) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = { + StandaloneDataConfig.class, + FlyWayConfig.class, + DPPPTDataServiceConfig.class, + RedeemDataServiceConfig.class, + TestConfig.class + }) +@ActiveProfiles({"hsqldb", "test-config"}) @Transactional public class DPPPTDataServiceTest { - @Autowired - private DPPPTDataService dppptDataService; - @Autowired - private RedeemDataService redeemDataService; - - @Test - @Transactional - public void testUpsertupsertExposee() { - Exposee expected = new Exposee(); - expected.setKey("key"); - var now = UTCInstant.now(); - expected.setKeyDate(now.atStartOfDay().getTimestamp()); - - dppptDataService.upsertExposee(expected, "AppSource"); - - List sortedExposedForDay = dppptDataService - .getSortedExposedForBatchReleaseTime(now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); - assertFalse(sortedExposedForDay.isEmpty()); - Exposee actual = sortedExposedForDay.get(0); - assertEquals(expected.getKey(), actual.getKey()); - assertEquals(expected.getKeyDate(), actual.getKeyDate()); - assertNotNull(actual.getId()); - } - - @Test - @Transactional - // depends on sorting of dbservice (in our case descsending with respect to id - // -> last inserted is first in list) - public void testUpsertExposees() throws Exception { - var expected = new ArrayList(); - var exposee1 = new Exposee(); - var exposee2 = new Exposee(); - exposee1.setKey("key1"); - exposee2.setKey("key2"); - - var now = UTCInstant.now(); - var nowMidnight = now.atStartOfDay(); - var yesterday = nowMidnight.minusDays(1); - exposee1.setKeyDate(nowMidnight.getTimestamp()); - exposee2.setKeyDate(yesterday.getTimestamp()); - - expected.add(exposee1); - expected.add(exposee2); - - dppptDataService.upsertExposees(expected, "AppSource"); - - List sortedExposedForDay = dppptDataService - .getSortedExposedForBatchReleaseTime(now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); - assertFalse(sortedExposedForDay.isEmpty()); - - Exposee actual = sortedExposedForDay.get(1); - assertEquals(expected.get(0).getKey(), actual.getKey()); - assertEquals(expected.get(0).getKeyDate(), actual.getKeyDate()); - assertNotNull(actual.getId()); - - Exposee actualYesterday = sortedExposedForDay.get(0); - assertEquals(expected.get(1).getKey(), actualYesterday.getKey()); - assertEquals(expected.get(1).getKeyDate(), actualYesterday.getKeyDate()); - assertNotNull(actualYesterday.getId()); - } - - @Test - @Transactional - public void testRedeemUUID() { - boolean actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertTrue(actual); - actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertFalse(actual); - actual = redeemDataService.checkAndInsertPublishUUID("1c444adb-0924-4dc4-a7eb-1f52aa6b9575"); - assertTrue(actual); - } - - //@Test - @Transactional - public void cleanUp() { - Exposee expected = new Exposee(); - expected.setKey("key"); - var now = UTCInstant.now(); - expected.setKeyDate(now.atStartOfDay().getTimestamp()); - - dppptDataService.upsertExposee(expected, "AppSource"); - dppptDataService.cleanDB(Duration.ofDays(21)); - - List sortedExposedForDay = dppptDataService - .getSortedExposedForBatchReleaseTime(now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); - assertFalse(sortedExposedForDay.isEmpty()); - - dppptDataService.cleanDB(Duration.ofDays(0)); - sortedExposedForDay = dppptDataService.getSortedExposedForBatchReleaseTime(now.plusMinutes(10).getTimestamp(), - 1 * 60 * 60 * 1000l); - assertTrue(sortedExposedForDay.isEmpty()); - } -} \ No newline at end of file + @Autowired private DPPPTDataService dppptDataService; + @Autowired private RedeemDataService redeemDataService; + + @Test + @Transactional + public void testUpsertupsertExposee() { + Exposee expected = new Exposee(); + expected.setKey("key"); + var now = UTCInstant.now(); + expected.setKeyDate(now.atStartOfDay().getTimestamp()); + + dppptDataService.upsertExposee(expected, "AppSource"); + + List sortedExposedForDay = + dppptDataService.getSortedExposedForBatchReleaseTime( + now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); + assertFalse(sortedExposedForDay.isEmpty()); + Exposee actual = sortedExposedForDay.get(0); + assertEquals(expected.getKey(), actual.getKey()); + assertEquals(expected.getKeyDate(), actual.getKeyDate()); + assertNotNull(actual.getId()); + } + + @Test + @Transactional + // depends on sorting of dbservice (in our case descsending with respect to id + // -> last inserted is first in list) + public void testUpsertExposees() throws Exception { + var expected = new ArrayList(); + var exposee1 = new Exposee(); + var exposee2 = new Exposee(); + exposee1.setKey("key1"); + exposee2.setKey("key2"); + + var now = UTCInstant.now(); + var nowMidnight = now.atStartOfDay(); + var yesterday = nowMidnight.minusDays(1); + exposee1.setKeyDate(nowMidnight.getTimestamp()); + exposee2.setKeyDate(yesterday.getTimestamp()); + + expected.add(exposee1); + expected.add(exposee2); + + dppptDataService.upsertExposees(expected, "AppSource"); + + List sortedExposedForDay = + dppptDataService.getSortedExposedForBatchReleaseTime( + now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); + assertFalse(sortedExposedForDay.isEmpty()); + + Exposee actual = sortedExposedForDay.get(1); + assertEquals(expected.get(0).getKey(), actual.getKey()); + assertEquals(expected.get(0).getKeyDate(), actual.getKeyDate()); + assertNotNull(actual.getId()); + + Exposee actualYesterday = sortedExposedForDay.get(0); + assertEquals(expected.get(1).getKey(), actualYesterday.getKey()); + assertEquals(expected.get(1).getKeyDate(), actualYesterday.getKeyDate()); + assertNotNull(actualYesterday.getId()); + } + + @Test + @Transactional + public void testRedeemUUID() { + boolean actual = + redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertTrue(actual); + actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertFalse(actual); + actual = redeemDataService.checkAndInsertPublishUUID("1c444adb-0924-4dc4-a7eb-1f52aa6b9575"); + assertTrue(actual); + } + + // @Test + @Transactional + public void cleanUp() { + Exposee expected = new Exposee(); + expected.setKey("key"); + var now = UTCInstant.now(); + expected.setKeyDate(now.atStartOfDay().getTimestamp()); + + dppptDataService.upsertExposee(expected, "AppSource"); + dppptDataService.cleanDB(Duration.ofDays(21)); + + List sortedExposedForDay = + dppptDataService.getSortedExposedForBatchReleaseTime( + now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); + assertFalse(sortedExposedForDay.isEmpty()); + + dppptDataService.cleanDB(Duration.ofDays(0)); + sortedExposedForDay = + dppptDataService.getSortedExposedForBatchReleaseTime( + now.plusMinutes(10).getTimestamp(), 1 * 60 * 60 * 1000l); + assertTrue(sortedExposedForDay.isEmpty()); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/PostgresDPPPTDataServiceTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/PostgresDPPPTDataServiceTest.java index 354caaf9..6da2c8cf 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/PostgresDPPPTDataServiceTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/PostgresDPPPTDataServiceTest.java @@ -10,6 +10,16 @@ package org.dpppt.backend.sdk.data; +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.*; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDate; +import java.util.List; +import javax.sql.DataSource; import org.assertj.core.api.Assertions; import org.dpppt.backend.sdk.data.config.DPPPTDataServiceConfig; import org.dpppt.backend.sdk.data.config.FlyWayConfig; @@ -27,149 +37,147 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import javax.sql.DataSource; -import java.sql.*; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDate; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = {PostgresDataConfig.class, FlyWayConfig.class, DPPPTDataServiceConfig.class, TestConfig.class}) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = { + PostgresDataConfig.class, + FlyWayConfig.class, + DPPPTDataServiceConfig.class, + TestConfig.class + }) @ActiveProfiles({"postgres", "test-config"}) public class PostgresDPPPTDataServiceTest { - private static final String APP_SOURCE = "test-app"; - public static final long BATCH_LENGTH = 2 * 60 * 60 * 1000L; - - @Autowired - private DPPPTDataService dppptDataService; - - @Autowired - private RedeemDataService redeemDataService; - - - @Autowired - private DataSource dataSource; - - @After - public void tearDown() throws SQLException { - executeSQL("truncate table t_exposed"); - executeSQL("truncate table t_redeem_uuid"); - } - - @Test - public void shouldAddAnExposee() throws SQLException { - // GIVEN - final long exposeeCountBefore = getExposeeCount(); - - Exposee exposee = createExposee("key1", "2014-01-28"); + private static final String APP_SOURCE = "test-app"; + public static final long BATCH_LENGTH = 2 * 60 * 60 * 1000L; - // WHEN - dppptDataService.upsertExposee(exposee, "test-app"); + @Autowired private DPPPTDataService dppptDataService; - // THEN - final long exposeeCountAfter = getExposeeCount(); - Assertions.assertThat(exposeeCountAfter).isEqualTo(exposeeCountBefore + 1); + @Autowired private RedeemDataService redeemDataService; - try ( - final Connection connection = dataSource.getConnection(); - final PreparedStatement preparedStatement = connection.prepareStatement("select * from t_exposed t where t.key = 'key1'"); - final ResultSet resultSet = preparedStatement.executeQuery()) { - resultSet.next(); + @Autowired private DataSource dataSource; - Assertions.assertThat(resultSet.getInt("pk_exposed_id")).isPositive(); - Assertions.assertThat(resultSet.getString("key")).isEqualTo("key1"); - Assertions.assertThat(resultSet.getString("received_at")).isNotNull(); - Assertions.assertThat(resultSet.getString("app_source")).isEqualTo(APP_SOURCE); - Assertions.assertThat(resultSet.getDate("key_date")).isEqualTo(Date.valueOf(LocalDate.of(2014, 1, 28))); - } - } + @After + public void tearDown() throws SQLException { + executeSQL("truncate table t_exposed"); + executeSQL("truncate table t_redeem_uuid"); + } - @Test - public void testRedeemUUID() { - boolean actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertTrue(actual); - actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertFalse(actual); - actual = redeemDataService.checkAndInsertPublishUUID("1c444adb-0924-4dc4-a7eb-1f52aa6b9575"); - assertTrue(actual); - } + @Test + public void shouldAddAnExposee() throws SQLException { + // GIVEN + final long exposeeCountBefore = getExposeeCount(); - @Test - public void cleanup() throws SQLException { - var now = UTCInstant.now(); - var receivedAt = now.minusDays(21); - Connection connection = dataSource.getConnection(); - String key = "someKey"; - insertExposeeWithReceivedAt(receivedAt.getInstant(), key); + Exposee exposee = createExposee("key1", "2014-01-28"); - List sortedExposedForDay = dppptDataService - .getSortedExposedForBatchReleaseTime(receivedAt.getTimestamp() + 1, 1 * 60 * 60 * 1000l); - assertFalse(sortedExposedForDay.isEmpty()); + // WHEN + dppptDataService.upsertExposee(exposee, "test-app"); - dppptDataService.cleanDB(Duration.ofDays(21)); - sortedExposedForDay = dppptDataService.getSortedExposedForBatchReleaseTime(receivedAt.getTimestamp() + 1, - 1 * 60 * 60 * 1000l); - assertTrue(sortedExposedForDay.isEmpty()); + // THEN + final long exposeeCountAfter = getExposeeCount(); + Assertions.assertThat(exposeeCountAfter).isEqualTo(exposeeCountBefore + 1); - } + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = + connection.prepareStatement("select * from t_exposed t where t.key = 'key1'"); + final ResultSet resultSet = preparedStatement.executeQuery()) { + resultSet.next(); - @Test - public void testBatchReleaseTime() throws SQLException { - var receivedAt = UTCInstant.parseDateTime("2014-01-28T00:00:00"); - String key = "key555"; - insertExposeeWithReceivedAt(receivedAt.getInstant(), key); - - long batchTime = UTCInstant.parseDateTime("2014-01-28T02:00:00").getInstant().toEpochMilli(); - List sortedExposedForBatchReleaseTime = dppptDataService.getSortedExposedForBatchReleaseTime(batchTime, BATCH_LENGTH); - assertEquals(1, sortedExposedForBatchReleaseTime.size()); - Exposee actual = sortedExposedForBatchReleaseTime.get(0); - assertEquals(actual.getKey(), key); - int maxExposedIdForBatchReleaseTime = dppptDataService.getMaxExposedIdForBatchReleaseTime(batchTime, BATCH_LENGTH); - assertEquals(1, maxExposedIdForBatchReleaseTime); - maxExposedIdForBatchReleaseTime = dppptDataService.getMaxExposedIdForBatchReleaseTime(receivedAt.getTimestamp(), PostgresDPPPTDataServiceTest.BATCH_LENGTH); - assertEquals(0, maxExposedIdForBatchReleaseTime); + Assertions.assertThat(resultSet.getInt("pk_exposed_id")).isPositive(); + Assertions.assertThat(resultSet.getString("key")).isEqualTo("key1"); + Assertions.assertThat(resultSet.getString("received_at")).isNotNull(); + Assertions.assertThat(resultSet.getString("app_source")).isEqualTo(APP_SOURCE); + Assertions.assertThat(resultSet.getDate("key_date")) + .isEqualTo(Date.valueOf(LocalDate.of(2014, 1, 28))); } - - - private void insertExposeeWithReceivedAt(Instant receivedAt, String key) throws SQLException { - Connection connection = dataSource.getConnection(); - String sql = "into t_exposed (pk_exposed_id, key, received_at, key_date, app_source) values (1, ?, ?, now(), 'appsource')"; - PreparedStatement preparedStatement = connection.prepareStatement("insert " + sql); - preparedStatement.setString(1, key); - preparedStatement.setTimestamp(2, new Timestamp(receivedAt.toEpochMilli())); - preparedStatement.execute(); - } - - @NotNull - private Exposee createExposee(String key, String keyDate) { - Exposee exposee = new Exposee(); - exposee.setKey(key); - exposee.setKeyDate(UTCInstant.parseDate("2014-01-28").getTimestamp()); - return exposee; - } - - private long getExposeeCount() throws SQLException { - try ( - final Connection connection = dataSource.getConnection(); - final PreparedStatement preparedStatement = connection.prepareStatement("select count(*) from t_exposed"); - final ResultSet resultSet = preparedStatement.executeQuery()) { - resultSet.next(); - return resultSet.getLong(1); - } + } + + @Test + public void testRedeemUUID() { + boolean actual = + redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertTrue(actual); + actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertFalse(actual); + actual = redeemDataService.checkAndInsertPublishUUID("1c444adb-0924-4dc4-a7eb-1f52aa6b9575"); + assertTrue(actual); + } + + @Test + public void cleanup() throws SQLException { + var now = UTCInstant.now(); + var receivedAt = now.minusDays(21); + Connection connection = dataSource.getConnection(); + String key = "someKey"; + insertExposeeWithReceivedAt(receivedAt.getInstant(), key); + + List sortedExposedForDay = + dppptDataService.getSortedExposedForBatchReleaseTime( + receivedAt.getTimestamp() + 1, 1 * 60 * 60 * 1000l); + assertFalse(sortedExposedForDay.isEmpty()); + + dppptDataService.cleanDB(Duration.ofDays(21)); + sortedExposedForDay = + dppptDataService.getSortedExposedForBatchReleaseTime( + receivedAt.getTimestamp() + 1, 1 * 60 * 60 * 1000l); + assertTrue(sortedExposedForDay.isEmpty()); + } + + @Test + public void testBatchReleaseTime() throws SQLException { + var receivedAt = UTCInstant.parseDateTime("2014-01-28T00:00:00"); + String key = "key555"; + insertExposeeWithReceivedAt(receivedAt.getInstant(), key); + + long batchTime = UTCInstant.parseDateTime("2014-01-28T02:00:00").getInstant().toEpochMilli(); + List sortedExposedForBatchReleaseTime = + dppptDataService.getSortedExposedForBatchReleaseTime(batchTime, BATCH_LENGTH); + assertEquals(1, sortedExposedForBatchReleaseTime.size()); + Exposee actual = sortedExposedForBatchReleaseTime.get(0); + assertEquals(actual.getKey(), key); + int maxExposedIdForBatchReleaseTime = + dppptDataService.getMaxExposedIdForBatchReleaseTime(batchTime, BATCH_LENGTH); + assertEquals(1, maxExposedIdForBatchReleaseTime); + maxExposedIdForBatchReleaseTime = + dppptDataService.getMaxExposedIdForBatchReleaseTime( + receivedAt.getTimestamp(), PostgresDPPPTDataServiceTest.BATCH_LENGTH); + assertEquals(0, maxExposedIdForBatchReleaseTime); + } + + private void insertExposeeWithReceivedAt(Instant receivedAt, String key) throws SQLException { + Connection connection = dataSource.getConnection(); + String sql = + "into t_exposed (pk_exposed_id, key, received_at, key_date, app_source) values (1, ?, ?," + + " now(), 'appsource')"; + PreparedStatement preparedStatement = connection.prepareStatement("insert " + sql); + preparedStatement.setString(1, key); + preparedStatement.setTimestamp(2, new Timestamp(receivedAt.toEpochMilli())); + preparedStatement.execute(); + } + + @NotNull + private Exposee createExposee(String key, String keyDate) { + Exposee exposee = new Exposee(); + exposee.setKey(key); + exposee.setKeyDate(UTCInstant.parseDate("2014-01-28").getTimestamp()); + return exposee; + } + + private long getExposeeCount() throws SQLException { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = + connection.prepareStatement("select count(*) from t_exposed"); + final ResultSet resultSet = preparedStatement.executeQuery()) { + resultSet.next(); + return resultSet.getLong(1); } + } - protected void executeSQL(String sql) throws SQLException { - try ( - final Connection connection = dataSource.getConnection(); - final PreparedStatement preparedStatement = connection.prepareStatement(sql); - ) { - preparedStatement.execute(); - } + protected void executeSQL(String sql) throws SQLException { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(sql); ) { + preparedStatement.execute(); } + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/DPPPTDataServiceConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/DPPPTDataServiceConfig.java index fc328acd..42fcfd04 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/DPPPTDataServiceConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/DPPPTDataServiceConfig.java @@ -10,6 +10,9 @@ package org.dpppt.backend.sdk.data.config; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import javax.sql.DataSource; import org.dpppt.backend.sdk.data.DPPPTDataService; import org.dpppt.backend.sdk.data.JDBCDPPPTDataServiceImpl; import org.dpppt.backend.sdk.data.JDBCRedeemDataServiceImpl; @@ -24,52 +27,51 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import java.security.NoSuchAlgorithmException; -import java.time.Duration; - -import javax.sql.DataSource; - @Configuration public class DPPPTDataServiceConfig { - @Value("${ws.gaen.randomkeysenabled: true}") - boolean randomkeysenabled; - @Value("${ws.exposedlist.releaseBucketDuration: 7200000}") - long releaseBucketDuration; + @Value("${ws.gaen.randomkeysenabled: true}") + boolean randomkeysenabled; + + @Value("${ws.exposedlist.releaseBucketDuration: 7200000}") + long releaseBucketDuration; - @Autowired - DataSource dataSource; + @Autowired DataSource dataSource; - @Bean - public DataSource fakeDataSource() { - return new EmbeddedDatabaseBuilder().generateUniqueName(true).setType(EmbeddedDatabaseType.HSQL).build(); - } + @Bean + public DataSource fakeDataSource() { + return new EmbeddedDatabaseBuilder() + .generateUniqueName(true) + .setType(EmbeddedDatabaseType.HSQL) + .build(); + } - @Autowired - String dbType; + @Autowired String dbType; - @Bean - public DPPPTDataService DPPPTDataService() { - return new JDBCDPPPTDataServiceImpl(dbType, dataSource); - } + @Bean + public DPPPTDataService DPPPTDataService() { + return new JDBCDPPPTDataServiceImpl(dbType, dataSource); + } - @Bean - public GAENDataService gaenDataService() { - return new JDBCGAENDataServiceImpl(dbType, dataSource, Duration.ofMillis(releaseBucketDuration)); - } + @Bean + public GAENDataService gaenDataService() { + return new JDBCGAENDataServiceImpl( + dbType, dataSource, Duration.ofMillis(releaseBucketDuration)); + } - @Bean - public RedeemDataService redeemDataService() { - return new JDBCRedeemDataServiceImpl(dataSource); - } + @Bean + public RedeemDataService redeemDataService() { + return new JDBCRedeemDataServiceImpl(dataSource); + } - @Bean - public GAENDataService fakeService() { - return new JDBCGAENDataServiceImpl("hsql", fakeDataSource(), Duration.ofMillis(releaseBucketDuration)); - } + @Bean + public GAENDataService fakeService() { + return new JDBCGAENDataServiceImpl( + "hsql", fakeDataSource(), Duration.ofMillis(releaseBucketDuration)); + } - @Bean - public FakeKeyService fakeKeyService() throws NoSuchAlgorithmException { - return new FakeKeyService(fakeService(), 10, 16, Duration.ofDays(21), randomkeysenabled); - } + @Bean + public FakeKeyService fakeKeyService() throws NoSuchAlgorithmException { + return new FakeKeyService(fakeService(), 10, 16, Duration.ofDays(21), randomkeysenabled); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/FlyWayConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/FlyWayConfig.java index 8be606ed..f7849eb5 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/FlyWayConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/FlyWayConfig.java @@ -10,42 +10,49 @@ package org.dpppt.backend.sdk.data.config; +import javax.sql.DataSource; import org.flywaydb.core.Flyway; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import javax.sql.DataSource; - @Configuration public class FlyWayConfig { - @Autowired - DataSource dataSource; - - @Autowired - DataSource fakeDataSource; - - @Bean - @Profile("hsqldb") - public Flyway flyway() { - Flyway flyWay = Flyway.configure().dataSource(dataSource).locations("classpath:/db/migration/hsqldb").load(); - flyWay.migrate(); - return flyWay; - } - - @Bean - @Profile("postgres") - public Flyway flywayPostgres() { - Flyway flyWay = Flyway.configure().dataSource(dataSource).locations("classpath:/db/migration/pgsql").load(); - flyWay.migrate(); - return flyWay; - } - @Bean - public Flyway fakeFlyway() { - Flyway flyWay = Flyway.configure().dataSource(fakeDataSource).locations("classpath:/db/migration/hsqldb").load(); - flyWay.migrate(); - return flyWay; - } + @Autowired DataSource dataSource; + + @Autowired DataSource fakeDataSource; + + @Bean + @Profile("hsqldb") + public Flyway flyway() { + Flyway flyWay = + Flyway.configure() + .dataSource(dataSource) + .locations("classpath:/db/migration/hsqldb") + .load(); + flyWay.migrate(); + return flyWay; + } + + @Bean + @Profile("postgres") + public Flyway flywayPostgres() { + Flyway flyWay = + Flyway.configure().dataSource(dataSource).locations("classpath:/db/migration/pgsql").load(); + flyWay.migrate(); + return flyWay; + } + + @Bean + public Flyway fakeFlyway() { + Flyway flyWay = + Flyway.configure() + .dataSource(fakeDataSource) + .locations("classpath:/db/migration/hsqldb") + .load(); + flyWay.migrate(); + return flyWay; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/PostgresDataConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/PostgresDataConfig.java index 0ec29889..7c2b5ba3 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/PostgresDataConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/PostgresDataConfig.java @@ -10,34 +10,32 @@ package org.dpppt.backend.sdk.data.config; +import javax.sql.DataSource; import org.dpppt.backend.sdk.data.util.SingletonPostgresContainer; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import javax.sql.DataSource; - @Configuration @Profile("postgres") public class PostgresDataConfig { - @Bean - public DataSource dataSource() { - final SingletonPostgresContainer instance = SingletonPostgresContainer.getInstance(); - instance.start(); - - return DataSourceBuilder.create() - .driverClassName(instance.getDriverClassName()) - .url(instance.getJdbcUrl()) - .username(instance.getUsername()) - .password(instance.getPassword()) - .build(); - } - - @Bean - public String dbType() { - return "pgsql"; - } - + @Bean + public DataSource dataSource() { + final SingletonPostgresContainer instance = SingletonPostgresContainer.getInstance(); + instance.start(); + + return DataSourceBuilder.create() + .driverClassName(instance.getDriverClassName()) + .url(instance.getJdbcUrl()) + .username(instance.getUsername()) + .password(instance.getPassword()) + .build(); + } + + @Bean + public String dbType() { + return "pgsql"; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/RedeemDataServiceConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/RedeemDataServiceConfig.java index a8f63877..9a2e60b5 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/RedeemDataServiceConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/RedeemDataServiceConfig.java @@ -10,9 +10,7 @@ package org.dpppt.backend.sdk.data.config; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.data.JDBCRedeemDataServiceImpl; import org.dpppt.backend.sdk.data.RedeemDataService; import org.springframework.beans.factory.annotation.Autowired; @@ -22,15 +20,12 @@ @Configuration public class RedeemDataServiceConfig { - @Autowired - DataSource dataSource; - - @Autowired - String dbType; + @Autowired DataSource dataSource; - @Bean - public RedeemDataService redeemDataService() { - return new JDBCRedeemDataServiceImpl(dataSource); - } + @Autowired String dbType; + @Bean + public RedeemDataService redeemDataService() { + return new JDBCRedeemDataServiceImpl(dataSource); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/StandaloneDataConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/StandaloneDataConfig.java index 5f457c38..82723d46 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/StandaloneDataConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/StandaloneDataConfig.java @@ -10,26 +10,27 @@ package org.dpppt.backend.sdk.data.config; +import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import javax.sql.DataSource; - @Configuration @Profile("hsqldb") public class StandaloneDataConfig { - @Bean - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder().generateUniqueName(true).setType(EmbeddedDatabaseType.HSQL).build(); - } - - @Bean - public String dbType() { - return "hsqldb"; - } + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .generateUniqueName(true) + .setType(EmbeddedDatabaseType.HSQL) + .build(); + } + @Bean + public String dbType() { + return "hsqldb"; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/TestConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/TestConfig.java index ea270cfb..087c6bc8 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/TestConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/config/TestConfig.java @@ -1,7 +1,6 @@ package org.dpppt.backend.sdk.data.config; import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,11 +9,11 @@ @Configuration("test-config") public class TestConfig { - @Autowired - DataSource dataSource; - @Bean - public PlatformTransactionManager testTransactionManager() throws Exception { - DataSourceTransactionManager dstm = new DataSourceTransactionManager(dataSource); - return dstm; - } -} \ No newline at end of file + @Autowired DataSource dataSource; + + @Bean + public PlatformTransactionManager testTransactionManager() throws Exception { + DataSourceTransactionManager dstm = new DataSourceTransactionManager(dataSource); + return dstm; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/GaenDataServiceTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/GaenDataServiceTest.java index 48e2a2d5..7bad5481 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/GaenDataServiceTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/GaenDataServiceTest.java @@ -5,7 +5,6 @@ import java.time.Duration; import java.util.Base64; import java.util.List; - import org.dpppt.backend.sdk.data.config.DPPPTDataServiceConfig; import org.dpppt.backend.sdk.data.config.FlyWayConfig; import org.dpppt.backend.sdk.data.config.RedeemDataServiceConfig; @@ -21,44 +20,51 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { StandaloneDataConfig.class, - FlyWayConfig.class, DPPPTDataServiceConfig.class, RedeemDataServiceConfig.class }) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = { + StandaloneDataConfig.class, + FlyWayConfig.class, + DPPPTDataServiceConfig.class, + RedeemDataServiceConfig.class + }) @ActiveProfiles("hsqldb") public class GaenDataServiceTest { - private static final Duration BUCKET_LENGTH = Duration.ofHours(2); - - @Autowired - private GAENDataService gaenDataService; + private static final Duration BUCKET_LENGTH = Duration.ofHours(2); - @Test - public void upsert() throws Exception { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int)UTCInstant.today().minus(Duration.ofDays(1)).get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - var tmpKey2 = new GaenKey(); - tmpKey2.setRollingStartNumber((int) UTCInstant.today().minus(Duration.ofDays(1)).get10MinutesSince1970()); - tmpKey2.setKeyData(Base64.getEncoder().encodeToString("testKey33Bytes--".getBytes("UTF-8"))); - tmpKey2.setRollingPeriod(144); - tmpKey2.setFake(0); - tmpKey2.setTransmissionRiskLevel(0); - List keys = List.of(tmpKey, tmpKey2); - var utcNow = UTCInstant.now(); - gaenDataService.upsertExposees(keys, utcNow); + @Autowired private GAENDataService gaenDataService; - long now = utcNow.getTimestamp(); - // calculate exposed until bucket, but get bucket in the future, as keys have - // been inserted with timestamp now. - long publishedUntil = now - (now % BUCKET_LENGTH.toMillis()) + BUCKET_LENGTH.toMillis(); + @Test + public void upsert() throws Exception { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) UTCInstant.today().minus(Duration.ofDays(1)).get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + var tmpKey2 = new GaenKey(); + tmpKey2.setRollingStartNumber( + (int) UTCInstant.today().minus(Duration.ofDays(1)).get10MinutesSince1970()); + tmpKey2.setKeyData(Base64.getEncoder().encodeToString("testKey33Bytes--".getBytes("UTF-8"))); + tmpKey2.setRollingPeriod(144); + tmpKey2.setFake(0); + tmpKey2.setTransmissionRiskLevel(0); + List keys = List.of(tmpKey, tmpKey2); + var utcNow = UTCInstant.now(); + gaenDataService.upsertExposees(keys, utcNow); - var returnedKeys = gaenDataService.getSortedExposedForKeyDate(UTCInstant.today().minusDays(1).getTimestamp(), null, - publishedUntil); + long now = utcNow.getTimestamp(); + // calculate exposed until bucket, but get bucket in the future, as keys have + // been inserted with timestamp now. + long publishedUntil = now - (now % BUCKET_LENGTH.toMillis()) + BUCKET_LENGTH.toMillis(); - assertEquals(keys.size(), returnedKeys.size()); - assertEquals(keys.get(1).getKeyData(), returnedKeys.get(0).getKeyData()); - } + var returnedKeys = + gaenDataService.getSortedExposedForKeyDate( + UTCInstant.today().minusDays(1).getTimestamp(), null, publishedUntil); -} \ No newline at end of file + assertEquals(keys.size(), returnedKeys.size()); + assertEquals(keys.get(1).getKeyData(), returnedKeys.get(0).getKeyData()); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/PostgresGaenDataServiceTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/PostgresGaenDataServiceTest.java index 284e11e5..27915ad7 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/PostgresGaenDataServiceTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/gaen/PostgresGaenDataServiceTest.java @@ -21,15 +21,12 @@ import java.sql.Timestamp; import java.time.Clock; import java.time.Duration; +import java.time.Instant; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.Base64; import java.util.List; -import java.time.Instant; - import javax.sql.DataSource; - -import org.dpppt.backend.sdk.data.JDBCRedeemDataServiceImpl; import org.dpppt.backend.sdk.data.RedeemDataService; import org.dpppt.backend.sdk.data.config.DPPPTDataServiceConfig; import org.dpppt.backend.sdk.data.config.FlyWayConfig; @@ -50,213 +47,231 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { PostgresDataConfig.class, - FlyWayConfig.class, DPPPTDataServiceConfig.class }) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = {PostgresDataConfig.class, FlyWayConfig.class, DPPPTDataServiceConfig.class}) @ActiveProfiles("postgres") -@TestPropertySource(properties = { "ws.gaen.randomkeysenabled=true" }) +@TestPropertySource(properties = {"ws.gaen.randomkeysenabled=true"}) public class PostgresGaenDataServiceTest { - private static final String APP_SOURCE = "test-app"; - private static final Duration BATCH_LENGTH = Duration.ofHours(2); - - @Autowired - private GAENDataService gaenDataService; - @Autowired - private FakeKeyService fakeKeyService; - - @Autowired - private RedeemDataService redeemDataService; - - @Autowired - private DataSource dataSource; - - @After - public void tearDown() throws SQLException { - executeSQL("truncate table t_exposed"); - executeSQL("truncate table t_redeem_uuid"); - } - - @Test - public void testFakeKeyContainsKeysForLast21Days() { - var today = UTCInstant.today(); - var noKeyAtThisDate = today.minusDays(22); - var keysUntilToday = today.minusDays(21); - - var keys = new ArrayList(); - var emptyList = fakeKeyService.fillUpKeys(keys, null, - noKeyAtThisDate.getTimestamp()); - assertEquals(0, emptyList.size()); - do { - keys.clear(); - var list = fakeKeyService.fillUpKeys(keys, null, - keysUntilToday.getTimestamp()); - - assertEquals(10, list.size()); - list = fakeKeyService.fillUpKeys(keys, UTCInstant.now().plusHours(3).getTimestamp(), keysUntilToday.getTimestamp()); - assertEquals(10, list.size()); - keysUntilToday = keysUntilToday.plusDays(1); - } while (keysUntilToday.isBeforeDateOf(today)); - - keys.clear(); - emptyList = fakeKeyService.fillUpKeys(keys, null, - noKeyAtThisDate.getTimestamp()); - assertEquals(0, emptyList.size()); - } - - @Test - public void testRedeemUUID() { - boolean actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertTrue(actual); - actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertFalse(actual); - actual = redeemDataService.checkAndInsertPublishUUID("1c444adb-0924-4dc4-a7eb-1f52aa6b9575"); - assertTrue(actual); - } - - @Test - public void testTokensArentDeletedBeforeExpire() throws Exception { - var localDateNow = UTCInstant.today(); - Clock twoMinutesToMidnight = Clock.fixed(localDateNow.plusDays(1).minusMinutes(2).getInstant(), ZoneOffset.UTC); - Clock twoMinutesAfterMidnight = Clock.fixed(localDateNow.plusDays(1).plusMinutes(2).getInstant(), ZoneOffset.UTC); - Clock nextDay = Clock.fixed(localDateNow.plusDays(2).plusMinutes(2).getInstant(), ZoneOffset.UTC); - - UTCInstant.setClock(twoMinutesToMidnight); - - boolean actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertTrue(actual); - - //token is still valid for 1 minute - UTCInstant.setClock(twoMinutesAfterMidnight); - - redeemDataService.cleanDB(Duration.ofDays(1)); - - actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertFalse(actual); - - UTCInstant.setClock(nextDay); - - redeemDataService.cleanDB(Duration.ofDays(1)); - - actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); - assertTrue(actual); - UTCInstant.resetClock(); - } - - @Test - public void cleanup() throws SQLException { - var now = UTCInstant.now(); - var receivedAt = now.minusDays(21); - Connection connection = dataSource.getConnection(); - String key = "someKey"; - insertExposeeWithReceivedAtAndKeyDate(receivedAt.getInstant(), receivedAt.minusDays(1).getInstant(), key); - - List sortedExposedForDay = gaenDataService.getSortedExposedForKeyDate( - receivedAt.minusDays(1).getInstant().toEpochMilli(), null, now.getInstant().toEpochMilli()); - - assertFalse(sortedExposedForDay.isEmpty()); - - gaenDataService.cleanDB(Duration.ofDays(21)); - sortedExposedForDay = gaenDataService.getSortedExposedForKeyDate( - receivedAt.minusDays(1).getInstant().toEpochMilli(), null, now.getInstant().toEpochMilli()); - - assertTrue(sortedExposedForDay.isEmpty()); - - } - - @Test - public void upsert() throws Exception { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) UTCInstant.today().minus(Duration.ofDays(1)).get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - List keys = List.of(tmpKey); - - gaenDataService.upsertExposees(keys, UTCInstant.now()); - - long now = System.currentTimeMillis(); - // calculate exposed until bucket, but get bucket in the future, as keys have - // been inserted with timestamp now. - long publishedUntil = now - (now % BATCH_LENGTH.toMillis()) + BATCH_LENGTH.toMillis(); - - var returnedKeys = gaenDataService.getSortedExposedForKeyDate( - UTCInstant.today().minus(Duration.ofDays(1)).getTimestamp(), null, - publishedUntil); - - assertEquals(keys.size(), returnedKeys.size()); - assertEquals(keys.get(0).getKeyData(), returnedKeys.get(0).getKeyData()); - } - - @Test - public void testBatchReleaseTime() throws SQLException { - var receivedAt = UTCInstant.parseDateTime("2014-01-28T00:00:00"); - String key = "key555"; - insertExposeeWithReceivedAtAndKeyDate(receivedAt.getInstant(), receivedAt.minus(Duration.ofDays(2)).getInstant(), key); - - var batchTime = UTCInstant.parseDateTime("2014-01-28T02:00:00"); - - var returnedKeys = gaenDataService - .getSortedExposedForKeyDate(receivedAt.minus(Duration.ofDays(2)).getTimestamp(), null, batchTime.getTimestamp()); - - assertEquals(1, returnedKeys.size()); - GaenKey actual = returnedKeys.get(0); - assertEquals(actual.getKeyData(), key); - - int maxExposedIdForBatchReleaseTime = gaenDataService - .getMaxExposedIdForKeyDate(receivedAt.minus(Duration.ofDays(2)).getTimestamp(), null, batchTime.getTimestamp()); - assertEquals(100, maxExposedIdForBatchReleaseTime); - - returnedKeys = gaenDataService.getSortedExposedForKeyDate(receivedAt.minus(Duration.ofDays(2)).getTimestamp(), - batchTime.getTimestamp(), batchTime.plusHours(2).getTimestamp()); - assertEquals(0, returnedKeys.size()); - } - - private void insertExposeeWithReceivedAt(Instant receivedAt, String key) throws SQLException { - Connection connection = dataSource.getConnection(); - String sql = "into t_gaen_exposed (pk_exposed_id, key, received_at, rolling_start_number, rolling_period, transmission_risk_level) values (100, ?, ?, ?, 144, 0)"; - PreparedStatement preparedStatement = connection.prepareStatement("insert " + sql); - preparedStatement.setString(1, key); - preparedStatement.setTimestamp(2, new Timestamp(receivedAt.toEpochMilli())); - preparedStatement.setInt(3, - (int) Duration.ofMillis(receivedAt.toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - preparedStatement.execute(); - } - - private void insertExposeeWithReceivedAtAndKeyDate(Instant receivedAt, Instant keyDate, String key) - throws SQLException { - Connection connection = dataSource.getConnection(); - String sql = "into t_gaen_exposed (pk_exposed_id, key, received_at, rolling_start_number, rolling_period, transmission_risk_level) values (100, ?, ?, ?, 144, 0)"; - PreparedStatement preparedStatement = connection.prepareStatement("insert " + sql); - preparedStatement.setString(1, key); - preparedStatement.setTimestamp(2, new Timestamp(receivedAt.toEpochMilli())); - preparedStatement.setInt(3, (int) GaenUnit.TenMinutes.between(Instant.ofEpochMilli(0), keyDate)); - preparedStatement.execute(); - } - - @NotNull - private Exposee createExposee(String key, String keyDate) { - Exposee exposee = new Exposee(); - exposee.setKey(key); - exposee.setKeyDate( - UTCInstant.parseDate("2014-01-28").getTimestamp()); - return exposee; - } - - private long getExposeeCount() throws SQLException { - try (final Connection connection = dataSource.getConnection(); - final PreparedStatement preparedStatement = connection - .prepareStatement("select count(*) from t_exposed"); - final ResultSet resultSet = preparedStatement.executeQuery()) { - resultSet.next(); - return resultSet.getLong(1); - } - } - - protected void executeSQL(String sql) throws SQLException { - try (final Connection connection = dataSource.getConnection(); - final PreparedStatement preparedStatement = connection.prepareStatement(sql);) { - preparedStatement.execute(); - } - } + private static final String APP_SOURCE = "test-app"; + private static final Duration BATCH_LENGTH = Duration.ofHours(2); + + @Autowired private GAENDataService gaenDataService; + @Autowired private FakeKeyService fakeKeyService; + + @Autowired private RedeemDataService redeemDataService; + + @Autowired private DataSource dataSource; + + @After + public void tearDown() throws SQLException { + executeSQL("truncate table t_exposed"); + executeSQL("truncate table t_redeem_uuid"); + } + + @Test + public void testFakeKeyContainsKeysForLast21Days() { + var today = UTCInstant.today(); + var noKeyAtThisDate = today.minusDays(22); + var keysUntilToday = today.minusDays(21); + + var keys = new ArrayList(); + var emptyList = fakeKeyService.fillUpKeys(keys, null, noKeyAtThisDate.getTimestamp()); + assertEquals(0, emptyList.size()); + do { + keys.clear(); + var list = fakeKeyService.fillUpKeys(keys, null, keysUntilToday.getTimestamp()); + + assertEquals(10, list.size()); + list = + fakeKeyService.fillUpKeys( + keys, UTCInstant.now().plusHours(3).getTimestamp(), keysUntilToday.getTimestamp()); + assertEquals(10, list.size()); + keysUntilToday = keysUntilToday.plusDays(1); + } while (keysUntilToday.isBeforeDateOf(today)); + + keys.clear(); + emptyList = fakeKeyService.fillUpKeys(keys, null, noKeyAtThisDate.getTimestamp()); + assertEquals(0, emptyList.size()); + } + + @Test + public void testRedeemUUID() { + boolean actual = + redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertTrue(actual); + actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertFalse(actual); + actual = redeemDataService.checkAndInsertPublishUUID("1c444adb-0924-4dc4-a7eb-1f52aa6b9575"); + assertTrue(actual); + } + + @Test + public void testTokensArentDeletedBeforeExpire() throws Exception { + var localDateNow = UTCInstant.today(); + Clock twoMinutesToMidnight = + Clock.fixed(localDateNow.plusDays(1).minusMinutes(2).getInstant(), ZoneOffset.UTC); + Clock twoMinutesAfterMidnight = + Clock.fixed(localDateNow.plusDays(1).plusMinutes(2).getInstant(), ZoneOffset.UTC); + Clock nextDay = + Clock.fixed(localDateNow.plusDays(2).plusMinutes(2).getInstant(), ZoneOffset.UTC); + + UTCInstant.setClock(twoMinutesToMidnight); + + boolean actual = + redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertTrue(actual); + + // token is still valid for 1 minute + UTCInstant.setClock(twoMinutesAfterMidnight); + + redeemDataService.cleanDB(Duration.ofDays(1)); + + actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertFalse(actual); + + UTCInstant.setClock(nextDay); + + redeemDataService.cleanDB(Duration.ofDays(1)); + + actual = redeemDataService.checkAndInsertPublishUUID("bc77d983-2359-48e8-835a-de673fe53ccb"); + assertTrue(actual); + UTCInstant.resetClock(); + } + + @Test + public void cleanup() throws SQLException { + var now = UTCInstant.now(); + var receivedAt = now.minusDays(21); + Connection connection = dataSource.getConnection(); + String key = "someKey"; + insertExposeeWithReceivedAtAndKeyDate( + receivedAt.getInstant(), receivedAt.minusDays(1).getInstant(), key); + + List sortedExposedForDay = + gaenDataService.getSortedExposedForKeyDate( + receivedAt.minusDays(1).getInstant().toEpochMilli(), + null, + now.getInstant().toEpochMilli()); + + assertFalse(sortedExposedForDay.isEmpty()); + + gaenDataService.cleanDB(Duration.ofDays(21)); + sortedExposedForDay = + gaenDataService.getSortedExposedForKeyDate( + receivedAt.minusDays(1).getInstant().toEpochMilli(), + null, + now.getInstant().toEpochMilli()); + + assertTrue(sortedExposedForDay.isEmpty()); + } + + @Test + public void upsert() throws Exception { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) UTCInstant.today().minus(Duration.ofDays(1)).get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + List keys = List.of(tmpKey); + + gaenDataService.upsertExposees(keys, UTCInstant.now()); + + long now = System.currentTimeMillis(); + // calculate exposed until bucket, but get bucket in the future, as keys have + // been inserted with timestamp now. + long publishedUntil = now - (now % BATCH_LENGTH.toMillis()) + BATCH_LENGTH.toMillis(); + + var returnedKeys = + gaenDataService.getSortedExposedForKeyDate( + UTCInstant.today().minus(Duration.ofDays(1)).getTimestamp(), null, publishedUntil); + + assertEquals(keys.size(), returnedKeys.size()); + assertEquals(keys.get(0).getKeyData(), returnedKeys.get(0).getKeyData()); + } + + @Test + public void testBatchReleaseTime() throws SQLException { + var receivedAt = UTCInstant.parseDateTime("2014-01-28T00:00:00"); + String key = "key555"; + insertExposeeWithReceivedAtAndKeyDate( + receivedAt.getInstant(), receivedAt.minus(Duration.ofDays(2)).getInstant(), key); + + var batchTime = UTCInstant.parseDateTime("2014-01-28T02:00:00"); + + var returnedKeys = + gaenDataService.getSortedExposedForKeyDate( + receivedAt.minus(Duration.ofDays(2)).getTimestamp(), null, batchTime.getTimestamp()); + + assertEquals(1, returnedKeys.size()); + GaenKey actual = returnedKeys.get(0); + assertEquals(actual.getKeyData(), key); + + int maxExposedIdForBatchReleaseTime = + gaenDataService.getMaxExposedIdForKeyDate( + receivedAt.minus(Duration.ofDays(2)).getTimestamp(), null, batchTime.getTimestamp()); + assertEquals(100, maxExposedIdForBatchReleaseTime); + + returnedKeys = + gaenDataService.getSortedExposedForKeyDate( + receivedAt.minus(Duration.ofDays(2)).getTimestamp(), + batchTime.getTimestamp(), + batchTime.plusHours(2).getTimestamp()); + assertEquals(0, returnedKeys.size()); + } + + private void insertExposeeWithReceivedAt(Instant receivedAt, String key) throws SQLException { + Connection connection = dataSource.getConnection(); + String sql = + "into t_gaen_exposed (pk_exposed_id, key, received_at, rolling_start_number," + + " rolling_period, transmission_risk_level) values (100, ?, ?, ?, 144, 0)"; + PreparedStatement preparedStatement = connection.prepareStatement("insert " + sql); + preparedStatement.setString(1, key); + preparedStatement.setTimestamp(2, new Timestamp(receivedAt.toEpochMilli())); + preparedStatement.setInt( + 3, (int) Duration.ofMillis(receivedAt.toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + preparedStatement.execute(); + } + + private void insertExposeeWithReceivedAtAndKeyDate( + Instant receivedAt, Instant keyDate, String key) throws SQLException { + Connection connection = dataSource.getConnection(); + String sql = + "into t_gaen_exposed (pk_exposed_id, key, received_at, rolling_start_number," + + " rolling_period, transmission_risk_level) values (100, ?, ?, ?, 144, 0)"; + PreparedStatement preparedStatement = connection.prepareStatement("insert " + sql); + preparedStatement.setString(1, key); + preparedStatement.setTimestamp(2, new Timestamp(receivedAt.toEpochMilli())); + preparedStatement.setInt( + 3, (int) GaenUnit.TenMinutes.between(Instant.ofEpochMilli(0), keyDate)); + preparedStatement.execute(); + } + + @NotNull + private Exposee createExposee(String key, String keyDate) { + Exposee exposee = new Exposee(); + exposee.setKey(key); + exposee.setKeyDate(UTCInstant.parseDate("2014-01-28").getTimestamp()); + return exposee; + } + + private long getExposeeCount() throws SQLException { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = + connection.prepareStatement("select count(*) from t_exposed"); + final ResultSet resultSet = preparedStatement.executeQuery()) { + resultSet.next(); + return resultSet.getLong(1); + } + } + + protected void executeSQL(String sql) throws SQLException { + try (final Connection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(sql); ) { + preparedStatement.execute(); + } + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/util/SingletonPostgresContainer.java b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/util/SingletonPostgresContainer.java index 1408db74..d4e3a673 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/util/SingletonPostgresContainer.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-data/src/test/java/org/dpppt/backend/sdk/data/util/SingletonPostgresContainer.java @@ -15,73 +15,74 @@ // JVM handles shut down public class SingletonPostgresContainer { - private static final String IMAGE_VERSION = "postgres:12"; - private static final String DB_URL = "DB_URL"; - private static final String DB_PORT = "DB_PORT"; - private static final String DB_USERNAME = "DB_USERNAME"; - private static final String DB_PASSWORD = "DB_PASSWORD"; - private static SingletonPostgresContainer INSTANCE; - - private PostgreSQLContainer container; - - private String jdbcUrl; - private String databaseName; - private String username; - private String password; - - private SingletonPostgresContainer() { - this.databaseName = "test-db"; - container = new PostgreSQLContainer<>(IMAGE_VERSION) + private static final String IMAGE_VERSION = "postgres:12"; + private static final String DB_URL = "DB_URL"; + private static final String DB_PORT = "DB_PORT"; + private static final String DB_USERNAME = "DB_USERNAME"; + private static final String DB_PASSWORD = "DB_PASSWORD"; + private static SingletonPostgresContainer INSTANCE; + + private PostgreSQLContainer container; + + private String jdbcUrl; + private String databaseName; + private String username; + private String password; + + private SingletonPostgresContainer() { + this.databaseName = "test-db"; + container = + new PostgreSQLContainer<>(IMAGE_VERSION) .withUsername("test") .withPassword("test") .withDatabaseName(this.databaseName); - } + } - public static SingletonPostgresContainer getInstance() { - if (INSTANCE == null) { - INSTANCE = new SingletonPostgresContainer(); - } - return INSTANCE; + public static SingletonPostgresContainer getInstance() { + if (INSTANCE == null) { + INSTANCE = new SingletonPostgresContainer(); } - - public void start() { - String baseUrl = "jdbc:postgresql://%s:%s/test-db"; - String dbUrl = System.getenv(DB_URL); - String dbPort = System.getenv(DB_PORT); - this.jdbcUrl = String.format(baseUrl, dbUrl, dbPort); - this.username = System.getenv(DB_USERNAME); - this.password = System.getenv(DB_PASSWORD); - - // avoid start container if is already up - if (System.getenv("SKIP_POSTGRES_CONTAINER") == null) { - container.start(); - this.jdbcUrl = container.getJdbcUrl(); - this.username = container.getUsername(); - this.password = container.getPassword(); - } - - System.setProperty(DB_URL, this.jdbcUrl); - System.setProperty(DB_USERNAME, this.username); - System.setProperty(DB_PASSWORD, this.password); + return INSTANCE; + } + + public void start() { + String baseUrl = "jdbc:postgresql://%s:%s/test-db"; + String dbUrl = System.getenv(DB_URL); + String dbPort = System.getenv(DB_PORT); + this.jdbcUrl = String.format(baseUrl, dbUrl, dbPort); + this.username = System.getenv(DB_USERNAME); + this.password = System.getenv(DB_PASSWORD); + + // avoid start container if is already up + if (System.getenv("SKIP_POSTGRES_CONTAINER") == null) { + container.start(); + this.jdbcUrl = container.getJdbcUrl(); + this.username = container.getUsername(); + this.password = container.getPassword(); } - public String getDriverClassName() { - return container.getDriverClassName(); - } + System.setProperty(DB_URL, this.jdbcUrl); + System.setProperty(DB_USERNAME, this.username); + System.setProperty(DB_PASSWORD, this.password); + } - public String getJdbcUrl() { - return jdbcUrl; - } + public String getDriverClassName() { + return container.getDriverClassName(); + } - public String getDatabaseName() { - return databaseName; - } + public String getJdbcUrl() { + return jdbcUrl; + } - public String getUsername() { - return username; - } + public String getDatabaseName() { + return databaseName; + } - public String getPassword() { - return password; - } + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Application.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Application.java index b60f3794..ba2620b2 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Application.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Application.java @@ -14,65 +14,58 @@ public class Application { - @NotNull - private String appId; - @NotNull - private String description; - @NotNull - private String backendBaseUrl; - @NotNull - private String listBaseUrl; - @NotNull - private String bleGattGuid; - @NotNull - private String contact; - - public String getAppId() { - return appId; - } - - public void setAppId(String appId) { - this.appId = appId; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getBackendBaseUrl() { - return backendBaseUrl; - } - - public void setBackendBaseUrl(String backendBaseUrl) { - this.backendBaseUrl = backendBaseUrl; - } - - public String getListBaseUrl() { - return listBaseUrl; - } - - public void setListBaseUrl(String listBaseUrl) { - this.listBaseUrl = listBaseUrl; - } - - public String getBleGattGuid() { - return bleGattGuid; - } - - public void setBleGattGuid(String bleGattGuid) { - this.bleGattGuid = bleGattGuid; - } - - public String getContact() { - return contact; - } - - public void setContact(String contact) { - this.contact = contact; - } - + @NotNull private String appId; + @NotNull private String description; + @NotNull private String backendBaseUrl; + @NotNull private String listBaseUrl; + @NotNull private String bleGattGuid; + @NotNull private String contact; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getBackendBaseUrl() { + return backendBaseUrl; + } + + public void setBackendBaseUrl(String backendBaseUrl) { + this.backendBaseUrl = backendBaseUrl; + } + + public String getListBaseUrl() { + return listBaseUrl; + } + + public void setListBaseUrl(String listBaseUrl) { + this.listBaseUrl = listBaseUrl; + } + + public String getBleGattGuid() { + return bleGattGuid; + } + + public void setBleGattGuid(String bleGattGuid) { + this.bleGattGuid = bleGattGuid; + } + + public String getContact() { + return contact; + } + + public void setContact(String contact) { + this.contact = contact; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/AuthDataMethod.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/AuthDataMethod.java index 5d2989f4..94d66124 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/AuthDataMethod.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/AuthDataMethod.java @@ -11,6 +11,6 @@ package org.dpppt.backend.sdk.model; public enum AuthDataMethod { - - NONE, REDEEM_CODE; + NONE, + REDEEM_CODE; } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/BucketList.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/BucketList.java index 215092b8..f195e3bd 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/BucketList.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/BucketList.java @@ -14,17 +14,20 @@ import java.util.List; public class BucketList { - List buckets; - public List getBuckets() { - return buckets; - } - public void setBuckets(List buckets) { - this.buckets = buckets; - } - public void addBucket(Long bucket) { - if(this.buckets == null) { - this.buckets = new ArrayList(); - } - this.buckets.add(bucket); + List buckets; + + public List getBuckets() { + return buckets; + } + + public void setBuckets(List buckets) { + this.buckets = buckets; + } + + public void addBucket(Long bucket) { + if (this.buckets == null) { + this.buckets = new ArrayList(); } -} \ No newline at end of file + this.buckets.add(bucket); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedKey.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedKey.java index ae28edce..7eb77d4a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedKey.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedKey.java @@ -4,26 +4,25 @@ import javax.validation.constraints.Size; public class ExposedKey { - @NotNull - @Size(min = 24, max = 44) - private String key; + @NotNull + @Size(min = 24, max = 44) + private String key; - @NotNull - private long keyDate; + @NotNull private long keyDate; - public String getKey() { - return key; - } + public String getKey() { + return key; + } - public void setKey(String key) { - this.key = key; - } + public void setKey(String key) { + this.key = key; + } - public long getKeyDate() { - return keyDate; - } + public long getKeyDate() { + return keyDate; + } - public void setKeyDate(long keyDate) { - this.keyDate = keyDate; - } -} \ No newline at end of file + public void setKeyDate(long keyDate) { + this.keyDate = keyDate; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedOverview.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedOverview.java index 044a443b..58343130 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedOverview.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposedOverview.java @@ -15,30 +15,29 @@ public class ExposedOverview { - private Long batchReleaseTime; + private Long batchReleaseTime; - private List exposed = new ArrayList<>(); + private List exposed = new ArrayList<>(); - public ExposedOverview() { - } + public ExposedOverview() {} - public Long getBatchReleaseTime() { - return batchReleaseTime; - } + public Long getBatchReleaseTime() { + return batchReleaseTime; + } - public void setBatchReleaseTime(Long batchReleaseTime) { - this.batchReleaseTime = batchReleaseTime; - } + public void setBatchReleaseTime(Long batchReleaseTime) { + this.batchReleaseTime = batchReleaseTime; + } - public ExposedOverview(List exposed) { - this.exposed = exposed; - } + public ExposedOverview(List exposed) { + this.exposed = exposed; + } - public List getExposed() { - return exposed; - } + public List getExposed() { + return exposed; + } - public void setExposed(List exposed) { - this.exposed = exposed; - } + public void setExposed(List exposed) { + this.exposed = exposed; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Exposee.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Exposee.java index cc4f9cf9..786c6a8d 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Exposee.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/Exposee.java @@ -10,42 +10,38 @@ package org.dpppt.backend.sdk.model; -import javax.validation.constraints.NotNull; - import com.fasterxml.jackson.annotation.JsonIgnore; +import javax.validation.constraints.NotNull; public class Exposee { - @JsonIgnore - private Integer Id; + @JsonIgnore private Integer Id; - @NotNull - private String key; + @NotNull private String key; - @NotNull - private long keyDate; + @NotNull private long keyDate; - public String getKey() { - return key; - } + public String getKey() { + return key; + } - public void setKey(String key) { - this.key = key; - } + public void setKey(String key) { + this.key = key; + } - @JsonIgnore - public Integer getId() { - return Id; - } + @JsonIgnore + public Integer getId() { + return Id; + } - public void setId(Integer id) { - Id = id; - } + public void setId(Integer id) { + Id = id; + } - public long getKeyDate() { - return keyDate; - } + public long getKeyDate() { + return keyDate; + } - public void setKeyDate(long keyDate) { - this.keyDate = keyDate; - } + public void setKeyDate(long keyDate) { + this.keyDate = keyDate; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeAuthData.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeAuthData.java index 07cd117e..2a43b19d 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeAuthData.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeAuthData.java @@ -12,13 +12,13 @@ public class ExposeeAuthData { - private String value; + private String value; - public String getValue() { - return value; - } + public String getValue() { + return value; + } - public void setValue(String value) { - this.value = value; - } + public void setValue(String value) { + this.value = value; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequest.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequest.java index fa903d9d..6349ed62 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequest.java @@ -15,46 +15,45 @@ public class ExposeeRequest { - private Integer fake = 0; + private Integer fake = 0; - @NotNull - @Size(min = 24, max = 44) - private String key; + @NotNull + @Size(min = 24, max = 44) + private String key; - @NotNull - private long keyDate; + @NotNull private long keyDate; - private ExposeeAuthData authData; + private ExposeeAuthData authData; - public String getKey() { - return key; - } + public String getKey() { + return key; + } - public void setKey(String key) { - this.key = key; - } + public void setKey(String key) { + this.key = key; + } - public ExposeeAuthData getAuthData() { - return authData; - } + public ExposeeAuthData getAuthData() { + return authData; + } - public void setAuthData(ExposeeAuthData authData) { - this.authData = authData; - } + public void setAuthData(ExposeeAuthData authData) { + this.authData = authData; + } - public long getKeyDate() { - return keyDate; - } + public long getKeyDate() { + return keyDate; + } - public void setKeyDate(long keyDate) { - this.keyDate = keyDate; - } + public void setKeyDate(long keyDate) { + this.keyDate = keyDate; + } - public Integer isFake() { - return fake; - } + public Integer isFake() { + return fake; + } - public void setIsFake(Integer fake) { - this.fake = fake; - } + public void setIsFake(Integer fake) { + this.fake = fake; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequestList.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequestList.java index 0373f35c..7921f9e1 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequestList.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/ExposeeRequestList.java @@ -1,30 +1,27 @@ package org.dpppt.backend.sdk.model; import java.util.List; - import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; public class ExposeeRequestList { - @NotNull - @NotEmpty - List<@NotNull ExposedKey> exposedKeys; + @NotNull @NotEmpty List<@NotNull ExposedKey> exposedKeys; - private Integer fake = 0; + private Integer fake = 0; - public List getExposedKeys() { - return exposedKeys; - } + public List getExposedKeys() { + return exposedKeys; + } - public Integer isFake() { - return fake; - } + public Integer isFake() { + return fake; + } - public void setFake(Integer fake) { - this.fake = fake; - } + public void setFake(Integer fake) { + this.fake = fake; + } - public void setExposedKeys(List exposedKeys) { - this.exposedKeys = exposedKeys; - } -} \ No newline at end of file + public void setExposedKeys(List exposedKeys) { + this.exposedKeys = exposedKeys; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/DayBuckets.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/DayBuckets.java index 38d43bc3..432c829d 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/DayBuckets.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/DayBuckets.java @@ -1,49 +1,56 @@ package org.dpppt.backend.sdk.model.gaen; import ch.ubique.openapi.docannotations.Documentation; - import java.util.List; -@Documentation(description = "DayBuckets holds a list of all available release buckets of a given day.\n" + - "The release buckets are stored as relative URLs to the base URL (currently /v1/gaen)\n" + - "and can be used to get the exposed keys starting from this release bucket.") +@Documentation( + description = + "DayBuckets holds a list of all available release buckets of a given day.\n" + + "The release buckets are stored as relative URLs to the base URL (currently" + + " /v1/gaen)\n" + + "and can be used to get the exposed keys starting from this release bucket.") public class DayBuckets { - @Documentation(description = "The day of all buckets, as midnight in milliseconds since the Unix epoch (1970-01-01)", - example = "1593043200000") - private Long dayTimestamp; - @Documentation(description = "The day as given by the request in /v1/gaen/buckets/{dayDateStr}", - example = "2020-06-27") - private String day; - @Documentation(description = "Relative URLs for the available release buckets", - example = "['/exposed/1593043200000', '/exposed/1593046800000'") - private List relativeUrls; - - public String getDay() { - return this.day; - } - - public List getRelativeUrls() { - return this.relativeUrls; - } - - public Long getDayTimestamp() { - return dayTimestamp; - } - - public DayBuckets setDay(String day) { - this.day = day; - return this; - } - - public DayBuckets setRelativeUrls(List relativeUrls) { - this.relativeUrls = relativeUrls; - return this; - } - - public DayBuckets setDayTimestamp(Long dayTimestamp) { - this.dayTimestamp = dayTimestamp; - return this; - } - -} \ No newline at end of file + @Documentation( + description = + "The day of all buckets, as midnight in milliseconds since the Unix epoch (1970-01-01)", + example = "1593043200000") + private Long dayTimestamp; + + @Documentation( + description = "The day as given by the request in /v1/gaen/buckets/{dayDateStr}", + example = "2020-06-27") + private String day; + + @Documentation( + description = "Relative URLs for the available release buckets", + example = "['/exposed/1593043200000', '/exposed/1593046800000'") + private List relativeUrls; + + public String getDay() { + return this.day; + } + + public List getRelativeUrls() { + return this.relativeUrls; + } + + public Long getDayTimestamp() { + return dayTimestamp; + } + + public DayBuckets setDay(String day) { + this.day = day; + return this; + } + + public DayBuckets setRelativeUrls(List relativeUrls) { + this.relativeUrls = relativeUrls; + return this; + } + + public DayBuckets setDayTimestamp(Long dayTimestamp) { + this.dayTimestamp = dayTimestamp; + return this; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenKey.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenKey.java index 3a045cca..8beec136 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenKey.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenKey.java @@ -1,85 +1,95 @@ package org.dpppt.backend.sdk.model.gaen; import ch.ubique.openapi.docannotations.Documentation; - import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** - * A GaenKey is a Temporary Exposure Key of a person being infected, so it's also an Exposed Key. - * To protect timing attacks, a key can be invalidated by the client by setting _fake_ to 1. + * A GaenKey is a Temporary Exposure Key of a person being infected, so it's also an Exposed Key. To + * protect timing attacks, a key can be invalidated by the client by setting _fake_ to 1. */ public class GaenKey { - public final static Integer GaenKeyDefaultRollingPeriod = 144; - - @NotNull - @Size(min = 24, max = 24) - @Documentation(description = "Represents the 16-byte Temporary Exposure Key in base64") - private String keyData; - - @NotNull - @Documentation(description = "The ENIntervalNumber as number of 10-minute intervals since the Unix epoch (1970-01-01)") - private Integer rollingStartNumber; - - @NotNull - @Documentation(description = "The TEKRollingPeriod indicates for how many 10-minute intervals the Temporary Exposure Key is valid") - private Integer rollingPeriod; - - @NotNull - @Documentation(description = "According to the Google API description a value between 0 and 4096, with higher values indicating a higher risk") - private Integer transmissionRiskLevel; - - @Documentation(description = "If fake = 0, the key is a valid key. If fake = 1, the key will be discarded.") - private Integer fake = 0; - - public GaenKey() { - } - - public GaenKey(String keyData, Integer rollingStartNumber, Integer rollingPeriod, Integer transmissionRiskLevel) { - this.keyData = keyData; - this.rollingStartNumber = rollingStartNumber; - this.rollingPeriod = rollingPeriod; - this.transmissionRiskLevel = transmissionRiskLevel; - } - - public String getKeyData() { - return this.keyData; - } - - public void setKeyData(String keyData) { - this.keyData = keyData; - } - - public Integer getRollingStartNumber() { - return this.rollingStartNumber; - } - - public void setRollingStartNumber(Integer rollingStartNumber) { - this.rollingStartNumber = rollingStartNumber; - } - - public Integer getRollingPeriod() { - return this.rollingPeriod; - } - - public void setRollingPeriod(Integer rollingPeriod) { - this.rollingPeriod = rollingPeriod; - } - - public Integer getTransmissionRiskLevel() { - return this.transmissionRiskLevel; - } - - public void setTransmissionRiskLevel(Integer transmissionRiskLevel) { - this.transmissionRiskLevel = transmissionRiskLevel; - } - - public Integer getFake() { - return this.fake; - } - - public void setFake(Integer fake) { - this.fake = fake; - } - -} \ No newline at end of file + public static final Integer GaenKeyDefaultRollingPeriod = 144; + + @NotNull + @Size(min = 24, max = 24) + @Documentation(description = "Represents the 16-byte Temporary Exposure Key in base64") + private String keyData; + + @NotNull + @Documentation( + description = + "The ENIntervalNumber as number of 10-minute intervals since the Unix epoch (1970-01-01)") + private Integer rollingStartNumber; + + @NotNull + @Documentation( + description = + "The TEKRollingPeriod indicates for how many 10-minute intervals the Temporary Exposure" + + " Key is valid") + private Integer rollingPeriod; + + @NotNull + @Documentation( + description = + "According to the Google API description a value between 0 and 4096, with higher values" + + " indicating a higher risk") + private Integer transmissionRiskLevel; + + @Documentation( + description = "If fake = 0, the key is a valid key. If fake = 1, the key will be discarded.") + private Integer fake = 0; + + public GaenKey() {} + + public GaenKey( + String keyData, + Integer rollingStartNumber, + Integer rollingPeriod, + Integer transmissionRiskLevel) { + this.keyData = keyData; + this.rollingStartNumber = rollingStartNumber; + this.rollingPeriod = rollingPeriod; + this.transmissionRiskLevel = transmissionRiskLevel; + } + + public String getKeyData() { + return this.keyData; + } + + public void setKeyData(String keyData) { + this.keyData = keyData; + } + + public Integer getRollingStartNumber() { + return this.rollingStartNumber; + } + + public void setRollingStartNumber(Integer rollingStartNumber) { + this.rollingStartNumber = rollingStartNumber; + } + + public Integer getRollingPeriod() { + return this.rollingPeriod; + } + + public void setRollingPeriod(Integer rollingPeriod) { + this.rollingPeriod = rollingPeriod; + } + + public Integer getTransmissionRiskLevel() { + return this.transmissionRiskLevel; + } + + public void setTransmissionRiskLevel(Integer transmissionRiskLevel) { + this.transmissionRiskLevel = transmissionRiskLevel; + } + + public Integer getFake() { + return this.fake; + } + + public void setFake(Integer fake) { + this.fake = fake; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenRequest.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenRequest.java index 9dd34c78..cf4088f2 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenRequest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenRequest.java @@ -1,45 +1,53 @@ package org.dpppt.backend.sdk.model.gaen; import ch.ubique.openapi.docannotations.Documentation; - import java.util.List; - import javax.validation.Valid; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** - * GaenRequest represents a request made by the client to the backend-server. - * It is used to publish the _Exposed Keys_ to the backend server. - * As the GAEN API on the mobile phones never release the current day's key, the - * client can set _delayedKeyDate_ to indicate a delayed key. + * GaenRequest represents a request made by the client to the backend-server. It is used to publish + * the _Exposed Keys_ to the backend server. As the GAEN API on the mobile phones never release the + * current day's key, the client can set _delayedKeyDate_ to indicate a delayed key. */ public class GaenRequest { - @NotNull - @NotEmpty - @Valid - @Size(min = 14, max = 30) - @Documentation(description = "Between 14 and 30 Temporary Exposure Keys - zero or more of them might be fake keys. Starting with EN 1.5 it is possible that clients send more than 14 keys.") - private List gaenKeys; - - @NotNull - @Documentation(description = "Prior to version 1.5 Exposure Keys for the day of report weren't available (since they were still used throughout this day RPI=144), so the submission of the last key had to be delayed. This Unix timestamp in milliseconds specifies, which key date the last key (which will be submitted on the next day) will have. The backend then issues a JWT to allow the submission of this last key with specified key date. This should not be necessary after the Exposure Framework is able to send and handle keys with RollingPeriod < 144 (e.g. only valid until submission).") - private Integer delayedKeyDate; - - public List getGaenKeys() { - return this.gaenKeys; - } - - public void setGaenKeys(List gaenKeys) { - this.gaenKeys = gaenKeys; - } - - public Integer getDelayedKeyDate() { - return this.delayedKeyDate; - } - - public void setDelayedKeyDate(Integer delayedKeyDate) { - this.delayedKeyDate = delayedKeyDate; - } -} \ No newline at end of file + @NotNull + @NotEmpty + @Valid + @Size(min = 14, max = 30) + @Documentation( + description = + "Between 14 and 30 Temporary Exposure Keys - zero or more of them might be fake keys." + + " Starting with EN 1.5 it is possible that clients send more than 14 keys.") + private List gaenKeys; + + @NotNull + @Documentation( + description = + "Prior to version 1.5 Exposure Keys for the day of report weren't available (since they" + + " were still used throughout this day RPI=144), so the submission of the last key" + + " had to be delayed. This Unix timestamp in milliseconds specifies, which key date" + + " the last key (which will be submitted on the next day) will have. The backend" + + " then issues a JWT to allow the submission of this last key with specified key" + + " date. This should not be necessary after the Exposure Framework is able to send" + + " and handle keys with RollingPeriod < 144 (e.g. only valid until submission).") + private Integer delayedKeyDate; + + public List getGaenKeys() { + return this.gaenKeys; + } + + public void setGaenKeys(List gaenKeys) { + this.gaenKeys = gaenKeys; + } + + public Integer getDelayedKeyDate() { + return this.delayedKeyDate; + } + + public void setDelayedKeyDate(Integer delayedKeyDate) { + this.delayedKeyDate = delayedKeyDate; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenSecondDay.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenSecondDay.java index 7d85aa05..32bd8113 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenSecondDay.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenSecondDay.java @@ -4,16 +4,13 @@ import javax.validation.constraints.NotNull; public class GaenSecondDay { - @NotNull - @Valid - private GaenKey delayedKey; + @NotNull @Valid private GaenKey delayedKey; - public GaenKey getDelayedKey() { - return this.delayedKey; - } + public GaenKey getDelayedKey() { + return this.delayedKey; + } - public void setDelayedKey(GaenKey delayedKey) { - this.delayedKey = delayedKey; - } - -} \ No newline at end of file + public void setDelayedKey(GaenKey delayedKey) { + this.delayedKey = delayedKey; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenUnit.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenUnit.java index 262c1b36..3c783443 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenUnit.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/GaenUnit.java @@ -16,40 +16,39 @@ public class GaenUnit implements TemporalUnit { - public static GaenUnit TenMinutes = new GaenUnit(); - - private static final int GAEN_MINUTES = 10; - - @Override - public Duration getDuration() { - - return Duration.ofMinutes(GAEN_MINUTES); - } - - @Override - public boolean isDurationEstimated() { - return false; - } - - @Override - public boolean isDateBased() { - return false; - } - - @Override - public boolean isTimeBased() { - return true; - } - - @Override - @SuppressWarnings("unchecked") - public R addTo(R temporal, long amount) { - return (R) temporal.plus(this.getDuration().multipliedBy(amount)); - } - - @Override - public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) { - return ChronoUnit.MINUTES.between(temporal1Inclusive, temporal2Exclusive) / GAEN_MINUTES; - } - -} \ No newline at end of file + public static GaenUnit TenMinutes = new GaenUnit(); + + private static final int GAEN_MINUTES = 10; + + @Override + public Duration getDuration() { + + return Duration.ofMinutes(GAEN_MINUTES); + } + + @Override + public boolean isDurationEstimated() { + return false; + } + + @Override + public boolean isDateBased() { + return false; + } + + @Override + public boolean isTimeBased() { + return true; + } + + @Override + @SuppressWarnings("unchecked") + public R addTo(R temporal, long amount) { + return (R) temporal.plus(this.getDuration().multipliedBy(amount)); + } + + @Override + public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) { + return ChronoUnit.MINUTES.between(temporal1Inclusive, temporal2Exclusive) / GAEN_MINUTES; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/FileProto.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/FileProto.java index 3e0b4e9b..962b19a5 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/FileProto.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/FileProto.java @@ -4,77 +4,56 @@ public final class FileProto { private FileProto() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) {} + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); } - public interface FileOrBuilder extends + + public interface FileOrBuilder + extends // @@protoc_insertion_point(interface_extends:File) com.google.protobuf.MessageOrBuilder { - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ boolean hasHeader(); - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ FileProto.Header getHeader(); - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ FileProto.HeaderOrBuilder getHeaderOrBuilder(); - /** - * repeated .Key key = 2; - */ - java.util.List - getKeyList(); - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ + java.util.List getKeyList(); + /** repeated .Key key = 2; */ FileProto.Key getKey(int index); - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ int getKeyCount(); - /** - * repeated .Key key = 2; - */ - java.util.List - getKeyOrBuilderList(); - /** - * repeated .Key key = 2; - */ - FileProto.KeyOrBuilder getKeyOrBuilder( - int index); + /** repeated .Key key = 2; */ + java.util.List getKeyOrBuilderList(); + /** repeated .Key key = 2; */ + FileProto.KeyOrBuilder getKeyOrBuilder(int index); } - /** - * Protobuf type {@code File} - */ - public static final class File extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code File} */ + public static final class File extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:File) FileOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use File.newBuilder() to construct. private File(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private File() { key_ = java.util.Collections.emptyList(); } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private File( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -94,42 +73,42 @@ private File( case 0: done = true; break; - case 10: { - FileProto.Header.Builder subBuilder = null; - if (((bitField0_ & 0x00000001) != 0)) { - subBuilder = header_.toBuilder(); - } - header_ = input.readMessage(FileProto.Header.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(header_); - header_ = subBuilder.buildPartial(); + case 10: + { + FileProto.Header.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) != 0)) { + subBuilder = header_.toBuilder(); + } + header_ = input.readMessage(FileProto.Header.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(header_); + header_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; } - bitField0_ |= 0x00000001; - break; - } - case 18: { - if (!((mutable_bitField0_ & 0x00000002) != 0)) { - key_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000002; + case 18: + { + if (!((mutable_bitField0_ & 0x00000002) != 0)) { + key_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000002; + } + key_.add(input.readMessage(FileProto.Key.PARSER, extensionRegistry)); + break; } - key_.add( - input.readMessage(FileProto.Key.PARSER, extensionRegistry)); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { if (((mutable_bitField0_ & 0x00000002) != 0)) { key_ = java.util.Collections.unmodifiableList(key_); @@ -138,77 +117,59 @@ private File( makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return FileProto.internal_static_File_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return FileProto.internal_static_File_fieldAccessorTable - .ensureFieldAccessorsInitialized( - FileProto.File.class, FileProto.File.Builder.class); + return FileProto.internal_static_File_fieldAccessorTable.ensureFieldAccessorsInitialized( + FileProto.File.class, FileProto.File.Builder.class); } private int bitField0_; public static final int HEADER_FIELD_NUMBER = 1; private FileProto.Header header_; - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public boolean hasHeader() { return ((bitField0_ & 0x00000001) != 0); } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public FileProto.Header getHeader() { return header_ == null ? FileProto.Header.getDefaultInstance() : header_; } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public FileProto.HeaderOrBuilder getHeaderOrBuilder() { return header_ == null ? FileProto.Header.getDefaultInstance() : header_; } public static final int KEY_FIELD_NUMBER = 2; private java.util.List key_; - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public java.util.List getKeyList() { return key_; } - /** - * repeated .Key key = 2; - */ - public java.util.List - getKeyOrBuilderList() { + /** repeated .Key key = 2; */ + public java.util.List getKeyOrBuilderList() { return key_; } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public int getKeyCount() { return key_.size(); } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public FileProto.Key getKey(int index) { return key_.get(index); } - /** - * repeated .Key key = 2; - */ - public FileProto.KeyOrBuilder getKeyOrBuilder( - int index) { + /** repeated .Key key = 2; */ + public FileProto.KeyOrBuilder getKeyOrBuilder(int index) { return key_.get(index); } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -220,8 +181,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { output.writeMessage(1, getHeader()); } @@ -238,12 +198,10 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, getHeader()); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, getHeader()); } for (int i = 0; i < key_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, key_.get(i)); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, key_.get(i)); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -253,7 +211,7 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof FileProto.File)) { return super.equals(obj); @@ -262,11 +220,9 @@ public boolean equals(final java.lang.Object obj) { if (hasHeader() != other.hasHeader()) return false; if (hasHeader()) { - if (!getHeader() - .equals(other.getHeader())) return false; + if (!getHeader().equals(other.getHeader())) return false; } - if (!getKeyList() - .equals(other.getKeyList())) return false; + if (!getKeyList().equals(other.getKeyList())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @@ -291,88 +247,92 @@ public int hashCode() { return hash; } - public static FileProto.File parseFrom( - java.nio.ByteBuffer data) + public static FileProto.File parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.File parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static FileProto.File parseFrom( - com.google.protobuf.ByteString data) + + public static FileProto.File parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.File parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static FileProto.File parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.File parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static FileProto.File parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static FileProto.File parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static FileProto.File parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } + public static FileProto.File parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static FileProto.File parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } - public static FileProto.File parseFrom( - com.google.protobuf.CodedInputStream input) + + public static FileProto.File parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static FileProto.File parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(FileProto.File prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -381,24 +341,21 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code File} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code File} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:File) FileProto.FileOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return FileProto.internal_static_File_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return FileProto.internal_static_File_fieldAccessorTable - .ensureFieldAccessorsInitialized( - FileProto.File.class, FileProto.File.Builder.class); + return FileProto.internal_static_File_fieldAccessorTable.ensureFieldAccessorsInitialized( + FileProto.File.class, FileProto.File.Builder.class); } // Construct using FileOuterClass.File.newBuilder() @@ -406,18 +363,18 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { getHeaderFieldBuilder(); getKeyFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); @@ -437,8 +394,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return FileProto.internal_static_File_descriptor; } @@ -487,38 +443,41 @@ public FileProto.File buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof FileProto.File) { - return mergeFrom((FileProto.File)other); + return mergeFrom((FileProto.File) other); } else { super.mergeFrom(other); return this; @@ -548,9 +507,10 @@ public Builder mergeFrom(FileProto.File other) { keyBuilder_ = null; key_ = other.key_; bitField0_ = (bitField0_ & ~0x00000002); - keyBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getKeyFieldBuilder() : null; + keyBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders + ? getKeyFieldBuilder() + : null; } else { keyBuilder_.addAllMessages(other.key_); } @@ -584,20 +544,18 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private FileProto.Header header_; private com.google.protobuf.SingleFieldBuilderV3< - FileProto.Header, FileProto.Header.Builder, FileProto.HeaderOrBuilder> headerBuilder_; - /** - * optional .Header header = 1; - */ + FileProto.Header, FileProto.Header.Builder, FileProto.HeaderOrBuilder> + headerBuilder_; + /** optional .Header header = 1; */ public boolean hasHeader() { return ((bitField0_ & 0x00000001) != 0); } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public FileProto.Header getHeader() { if (headerBuilder_ == null) { return header_ == null ? FileProto.Header.getDefaultInstance() : header_; @@ -605,9 +563,7 @@ public FileProto.Header getHeader() { return headerBuilder_.getMessage(); } } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public Builder setHeader(FileProto.Header value) { if (headerBuilder_ == null) { if (value == null) { @@ -621,11 +577,8 @@ public Builder setHeader(FileProto.Header value) { bitField0_ |= 0x00000001; return this; } - /** - * optional .Header header = 1; - */ - public Builder setHeader( - FileProto.Header.Builder builderForValue) { + /** optional .Header header = 1; */ + public Builder setHeader(FileProto.Header.Builder builderForValue) { if (headerBuilder_ == null) { header_ = builderForValue.build(); onChanged(); @@ -635,16 +588,13 @@ public Builder setHeader( bitField0_ |= 0x00000001; return this; } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public Builder mergeHeader(FileProto.Header value) { if (headerBuilder_ == null) { - if (((bitField0_ & 0x00000001) != 0) && - header_ != null && - header_ != FileProto.Header.getDefaultInstance()) { - header_ = - FileProto.Header.newBuilder(header_).mergeFrom(value).buildPartial(); + if (((bitField0_ & 0x00000001) != 0) + && header_ != null + && header_ != FileProto.Header.getDefaultInstance()) { + header_ = FileProto.Header.newBuilder(header_).mergeFrom(value).buildPartial(); } else { header_ = value; } @@ -655,9 +605,7 @@ public Builder mergeHeader(FileProto.Header value) { bitField0_ |= 0x00000001; return this; } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public Builder clearHeader() { if (headerBuilder_ == null) { header_ = null; @@ -668,57 +616,48 @@ public Builder clearHeader() { bitField0_ = (bitField0_ & ~0x00000001); return this; } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public FileProto.Header.Builder getHeaderBuilder() { bitField0_ |= 0x00000001; onChanged(); return getHeaderFieldBuilder().getBuilder(); } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ public FileProto.HeaderOrBuilder getHeaderOrBuilder() { if (headerBuilder_ != null) { return headerBuilder_.getMessageOrBuilder(); } else { - return header_ == null ? - FileProto.Header.getDefaultInstance() : header_; + return header_ == null ? FileProto.Header.getDefaultInstance() : header_; } } - /** - * optional .Header header = 1; - */ + /** optional .Header header = 1; */ private com.google.protobuf.SingleFieldBuilderV3< - FileProto.Header, FileProto.Header.Builder, FileProto.HeaderOrBuilder> + FileProto.Header, FileProto.Header.Builder, FileProto.HeaderOrBuilder> getHeaderFieldBuilder() { if (headerBuilder_ == null) { - headerBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - FileProto.Header, FileProto.Header.Builder, FileProto.HeaderOrBuilder>( - getHeader(), - getParentForChildren(), - isClean()); + headerBuilder_ = + new com.google.protobuf.SingleFieldBuilderV3< + FileProto.Header, FileProto.Header.Builder, FileProto.HeaderOrBuilder>( + getHeader(), getParentForChildren(), isClean()); header_ = null; } return headerBuilder_; } - private java.util.List key_ = - java.util.Collections.emptyList(); + private java.util.List key_ = java.util.Collections.emptyList(); + private void ensureKeyIsMutable() { if (!((bitField0_ & 0x00000002) != 0)) { key_ = new java.util.ArrayList(key_); bitField0_ |= 0x00000002; - } + } } private com.google.protobuf.RepeatedFieldBuilderV3< - FileProto.Key, FileProto.Key.Builder, FileProto.KeyOrBuilder> keyBuilder_; + FileProto.Key, FileProto.Key.Builder, FileProto.KeyOrBuilder> + keyBuilder_; - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public java.util.List getKeyList() { if (keyBuilder_ == null) { return java.util.Collections.unmodifiableList(key_); @@ -726,9 +665,7 @@ public java.util.List getKeyList() { return keyBuilder_.getMessageList(); } } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public int getKeyCount() { if (keyBuilder_ == null) { return key_.size(); @@ -736,9 +673,7 @@ public int getKeyCount() { return keyBuilder_.getCount(); } } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public FileProto.Key getKey(int index) { if (keyBuilder_ == null) { return key_.get(index); @@ -746,11 +681,8 @@ public FileProto.Key getKey(int index) { return keyBuilder_.getMessage(index); } } - /** - * repeated .Key key = 2; - */ - public Builder setKey( - int index, FileProto.Key value) { + /** repeated .Key key = 2; */ + public Builder setKey(int index, FileProto.Key value) { if (keyBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -763,11 +695,8 @@ public Builder setKey( } return this; } - /** - * repeated .Key key = 2; - */ - public Builder setKey( - int index, FileProto.Key.Builder builderForValue) { + /** repeated .Key key = 2; */ + public Builder setKey(int index, FileProto.Key.Builder builderForValue) { if (keyBuilder_ == null) { ensureKeyIsMutable(); key_.set(index, builderForValue.build()); @@ -777,9 +706,7 @@ public Builder setKey( } return this; } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public Builder addKey(FileProto.Key value) { if (keyBuilder_ == null) { if (value == null) { @@ -793,11 +720,8 @@ public Builder addKey(FileProto.Key value) { } return this; } - /** - * repeated .Key key = 2; - */ - public Builder addKey( - int index, FileProto.Key value) { + /** repeated .Key key = 2; */ + public Builder addKey(int index, FileProto.Key value) { if (keyBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -810,11 +734,8 @@ public Builder addKey( } return this; } - /** - * repeated .Key key = 2; - */ - public Builder addKey( - FileProto.Key.Builder builderForValue) { + /** repeated .Key key = 2; */ + public Builder addKey(FileProto.Key.Builder builderForValue) { if (keyBuilder_ == null) { ensureKeyIsMutable(); key_.add(builderForValue.build()); @@ -824,11 +745,8 @@ public Builder addKey( } return this; } - /** - * repeated .Key key = 2; - */ - public Builder addKey( - int index, FileProto.Key.Builder builderForValue) { + /** repeated .Key key = 2; */ + public Builder addKey(int index, FileProto.Key.Builder builderForValue) { if (keyBuilder_ == null) { ensureKeyIsMutable(); key_.add(index, builderForValue.build()); @@ -838,24 +756,18 @@ public Builder addKey( } return this; } - /** - * repeated .Key key = 2; - */ - public Builder addAllKey( - java.lang.Iterable values) { + /** repeated .Key key = 2; */ + public Builder addAllKey(java.lang.Iterable values) { if (keyBuilder_ == null) { ensureKeyIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, key_); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, key_); onChanged(); } else { keyBuilder_.addAllMessages(values); } return this; } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public Builder clearKey() { if (keyBuilder_ == null) { key_ = java.util.Collections.emptyList(); @@ -866,9 +778,7 @@ public Builder clearKey() { } return this; } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public Builder removeKey(int index) { if (keyBuilder_ == null) { ensureKeyIsMutable(); @@ -879,70 +789,52 @@ public Builder removeKey(int index) { } return this; } - /** - * repeated .Key key = 2; - */ - public FileProto.Key.Builder getKeyBuilder( - int index) { + /** repeated .Key key = 2; */ + public FileProto.Key.Builder getKeyBuilder(int index) { return getKeyFieldBuilder().getBuilder(index); } - /** - * repeated .Key key = 2; - */ - public FileProto.KeyOrBuilder getKeyOrBuilder( - int index) { + /** repeated .Key key = 2; */ + public FileProto.KeyOrBuilder getKeyOrBuilder(int index) { if (keyBuilder_ == null) { - return key_.get(index); } else { + return key_.get(index); + } else { return keyBuilder_.getMessageOrBuilder(index); } } - /** - * repeated .Key key = 2; - */ - public java.util.List - getKeyOrBuilderList() { + /** repeated .Key key = 2; */ + public java.util.List getKeyOrBuilderList() { if (keyBuilder_ != null) { return keyBuilder_.getMessageOrBuilderList(); } else { return java.util.Collections.unmodifiableList(key_); } } - /** - * repeated .Key key = 2; - */ + /** repeated .Key key = 2; */ public FileProto.Key.Builder addKeyBuilder() { - return getKeyFieldBuilder().addBuilder( - FileProto.Key.getDefaultInstance()); + return getKeyFieldBuilder().addBuilder(FileProto.Key.getDefaultInstance()); } - /** - * repeated .Key key = 2; - */ - public FileProto.Key.Builder addKeyBuilder( - int index) { - return getKeyFieldBuilder().addBuilder( - index, FileProto.Key.getDefaultInstance()); + /** repeated .Key key = 2; */ + public FileProto.Key.Builder addKeyBuilder(int index) { + return getKeyFieldBuilder().addBuilder(index, FileProto.Key.getDefaultInstance()); } - /** - * repeated .Key key = 2; - */ - public java.util.List - getKeyBuilderList() { + /** repeated .Key key = 2; */ + public java.util.List getKeyBuilderList() { return getKeyFieldBuilder().getBuilderList(); } + private com.google.protobuf.RepeatedFieldBuilderV3< - FileProto.Key, FileProto.Key.Builder, FileProto.KeyOrBuilder> + FileProto.Key, FileProto.Key.Builder, FileProto.KeyOrBuilder> getKeyFieldBuilder() { if (keyBuilder_ == null) { - keyBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - FileProto.Key, FileProto.Key.Builder, FileProto.KeyOrBuilder>( - key_, - ((bitField0_ & 0x00000002) != 0), - getParentForChildren(), - isClean()); + keyBuilder_ = + new com.google.protobuf.RepeatedFieldBuilderV3< + FileProto.Key, FileProto.Key.Builder, FileProto.KeyOrBuilder>( + key_, ((bitField0_ & 0x00000002) != 0), getParentForChildren(), isClean()); key_ = null; } return keyBuilder_; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -955,12 +847,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:File) } // @@protoc_insertion_point(class_scope:File) private static final FileProto.File DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new FileProto.File(); } @@ -969,16 +861,17 @@ public static FileProto.File getDefaultInstance() { return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public File parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new File(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public File parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new File(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -993,14 +886,16 @@ public com.google.protobuf.Parser getParserForType() { public FileProto.File getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface HeaderOrBuilder extends + public interface HeaderOrBuilder + extends // @@protoc_insertion_point(interface_extends:Header) com.google.protobuf.MessageOrBuilder { /** + * + * *

      * Time window of keys in this file based on arrival to server, in UTC.
      * 
@@ -1009,6 +904,8 @@ public interface HeaderOrBuilder extends */ boolean hasStartTimestamp(); /** + * + * *
      * Time window of keys in this file based on arrival to server, in UTC.
      * 
@@ -1017,16 +914,14 @@ public interface HeaderOrBuilder extends */ long getStartTimestamp(); - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ boolean hasEndTimestamp(); - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ long getEndTimestamp(); /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -1035,6 +930,8 @@ public interface HeaderOrBuilder extends */ boolean hasRegion(); /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -1043,16 +940,19 @@ public interface HeaderOrBuilder extends */ java.lang.String getRegion(); /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
* * optional string region = 3; */ - com.google.protobuf.ByteString - getRegionBytes(); + com.google.protobuf.ByteString getRegionBytes(); /** + * + * *
      * E.g., Batch 2 of 10
      * 
@@ -1061,6 +961,8 @@ public interface HeaderOrBuilder extends */ boolean hasBatchNum(); /** + * + * *
      * E.g., Batch 2 of 10
      * 
@@ -1069,36 +971,31 @@ public interface HeaderOrBuilder extends */ int getBatchNum(); - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ boolean hasBatchSize(); - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ int getBatchSize(); } - /** - * Protobuf type {@code Header} - */ - public static final class Header extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code Header} */ + public static final class Header extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:Header) HeaderOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use Header.newBuilder() to construct. private Header(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private Header() { region_ = ""; } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private Header( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -1118,68 +1015,73 @@ private Header( case 0: done = true; break; - case 8: { - bitField0_ |= 0x00000001; - startTimestamp_ = input.readInt64(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - endTimestamp_ = input.readInt64(); - break; - } - case 26: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000004; - region_ = bs; - break; - } - case 32: { - bitField0_ |= 0x00000008; - batchNum_ = input.readInt32(); - break; - } - case 40: { - bitField0_ |= 0x00000010; - batchSize_ = input.readInt32(); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 8: + { + bitField0_ |= 0x00000001; + startTimestamp_ = input.readInt64(); + break; + } + case 16: + { + bitField0_ |= 0x00000002; + endTimestamp_ = input.readInt64(); + break; + } + case 26: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000004; + region_ = bs; + break; + } + case 32: + { + bitField0_ |= 0x00000008; + batchNum_ = input.readInt32(); + break; + } + case 40: + { + bitField0_ |= 0x00000010; + batchSize_ = input.readInt32(); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return FileProto.internal_static_Header_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return FileProto.internal_static_Header_fieldAccessorTable - .ensureFieldAccessorsInitialized( - FileProto.Header.class, FileProto.Header.Builder.class); + return FileProto.internal_static_Header_fieldAccessorTable.ensureFieldAccessorsInitialized( + FileProto.Header.class, FileProto.Header.Builder.class); } private int bitField0_; public static final int STARTTIMESTAMP_FIELD_NUMBER = 1; private long startTimestamp_; /** + * + * *
      * Time window of keys in this file based on arrival to server, in UTC.
      * 
@@ -1190,6 +1092,8 @@ public boolean hasStartTimestamp() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
      * Time window of keys in this file based on arrival to server, in UTC.
      * 
@@ -1202,15 +1106,11 @@ public long getStartTimestamp() { public static final int ENDTIMESTAMP_FIELD_NUMBER = 2; private long endTimestamp_; - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ public boolean hasEndTimestamp() { return ((bitField0_ & 0x00000002) != 0); } - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ public long getEndTimestamp() { return endTimestamp_; } @@ -1218,6 +1118,8 @@ public long getEndTimestamp() { public static final int REGION_FIELD_NUMBER = 3; private volatile java.lang.Object region_; /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -1228,6 +1130,8 @@ public boolean hasRegion() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -1239,8 +1143,7 @@ public java.lang.String getRegion() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { region_ = s; @@ -1249,19 +1152,19 @@ public java.lang.String getRegion() { } } /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
* * optional string region = 3; */ - public com.google.protobuf.ByteString - getRegionBytes() { + public com.google.protobuf.ByteString getRegionBytes() { java.lang.Object ref = region_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); region_ = b; return b; } else { @@ -1272,6 +1175,8 @@ public java.lang.String getRegion() { public static final int BATCHNUM_FIELD_NUMBER = 4; private int batchNum_; /** + * + * *
      * E.g., Batch 2 of 10
      * 
@@ -1282,6 +1187,8 @@ public boolean hasBatchNum() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
      * E.g., Batch 2 of 10
      * 
@@ -1294,20 +1201,17 @@ public int getBatchNum() { public static final int BATCHSIZE_FIELD_NUMBER = 5; private int batchSize_; - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ public boolean hasBatchSize() { return ((bitField0_ & 0x00000010) != 0); } - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ public int getBatchSize() { return batchSize_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -1319,8 +1223,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { output.writeInt64(1, startTimestamp_); } @@ -1346,23 +1249,19 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, startTimestamp_); + size += com.google.protobuf.CodedOutputStream.computeInt64Size(1, startTimestamp_); } if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(2, endTimestamp_); + size += com.google.protobuf.CodedOutputStream.computeInt64Size(2, endTimestamp_); } if (((bitField0_ & 0x00000004) != 0)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, region_); } if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, batchNum_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(4, batchNum_); } if (((bitField0_ & 0x00000010) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(5, batchSize_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(5, batchSize_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -1372,7 +1271,7 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof FileProto.Header)) { return super.equals(obj); @@ -1381,28 +1280,23 @@ public boolean equals(final java.lang.Object obj) { if (hasStartTimestamp() != other.hasStartTimestamp()) return false; if (hasStartTimestamp()) { - if (getStartTimestamp() - != other.getStartTimestamp()) return false; + if (getStartTimestamp() != other.getStartTimestamp()) return false; } if (hasEndTimestamp() != other.hasEndTimestamp()) return false; if (hasEndTimestamp()) { - if (getEndTimestamp() - != other.getEndTimestamp()) return false; + if (getEndTimestamp() != other.getEndTimestamp()) return false; } if (hasRegion() != other.hasRegion()) return false; if (hasRegion()) { - if (!getRegion() - .equals(other.getRegion())) return false; + if (!getRegion().equals(other.getRegion())) return false; } if (hasBatchNum() != other.hasBatchNum()) return false; if (hasBatchNum()) { - if (getBatchNum() - != other.getBatchNum()) return false; + if (getBatchNum() != other.getBatchNum()) return false; } if (hasBatchSize() != other.hasBatchSize()) return false; if (hasBatchSize()) { - if (getBatchSize() - != other.getBatchSize()) return false; + if (getBatchSize() != other.getBatchSize()) return false; } if (!unknownFields.equals(other.unknownFields)) return false; return true; @@ -1417,13 +1311,11 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); if (hasStartTimestamp()) { hash = (37 * hash) + STARTTIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getStartTimestamp()); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getStartTimestamp()); } if (hasEndTimestamp()) { hash = (37 * hash) + ENDTIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getEndTimestamp()); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getEndTimestamp()); } if (hasRegion()) { hash = (37 * hash) + REGION_FIELD_NUMBER; @@ -1442,88 +1334,92 @@ public int hashCode() { return hash; } - public static FileProto.Header parseFrom( - java.nio.ByteBuffer data) + public static FileProto.Header parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.Header parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static FileProto.Header parseFrom( - com.google.protobuf.ByteString data) + + public static FileProto.Header parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.Header parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static FileProto.Header parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.Header parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static FileProto.Header parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static FileProto.Header parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static FileProto.Header parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } + public static FileProto.Header parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static FileProto.Header parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } - public static FileProto.Header parseFrom( - com.google.protobuf.CodedInputStream input) + + public static FileProto.Header parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static FileProto.Header parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(FileProto.Header prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -1532,24 +1428,21 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code Header} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code Header} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:Header) FileProto.HeaderOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return FileProto.internal_static_Header_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return FileProto.internal_static_Header_fieldAccessorTable - .ensureFieldAccessorsInitialized( - FileProto.Header.class, FileProto.Header.Builder.class); + return FileProto.internal_static_Header_fieldAccessorTable.ensureFieldAccessorsInitialized( + FileProto.Header.class, FileProto.Header.Builder.class); } // Construct using FileOuterClass.Header.newBuilder() @@ -1557,16 +1450,15 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {} } + @java.lang.Override public Builder clear() { super.clear(); @@ -1584,8 +1476,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return FileProto.internal_static_Header_descriptor; } @@ -1637,38 +1528,41 @@ public FileProto.Header buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof FileProto.Header) { - return mergeFrom((FileProto.Header)other); + return mergeFrom((FileProto.Header) other); } else { super.mergeFrom(other); return this; @@ -1722,10 +1616,13 @@ public Builder mergeFrom( } return this; } + private int bitField0_; - private long startTimestamp_ ; + private long startTimestamp_; /** + * + * *
        * Time window of keys in this file based on arrival to server, in UTC.
        * 
@@ -1736,6 +1633,8 @@ public boolean hasStartTimestamp() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
        * Time window of keys in this file based on arrival to server, in UTC.
        * 
@@ -1746,6 +1645,8 @@ public long getStartTimestamp() { return startTimestamp_; } /** + * + * *
        * Time window of keys in this file based on arrival to server, in UTC.
        * 
@@ -1759,6 +1660,8 @@ public Builder setStartTimestamp(long value) { return this; } /** + * + * *
        * Time window of keys in this file based on arrival to server, in UTC.
        * 
@@ -1772,31 +1675,23 @@ public Builder clearStartTimestamp() { return this; } - private long endTimestamp_ ; - /** - * optional int64 endTimestamp = 2; - */ + private long endTimestamp_; + /** optional int64 endTimestamp = 2; */ public boolean hasEndTimestamp() { return ((bitField0_ & 0x00000002) != 0); } - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ public long getEndTimestamp() { return endTimestamp_; } - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ public Builder setEndTimestamp(long value) { bitField0_ |= 0x00000002; endTimestamp_ = value; onChanged(); return this; } - /** - * optional int64 endTimestamp = 2; - */ + /** optional int64 endTimestamp = 2; */ public Builder clearEndTimestamp() { bitField0_ = (bitField0_ & ~0x00000002); endTimestamp_ = 0L; @@ -1806,6 +1701,8 @@ public Builder clearEndTimestamp() { private java.lang.Object region_ = ""; /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
@@ -1816,6 +1713,8 @@ public boolean hasRegion() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
@@ -1825,8 +1724,7 @@ public boolean hasRegion() { public java.lang.String getRegion() { java.lang.Object ref = region_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { region_ = s; @@ -1837,19 +1735,19 @@ public java.lang.String getRegion() { } } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
* * optional string region = 3; */ - public com.google.protobuf.ByteString - getRegionBytes() { + public com.google.protobuf.ByteString getRegionBytes() { java.lang.Object ref = region_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); region_ = b; return b; } else { @@ -1857,23 +1755,26 @@ public java.lang.String getRegion() { } } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
* * optional string region = 3; */ - public Builder setRegion( - java.lang.String value) { + public Builder setRegion(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; region_ = value; onChanged(); return this; } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
@@ -1887,25 +1788,28 @@ public Builder clearRegion() { return this; } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
* * optional string region = 3; */ - public Builder setRegionBytes( - com.google.protobuf.ByteString value) { + public Builder setRegionBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; region_ = value; onChanged(); return this; } - private int batchNum_ ; + private int batchNum_; /** + * + * *
        * E.g., Batch 2 of 10
        * 
@@ -1916,6 +1820,8 @@ public boolean hasBatchNum() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
        * E.g., Batch 2 of 10
        * 
@@ -1926,6 +1832,8 @@ public int getBatchNum() { return batchNum_; } /** + * + * *
        * E.g., Batch 2 of 10
        * 
@@ -1939,6 +1847,8 @@ public Builder setBatchNum(int value) { return this; } /** + * + * *
        * E.g., Batch 2 of 10
        * 
@@ -1952,37 +1862,30 @@ public Builder clearBatchNum() { return this; } - private int batchSize_ ; - /** - * optional int32 batchSize = 5; - */ + private int batchSize_; + /** optional int32 batchSize = 5; */ public boolean hasBatchSize() { return ((bitField0_ & 0x00000010) != 0); } - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ public int getBatchSize() { return batchSize_; } - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ public Builder setBatchSize(int value) { bitField0_ |= 0x00000010; batchSize_ = value; onChanged(); return this; } - /** - * optional int32 batchSize = 5; - */ + /** optional int32 batchSize = 5; */ public Builder clearBatchSize() { bitField0_ = (bitField0_ & ~0x00000010); batchSize_ = 0; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -1995,12 +1898,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Header) } // @@protoc_insertion_point(class_scope:Header) private static final FileProto.Header DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new FileProto.Header(); } @@ -2009,16 +1912,17 @@ public static FileProto.Header getDefaultInstance() { return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser
- PARSER = new com.google.protobuf.AbstractParser
() { - @java.lang.Override - public Header parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Header(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser
PARSER = + new com.google.protobuf.AbstractParser
() { + @java.lang.Override + public Header parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Header(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser
parser() { return PARSER; @@ -2033,14 +1937,16 @@ public com.google.protobuf.Parser
getParserForType() { public FileProto.Header getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface KeyOrBuilder extends + public interface KeyOrBuilder + extends // @@protoc_insertion_point(interface_extends:Key) com.google.protobuf.MessageOrBuilder { /** + * + * *
      * Key of infected user
      * 
@@ -2049,6 +1955,8 @@ public interface KeyOrBuilder extends */ boolean hasKeyData(); /** + * + * *
      * Key of infected user
      * 
@@ -2058,6 +1966,8 @@ public interface KeyOrBuilder extends com.google.protobuf.ByteString getKeyData(); /** + * + * *
      * Interval number when the key's EKRollingPeriod started.
      * 
@@ -2066,6 +1976,8 @@ public interface KeyOrBuilder extends */ boolean hasRollingStartNumber(); /** + * + * *
      * Interval number when the key's EKRollingPeriod started.
      * 
@@ -2075,6 +1987,8 @@ public interface KeyOrBuilder extends int getRollingStartNumber(); /** + * + * *
      * Number of 10-minute windows between key rolling.
      * 
@@ -2083,6 +1997,8 @@ public interface KeyOrBuilder extends */ boolean hasRollingPeriod(); /** + * + * *
      * Number of 10-minute windows between key rolling.
      * 
@@ -2092,6 +2008,8 @@ public interface KeyOrBuilder extends int getRollingPeriod(); /** + * + * *
      * Risk of transmission associated with the person this key came from.
      * 
@@ -2100,6 +2018,8 @@ public interface KeyOrBuilder extends */ boolean hasTransmissionRiskLevel(); /** + * + * *
      * Risk of transmission associated with the person this key came from.
      * 
@@ -2108,27 +2028,26 @@ public interface KeyOrBuilder extends */ int getTransmissionRiskLevel(); } - /** - * Protobuf type {@code Key} - */ - public static final class Key extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code Key} */ + public static final class Key extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:Key) KeyOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use Key.newBuilder() to construct. private Key(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private Key() { keyData_ = com.google.protobuf.ByteString.EMPTY; } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private Key( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -2148,62 +2067,66 @@ private Key( case 0: done = true; break; - case 10: { - bitField0_ |= 0x00000001; - keyData_ = input.readBytes(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - rollingStartNumber_ = input.readUInt32(); - break; - } - case 24: { - bitField0_ |= 0x00000004; - rollingPeriod_ = input.readUInt32(); - break; - } - case 32: { - bitField0_ |= 0x00000008; - transmissionRiskLevel_ = input.readInt32(); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 10: + { + bitField0_ |= 0x00000001; + keyData_ = input.readBytes(); + break; + } + case 16: + { + bitField0_ |= 0x00000002; + rollingStartNumber_ = input.readUInt32(); + break; + } + case 24: + { + bitField0_ |= 0x00000004; + rollingPeriod_ = input.readUInt32(); + break; + } + case 32: + { + bitField0_ |= 0x00000008; + transmissionRiskLevel_ = input.readInt32(); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return FileProto.internal_static_Key_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return FileProto.internal_static_Key_fieldAccessorTable - .ensureFieldAccessorsInitialized( - FileProto.Key.class, FileProto.Key.Builder.class); + return FileProto.internal_static_Key_fieldAccessorTable.ensureFieldAccessorsInitialized( + FileProto.Key.class, FileProto.Key.Builder.class); } private int bitField0_; public static final int KEYDATA_FIELD_NUMBER = 1; private com.google.protobuf.ByteString keyData_; /** + * + * *
      * Key of infected user
      * 
@@ -2214,6 +2137,8 @@ public boolean hasKeyData() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
      * Key of infected user
      * 
@@ -2227,6 +2152,8 @@ public com.google.protobuf.ByteString getKeyData() { public static final int ROLLINGSTARTNUMBER_FIELD_NUMBER = 2; private int rollingStartNumber_; /** + * + * *
      * Interval number when the key's EKRollingPeriod started.
      * 
@@ -2237,6 +2164,8 @@ public boolean hasRollingStartNumber() { return ((bitField0_ & 0x00000002) != 0); } /** + * + * *
      * Interval number when the key's EKRollingPeriod started.
      * 
@@ -2250,6 +2179,8 @@ public int getRollingStartNumber() { public static final int ROLLINGPERIOD_FIELD_NUMBER = 3; private int rollingPeriod_; /** + * + * *
      * Number of 10-minute windows between key rolling.
      * 
@@ -2260,6 +2191,8 @@ public boolean hasRollingPeriod() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
      * Number of 10-minute windows between key rolling.
      * 
@@ -2273,6 +2206,8 @@ public int getRollingPeriod() { public static final int TRANSMISSIONRISKLEVEL_FIELD_NUMBER = 4; private int transmissionRiskLevel_; /** + * + * *
      * Risk of transmission associated with the person this key came from.
      * 
@@ -2283,6 +2218,8 @@ public boolean hasTransmissionRiskLevel() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
      * Risk of transmission associated with the person this key came from.
      * 
@@ -2294,6 +2231,7 @@ public int getTransmissionRiskLevel() { } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -2305,8 +2243,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { output.writeBytes(1, keyData_); } @@ -2329,20 +2266,16 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, keyData_); + size += com.google.protobuf.CodedOutputStream.computeBytesSize(1, keyData_); } if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(2, rollingStartNumber_); + size += com.google.protobuf.CodedOutputStream.computeUInt32Size(2, rollingStartNumber_); } if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(3, rollingPeriod_); + size += com.google.protobuf.CodedOutputStream.computeUInt32Size(3, rollingPeriod_); } if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, transmissionRiskLevel_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(4, transmissionRiskLevel_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -2352,7 +2285,7 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof FileProto.Key)) { return super.equals(obj); @@ -2361,23 +2294,19 @@ public boolean equals(final java.lang.Object obj) { if (hasKeyData() != other.hasKeyData()) return false; if (hasKeyData()) { - if (!getKeyData() - .equals(other.getKeyData())) return false; + if (!getKeyData().equals(other.getKeyData())) return false; } if (hasRollingStartNumber() != other.hasRollingStartNumber()) return false; if (hasRollingStartNumber()) { - if (getRollingStartNumber() - != other.getRollingStartNumber()) return false; + if (getRollingStartNumber() != other.getRollingStartNumber()) return false; } if (hasRollingPeriod() != other.hasRollingPeriod()) return false; if (hasRollingPeriod()) { - if (getRollingPeriod() - != other.getRollingPeriod()) return false; + if (getRollingPeriod() != other.getRollingPeriod()) return false; } if (hasTransmissionRiskLevel() != other.hasTransmissionRiskLevel()) return false; if (hasTransmissionRiskLevel()) { - if (getTransmissionRiskLevel() - != other.getTransmissionRiskLevel()) return false; + if (getTransmissionRiskLevel() != other.getTransmissionRiskLevel()) return false; } if (!unknownFields.equals(other.unknownFields)) return false; return true; @@ -2411,88 +2340,92 @@ public int hashCode() { return hash; } - public static FileProto.Key parseFrom( - java.nio.ByteBuffer data) + public static FileProto.Key parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.Key parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static FileProto.Key parseFrom( - com.google.protobuf.ByteString data) + + public static FileProto.Key parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.Key parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static FileProto.Key parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static FileProto.Key parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static FileProto.Key parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static FileProto.Key parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static FileProto.Key parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } + public static FileProto.Key parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static FileProto.Key parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } - public static FileProto.Key parseFrom( - com.google.protobuf.CodedInputStream input) + + public static FileProto.Key parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static FileProto.Key parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(FileProto.Key prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -2501,24 +2434,21 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code Key} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code Key} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:Key) FileProto.KeyOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return FileProto.internal_static_Key_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return FileProto.internal_static_Key_fieldAccessorTable - .ensureFieldAccessorsInitialized( - FileProto.Key.class, FileProto.Key.Builder.class); + return FileProto.internal_static_Key_fieldAccessorTable.ensureFieldAccessorsInitialized( + FileProto.Key.class, FileProto.Key.Builder.class); } // Construct using FileOuterClass.Key.newBuilder() @@ -2526,16 +2456,15 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {} } + @java.lang.Override public Builder clear() { super.clear(); @@ -2551,8 +2480,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return FileProto.internal_static_Key_descriptor; } @@ -2600,38 +2528,41 @@ public FileProto.Key buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof FileProto.Key) { - return mergeFrom((FileProto.Key)other); + return mergeFrom((FileProto.Key) other); } else { super.mergeFrom(other); return this; @@ -2680,10 +2611,13 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private com.google.protobuf.ByteString keyData_ = com.google.protobuf.ByteString.EMPTY; /** + * + * *
        * Key of infected user
        * 
@@ -2694,6 +2628,8 @@ public boolean hasKeyData() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
        * Key of infected user
        * 
@@ -2704,6 +2640,8 @@ public com.google.protobuf.ByteString getKeyData() { return keyData_; } /** + * + * *
        * Key of infected user
        * 
@@ -2712,14 +2650,16 @@ public com.google.protobuf.ByteString getKeyData() { */ public Builder setKeyData(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; keyData_ = value; onChanged(); return this; } /** + * + * *
        * Key of infected user
        * 
@@ -2733,8 +2673,10 @@ public Builder clearKeyData() { return this; } - private int rollingStartNumber_ ; + private int rollingStartNumber_; /** + * + * *
        * Interval number when the key's EKRollingPeriod started.
        * 
@@ -2745,6 +2687,8 @@ public boolean hasRollingStartNumber() { return ((bitField0_ & 0x00000002) != 0); } /** + * + * *
        * Interval number when the key's EKRollingPeriod started.
        * 
@@ -2755,6 +2699,8 @@ public int getRollingStartNumber() { return rollingStartNumber_; } /** + * + * *
        * Interval number when the key's EKRollingPeriod started.
        * 
@@ -2768,6 +2714,8 @@ public Builder setRollingStartNumber(int value) { return this; } /** + * + * *
        * Interval number when the key's EKRollingPeriod started.
        * 
@@ -2781,8 +2729,10 @@ public Builder clearRollingStartNumber() { return this; } - private int rollingPeriod_ ; + private int rollingPeriod_; /** + * + * *
        * Number of 10-minute windows between key rolling.
        * 
@@ -2793,6 +2743,8 @@ public boolean hasRollingPeriod() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
        * Number of 10-minute windows between key rolling.
        * 
@@ -2803,6 +2755,8 @@ public int getRollingPeriod() { return rollingPeriod_; } /** + * + * *
        * Number of 10-minute windows between key rolling.
        * 
@@ -2816,6 +2770,8 @@ public Builder setRollingPeriod(int value) { return this; } /** + * + * *
        * Number of 10-minute windows between key rolling.
        * 
@@ -2829,8 +2785,10 @@ public Builder clearRollingPeriod() { return this; } - private int transmissionRiskLevel_ ; + private int transmissionRiskLevel_; /** + * + * *
        * Risk of transmission associated with the person this key came from.
        * 
@@ -2841,6 +2799,8 @@ public boolean hasTransmissionRiskLevel() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
        * Risk of transmission associated with the person this key came from.
        * 
@@ -2851,6 +2811,8 @@ public int getTransmissionRiskLevel() { return transmissionRiskLevel_; } /** + * + * *
        * Risk of transmission associated with the person this key came from.
        * 
@@ -2864,6 +2826,8 @@ public Builder setTransmissionRiskLevel(int value) { return this; } /** + * + * *
        * Risk of transmission associated with the person this key came from.
        * 
@@ -2876,6 +2840,7 @@ public Builder clearTransmissionRiskLevel() { onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -2888,12 +2853,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Key) } // @@protoc_insertion_point(class_scope:Key) private static final FileProto.Key DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new FileProto.Key(); } @@ -2902,16 +2867,17 @@ public static FileProto.Key getDefaultInstance() { return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public Key parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Key(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Key parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Key(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -2926,71 +2892,76 @@ public com.google.protobuf.Parser getParserForType() { public FileProto.Key getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_File_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + private static final com.google.protobuf.Descriptors.Descriptor internal_static_File_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_File_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Header_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + private static final com.google.protobuf.Descriptors.Descriptor internal_static_Header_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_Header_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Key_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + private static final com.google.protobuf.Descriptors.Descriptor internal_static_Key_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_Key_fieldAccessorTable; - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + static { java.lang.String[] descriptorData = { - "\n\nfile.proto\"2\n\004File\022\027\n\006header\030\001 \001(\0132\007.H" + - "eader\022\021\n\003key\030\002 \003(\0132\004.Key\"k\n\006Header\022\026\n\016st" + - "artTimestamp\030\001 \001(\003\022\024\n\014endTimestamp\030\002 \001(\003" + - "\022\016\n\006region\030\003 \001(\t\022\020\n\010batchNum\030\004 \001(\005\022\021\n\tba" + - "tchSize\030\005 \001(\005\"h\n\003Key\022\017\n\007keyData\030\001 \001(\014\022\032\n" + - "\022rollingStartNumber\030\002 \001(\r\022\025\n\rrollingPeri" + - "od\030\003 \001(\r\022\035\n\025transmissionRiskLevel\030\004 \001(\005" + "\n\n" + + "file.proto\"2\n" + + "\004File\022\027\n" + + "\006header\030\001 \001(\0132\007.Header\022\021\n" + + "\003key\030\002 \003(\0132\004.Key\"k\n" + + "\006Header\022\026\n" + + "\016startTimestamp\030\001 \001(\003\022\024\n" + + "\014endTimestamp\030\002 \001(\003\022\016\n" + + "\006region\030\003 \001(\t\022\020\n" + + "\010batchNum\030\004 \001(\005\022\021\n" + + "\tbatchSize\030\005 \001(\005\"h\n" + + "\003Key\022\017\n" + + "\007keyData\030\001 \001(\014\022\032\n" + + "\022rollingStartNumber\030\002 \001(\r" + + "\022\025\n\r" + + "rollingPeriod\030\003 \001(\r" + + "\022\035\n" + + "\025transmissionRiskLevel\030\004 \001(\005" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - internal_static_File_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_File_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_File_descriptor, - new java.lang.String[] { "Header", "Key", }); - internal_static_Header_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_Header_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Header_descriptor, - new java.lang.String[] { "StartTimestamp", "EndTimestamp", "Region", "BatchNum", "BatchSize", }); - internal_static_Key_descriptor = - getDescriptor().getMessageTypes().get(2); - internal_static_Key_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Key_descriptor, - new java.lang.String[] { "KeyData", "RollingStartNumber", "RollingPeriod", "TransmissionRiskLevel", }); + com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( + descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner); + internal_static_File_descriptor = getDescriptor().getMessageTypes().get(0); + internal_static_File_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_File_descriptor, + new java.lang.String[] { + "Header", "Key", + }); + internal_static_Header_descriptor = getDescriptor().getMessageTypes().get(1); + internal_static_Header_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_Header_descriptor, + new java.lang.String[] { + "StartTimestamp", "EndTimestamp", "Region", "BatchNum", "BatchSize", + }); + internal_static_Key_descriptor = getDescriptor().getMessageTypes().get(2); + internal_static_Key_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_Key_descriptor, + new java.lang.String[] { + "KeyData", "RollingStartNumber", "RollingPeriod", "TransmissionRiskLevel", + }); } // @@protoc_insertion_point(outer_class_scope) diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/TemporaryExposureKeyFormat.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/TemporaryExposureKeyFormat.java index d20bea8f..b4dc2ec1 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/TemporaryExposureKeyFormat.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/gaen/proto/TemporaryExposureKeyFormat.java @@ -4,20 +4,21 @@ public final class TemporaryExposureKeyFormat { private TemporaryExposureKeyFormat() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) {} + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); } - public interface TemporaryExposureKeyExportOrBuilder extends + + public interface TemporaryExposureKeyExportOrBuilder + extends // @@protoc_insertion_point(interface_extends:TemporaryExposureKeyExport) com.google.protobuf.MessageOrBuilder { /** + * + * *
      * Time window of keys in this batch based on arrival to server, in UTC seconds
      * 
@@ -26,6 +27,8 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ boolean hasStartTimestamp(); /** + * + * *
      * Time window of keys in this batch based on arrival to server, in UTC seconds
      * 
@@ -34,16 +37,14 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ long getStartTimestamp(); - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ boolean hasEndTimestamp(); - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ long getEndTimestamp(); /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -52,6 +53,8 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ boolean hasRegion(); /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -60,16 +63,19 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ java.lang.String getRegion(); /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
* * optional string region = 3; */ - com.google.protobuf.ByteString - getRegionBytes(); + com.google.protobuf.ByteString getRegionBytes(); /** + * + * *
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * 
@@ -78,6 +84,8 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ boolean hasBatchNum(); /** + * + * *
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * 
@@ -86,25 +94,24 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ int getBatchNum(); - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ boolean hasBatchSize(); - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ int getBatchSize(); /** + * + * *
      * Information about associated signatures
      * 
* * repeated .SignatureInfo signature_infos = 6; */ - java.util.List - getSignatureInfosList(); + java.util.List getSignatureInfosList(); /** + * + * *
      * Information about associated signatures
      * 
@@ -113,6 +120,8 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ TemporaryExposureKeyFormat.SignatureInfo getSignatureInfos(int index); /** + * + * *
      * Information about associated signatures
      * 
@@ -121,34 +130,40 @@ public interface TemporaryExposureKeyExportOrBuilder extends */ int getSignatureInfosCount(); /** + * + * *
      * Information about associated signatures
      * 
* * repeated .SignatureInfo signature_infos = 6; */ - java.util.List + java.util.List getSignatureInfosOrBuilderList(); /** + * + * *
      * Information about associated signatures
      * 
* * repeated .SignatureInfo signature_infos = 6; */ - TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder( - int index); + TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder(int index); /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
* * repeated .TemporaryExposureKey keys = 7; */ - java.util.List - getKeysList(); + java.util.List getKeysList(); /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
@@ -157,6 +172,8 @@ TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder( */ TemporaryExposureKeyFormat.TemporaryExposureKey getKeys(int index); /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
@@ -165,36 +182,39 @@ TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder( */ int getKeysCount(); /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
* * repeated .TemporaryExposureKey keys = 7; */ - java.util.List + java.util.List getKeysOrBuilderList(); /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
* * repeated .TemporaryExposureKey keys = 7; */ - TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder( - int index); + TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder(int index); } - /** - * Protobuf type {@code TemporaryExposureKeyExport} - */ - public static final class TemporaryExposureKeyExport extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code TemporaryExposureKeyExport} */ + public static final class TemporaryExposureKeyExport + extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:TemporaryExposureKeyExport) TemporaryExposureKeyExportOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use TemporaryExposureKeyExport.newBuilder() to construct. private TemporaryExposureKeyExport(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private TemporaryExposureKeyExport() { region_ = ""; signatureInfos_ = java.util.Collections.emptyList(); @@ -202,10 +222,10 @@ private TemporaryExposureKeyExport() { } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private TemporaryExposureKeyExport( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -225,64 +245,74 @@ private TemporaryExposureKeyExport( case 0: done = true; break; - case 9: { - bitField0_ |= 0x00000001; - startTimestamp_ = input.readFixed64(); - break; - } - case 17: { - bitField0_ |= 0x00000002; - endTimestamp_ = input.readFixed64(); - break; - } - case 26: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000004; - region_ = bs; - break; - } - case 32: { - bitField0_ |= 0x00000008; - batchNum_ = input.readInt32(); - break; - } - case 40: { - bitField0_ |= 0x00000010; - batchSize_ = input.readInt32(); - break; - } - case 50: { - if (!((mutable_bitField0_ & 0x00000020) != 0)) { - signatureInfos_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000020; + case 9: + { + bitField0_ |= 0x00000001; + startTimestamp_ = input.readFixed64(); + break; } - signatureInfos_.add( - input.readMessage(TemporaryExposureKeyFormat.SignatureInfo.PARSER, extensionRegistry)); - break; - } - case 58: { - if (!((mutable_bitField0_ & 0x00000040) != 0)) { - keys_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000040; + case 17: + { + bitField0_ |= 0x00000002; + endTimestamp_ = input.readFixed64(); + break; } - keys_.add( - input.readMessage(TemporaryExposureKeyFormat.TemporaryExposureKey.PARSER, extensionRegistry)); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 26: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000004; + region_ = bs; + break; + } + case 32: + { + bitField0_ |= 0x00000008; + batchNum_ = input.readInt32(); + break; + } + case 40: + { + bitField0_ |= 0x00000010; + batchSize_ = input.readInt32(); + break; + } + case 50: + { + if (!((mutable_bitField0_ & 0x00000020) != 0)) { + signatureInfos_ = + new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000020; + } + signatureInfos_.add( + input.readMessage( + TemporaryExposureKeyFormat.SignatureInfo.PARSER, extensionRegistry)); + break; + } + case 58: + { + if (!((mutable_bitField0_ & 0x00000040) != 0)) { + keys_ = + new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000040; + } + keys_.add( + input.readMessage( + TemporaryExposureKeyFormat.TemporaryExposureKey.PARSER, extensionRegistry)); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { if (((mutable_bitField0_ & 0x00000020) != 0)) { signatureInfos_ = java.util.Collections.unmodifiableList(signatureInfos_); @@ -294,23 +324,27 @@ private TemporaryExposureKeyExport( makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKeyExport_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKeyExport_fieldAccessorTable + return TemporaryExposureKeyFormat + .internal_static_TemporaryExposureKeyExport_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TemporaryExposureKeyExport.class, TemporaryExposureKeyFormat.TemporaryExposureKeyExport.Builder.class); + TemporaryExposureKeyFormat.TemporaryExposureKeyExport.class, + TemporaryExposureKeyFormat.TemporaryExposureKeyExport.Builder.class); } private int bitField0_; public static final int START_TIMESTAMP_FIELD_NUMBER = 1; private long startTimestamp_; /** + * + * *
      * Time window of keys in this batch based on arrival to server, in UTC seconds
      * 
@@ -321,6 +355,8 @@ public boolean hasStartTimestamp() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
      * Time window of keys in this batch based on arrival to server, in UTC seconds
      * 
@@ -333,15 +369,11 @@ public long getStartTimestamp() { public static final int END_TIMESTAMP_FIELD_NUMBER = 2; private long endTimestamp_; - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ public boolean hasEndTimestamp() { return ((bitField0_ & 0x00000002) != 0); } - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ public long getEndTimestamp() { return endTimestamp_; } @@ -349,6 +381,8 @@ public long getEndTimestamp() { public static final int REGION_FIELD_NUMBER = 3; private volatile java.lang.Object region_; /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -359,6 +393,8 @@ public boolean hasRegion() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
@@ -370,8 +406,7 @@ public java.lang.String getRegion() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { region_ = s; @@ -380,19 +415,19 @@ public java.lang.String getRegion() { } } /** + * + * *
      * Region for which these keys came from (e.g., country)
      * 
* * optional string region = 3; */ - public com.google.protobuf.ByteString - getRegionBytes() { + public com.google.protobuf.ByteString getRegionBytes() { java.lang.Object ref = region_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); region_ = b; return b; } else { @@ -403,6 +438,8 @@ public java.lang.String getRegion() { public static final int BATCH_NUM_FIELD_NUMBER = 4; private int batchNum_; /** + * + * *
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * 
@@ -413,6 +450,8 @@ public boolean hasBatchNum() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * 
@@ -425,15 +464,11 @@ public int getBatchNum() { public static final int BATCH_SIZE_FIELD_NUMBER = 5; private int batchSize_; - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ public boolean hasBatchSize() { return ((bitField0_ & 0x00000010) != 0); } - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ public int getBatchSize() { return batchSize_; } @@ -441,6 +476,8 @@ public int getBatchSize() { public static final int SIGNATURE_INFOS_FIELD_NUMBER = 6; private java.util.List signatureInfos_; /** + * + * *
      * Information about associated signatures
      * 
@@ -451,17 +488,21 @@ public java.util.List getSignatureInfo return signatureInfos_; } /** + * + * *
      * Information about associated signatures
      * 
* * repeated .SignatureInfo signature_infos = 6; */ - public java.util.List + public java.util.List getSignatureInfosOrBuilderList() { return signatureInfos_; } /** + * + * *
      * Information about associated signatures
      * 
@@ -472,6 +513,8 @@ public int getSignatureInfosCount() { return signatureInfos_.size(); } /** + * + * *
      * Information about associated signatures
      * 
@@ -482,20 +525,23 @@ public TemporaryExposureKeyFormat.SignatureInfo getSignatureInfos(int index) { return signatureInfos_.get(index); } /** + * + * *
      * Information about associated signatures
      * 
* * repeated .SignatureInfo signature_infos = 6; */ - public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder( - int index) { + public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder(int index) { return signatureInfos_.get(index); } public static final int KEYS_FIELD_NUMBER = 7; private java.util.List keys_; /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
@@ -506,17 +552,21 @@ public java.util.List getKeysLi return keys_; } /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
* * repeated .TemporaryExposureKey keys = 7; */ - public java.util.List + public java.util.List getKeysOrBuilderList() { return keys_; } /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
@@ -527,6 +577,8 @@ public int getKeysCount() { return keys_.size(); } /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
@@ -537,18 +589,20 @@ public TemporaryExposureKeyFormat.TemporaryExposureKey getKeys(int index) { return keys_.get(index); } /** + * + * *
      * The TemporaryExposureKeys themselves
      * 
* * repeated .TemporaryExposureKey keys = 7; */ - public TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder( - int index) { + public TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder(int index) { return keys_.get(index); } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -560,8 +614,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { output.writeFixed64(1, startTimestamp_); } @@ -593,31 +646,25 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeFixed64Size(1, startTimestamp_); + size += com.google.protobuf.CodedOutputStream.computeFixed64Size(1, startTimestamp_); } if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeFixed64Size(2, endTimestamp_); + size += com.google.protobuf.CodedOutputStream.computeFixed64Size(2, endTimestamp_); } if (((bitField0_ & 0x00000004) != 0)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, region_); } if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, batchNum_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(4, batchNum_); } if (((bitField0_ & 0x00000010) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(5, batchSize_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(5, batchSize_); } for (int i = 0; i < signatureInfos_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, signatureInfos_.get(i)); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(6, signatureInfos_.get(i)); } for (int i = 0; i < keys_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(7, keys_.get(i)); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(7, keys_.get(i)); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -627,42 +674,36 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof TemporaryExposureKeyFormat.TemporaryExposureKeyExport)) { return super.equals(obj); } - TemporaryExposureKeyFormat.TemporaryExposureKeyExport other = (TemporaryExposureKeyFormat.TemporaryExposureKeyExport) obj; + TemporaryExposureKeyFormat.TemporaryExposureKeyExport other = + (TemporaryExposureKeyFormat.TemporaryExposureKeyExport) obj; if (hasStartTimestamp() != other.hasStartTimestamp()) return false; if (hasStartTimestamp()) { - if (getStartTimestamp() - != other.getStartTimestamp()) return false; + if (getStartTimestamp() != other.getStartTimestamp()) return false; } if (hasEndTimestamp() != other.hasEndTimestamp()) return false; if (hasEndTimestamp()) { - if (getEndTimestamp() - != other.getEndTimestamp()) return false; + if (getEndTimestamp() != other.getEndTimestamp()) return false; } if (hasRegion() != other.hasRegion()) return false; if (hasRegion()) { - if (!getRegion() - .equals(other.getRegion())) return false; + if (!getRegion().equals(other.getRegion())) return false; } if (hasBatchNum() != other.hasBatchNum()) return false; if (hasBatchNum()) { - if (getBatchNum() - != other.getBatchNum()) return false; + if (getBatchNum() != other.getBatchNum()) return false; } if (hasBatchSize() != other.hasBatchSize()) return false; if (hasBatchSize()) { - if (getBatchSize() - != other.getBatchSize()) return false; + if (getBatchSize() != other.getBatchSize()) return false; } - if (!getSignatureInfosList() - .equals(other.getSignatureInfosList())) return false; - if (!getKeysList() - .equals(other.getKeysList())) return false; + if (!getSignatureInfosList().equals(other.getSignatureInfosList())) return false; + if (!getKeysList().equals(other.getKeysList())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @@ -676,13 +717,11 @@ public int hashCode() { hash = (19 * hash) + getDescriptor().hashCode(); if (hasStartTimestamp()) { hash = (37 * hash) + START_TIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getStartTimestamp()); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getStartTimestamp()); } if (hasEndTimestamp()) { hash = (37 * hash) + END_TIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getEndTimestamp()); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getEndTimestamp()); } if (hasRegion()) { hash = (37 * hash) + REGION_FIELD_NUMBER; @@ -710,87 +749,94 @@ public int hashCode() { } public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { + java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(TemporaryExposureKeyFormat.TemporaryExposureKeyExport prototype) { + + public static Builder newBuilder( + TemporaryExposureKeyFormat.TemporaryExposureKeyExport prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -799,24 +845,24 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code TemporaryExposureKeyExport} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code TemporaryExposureKeyExport} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:TemporaryExposureKeyExport) TemporaryExposureKeyFormat.TemporaryExposureKeyExportOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKeyExport_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKeyExport_fieldAccessorTable + return TemporaryExposureKeyFormat + .internal_static_TemporaryExposureKeyExport_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TemporaryExposureKeyExport.class, TemporaryExposureKeyFormat.TemporaryExposureKeyExport.Builder.class); + TemporaryExposureKeyFormat.TemporaryExposureKeyExport.class, + TemporaryExposureKeyFormat.TemporaryExposureKeyExport.Builder.class); } // Construct using TemporaryExposureKeyFormat.TemporaryExposureKeyExport.newBuilder() @@ -824,18 +870,18 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { getSignatureInfosFieldBuilder(); getKeysFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); @@ -865,8 +911,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKeyExport_descriptor; } @@ -886,7 +931,8 @@ public TemporaryExposureKeyFormat.TemporaryExposureKeyExport build() { @java.lang.Override public TemporaryExposureKeyFormat.TemporaryExposureKeyExport buildPartial() { - TemporaryExposureKeyFormat.TemporaryExposureKeyExport result = new TemporaryExposureKeyFormat.TemporaryExposureKeyExport(this); + TemporaryExposureKeyFormat.TemporaryExposureKeyExport result = + new TemporaryExposureKeyFormat.TemporaryExposureKeyExport(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -936,38 +982,41 @@ public TemporaryExposureKeyFormat.TemporaryExposureKeyExport buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof TemporaryExposureKeyFormat.TemporaryExposureKeyExport) { - return mergeFrom((TemporaryExposureKeyFormat.TemporaryExposureKeyExport)other); + return mergeFrom((TemporaryExposureKeyFormat.TemporaryExposureKeyExport) other); } else { super.mergeFrom(other); return this; @@ -975,7 +1024,8 @@ public Builder mergeFrom(com.google.protobuf.Message other) { } public Builder mergeFrom(TemporaryExposureKeyFormat.TemporaryExposureKeyExport other) { - if (other == TemporaryExposureKeyFormat.TemporaryExposureKeyExport.getDefaultInstance()) return this; + if (other == TemporaryExposureKeyFormat.TemporaryExposureKeyExport.getDefaultInstance()) + return this; if (other.hasStartTimestamp()) { setStartTimestamp(other.getStartTimestamp()); } @@ -1011,9 +1061,10 @@ public Builder mergeFrom(TemporaryExposureKeyFormat.TemporaryExposureKeyExport o signatureInfosBuilder_ = null; signatureInfos_ = other.signatureInfos_; bitField0_ = (bitField0_ & ~0x00000020); - signatureInfosBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getSignatureInfosFieldBuilder() : null; + signatureInfosBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders + ? getSignatureInfosFieldBuilder() + : null; } else { signatureInfosBuilder_.addAllMessages(other.signatureInfos_); } @@ -1037,9 +1088,10 @@ public Builder mergeFrom(TemporaryExposureKeyFormat.TemporaryExposureKeyExport o keysBuilder_ = null; keys_ = other.keys_; bitField0_ = (bitField0_ & ~0x00000040); - keysBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getKeysFieldBuilder() : null; + keysBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders + ? getKeysFieldBuilder() + : null; } else { keysBuilder_.addAllMessages(other.keys_); } @@ -1064,7 +1116,8 @@ public Builder mergeFrom( try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (TemporaryExposureKeyFormat.TemporaryExposureKeyExport) e.getUnfinishedMessage(); + parsedMessage = + (TemporaryExposureKeyFormat.TemporaryExposureKeyExport) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -1073,10 +1126,13 @@ public Builder mergeFrom( } return this; } + private int bitField0_; - private long startTimestamp_ ; + private long startTimestamp_; /** + * + * *
        * Time window of keys in this batch based on arrival to server, in UTC seconds
        * 
@@ -1087,6 +1143,8 @@ public boolean hasStartTimestamp() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
        * Time window of keys in this batch based on arrival to server, in UTC seconds
        * 
@@ -1097,6 +1155,8 @@ public long getStartTimestamp() { return startTimestamp_; } /** + * + * *
        * Time window of keys in this batch based on arrival to server, in UTC seconds
        * 
@@ -1110,6 +1170,8 @@ public Builder setStartTimestamp(long value) { return this; } /** + * + * *
        * Time window of keys in this batch based on arrival to server, in UTC seconds
        * 
@@ -1123,31 +1185,23 @@ public Builder clearStartTimestamp() { return this; } - private long endTimestamp_ ; - /** - * optional fixed64 end_timestamp = 2; - */ + private long endTimestamp_; + /** optional fixed64 end_timestamp = 2; */ public boolean hasEndTimestamp() { return ((bitField0_ & 0x00000002) != 0); } - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ public long getEndTimestamp() { return endTimestamp_; } - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ public Builder setEndTimestamp(long value) { bitField0_ |= 0x00000002; endTimestamp_ = value; onChanged(); return this; } - /** - * optional fixed64 end_timestamp = 2; - */ + /** optional fixed64 end_timestamp = 2; */ public Builder clearEndTimestamp() { bitField0_ = (bitField0_ & ~0x00000002); endTimestamp_ = 0L; @@ -1157,6 +1211,8 @@ public Builder clearEndTimestamp() { private java.lang.Object region_ = ""; /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
@@ -1167,6 +1223,8 @@ public boolean hasRegion() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
@@ -1176,8 +1234,7 @@ public boolean hasRegion() { public java.lang.String getRegion() { java.lang.Object ref = region_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { region_ = s; @@ -1188,19 +1245,19 @@ public java.lang.String getRegion() { } } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
* * optional string region = 3; */ - public com.google.protobuf.ByteString - getRegionBytes() { + public com.google.protobuf.ByteString getRegionBytes() { java.lang.Object ref = region_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); region_ = b; return b; } else { @@ -1208,23 +1265,26 @@ public java.lang.String getRegion() { } } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
* * optional string region = 3; */ - public Builder setRegion( - java.lang.String value) { + public Builder setRegion(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; region_ = value; onChanged(); return this; } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
@@ -1238,25 +1298,28 @@ public Builder clearRegion() { return this; } /** + * + * *
        * Region for which these keys came from (e.g., country)
        * 
* * optional string region = 3; */ - public Builder setRegionBytes( - com.google.protobuf.ByteString value) { + public Builder setRegionBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; region_ = value; onChanged(); return this; } - private int batchNum_ ; + private int batchNum_; /** + * + * *
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * 
@@ -1267,6 +1330,8 @@ public boolean hasBatchNum() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * 
@@ -1277,6 +1342,8 @@ public int getBatchNum() { return batchNum_; } /** + * + * *
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * 
@@ -1290,6 +1357,8 @@ public Builder setBatchNum(int value) { return this; } /** + * + * *
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * 
@@ -1303,31 +1372,23 @@ public Builder clearBatchNum() { return this; } - private int batchSize_ ; - /** - * optional int32 batch_size = 5; - */ + private int batchSize_; + /** optional int32 batch_size = 5; */ public boolean hasBatchSize() { return ((bitField0_ & 0x00000010) != 0); } - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ public int getBatchSize() { return batchSize_; } - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ public Builder setBatchSize(int value) { bitField0_ |= 0x00000010; batchSize_ = value; onChanged(); return this; } - /** - * optional int32 batch_size = 5; - */ + /** optional int32 batch_size = 5; */ public Builder clearBatchSize() { bitField0_ = (bitField0_ & ~0x00000010); batchSize_ = 0; @@ -1336,18 +1397,25 @@ public Builder clearBatchSize() { } private java.util.List signatureInfos_ = - java.util.Collections.emptyList(); + java.util.Collections.emptyList(); + private void ensureSignatureInfosIsMutable() { if (!((bitField0_ & 0x00000020) != 0)) { - signatureInfos_ = new java.util.ArrayList(signatureInfos_); + signatureInfos_ = + new java.util.ArrayList(signatureInfos_); bitField0_ |= 0x00000020; - } + } } private com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.SignatureInfo, TemporaryExposureKeyFormat.SignatureInfo.Builder, TemporaryExposureKeyFormat.SignatureInfoOrBuilder> signatureInfosBuilder_; + TemporaryExposureKeyFormat.SignatureInfo, + TemporaryExposureKeyFormat.SignatureInfo.Builder, + TemporaryExposureKeyFormat.SignatureInfoOrBuilder> + signatureInfosBuilder_; /** + * + * *
        * Information about associated signatures
        * 
@@ -1362,6 +1430,8 @@ public java.util.List getSignatureInfo } } /** + * + * *
        * Information about associated signatures
        * 
@@ -1376,6 +1446,8 @@ public int getSignatureInfosCount() { } } /** + * + * *
        * Information about associated signatures
        * 
@@ -1390,14 +1462,15 @@ public TemporaryExposureKeyFormat.SignatureInfo getSignatureInfos(int index) { } } /** + * + * *
        * Information about associated signatures
        * 
* * repeated .SignatureInfo signature_infos = 6; */ - public Builder setSignatureInfos( - int index, TemporaryExposureKeyFormat.SignatureInfo value) { + public Builder setSignatureInfos(int index, TemporaryExposureKeyFormat.SignatureInfo value) { if (signatureInfosBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -1411,6 +1484,8 @@ public Builder setSignatureInfos( return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1429,6 +1504,8 @@ public Builder setSignatureInfos( return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1449,14 +1526,15 @@ public Builder addSignatureInfos(TemporaryExposureKeyFormat.SignatureInfo value) return this; } /** + * + * *
        * Information about associated signatures
        * 
* * repeated .SignatureInfo signature_infos = 6; */ - public Builder addSignatureInfos( - int index, TemporaryExposureKeyFormat.SignatureInfo value) { + public Builder addSignatureInfos(int index, TemporaryExposureKeyFormat.SignatureInfo value) { if (signatureInfosBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -1470,6 +1548,8 @@ public Builder addSignatureInfos( return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1488,6 +1568,8 @@ public Builder addSignatureInfos( return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1506,6 +1588,8 @@ public Builder addSignatureInfos( return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1516,8 +1600,7 @@ public Builder addAllSignatureInfos( java.lang.Iterable values) { if (signatureInfosBuilder_ == null) { ensureSignatureInfosIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, signatureInfos_); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, signatureInfos_); onChanged(); } else { signatureInfosBuilder_.addAllMessages(values); @@ -1525,6 +1608,8 @@ public Builder addAllSignatureInfos( return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1542,6 +1627,8 @@ public Builder clearSignatureInfos() { return this; } /** + * + * *
        * Information about associated signatures
        * 
@@ -1559,17 +1646,20 @@ public Builder removeSignatureInfos(int index) { return this; } /** + * + * *
        * Information about associated signatures
        * 
* * repeated .SignatureInfo signature_infos = 6; */ - public TemporaryExposureKeyFormat.SignatureInfo.Builder getSignatureInfosBuilder( - int index) { + public TemporaryExposureKeyFormat.SignatureInfo.Builder getSignatureInfosBuilder(int index) { return getSignatureInfosFieldBuilder().getBuilder(index); } /** + * + * *
        * Information about associated signatures
        * 
@@ -1579,19 +1669,22 @@ public TemporaryExposureKeyFormat.SignatureInfo.Builder getSignatureInfosBuilder public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuilder( int index) { if (signatureInfosBuilder_ == null) { - return signatureInfos_.get(index); } else { + return signatureInfos_.get(index); + } else { return signatureInfosBuilder_.getMessageOrBuilder(index); } } /** + * + * *
        * Information about associated signatures
        * 
* * repeated .SignatureInfo signature_infos = 6; */ - public java.util.List - getSignatureInfosOrBuilderList() { + public java.util.List + getSignatureInfosOrBuilderList() { if (signatureInfosBuilder_ != null) { return signatureInfosBuilder_.getMessageOrBuilderList(); } else { @@ -1599,6 +1692,8 @@ public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuil } } /** + * + * *
        * Information about associated signatures
        * 
@@ -1606,38 +1701,47 @@ public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfosOrBuil * repeated .SignatureInfo signature_infos = 6; */ public TemporaryExposureKeyFormat.SignatureInfo.Builder addSignatureInfosBuilder() { - return getSignatureInfosFieldBuilder().addBuilder( - TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance()); + return getSignatureInfosFieldBuilder() + .addBuilder(TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance()); } /** + * + * *
        * Information about associated signatures
        * 
* * repeated .SignatureInfo signature_infos = 6; */ - public TemporaryExposureKeyFormat.SignatureInfo.Builder addSignatureInfosBuilder( - int index) { - return getSignatureInfosFieldBuilder().addBuilder( - index, TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance()); + public TemporaryExposureKeyFormat.SignatureInfo.Builder addSignatureInfosBuilder(int index) { + return getSignatureInfosFieldBuilder() + .addBuilder(index, TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance()); } /** + * + * *
        * Information about associated signatures
        * 
* * repeated .SignatureInfo signature_infos = 6; */ - public java.util.List - getSignatureInfosBuilderList() { + public java.util.List + getSignatureInfosBuilderList() { return getSignatureInfosFieldBuilder().getBuilderList(); } + private com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.SignatureInfo, TemporaryExposureKeyFormat.SignatureInfo.Builder, TemporaryExposureKeyFormat.SignatureInfoOrBuilder> + TemporaryExposureKeyFormat.SignatureInfo, + TemporaryExposureKeyFormat.SignatureInfo.Builder, + TemporaryExposureKeyFormat.SignatureInfoOrBuilder> getSignatureInfosFieldBuilder() { if (signatureInfosBuilder_ == null) { - signatureInfosBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.SignatureInfo, TemporaryExposureKeyFormat.SignatureInfo.Builder, TemporaryExposureKeyFormat.SignatureInfoOrBuilder>( + signatureInfosBuilder_ = + new com.google.protobuf.RepeatedFieldBuilderV3< + TemporaryExposureKeyFormat.SignatureInfo, + TemporaryExposureKeyFormat.SignatureInfo.Builder, + TemporaryExposureKeyFormat.SignatureInfoOrBuilder>( signatureInfos_, ((bitField0_ & 0x00000020) != 0), getParentForChildren(), @@ -1648,18 +1752,24 @@ public TemporaryExposureKeyFormat.SignatureInfo.Builder addSignatureInfosBuilder } private java.util.List keys_ = - java.util.Collections.emptyList(); + java.util.Collections.emptyList(); + private void ensureKeysIsMutable() { if (!((bitField0_ & 0x00000040) != 0)) { keys_ = new java.util.ArrayList(keys_); bitField0_ |= 0x00000040; - } + } } private com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.TemporaryExposureKey, TemporaryExposureKeyFormat.TemporaryExposureKey.Builder, TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder> keysBuilder_; + TemporaryExposureKeyFormat.TemporaryExposureKey, + TemporaryExposureKeyFormat.TemporaryExposureKey.Builder, + TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder> + keysBuilder_; /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1674,6 +1784,8 @@ public java.util.List getKeysLi } } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1688,6 +1800,8 @@ public int getKeysCount() { } } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1702,14 +1816,15 @@ public TemporaryExposureKeyFormat.TemporaryExposureKey getKeys(int index) { } } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public Builder setKeys( - int index, TemporaryExposureKeyFormat.TemporaryExposureKey value) { + public Builder setKeys(int index, TemporaryExposureKeyFormat.TemporaryExposureKey value) { if (keysBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -1723,6 +1838,8 @@ public Builder setKeys( return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1741,6 +1858,8 @@ public Builder setKeys( return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1761,14 +1880,15 @@ public Builder addKeys(TemporaryExposureKeyFormat.TemporaryExposureKey value) { return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public Builder addKeys( - int index, TemporaryExposureKeyFormat.TemporaryExposureKey value) { + public Builder addKeys(int index, TemporaryExposureKeyFormat.TemporaryExposureKey value) { if (keysBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -1782,6 +1902,8 @@ public Builder addKeys( return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1800,6 +1922,8 @@ public Builder addKeys( return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1818,6 +1942,8 @@ public Builder addKeys( return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1828,8 +1954,7 @@ public Builder addAllKeys( java.lang.Iterable values) { if (keysBuilder_ == null) { ensureKeysIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, keys_); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, keys_); onChanged(); } else { keysBuilder_.addAllMessages(values); @@ -1837,6 +1962,8 @@ public Builder addAllKeys( return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1854,6 +1981,8 @@ public Builder clearKeys() { return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1871,39 +2000,44 @@ public Builder removeKeys(int index) { return this; } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public TemporaryExposureKeyFormat.TemporaryExposureKey.Builder getKeysBuilder( - int index) { + public TemporaryExposureKeyFormat.TemporaryExposureKey.Builder getKeysBuilder(int index) { return getKeysFieldBuilder().getBuilder(index); } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder( - int index) { + public TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder(int index) { if (keysBuilder_ == null) { - return keys_.get(index); } else { + return keys_.get(index); + } else { return keysBuilder_.getMessageOrBuilder(index); } } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public java.util.List - getKeysOrBuilderList() { + public java.util.List + getKeysOrBuilderList() { if (keysBuilder_ != null) { return keysBuilder_.getMessageOrBuilderList(); } else { @@ -1911,6 +2045,8 @@ public TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder } } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
@@ -1918,46 +2054,54 @@ public TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder getKeysOrBuilder * repeated .TemporaryExposureKey keys = 7; */ public TemporaryExposureKeyFormat.TemporaryExposureKey.Builder addKeysBuilder() { - return getKeysFieldBuilder().addBuilder( - TemporaryExposureKeyFormat.TemporaryExposureKey.getDefaultInstance()); + return getKeysFieldBuilder() + .addBuilder(TemporaryExposureKeyFormat.TemporaryExposureKey.getDefaultInstance()); } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public TemporaryExposureKeyFormat.TemporaryExposureKey.Builder addKeysBuilder( - int index) { - return getKeysFieldBuilder().addBuilder( - index, TemporaryExposureKeyFormat.TemporaryExposureKey.getDefaultInstance()); + public TemporaryExposureKeyFormat.TemporaryExposureKey.Builder addKeysBuilder(int index) { + return getKeysFieldBuilder() + .addBuilder( + index, TemporaryExposureKeyFormat.TemporaryExposureKey.getDefaultInstance()); } /** + * + * *
        * The TemporaryExposureKeys themselves
        * 
* * repeated .TemporaryExposureKey keys = 7; */ - public java.util.List - getKeysBuilderList() { + public java.util.List + getKeysBuilderList() { return getKeysFieldBuilder().getBuilderList(); } + private com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.TemporaryExposureKey, TemporaryExposureKeyFormat.TemporaryExposureKey.Builder, TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder> + TemporaryExposureKeyFormat.TemporaryExposureKey, + TemporaryExposureKeyFormat.TemporaryExposureKey.Builder, + TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder> getKeysFieldBuilder() { if (keysBuilder_ == null) { - keysBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.TemporaryExposureKey, TemporaryExposureKeyFormat.TemporaryExposureKey.Builder, TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder>( - keys_, - ((bitField0_ & 0x00000040) != 0), - getParentForChildren(), - isClean()); + keysBuilder_ = + new com.google.protobuf.RepeatedFieldBuilderV3< + TemporaryExposureKeyFormat.TemporaryExposureKey, + TemporaryExposureKeyFormat.TemporaryExposureKey.Builder, + TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder>( + keys_, ((bitField0_ & 0x00000040) != 0), getParentForChildren(), isClean()); keys_ = null; } return keysBuilder_; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -1970,12 +2114,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:TemporaryExposureKeyExport) } // @@protoc_insertion_point(class_scope:TemporaryExposureKeyExport) private static final TemporaryExposureKeyFormat.TemporaryExposureKeyExport DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new TemporaryExposureKeyFormat.TemporaryExposureKeyExport(); } @@ -1984,16 +2128,17 @@ public static TemporaryExposureKeyFormat.TemporaryExposureKeyExport getDefaultIn return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TemporaryExposureKeyExport parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new TemporaryExposureKeyExport(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TemporaryExposureKeyExport parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new TemporaryExposureKeyExport(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -2008,14 +2153,16 @@ public com.google.protobuf.Parser getParserForType() public TemporaryExposureKeyFormat.TemporaryExposureKeyExport getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface SignatureInfoOrBuilder extends + public interface SignatureInfoOrBuilder + extends // @@protoc_insertion_point(interface_extends:SignatureInfo) com.google.protobuf.MessageOrBuilder { /** + * + * *
      * Apple App Store Application Bundle ID
      * 
@@ -2024,6 +2171,8 @@ public interface SignatureInfoOrBuilder extends */ boolean hasAppBundleId(); /** + * + * *
      * Apple App Store Application Bundle ID
      * 
@@ -2032,16 +2181,19 @@ public interface SignatureInfoOrBuilder extends */ java.lang.String getAppBundleId(); /** + * + * *
      * Apple App Store Application Bundle ID
      * 
* * optional string app_bundle_id = 1; */ - com.google.protobuf.ByteString - getAppBundleIdBytes(); + com.google.protobuf.ByteString getAppBundleIdBytes(); /** + * + * *
      * Android App package name
      * 
@@ -2050,6 +2202,8 @@ public interface SignatureInfoOrBuilder extends */ boolean hasAndroidPackage(); /** + * + * *
      * Android App package name
      * 
@@ -2058,16 +2212,19 @@ public interface SignatureInfoOrBuilder extends */ java.lang.String getAndroidPackage(); /** + * + * *
      * Android App package name
      * 
* * optional string android_package = 2; */ - com.google.protobuf.ByteString - getAndroidPackageBytes(); + com.google.protobuf.ByteString getAndroidPackageBytes(); /** + * + * *
      * Key version for rollovers
      * 
@@ -2076,6 +2233,8 @@ public interface SignatureInfoOrBuilder extends */ boolean hasVerificationKeyVersion(); /** + * + * *
      * Key version for rollovers
      * 
@@ -2084,30 +2243,26 @@ public interface SignatureInfoOrBuilder extends */ java.lang.String getVerificationKeyVersion(); /** + * + * *
      * Key version for rollovers
      * 
* * optional string verification_key_version = 3; */ - com.google.protobuf.ByteString - getVerificationKeyVersionBytes(); + com.google.protobuf.ByteString getVerificationKeyVersionBytes(); - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ boolean hasVerificationKeyId(); - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ java.lang.String getVerificationKeyId(); - /** - * optional string verification_key_id = 4; - */ - com.google.protobuf.ByteString - getVerificationKeyIdBytes(); + /** optional string verification_key_id = 4; */ + com.google.protobuf.ByteString getVerificationKeyIdBytes(); /** + * + * *
      * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
      * 
@@ -2116,6 +2271,8 @@ public interface SignatureInfoOrBuilder extends */ boolean hasSignatureAlgorithm(); /** + * + * *
      * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
      * 
@@ -2124,27 +2281,27 @@ public interface SignatureInfoOrBuilder extends */ java.lang.String getSignatureAlgorithm(); /** + * + * *
      * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
      * 
* * optional string signature_algorithm = 5; */ - com.google.protobuf.ByteString - getSignatureAlgorithmBytes(); + com.google.protobuf.ByteString getSignatureAlgorithmBytes(); } - /** - * Protobuf type {@code SignatureInfo} - */ - public static final class SignatureInfo extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code SignatureInfo} */ + public static final class SignatureInfo extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:SignatureInfo) SignatureInfoOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use SignatureInfo.newBuilder() to construct. private SignatureInfo(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private SignatureInfo() { appBundleId_ = ""; androidPackage_ = ""; @@ -2154,10 +2311,10 @@ private SignatureInfo() { } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private SignatureInfo( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -2177,57 +2334,61 @@ private SignatureInfo( case 0: done = true; break; - case 10: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000001; - appBundleId_ = bs; - break; - } - case 18: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000002; - androidPackage_ = bs; - break; - } - case 26: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000004; - verificationKeyVersion_ = bs; - break; - } - case 34: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000008; - verificationKeyId_ = bs; - break; - } - case 42: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000010; - signatureAlgorithm_ = bs; - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 10: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + appBundleId_ = bs; + break; + } + case 18: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + androidPackage_ = bs; + break; + } + case 26: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000004; + verificationKeyVersion_ = bs; + break; + } + case 34: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000008; + verificationKeyId_ = bs; + break; + } + case 42: + { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000010; + signatureAlgorithm_ = bs; + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_SignatureInfo_descriptor; } @@ -2236,13 +2397,16 @@ private SignatureInfo( internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_SignatureInfo_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.SignatureInfo.class, TemporaryExposureKeyFormat.SignatureInfo.Builder.class); + TemporaryExposureKeyFormat.SignatureInfo.class, + TemporaryExposureKeyFormat.SignatureInfo.Builder.class); } private int bitField0_; public static final int APP_BUNDLE_ID_FIELD_NUMBER = 1; private volatile java.lang.Object appBundleId_; /** + * + * *
      * Apple App Store Application Bundle ID
      * 
@@ -2253,6 +2417,8 @@ public boolean hasAppBundleId() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
      * Apple App Store Application Bundle ID
      * 
@@ -2264,8 +2430,7 @@ public java.lang.String getAppBundleId() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { appBundleId_ = s; @@ -2274,19 +2439,19 @@ public java.lang.String getAppBundleId() { } } /** + * + * *
      * Apple App Store Application Bundle ID
      * 
* * optional string app_bundle_id = 1; */ - public com.google.protobuf.ByteString - getAppBundleIdBytes() { + public com.google.protobuf.ByteString getAppBundleIdBytes() { java.lang.Object ref = appBundleId_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); appBundleId_ = b; return b; } else { @@ -2297,6 +2462,8 @@ public java.lang.String getAppBundleId() { public static final int ANDROID_PACKAGE_FIELD_NUMBER = 2; private volatile java.lang.Object androidPackage_; /** + * + * *
      * Android App package name
      * 
@@ -2307,6 +2474,8 @@ public boolean hasAndroidPackage() { return ((bitField0_ & 0x00000002) != 0); } /** + * + * *
      * Android App package name
      * 
@@ -2318,8 +2487,7 @@ public java.lang.String getAndroidPackage() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { androidPackage_ = s; @@ -2328,19 +2496,19 @@ public java.lang.String getAndroidPackage() { } } /** + * + * *
      * Android App package name
      * 
* * optional string android_package = 2; */ - public com.google.protobuf.ByteString - getAndroidPackageBytes() { + public com.google.protobuf.ByteString getAndroidPackageBytes() { java.lang.Object ref = androidPackage_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); androidPackage_ = b; return b; } else { @@ -2351,6 +2519,8 @@ public java.lang.String getAndroidPackage() { public static final int VERIFICATION_KEY_VERSION_FIELD_NUMBER = 3; private volatile java.lang.Object verificationKeyVersion_; /** + * + * *
      * Key version for rollovers
      * 
@@ -2361,6 +2531,8 @@ public boolean hasVerificationKeyVersion() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
      * Key version for rollovers
      * 
@@ -2372,8 +2544,7 @@ public java.lang.String getVerificationKeyVersion() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { verificationKeyVersion_ = s; @@ -2382,19 +2553,19 @@ public java.lang.String getVerificationKeyVersion() { } } /** + * + * *
      * Key version for rollovers
      * 
* * optional string verification_key_version = 3; */ - public com.google.protobuf.ByteString - getVerificationKeyVersionBytes() { + public com.google.protobuf.ByteString getVerificationKeyVersionBytes() { java.lang.Object ref = verificationKeyVersion_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); verificationKeyVersion_ = b; return b; } else { @@ -2404,22 +2575,17 @@ public java.lang.String getVerificationKeyVersion() { public static final int VERIFICATION_KEY_ID_FIELD_NUMBER = 4; private volatile java.lang.Object verificationKeyId_; - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ public boolean hasVerificationKeyId() { return ((bitField0_ & 0x00000008) != 0); } - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ public java.lang.String getVerificationKeyId() { java.lang.Object ref = verificationKeyId_; if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { verificationKeyId_ = s; @@ -2427,16 +2593,12 @@ public java.lang.String getVerificationKeyId() { return s; } } - /** - * optional string verification_key_id = 4; - */ - public com.google.protobuf.ByteString - getVerificationKeyIdBytes() { + /** optional string verification_key_id = 4; */ + public com.google.protobuf.ByteString getVerificationKeyIdBytes() { java.lang.Object ref = verificationKeyId_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); verificationKeyId_ = b; return b; } else { @@ -2447,6 +2609,8 @@ public java.lang.String getVerificationKeyId() { public static final int SIGNATURE_ALGORITHM_FIELD_NUMBER = 5; private volatile java.lang.Object signatureAlgorithm_; /** + * + * *
      * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
      * 
@@ -2457,6 +2621,8 @@ public boolean hasSignatureAlgorithm() { return ((bitField0_ & 0x00000010) != 0); } /** + * + * *
      * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
      * 
@@ -2468,8 +2634,7 @@ public java.lang.String getSignatureAlgorithm() { if (ref instanceof java.lang.String) { return (java.lang.String) ref; } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { signatureAlgorithm_ = s; @@ -2478,19 +2643,19 @@ public java.lang.String getSignatureAlgorithm() { } } /** + * + * *
      * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
      * 
* * optional string signature_algorithm = 5; */ - public com.google.protobuf.ByteString - getSignatureAlgorithmBytes() { + public com.google.protobuf.ByteString getSignatureAlgorithmBytes() { java.lang.Object ref = signatureAlgorithm_; if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); signatureAlgorithm_ = b; return b; } else { @@ -2499,6 +2664,7 @@ public java.lang.String getSignatureAlgorithm() { } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -2510,8 +2676,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 1, appBundleId_); } @@ -2543,7 +2708,8 @@ public int getSerializedSize() { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, androidPackage_); } if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, verificationKeyVersion_); + size += + com.google.protobuf.GeneratedMessageV3.computeStringSize(3, verificationKeyVersion_); } if (((bitField0_ & 0x00000008) != 0)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, verificationKeyId_); @@ -2559,37 +2725,33 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof TemporaryExposureKeyFormat.SignatureInfo)) { return super.equals(obj); } - TemporaryExposureKeyFormat.SignatureInfo other = (TemporaryExposureKeyFormat.SignatureInfo) obj; + TemporaryExposureKeyFormat.SignatureInfo other = + (TemporaryExposureKeyFormat.SignatureInfo) obj; if (hasAppBundleId() != other.hasAppBundleId()) return false; if (hasAppBundleId()) { - if (!getAppBundleId() - .equals(other.getAppBundleId())) return false; + if (!getAppBundleId().equals(other.getAppBundleId())) return false; } if (hasAndroidPackage() != other.hasAndroidPackage()) return false; if (hasAndroidPackage()) { - if (!getAndroidPackage() - .equals(other.getAndroidPackage())) return false; + if (!getAndroidPackage().equals(other.getAndroidPackage())) return false; } if (hasVerificationKeyVersion() != other.hasVerificationKeyVersion()) return false; if (hasVerificationKeyVersion()) { - if (!getVerificationKeyVersion() - .equals(other.getVerificationKeyVersion())) return false; + if (!getVerificationKeyVersion().equals(other.getVerificationKeyVersion())) return false; } if (hasVerificationKeyId() != other.hasVerificationKeyId()) return false; if (hasVerificationKeyId()) { - if (!getVerificationKeyId() - .equals(other.getVerificationKeyId())) return false; + if (!getVerificationKeyId().equals(other.getVerificationKeyId())) return false; } if (hasSignatureAlgorithm() != other.hasSignatureAlgorithm()) return false; if (hasSignatureAlgorithm()) { - if (!getSignatureAlgorithm() - .equals(other.getSignatureAlgorithm())) return false; + if (!getSignatureAlgorithm().equals(other.getSignatureAlgorithm())) return false; } if (!unknownFields.equals(other.unknownFields)) return false; return true; @@ -2627,88 +2789,94 @@ public int hashCode() { return hash; } - public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( - java.nio.ByteBuffer data) + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom(java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static TemporaryExposureKeyFormat.SignatureInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.SignatureInfo parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.SignatureInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.SignatureInfo parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(TemporaryExposureKeyFormat.SignatureInfo prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -2717,15 +2885,13 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code SignatureInfo} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code SignatureInfo} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:SignatureInfo) TemporaryExposureKeyFormat.SignatureInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_SignatureInfo_descriptor; } @@ -2734,7 +2900,8 @@ public static final class Builder extends internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_SignatureInfo_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.SignatureInfo.class, TemporaryExposureKeyFormat.SignatureInfo.Builder.class); + TemporaryExposureKeyFormat.SignatureInfo.class, + TemporaryExposureKeyFormat.SignatureInfo.Builder.class); } // Construct using TemporaryExposureKeyFormat.SignatureInfo.newBuilder() @@ -2742,16 +2909,15 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {} } + @java.lang.Override public Builder clear() { super.clear(); @@ -2769,8 +2935,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return TemporaryExposureKeyFormat.internal_static_SignatureInfo_descriptor; } @@ -2790,7 +2955,8 @@ public TemporaryExposureKeyFormat.SignatureInfo build() { @java.lang.Override public TemporaryExposureKeyFormat.SignatureInfo buildPartial() { - TemporaryExposureKeyFormat.SignatureInfo result = new TemporaryExposureKeyFormat.SignatureInfo(this); + TemporaryExposureKeyFormat.SignatureInfo result = + new TemporaryExposureKeyFormat.SignatureInfo(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -2822,38 +2988,41 @@ public TemporaryExposureKeyFormat.SignatureInfo buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof TemporaryExposureKeyFormat.SignatureInfo) { - return mergeFrom((TemporaryExposureKeyFormat.SignatureInfo)other); + return mergeFrom((TemporaryExposureKeyFormat.SignatureInfo) other); } else { super.mergeFrom(other); return this; @@ -2915,10 +3084,13 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private java.lang.Object appBundleId_ = ""; /** + * + * *
        * Apple App Store Application Bundle ID
        * 
@@ -2929,6 +3101,8 @@ public boolean hasAppBundleId() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
        * Apple App Store Application Bundle ID
        * 
@@ -2938,8 +3112,7 @@ public boolean hasAppBundleId() { public java.lang.String getAppBundleId() { java.lang.Object ref = appBundleId_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { appBundleId_ = s; @@ -2950,19 +3123,19 @@ public java.lang.String getAppBundleId() { } } /** + * + * *
        * Apple App Store Application Bundle ID
        * 
* * optional string app_bundle_id = 1; */ - public com.google.protobuf.ByteString - getAppBundleIdBytes() { + public com.google.protobuf.ByteString getAppBundleIdBytes() { java.lang.Object ref = appBundleId_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); appBundleId_ = b; return b; } else { @@ -2970,23 +3143,26 @@ public java.lang.String getAppBundleId() { } } /** + * + * *
        * Apple App Store Application Bundle ID
        * 
* * optional string app_bundle_id = 1; */ - public Builder setAppBundleId( - java.lang.String value) { + public Builder setAppBundleId(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; appBundleId_ = value; onChanged(); return this; } /** + * + * *
        * Apple App Store Application Bundle ID
        * 
@@ -3000,18 +3176,19 @@ public Builder clearAppBundleId() { return this; } /** + * + * *
        * Apple App Store Application Bundle ID
        * 
* * optional string app_bundle_id = 1; */ - public Builder setAppBundleIdBytes( - com.google.protobuf.ByteString value) { + public Builder setAppBundleIdBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; appBundleId_ = value; onChanged(); return this; @@ -3019,6 +3196,8 @@ public Builder setAppBundleIdBytes( private java.lang.Object androidPackage_ = ""; /** + * + * *
        * Android App package name
        * 
@@ -3029,6 +3208,8 @@ public boolean hasAndroidPackage() { return ((bitField0_ & 0x00000002) != 0); } /** + * + * *
        * Android App package name
        * 
@@ -3038,8 +3219,7 @@ public boolean hasAndroidPackage() { public java.lang.String getAndroidPackage() { java.lang.Object ref = androidPackage_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { androidPackage_ = s; @@ -3050,19 +3230,19 @@ public java.lang.String getAndroidPackage() { } } /** + * + * *
        * Android App package name
        * 
* * optional string android_package = 2; */ - public com.google.protobuf.ByteString - getAndroidPackageBytes() { + public com.google.protobuf.ByteString getAndroidPackageBytes() { java.lang.Object ref = androidPackage_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); androidPackage_ = b; return b; } else { @@ -3070,23 +3250,26 @@ public java.lang.String getAndroidPackage() { } } /** + * + * *
        * Android App package name
        * 
* * optional string android_package = 2; */ - public Builder setAndroidPackage( - java.lang.String value) { + public Builder setAndroidPackage(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; androidPackage_ = value; onChanged(); return this; } /** + * + * *
        * Android App package name
        * 
@@ -3100,18 +3283,19 @@ public Builder clearAndroidPackage() { return this; } /** + * + * *
        * Android App package name
        * 
* * optional string android_package = 2; */ - public Builder setAndroidPackageBytes( - com.google.protobuf.ByteString value) { + public Builder setAndroidPackageBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; androidPackage_ = value; onChanged(); return this; @@ -3119,6 +3303,8 @@ public Builder setAndroidPackageBytes( private java.lang.Object verificationKeyVersion_ = ""; /** + * + * *
        * Key version for rollovers
        * 
@@ -3129,6 +3315,8 @@ public boolean hasVerificationKeyVersion() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
        * Key version for rollovers
        * 
@@ -3138,8 +3326,7 @@ public boolean hasVerificationKeyVersion() { public java.lang.String getVerificationKeyVersion() { java.lang.Object ref = verificationKeyVersion_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { verificationKeyVersion_ = s; @@ -3150,19 +3337,19 @@ public java.lang.String getVerificationKeyVersion() { } } /** + * + * *
        * Key version for rollovers
        * 
* * optional string verification_key_version = 3; */ - public com.google.protobuf.ByteString - getVerificationKeyVersionBytes() { + public com.google.protobuf.ByteString getVerificationKeyVersionBytes() { java.lang.Object ref = verificationKeyVersion_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); verificationKeyVersion_ = b; return b; } else { @@ -3170,23 +3357,26 @@ public java.lang.String getVerificationKeyVersion() { } } /** + * + * *
        * Key version for rollovers
        * 
* * optional string verification_key_version = 3; */ - public Builder setVerificationKeyVersion( - java.lang.String value) { + public Builder setVerificationKeyVersion(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; verificationKeyVersion_ = value; onChanged(); return this; } /** + * + * *
        * Key version for rollovers
        * 
@@ -3200,38 +3390,34 @@ public Builder clearVerificationKeyVersion() { return this; } /** + * + * *
        * Key version for rollovers
        * 
* * optional string verification_key_version = 3; */ - public Builder setVerificationKeyVersionBytes( - com.google.protobuf.ByteString value) { + public Builder setVerificationKeyVersionBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; verificationKeyVersion_ = value; onChanged(); return this; } private java.lang.Object verificationKeyId_ = ""; - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ public boolean hasVerificationKeyId() { return ((bitField0_ & 0x00000008) != 0); } - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ public java.lang.String getVerificationKeyId() { java.lang.Object ref = verificationKeyId_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { verificationKeyId_ = s; @@ -3241,53 +3427,41 @@ public java.lang.String getVerificationKeyId() { return (java.lang.String) ref; } } - /** - * optional string verification_key_id = 4; - */ - public com.google.protobuf.ByteString - getVerificationKeyIdBytes() { + /** optional string verification_key_id = 4; */ + public com.google.protobuf.ByteString getVerificationKeyIdBytes() { java.lang.Object ref = verificationKeyId_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); verificationKeyId_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } - /** - * optional string verification_key_id = 4; - */ - public Builder setVerificationKeyId( - java.lang.String value) { + /** optional string verification_key_id = 4; */ + public Builder setVerificationKeyId(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000008; + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; verificationKeyId_ = value; onChanged(); return this; } - /** - * optional string verification_key_id = 4; - */ + /** optional string verification_key_id = 4; */ public Builder clearVerificationKeyId() { bitField0_ = (bitField0_ & ~0x00000008); verificationKeyId_ = getDefaultInstance().getVerificationKeyId(); onChanged(); return this; } - /** - * optional string verification_key_id = 4; - */ - public Builder setVerificationKeyIdBytes( - com.google.protobuf.ByteString value) { + /** optional string verification_key_id = 4; */ + public Builder setVerificationKeyIdBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000008; + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; verificationKeyId_ = value; onChanged(); return this; @@ -3295,6 +3469,8 @@ public Builder setVerificationKeyIdBytes( private java.lang.Object signatureAlgorithm_ = ""; /** + * + * *
        * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
        * 
@@ -3305,6 +3481,8 @@ public boolean hasSignatureAlgorithm() { return ((bitField0_ & 0x00000010) != 0); } /** + * + * *
        * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
        * 
@@ -3314,8 +3492,7 @@ public boolean hasSignatureAlgorithm() { public java.lang.String getSignatureAlgorithm() { java.lang.Object ref = signatureAlgorithm_; if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; java.lang.String s = bs.toStringUtf8(); if (bs.isValidUtf8()) { signatureAlgorithm_ = s; @@ -3326,19 +3503,19 @@ public java.lang.String getSignatureAlgorithm() { } } /** + * + * *
        * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
        * 
* * optional string signature_algorithm = 5; */ - public com.google.protobuf.ByteString - getSignatureAlgorithmBytes() { + public com.google.protobuf.ByteString getSignatureAlgorithmBytes() { java.lang.Object ref = signatureAlgorithm_; if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); signatureAlgorithm_ = b; return b; } else { @@ -3346,23 +3523,26 @@ public java.lang.String getSignatureAlgorithm() { } } /** + * + * *
        * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
        * 
* * optional string signature_algorithm = 5; */ - public Builder setSignatureAlgorithm( - java.lang.String value) { + public Builder setSignatureAlgorithm(java.lang.String value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000010; + throw new NullPointerException(); + } + bitField0_ |= 0x00000010; signatureAlgorithm_ = value; onChanged(); return this; } /** + * + * *
        * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
        * 
@@ -3376,22 +3556,24 @@ public Builder clearSignatureAlgorithm() { return this; } /** + * + * *
        * E.g. ECDSA using a p-256 curve and SHA-256 as a hash function
        * 
* * optional string signature_algorithm = 5; */ - public Builder setSignatureAlgorithmBytes( - com.google.protobuf.ByteString value) { + public Builder setSignatureAlgorithmBytes(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000010; + throw new NullPointerException(); + } + bitField0_ |= 0x00000010; signatureAlgorithm_ = value; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -3404,12 +3586,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:SignatureInfo) } // @@protoc_insertion_point(class_scope:SignatureInfo) private static final TemporaryExposureKeyFormat.SignatureInfo DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new TemporaryExposureKeyFormat.SignatureInfo(); } @@ -3418,16 +3600,17 @@ public static TemporaryExposureKeyFormat.SignatureInfo getDefaultInstance() { return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SignatureInfo parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new SignatureInfo(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SignatureInfo parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new SignatureInfo(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -3442,14 +3625,16 @@ public com.google.protobuf.Parser getParserForType() { public TemporaryExposureKeyFormat.SignatureInfo getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface TemporaryExposureKeyOrBuilder extends + public interface TemporaryExposureKeyOrBuilder + extends // @@protoc_insertion_point(interface_extends:TemporaryExposureKey) com.google.protobuf.MessageOrBuilder { /** + * + * *
      * Key of infected user
      * 
@@ -3458,6 +3643,8 @@ public interface TemporaryExposureKeyOrBuilder extends */ boolean hasKeyData(); /** + * + * *
      * Key of infected user
      * 
@@ -3467,6 +3654,8 @@ public interface TemporaryExposureKeyOrBuilder extends com.google.protobuf.ByteString getKeyData(); /** + * + * *
      * Varying risk associated with a key depending on diagnosis method
      * 
@@ -3475,6 +3664,8 @@ public interface TemporaryExposureKeyOrBuilder extends */ boolean hasTransmissionRiskLevel(); /** + * + * *
      * Varying risk associated with a key depending on diagnosis method
      * 
@@ -3484,6 +3675,8 @@ public interface TemporaryExposureKeyOrBuilder extends int getTransmissionRiskLevel(); /** + * + * *
      * The interval number since epoch for which a key starts
      * 
@@ -3492,6 +3685,8 @@ public interface TemporaryExposureKeyOrBuilder extends */ boolean hasRollingStartIntervalNumber(); /** + * + * *
      * The interval number since epoch for which a key starts
      * 
@@ -3501,6 +3696,8 @@ public interface TemporaryExposureKeyOrBuilder extends int getRollingStartIntervalNumber(); /** + * + * *
      * Increments of 10 minutes describing how long a key is valid
      * 
@@ -3509,6 +3706,8 @@ public interface TemporaryExposureKeyOrBuilder extends */ boolean hasRollingPeriod(); /** + * + * *
      * Increments of 10 minutes describing how long a key is valid
      * 
@@ -3517,28 +3716,27 @@ public interface TemporaryExposureKeyOrBuilder extends */ int getRollingPeriod(); } - /** - * Protobuf type {@code TemporaryExposureKey} - */ - public static final class TemporaryExposureKey extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code TemporaryExposureKey} */ + public static final class TemporaryExposureKey extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:TemporaryExposureKey) TemporaryExposureKeyOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use TemporaryExposureKey.newBuilder() to construct. private TemporaryExposureKey(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private TemporaryExposureKey() { keyData_ = com.google.protobuf.ByteString.EMPTY; rollingPeriod_ = 144; } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private TemporaryExposureKey( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -3558,47 +3756,50 @@ private TemporaryExposureKey( case 0: done = true; break; - case 10: { - bitField0_ |= 0x00000001; - keyData_ = input.readBytes(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - transmissionRiskLevel_ = input.readInt32(); - break; - } - case 24: { - bitField0_ |= 0x00000004; - rollingStartIntervalNumber_ = input.readInt32(); - break; - } - case 32: { - bitField0_ |= 0x00000008; - rollingPeriod_ = input.readInt32(); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 10: + { + bitField0_ |= 0x00000001; + keyData_ = input.readBytes(); + break; + } + case 16: + { + bitField0_ |= 0x00000002; + transmissionRiskLevel_ = input.readInt32(); + break; + } + case 24: + { + bitField0_ |= 0x00000004; + rollingStartIntervalNumber_ = input.readInt32(); + break; + } + case 32: + { + bitField0_ |= 0x00000008; + rollingPeriod_ = input.readInt32(); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKey_descriptor; } @@ -3607,13 +3808,16 @@ private TemporaryExposureKey( internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKey_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TemporaryExposureKey.class, TemporaryExposureKeyFormat.TemporaryExposureKey.Builder.class); + TemporaryExposureKeyFormat.TemporaryExposureKey.class, + TemporaryExposureKeyFormat.TemporaryExposureKey.Builder.class); } private int bitField0_; public static final int KEY_DATA_FIELD_NUMBER = 1; private com.google.protobuf.ByteString keyData_; /** + * + * *
      * Key of infected user
      * 
@@ -3624,6 +3828,8 @@ public boolean hasKeyData() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
      * Key of infected user
      * 
@@ -3637,6 +3843,8 @@ public com.google.protobuf.ByteString getKeyData() { public static final int TRANSMISSION_RISK_LEVEL_FIELD_NUMBER = 2; private int transmissionRiskLevel_; /** + * + * *
      * Varying risk associated with a key depending on diagnosis method
      * 
@@ -3647,6 +3855,8 @@ public boolean hasTransmissionRiskLevel() { return ((bitField0_ & 0x00000002) != 0); } /** + * + * *
      * Varying risk associated with a key depending on diagnosis method
      * 
@@ -3660,6 +3870,8 @@ public int getTransmissionRiskLevel() { public static final int ROLLING_START_INTERVAL_NUMBER_FIELD_NUMBER = 3; private int rollingStartIntervalNumber_; /** + * + * *
      * The interval number since epoch for which a key starts
      * 
@@ -3670,6 +3882,8 @@ public boolean hasRollingStartIntervalNumber() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
      * The interval number since epoch for which a key starts
      * 
@@ -3683,6 +3897,8 @@ public int getRollingStartIntervalNumber() { public static final int ROLLING_PERIOD_FIELD_NUMBER = 4; private int rollingPeriod_; /** + * + * *
      * Increments of 10 minutes describing how long a key is valid
      * 
@@ -3693,6 +3909,8 @@ public boolean hasRollingPeriod() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
      * Increments of 10 minutes describing how long a key is valid
      * 
@@ -3704,6 +3922,7 @@ public int getRollingPeriod() { } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -3715,8 +3934,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { output.writeBytes(1, keyData_); } @@ -3739,20 +3957,17 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, keyData_); + size += com.google.protobuf.CodedOutputStream.computeBytesSize(1, keyData_); } if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, transmissionRiskLevel_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(2, transmissionRiskLevel_); } if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, rollingStartIntervalNumber_); + size += + com.google.protobuf.CodedOutputStream.computeInt32Size(3, rollingStartIntervalNumber_); } if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, rollingPeriod_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(4, rollingPeriod_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -3762,32 +3977,29 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof TemporaryExposureKeyFormat.TemporaryExposureKey)) { return super.equals(obj); } - TemporaryExposureKeyFormat.TemporaryExposureKey other = (TemporaryExposureKeyFormat.TemporaryExposureKey) obj; + TemporaryExposureKeyFormat.TemporaryExposureKey other = + (TemporaryExposureKeyFormat.TemporaryExposureKey) obj; if (hasKeyData() != other.hasKeyData()) return false; if (hasKeyData()) { - if (!getKeyData() - .equals(other.getKeyData())) return false; + if (!getKeyData().equals(other.getKeyData())) return false; } if (hasTransmissionRiskLevel() != other.hasTransmissionRiskLevel()) return false; if (hasTransmissionRiskLevel()) { - if (getTransmissionRiskLevel() - != other.getTransmissionRiskLevel()) return false; + if (getTransmissionRiskLevel() != other.getTransmissionRiskLevel()) return false; } if (hasRollingStartIntervalNumber() != other.hasRollingStartIntervalNumber()) return false; if (hasRollingStartIntervalNumber()) { - if (getRollingStartIntervalNumber() - != other.getRollingStartIntervalNumber()) return false; + if (getRollingStartIntervalNumber() != other.getRollingStartIntervalNumber()) return false; } if (hasRollingPeriod() != other.hasRollingPeriod()) return false; if (hasRollingPeriod()) { - if (getRollingPeriod() - != other.getRollingPeriod()) return false; + if (getRollingPeriod() != other.getRollingPeriod()) return false; } if (!unknownFields.equals(other.unknownFields)) return false; return true; @@ -3822,87 +4034,93 @@ public int hashCode() { } public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { + java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static TemporaryExposureKeyFormat.TemporaryExposureKey parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TemporaryExposureKey parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(TemporaryExposureKeyFormat.TemporaryExposureKey prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -3911,15 +4129,13 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code TemporaryExposureKey} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code TemporaryExposureKey} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:TemporaryExposureKey) TemporaryExposureKeyFormat.TemporaryExposureKeyOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKey_descriptor; } @@ -3928,7 +4144,8 @@ public static final class Builder extends internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKey_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TemporaryExposureKey.class, TemporaryExposureKeyFormat.TemporaryExposureKey.Builder.class); + TemporaryExposureKeyFormat.TemporaryExposureKey.class, + TemporaryExposureKeyFormat.TemporaryExposureKey.Builder.class); } // Construct using TemporaryExposureKeyFormat.TemporaryExposureKey.newBuilder() @@ -3936,16 +4153,15 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {} } + @java.lang.Override public Builder clear() { super.clear(); @@ -3961,8 +4177,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return TemporaryExposureKeyFormat.internal_static_TemporaryExposureKey_descriptor; } @@ -3982,7 +4197,8 @@ public TemporaryExposureKeyFormat.TemporaryExposureKey build() { @java.lang.Override public TemporaryExposureKeyFormat.TemporaryExposureKey buildPartial() { - TemporaryExposureKeyFormat.TemporaryExposureKey result = new TemporaryExposureKeyFormat.TemporaryExposureKey(this); + TemporaryExposureKeyFormat.TemporaryExposureKey result = + new TemporaryExposureKeyFormat.TemporaryExposureKey(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -4010,38 +4226,41 @@ public TemporaryExposureKeyFormat.TemporaryExposureKey buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof TemporaryExposureKeyFormat.TemporaryExposureKey) { - return mergeFrom((TemporaryExposureKeyFormat.TemporaryExposureKey)other); + return mergeFrom((TemporaryExposureKeyFormat.TemporaryExposureKey) other); } else { super.mergeFrom(other); return this; @@ -4049,7 +4268,8 @@ public Builder mergeFrom(com.google.protobuf.Message other) { } public Builder mergeFrom(TemporaryExposureKeyFormat.TemporaryExposureKey other) { - if (other == TemporaryExposureKeyFormat.TemporaryExposureKey.getDefaultInstance()) return this; + if (other == TemporaryExposureKeyFormat.TemporaryExposureKey.getDefaultInstance()) + return this; if (other.hasKeyData()) { setKeyData(other.getKeyData()); } @@ -4081,7 +4301,8 @@ public Builder mergeFrom( try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (TemporaryExposureKeyFormat.TemporaryExposureKey) e.getUnfinishedMessage(); + parsedMessage = + (TemporaryExposureKeyFormat.TemporaryExposureKey) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -4090,10 +4311,13 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private com.google.protobuf.ByteString keyData_ = com.google.protobuf.ByteString.EMPTY; /** + * + * *
        * Key of infected user
        * 
@@ -4104,6 +4328,8 @@ public boolean hasKeyData() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
        * Key of infected user
        * 
@@ -4114,6 +4340,8 @@ public com.google.protobuf.ByteString getKeyData() { return keyData_; } /** + * + * *
        * Key of infected user
        * 
@@ -4122,14 +4350,16 @@ public com.google.protobuf.ByteString getKeyData() { */ public Builder setKeyData(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; keyData_ = value; onChanged(); return this; } /** + * + * *
        * Key of infected user
        * 
@@ -4143,8 +4373,10 @@ public Builder clearKeyData() { return this; } - private int transmissionRiskLevel_ ; + private int transmissionRiskLevel_; /** + * + * *
        * Varying risk associated with a key depending on diagnosis method
        * 
@@ -4155,6 +4387,8 @@ public boolean hasTransmissionRiskLevel() { return ((bitField0_ & 0x00000002) != 0); } /** + * + * *
        * Varying risk associated with a key depending on diagnosis method
        * 
@@ -4165,6 +4399,8 @@ public int getTransmissionRiskLevel() { return transmissionRiskLevel_; } /** + * + * *
        * Varying risk associated with a key depending on diagnosis method
        * 
@@ -4178,6 +4414,8 @@ public Builder setTransmissionRiskLevel(int value) { return this; } /** + * + * *
        * Varying risk associated with a key depending on diagnosis method
        * 
@@ -4191,8 +4429,10 @@ public Builder clearTransmissionRiskLevel() { return this; } - private int rollingStartIntervalNumber_ ; + private int rollingStartIntervalNumber_; /** + * + * *
        * The interval number since epoch for which a key starts
        * 
@@ -4203,6 +4443,8 @@ public boolean hasRollingStartIntervalNumber() { return ((bitField0_ & 0x00000004) != 0); } /** + * + * *
        * The interval number since epoch for which a key starts
        * 
@@ -4213,6 +4455,8 @@ public int getRollingStartIntervalNumber() { return rollingStartIntervalNumber_; } /** + * + * *
        * The interval number since epoch for which a key starts
        * 
@@ -4226,6 +4470,8 @@ public Builder setRollingStartIntervalNumber(int value) { return this; } /** + * + * *
        * The interval number since epoch for which a key starts
        * 
@@ -4241,6 +4487,8 @@ public Builder clearRollingStartIntervalNumber() { private int rollingPeriod_ = 144; /** + * + * *
        * Increments of 10 minutes describing how long a key is valid
        * 
@@ -4251,6 +4499,8 @@ public boolean hasRollingPeriod() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
        * Increments of 10 minutes describing how long a key is valid
        * 
@@ -4261,6 +4511,8 @@ public int getRollingPeriod() { return rollingPeriod_; } /** + * + * *
        * Increments of 10 minutes describing how long a key is valid
        * 
@@ -4274,6 +4526,8 @@ public Builder setRollingPeriod(int value) { return this; } /** + * + * *
        * Increments of 10 minutes describing how long a key is valid
        * 
@@ -4286,6 +4540,7 @@ public Builder clearRollingPeriod() { onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -4298,12 +4553,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:TemporaryExposureKey) } // @@protoc_insertion_point(class_scope:TemporaryExposureKey) private static final TemporaryExposureKeyFormat.TemporaryExposureKey DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new TemporaryExposureKeyFormat.TemporaryExposureKey(); } @@ -4312,16 +4567,17 @@ public static TemporaryExposureKeyFormat.TemporaryExposureKey getDefaultInstance return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TemporaryExposureKey parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new TemporaryExposureKey(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TemporaryExposureKey parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new TemporaryExposureKey(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -4336,58 +4592,45 @@ public com.google.protobuf.Parser getParserForType() { public TemporaryExposureKeyFormat.TemporaryExposureKey getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface TEKSignatureListOrBuilder extends + public interface TEKSignatureListOrBuilder + extends // @@protoc_insertion_point(interface_extends:TEKSignatureList) com.google.protobuf.MessageOrBuilder { - /** - * repeated .TEKSignature signatures = 1; - */ - java.util.List - getSignaturesList(); - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ + java.util.List getSignaturesList(); + /** repeated .TEKSignature signatures = 1; */ TemporaryExposureKeyFormat.TEKSignature getSignatures(int index); - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ int getSignaturesCount(); - /** - * repeated .TEKSignature signatures = 1; - */ - java.util.List + /** repeated .TEKSignature signatures = 1; */ + java.util.List getSignaturesOrBuilderList(); - /** - * repeated .TEKSignature signatures = 1; - */ - TemporaryExposureKeyFormat.TEKSignatureOrBuilder getSignaturesOrBuilder( - int index); + /** repeated .TEKSignature signatures = 1; */ + TemporaryExposureKeyFormat.TEKSignatureOrBuilder getSignaturesOrBuilder(int index); } - /** - * Protobuf type {@code TEKSignatureList} - */ - public static final class TEKSignatureList extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code TEKSignatureList} */ + public static final class TEKSignatureList extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:TEKSignatureList) TEKSignatureListOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use TEKSignatureList.newBuilder() to construct. private TEKSignatureList(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private TEKSignatureList() { signatures_ = java.util.Collections.emptyList(); } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private TEKSignatureList( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -4407,29 +4650,30 @@ private TEKSignatureList( case 0: done = true; break; - case 10: { - if (!((mutable_bitField0_ & 0x00000001) != 0)) { - signatures_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000001; + case 10: + { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + signatures_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + signatures_.add( + input.readMessage( + TemporaryExposureKeyFormat.TEKSignature.PARSER, extensionRegistry)); + break; } - signatures_.add( - input.readMessage(TemporaryExposureKeyFormat.TEKSignature.PARSER, extensionRegistry)); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { if (((mutable_bitField0_ & 0x00000001) != 0)) { signatures_ = java.util.Collections.unmodifiableList(signatures_); @@ -4438,8 +4682,8 @@ private TEKSignatureList( makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TEKSignatureList_descriptor; } @@ -4448,45 +4692,36 @@ private TEKSignatureList( internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_TEKSignatureList_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TEKSignatureList.class, TemporaryExposureKeyFormat.TEKSignatureList.Builder.class); + TemporaryExposureKeyFormat.TEKSignatureList.class, + TemporaryExposureKeyFormat.TEKSignatureList.Builder.class); } public static final int SIGNATURES_FIELD_NUMBER = 1; private java.util.List signatures_; - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public java.util.List getSignaturesList() { return signatures_; } - /** - * repeated .TEKSignature signatures = 1; - */ - public java.util.List + /** repeated .TEKSignature signatures = 1; */ + public java.util.List getSignaturesOrBuilderList() { return signatures_; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public int getSignaturesCount() { return signatures_.size(); } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public TemporaryExposureKeyFormat.TEKSignature getSignatures(int index) { return signatures_.get(index); } - /** - * repeated .TEKSignature signatures = 1; - */ - public TemporaryExposureKeyFormat.TEKSignatureOrBuilder getSignaturesOrBuilder( - int index) { + /** repeated .TEKSignature signatures = 1; */ + public TemporaryExposureKeyFormat.TEKSignatureOrBuilder getSignaturesOrBuilder(int index) { return signatures_.get(index); } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -4498,8 +4733,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { for (int i = 0; i < signatures_.size(); i++) { output.writeMessage(1, signatures_.get(i)); } @@ -4513,8 +4747,7 @@ public int getSerializedSize() { size = 0; for (int i = 0; i < signatures_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, signatures_.get(i)); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, signatures_.get(i)); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -4524,15 +4757,15 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof TemporaryExposureKeyFormat.TEKSignatureList)) { return super.equals(obj); } - TemporaryExposureKeyFormat.TEKSignatureList other = (TemporaryExposureKeyFormat.TEKSignatureList) obj; + TemporaryExposureKeyFormat.TEKSignatureList other = + (TemporaryExposureKeyFormat.TEKSignatureList) obj; - if (!getSignaturesList() - .equals(other.getSignaturesList())) return false; + if (!getSignaturesList().equals(other.getSignaturesList())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @@ -4553,88 +4786,94 @@ public int hashCode() { return hash; } - public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( - java.nio.ByteBuffer data) + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom(java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static TemporaryExposureKeyFormat.TEKSignatureList parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.TEKSignatureList parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TEKSignatureList parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(TemporaryExposureKeyFormat.TEKSignatureList prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -4643,15 +4882,13 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code TEKSignatureList} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code TEKSignatureList} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:TEKSignatureList) TemporaryExposureKeyFormat.TEKSignatureListOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TEKSignatureList_descriptor; } @@ -4660,7 +4897,8 @@ public static final class Builder extends internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_TEKSignatureList_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TEKSignatureList.class, TemporaryExposureKeyFormat.TEKSignatureList.Builder.class); + TemporaryExposureKeyFormat.TEKSignatureList.class, + TemporaryExposureKeyFormat.TEKSignatureList.Builder.class); } // Construct using TemporaryExposureKeyFormat.TEKSignatureList.newBuilder() @@ -4668,17 +4906,17 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { getSignaturesFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); @@ -4692,8 +4930,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return TemporaryExposureKeyFormat.internal_static_TEKSignatureList_descriptor; } @@ -4713,7 +4950,8 @@ public TemporaryExposureKeyFormat.TEKSignatureList build() { @java.lang.Override public TemporaryExposureKeyFormat.TEKSignatureList buildPartial() { - TemporaryExposureKeyFormat.TEKSignatureList result = new TemporaryExposureKeyFormat.TEKSignatureList(this); + TemporaryExposureKeyFormat.TEKSignatureList result = + new TemporaryExposureKeyFormat.TEKSignatureList(this); int from_bitField0_ = bitField0_; if (signaturesBuilder_ == null) { if (((bitField0_ & 0x00000001) != 0)) { @@ -4732,38 +4970,41 @@ public TemporaryExposureKeyFormat.TEKSignatureList buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof TemporaryExposureKeyFormat.TEKSignatureList) { - return mergeFrom((TemporaryExposureKeyFormat.TEKSignatureList)other); + return mergeFrom((TemporaryExposureKeyFormat.TEKSignatureList) other); } else { super.mergeFrom(other); return this; @@ -4790,9 +5031,10 @@ public Builder mergeFrom(TemporaryExposureKeyFormat.TEKSignatureList other) { signaturesBuilder_ = null; signatures_ = other.signatures_; bitField0_ = (bitField0_ & ~0x00000001); - signaturesBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getSignaturesFieldBuilder() : null; + signaturesBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders + ? getSignaturesFieldBuilder() + : null; } else { signaturesBuilder_.addAllMessages(other.signatures_); } @@ -4826,23 +5068,27 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private java.util.List signatures_ = - java.util.Collections.emptyList(); + java.util.Collections.emptyList(); + private void ensureSignaturesIsMutable() { if (!((bitField0_ & 0x00000001) != 0)) { - signatures_ = new java.util.ArrayList(signatures_); + signatures_ = + new java.util.ArrayList(signatures_); bitField0_ |= 0x00000001; - } + } } private com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.TEKSignature, TemporaryExposureKeyFormat.TEKSignature.Builder, TemporaryExposureKeyFormat.TEKSignatureOrBuilder> signaturesBuilder_; + TemporaryExposureKeyFormat.TEKSignature, + TemporaryExposureKeyFormat.TEKSignature.Builder, + TemporaryExposureKeyFormat.TEKSignatureOrBuilder> + signaturesBuilder_; - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public java.util.List getSignaturesList() { if (signaturesBuilder_ == null) { return java.util.Collections.unmodifiableList(signatures_); @@ -4850,9 +5096,7 @@ public java.util.List getSignaturesList return signaturesBuilder_.getMessageList(); } } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public int getSignaturesCount() { if (signaturesBuilder_ == null) { return signatures_.size(); @@ -4860,9 +5104,7 @@ public int getSignaturesCount() { return signaturesBuilder_.getCount(); } } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public TemporaryExposureKeyFormat.TEKSignature getSignatures(int index) { if (signaturesBuilder_ == null) { return signatures_.get(index); @@ -4870,11 +5112,8 @@ public TemporaryExposureKeyFormat.TEKSignature getSignatures(int index) { return signaturesBuilder_.getMessage(index); } } - /** - * repeated .TEKSignature signatures = 1; - */ - public Builder setSignatures( - int index, TemporaryExposureKeyFormat.TEKSignature value) { + /** repeated .TEKSignature signatures = 1; */ + public Builder setSignatures(int index, TemporaryExposureKeyFormat.TEKSignature value) { if (signaturesBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -4887,9 +5126,7 @@ public Builder setSignatures( } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder setSignatures( int index, TemporaryExposureKeyFormat.TEKSignature.Builder builderForValue) { if (signaturesBuilder_ == null) { @@ -4901,9 +5138,7 @@ public Builder setSignatures( } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder addSignatures(TemporaryExposureKeyFormat.TEKSignature value) { if (signaturesBuilder_ == null) { if (value == null) { @@ -4917,11 +5152,8 @@ public Builder addSignatures(TemporaryExposureKeyFormat.TEKSignature value) { } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ - public Builder addSignatures( - int index, TemporaryExposureKeyFormat.TEKSignature value) { + /** repeated .TEKSignature signatures = 1; */ + public Builder addSignatures(int index, TemporaryExposureKeyFormat.TEKSignature value) { if (signaturesBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -4934,9 +5166,7 @@ public Builder addSignatures( } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder addSignatures( TemporaryExposureKeyFormat.TEKSignature.Builder builderForValue) { if (signaturesBuilder_ == null) { @@ -4948,9 +5178,7 @@ public Builder addSignatures( } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder addSignatures( int index, TemporaryExposureKeyFormat.TEKSignature.Builder builderForValue) { if (signaturesBuilder_ == null) { @@ -4962,24 +5190,19 @@ public Builder addSignatures( } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder addAllSignatures( java.lang.Iterable values) { if (signaturesBuilder_ == null) { ensureSignaturesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, signatures_); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, signatures_); onChanged(); } else { signaturesBuilder_.addAllMessages(values); } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder clearSignatures() { if (signaturesBuilder_ == null) { signatures_ = java.util.Collections.emptyList(); @@ -4990,9 +5213,7 @@ public Builder clearSignatures() { } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public Builder removeSignatures(int index) { if (signaturesBuilder_ == null) { ensureSignaturesIsMutable(); @@ -5003,70 +5224,60 @@ public Builder removeSignatures(int index) { } return this; } - /** - * repeated .TEKSignature signatures = 1; - */ - public TemporaryExposureKeyFormat.TEKSignature.Builder getSignaturesBuilder( - int index) { + /** repeated .TEKSignature signatures = 1; */ + public TemporaryExposureKeyFormat.TEKSignature.Builder getSignaturesBuilder(int index) { return getSignaturesFieldBuilder().getBuilder(index); } - /** - * repeated .TEKSignature signatures = 1; - */ - public TemporaryExposureKeyFormat.TEKSignatureOrBuilder getSignaturesOrBuilder( - int index) { + /** repeated .TEKSignature signatures = 1; */ + public TemporaryExposureKeyFormat.TEKSignatureOrBuilder getSignaturesOrBuilder(int index) { if (signaturesBuilder_ == null) { - return signatures_.get(index); } else { + return signatures_.get(index); + } else { return signaturesBuilder_.getMessageOrBuilder(index); } } - /** - * repeated .TEKSignature signatures = 1; - */ - public java.util.List - getSignaturesOrBuilderList() { + /** repeated .TEKSignature signatures = 1; */ + public java.util.List + getSignaturesOrBuilderList() { if (signaturesBuilder_ != null) { return signaturesBuilder_.getMessageOrBuilderList(); } else { return java.util.Collections.unmodifiableList(signatures_); } } - /** - * repeated .TEKSignature signatures = 1; - */ + /** repeated .TEKSignature signatures = 1; */ public TemporaryExposureKeyFormat.TEKSignature.Builder addSignaturesBuilder() { - return getSignaturesFieldBuilder().addBuilder( - TemporaryExposureKeyFormat.TEKSignature.getDefaultInstance()); + return getSignaturesFieldBuilder() + .addBuilder(TemporaryExposureKeyFormat.TEKSignature.getDefaultInstance()); } - /** - * repeated .TEKSignature signatures = 1; - */ - public TemporaryExposureKeyFormat.TEKSignature.Builder addSignaturesBuilder( - int index) { - return getSignaturesFieldBuilder().addBuilder( - index, TemporaryExposureKeyFormat.TEKSignature.getDefaultInstance()); + /** repeated .TEKSignature signatures = 1; */ + public TemporaryExposureKeyFormat.TEKSignature.Builder addSignaturesBuilder(int index) { + return getSignaturesFieldBuilder() + .addBuilder(index, TemporaryExposureKeyFormat.TEKSignature.getDefaultInstance()); } - /** - * repeated .TEKSignature signatures = 1; - */ - public java.util.List - getSignaturesBuilderList() { + /** repeated .TEKSignature signatures = 1; */ + public java.util.List + getSignaturesBuilderList() { return getSignaturesFieldBuilder().getBuilderList(); } + private com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.TEKSignature, TemporaryExposureKeyFormat.TEKSignature.Builder, TemporaryExposureKeyFormat.TEKSignatureOrBuilder> + TemporaryExposureKeyFormat.TEKSignature, + TemporaryExposureKeyFormat.TEKSignature.Builder, + TemporaryExposureKeyFormat.TEKSignatureOrBuilder> getSignaturesFieldBuilder() { if (signaturesBuilder_ == null) { - signaturesBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - TemporaryExposureKeyFormat.TEKSignature, TemporaryExposureKeyFormat.TEKSignature.Builder, TemporaryExposureKeyFormat.TEKSignatureOrBuilder>( - signatures_, - ((bitField0_ & 0x00000001) != 0), - getParentForChildren(), - isClean()); + signaturesBuilder_ = + new com.google.protobuf.RepeatedFieldBuilderV3< + TemporaryExposureKeyFormat.TEKSignature, + TemporaryExposureKeyFormat.TEKSignature.Builder, + TemporaryExposureKeyFormat.TEKSignatureOrBuilder>( + signatures_, ((bitField0_ & 0x00000001) != 0), getParentForChildren(), isClean()); signatures_ = null; } return signaturesBuilder_; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -5079,12 +5290,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:TEKSignatureList) } // @@protoc_insertion_point(class_scope:TEKSignatureList) private static final TemporaryExposureKeyFormat.TEKSignatureList DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new TemporaryExposureKeyFormat.TEKSignatureList(); } @@ -5093,16 +5304,17 @@ public static TemporaryExposureKeyFormat.TEKSignatureList getDefaultInstance() { return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TEKSignatureList parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new TEKSignatureList(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TEKSignatureList parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new TEKSignatureList(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -5117,14 +5329,16 @@ public com.google.protobuf.Parser getParserForType() { public TemporaryExposureKeyFormat.TEKSignatureList getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface TEKSignatureOrBuilder extends + public interface TEKSignatureOrBuilder + extends // @@protoc_insertion_point(interface_extends:TEKSignature) com.google.protobuf.MessageOrBuilder { /** + * + * *
      * Info about the signing key, version, algorithm, etc
      * 
@@ -5133,6 +5347,8 @@ public interface TEKSignatureOrBuilder extends */ boolean hasSignatureInfo(); /** + * + * *
      * Info about the signing key, version, algorithm, etc
      * 
@@ -5141,6 +5357,8 @@ public interface TEKSignatureOrBuilder extends */ TemporaryExposureKeyFormat.SignatureInfo getSignatureInfo(); /** + * + * *
      * Info about the signing key, version, algorithm, etc
      * 
@@ -5150,6 +5368,8 @@ public interface TEKSignatureOrBuilder extends TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfoOrBuilder(); /** + * + * *
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * E.g., Batch 2 of 10
@@ -5159,6 +5379,8 @@ public interface TEKSignatureOrBuilder extends
      */
     boolean hasBatchNum();
     /**
+     *
+     *
      * 
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * E.g., Batch 2 of 10
@@ -5168,16 +5390,14 @@ public interface TEKSignatureOrBuilder extends
      */
     int getBatchNum();
 
-    /**
-     * optional int32 batch_size = 3;
-     */
+    /** optional int32 batch_size = 3; */
     boolean hasBatchSize();
-    /**
-     * optional int32 batch_size = 3;
-     */
+    /** optional int32 batch_size = 3; */
     int getBatchSize();
 
     /**
+     *
+     *
      * 
      * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
      * 
@@ -5186,6 +5406,8 @@ public interface TEKSignatureOrBuilder extends */ boolean hasSignature(); /** + * + * *
      * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
      * 
@@ -5194,27 +5416,26 @@ public interface TEKSignatureOrBuilder extends */ com.google.protobuf.ByteString getSignature(); } - /** - * Protobuf type {@code TEKSignature} - */ - public static final class TEKSignature extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code TEKSignature} */ + public static final class TEKSignature extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:TEKSignature) TEKSignatureOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use TEKSignature.newBuilder() to construct. private TEKSignature(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private TEKSignature() { signature_ = com.google.protobuf.ByteString.EMPTY; } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private TEKSignature( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -5234,55 +5455,60 @@ private TEKSignature( case 0: done = true; break; - case 10: { - TemporaryExposureKeyFormat.SignatureInfo.Builder subBuilder = null; - if (((bitField0_ & 0x00000001) != 0)) { - subBuilder = signatureInfo_.toBuilder(); + case 10: + { + TemporaryExposureKeyFormat.SignatureInfo.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) != 0)) { + subBuilder = signatureInfo_.toBuilder(); + } + signatureInfo_ = + input.readMessage( + TemporaryExposureKeyFormat.SignatureInfo.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(signatureInfo_); + signatureInfo_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; } - signatureInfo_ = input.readMessage(TemporaryExposureKeyFormat.SignatureInfo.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(signatureInfo_); - signatureInfo_ = subBuilder.buildPartial(); + case 16: + { + bitField0_ |= 0x00000002; + batchNum_ = input.readInt32(); + break; } - bitField0_ |= 0x00000001; - break; - } - case 16: { - bitField0_ |= 0x00000002; - batchNum_ = input.readInt32(); - break; - } - case 24: { - bitField0_ |= 0x00000004; - batchSize_ = input.readInt32(); - break; - } - case 34: { - bitField0_ |= 0x00000008; - signature_ = input.readBytes(); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 24: + { + bitField0_ |= 0x00000004; + batchSize_ = input.readInt32(); + break; + } + case 34: + { + bitField0_ |= 0x00000008; + signature_ = input.readBytes(); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TEKSignature_descriptor; } @@ -5291,13 +5517,16 @@ private TEKSignature( internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_TEKSignature_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TEKSignature.class, TemporaryExposureKeyFormat.TEKSignature.Builder.class); + TemporaryExposureKeyFormat.TEKSignature.class, + TemporaryExposureKeyFormat.TEKSignature.Builder.class); } private int bitField0_; public static final int SIGNATURE_INFO_FIELD_NUMBER = 1; private TemporaryExposureKeyFormat.SignatureInfo signatureInfo_; /** + * + * *
      * Info about the signing key, version, algorithm, etc
      * 
@@ -5308,6 +5537,8 @@ public boolean hasSignatureInfo() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
      * Info about the signing key, version, algorithm, etc
      * 
@@ -5315,9 +5546,13 @@ public boolean hasSignatureInfo() { * optional .SignatureInfo signature_info = 1; */ public TemporaryExposureKeyFormat.SignatureInfo getSignatureInfo() { - return signatureInfo_ == null ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() : signatureInfo_; + return signatureInfo_ == null + ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() + : signatureInfo_; } /** + * + * *
      * Info about the signing key, version, algorithm, etc
      * 
@@ -5325,12 +5560,16 @@ public TemporaryExposureKeyFormat.SignatureInfo getSignatureInfo() { * optional .SignatureInfo signature_info = 1; */ public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfoOrBuilder() { - return signatureInfo_ == null ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() : signatureInfo_; + return signatureInfo_ == null + ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() + : signatureInfo_; } public static final int BATCH_NUM_FIELD_NUMBER = 2; private int batchNum_; /** + * + * *
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * E.g., Batch 2 of 10
@@ -5342,6 +5581,8 @@ public boolean hasBatchNum() {
       return ((bitField0_ & 0x00000002) != 0);
     }
     /**
+     *
+     *
      * 
      * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
      * E.g., Batch 2 of 10
@@ -5355,15 +5596,11 @@ public int getBatchNum() {
 
     public static final int BATCH_SIZE_FIELD_NUMBER = 3;
     private int batchSize_;
-    /**
-     * optional int32 batch_size = 3;
-     */
+    /** optional int32 batch_size = 3; */
     public boolean hasBatchSize() {
       return ((bitField0_ & 0x00000004) != 0);
     }
-    /**
-     * optional int32 batch_size = 3;
-     */
+    /** optional int32 batch_size = 3; */
     public int getBatchSize() {
       return batchSize_;
     }
@@ -5371,6 +5608,8 @@ public int getBatchSize() {
     public static final int SIGNATURE_FIELD_NUMBER = 4;
     private com.google.protobuf.ByteString signature_;
     /**
+     *
+     *
      * 
      * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
      * 
@@ -5381,6 +5620,8 @@ public boolean hasSignature() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
      * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
      * 
@@ -5392,6 +5633,7 @@ public com.google.protobuf.ByteString getSignature() { } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -5403,8 +5645,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (((bitField0_ & 0x00000001) != 0)) { output.writeMessage(1, getSignatureInfo()); } @@ -5427,20 +5668,16 @@ public int getSerializedSize() { size = 0; if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, getSignatureInfo()); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, getSignatureInfo()); } if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, batchNum_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(2, batchNum_); } if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, batchSize_); + size += com.google.protobuf.CodedOutputStream.computeInt32Size(3, batchSize_); } if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(4, signature_); + size += com.google.protobuf.CodedOutputStream.computeBytesSize(4, signature_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -5450,7 +5687,7 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof TemporaryExposureKeyFormat.TEKSignature)) { return super.equals(obj); @@ -5459,23 +5696,19 @@ public boolean equals(final java.lang.Object obj) { if (hasSignatureInfo() != other.hasSignatureInfo()) return false; if (hasSignatureInfo()) { - if (!getSignatureInfo() - .equals(other.getSignatureInfo())) return false; + if (!getSignatureInfo().equals(other.getSignatureInfo())) return false; } if (hasBatchNum() != other.hasBatchNum()) return false; if (hasBatchNum()) { - if (getBatchNum() - != other.getBatchNum()) return false; + if (getBatchNum() != other.getBatchNum()) return false; } if (hasBatchSize() != other.hasBatchSize()) return false; if (hasBatchSize()) { - if (getBatchSize() - != other.getBatchSize()) return false; + if (getBatchSize() != other.getBatchSize()) return false; } if (hasSignature() != other.hasSignature()) return false; if (hasSignature()) { - if (!getSignature() - .equals(other.getSignature())) return false; + if (!getSignature().equals(other.getSignature())) return false; } if (!unknownFields.equals(other.unknownFields)) return false; return true; @@ -5509,88 +5742,94 @@ public int hashCode() { return hash; } - public static TemporaryExposureKeyFormat.TEKSignature parseFrom( - java.nio.ByteBuffer data) + public static TemporaryExposureKeyFormat.TEKSignature parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom(java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static TemporaryExposureKeyFormat.TEKSignature parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static TemporaryExposureKeyFormat.TEKSignature parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TEKSignature parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static TemporaryExposureKeyFormat.TEKSignature parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } + public static Builder newBuilder(TemporaryExposureKeyFormat.TEKSignature prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -5599,15 +5838,13 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code TEKSignature} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code TEKSignature} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:TEKSignature) TemporaryExposureKeyFormat.TEKSignatureOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return TemporaryExposureKeyFormat.internal_static_TEKSignature_descriptor; } @@ -5616,7 +5853,8 @@ public static final class Builder extends internalGetFieldAccessorTable() { return TemporaryExposureKeyFormat.internal_static_TEKSignature_fieldAccessorTable .ensureFieldAccessorsInitialized( - TemporaryExposureKeyFormat.TEKSignature.class, TemporaryExposureKeyFormat.TEKSignature.Builder.class); + TemporaryExposureKeyFormat.TEKSignature.class, + TemporaryExposureKeyFormat.TEKSignature.Builder.class); } // Construct using TemporaryExposureKeyFormat.TEKSignature.newBuilder() @@ -5624,17 +5862,17 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { getSignatureInfoFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); @@ -5654,8 +5892,7 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return TemporaryExposureKeyFormat.internal_static_TEKSignature_descriptor; } @@ -5675,7 +5912,8 @@ public TemporaryExposureKeyFormat.TEKSignature build() { @java.lang.Override public TemporaryExposureKeyFormat.TEKSignature buildPartial() { - TemporaryExposureKeyFormat.TEKSignature result = new TemporaryExposureKeyFormat.TEKSignature(this); + TemporaryExposureKeyFormat.TEKSignature result = + new TemporaryExposureKeyFormat.TEKSignature(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; if (((from_bitField0_ & 0x00000001) != 0)) { @@ -5707,38 +5945,41 @@ public TemporaryExposureKeyFormat.TEKSignature buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof TemporaryExposureKeyFormat.TEKSignature) { - return mergeFrom((TemporaryExposureKeyFormat.TEKSignature)other); + return mergeFrom((TemporaryExposureKeyFormat.TEKSignature) other); } else { super.mergeFrom(other); return this; @@ -5787,12 +6028,18 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private TemporaryExposureKeyFormat.SignatureInfo signatureInfo_; private com.google.protobuf.SingleFieldBuilderV3< - TemporaryExposureKeyFormat.SignatureInfo, TemporaryExposureKeyFormat.SignatureInfo.Builder, TemporaryExposureKeyFormat.SignatureInfoOrBuilder> signatureInfoBuilder_; + TemporaryExposureKeyFormat.SignatureInfo, + TemporaryExposureKeyFormat.SignatureInfo.Builder, + TemporaryExposureKeyFormat.SignatureInfoOrBuilder> + signatureInfoBuilder_; /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5803,6 +6050,8 @@ public boolean hasSignatureInfo() { return ((bitField0_ & 0x00000001) != 0); } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5811,12 +6060,16 @@ public boolean hasSignatureInfo() { */ public TemporaryExposureKeyFormat.SignatureInfo getSignatureInfo() { if (signatureInfoBuilder_ == null) { - return signatureInfo_ == null ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() : signatureInfo_; + return signatureInfo_ == null + ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() + : signatureInfo_; } else { return signatureInfoBuilder_.getMessage(); } } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5837,6 +6090,8 @@ public Builder setSignatureInfo(TemporaryExposureKeyFormat.SignatureInfo value) return this; } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5855,6 +6110,8 @@ public Builder setSignatureInfo( return this; } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5863,11 +6120,13 @@ public Builder setSignatureInfo( */ public Builder mergeSignatureInfo(TemporaryExposureKeyFormat.SignatureInfo value) { if (signatureInfoBuilder_ == null) { - if (((bitField0_ & 0x00000001) != 0) && - signatureInfo_ != null && - signatureInfo_ != TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance()) { + if (((bitField0_ & 0x00000001) != 0) + && signatureInfo_ != null + && signatureInfo_ != TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance()) { signatureInfo_ = - TemporaryExposureKeyFormat.SignatureInfo.newBuilder(signatureInfo_).mergeFrom(value).buildPartial(); + TemporaryExposureKeyFormat.SignatureInfo.newBuilder(signatureInfo_) + .mergeFrom(value) + .buildPartial(); } else { signatureInfo_ = value; } @@ -5879,6 +6138,8 @@ public Builder mergeSignatureInfo(TemporaryExposureKeyFormat.SignatureInfo value return this; } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5896,6 +6157,8 @@ public Builder clearSignatureInfo() { return this; } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5908,6 +6171,8 @@ public TemporaryExposureKeyFormat.SignatureInfo.Builder getSignatureInfoBuilder( return getSignatureInfoFieldBuilder().getBuilder(); } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5918,11 +6183,14 @@ public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfoOrBuild if (signatureInfoBuilder_ != null) { return signatureInfoBuilder_.getMessageOrBuilder(); } else { - return signatureInfo_ == null ? - TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() : signatureInfo_; + return signatureInfo_ == null + ? TemporaryExposureKeyFormat.SignatureInfo.getDefaultInstance() + : signatureInfo_; } } /** + * + * *
        * Info about the signing key, version, algorithm, etc
        * 
@@ -5930,21 +6198,26 @@ public TemporaryExposureKeyFormat.SignatureInfoOrBuilder getSignatureInfoOrBuild * optional .SignatureInfo signature_info = 1; */ private com.google.protobuf.SingleFieldBuilderV3< - TemporaryExposureKeyFormat.SignatureInfo, TemporaryExposureKeyFormat.SignatureInfo.Builder, TemporaryExposureKeyFormat.SignatureInfoOrBuilder> + TemporaryExposureKeyFormat.SignatureInfo, + TemporaryExposureKeyFormat.SignatureInfo.Builder, + TemporaryExposureKeyFormat.SignatureInfoOrBuilder> getSignatureInfoFieldBuilder() { if (signatureInfoBuilder_ == null) { - signatureInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - TemporaryExposureKeyFormat.SignatureInfo, TemporaryExposureKeyFormat.SignatureInfo.Builder, TemporaryExposureKeyFormat.SignatureInfoOrBuilder>( - getSignatureInfo(), - getParentForChildren(), - isClean()); + signatureInfoBuilder_ = + new com.google.protobuf.SingleFieldBuilderV3< + TemporaryExposureKeyFormat.SignatureInfo, + TemporaryExposureKeyFormat.SignatureInfo.Builder, + TemporaryExposureKeyFormat.SignatureInfoOrBuilder>( + getSignatureInfo(), getParentForChildren(), isClean()); signatureInfo_ = null; } return signatureInfoBuilder_; } - private int batchNum_ ; + private int batchNum_; /** + * + * *
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * E.g., Batch 2 of 10
@@ -5956,6 +6229,8 @@ public boolean hasBatchNum() {
         return ((bitField0_ & 0x00000002) != 0);
       }
       /**
+       *
+       *
        * 
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * E.g., Batch 2 of 10
@@ -5967,6 +6242,8 @@ public int getBatchNum() {
         return batchNum_;
       }
       /**
+       *
+       *
        * 
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * E.g., Batch 2 of 10
@@ -5981,6 +6258,8 @@ public Builder setBatchNum(int value) {
         return this;
       }
       /**
+       *
+       *
        * 
        * E.g., File 2 in batch size of 10. Ordinal, 1-based numbering.
        * E.g., Batch 2 of 10
@@ -5995,31 +6274,23 @@ public Builder clearBatchNum() {
         return this;
       }
 
-      private int batchSize_ ;
-      /**
-       * optional int32 batch_size = 3;
-       */
+      private int batchSize_;
+      /** optional int32 batch_size = 3; */
       public boolean hasBatchSize() {
         return ((bitField0_ & 0x00000004) != 0);
       }
-      /**
-       * optional int32 batch_size = 3;
-       */
+      /** optional int32 batch_size = 3; */
       public int getBatchSize() {
         return batchSize_;
       }
-      /**
-       * optional int32 batch_size = 3;
-       */
+      /** optional int32 batch_size = 3; */
       public Builder setBatchSize(int value) {
         bitField0_ |= 0x00000004;
         batchSize_ = value;
         onChanged();
         return this;
       }
-      /**
-       * optional int32 batch_size = 3;
-       */
+      /** optional int32 batch_size = 3; */
       public Builder clearBatchSize() {
         bitField0_ = (bitField0_ & ~0x00000004);
         batchSize_ = 0;
@@ -6029,6 +6300,8 @@ public Builder clearBatchSize() {
 
       private com.google.protobuf.ByteString signature_ = com.google.protobuf.ByteString.EMPTY;
       /**
+       *
+       *
        * 
        * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
        * 
@@ -6039,6 +6312,8 @@ public boolean hasSignature() { return ((bitField0_ & 0x00000008) != 0); } /** + * + * *
        * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
        * 
@@ -6049,6 +6324,8 @@ public com.google.protobuf.ByteString getSignature() { return signature_; } /** + * + * *
        * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
        * 
@@ -6057,14 +6334,16 @@ public com.google.protobuf.ByteString getSignature() { */ public Builder setSignature(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000008; + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; signature_ = value; onChanged(); return this; } /** + * + * *
        * Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
        * 
@@ -6077,6 +6356,7 @@ public Builder clearSignature() { onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -6089,12 +6369,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:TEKSignature) } // @@protoc_insertion_point(class_scope:TEKSignature) private static final TemporaryExposureKeyFormat.TEKSignature DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new TemporaryExposureKeyFormat.TEKSignature(); } @@ -6103,16 +6383,17 @@ public static TemporaryExposureKeyFormat.TEKSignature getDefaultInstance() { return DEFAULT_INSTANCE; } - @java.lang.Deprecated public static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TEKSignature parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new TEKSignature(input, extensionRegistry); - } - }; + @java.lang.Deprecated + public static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public TEKSignature parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new TEKSignature(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -6127,104 +6408,112 @@ public com.google.protobuf.Parser getParserForType() { public TemporaryExposureKeyFormat.TEKSignature getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } private static final com.google.protobuf.Descriptors.Descriptor - internal_static_TemporaryExposureKeyExport_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_TemporaryExposureKeyExport_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_TemporaryExposureKeyExport_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_SignatureInfo_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_SignatureInfo_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_SignatureInfo_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_TemporaryExposureKey_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_TemporaryExposureKey_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_TemporaryExposureKey_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_TEKSignatureList_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_TEKSignatureList_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_TEKSignatureList_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_TEKSignature_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_TEKSignature_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_TEKSignature_fieldAccessorTable; - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + static { java.lang.String[] descriptorData = { - "\n TemporaryExposureKeyFormat.proto\"\321\001\n\032T" + - "emporaryExposureKeyExport\022\027\n\017start_times" + - "tamp\030\001 \001(\006\022\025\n\rend_timestamp\030\002 \001(\006\022\016\n\006reg" + - "ion\030\003 \001(\t\022\021\n\tbatch_num\030\004 \001(\005\022\022\n\nbatch_si" + - "ze\030\005 \001(\005\022\'\n\017signature_infos\030\006 \003(\0132\016.Sign" + - "atureInfo\022#\n\004keys\030\007 \003(\0132\025.TemporaryExpos" + - "ureKey\"\233\001\n\rSignatureInfo\022\025\n\rapp_bundle_i" + - "d\030\001 \001(\t\022\027\n\017android_package\030\002 \001(\t\022 \n\030veri" + - "fication_key_version\030\003 \001(\t\022\033\n\023verificati" + - "on_key_id\030\004 \001(\t\022\033\n\023signature_algorithm\030\005" + - " \001(\t\"\215\001\n\024TemporaryExposureKey\022\020\n\010key_dat" + - "a\030\001 \001(\014\022\037\n\027transmission_risk_level\030\002 \001(\005" + - "\022%\n\035rolling_start_interval_number\030\003 \001(\005\022" + - "\033\n\016rolling_period\030\004 \001(\005:\003144\"5\n\020TEKSigna" + - "tureList\022!\n\nsignatures\030\001 \003(\0132\r.TEKSignat" + - "ure\"p\n\014TEKSignature\022&\n\016signature_info\030\001 " + - "\001(\0132\016.SignatureInfo\022\021\n\tbatch_num\030\002 \001(\005\022\022" + - "\n\nbatch_size\030\003 \001(\005\022\021\n\tsignature\030\004 \001(\014" + "\n TemporaryExposureKeyFormat.proto\"\321\001\n\032T" + + "emporaryExposureKeyExport\022\027\n\017start_times" + + "tamp\030\001 \001(\006\022\025\n\rend_timestamp\030\002 \001(\006\022\016\n\006reg" + + "ion\030\003 \001(\t\022\021\n\tbatch_num\030\004 \001(\005\022\022\n\nbatch_si" + + "ze\030\005 \001(\005\022\'\n\017signature_infos\030\006 \003(\0132\016.Sign" + + "atureInfo\022#\n\004keys\030\007 \003(\0132\025.TemporaryExpos" + + "ureKey\"\233\001\n\rSignatureInfo\022\025\n\rapp_bundle_i" + + "d\030\001 \001(\t\022\027\n\017android_package\030\002 \001(\t\022 \n\030veri" + + "fication_key_version\030\003 \001(\t\022\033\n\023verificati" + + "on_key_id\030\004 \001(\t\022\033\n\023signature_algorithm\030\005" + + " \001(\t\"\215\001\n\024TemporaryExposureKey\022\020\n\010key_dat" + + "a\030\001 \001(\014\022\037\n\027transmission_risk_level\030\002 \001(\005" + + "\022%\n\035rolling_start_interval_number\030\003 \001(\005\022" + + "\033\n\016rolling_period\030\004 \001(\005:\003144\"5\n\020TEKSigna" + + "tureList\022!\n\nsignatures\030\001 \003(\0132\r.TEKSignat" + + "ure\"p\n\014TEKSignature\022&\n\016signature_info\030\001 " + + "\001(\0132\016.SignatureInfo\022\021\n\tbatch_num\030\002 \001(\005\022\022" + + "\n\nbatch_size\030\003 \001(\005\022\021\n\tsignature\030\004 \001(\014" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); + com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( + descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner); internal_static_TemporaryExposureKeyExport_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_TemporaryExposureKeyExport_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_TemporaryExposureKeyExport_descriptor, - new java.lang.String[] { "StartTimestamp", "EndTimestamp", "Region", "BatchNum", "BatchSize", "SignatureInfos", "Keys", }); - internal_static_SignatureInfo_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_SignatureInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_SignatureInfo_descriptor, - new java.lang.String[] { "AppBundleId", "AndroidPackage", "VerificationKeyVersion", "VerificationKeyId", "SignatureAlgorithm", }); - internal_static_TemporaryExposureKey_descriptor = - getDescriptor().getMessageTypes().get(2); - internal_static_TemporaryExposureKey_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_TemporaryExposureKey_descriptor, - new java.lang.String[] { "KeyData", "TransmissionRiskLevel", "RollingStartIntervalNumber", "RollingPeriod", }); - internal_static_TEKSignatureList_descriptor = - getDescriptor().getMessageTypes().get(3); - internal_static_TEKSignatureList_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_TEKSignatureList_descriptor, - new java.lang.String[] { "Signatures", }); - internal_static_TEKSignature_descriptor = - getDescriptor().getMessageTypes().get(4); - internal_static_TEKSignature_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_TEKSignature_descriptor, - new java.lang.String[] { "SignatureInfo", "BatchNum", "BatchSize", "Signature", }); + getDescriptor().getMessageTypes().get(0); + internal_static_TemporaryExposureKeyExport_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_TemporaryExposureKeyExport_descriptor, + new java.lang.String[] { + "StartTimestamp", + "EndTimestamp", + "Region", + "BatchNum", + "BatchSize", + "SignatureInfos", + "Keys", + }); + internal_static_SignatureInfo_descriptor = getDescriptor().getMessageTypes().get(1); + internal_static_SignatureInfo_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_SignatureInfo_descriptor, + new java.lang.String[] { + "AppBundleId", + "AndroidPackage", + "VerificationKeyVersion", + "VerificationKeyId", + "SignatureAlgorithm", + }); + internal_static_TemporaryExposureKey_descriptor = getDescriptor().getMessageTypes().get(2); + internal_static_TemporaryExposureKey_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_TemporaryExposureKey_descriptor, + new java.lang.String[] { + "KeyData", "TransmissionRiskLevel", "RollingStartIntervalNumber", "RollingPeriod", + }); + internal_static_TEKSignatureList_descriptor = getDescriptor().getMessageTypes().get(3); + internal_static_TEKSignatureList_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_TEKSignatureList_descriptor, + new java.lang.String[] { + "Signatures", + }); + internal_static_TEKSignature_descriptor = getDescriptor().getMessageTypes().get(4); + internal_static_TEKSignature_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_TEKSignature_descriptor, + new java.lang.String[] { + "SignatureInfo", "BatchNum", "BatchSize", "Signature", + }); } // @@protoc_insertion_point(outer_class_scope) diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/keycloak/KeyCloakPublicKey.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/keycloak/KeyCloakPublicKey.java index b7be791b..2aa29569 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/keycloak/KeyCloakPublicKey.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/keycloak/KeyCloakPublicKey.java @@ -12,55 +12,58 @@ import com.fasterxml.jackson.annotation.JsonProperty; - public class KeyCloakPublicKey { - private String realm; - @JsonProperty("public_key") - private String publicKey; - @JsonProperty("token-service") - private String tokenService; - @JsonProperty("account-service") - private String accountService; - @JsonProperty("tokens-not-before") - private String tokensNotBefore; - - public String getRealm() { - return realm; - } - - public void setRealm(String realm) { - this.realm = realm; - } - - public String getPublicKey() { - return publicKey; - } - - public void setPublicKey(String publicKey) { - this.publicKey = publicKey; - } - - public String getTokenService() { - return tokenService; - } - - public void setTokenService(String tokenService) { - this.tokenService = tokenService; - } - - public String getAccountService() { - return accountService; - } - - public void setAccountService(String accountService) { - this.accountService = accountService; - } - - public String getTokensNotBefore() { - return tokensNotBefore; - } - - public void setTokensNotBefore(String tokensNotBefore) { - this.tokensNotBefore = tokensNotBefore; - } + private String realm; + + @JsonProperty("public_key") + private String publicKey; + + @JsonProperty("token-service") + private String tokenService; + + @JsonProperty("account-service") + private String accountService; + + @JsonProperty("tokens-not-before") + private String tokensNotBefore; + + public String getRealm() { + return realm; + } + + public void setRealm(String realm) { + this.realm = realm; + } + + public String getPublicKey() { + return publicKey; + } + + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + public String getTokenService() { + return tokenService; + } + + public void setTokenService(String tokenService) { + this.tokenService = tokenService; + } + + public String getAccountService() { + return accountService; + } + + public void setAccountService(String accountService) { + this.accountService = accountService; + } + + public String getTokensNotBefore() { + return tokensNotBefore; + } + + public void setTokensNotBefore(String tokensNotBefore) { + this.tokensNotBefore = tokensNotBefore; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/proto/Exposed.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/proto/Exposed.java index ee486322..06ba6f4a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/proto/Exposed.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/model/proto/Exposed.java @@ -15,69 +15,53 @@ public final class Exposed { private Exposed() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry) {} + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); } - public interface ProtoExposedListOrBuilder extends + + public interface ProtoExposedListOrBuilder + extends // @@protoc_insertion_point(interface_extends:org.dpppt.backend.sdk.model.proto.ProtoExposedList) com.google.protobuf.MessageOrBuilder { - /** - * int64 batchReleaseTime = 1; - */ + /** int64 batchReleaseTime = 1; */ long getBatchReleaseTime(); - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - java.util.List - getExposedList(); - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + java.util.List getExposedList(); + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee getExposed(int index); - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ int getExposedCount(); - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - java.util.List + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + java.util.List getExposedOrBuilderList(); - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder getExposedOrBuilder( - int index); + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder getExposedOrBuilder(int index); } - /** - * Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposedList} - */ - public static final class ProtoExposedList extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposedList} */ + public static final class ProtoExposedList extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:org.dpppt.backend.sdk.model.proto.ProtoExposedList) ProtoExposedListOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use ProtoExposedList.newBuilder() to construct. private ProtoExposedList(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private ProtoExposedList() { exposed_ = java.util.Collections.emptyList(); } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private ProtoExposedList( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -97,34 +81,38 @@ private ProtoExposedList( case 0: done = true; break; - case 8: { - - batchReleaseTime_ = input.readInt64(); - break; - } - case 18: { - if (!((mutable_bitField0_ & 0x00000002) != 0)) { - exposed_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000002; + case 8: + { + batchReleaseTime_ = input.readInt64(); + break; } - exposed_.add( - input.readMessage(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.parser(), extensionRegistry)); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 18: + { + if (!((mutable_bitField0_ & 0x00000002) != 0)) { + exposed_ = + new java.util.ArrayList< + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee>(); + mutable_bitField0_ |= 0x00000002; + } + exposed_.add( + input.readMessage( + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.parser(), + extensionRegistry)); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { if (((mutable_bitField0_ & 0x00000002) != 0)) { exposed_ = java.util.Collections.unmodifiableList(exposed_); @@ -133,65 +121,57 @@ private ProtoExposedList( makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable .ensureFieldAccessorsInitialized( - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.class, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.Builder.class); + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.class, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.Builder.class); } private int bitField0_; public static final int BATCHRELEASETIME_FIELD_NUMBER = 1; private long batchReleaseTime_; - /** - * int64 batchReleaseTime = 1; - */ + /** int64 batchReleaseTime = 1; */ public long getBatchReleaseTime() { return batchReleaseTime_; } public static final int EXPOSED_FIELD_NUMBER = 2; private java.util.List exposed_; - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public java.util.List getExposedList() { return exposed_; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - public java.util.List + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + public java.util.List getExposedOrBuilderList() { return exposed_; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public int getExposedCount() { return exposed_.size(); } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee getExposed(int index) { return exposed_.get(index); } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder getExposedOrBuilder( int index) { return exposed_.get(index); } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -203,8 +183,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (batchReleaseTime_ != 0L) { output.writeInt64(1, batchReleaseTime_); } @@ -221,12 +200,10 @@ public int getSerializedSize() { size = 0; if (batchReleaseTime_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, batchReleaseTime_); + size += com.google.protobuf.CodedOutputStream.computeInt64Size(1, batchReleaseTime_); } for (int i = 0; i < exposed_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, exposed_.get(i)); + size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, exposed_.get(i)); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -236,17 +213,16 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList)) { return super.equals(obj); } - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList other = (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList) obj; + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList other = + (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList) obj; - if (getBatchReleaseTime() - != other.getBatchReleaseTime()) return false; - if (!getExposedList() - .equals(other.getExposedList())) return false; + if (getBatchReleaseTime() != other.getBatchReleaseTime()) return false; + if (!getExposedList().equals(other.getExposedList())) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @@ -259,8 +235,7 @@ public int hashCode() { int hash = 41; hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + BATCHRELEASETIME_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getBatchReleaseTime()); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getBatchReleaseTime()); if (getExposedCount() > 0) { hash = (37 * hash) + EXPOSED_FIELD_NUMBER; hash = (53 * hash) + getExposedList().hashCode(); @@ -271,87 +246,94 @@ public int hashCode() { } public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { + java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList prototype) { + + public static Builder newBuilder( + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -360,24 +342,25 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposedList} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposedList} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:org.dpppt.backend.sdk.model.proto.ProtoExposedList) org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedListOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable .ensureFieldAccessorsInitialized( - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.class, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.Builder.class); + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.class, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.Builder.class); } // Construct using org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.newBuilder() @@ -385,17 +368,17 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { getExposedFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); @@ -411,13 +394,14 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; } @java.lang.Override - public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList getDefaultInstanceForType() { + public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList + getDefaultInstanceForType() { return org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.getDefaultInstance(); } @@ -432,7 +416,8 @@ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList build() { @java.lang.Override public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList buildPartial() { - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList result = new org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList(this); + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList result = + new org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList(this); int from_bitField0_ = bitField0_; int to_bitField0_ = 0; result.batchReleaseTime_ = batchReleaseTime_; @@ -454,38 +439,41 @@ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList buildPartial() public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList) { - return mergeFrom((org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList)other); + return mergeFrom((org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList) other); } else { super.mergeFrom(other); return this; @@ -493,7 +481,9 @@ public Builder mergeFrom(com.google.protobuf.Message other) { } public Builder mergeFrom(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList other) { - if (other == org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.getDefaultInstance()) return this; + if (other + == org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList.getDefaultInstance()) + return this; if (other.getBatchReleaseTime() != 0L) { setBatchReleaseTime(other.getBatchReleaseTime()); } @@ -515,9 +505,10 @@ public Builder mergeFrom(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedL exposedBuilder_ = null; exposed_ = other.exposed_; bitField0_ = (bitField0_ & ~0x00000002); - exposedBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getExposedFieldBuilder() : null; + exposedBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders + ? getExposedFieldBuilder() + : null; } else { exposedBuilder_.addAllMessages(other.exposed_); } @@ -542,7 +533,8 @@ public Builder mergeFrom( try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList) e.getUnfinishedMessage(); + parsedMessage = + (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -551,59 +543,57 @@ public Builder mergeFrom( } return this; } + private int bitField0_; - private long batchReleaseTime_ ; - /** - * int64 batchReleaseTime = 1; - */ + private long batchReleaseTime_; + /** int64 batchReleaseTime = 1; */ public long getBatchReleaseTime() { return batchReleaseTime_; } - /** - * int64 batchReleaseTime = 1; - */ + /** int64 batchReleaseTime = 1; */ public Builder setBatchReleaseTime(long value) { - + batchReleaseTime_ = value; onChanged(); return this; } - /** - * int64 batchReleaseTime = 1; - */ + /** int64 batchReleaseTime = 1; */ public Builder clearBatchReleaseTime() { - + batchReleaseTime_ = 0L; onChanged(); return this; } private java.util.List exposed_ = - java.util.Collections.emptyList(); + java.util.Collections.emptyList(); + private void ensureExposedIsMutable() { if (!((bitField0_ & 0x00000002) != 0)) { - exposed_ = new java.util.ArrayList(exposed_); + exposed_ = + new java.util.ArrayList( + exposed_); bitField0_ |= 0x00000002; - } + } } private com.google.protobuf.RepeatedFieldBuilderV3< - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder> exposedBuilder_; - - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - public java.util.List getExposedList() { + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder> + exposedBuilder_; + + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + public java.util.List + getExposedList() { if (exposedBuilder_ == null) { return java.util.Collections.unmodifiableList(exposed_); } else { return exposedBuilder_.getMessageList(); } } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public int getExposedCount() { if (exposedBuilder_ == null) { return exposed_.size(); @@ -611,9 +601,7 @@ public int getExposedCount() { return exposedBuilder_.getCount(); } } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee getExposed(int index) { if (exposedBuilder_ == null) { return exposed_.get(index); @@ -621,9 +609,7 @@ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee getExposed(int ind return exposedBuilder_.getMessage(index); } } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder setExposed( int index, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee value) { if (exposedBuilder_ == null) { @@ -638,11 +624,10 @@ public Builder setExposed( } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder setExposed( - int index, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder builderForValue) { + int index, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder builderForValue) { if (exposedBuilder_ == null) { ensureExposedIsMutable(); exposed_.set(index, builderForValue.build()); @@ -652,9 +637,7 @@ public Builder setExposed( } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder addExposed(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee value) { if (exposedBuilder_ == null) { if (value == null) { @@ -668,9 +651,7 @@ public Builder addExposed(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder addExposed( int index, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee value) { if (exposedBuilder_ == null) { @@ -685,9 +666,7 @@ public Builder addExposed( } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder addExposed( org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder builderForValue) { if (exposedBuilder_ == null) { @@ -699,11 +678,10 @@ public Builder addExposed( } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder addExposed( - int index, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder builderForValue) { + int index, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder builderForValue) { if (exposedBuilder_ == null) { ensureExposedIsMutable(); exposed_.add(index, builderForValue.build()); @@ -713,24 +691,20 @@ public Builder addExposed( } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder addAllExposed( - java.lang.Iterable values) { + java.lang.Iterable + values) { if (exposedBuilder_ == null) { ensureExposedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, exposed_); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, exposed_); onChanged(); } else { exposedBuilder_.addAllMessages(values); } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder clearExposed() { if (exposedBuilder_ == null) { exposed_ = java.util.Collections.emptyList(); @@ -741,9 +715,7 @@ public Builder clearExposed() { } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public Builder removeExposed(int index) { if (exposedBuilder_ == null) { ensureExposedIsMutable(); @@ -754,70 +726,66 @@ public Builder removeExposed(int index) { } return this; } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder getExposedBuilder( int index) { return getExposedFieldBuilder().getBuilder(index); } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder getExposedOrBuilder( int index) { if (exposedBuilder_ == null) { - return exposed_.get(index); } else { + return exposed_.get(index); + } else { return exposedBuilder_.getMessageOrBuilder(index); } } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - public java.util.List - getExposedOrBuilderList() { + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + public java.util.List< + ? extends org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder> + getExposedOrBuilderList() { if (exposedBuilder_ != null) { return exposedBuilder_.getMessageOrBuilderList(); } else { return java.util.Collections.unmodifiableList(exposed_); } } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder addExposedBuilder() { - return getExposedFieldBuilder().addBuilder( - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.getDefaultInstance()); + return getExposedFieldBuilder() + .addBuilder( + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.getDefaultInstance()); } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder addExposedBuilder( int index) { - return getExposedFieldBuilder().addBuilder( - index, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.getDefaultInstance()); - } - /** - * repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; - */ - public java.util.List - getExposedBuilderList() { + return getExposedFieldBuilder() + .addBuilder( + index, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.getDefaultInstance()); + } + /** repeated .org.dpppt.backend.sdk.model.proto.ProtoExposee exposed = 2; */ + public java.util.List + getExposedBuilderList() { return getExposedFieldBuilder().getBuilderList(); } + private com.google.protobuf.RepeatedFieldBuilderV3< - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder> + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder> getExposedFieldBuilder() { if (exposedBuilder_ == null) { - exposedBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder>( - exposed_, - ((bitField0_ & 0x00000002) != 0), - getParentForChildren(), - isClean()); + exposedBuilder_ = + new com.google.protobuf.RepeatedFieldBuilderV3< + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder>( + exposed_, ((bitField0_ & 0x00000002) != 0), getParentForChildren(), isClean()); exposed_ = null; } return exposedBuilder_; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -830,12 +798,13 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:org.dpppt.backend.sdk.model.proto.ProtoExposedList) } // @@protoc_insertion_point(class_scope:org.dpppt.backend.sdk.model.proto.ProtoExposedList) - private static final org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList DEFAULT_INSTANCE; + private static final org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList + DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList(); } @@ -844,16 +813,16 @@ public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList getDefa return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ProtoExposedList parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new ProtoExposedList(input, extensionRegistry); - } - }; + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ProtoExposedList parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ProtoExposedList(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -868,44 +837,39 @@ public com.google.protobuf.Parser getParserForType() { public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposedList getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } - public interface ProtoExposeeOrBuilder extends + public interface ProtoExposeeOrBuilder + extends // @@protoc_insertion_point(interface_extends:org.dpppt.backend.sdk.model.proto.ProtoExposee) com.google.protobuf.MessageOrBuilder { - /** - * bytes key = 2; - */ + /** bytes key = 2; */ com.google.protobuf.ByteString getKey(); - /** - * int64 keyDate = 3; - */ + /** int64 keyDate = 3; */ long getKeyDate(); } - /** - * Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposee} - */ - public static final class ProtoExposee extends - com.google.protobuf.GeneratedMessageV3 implements + /** Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposee} */ + public static final class ProtoExposee extends com.google.protobuf.GeneratedMessageV3 + implements // @@protoc_insertion_point(message_implements:org.dpppt.backend.sdk.model.proto.ProtoExposee) ProtoExposeeOrBuilder { - private static final long serialVersionUID = 0L; + private static final long serialVersionUID = 0L; // Use ProtoExposee.newBuilder() to construct. private ProtoExposee(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } + private ProtoExposee() { key_ = com.google.protobuf.ByteString.EMPTY; } @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { return this.unknownFields; } + private ProtoExposee( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) @@ -925,67 +889,66 @@ private ProtoExposee( case 0: done = true; break; - case 18: { - - key_ = input.readBytes(); - break; - } - case 24: { - - keyDate_ = input.readInt64(); - break; - } - default: { - if (!parseUnknownField( - input, unknownFields, extensionRegistry, tag)) { - done = true; + case 18: + { + key_ = input.readBytes(); + break; + } + case 24: + { + keyDate_ = input.readInt64(); + break; + } + default: + { + if (!parseUnknownField(input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; } - break; - } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); } finally { this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable .ensureFieldAccessorsInitialized( - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.class, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder.class); + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.class, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder.class); } public static final int KEY_FIELD_NUMBER = 2; private com.google.protobuf.ByteString key_; - /** - * bytes key = 2; - */ + /** bytes key = 2; */ public com.google.protobuf.ByteString getKey() { return key_; } public static final int KEYDATE_FIELD_NUMBER = 3; private long keyDate_; - /** - * int64 keyDate = 3; - */ + /** int64 keyDate = 3; */ public long getKeyDate() { return keyDate_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -997,8 +960,7 @@ public final boolean isInitialized() { } @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (!key_.isEmpty()) { output.writeBytes(2, key_); } @@ -1015,12 +977,10 @@ public int getSerializedSize() { size = 0; if (!key_.isEmpty()) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, key_); + size += com.google.protobuf.CodedOutputStream.computeBytesSize(2, key_); } if (keyDate_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(3, keyDate_); + size += com.google.protobuf.CodedOutputStream.computeInt64Size(3, keyDate_); } size += unknownFields.getSerializedSize(); memoizedSize = size; @@ -1030,17 +990,16 @@ public int getSerializedSize() { @java.lang.Override public boolean equals(final java.lang.Object obj) { if (obj == this) { - return true; + return true; } if (!(obj instanceof org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee)) { return super.equals(obj); } - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee other = (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee) obj; + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee other = + (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee) obj; - if (!getKey() - .equals(other.getKey())) return false; - if (getKeyDate() - != other.getKeyDate()) return false; + if (!getKey().equals(other.getKey())) return false; + if (getKeyDate() != other.getKeyDate()) return false; if (!unknownFields.equals(other.unknownFields)) return false; return true; } @@ -1055,95 +1014,101 @@ public int hashCode() { hash = (37 * hash) + KEY_FIELD_NUMBER; hash = (53 * hash) + getKey().hashCode(); hash = (37 * hash) + KEYDATE_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getKeyDate()); + hash = (53 * hash) + com.google.protobuf.Internal.hashLong(getKeyDate()); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { + java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } - public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); + + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); } + public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); + return com.google.protobuf.GeneratedMessageV3.parseWithIOException( + PARSER, input, extensionRegistry); } @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } + public Builder newBuilderForType() { + return newBuilder(); + } + public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee prototype) { + + public static Builder newBuilder( + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } @java.lang.Override @@ -1152,24 +1117,25 @@ protected Builder newBuilderForType( Builder builder = new Builder(parent); return builder; } - /** - * Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposee} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements + /** Protobuf type {@code org.dpppt.backend.sdk.model.proto.ProtoExposee} */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements // @@protoc_insertion_point(builder_implements:org.dpppt.backend.sdk.model.proto.ProtoExposee) org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposeeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable .ensureFieldAccessorsInitialized( - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.class, org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder.class); + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.class, + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.Builder.class); } // Construct using org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.newBuilder() @@ -1177,16 +1143,15 @@ private Builder() { maybeForceBuilderInitialization(); } - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { super(parent); maybeForceBuilderInitialization(); } + private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } + if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {} } + @java.lang.Override public Builder clear() { super.clear(); @@ -1198,9 +1163,9 @@ public Builder clear() { } @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.dpppt.backend.sdk.model.proto.Exposed.internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return org.dpppt.backend.sdk.model.proto.Exposed + .internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; } @java.lang.Override @@ -1219,7 +1184,8 @@ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee build() { @java.lang.Override public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee buildPartial() { - org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee result = new org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee(this); + org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee result = + new org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee(this); result.key_ = key_; result.keyDate_ = keyDate_; onBuilt(); @@ -1230,38 +1196,41 @@ public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee buildPartial() { public Builder clone() { return super.clone(); } + @java.lang.Override public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.setField(field, value); } + @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { + public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) { return super.clearField(field); } + @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { + public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) { return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { + int index, + java.lang.Object value) { return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { + com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) { return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { if (other instanceof org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee) { - return mergeFrom((org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee)other); + return mergeFrom((org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee) other); } else { super.mergeFrom(other); return this; @@ -1269,7 +1238,8 @@ public Builder mergeFrom(com.google.protobuf.Message other) { } public Builder mergeFrom(org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee other) { - if (other == org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.getDefaultInstance()) return this; + if (other == org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee.getDefaultInstance()) + return this; if (other.getKey() != com.google.protobuf.ByteString.EMPTY) { setKey(other.getKey()); } @@ -1295,7 +1265,8 @@ public Builder mergeFrom( try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee) e.getUnfinishedMessage(); + parsedMessage = + (org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -1306,59 +1277,48 @@ public Builder mergeFrom( } private com.google.protobuf.ByteString key_ = com.google.protobuf.ByteString.EMPTY; - /** - * bytes key = 2; - */ + /** bytes key = 2; */ public com.google.protobuf.ByteString getKey() { return key_; } - /** - * bytes key = 2; - */ + /** bytes key = 2; */ public Builder setKey(com.google.protobuf.ByteString value) { if (value == null) { - throw new NullPointerException(); - } - + throw new NullPointerException(); + } + key_ = value; onChanged(); return this; } - /** - * bytes key = 2; - */ + /** bytes key = 2; */ public Builder clearKey() { - + key_ = getDefaultInstance().getKey(); onChanged(); return this; } - private long keyDate_ ; - /** - * int64 keyDate = 3; - */ + private long keyDate_; + /** int64 keyDate = 3; */ public long getKeyDate() { return keyDate_; } - /** - * int64 keyDate = 3; - */ + /** int64 keyDate = 3; */ public Builder setKeyDate(long value) { - + keyDate_ = value; onChanged(); return this; } - /** - * int64 keyDate = 3; - */ + /** int64 keyDate = 3; */ public Builder clearKeyDate() { - + keyDate_ = 0L; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { @@ -1371,12 +1331,12 @@ public final Builder mergeUnknownFields( return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:org.dpppt.backend.sdk.model.proto.ProtoExposee) } // @@protoc_insertion_point(class_scope:org.dpppt.backend.sdk.model.proto.ProtoExposee) private static final org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee DEFAULT_INSTANCE; + static { DEFAULT_INSTANCE = new org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee(); } @@ -1385,16 +1345,16 @@ public static org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee getDefaultI return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ProtoExposee parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new ProtoExposee(input, extensionRegistry); - } - }; + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ProtoExposee parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new ProtoExposee(input, extensionRegistry); + } + }; public static com.google.protobuf.Parser parser() { return PARSER; @@ -1409,59 +1369,58 @@ public com.google.protobuf.Parser getParserForType() { public org.dpppt.backend.sdk.model.proto.Exposed.ProtoExposee getDefaultInstanceForType() { return DEFAULT_INSTANCE; } - } private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor; + private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable; - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { return descriptor; } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + static { java.lang.String[] descriptorData = { - "\n\rexposed.proto\022!org.dpppt.backend.sdk.m" + - "odel.proto\"n\n\020ProtoExposedList\022\030\n\020batchR" + - "eleaseTime\030\001 \001(\003\022@\n\007exposed\030\002 \003(\0132/.org." + - "dpppt.backend.sdk.model.proto.ProtoExpos" + - "ee\",\n\014ProtoExposee\022\013\n\003key\030\002 \001(\014\022\017\n\007keyDa" + - "te\030\003 \001(\003b\006proto3" + "\n\rexposed.proto\022!org.dpppt.backend.sdk.m" + + "odel.proto\"n\n\020ProtoExposedList\022\030\n\020batchR" + + "eleaseTime\030\001 \001(\003\022@\n\007exposed\030\002 \003(\0132/.org." + + "dpppt.backend.sdk.model.proto.ProtoExpos" + + "ee\",\n\014ProtoExposee\022\013\n\003key\030\002 \001(\014\022\017\n\007keyDa" + + "te\030\003 \001(\003b\006proto3" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.Descriptors.FileDescriptor root) { descriptor = root; return null; } }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); + com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( + descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner); internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor, - new java.lang.String[] { "BatchReleaseTime", "Exposed", }); + getDescriptor().getMessageTypes().get(0); + internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposedList_descriptor, + new java.lang.String[] { + "BatchReleaseTime", "Exposed", + }); internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor, - new java.lang.String[] { "Key", "KeyDate", }); + getDescriptor().getMessageTypes().get(1); + internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_org_dpppt_backend_sdk_model_proto_ProtoExposee_descriptor, + new java.lang.String[] { + "Key", "KeyDate", + }); } // @@protoc_insertion_point(outer_class_scope) diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/semver/Version.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/semver/Version.java index a521adf4..f732150d 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/semver/Version.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/semver/Version.java @@ -4,228 +4,246 @@ import java.util.regex.Pattern; public class Version implements Comparable { - private Integer major; - private Integer minor; - private Integer patch; - private String preReleaseString = ""; - private String metaInfo = ""; - private String platform = ""; - - private final Pattern semVerPattern = Pattern.compile("^(?:(?ios|android)-)?(?0|[1-9]\\d*)(\\.(?0|[1-9]\\d*))?(\\.(?0|[1-9]\\d*))?(?:-(?(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); - - public Version() { - } - - public Version(String versionString) { - if(versionString == null) { - this.setInvalidValue(); - return; - } - this.major = -1; - this.minor = 0; - this.patch = 0; - - var matches = semVerPattern.matcher(versionString.trim()); - if(matches.find()) { - this.major = Integer.parseInt(matches.group("major")); - if(matches.group("minor") != null) { - this.minor = Integer.parseInt(matches.group("minor")); - } - if(matches.group("patch") != null) { - this.patch = Integer.parseInt(matches.group("patch")); - } - if(matches.group("platform") != null) { - this.platform = matches.group("platform"); - } - if(matches.group("prerelease") != null) { - this.preReleaseString = matches.group("prerelease"); - } - if(matches.group("buildmetadata") != null) { - this.metaInfo = matches.group("buildmetadata"); - } - } else { - this.setInvalidValue(); - } - } - - public Version(Integer major, Integer minor, Integer patch) { - this.major = major; - this.minor = minor; - this.patch = patch; - this.preReleaseString = ""; - this.metaInfo = ""; - } - public Version(Integer major, Integer minor) { - this.major = major; - this.minor = minor; - this.patch = 0; - this.preReleaseString = ""; - this.metaInfo = ""; - } - public Version(Integer major) { - this.major = major; - this.minor = 0; - this.patch = 0; - this.preReleaseString = ""; - this.metaInfo = ""; - } - - public Version(Integer major, Integer minor, Integer patch, String preReleaseString, String metaInfo) { - this.major = major; - this.minor = minor; - this.patch = patch; - this.preReleaseString = preReleaseString; - this.metaInfo = metaInfo; - } - - private void setInvalidValue() { - this.major = -1; - this.minor = -1; - this.patch = -1; - this.preReleaseString = ""; - this.metaInfo = ""; - } - public boolean isValid() { - return major.compareTo(Integer.valueOf(0)) >= 0 - && minor.compareTo(Integer.valueOf(0)) >= 0 - && patch.compareTo(Integer.valueOf(0)) >= 0; - } - - public Integer getMajor() { - return this.major; - } - - public void setMajor(Integer major) { - this.major = major; - } - - public Integer getMinor() { - return this.minor; - } - - public void setMinor(Integer minor) { - this.minor = minor; - } - - public Integer getPatch() { - return this.patch; - } - - public void setPatch(Integer patch) { - this.patch = patch; - } - - public String getPreReleaseString() { - return this.preReleaseString; - } - - public void setPreReleaseString(String preReleaseString) { - this.preReleaseString = preReleaseString; - } - - public String getMetaInfo() { - return this.metaInfo; - } - - public void setMetaInfo(String metaInfo) { - this.metaInfo = metaInfo; - } - public String getPlatform() { - return this.platform; - } - - public void setPlatform(String platform) { - this.platform = platform; - } - - public Version major(Integer major) { - this.major = major; - return this; - } - - public Version minor(Integer minor) { - this.minor = minor; - return this; - } - - public Version patch(Integer patch) { - this.patch = patch; - return this; - } - - public Version preReleaseString(String preReleaseString) { - this.preReleaseString = preReleaseString; - return this; - } - - public Version metaInfo(String metaInfo) { - this.metaInfo = metaInfo; - return this; - } - - public boolean isPrerelease() { - return !preReleaseString.isEmpty(); - } - - public boolean isAndroid() { - return platform.contains("android") || metaInfo.contains("android"); - } - public boolean isIOS() { - return platform.contains("ios") || metaInfo.contains("ios"); - } - - @Override - public boolean equals(Object o) { - if (o == this) - return true; - if (!(o instanceof Version)) { - return false; - } - Version version = (Version) o; - return Objects.equals(major, version.major) && Objects.equals(minor, version.minor) && Objects.equals(patch, version.patch) && Objects.equals(preReleaseString, version.preReleaseString) && Objects.equals(metaInfo, version.metaInfo) && Objects.equals(platform, version.platform); - } - - @Override - public int hashCode() { - return Objects.hash(major, minor, patch, preReleaseString, metaInfo); - } - - @Override - public String toString() { - return getMajor() + "." + getMinor() + "." + getPatch() + (getPreReleaseString().isEmpty()? "" : "-" + getPreReleaseString()) + (getMetaInfo().isEmpty()? "" : "+" + getMetaInfo()); - } - - @Override - public int compareTo(Version o) { - if(this.major.compareTo(o.major) != 0) { - return this.major.compareTo(o.major); - } - if(this.minor.compareTo(o.minor) != 0) { - return this.minor.compareTo(o.minor); - } - if(this.patch.compareTo(o.patch) != 0) { - return this.patch.compareTo(o.patch); - } - if(this.isPrerelease() && o.isPrerelease()) { - if(this.preReleaseString.compareTo(o.preReleaseString) != 0) { - return this.preReleaseString.compareTo(o.preReleaseString); - } - } else if(this.isPrerelease() && !o.isPrerelease()) { - return -1; - } else if(!this.isPrerelease() && o.isPrerelease()) { - return 1; - } - return 0; - } - - public boolean isSmallerVersionThan(Version other) { - return this.compareTo(other) < 0; - } - public boolean isLargerVersionThan(Version other) { - return this.compareTo(other) > 0; - } - public boolean isSameVersionAs(Version other) { - return this.compareTo(other) == 0; - } - -} \ No newline at end of file + private Integer major; + private Integer minor; + private Integer patch; + private String preReleaseString = ""; + private String metaInfo = ""; + private String platform = ""; + + private final Pattern semVerPattern = + Pattern.compile( + "^(?:(?ios|android)-)?(?0|[1-9]\\d*)(\\.(?0|[1-9]\\d*))?(\\.(?0|[1-9]\\d*))?(?:-(?(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); + + public Version() {} + + public Version(String versionString) { + if (versionString == null) { + this.setInvalidValue(); + return; + } + this.major = -1; + this.minor = 0; + this.patch = 0; + + var matches = semVerPattern.matcher(versionString.trim()); + if (matches.find()) { + this.major = Integer.parseInt(matches.group("major")); + if (matches.group("minor") != null) { + this.minor = Integer.parseInt(matches.group("minor")); + } + if (matches.group("patch") != null) { + this.patch = Integer.parseInt(matches.group("patch")); + } + if (matches.group("platform") != null) { + this.platform = matches.group("platform"); + } + if (matches.group("prerelease") != null) { + this.preReleaseString = matches.group("prerelease"); + } + if (matches.group("buildmetadata") != null) { + this.metaInfo = matches.group("buildmetadata"); + } + } else { + this.setInvalidValue(); + } + } + + public Version(Integer major, Integer minor, Integer patch) { + this.major = major; + this.minor = minor; + this.patch = patch; + this.preReleaseString = ""; + this.metaInfo = ""; + } + + public Version(Integer major, Integer minor) { + this.major = major; + this.minor = minor; + this.patch = 0; + this.preReleaseString = ""; + this.metaInfo = ""; + } + + public Version(Integer major) { + this.major = major; + this.minor = 0; + this.patch = 0; + this.preReleaseString = ""; + this.metaInfo = ""; + } + + public Version( + Integer major, Integer minor, Integer patch, String preReleaseString, String metaInfo) { + this.major = major; + this.minor = minor; + this.patch = patch; + this.preReleaseString = preReleaseString; + this.metaInfo = metaInfo; + } + + private void setInvalidValue() { + this.major = -1; + this.minor = -1; + this.patch = -1; + this.preReleaseString = ""; + this.metaInfo = ""; + } + + public boolean isValid() { + return major.compareTo(Integer.valueOf(0)) >= 0 + && minor.compareTo(Integer.valueOf(0)) >= 0 + && patch.compareTo(Integer.valueOf(0)) >= 0; + } + + public Integer getMajor() { + return this.major; + } + + public void setMajor(Integer major) { + this.major = major; + } + + public Integer getMinor() { + return this.minor; + } + + public void setMinor(Integer minor) { + this.minor = minor; + } + + public Integer getPatch() { + return this.patch; + } + + public void setPatch(Integer patch) { + this.patch = patch; + } + + public String getPreReleaseString() { + return this.preReleaseString; + } + + public void setPreReleaseString(String preReleaseString) { + this.preReleaseString = preReleaseString; + } + + public String getMetaInfo() { + return this.metaInfo; + } + + public void setMetaInfo(String metaInfo) { + this.metaInfo = metaInfo; + } + + public String getPlatform() { + return this.platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public Version major(Integer major) { + this.major = major; + return this; + } + + public Version minor(Integer minor) { + this.minor = minor; + return this; + } + + public Version patch(Integer patch) { + this.patch = patch; + return this; + } + + public Version preReleaseString(String preReleaseString) { + this.preReleaseString = preReleaseString; + return this; + } + + public Version metaInfo(String metaInfo) { + this.metaInfo = metaInfo; + return this; + } + + public boolean isPrerelease() { + return !preReleaseString.isEmpty(); + } + + public boolean isAndroid() { + return platform.contains("android") || metaInfo.contains("android"); + } + + public boolean isIOS() { + return platform.contains("ios") || metaInfo.contains("ios"); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Version)) { + return false; + } + Version version = (Version) o; + return Objects.equals(major, version.major) + && Objects.equals(minor, version.minor) + && Objects.equals(patch, version.patch) + && Objects.equals(preReleaseString, version.preReleaseString) + && Objects.equals(metaInfo, version.metaInfo) + && Objects.equals(platform, version.platform); + } + + @Override + public int hashCode() { + return Objects.hash(major, minor, patch, preReleaseString, metaInfo); + } + + @Override + public String toString() { + return getMajor() + + "." + + getMinor() + + "." + + getPatch() + + (getPreReleaseString().isEmpty() ? "" : "-" + getPreReleaseString()) + + (getMetaInfo().isEmpty() ? "" : "+" + getMetaInfo()); + } + + @Override + public int compareTo(Version o) { + if (this.major.compareTo(o.major) != 0) { + return this.major.compareTo(o.major); + } + if (this.minor.compareTo(o.minor) != 0) { + return this.minor.compareTo(o.minor); + } + if (this.patch.compareTo(o.patch) != 0) { + return this.patch.compareTo(o.patch); + } + if (this.isPrerelease() && o.isPrerelease()) { + if (this.preReleaseString.compareTo(o.preReleaseString) != 0) { + return this.preReleaseString.compareTo(o.preReleaseString); + } + } else if (this.isPrerelease() && !o.isPrerelease()) { + return -1; + } else if (!this.isPrerelease() && o.isPrerelease()) { + return 1; + } + return 0; + } + + public boolean isSmallerVersionThan(Version other) { + return this.compareTo(other) < 0; + } + + public boolean isLargerVersionThan(Version other) { + return this.compareTo(other) > 0; + } + + public boolean isSameVersionAs(Version other) { + return this.compareTo(other) == 0; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/utils/UTCInstant.java b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/utils/UTCInstant.java index 80b25f43..6da4d0eb 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/utils/UTCInstant.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-model/src/main/java/org/dpppt/backend/sdk/utils/UTCInstant.java @@ -10,227 +10,223 @@ import java.time.ZoneOffset; import java.time.temporal.TemporalUnit; import java.util.Date; - import org.dpppt.backend.sdk.model.gaen.GaenUnit; /** - * This class collects all usages of time within the project. Any `java.time.*` - * class should have its equivalent regarding UTC. - * - * All timestamps should be described as 'milliseconds since Unix epoch'. - * - * - * IMPORTANT: `Local*` classes do not carry any timezone informations. As such, - * all comparisons are made regarding 'UTC' - * - * + * This class collects all usages of time within the project. Any `java.time.*` class should have + * its equivalent regarding UTC. + * + *

All timestamps should be described as 'milliseconds since Unix epoch'. + * + *

IMPORTANT: `Local*` classes do not carry any timezone informations. As such, all comparisons + * are made regarding 'UTC' */ - public class UTCInstant { - private final long timestamp; - private static Clock currentClock = Clock.systemUTC(); - - public static UTCInstant today() { - return UTCInstant.now().atStartOfDay(); - } - - public static UTCInstant midnight1970() { - return new UTCInstant(0); - } - - public UTCInstant(long timestamp) { - this.timestamp = timestamp; - } - - public UTCInstant(Duration duration, UTCInstant since) { - this.timestamp = since.timestamp + duration.toMillis(); - } - - public UTCInstant(Instant instant) { - this.timestamp = instant.toEpochMilli(); - } - - public UTCInstant(long units, TemporalUnit interval) { - this.timestamp = units * interval.getDuration().toMillis(); - } - - public UTCInstant(OffsetDateTime offsetDateTime) { - this.timestamp = offsetDateTime.toInstant().toEpochMilli(); - } - - //TODO: make protected and subclass for use in tests - public static void setClock(Clock clock) { - currentClock = clock; - } - - public static void resetClock() { - currentClock = Clock.systemUTC(); - } - - public static UTCInstant now() { - var nowTimestamp = currentClock.millis(); - return new UTCInstant(nowTimestamp); - } - - public static UTCInstant of(long amount, TemporalUnit unit) { - return new UTCInstant(amount, unit); - } - - public static UTCInstant ofEpochMillis(long epochMillis) { - return new UTCInstant(epochMillis); - } - - public static UTCInstant parseDate(String dateString) { - var timestamp = LocalDate.parse(dateString).atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(); - return new UTCInstant(timestamp); - } - - public static UTCInstant parseDateTime(String dateString) { - var timestamp = LocalDateTime.parse(dateString).toInstant(ZoneOffset.UTC).toEpochMilli(); - return new UTCInstant(timestamp); - } - - public Date getDate() { - return Date.from(getInstant()); - } - - public Instant getInstant() { - return Instant.ofEpochMilli(this.timestamp); - } - - public Duration getDuration(long since) { - return Duration.ofMillis(this.timestamp - since); - } - - public Duration getDuration(UTCInstant since) { - return Duration.ofMillis(this.timestamp - since.timestamp); - } - - public OffsetDateTime getOffsetDateTime() { - return OffsetDateTime.ofInstant(getInstant(), ZoneOffset.UTC); - } - - public LocalDateTime getLocalDateTime() { - return LocalDateTime.ofInstant(getInstant(), ZoneOffset.UTC); - } - - public UTCInstant atStartOfDay() { - return new UTCInstant(getLocalDate().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()); - } - - public LocalDate getLocalDate() { - return getLocalDateTime().toLocalDate(); - } - - public LocalTime getLocalTime() { - return getLocalDateTime().toLocalTime(); - } - - public UTCInstant plus(Duration duration) { - return new UTCInstant(this.timestamp + duration.toMillis()); - } - - public UTCInstant minus(Duration duration) { - return new UTCInstant(this.timestamp - duration.toMillis()); - } - - public UTCInstant plusYears(long years) { - return new UTCInstant(this.getOffsetDateTime().plusYears(years)); - } - - public UTCInstant minusYears(long years) { - return new UTCInstant(this.getOffsetDateTime().minusYears(years)); - } - - public UTCInstant plusDays(long days) { - return new UTCInstant(this.timestamp + Duration.ofDays(days).toMillis()); - } - - public UTCInstant minusDays(long days) { - return new UTCInstant(this.timestamp - Duration.ofDays(days).toMillis()); - } - - public UTCInstant plusHours(long hours) { - return new UTCInstant(this.timestamp + Duration.ofHours(hours).toMillis()); - } - - public UTCInstant minusHours(long hours) { - return new UTCInstant(this.timestamp - Duration.ofHours(hours).toMillis()); - } - - public UTCInstant plusMinutes(long minutes) { - return new UTCInstant(this.timestamp + Duration.ofMinutes(minutes).toMillis()); - } - - public UTCInstant minusMinutes(long minutes) { - return new UTCInstant(this.timestamp - Duration.ofMinutes(minutes).toMillis()); - } - - public UTCInstant plusSeconds(long seconds) { - return new UTCInstant(this.timestamp + Duration.ofSeconds(seconds).toMillis()); - } - - public UTCInstant minusSeconds(long seconds) { - return new UTCInstant(this.timestamp - Duration.ofSeconds(seconds).toMillis()); - } - - public boolean isMidnight() { - return getLocalTime().equals(LocalTime.MIDNIGHT); - } - - public long getTimestamp() { - return timestamp; - } - - public long get10MinutesSince1970() { - return getDuration(midnight1970()).dividedBy(GaenUnit.TenMinutes.getDuration()); - } - - public boolean hasSameDateAs(UTCInstant otherInstant) { - return this.getLocalDate().isEqual(otherInstant.getLocalDate()); - } + private final long timestamp; + private static Clock currentClock = Clock.systemUTC(); + + public static UTCInstant today() { + return UTCInstant.now().atStartOfDay(); + } + + public static UTCInstant midnight1970() { + return new UTCInstant(0); + } + + public UTCInstant(long timestamp) { + this.timestamp = timestamp; + } + + public UTCInstant(Duration duration, UTCInstant since) { + this.timestamp = since.timestamp + duration.toMillis(); + } + + public UTCInstant(Instant instant) { + this.timestamp = instant.toEpochMilli(); + } + + public UTCInstant(long units, TemporalUnit interval) { + this.timestamp = units * interval.getDuration().toMillis(); + } + + public UTCInstant(OffsetDateTime offsetDateTime) { + this.timestamp = offsetDateTime.toInstant().toEpochMilli(); + } + + // TODO: make protected and subclass for use in tests + public static void setClock(Clock clock) { + currentClock = clock; + } + + public static void resetClock() { + currentClock = Clock.systemUTC(); + } + + public static UTCInstant now() { + var nowTimestamp = currentClock.millis(); + return new UTCInstant(nowTimestamp); + } + + public static UTCInstant of(long amount, TemporalUnit unit) { + return new UTCInstant(amount, unit); + } + + public static UTCInstant ofEpochMillis(long epochMillis) { + return new UTCInstant(epochMillis); + } + + public static UTCInstant parseDate(String dateString) { + var timestamp = + LocalDate.parse(dateString).atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli(); + return new UTCInstant(timestamp); + } + + public static UTCInstant parseDateTime(String dateString) { + var timestamp = LocalDateTime.parse(dateString).toInstant(ZoneOffset.UTC).toEpochMilli(); + return new UTCInstant(timestamp); + } + + public Date getDate() { + return Date.from(getInstant()); + } + + public Instant getInstant() { + return Instant.ofEpochMilli(this.timestamp); + } + + public Duration getDuration(long since) { + return Duration.ofMillis(this.timestamp - since); + } + + public Duration getDuration(UTCInstant since) { + return Duration.ofMillis(this.timestamp - since.timestamp); + } + + public OffsetDateTime getOffsetDateTime() { + return OffsetDateTime.ofInstant(getInstant(), ZoneOffset.UTC); + } + + public LocalDateTime getLocalDateTime() { + return LocalDateTime.ofInstant(getInstant(), ZoneOffset.UTC); + } + + public UTCInstant atStartOfDay() { + return new UTCInstant(getLocalDate().atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli()); + } + + public LocalDate getLocalDate() { + return getLocalDateTime().toLocalDate(); + } + + public LocalTime getLocalTime() { + return getLocalDateTime().toLocalTime(); + } + + public UTCInstant plus(Duration duration) { + return new UTCInstant(this.timestamp + duration.toMillis()); + } + + public UTCInstant minus(Duration duration) { + return new UTCInstant(this.timestamp - duration.toMillis()); + } + + public UTCInstant plusYears(long years) { + return new UTCInstant(this.getOffsetDateTime().plusYears(years)); + } + + public UTCInstant minusYears(long years) { + return new UTCInstant(this.getOffsetDateTime().minusYears(years)); + } + + public UTCInstant plusDays(long days) { + return new UTCInstant(this.timestamp + Duration.ofDays(days).toMillis()); + } + + public UTCInstant minusDays(long days) { + return new UTCInstant(this.timestamp - Duration.ofDays(days).toMillis()); + } + + public UTCInstant plusHours(long hours) { + return new UTCInstant(this.timestamp + Duration.ofHours(hours).toMillis()); + } + + public UTCInstant minusHours(long hours) { + return new UTCInstant(this.timestamp - Duration.ofHours(hours).toMillis()); + } + + public UTCInstant plusMinutes(long minutes) { + return new UTCInstant(this.timestamp + Duration.ofMinutes(minutes).toMillis()); + } + + public UTCInstant minusMinutes(long minutes) { + return new UTCInstant(this.timestamp - Duration.ofMinutes(minutes).toMillis()); + } + + public UTCInstant plusSeconds(long seconds) { + return new UTCInstant(this.timestamp + Duration.ofSeconds(seconds).toMillis()); + } + + public UTCInstant minusSeconds(long seconds) { + return new UTCInstant(this.timestamp - Duration.ofSeconds(seconds).toMillis()); + } + + public boolean isMidnight() { + return getLocalTime().equals(LocalTime.MIDNIGHT); + } + + public long getTimestamp() { + return timestamp; + } + + public long get10MinutesSince1970() { + return getDuration(midnight1970()).dividedBy(GaenUnit.TenMinutes.getDuration()); + } + + public boolean hasSameDateAs(UTCInstant otherInstant) { + return this.getLocalDate().isEqual(otherInstant.getLocalDate()); + } - public boolean hasSameTimeOfDayAs(UTCInstant otherInstant) { - return this.getLocalTime().equals(otherInstant.getLocalTime()); - } + public boolean hasSameTimeOfDayAs(UTCInstant otherInstant) { + return this.getLocalTime().equals(otherInstant.getLocalTime()); + } - public boolean isBeforeEpochMillisOf(UTCInstant otherInstant) { - return this.getTimestamp() < otherInstant.getTimestamp(); - } + public boolean isBeforeEpochMillisOf(UTCInstant otherInstant) { + return this.getTimestamp() < otherInstant.getTimestamp(); + } - public boolean isAfterEpochMillisOf(UTCInstant otherInstant) { - return this.getTimestamp() > otherInstant.getTimestamp(); - } + public boolean isAfterEpochMillisOf(UTCInstant otherInstant) { + return this.getTimestamp() > otherInstant.getTimestamp(); + } - public boolean isBeforeDateOf(UTCInstant otherInstant) { - return this.getLocalDate().isBefore(otherInstant.getLocalDate()); - } + public boolean isBeforeDateOf(UTCInstant otherInstant) { + return this.getLocalDate().isBefore(otherInstant.getLocalDate()); + } - public boolean isAfterDateOf(UTCInstant otherInstant) { - return this.getLocalDate().isAfter(otherInstant.getLocalDate()); - } + public boolean isAfterDateOf(UTCInstant otherInstant) { + return this.getLocalDate().isAfter(otherInstant.getLocalDate()); + } - public boolean isBeforeDateOf(LocalDate otherDate) { - return this.getLocalDate().isBefore(otherDate); - } + public boolean isBeforeDateOf(LocalDate otherDate) { + return this.getLocalDate().isBefore(otherDate); + } - public boolean isAfterDateOf(LocalDate otherDate) { - return this.getLocalDate().isAfter(otherDate); - } + public boolean isAfterDateOf(LocalDate otherDate) { + return this.getLocalDate().isAfter(otherDate); + } - public boolean isBeforeTimeOfDayOf(UTCInstant otherInstant) { - return this.getLocalTime().isBefore(otherInstant.getLocalTime()); - } + public boolean isBeforeTimeOfDayOf(UTCInstant otherInstant) { + return this.getLocalTime().isBefore(otherInstant.getLocalTime()); + } - public boolean isAfterTimeOfDayOf(UTCInstant otherInstant) { - return this.getLocalTime().isAfter(otherInstant.getLocalTime()); - } + public boolean isAfterTimeOfDayOf(UTCInstant otherInstant) { + return this.getLocalTime().isAfter(otherInstant.getLocalTime()); + } - public boolean isBeforeToday() { - return this.isBeforeDateOf(UTCInstant.now()); - } + public boolean isBeforeToday() { + return this.isBeforeDateOf(UTCInstant.now()); + } - public boolean isAfterToday() { - return this.isAfterDateOf(UTCInstant.now()); - } + public boolean isAfterToday() { + return this.isAfterDateOf(UTCInstant.now()); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/Application.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/Application.java index ac204db6..d2dcb6f7 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/Application.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/Application.java @@ -19,13 +19,13 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration -@ComponentScan(basePackages = { "org.dpppt.backend.sdk.ws.config" }) -@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class }) +@ComponentScan(basePackages = {"org.dpppt.backend.sdk.ws.config"}) +@EnableAutoConfiguration( + exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class}) @EnableWebMvc public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class); - } - + public static void main(String[] args) { + SpringApplication.run(Application.class); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/ActuatorSecurity.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/ActuatorSecurity.java index 8eb6a2ad..213c6c58 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/ActuatorSecurity.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/ActuatorSecurity.java @@ -27,64 +27,92 @@ @EnableWebSecurity public class ActuatorSecurity extends WebSecurityConfigurerAdapter { - private static final String PROMETHEUS_ROLE = "PROMETHEUS"; + private static final String PROMETHEUS_ROLE = "PROMETHEUS"; - @Value("${ws.monitor.prometheus.user}") - private String user; + @Value("${ws.monitor.prometheus.user}") + private String user; - @Autowired Environment environment; - // region Actuator Passwords - //---------------------------------------------------------------------------------------------------------------------------------- - @Bean - @Profile("cloud-dev") - ActuatorSecurityConfig passwordCloudDev() { - return new ActuatorSecurityConfig(user, environment.getProperty("vcap.services.ha_prometheus_dev.credentials.password")); - } - @Bean - @Profile("cloud-test") - ActuatorSecurityConfig passwordCloudTest() { - return new ActuatorSecurityConfig(user, environment.getProperty("vcap.services.ha_prometheus_test.credentials.password")); - } - @Bean - @Profile("cloud-abn") - ActuatorSecurityConfig passwordCloudAbn() { - return new ActuatorSecurityConfig(user, environment.getProperty("vcap.services.ha_prometheus_abn.credentials.password")); - } - @Bean - @Profile("cloud-prod") - ActuatorSecurityConfig passwordProdAbn() { - return new ActuatorSecurityConfig(user, environment.getProperty("vcap.services.ha_prometheus_prod.credentials.password")); - } + @Autowired Environment environment; + // region Actuator Passwords + // ---------------------------------------------------------------------------------------------------------------------------------- + @Bean + @Profile("cloud-dev") + ActuatorSecurityConfig passwordCloudDev() { + return new ActuatorSecurityConfig( + user, environment.getProperty("vcap.services.ha_prometheus_dev.credentials.password")); + } - @Bean - @ConditionalOnMissingBean - ActuatorSecurityConfig passwordDefault() { - return new ActuatorSecurityConfig(user, environment.getProperty("ws.monitor.prometheus.password")); - } - //---------------------------------------------------------------------------------------------------------------------------------- - //endregion - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.requestMatcher(org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.toAnyEndpoint()). - authorizeRequests(). - requestMatchers(org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to(HealthEndpoint.class)).permitAll(). - requestMatchers(org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to(InfoEndpoint.class)).permitAll(). - requestMatchers(org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to(LoggersEndpoint.class)).hasRole(PROMETHEUS_ROLE). - requestMatchers(org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to(PrometheusScrapeEndpoint.class)).hasRole(PROMETHEUS_ROLE). - anyRequest().denyAll(). - and(). - httpBasic(); + @Bean + @Profile("cloud-test") + ActuatorSecurityConfig passwordCloudTest() { + return new ActuatorSecurityConfig( + user, environment.getProperty("vcap.services.ha_prometheus_test.credentials.password")); + } - http.csrf().ignoringAntMatchers("/actuator/loggers/**"); - } + @Bean + @Profile("cloud-abn") + ActuatorSecurityConfig passwordCloudAbn() { + return new ActuatorSecurityConfig( + user, environment.getProperty("vcap.services.ha_prometheus_abn.credentials.password")); + } - @Autowired - protected void configureGlobal(AuthenticationManagerBuilder auth, ActuatorSecurityConfig securityConfig) throws Exception { - auth.inMemoryAuthentication().withUser(securityConfig.getUsername()).password(passwordEncoder().encode(securityConfig.getPassword())).roles(PROMETHEUS_ROLE); - } - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } -} \ No newline at end of file + @Bean + @Profile("cloud-prod") + ActuatorSecurityConfig passwordProdAbn() { + return new ActuatorSecurityConfig( + user, environment.getProperty("vcap.services.ha_prometheus_prod.credentials.password")); + } + + @Bean + @ConditionalOnMissingBean + ActuatorSecurityConfig passwordDefault() { + return new ActuatorSecurityConfig( + user, environment.getProperty("ws.monitor.prometheus.password")); + } + // ---------------------------------------------------------------------------------------------------------------------------------- + // endregion + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.requestMatcher( + org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest + .toAnyEndpoint()) + .authorizeRequests() + .requestMatchers( + org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to( + HealthEndpoint.class)) + .permitAll() + .requestMatchers( + org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to( + InfoEndpoint.class)) + .permitAll() + .requestMatchers( + org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to( + LoggersEndpoint.class)) + .hasRole(PROMETHEUS_ROLE) + .requestMatchers( + org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest.to( + PrometheusScrapeEndpoint.class)) + .hasRole(PROMETHEUS_ROLE) + .anyRequest() + .denyAll() + .and() + .httpBasic(); + + http.csrf().ignoringAntMatchers("/actuator/loggers/**"); + } + + @Autowired + protected void configureGlobal( + AuthenticationManagerBuilder auth, ActuatorSecurityConfig securityConfig) throws Exception { + auth.inMemoryAuthentication() + .withUser(securityConfig.getUsername()) + .password(passwordEncoder().encode(securityConfig.getPassword())) + .roles(PROMETHEUS_ROLE); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/MultipleJWTConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/MultipleJWTConfig.java index a90b1a5d..709b6908 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/MultipleJWTConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/MultipleJWTConfig.java @@ -16,7 +16,6 @@ import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.time.Duration; - import org.apache.commons.io.IOUtils; import org.dpppt.backend.sdk.data.DPPPTDataService; import org.dpppt.backend.sdk.data.RedeemDataService; @@ -54,148 +53,150 @@ @Profile(value = "jwt") public class MultipleJWTConfig { - public static class CommonJWTBase extends WebSecurityConfigurerAdapter { - @Value("${ws.app.jwt.publickey}") - String publicKey; - - @Value("${ws.app.jwt.maxValidityMinutes: 60}") - int maxValidityMinutes; - - @Value("${ws.retentiondays: 14}") - int retentionDays; - - @Autowired - @Lazy - DPPPTDataService dataService; - - @Autowired - @Lazy - RedeemDataService redeemDataService; - - protected String loadPublicKey() throws IOException { - if (publicKey.startsWith("keycloak:")) { - String url = publicKey.replace("keycloak:/", ""); - return KeyHelper.getPublicKeyFromKeycloak(url); - } - InputStream in = null; - if (publicKey.startsWith("classpath:/")) { - in = new ClassPathResource(publicKey.substring(11)).getInputStream(); - return readAsStringFromInputStreamAndClose(in); - } else if (publicKey.startsWith("file:/")) { - in = new FileInputStream(publicKey); - return readAsStringFromInputStreamAndClose(in); - } - return publicKey; - } - - private String readAsStringFromInputStreamAndClose(InputStream in) throws IOException { - String result = IOUtils.toString(in); - in.close(); - return result; - } - } - - @Order(1) - public static class WSJWTSecondConfig extends CommonJWTBase { - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() - .antMatcher("/v1/gaen/exposednextday") - .cors() - .and() + public static class CommonJWTBase extends WebSecurityConfigurerAdapter { + @Value("${ws.app.jwt.publickey}") + String publicKey; + + @Value("${ws.app.jwt.maxValidityMinutes: 60}") + int maxValidityMinutes; + + @Value("${ws.retentiondays: 14}") + int retentionDays; + + @Autowired @Lazy DPPPTDataService dataService; + + @Autowired @Lazy RedeemDataService redeemDataService; + + protected String loadPublicKey() throws IOException { + if (publicKey.startsWith("keycloak:")) { + String url = publicKey.replace("keycloak:/", ""); + return KeyHelper.getPublicKeyFromKeycloak(url); + } + InputStream in = null; + if (publicKey.startsWith("classpath:/")) { + in = new ClassPathResource(publicKey.substring(11)).getInputStream(); + return readAsStringFromInputStreamAndClose(in); + } else if (publicKey.startsWith("file:/")) { + in = new FileInputStream(publicKey); + return readAsStringFromInputStreamAndClose(in); + } + return publicKey; + } + + private String readAsStringFromInputStreamAndClose(InputStream in) throws IOException { + String result = IOUtils.toString(in); + in.close(); + return result; + } + } + + @Order(1) + public static class WSJWTSecondConfig extends CommonJWTBase { + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .antMatcher("/v1/gaen/exposednextday") + .cors() + .and() .authorizeRequests() - .antMatchers(HttpMethod.POST, "/v1/gaen/exposednextday") - .authenticated() - .anyRequest() - .permitAll() - .and() + .antMatchers(HttpMethod.POST, "/v1/gaen/exposednextday") + .authenticated() + .anyRequest() + .permitAll() + .and() .oauth2ResourceServer() - .jwt().decoder(jwtDecoderSecondDay()); - // @formatter:on - } - - @Autowired - @Lazy - KeyVault keyVault; - - @Bean - public JWTValidator jwtValidatorGAEN() { - return new JWTValidator(redeemDataService, Duration.ofDays(3)); - } - - @Bean - public JWTClaimSetConverter claimConverterGAEN() { - return new JWTClaimSetConverter(); - } - - @Bean - public JwtDecoder jwtDecoderSecondDay() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException { - - var jwtDecoder = new DPPTJwtDecoder(keyVault.get("nextDayJWT").getPublic()); - // jwtDecoder.setClaimSetConverter(claimConverterGAEN()); - - OAuth2TokenValidator defaultValidators = JwtValidators.createDefault(); - jwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(defaultValidators, jwtValidatorGAEN())); - return jwtDecoder; - } - } - - @Order(2) - public static class WSJWTConfig extends CommonJWTBase { - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() - //.regexMatcher("/v1/(exposed|exposedlist|gaen/exposed)") - .csrf().disable() - .cors() - .and() + .jwt() + .decoder(jwtDecoderSecondDay()); + // @formatter:on + } + + @Autowired @Lazy KeyVault keyVault; + + @Bean + public JWTValidator jwtValidatorGAEN() { + return new JWTValidator(redeemDataService, Duration.ofDays(3)); + } + + @Bean + public JWTClaimSetConverter claimConverterGAEN() { + return new JWTClaimSetConverter(); + } + + @Bean + public JwtDecoder jwtDecoderSecondDay() + throws InvalidKeySpecException, NoSuchAlgorithmException, IOException { + + var jwtDecoder = new DPPTJwtDecoder(keyVault.get("nextDayJWT").getPublic()); + // jwtDecoder.setClaimSetConverter(claimConverterGAEN()); + + OAuth2TokenValidator defaultValidators = JwtValidators.createDefault(); + jwtDecoder.setJwtValidator( + new DelegatingOAuth2TokenValidator<>(defaultValidators, jwtValidatorGAEN())); + return jwtDecoder; + } + } + + @Order(2) + public static class WSJWTConfig extends CommonJWTBase { + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + // .regexMatcher("/v1/(exposed|exposedlist|gaen/exposed)") + .csrf() + .disable() + .cors() + .and() .authorizeRequests() - .antMatchers(HttpMethod.POST, "/v1/exposed", "/v1/exposedlist", "/v1/gaen/exposed") - .authenticated() - .anyRequest() - .permitAll() - .and() + .antMatchers(HttpMethod.POST, "/v1/exposed", "/v1/exposedlist", "/v1/gaen/exposed") + .authenticated() + .anyRequest() + .permitAll() + .and() .oauth2ResourceServer() .jwt(); - // @formatter:on - } - - @Bean - public JWTValidator jwtValidator() { - return new JWTValidator(redeemDataService, Duration.ofMinutes(maxValidityMinutes)); - } - - @Bean - public ValidateRequest requestValidator(ValidationUtils dpptValidationUtils) { - return new JWTValidateRequest(dpptValidationUtils); - } - - @Bean - public ValidateRequest gaenRequestValidator(ValidationUtils gaenValidationUtils) { - return new org.dpppt.backend.sdk.ws.security.gaen.JWTValidateRequest(gaenValidationUtils); - } - - @Bean - public JWTClaimSetConverter claimConverter() { - return new JWTClaimSetConverter(); - } - - @Bean - @Primary - public JwtDecoder jwtDecoder() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, - PublicKeyNoSuitableEncodingFoundException { - DPPTJwtDecoder jwtDecoder = new DPPTJwtDecoder(KeyVault.loadPublicKey(loadPublicKey(), "RSA")); - - OAuth2TokenValidator defaultValidators = JwtValidators.createDefault(); - jwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(defaultValidators, jwtValidator())); - return jwtDecoder; - } - } - -} \ No newline at end of file + // @formatter:on + } + + @Bean + public JWTValidator jwtValidator() { + return new JWTValidator(redeemDataService, Duration.ofMinutes(maxValidityMinutes)); + } + + @Bean + public ValidateRequest requestValidator(ValidationUtils dpptValidationUtils) { + return new JWTValidateRequest(dpptValidationUtils); + } + + @Bean + public ValidateRequest gaenRequestValidator(ValidationUtils gaenValidationUtils) { + return new org.dpppt.backend.sdk.ws.security.gaen.JWTValidateRequest(gaenValidationUtils); + } + + @Bean + public JWTClaimSetConverter claimConverter() { + return new JWTClaimSetConverter(); + } + + @Bean + @Primary + public JwtDecoder jwtDecoder() + throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, + PublicKeyNoSuitableEncodingFoundException { + DPPTJwtDecoder jwtDecoder = + new DPPTJwtDecoder(KeyVault.loadPublicKey(loadPublicKey(), "RSA")); + + OAuth2TokenValidator defaultValidators = JwtValidators.createDefault(); + jwtDecoder.setJwtValidator( + new DelegatingOAuth2TokenValidator<>(defaultValidators, jwtValidator())); + return jwtDecoder; + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/TestingCloudDevConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/TestingCloudDevConfig.java index d648c2b0..209f9889 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/TestingCloudDevConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/TestingCloudDevConfig.java @@ -10,9 +10,7 @@ package org.dpppt.backend.sdk.ws.config; import java.util.Base64; - import javax.sql.DataSource; - import org.flywaydb.core.Flyway; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -21,41 +19,45 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; - @Configuration @Profile("test-cloud") -public class TestingCloudDevConfig extends WSCloudBaseConfig{ - - @Value("${vcap.services.ecdsa_dev.credentials.privateKey}") - private String privateKey; - @Value("${vcap.services.ecdsa_dev.credentials.publicKey}") - public String publicKey; - - @Override - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); - } - @Override - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); - } - - @Bean - DataSource hsqlSource() { - return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build(); - } - - - @Bean - @Override - public Flyway flyway() { - Flyway flyWay = Flyway.configure().dataSource(dataSource()).locations("classpath:/db/migration/hsqldb").load(); - flyWay.migrate(); - return flyWay; - } - - @Override - public String getDbType() { - return "hsqldb"; - } -} \ No newline at end of file +public class TestingCloudDevConfig extends WSCloudBaseConfig { + + @Value("${vcap.services.ecdsa_dev.credentials.privateKey}") + private String privateKey; + + @Value("${vcap.services.ecdsa_dev.credentials.publicKey}") + public String publicKey; + + @Override + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + + @Override + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } + + @Bean + DataSource hsqlSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build(); + } + + @Bean + @Override + public Flyway flyway() { + Flyway flyWay = + Flyway.configure() + .dataSource(dataSource()) + .locations("classpath:/db/migration/hsqldb") + .load(); + flyWay.migrate(); + return flyWay; + } + + @Override + public String getDbType() { + return "hsqldb"; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSBaseConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSBaseConfig.java index f6b6924f..16b7e16b 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSBaseConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSBaseConfig.java @@ -10,21 +10,20 @@ package org.dpppt.backend.sdk.ws.config; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.hubspot.jackson.datatype.protobuf.ProtobufModule; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; import java.security.KeyPair; import java.time.Duration; import java.time.ZoneOffset; import java.util.List; import java.util.Map; import java.util.TimeZone; - import javax.sql.DataSource; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; -import com.hubspot.jackson.datatype.protobuf.ProtobufModule; - import org.dpppt.backend.sdk.data.DPPPTDataService; import org.dpppt.backend.sdk.data.JDBCDPPPTDataServiceImpl; import org.dpppt.backend.sdk.data.JDBCRedeemDataServiceImpl; @@ -36,12 +35,12 @@ import org.dpppt.backend.sdk.ws.controller.GaenController; import org.dpppt.backend.sdk.ws.filter.ResponseWrapperFilter; import org.dpppt.backend.sdk.ws.insertmanager.InsertManager; -import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.NonFakeKeysFilter; -import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.ValidRollingPeriodFilter; -import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.KeysMatchingJWTFilter; import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.Base64Filter; +import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.KeysMatchingJWTFilter; +import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.NonFakeKeysFilter; import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.RollingStartNumberAfterDayAfterTomorrowFilter; import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.RollingStartNumberInRetentionPeriodFilter; +import org.dpppt.backend.sdk.ws.insertmanager.insertionfilters.ValidRollingPeriodFilter; import org.dpppt.backend.sdk.ws.insertmanager.insertionmodifier.IOSLegacyProblemRPLT144Modifier; import org.dpppt.backend.sdk.ws.insertmanager.insertionmodifier.OldAndroid0RPModifier; import org.dpppt.backend.sdk.ws.interceptor.HeaderInjector; @@ -75,265 +74,314 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.security.Keys; - @Configuration @EnableScheduling public abstract class WSBaseConfig implements SchedulingConfigurer, WebMvcConfigurer { - protected final Logger logger = LoggerFactory.getLogger(getClass()); + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + public abstract DataSource dataSource(); + + public abstract Flyway flyway(); + + public abstract String getDbType(); + + @Value( + "#{${ws.security.headers: {'X-Content-Type-Options':'nosniff'," + + " 'X-Frame-Options':'DENY','X-Xss-Protection':'1; mode=block'}}}") + Map additionalHeaders; + + @Value("${ws.exposedlist.cachecontrol: 300000}") + int exposedListCacheControl; + + @Value("${ws.headers.protected:}") + List protectedHeaders; - public abstract DataSource dataSource(); + @Value("${ws.headers.debug: false}") + boolean setDebugHeaders; - public abstract Flyway flyway(); + @Value("${ws.gaen.randomkeysenabled: false}") + boolean randomkeysenabled; - public abstract String getDbType(); + @Value("${ws.gaen.randomkeyamount: 10}") + int randomkeyamount; - @Value("#{${ws.security.headers: {'X-Content-Type-Options':'nosniff', 'X-Frame-Options':'DENY','X-Xss-Protection':'1; mode=block'}}}") - Map additionalHeaders; - - @Value("${ws.exposedlist.cachecontrol: 300000}") - int exposedListCacheControl; - - @Value("${ws.headers.protected:}") - List protectedHeaders; - - @Value("${ws.headers.debug: false}") - boolean setDebugHeaders; - - @Value("${ws.gaen.randomkeysenabled: false}") - boolean randomkeysenabled; - - @Value("${ws.gaen.randomkeyamount: 10}") - int randomkeyamount; - - @Value("${ws.retentiondays: 14}") - int retentionDays; - - @Value("${ws.exposedlist.releaseBucketDuration: 7200000}") - long releaseBucketDuration; - - @Value("${ws.exposedlist.requestTime: 1500}") - long requestTime; - - @Value("${ws.app.source}") - String appSource; - - @Value("${ws.app.gaen.region:ch}") - String gaenRegion; - - @Value("${ws.app.gaen.key_size: 16}") - int gaenKeySizeBytes; - @Value("${ws.app.key_size: 32}") - int keySizeBytes; - - @Value("${ws.app.ios.bundleId:org.dppt.ios.demo}") - String bundleId; - @Value("${ws.app.android.packageName:org.dpppt.android.demo}") - String packageName; - @Value("${ws.app.gaen.keyVersion:v1}") - String keyVersion; - @Value("${ws.app.gaen.keyIdentifier:228}") - String keyIdentifier; - @Value("${ws.app.gaen.algorithm:1.2.840.10045.4.3.2}") - String gaenAlgorithm; - - @Autowired(required = false) - ValidateRequest requestValidator; - - @Autowired(required = false) - ValidateRequest gaenRequestValidator; - - @Autowired - @Lazy - KeyVault keyVault; - - final SignatureAlgorithm algorithm = SignatureAlgorithm.ES256; - - public String getBundleId() { - return this.bundleId; - } - - public String getPackageName() { - return this.packageName; - } - - public String getKeyVersion() { - return this.keyVersion; - } - - public String getKeyIdentifier() { - return this.keyIdentifier; - } - - @Bean - public FakeKeyService fakeKeyService() { - try { - DataSource fakeDataSource = new EmbeddedDatabaseBuilder().generateUniqueName(true) - .setType(EmbeddedDatabaseType.HSQL).build(); - Flyway flyWay = Flyway.configure().dataSource(fakeDataSource).locations("classpath:/db/migration/hsqldb") - .load(); - flyWay.migrate(); - GAENDataService fakeGaenService = new JDBCGAENDataServiceImpl("hsql", fakeDataSource,Duration.ofMillis(releaseBucketDuration)); - return new FakeKeyService(fakeGaenService, Integer.valueOf(randomkeyamount), - Integer.valueOf(gaenKeySizeBytes), Duration.ofDays(retentionDays), randomkeysenabled); - } catch (Exception ex) { - throw new RuntimeException("FakeKeyService could not be instantiated", ex); - } - } - - @Bean - public ProtoSignature gaenSigner() { - try { - return new ProtoSignature(gaenAlgorithm, keyVault.get("gaen"), getBundleId(), getPackageName(), - getKeyVersion(), getKeyIdentifier(), gaenRegion, Duration.ofMillis(releaseBucketDuration)); - } catch (Exception ex) { - throw new RuntimeException("Cannot initialize signer for protobuf"); - } - } - @Bean - public InsertManager insertManager() { - var manager = new InsertManager(gaenDataService(), gaenValidationUtils()); - manager.addFilter(new Base64Filter(gaenValidationUtils())); - manager.addFilter(new KeysMatchingJWTFilter(gaenRequestValidator, gaenValidationUtils())); - manager.addFilter(new RollingStartNumberAfterDayAfterTomorrowFilter()); - manager.addFilter(new RollingStartNumberInRetentionPeriodFilter(gaenValidationUtils())); - manager.addFilter(new NonFakeKeysFilter()); - manager.addFilter(new ValidRollingPeriodFilter()); - return manager; - } - - @ConditionalOnProperty( - value="ws.app.gaen.insertmanager.android0rpmodifier", - havingValue = "true", - matchIfMissing = false) - @Bean public OldAndroid0RPModifier oldAndroid0RPModifier(InsertManager manager){ - var androidModifier = new OldAndroid0RPModifier(); - manager.addModifier(androidModifier); - return androidModifier; - } - - @ConditionalOnProperty( - value="ws.app.gaen.insertmanager.iosrplt144modifier", - havingValue = "true", - matchIfMissing = false) - @Bean public IOSLegacyProblemRPLT144Modifier iosLegacyProblemRPLT144(InsertManager manager){ - var iosModifier = new IOSLegacyProblemRPLT144Modifier(); - manager.addModifier(iosModifier); - return iosModifier; - } - - - @Bean - public DPPPTController dppptSDKController() { - ValidateRequest theValidator = requestValidator; - if (theValidator == null) { - theValidator = new NoValidateRequest(dpptValidationUtils()); - } - return new DPPPTController(dppptSDKDataService(), appSource, exposedListCacheControl, theValidator, - dpptValidationUtils(), releaseBucketDuration, requestTime); - } - - @Bean - public ValidationUtils dpptValidationUtils() { - return new ValidationUtils(keySizeBytes, Duration.ofDays(retentionDays), releaseBucketDuration); - } - - @Bean - public ValidationUtils gaenValidationUtils() { - return new ValidationUtils(gaenKeySizeBytes, Duration.ofDays(retentionDays), releaseBucketDuration); - } - - @Bean - public GaenController gaenController() { - ValidateRequest theValidator = gaenRequestValidator; - if (theValidator == null) { - theValidator = backupValidator(); - } - return new GaenController(insertManager(),gaenDataService(), fakeKeyService(), theValidator, gaenSigner(), - gaenValidationUtils(), Duration.ofMillis(releaseBucketDuration), Duration.ofMillis(requestTime), - Duration.ofMillis(exposedListCacheControl), keyVault.get("nextDayJWT").getPrivate()); - } - - @Bean - ValidateRequest backupValidator() { - return new NoValidateRequest(gaenValidationUtils()); - } - - @Bean - public DPPPTDataService dppptSDKDataService() { - return new JDBCDPPPTDataServiceImpl(getDbType(), dataSource()); - } - - @Bean - public GAENDataService gaenDataService() { - return new JDBCGAENDataServiceImpl(getDbType(), dataSource(), Duration.ofMillis(releaseBucketDuration)); - } - - @Bean - public RedeemDataService redeemDataService() { - return new JDBCRedeemDataServiceImpl(dataSource()); - } - - @Bean - public MappingJackson2HttpMessageConverter converter() { - ObjectMapper mapper = new ObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) - .setSerializationInclusion(JsonInclude.Include.NON_ABSENT) - .registerModules(new ProtobufModule(), new Jdk8Module()); - return new MappingJackson2HttpMessageConverter(mapper); - } - - @Override - public void extendMessageConverters(List> converters) { - converters.add(new ProtobufHttpMessageConverter()); - WebMvcConfigurer.super.extendMessageConverters(converters); - } - - @Bean - public ResponseWrapperFilter hashFilter() { - return new ResponseWrapperFilter(keyVault.get("hashFilter"), retentionDays, protectedHeaders, setDebugHeaders); - } - @Bean - public HeaderInjector securityHeaderInjector(){ - return new HeaderInjector(additionalHeaders); - } - - public KeyPair getKeyPair(SignatureAlgorithm algorithm) { - logger.warn("USING FALLBACK KEYPAIR. WONT'T PERSIST APP RESTART AND PROBABLY DOES NOT HAVE ENOUGH ENTROPY."); - - return Keys.keyPairFor(algorithm); - } - - @Override - public void configureAsyncSupport(AsyncSupportConfigurer configurer) { - configurer.setTaskExecutor(mvcTaskExecutor()); - configurer.setDefaultTimeout(5_000); - } - - @Bean - public ThreadPoolTaskExecutor mvcTaskExecutor() { - ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); - taskExecutor.setThreadNamePrefix("mvc-task-"); - taskExecutor.setMaxPoolSize(1000); - return taskExecutor; - } - - @Override - public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { - taskRegistrar.addFixedRateTask(new IntervalTask(() -> { - logger.info("Start DB cleanup"); - dppptSDKDataService().cleanDB(Duration.ofDays(retentionDays)); - gaenDataService().cleanDB(Duration.ofDays(retentionDays)); - redeemDataService().cleanDB(Duration.ofDays(2)); - logger.info("DB cleanup up"); - }, 60 * 60 * 1000L)); - - var trigger = new CronTrigger("0 0 2 * * *", TimeZone.getTimeZone(ZoneOffset.UTC)); - taskRegistrar.addCronTask(new CronTask(() -> fakeKeyService().updateFakeKeys(), trigger)); - } - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(securityHeaderInjector()); - } + @Value("${ws.retentiondays: 14}") + int retentionDays; + + @Value("${ws.exposedlist.releaseBucketDuration: 7200000}") + long releaseBucketDuration; + + @Value("${ws.exposedlist.requestTime: 1500}") + long requestTime; + + @Value("${ws.app.source}") + String appSource; + + @Value("${ws.app.gaen.region:ch}") + String gaenRegion; + + @Value("${ws.app.gaen.key_size: 16}") + int gaenKeySizeBytes; + + @Value("${ws.app.key_size: 32}") + int keySizeBytes; + + @Value("${ws.app.ios.bundleId:org.dppt.ios.demo}") + String bundleId; + + @Value("${ws.app.android.packageName:org.dpppt.android.demo}") + String packageName; + + @Value("${ws.app.gaen.keyVersion:v1}") + String keyVersion; + + @Value("${ws.app.gaen.keyIdentifier:228}") + String keyIdentifier; + + @Value("${ws.app.gaen.algorithm:1.2.840.10045.4.3.2}") + String gaenAlgorithm; + + @Autowired(required = false) + ValidateRequest requestValidator; + + @Autowired(required = false) + ValidateRequest gaenRequestValidator; + + @Autowired @Lazy KeyVault keyVault; + + final SignatureAlgorithm algorithm = SignatureAlgorithm.ES256; + + public String getBundleId() { + return this.bundleId; + } + + public String getPackageName() { + return this.packageName; + } + + public String getKeyVersion() { + return this.keyVersion; + } + + public String getKeyIdentifier() { + return this.keyIdentifier; + } + + @Bean + public FakeKeyService fakeKeyService() { + try { + DataSource fakeDataSource = + new EmbeddedDatabaseBuilder() + .generateUniqueName(true) + .setType(EmbeddedDatabaseType.HSQL) + .build(); + Flyway flyWay = + Flyway.configure() + .dataSource(fakeDataSource) + .locations("classpath:/db/migration/hsqldb") + .load(); + flyWay.migrate(); + GAENDataService fakeGaenService = + new JDBCGAENDataServiceImpl( + "hsql", fakeDataSource, Duration.ofMillis(releaseBucketDuration)); + return new FakeKeyService( + fakeGaenService, + Integer.valueOf(randomkeyamount), + Integer.valueOf(gaenKeySizeBytes), + Duration.ofDays(retentionDays), + randomkeysenabled); + } catch (Exception ex) { + throw new RuntimeException("FakeKeyService could not be instantiated", ex); + } + } + + @Bean + public ProtoSignature gaenSigner() { + try { + return new ProtoSignature( + gaenAlgorithm, + keyVault.get("gaen"), + getBundleId(), + getPackageName(), + getKeyVersion(), + getKeyIdentifier(), + gaenRegion, + Duration.ofMillis(releaseBucketDuration)); + } catch (Exception ex) { + throw new RuntimeException("Cannot initialize signer for protobuf"); + } + } + + @Bean + public InsertManager insertManager() { + var manager = new InsertManager(gaenDataService(), gaenValidationUtils()); + manager.addFilter(new Base64Filter(gaenValidationUtils())); + manager.addFilter(new KeysMatchingJWTFilter(gaenRequestValidator, gaenValidationUtils())); + manager.addFilter(new RollingStartNumberAfterDayAfterTomorrowFilter()); + manager.addFilter(new RollingStartNumberInRetentionPeriodFilter(gaenValidationUtils())); + manager.addFilter(new NonFakeKeysFilter()); + manager.addFilter(new ValidRollingPeriodFilter()); + return manager; + } + + @ConditionalOnProperty( + value = "ws.app.gaen.insertmanager.android0rpmodifier", + havingValue = "true", + matchIfMissing = false) + @Bean + public OldAndroid0RPModifier oldAndroid0RPModifier(InsertManager manager) { + var androidModifier = new OldAndroid0RPModifier(); + manager.addModifier(androidModifier); + return androidModifier; + } + + @ConditionalOnProperty( + value = "ws.app.gaen.insertmanager.iosrplt144modifier", + havingValue = "true", + matchIfMissing = false) + @Bean + public IOSLegacyProblemRPLT144Modifier iosLegacyProblemRPLT144(InsertManager manager) { + var iosModifier = new IOSLegacyProblemRPLT144Modifier(); + manager.addModifier(iosModifier); + return iosModifier; + } + + @Bean + public DPPPTController dppptSDKController() { + ValidateRequest theValidator = requestValidator; + if (theValidator == null) { + theValidator = new NoValidateRequest(dpptValidationUtils()); + } + return new DPPPTController( + dppptSDKDataService(), + appSource, + exposedListCacheControl, + theValidator, + dpptValidationUtils(), + releaseBucketDuration, + requestTime); + } + + @Bean + public ValidationUtils dpptValidationUtils() { + return new ValidationUtils(keySizeBytes, Duration.ofDays(retentionDays), releaseBucketDuration); + } + + @Bean + public ValidationUtils gaenValidationUtils() { + return new ValidationUtils( + gaenKeySizeBytes, Duration.ofDays(retentionDays), releaseBucketDuration); + } + + @Bean + public GaenController gaenController() { + ValidateRequest theValidator = gaenRequestValidator; + if (theValidator == null) { + theValidator = backupValidator(); + } + return new GaenController( + insertManager(), + gaenDataService(), + fakeKeyService(), + theValidator, + gaenSigner(), + gaenValidationUtils(), + Duration.ofMillis(releaseBucketDuration), + Duration.ofMillis(requestTime), + Duration.ofMillis(exposedListCacheControl), + keyVault.get("nextDayJWT").getPrivate()); + } + + @Bean + ValidateRequest backupValidator() { + return new NoValidateRequest(gaenValidationUtils()); + } + + @Bean + public DPPPTDataService dppptSDKDataService() { + return new JDBCDPPPTDataServiceImpl(getDbType(), dataSource()); + } + + @Bean + public GAENDataService gaenDataService() { + return new JDBCGAENDataServiceImpl( + getDbType(), dataSource(), Duration.ofMillis(releaseBucketDuration)); + } + + @Bean + public RedeemDataService redeemDataService() { + return new JDBCRedeemDataServiceImpl(dataSource()); + } + + @Bean + public MappingJackson2HttpMessageConverter converter() { + ObjectMapper mapper = + new ObjectMapper() + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .setSerializationInclusion(JsonInclude.Include.NON_ABSENT) + .registerModules(new ProtobufModule(), new Jdk8Module()); + return new MappingJackson2HttpMessageConverter(mapper); + } + + @Override + public void extendMessageConverters(List> converters) { + converters.add(new ProtobufHttpMessageConverter()); + WebMvcConfigurer.super.extendMessageConverters(converters); + } + + @Bean + public ResponseWrapperFilter hashFilter() { + return new ResponseWrapperFilter( + keyVault.get("hashFilter"), retentionDays, protectedHeaders, setDebugHeaders); + } + + @Bean + public HeaderInjector securityHeaderInjector() { + return new HeaderInjector(additionalHeaders); + } + + public KeyPair getKeyPair(SignatureAlgorithm algorithm) { + logger.warn( + "USING FALLBACK KEYPAIR. WONT'T PERSIST APP RESTART AND PROBABLY DOES NOT HAVE ENOUGH" + + " ENTROPY."); + + return Keys.keyPairFor(algorithm); + } + + @Override + public void configureAsyncSupport(AsyncSupportConfigurer configurer) { + configurer.setTaskExecutor(mvcTaskExecutor()); + configurer.setDefaultTimeout(5_000); + } + + @Bean + public ThreadPoolTaskExecutor mvcTaskExecutor() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setThreadNamePrefix("mvc-task-"); + taskExecutor.setMaxPoolSize(1000); + return taskExecutor; + } + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.addFixedRateTask( + new IntervalTask( + () -> { + logger.info("Start DB cleanup"); + dppptSDKDataService().cleanDB(Duration.ofDays(retentionDays)); + gaenDataService().cleanDB(Duration.ofDays(retentionDays)); + redeemDataService().cleanDB(Duration.ofDays(2)); + logger.info("DB cleanup up"); + }, + 60 * 60 * 1000L)); + + var trigger = new CronTrigger("0 0 2 * * *", TimeZone.getTimeZone(ZoneOffset.UTC)); + taskRegistrar.addCronTask(new CronTask(() -> fakeKeyService().updateFakeKeys(), trigger)); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(securityHeaderInjector()); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudAbnConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudAbnConfig.java index bed17677..faf9d9fc 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudAbnConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudAbnConfig.java @@ -11,7 +11,6 @@ package org.dpppt.backend.sdk.ws.config; import java.util.Base64; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -19,27 +18,29 @@ @Configuration @Profile("cloud-abn") public class WSCloudAbnConfig extends WSCloudBaseConfig { - @Value("${vcap.services.ecdsa_abn.credentials.privateKey}") - private String privateKey; - @Value("${vcap.services.ecdsa_abn.credentials.publicKey}") - public String publicKey; - - @Override - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); - } - @Override - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); - } - - @Override - public String getBundleId() { - return "ch.admin.bag.dp3t.abn"; - } - - @Override - public String getPackageName() { - return "ch.admin.bag.dp3t"; - } -} \ No newline at end of file + @Value("${vcap.services.ecdsa_abn.credentials.privateKey}") + private String privateKey; + + @Value("${vcap.services.ecdsa_abn.credentials.publicKey}") + public String publicKey; + + @Override + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + + @Override + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } + + @Override + public String getBundleId() { + return "ch.admin.bag.dp3t.abn"; + } + + @Override + public String getPackageName() { + return "ch.admin.bag.dp3t"; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudBaseConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudBaseConfig.java index dc54d88e..b5f0e263 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudBaseConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudBaseConfig.java @@ -11,7 +11,6 @@ package org.dpppt.backend.sdk.ws.config; import javax.sql.DataSource; - import org.dpppt.backend.sdk.ws.security.KeyVault; import org.dpppt.backend.sdk.ws.security.KeyVault.PrivateKeyNoSuitableEncodingFoundException; import org.dpppt.backend.sdk.ws.security.KeyVault.PublicKeyNoSuitableEncodingFoundException; @@ -25,58 +24,61 @@ @Configuration public abstract class WSCloudBaseConfig extends WSBaseConfig { - @Autowired - @Lazy - private DataSource dataSource; + @Autowired @Lazy private DataSource dataSource; - abstract String getPublicKey(); + abstract String getPublicKey(); - abstract String getPrivateKey(); + abstract String getPrivateKey(); - @Value("${ws.cloud.base.config.publicKey.fromCertificate:true}") - private boolean publicKeyFromCertificate; + @Value("${ws.cloud.base.config.publicKey.fromCertificate:true}") + private boolean publicKeyFromCertificate; - @Override - public DataSource dataSource() { - return dataSource; - } + @Override + public DataSource dataSource() { + return dataSource; + } - @Bean - @Override - public Flyway flyway() { - Flyway flyWay = Flyway.configure().dataSource(dataSource()).locations("classpath:/db/migration/pgsql_cluster") - .load(); - flyWay.migrate(); - return flyWay; + @Bean + @Override + public Flyway flyway() { + Flyway flyWay = + Flyway.configure() + .dataSource(dataSource()) + .locations("classpath:/db/migration/pgsql_cluster") + .load(); + flyWay.migrate(); + return flyWay; + } - } + @Override + public String getDbType() { + return "pgsql"; + } - @Override - public String getDbType() { - return "pgsql"; - } + @Bean + protected KeyVault keyVault() { + var privateKey = getPrivateKey(); + var publicKey = getPublicKey(); - @Bean - protected KeyVault keyVault() { - var privateKey = getPrivateKey(); - var publicKey = getPublicKey(); - - if(privateKey.isEmpty() || publicKey.isEmpty()) { - var kp = super.getKeyPair(algorithm); - var gaenKp = new KeyVault.KeyVaultKeyPair("gaen", kp); - var nextDayJWTKp = new KeyVault.KeyVaultKeyPair("nextDayJWT", kp); - var hashFilterKp = new KeyVault.KeyVaultKeyPair("hashFilter", kp); - return new KeyVault(gaenKp, nextDayJWTKp, hashFilterKp); - } + if (privateKey.isEmpty() || publicKey.isEmpty()) { + var kp = super.getKeyPair(algorithm); + var gaenKp = new KeyVault.KeyVaultKeyPair("gaen", kp); + var nextDayJWTKp = new KeyVault.KeyVaultKeyPair("nextDayJWT", kp); + var hashFilterKp = new KeyVault.KeyVaultKeyPair("hashFilter", kp); + return new KeyVault(gaenKp, nextDayJWTKp, hashFilterKp); + } - var gaen = new KeyVault.KeyVaultEntry("gaen", getPrivateKey(), getPublicKey(), "EC"); - var nextDayJWT = new KeyVault.KeyVaultEntry("nextDayJWT", getPrivateKey(), getPublicKey(), "EC"); - var hashFilter = new KeyVault.KeyVaultEntry("hashFilter", getPrivateKey(), getPublicKey(), "EC"); + var gaen = new KeyVault.KeyVaultEntry("gaen", getPrivateKey(), getPublicKey(), "EC"); + var nextDayJWT = + new KeyVault.KeyVaultEntry("nextDayJWT", getPrivateKey(), getPublicKey(), "EC"); + var hashFilter = + new KeyVault.KeyVaultEntry("hashFilter", getPrivateKey(), getPublicKey(), "EC"); - try { - return new KeyVault(gaen, nextDayJWT, hashFilter); - } catch (PrivateKeyNoSuitableEncodingFoundException | PublicKeyNoSuitableEncodingFoundException e) { - throw new RuntimeException(e); - } - } + try { + return new KeyVault(gaen, nextDayJWT, hashFilter); + } catch (PrivateKeyNoSuitableEncodingFoundException + | PublicKeyNoSuitableEncodingFoundException e) { + throw new RuntimeException(e); + } + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudDevConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudDevConfig.java index 5a7081fe..9d15c45e 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudDevConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudDevConfig.java @@ -11,7 +11,6 @@ package org.dpppt.backend.sdk.ws.config; import java.util.Base64; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -19,27 +18,29 @@ @Configuration @Profile("cloud-dev") public class WSCloudDevConfig extends WSCloudBaseConfig { - @Value("${vcap.services.ecdsa_dev.credentials.privateKey}") - private String privateKey; - @Value("${vcap.services.ecdsa_dev.credentials.publicKey}") - public String publicKey; - - @Override - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); - } - @Override - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); - } - - @Override - public String getBundleId() { - return "ch.admin.bag.dp3t.dev"; - } - - @Override - public String getPackageName() { - return "ch.admin.bag.dp3t"; - } -} \ No newline at end of file + @Value("${vcap.services.ecdsa_dev.credentials.privateKey}") + private String privateKey; + + @Value("${vcap.services.ecdsa_dev.credentials.publicKey}") + public String publicKey; + + @Override + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + + @Override + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } + + @Override + public String getBundleId() { + return "ch.admin.bag.dp3t.dev"; + } + + @Override + public String getPackageName() { + return "ch.admin.bag.dp3t"; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudProdConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudProdConfig.java index f601755a..2594eb80 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudProdConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudProdConfig.java @@ -11,7 +11,6 @@ package org.dpppt.backend.sdk.ws.config; import java.util.Base64; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -19,27 +18,29 @@ @Configuration @Profile("cloud-prod") public class WSCloudProdConfig extends WSCloudBaseConfig { - @Value("${vcap.services.ecdsa_prod.credentials.privateKey}") - private String privateKey; - @Value("${vcap.services.ecdsa_prod.credentials.publicKey}") - public String publicKey; - - @Override - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); - } - @Override - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); - } - - @Override - public String getBundleId() { - return "ch.admin.bag.dp3t"; - } - - @Override - public String getPackageName() { - return "ch.admin.bag.dp3t"; - } -} \ No newline at end of file + @Value("${vcap.services.ecdsa_prod.credentials.privateKey}") + private String privateKey; + + @Value("${vcap.services.ecdsa_prod.credentials.publicKey}") + public String publicKey; + + @Override + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + + @Override + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } + + @Override + public String getBundleId() { + return "ch.admin.bag.dp3t"; + } + + @Override + public String getPackageName() { + return "ch.admin.bag.dp3t"; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudTestConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudTestConfig.java index 1fa231cd..4a3378ae 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudTestConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSCloudTestConfig.java @@ -11,7 +11,6 @@ package org.dpppt.backend.sdk.ws.config; import java.util.Base64; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -19,27 +18,29 @@ @Configuration @Profile("cloud-test") public class WSCloudTestConfig extends WSCloudBaseConfig { - @Value("${vcap.services.ecdsa_test.credentials.privateKey}") - private String privateKey; - @Value("${vcap.services.ecdsa_test.credentials.publicKey}") - public String publicKey; - - @Override - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); - } - @Override - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); - } - - @Override - public String getBundleId() { - return "ch.admin.bag.dp3t.test"; - } - - @Override - public String getPackageName() { - return "ch.admin.bag.dp3t"; - } -} \ No newline at end of file + @Value("${vcap.services.ecdsa_test.credentials.privateKey}") + private String privateKey; + + @Value("${vcap.services.ecdsa_test.credentials.publicKey}") + public String publicKey; + + @Override + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + + @Override + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } + + @Override + public String getBundleId() { + return "ch.admin.bag.dp3t.test"; + } + + @Override + public String getPackageName() { + return "ch.admin.bag.dp3t"; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSDevConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSDevConfig.java index c66434a9..8702637a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSDevConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSDevConfig.java @@ -11,9 +11,7 @@ package org.dpppt.backend.sdk.ws.config; import java.util.Base64; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.ws.security.KeyVault; import org.dpppt.backend.sdk.ws.security.KeyVault.PrivateKeyNoSuitableEncodingFoundException; import org.dpppt.backend.sdk.ws.security.KeyVault.PublicKeyNoSuitableEncodingFoundException; @@ -29,64 +27,70 @@ @Profile("dev") public class WSDevConfig extends WSBaseConfig { - - @Value("${ws.ecdsa.credentials.privateKey:}") - private String privateKey; - - @Value("${ws.ecdsa.credentials.publicKey:}") - public String publicKey; + @Value("${ws.ecdsa.credentials.privateKey:}") + private String privateKey; - @Bean - @Override - public DataSource dataSource() { - return new EmbeddedDatabaseBuilder().generateUniqueName(true).setType(EmbeddedDatabaseType.HSQL).build(); - } + @Value("${ws.ecdsa.credentials.publicKey:}") + public String publicKey; - @Bean - @Override - public Flyway flyway() { - Flyway flyWay = Flyway.configure().dataSource(dataSource()).locations("classpath:/db/migration/hsqldb").load(); - flyWay.migrate(); - return flyWay; - } + @Bean + @Override + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .generateUniqueName(true) + .setType(EmbeddedDatabaseType.HSQL) + .build(); + } - @Override - public String getDbType() { - return "hsqldb"; - } + @Bean + @Override + public Flyway flyway() { + Flyway flyWay = + Flyway.configure() + .dataSource(dataSource()) + .locations("classpath:/db/migration/hsqldb") + .load(); + flyWay.migrate(); + return flyWay; + } - @Bean - KeyVault keyVault() { - var privateKey = getPrivateKey(); - var publicKey = getPublicKey(); - - if(privateKey.isEmpty() || publicKey.isEmpty()) { - var kp = super.getKeyPair(algorithm); - var gaenKp = new KeyVault.KeyVaultKeyPair("gaen", kp); - var nextDayJWTKp = new KeyVault.KeyVaultKeyPair("nextDayJWT", kp); - var hashFilterKp = new KeyVault.KeyVaultKeyPair("hashFilter", kp); - return new KeyVault(gaenKp, nextDayJWTKp, hashFilterKp); - } - else { - var gaen = new KeyVault.KeyVaultEntry("gaen", getPrivateKey(), getPublicKey(), "EC"); - var nextDayJWT = new KeyVault.KeyVaultEntry("nextDayJWT", getPrivateKey(), getPublicKey(), "EC"); - var hashFilter = new KeyVault.KeyVaultEntry("hashFilter", getPrivateKey(), getPublicKey(), "EC"); + @Override + public String getDbType() { + return "hsqldb"; + } - try { - return new KeyVault(gaen, nextDayJWT, hashFilter); - } catch (PrivateKeyNoSuitableEncodingFoundException | PublicKeyNoSuitableEncodingFoundException e) { - throw new RuntimeException(e); - } - } - } + @Bean + KeyVault keyVault() { + var privateKey = getPrivateKey(); + var publicKey = getPublicKey(); - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); - } + if (privateKey.isEmpty() || publicKey.isEmpty()) { + var kp = super.getKeyPair(algorithm); + var gaenKp = new KeyVault.KeyVaultKeyPair("gaen", kp); + var nextDayJWTKp = new KeyVault.KeyVaultKeyPair("nextDayJWT", kp); + var hashFilterKp = new KeyVault.KeyVaultKeyPair("hashFilter", kp); + return new KeyVault(gaenKp, nextDayJWTKp, hashFilterKp); + } else { + var gaen = new KeyVault.KeyVaultEntry("gaen", getPrivateKey(), getPublicKey(), "EC"); + var nextDayJWT = + new KeyVault.KeyVaultEntry("nextDayJWT", getPrivateKey(), getPublicKey(), "EC"); + var hashFilter = + new KeyVault.KeyVaultEntry("hashFilter", getPrivateKey(), getPublicKey(), "EC"); - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); + try { + return new KeyVault(gaen, nextDayJWT, hashFilter); + } catch (PrivateKeyNoSuitableEncodingFoundException + | PublicKeyNoSuitableEncodingFoundException e) { + throw new RuntimeException(e); + } } + } + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSProdConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSProdConfig.java index cceb9fcd..5c26c763 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSProdConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/WSProdConfig.java @@ -10,13 +10,13 @@ package org.dpppt.backend.sdk.ws.config; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import java.time.Duration; import java.util.Arrays; import java.util.Base64; import java.util.Properties; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.data.gaen.DebugGAENDataService; import org.dpppt.backend.sdk.data.gaen.DebugJDBCGAENDataServiceImpl; import org.dpppt.backend.sdk.ws.controller.DebugController; @@ -34,152 +34,156 @@ import org.springframework.context.annotation.Profile; import org.springframework.core.env.Environment; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; - @Configuration @Profile("prod") public class WSProdConfig extends WSBaseConfig { - - @Value("${datasource.username}") - String dataSourceUser; - - @Value("${datasource.password}") - String dataSourcePassword; - - @Value("${datasource.url}") - String dataSourceUrl; - - @Value("${datasource.driverClassName}") - String dataSourceDriver; - - @Value("${datasource.failFast}") - String dataSourceFailFast; - - @Value("${datasource.maximumPoolSize}") - String dataSourceMaximumPoolSize; - - @Value("${datasource.maxLifetime}") - String dataSourceMaxLifetime; - - @Value("${datasource.idleTimeout}") - String dataSourceIdleTimeout; - - @Value("${datasource.connectionTimeout}") - String dataSourceConnectionTimeout; - - @Value("${ws.ecdsa.credentials.privateKey:}") - private String privateKey; - - @Value("${ws.ecdsa.credentials.publicKey:}") - public String publicKey; - - @Bean(destroyMethod = "close") - public DataSource dataSource() { - HikariConfig config = new HikariConfig(); - Properties props = new Properties(); - props.put("url", dataSourceUrl); - props.put("user", dataSourceUser); - props.put("password", dataSourcePassword); - config.setDataSourceProperties(props); - config.setDataSourceClassName(dataSourceDriver); - config.setMaximumPoolSize(Integer.parseInt(dataSourceMaximumPoolSize)); - config.setMaxLifetime(Integer.parseInt(dataSourceMaxLifetime)); - config.setIdleTimeout(Integer.parseInt(dataSourceIdleTimeout)); - config.setConnectionTimeout(Integer.parseInt(dataSourceConnectionTimeout)); - return new HikariDataSource(config); - } - - @Bean - @Override - public Flyway flyway() { - Flyway flyWay = Flyway.configure().dataSource(dataSource()).locations("classpath:/db/migration/pgsql").load(); - flyWay.migrate(); - return flyWay; - } - - @Override - public String getDbType() { - return "pgsql"; - } - - @Bean - KeyVault keyVault() { - var privateKey = getPrivateKey(); - var publicKey = getPublicKey(); - - if(privateKey.isEmpty() || publicKey.isEmpty()) { - var kp = super.getKeyPair(algorithm); - var gaenKp = new KeyVault.KeyVaultKeyPair("gaen", kp); - var nextDayJWTKp = new KeyVault.KeyVaultKeyPair("nextDayJWT", kp); - var hashFilterKp = new KeyVault.KeyVaultKeyPair("hashFilter", kp); - return new KeyVault(gaenKp, nextDayJWTKp, hashFilterKp); - } - - var gaen = new KeyVault.KeyVaultEntry("gaen", getPrivateKey(), getPublicKey(), "EC"); - var nextDayJWT = new KeyVault.KeyVaultEntry("nextDayJWT", getPrivateKey(), getPublicKey(), "EC"); - var hashFilter = new KeyVault.KeyVaultEntry("hashFilter", getPrivateKey(), getPublicKey(), "EC"); - - try { - return new KeyVault(gaen, nextDayJWT, hashFilter); - } catch (PrivateKeyNoSuitableEncodingFoundException | PublicKeyNoSuitableEncodingFoundException e) { - throw new RuntimeException(e); - } - } - - String getPrivateKey() { - return new String(Base64.getDecoder().decode(privateKey)); + + @Value("${datasource.username}") + String dataSourceUser; + + @Value("${datasource.password}") + String dataSourcePassword; + + @Value("${datasource.url}") + String dataSourceUrl; + + @Value("${datasource.driverClassName}") + String dataSourceDriver; + + @Value("${datasource.failFast}") + String dataSourceFailFast; + + @Value("${datasource.maximumPoolSize}") + String dataSourceMaximumPoolSize; + + @Value("${datasource.maxLifetime}") + String dataSourceMaxLifetime; + + @Value("${datasource.idleTimeout}") + String dataSourceIdleTimeout; + + @Value("${datasource.connectionTimeout}") + String dataSourceConnectionTimeout; + + @Value("${ws.ecdsa.credentials.privateKey:}") + private String privateKey; + + @Value("${ws.ecdsa.credentials.publicKey:}") + public String publicKey; + + @Bean(destroyMethod = "close") + public DataSource dataSource() { + HikariConfig config = new HikariConfig(); + Properties props = new Properties(); + props.put("url", dataSourceUrl); + props.put("user", dataSourceUser); + props.put("password", dataSourcePassword); + config.setDataSourceProperties(props); + config.setDataSourceClassName(dataSourceDriver); + config.setMaximumPoolSize(Integer.parseInt(dataSourceMaximumPoolSize)); + config.setMaxLifetime(Integer.parseInt(dataSourceMaxLifetime)); + config.setIdleTimeout(Integer.parseInt(dataSourceIdleTimeout)); + config.setConnectionTimeout(Integer.parseInt(dataSourceConnectionTimeout)); + return new HikariDataSource(config); + } + + @Bean + @Override + public Flyway flyway() { + Flyway flyWay = + Flyway.configure() + .dataSource(dataSource()) + .locations("classpath:/db/migration/pgsql") + .load(); + flyWay.migrate(); + return flyWay; + } + + @Override + public String getDbType() { + return "pgsql"; + } + + @Bean + KeyVault keyVault() { + var privateKey = getPrivateKey(); + var publicKey = getPublicKey(); + + if (privateKey.isEmpty() || publicKey.isEmpty()) { + var kp = super.getKeyPair(algorithm); + var gaenKp = new KeyVault.KeyVaultKeyPair("gaen", kp); + var nextDayJWTKp = new KeyVault.KeyVaultKeyPair("nextDayJWT", kp); + var hashFilterKp = new KeyVault.KeyVaultKeyPair("hashFilter", kp); + return new KeyVault(gaenKp, nextDayJWTKp, hashFilterKp); } - String getPublicKey() { - return new String(Base64.getDecoder().decode(publicKey)); - } - - @Profile("debug") - @Configuration - public static class DebugConfig { - @Value("${ws.exposedlist.debug.releaseBucketDuration: 86400000}") - long releaseBucketDuration; - - @Value("${ws.exposedlist.debug.requestTime: 1500}") - long requestTime; - - @Autowired - KeyVault keyVault; - @Autowired - Flyway flyway; - @Autowired - DataSource dataSource; - @Autowired - ProtoSignature gaenSigner; - @Autowired - ValidateRequest backupValidator; - @Autowired - ValidationUtils gaenValidationUtils; - @Autowired - Environment env; - - protected boolean isProd() { - return Arrays.asList(env.getActiveProfiles()).contains("prod"); - } - protected boolean isDev() { - return Arrays.asList(env.getActiveProfiles()).contains("dev"); - } - - @Bean - DebugGAENDataService dataService() { - String dbType = ""; - if(isProd()) { - dbType = "pgsql"; - } else if(isDev()) { - dbType = "hsqldb"; - } - return new DebugJDBCGAENDataServiceImpl(dbType, dataSource); - } - @Bean - DebugController debugController() { - return new DebugController(dataService(),gaenSigner,backupValidator, gaenValidationUtils,Duration.ofMillis(releaseBucketDuration), Duration.ofMillis(requestTime)); - } - } + var gaen = new KeyVault.KeyVaultEntry("gaen", getPrivateKey(), getPublicKey(), "EC"); + var nextDayJWT = + new KeyVault.KeyVaultEntry("nextDayJWT", getPrivateKey(), getPublicKey(), "EC"); + var hashFilter = + new KeyVault.KeyVaultEntry("hashFilter", getPrivateKey(), getPublicKey(), "EC"); + + try { + return new KeyVault(gaen, nextDayJWT, hashFilter); + } catch (PrivateKeyNoSuitableEncodingFoundException + | PublicKeyNoSuitableEncodingFoundException e) { + throw new RuntimeException(e); + } + } + + String getPrivateKey() { + return new String(Base64.getDecoder().decode(privateKey)); + } + + String getPublicKey() { + return new String(Base64.getDecoder().decode(publicKey)); + } + + @Profile("debug") + @Configuration + public static class DebugConfig { + @Value("${ws.exposedlist.debug.releaseBucketDuration: 86400000}") + long releaseBucketDuration; + + @Value("${ws.exposedlist.debug.requestTime: 1500}") + long requestTime; + + @Autowired KeyVault keyVault; + @Autowired Flyway flyway; + @Autowired DataSource dataSource; + @Autowired ProtoSignature gaenSigner; + @Autowired ValidateRequest backupValidator; + @Autowired ValidationUtils gaenValidationUtils; + @Autowired Environment env; + + protected boolean isProd() { + return Arrays.asList(env.getActiveProfiles()).contains("prod"); + } + + protected boolean isDev() { + return Arrays.asList(env.getActiveProfiles()).contains("dev"); + } + @Bean + DebugGAENDataService dataService() { + String dbType = ""; + if (isProd()) { + dbType = "pgsql"; + } else if (isDev()) { + dbType = "hsqldb"; + } + return new DebugJDBCGAENDataServiceImpl(dbType, dataSource); + } + + @Bean + DebugController debugController() { + return new DebugController( + dataService(), + gaenSigner, + backupValidator, + gaenValidationUtils, + Duration.ofMillis(releaseBucketDuration), + Duration.ofMillis(requestTime)); + } + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/configbeans/ActuatorSecurityConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/configbeans/ActuatorSecurityConfig.java index d29580b5..b8bd4eab 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/configbeans/ActuatorSecurityConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/config/configbeans/ActuatorSecurityConfig.java @@ -1,19 +1,19 @@ package org.dpppt.backend.sdk.ws.config.configbeans; public class ActuatorSecurityConfig { - private final String username; - private final String password; + private final String username; + private final String password; - public String getUsername() { - return username; - } + public String getUsername() { + return username; + } - public String getPassword() { - return password; - } + public String getPassword() { + return password; + } - public ActuatorSecurityConfig(String username, String password) { - this.username = username; - this.password = password; - } -} \ No newline at end of file + public ActuatorSecurityConfig(String username, String password) { + this.username = username; + this.password = password; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DPPPTController.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DPPPTController.java index c5096a13..ea85aea9 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DPPPTController.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DPPPTController.java @@ -10,15 +10,15 @@ package org.dpppt.backend.sdk.ws.controller; +import ch.ubique.openapi.docannotations.Documentation; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.protobuf.ByteString; import java.time.Duration; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Base64; import java.util.List; - import javax.validation.Valid; - -import com.fasterxml.jackson.core.JsonProcessingException; import org.dpppt.backend.sdk.data.DPPPTDataService; import org.dpppt.backend.sdk.model.BucketList; import org.dpppt.backend.sdk.model.ExposedOverview; @@ -26,11 +26,11 @@ import org.dpppt.backend.sdk.model.ExposeeRequest; import org.dpppt.backend.sdk.model.ExposeeRequestList; import org.dpppt.backend.sdk.model.proto.Exposed; +import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.security.ValidateRequest; import org.dpppt.backend.sdk.ws.security.ValidateRequest.ClaimIsBeforeOnsetException; import org.dpppt.backend.sdk.ws.security.ValidateRequest.InvalidDateException; import org.dpppt.backend.sdk.ws.security.ValidateRequest.WrongScopeException; -import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.util.ValidationUtils; import org.dpppt.backend.sdk.ws.util.ValidationUtils.BadBatchReleaseTimeException; import org.springframework.http.CacheControl; @@ -51,219 +51,282 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.WebRequest; -import ch.ubique.openapi.docannotations.Documentation; - -import com.google.protobuf.ByteString; - @Controller @RequestMapping("/v1") public class DPPPTController { - private final DPPPTDataService dataService; - private final String appSource; - private final int exposedListCacheControl; - private final ValidateRequest validateRequest; - private final ValidationUtils validationUtils; - // time in milliseconds that exposed keys are hidden before being served, in order to prevent timing attacks - private final long releaseBucketDuration; - private final long requestTime; - - - public DPPPTController(DPPPTDataService dataService, String appSource, - int exposedListCacheControl, ValidateRequest validateRequest, ValidationUtils validationUtils, long releaseBucketDuration, - long requestTime) { - this.dataService = dataService; - this.appSource = appSource; - this.exposedListCacheControl = exposedListCacheControl/1000/60; - this.validateRequest = validateRequest; - this.validationUtils = validationUtils; - this.releaseBucketDuration = releaseBucketDuration; - this.requestTime = requestTime; - } - - @CrossOrigin(origins = { "https://editor.swagger.io" }) - @GetMapping(value = "") - @Documentation(description = "Hello return", responses = {"200=>server live"}) - public @ResponseBody ResponseEntity hello() { - return ResponseEntity.ok().header("X-HELLO", "dp3t").body("Hello from DP3T WS"); - } - - @CrossOrigin(origins = { "https://editor.swagger.io" }) - @PostMapping(value = "/exposed") - @Documentation( - description = "Send exposed key to server", - responses = { - "200=>The exposed keys have been stored in the database", - "400=>Invalid base64 encoding in expose request", - "403=>Authentication failed" - }) - public @ResponseBody ResponseEntity addExposee(@Valid @RequestBody - @Documentation(description = "The ExposeeRequest contains the SecretKey from the guessed infection date, the infection date itself, and some authentication data to verify the test result") - ExposeeRequest exposeeRequest, - @RequestHeader(value = "User-Agent", required = true) - @Documentation(description = "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS) + OS-Version", example = "ch.ubique.android.starsdk;1.0;iOS;13.3") - String userAgent, - @AuthenticationPrincipal Object principal) throws InvalidDateException, WrongScopeException, ClaimIsBeforeOnsetException { - var now = UTCInstant.now(); - - if (!this.validateRequest.isValid(principal)) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); - } - if (!validationUtils.isValidBase64Key(exposeeRequest.getKey())) { - return new ResponseEntity<>("No valid base64 key", HttpStatus.BAD_REQUEST); - } - // TODO: should we give that information? - Exposee exposee = new Exposee(); - exposee.setKey(exposeeRequest.getKey()); - long keyDate = this.validateRequest.validateKeyDate(now, principal, exposeeRequest); - - exposee.setKeyDate(keyDate); - if (!this.validateRequest.isFakeRequest(principal, exposeeRequest)) { - dataService.upsertExposee(exposee, appSource); - } - - long after = System.currentTimeMillis(); - long duration = after - now.getTimestamp(); - try { - Thread.sleep(Math.max(this.requestTime - duration, 0)); - } catch (Exception ex) { - - } - return ResponseEntity.ok().build(); - } - - @CrossOrigin(origins = { "https://editor.swagger.io" }) - @PostMapping(value = "/exposedlist") - @Documentation(description = "Send a list of exposed keys to server", - responses = { - "200=>The exposed keys have been stored in the database", - "400=>Invalid base64 encoding in exposee request", - "403=>Authentication failed"}) - public @ResponseBody ResponseEntity addExposee(@Valid @RequestBody - @Documentation(description = "The ExposeeRequest contains the SecretKey from the guessed infection date, the infection date itself, and some authentication data to verify the test result") - ExposeeRequestList exposeeRequests, - @RequestHeader(value = "User-Agent", required = true) - @Documentation(description = "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS) + OS-Version", example = "ch.ubique.android.starsdk;1.0;iOS;13.3") - String userAgent, - @AuthenticationPrincipal Object principal) throws InvalidDateException, WrongScopeException, ClaimIsBeforeOnsetException { - var now = UTCInstant.now(); - - if (!this.validateRequest.isValid(principal)) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); - } - - List exposees = new ArrayList<>(); - for (var exposedKey : exposeeRequests.getExposedKeys()) { - if (!validationUtils.isValidBase64Key(exposedKey.getKey())) { - return new ResponseEntity<>("No valid base64 key", HttpStatus.BAD_REQUEST); - } - - Exposee exposee = new Exposee(); - exposee.setKey(exposedKey.getKey()); - long keyDate = this.validateRequest.validateKeyDate(now, principal, exposedKey); - - exposee.setKeyDate(keyDate); - exposees.add(exposee); - } - - if (!this.validateRequest.isFakeRequest(principal, exposeeRequests)) { - dataService.upsertExposees(exposees, appSource); - } - - long after = System.currentTimeMillis(); - long duration = after - now.getTimestamp(); - try { - Thread.sleep(Math.max(this.requestTime - duration, 0)); - } catch (Exception ex) { - - } - return ResponseEntity.ok().build(); - } - - @CrossOrigin(origins = { "https://editor.swagger.io" }) - @GetMapping(value = "/exposedjson/{batchReleaseTime}", produces = "application/json") - @Documentation(description = "Query list of exposed keys from a specific batch release time", - responses = { - "200=>Returns ExposedOverview in json format, which includes all exposed keys which were published on _batchReleaseTime_", - "404=>Couldn't find _batchReleaseTime_" - }) - public @ResponseBody ResponseEntity getExposedByDayDate(@PathVariable - @Documentation(description = "The batch release date of the exposed keys in milliseconds since Unix Epoch (1970-01-01), must be a multiple of 2 * 60 * 60 * 1000", - example = "1593043200000") - long batchReleaseTime, - WebRequest request) throws BadBatchReleaseTimeException{ - var now = UTCInstant.now(); - if(!validationUtils.isValidBatchReleaseTime(UTCInstant.ofEpochMillis(batchReleaseTime), now)) { - return ResponseEntity.notFound().build(); - } - - List exposeeList = dataService.getSortedExposedForBatchReleaseTime(batchReleaseTime, releaseBucketDuration); - ExposedOverview overview = new ExposedOverview(exposeeList); - overview.setBatchReleaseTime(batchReleaseTime); - return ResponseEntity.ok().cacheControl(CacheControl.maxAge(Duration.ofMinutes(exposedListCacheControl))) - .header("X-BATCH-RELEASE-TIME", Long.toString(batchReleaseTime)).body(overview); - } - - @CrossOrigin(origins = { "https://editor.swagger.io" }) - @GetMapping(value = "/exposed/{batchReleaseTime}", produces = "application/x-protobuf") - @Documentation(description = "Query list of exposed keys from a specific batch release time", - responses = { - "200=>Returns ExposedOverview in protobuf format, which includes all exposed keys which were published on _batchReleaseTime_", - "404=>Couldn't find _batchReleaseTime_" - }) - public @ResponseBody ResponseEntity getExposedByBatch(@PathVariable - @Documentation(description = "The batch release date of the exposed keys in milliseconds since Unix Epoch (1970-01-01), must be a multiple of 2 * 60 * 60 * 1000", - example = "1593043200000") - long batchReleaseTime, - WebRequest request) throws BadBatchReleaseTimeException { - var now = UTCInstant.now(); - if(!validationUtils.isValidBatchReleaseTime(UTCInstant.ofEpochMillis(batchReleaseTime), now)) { - return ResponseEntity.notFound().build(); - } - - List exposeeList = dataService.getSortedExposedForBatchReleaseTime(batchReleaseTime, releaseBucketDuration); - List exposees = new ArrayList<>(); - for (Exposee exposee : exposeeList) { - Exposed.ProtoExposee protoExposee = Exposed.ProtoExposee.newBuilder() - .setKey(ByteString.copyFrom(Base64.getDecoder().decode(exposee.getKey()))) - .setKeyDate(exposee.getKeyDate()).build(); - exposees.add(protoExposee); - } - Exposed.ProtoExposedList protoExposee = Exposed.ProtoExposedList.newBuilder().addAllExposed(exposees) - .setBatchReleaseTime(batchReleaseTime).build(); - - return ResponseEntity.ok().cacheControl(CacheControl.maxAge(Duration.ofMinutes(exposedListCacheControl))) - .header("X-BATCH-RELEASE-TIME", Long.toString(batchReleaseTime)).body(protoExposee); - } - - @CrossOrigin(origins = { "https://editor.swagger.io" }) - @GetMapping(value = "/buckets/{dayDateStr}", produces = "application/json") - @Documentation(description = "Query number of available buckets in a given day, starting from midnight UTC", - responses = { - "200=>Returns BucketList in json format, indicating all available buckets since _dayDateStr_" - }) - public @ResponseBody ResponseEntity getListOfBuckets(@PathVariable - @Documentation(description = "The date starting when to return the available buckets, in ISO8601 date format", example = "2019-01-31") - String dayDateStr) { - var day = UTCInstant.parseDate(dayDateStr); - var currentBucket = day; - var now = UTCInstant.now(); - List bucketList = new ArrayList<>(); - while (currentBucket.getTimestamp() < Math.min(day.plusDays(1).getTimestamp(), - now.getTimestamp())) { - bucketList.add(currentBucket.getTimestamp()); - currentBucket = currentBucket.plusSeconds(releaseBucketDuration / 1000); - } - BucketList list = new BucketList(); - list.setBuckets(bucketList); - return ResponseEntity.ok(list); - } - - @ExceptionHandler({IllegalArgumentException.class, InvalidDateException.class, JsonProcessingException.class, - MethodArgumentNotValidException.class, BadBatchReleaseTimeException.class, DateTimeParseException.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ResponseEntity invalidArguments() { - return ResponseEntity.badRequest().build(); - } - + private final DPPPTDataService dataService; + private final String appSource; + private final int exposedListCacheControl; + private final ValidateRequest validateRequest; + private final ValidationUtils validationUtils; + // time in milliseconds that exposed keys are hidden before being served, in order to prevent + // timing attacks + private final long releaseBucketDuration; + private final long requestTime; + + public DPPPTController( + DPPPTDataService dataService, + String appSource, + int exposedListCacheControl, + ValidateRequest validateRequest, + ValidationUtils validationUtils, + long releaseBucketDuration, + long requestTime) { + this.dataService = dataService; + this.appSource = appSource; + this.exposedListCacheControl = exposedListCacheControl / 1000 / 60; + this.validateRequest = validateRequest; + this.validationUtils = validationUtils; + this.releaseBucketDuration = releaseBucketDuration; + this.requestTime = requestTime; + } + + @CrossOrigin(origins = {"https://editor.swagger.io"}) + @GetMapping(value = "") + @Documentation( + description = "Hello return", + responses = {"200=>server live"}) + public @ResponseBody ResponseEntity hello() { + return ResponseEntity.ok().header("X-HELLO", "dp3t").body("Hello from DP3T WS"); + } + + @CrossOrigin(origins = {"https://editor.swagger.io"}) + @PostMapping(value = "/exposed") + @Documentation( + description = "Send exposed key to server", + responses = { + "200=>The exposed keys have been stored in the database", + "400=>Invalid base64 encoding in expose request", + "403=>Authentication failed" + }) + public @ResponseBody ResponseEntity addExposee( + @Valid + @RequestBody + @Documentation( + description = + "The ExposeeRequest contains the SecretKey from the guessed infection date, the" + + " infection date itself, and some authentication data to verify the test" + + " result") + ExposeeRequest exposeeRequest, + @RequestHeader(value = "User-Agent", required = true) + @Documentation( + description = + "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS)" + + " + OS-Version", + example = "ch.ubique.android.starsdk;1.0;iOS;13.3") + String userAgent, + @AuthenticationPrincipal Object principal) + throws InvalidDateException, WrongScopeException, ClaimIsBeforeOnsetException { + var now = UTCInstant.now(); + + if (!this.validateRequest.isValid(principal)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + if (!validationUtils.isValidBase64Key(exposeeRequest.getKey())) { + return new ResponseEntity<>("No valid base64 key", HttpStatus.BAD_REQUEST); + } + // TODO: should we give that information? + Exposee exposee = new Exposee(); + exposee.setKey(exposeeRequest.getKey()); + long keyDate = this.validateRequest.validateKeyDate(now, principal, exposeeRequest); + + exposee.setKeyDate(keyDate); + if (!this.validateRequest.isFakeRequest(principal, exposeeRequest)) { + dataService.upsertExposee(exposee, appSource); + } + + long after = System.currentTimeMillis(); + long duration = after - now.getTimestamp(); + try { + Thread.sleep(Math.max(this.requestTime - duration, 0)); + } catch (Exception ex) { + + } + return ResponseEntity.ok().build(); + } + + @CrossOrigin(origins = {"https://editor.swagger.io"}) + @PostMapping(value = "/exposedlist") + @Documentation( + description = "Send a list of exposed keys to server", + responses = { + "200=>The exposed keys have been stored in the database", + "400=>Invalid base64 encoding in exposee request", + "403=>Authentication failed" + }) + public @ResponseBody ResponseEntity addExposee( + @Valid + @RequestBody + @Documentation( + description = + "The ExposeeRequest contains the SecretKey from the guessed infection date, the" + + " infection date itself, and some authentication data to verify the test" + + " result") + ExposeeRequestList exposeeRequests, + @RequestHeader(value = "User-Agent", required = true) + @Documentation( + description = + "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS)" + + " + OS-Version", + example = "ch.ubique.android.starsdk;1.0;iOS;13.3") + String userAgent, + @AuthenticationPrincipal Object principal) + throws InvalidDateException, WrongScopeException, ClaimIsBeforeOnsetException { + var now = UTCInstant.now(); + + if (!this.validateRequest.isValid(principal)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + List exposees = new ArrayList<>(); + for (var exposedKey : exposeeRequests.getExposedKeys()) { + if (!validationUtils.isValidBase64Key(exposedKey.getKey())) { + return new ResponseEntity<>("No valid base64 key", HttpStatus.BAD_REQUEST); + } + + Exposee exposee = new Exposee(); + exposee.setKey(exposedKey.getKey()); + long keyDate = this.validateRequest.validateKeyDate(now, principal, exposedKey); + + exposee.setKeyDate(keyDate); + exposees.add(exposee); + } + + if (!this.validateRequest.isFakeRequest(principal, exposeeRequests)) { + dataService.upsertExposees(exposees, appSource); + } + + long after = System.currentTimeMillis(); + long duration = after - now.getTimestamp(); + try { + Thread.sleep(Math.max(this.requestTime - duration, 0)); + } catch (Exception ex) { + + } + return ResponseEntity.ok().build(); + } + + @CrossOrigin(origins = {"https://editor.swagger.io"}) + @GetMapping(value = "/exposedjson/{batchReleaseTime}", produces = "application/json") + @Documentation( + description = "Query list of exposed keys from a specific batch release time", + responses = { + "200=>Returns ExposedOverview in json format, which includes all exposed keys which were" + + " published on _batchReleaseTime_", + "404=>Couldn't find _batchReleaseTime_" + }) + public @ResponseBody ResponseEntity getExposedByDayDate( + @PathVariable + @Documentation( + description = + "The batch release date of the exposed keys in milliseconds since Unix Epoch" + + " (1970-01-01), must be a multiple of 2 * 60 * 60 * 1000", + example = "1593043200000") + long batchReleaseTime, + WebRequest request) + throws BadBatchReleaseTimeException { + var now = UTCInstant.now(); + if (!validationUtils.isValidBatchReleaseTime(UTCInstant.ofEpochMillis(batchReleaseTime), now)) { + return ResponseEntity.notFound().build(); + } + + List exposeeList = + dataService.getSortedExposedForBatchReleaseTime(batchReleaseTime, releaseBucketDuration); + ExposedOverview overview = new ExposedOverview(exposeeList); + overview.setBatchReleaseTime(batchReleaseTime); + return ResponseEntity.ok() + .cacheControl(CacheControl.maxAge(Duration.ofMinutes(exposedListCacheControl))) + .header("X-BATCH-RELEASE-TIME", Long.toString(batchReleaseTime)) + .body(overview); + } + + @CrossOrigin(origins = {"https://editor.swagger.io"}) + @GetMapping(value = "/exposed/{batchReleaseTime}", produces = "application/x-protobuf") + @Documentation( + description = "Query list of exposed keys from a specific batch release time", + responses = { + "200=>Returns ExposedOverview in protobuf format, which includes all exposed keys which" + + " were published on _batchReleaseTime_", + "404=>Couldn't find _batchReleaseTime_" + }) + public @ResponseBody ResponseEntity getExposedByBatch( + @PathVariable + @Documentation( + description = + "The batch release date of the exposed keys in milliseconds since Unix Epoch" + + " (1970-01-01), must be a multiple of 2 * 60 * 60 * 1000", + example = "1593043200000") + long batchReleaseTime, + WebRequest request) + throws BadBatchReleaseTimeException { + var now = UTCInstant.now(); + if (!validationUtils.isValidBatchReleaseTime(UTCInstant.ofEpochMillis(batchReleaseTime), now)) { + return ResponseEntity.notFound().build(); + } + + List exposeeList = + dataService.getSortedExposedForBatchReleaseTime(batchReleaseTime, releaseBucketDuration); + List exposees = new ArrayList<>(); + for (Exposee exposee : exposeeList) { + Exposed.ProtoExposee protoExposee = + Exposed.ProtoExposee.newBuilder() + .setKey(ByteString.copyFrom(Base64.getDecoder().decode(exposee.getKey()))) + .setKeyDate(exposee.getKeyDate()) + .build(); + exposees.add(protoExposee); + } + Exposed.ProtoExposedList protoExposee = + Exposed.ProtoExposedList.newBuilder() + .addAllExposed(exposees) + .setBatchReleaseTime(batchReleaseTime) + .build(); + + return ResponseEntity.ok() + .cacheControl(CacheControl.maxAge(Duration.ofMinutes(exposedListCacheControl))) + .header("X-BATCH-RELEASE-TIME", Long.toString(batchReleaseTime)) + .body(protoExposee); + } + + @CrossOrigin(origins = {"https://editor.swagger.io"}) + @GetMapping(value = "/buckets/{dayDateStr}", produces = "application/json") + @Documentation( + description = "Query number of available buckets in a given day, starting from midnight UTC", + responses = { + "200=>Returns BucketList in json format, indicating all available buckets since" + + " _dayDateStr_" + }) + public @ResponseBody ResponseEntity getListOfBuckets( + @PathVariable + @Documentation( + description = + "The date starting when to return the available buckets, in ISO8601 date format", + example = "2019-01-31") + String dayDateStr) { + var day = UTCInstant.parseDate(dayDateStr); + var currentBucket = day; + var now = UTCInstant.now(); + List bucketList = new ArrayList<>(); + while (currentBucket.getTimestamp() + < Math.min(day.plusDays(1).getTimestamp(), now.getTimestamp())) { + bucketList.add(currentBucket.getTimestamp()); + currentBucket = currentBucket.plusSeconds(releaseBucketDuration / 1000); + } + BucketList list = new BucketList(); + list.setBuckets(bucketList); + return ResponseEntity.ok(list); + } + + @ExceptionHandler({ + IllegalArgumentException.class, + InvalidDateException.class, + JsonProcessingException.class, + MethodArgumentNotValidException.class, + BadBatchReleaseTimeException.class, + DateTimeParseException.class + }) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity invalidArguments() { + return ResponseEntity.badRequest().build(); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DebugController.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DebugController.java index 567b5c9b..6dd653aa 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DebugController.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/DebugController.java @@ -7,19 +7,17 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; - import javax.validation.Valid; - import org.dpppt.backend.sdk.data.gaen.DebugGAENDataService; import org.dpppt.backend.sdk.model.gaen.DayBuckets; import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.GaenRequest; +import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.security.ValidateRequest; import org.dpppt.backend.sdk.ws.security.ValidateRequest.ClaimIsBeforeOnsetException; import org.dpppt.backend.sdk.ws.security.ValidateRequest.InvalidDateException; import org.dpppt.backend.sdk.ws.security.ValidateRequest.WrongScopeException; import org.dpppt.backend.sdk.ws.security.signature.ProtoSignature; -import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.util.ValidationUtils; import org.dpppt.backend.sdk.ws.util.ValidationUtils.BadBatchReleaseTimeException; import org.springframework.http.HttpStatus; @@ -39,105 +37,117 @@ @Controller @RequestMapping("/v1/debug") public class DebugController { - private final ValidateRequest validateRequest; - private final ValidationUtils validationUtils; - private final Duration releaseBucketDuration; - private final Duration requestTime; - private final ProtoSignature gaenSigner; - private final DebugGAENDataService dataService; - - public DebugController(DebugGAENDataService dataService, ProtoSignature gaenSigner, ValidateRequest validateRequest, ValidationUtils validationUtils, Duration releaseBucketDuration, Duration requestTime) { - this.validateRequest = validateRequest; - this.validationUtils = validationUtils; - this.releaseBucketDuration = releaseBucketDuration; - this.requestTime = requestTime; - this.gaenSigner = gaenSigner; - this.dataService = dataService; + private final ValidateRequest validateRequest; + private final ValidationUtils validationUtils; + private final Duration releaseBucketDuration; + private final Duration requestTime; + private final ProtoSignature gaenSigner; + private final DebugGAENDataService dataService; + + public DebugController( + DebugGAENDataService dataService, + ProtoSignature gaenSigner, + ValidateRequest validateRequest, + ValidationUtils validationUtils, + Duration releaseBucketDuration, + Duration requestTime) { + this.validateRequest = validateRequest; + this.validationUtils = validationUtils; + this.releaseBucketDuration = releaseBucketDuration; + this.requestTime = requestTime; + this.gaenSigner = gaenSigner; + this.dataService = dataService; + } + + @PostMapping(value = "/exposed") + public @ResponseBody ResponseEntity addExposed( + @Valid @RequestBody GaenRequest gaenRequest, + @RequestHeader(value = "User-Agent", required = true) String userAgent, + @RequestHeader(value = "X-Device-Name", required = true) String deviceName, + @AuthenticationPrincipal Object principal) + throws InvalidDateException, ClaimIsBeforeOnsetException, WrongScopeException { + var now = UTCInstant.now(); + this.validateRequest.isValid(principal); + + List nonFakeKeys = new ArrayList<>(); + for (var key : gaenRequest.getGaenKeys()) { + if (!validationUtils.isValidBase64Key(key.getKeyData())) { + return new ResponseEntity<>("No valid base64 key", HttpStatus.BAD_REQUEST); + } + this.validateRequest.validateKeyDate(now, principal, key); + if (this.validateRequest.isFakeRequest(principal, key)) { + continue; + } else { + nonFakeKeys.add(key); + } } - - @PostMapping(value = "/exposed") - public @ResponseBody ResponseEntity addExposed(@Valid @RequestBody GaenRequest gaenRequest, - @RequestHeader(value = "User-Agent", required = true) String userAgent, - @RequestHeader(value = "X-Device-Name", required = true) String deviceName, - @AuthenticationPrincipal Object principal) throws InvalidDateException, ClaimIsBeforeOnsetException, WrongScopeException { - var now = UTCInstant.now(); - this.validateRequest.isValid(principal); - - List nonFakeKeys = new ArrayList<>(); - for (var key : gaenRequest.getGaenKeys()) { - if (!validationUtils.isValidBase64Key(key.getKeyData())) { - return new ResponseEntity<>("No valid base64 key", HttpStatus.BAD_REQUEST); - } - this.validateRequest.validateKeyDate(now, principal, key); - if (this.validateRequest.isFakeRequest(principal, key)) { - continue; - } else { - nonFakeKeys.add(key); - } - } - if (principal instanceof Jwt && ((Jwt) principal).containsClaim("fake") - && ((Jwt) principal).getClaim("fake").equals("1") && !nonFakeKeys.isEmpty()) { - return ResponseEntity.badRequest().body("Claim is fake but list contains non fake keys"); - } - if (!nonFakeKeys.isEmpty()) { - dataService.upsertExposees(deviceName, nonFakeKeys); - } - - var responseBuilder = ResponseEntity.ok(); - - normalizeRequestTime(now.getTimestamp()); - return responseBuilder.build(); + if (principal instanceof Jwt + && ((Jwt) principal).containsClaim("fake") + && ((Jwt) principal).getClaim("fake").equals("1") + && !nonFakeKeys.isEmpty()) { + return ResponseEntity.badRequest().body("Claim is fake but list contains non fake keys"); } + if (!nonFakeKeys.isEmpty()) { + dataService.upsertExposees(deviceName, nonFakeKeys); + } + + var responseBuilder = ResponseEntity.ok(); + + normalizeRequestTime(now.getTimestamp()); + return responseBuilder.build(); + } - @GetMapping(value = "/exposed/{batchReleaseTime}", produces = "application/zip") - public @ResponseBody ResponseEntity getExposedKeys(@PathVariable long batchReleaseTime, WebRequest request) - throws BadBatchReleaseTimeException, IOException, InvalidKeyException, - NoSuchAlgorithmException, SignatureException { - - var batchReleaseTimeDuration = Duration.ofMillis(batchReleaseTime); - if (batchReleaseTime % releaseBucketDuration.toMillis() != 0) { - return ResponseEntity.notFound().build(); - } - - var exposedKeys = dataService.getSortedExposedForBatchReleaseTime(batchReleaseTimeDuration.toMillis(), releaseBucketDuration.toMillis()); - - byte[] payload = gaenSigner.getPayload(exposedKeys); - - return ResponseEntity.ok() - .header("X-BATCH-RELEASE-TIME", Long.toString(batchReleaseTimeDuration.toMillis())) - .body(payload); + @GetMapping(value = "/exposed/{batchReleaseTime}", produces = "application/zip") + public @ResponseBody ResponseEntity getExposedKeys( + @PathVariable long batchReleaseTime, WebRequest request) + throws BadBatchReleaseTimeException, IOException, InvalidKeyException, + NoSuchAlgorithmException, SignatureException { + + var batchReleaseTimeDuration = Duration.ofMillis(batchReleaseTime); + if (batchReleaseTime % releaseBucketDuration.toMillis() != 0) { + return ResponseEntity.notFound().build(); } - @GetMapping(value = "/buckets/{dayDateStr}") - public @ResponseBody ResponseEntity getBuckets(@PathVariable String dayDateStr) { - var atStartOfDay = UTCInstant.parseDate(dayDateStr); - var end = atStartOfDay.plusDays(1); - var now = UTCInstant.now(); - // if (!validationUtils.isDateInRange(atStartOfDay)) { - // return ResponseEntity.notFound().build(); - // } - var relativeUrls = new ArrayList(); - var dayBuckets = new DayBuckets(); - - String controllerMapping = this.getClass().getAnnotation(RequestMapping.class).value()[0]; - dayBuckets.setDay(dayDateStr).setRelativeUrls(relativeUrls); - - while (atStartOfDay.getTimestamp() < Math.min(now.getTimestamp(), - end.getTimestamp())) { - relativeUrls.add(controllerMapping + "/exposed" + "/" + atStartOfDay.getTimestamp()); - atStartOfDay = atStartOfDay.plus(this.releaseBucketDuration); - } - - return ResponseEntity.ok(dayBuckets); + var exposedKeys = + dataService.getSortedExposedForBatchReleaseTime( + batchReleaseTimeDuration.toMillis(), releaseBucketDuration.toMillis()); + + byte[] payload = gaenSigner.getPayload(exposedKeys); + + return ResponseEntity.ok() + .header("X-BATCH-RELEASE-TIME", Long.toString(batchReleaseTimeDuration.toMillis())) + .body(payload); + } + + @GetMapping(value = "/buckets/{dayDateStr}") + public @ResponseBody ResponseEntity getBuckets(@PathVariable String dayDateStr) { + var atStartOfDay = UTCInstant.parseDate(dayDateStr); + var end = atStartOfDay.plusDays(1); + var now = UTCInstant.now(); + // if (!validationUtils.isDateInRange(atStartOfDay)) { + // return ResponseEntity.notFound().build(); + // } + var relativeUrls = new ArrayList(); + var dayBuckets = new DayBuckets(); + + String controllerMapping = this.getClass().getAnnotation(RequestMapping.class).value()[0]; + dayBuckets.setDay(dayDateStr).setRelativeUrls(relativeUrls); + + while (atStartOfDay.getTimestamp() < Math.min(now.getTimestamp(), end.getTimestamp())) { + relativeUrls.add(controllerMapping + "/exposed" + "/" + atStartOfDay.getTimestamp()); + atStartOfDay = atStartOfDay.plus(this.releaseBucketDuration); } - private void normalizeRequestTime(long now) { - long after = UTCInstant.now().getTimestamp(); - long duration = after - now; - try { - Thread.sleep(Math.max(requestTime.minusMillis(duration).toMillis(), 0)); - } catch (Exception ex) { + return ResponseEntity.ok(dayBuckets); + } + + private void normalizeRequestTime(long now) { + long after = UTCInstant.now().getTimestamp(); + long duration = after - now; + try { + Thread.sleep(Math.max(requestTime.minusMillis(duration).toMillis(), 0)); + } catch (Exception ex) { - } } -} \ No newline at end of file + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/GaenController.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/GaenController.java index e3c3d7a2..055b3d66 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/GaenController.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/controller/GaenController.java @@ -9,6 +9,9 @@ */ package org.dpppt.backend.sdk.ws.controller; +import ch.ubique.openapi.docannotations.Documentation; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.jsonwebtoken.Jwts; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -20,11 +23,7 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.Callable; - import javax.validation.Valid; - -import com.fasterxml.jackson.core.JsonProcessingException; - import org.dpppt.backend.sdk.data.gaen.FakeKeyService; import org.dpppt.backend.sdk.data.gaen.GAENDataService; import org.dpppt.backend.sdk.model.gaen.DayBuckets; @@ -66,257 +65,322 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; -import ch.ubique.openapi.docannotations.Documentation; -import io.jsonwebtoken.Jwts; - @Controller @RequestMapping("/v1/gaen") @Documentation(description = "The GAEN endpoint for the mobile clients") /** - * The GaenController defines the API endpoints for the mobile clients to access the GAEN functionality of the - * red backend. - * Clients can send new Exposed Keys, or request the existing Exposed Keys. + * The GaenController defines the API endpoints for the mobile clients to access the GAEN + * functionality of the red backend. Clients can send new Exposed Keys, or request the existing + * Exposed Keys. */ public class GaenController { - private static final Logger logger = LoggerFactory.getLogger(GaenController.class); - - // releaseBucketDuration is used to delay the publishing of Exposed Keys by splitting the database up into batches of keys - // in releaseBucketDuration duration. The current batch is never published, only previous batches are published. - private final Duration releaseBucketDuration; - - private final Duration requestTime; - private final ValidateRequest validateRequest; - private final ValidationUtils validationUtils; - private final InsertManager insertManager; - private final GAENDataService dataService; - private final FakeKeyService fakeKeyService; - private final Duration exposedListCacheControl; - private final PrivateKey secondDayKey; - private final ProtoSignature gaenSigner; - - public GaenController(InsertManager insertManager, GAENDataService dataService, FakeKeyService fakeKeyService, ValidateRequest validateRequest, - ProtoSignature gaenSigner, ValidationUtils validationUtils, Duration releaseBucketDuration, Duration requestTime, - Duration exposedListCacheControl, PrivateKey secondDayKey) { - this.insertManager = insertManager; - this.dataService = dataService; - this.fakeKeyService = fakeKeyService; - this.releaseBucketDuration = releaseBucketDuration; - this.validateRequest = validateRequest; - this.requestTime = requestTime; - this.validationUtils = validationUtils; - this.exposedListCacheControl = exposedListCacheControl; - this.secondDayKey = secondDayKey; - this.gaenSigner = gaenSigner; - } - - @PostMapping(value = "/exposed") - @Documentation( - description = "Send exposed keys to server - includes a fix for the fact that GAEN doesn't give access to the current day's exposed key", - responses = { - "200=>The exposed keys have been stored in the database", - "400=>Invalid base64 encoding in GaenRequest", - "403=>Authentication failed" - }) - public @ResponseBody Callable> addExposed( - @Valid @RequestBody - @Documentation(description = "The GaenRequest contains the SecretKey from the guessed infection date, the infection date itself, and some authentication data to verify the test result") - GaenRequest gaenRequest, - @RequestHeader(value = "User-Agent") - @Documentation(description = "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS) + OS-Version", example = "ch.ubique.android.starsdk;1.0;iOS;13.3") - String userAgent, - @AuthenticationPrincipal - @Documentation(description = "JWT token that can be verified by the backend server") - Object principal) - throws WrongScopeException, KeyIsNotBase64Exception, DelayedKeyDateIsInvalid { - var now = UTCInstant.now(); - - this.validateRequest.isValid(principal); - - //Filter out non valid keys and insert them into the database (c.f. InsertManager and configured Filters in the WSBaseConfig) - insertIntoDatabaseIfJWTIsNotFake(gaenRequest.getGaenKeys(), userAgent, principal, now); - - this.validationUtils.validateDelayedKeyDate(now, UTCInstant.of(gaenRequest.getDelayedKeyDate(), GaenUnit.TenMinutes)); - - var responseBuilder = ResponseEntity.ok(); - if (principal instanceof Jwt) { - var originalJWT = (Jwt) principal; - var jwtBuilder = Jwts.builder().setId(UUID.randomUUID().toString()).setIssuedAt(now.getDate()) - .setIssuer("dpppt-sdk-backend").setSubject(originalJWT.getSubject()) - .setExpiration(now.plusDays(2).getDate()) - .claim("scope", "currentDayExposed").claim("delayedKeyDate", gaenRequest.getDelayedKeyDate()); - if (originalJWT.containsClaim("fake")) { - jwtBuilder.claim("fake", originalJWT.getClaim("fake")); - } - String jwt = jwtBuilder.signWith(secondDayKey).compact(); - responseBuilder.header("Authorization", "Bearer " + jwt); - } - Callable> cb = () -> { - normalizeRequestTime(now.getTimestamp()); - return responseBuilder.body("OK"); - }; - return cb; - } - - @PostMapping(value = "/exposednextday") - @Documentation(description = "Allows the client to send the last exposed key of the infection to the backend server. The JWT must come from a previous call to /exposed", - responses = { - "200=>The exposed key has been stored in the backend", - "400=>" + - "- Ivnalid base64 encoded Temporary Exposure Key" + - "- TEK-date does not match delayedKeyDAte claim in Jwt", - "403=>No delayedKeyDate claim in authentication" - }) - public @ResponseBody Callable> addExposedSecond( - @Valid @RequestBody - @Documentation(description = "The last exposed key of the user") - GaenSecondDay gaenSecondDay, - @Documentation(description = "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS) + OS-Version", example = "ch.ubique.android.starsdk;1.0;iOS;13.3") - @RequestHeader(value = "User-Agent") - String userAgent, - @AuthenticationPrincipal - @Documentation(description = "JWT token that can be verified by the backend server, must have been created by /v1/gaen/exposed and contain the delayedKeyDate") - Object principal) throws KeyIsNotBase64Exception, DelayedKeyDateClaimIsWrong { - var now = UTCInstant.now(); - - validationUtils.checkForDelayedKeyDateClaim(principal, gaenSecondDay.getDelayedKey()); - - //Filter out non valid keys and insert them into the database (c.f. InsertManager and configured Filters in the WSBaseConfig) - insertIntoDatabaseIfJWTIsNotFake(gaenSecondDay.getDelayedKey(), userAgent, principal, now); - - return () -> { - normalizeRequestTime(now.getTimestamp()); - return ResponseEntity.ok().body("OK"); - }; - - } - - @GetMapping(value = "/exposed/{keyDate}", produces = "application/zip") - @Documentation(description = "Request the exposed key from a given date", - responses = { - "200=>zipped export.bin and export.sig of all keys in that interval", - "404=>" + - "- invalid starting key date, doesn't point to midnight UTC" + - "- _publishedAfter_ is not at the beginning of a batch release time, currently 2h", - }) - public @ResponseBody ResponseEntity getExposedKeys( - @PathVariable - @Documentation(description = "Requested date for Exposed Keys retrieval, in milliseconds since Unix epoch (1970-01-01). It must indicate the beginning of a TEKRollingPeriod, currently midnight UTC.", - example = "1593043200000") - long keyDate, - @RequestParam(required = false) - @Documentation(description = "Restrict returned Exposed Keys to dates after this parameter. Given in milliseconds since Unix epoch (1970-01-01).", - example = "1593043200000") - Long publishedafter) - throws BadBatchReleaseTimeException, IOException, InvalidKeyException, SignatureException, - NoSuchAlgorithmException { - var now = UTCInstant.now(); - if (!validationUtils.isValidKeyDate(UTCInstant.ofEpochMillis(keyDate))) { - return ResponseEntity.notFound().build(); - } - if (publishedafter != null && !validationUtils.isValidBatchReleaseTime(UTCInstant.ofEpochMillis(publishedafter), now)) { - return ResponseEntity.notFound().build(); - } - - - // calculate exposed until bucket - long publishedUntil = now.getTimestamp() - (now.getTimestamp() % releaseBucketDuration.toMillis()); - - var exposedKeys = dataService.getSortedExposedForKeyDate(keyDate, publishedafter, publishedUntil); - exposedKeys = fakeKeyService.fillUpKeys(exposedKeys, publishedafter, keyDate); - if (exposedKeys.isEmpty()) { - return ResponseEntity.noContent().cacheControl(CacheControl.maxAge(exposedListCacheControl)) - .header("X-PUBLISHED-UNTIL", Long.toString(publishedUntil)).build(); - } - - ProtoSignatureWrapper payload = gaenSigner.getPayload(exposedKeys); - - return ResponseEntity.ok().cacheControl(CacheControl.maxAge(exposedListCacheControl)) - .header("X-PUBLISHED-UNTIL", Long.toString(publishedUntil)).body(payload.getZip()); - } - - @GetMapping(value = "/buckets/{dayDateStr}") - @Documentation(description = "Request the available release batch times for a given day", - responses = { - "200=>zipped export.bin and export.sig of all keys in that interval", - "404=>invalid starting key date, points outside of the retention range" - }) - public @ResponseBody ResponseEntity getBuckets( - @PathVariable - @Documentation(description = "Starting date for exposed key retrieval, as ISO-8601 format", - example = "2020-06-27") - String dayDateStr) { - var atStartOfDay = UTCInstant.parseDate(dayDateStr); - var end = atStartOfDay.plusDays(1); - var now = UTCInstant.now(); - if (!validationUtils.isDateInRange(atStartOfDay, now)) { - return ResponseEntity.notFound().build(); - } - var relativeUrls = new ArrayList(); - var dayBuckets = new DayBuckets(); - - String controllerMapping = this.getClass().getAnnotation(RequestMapping.class).value()[0]; - dayBuckets.setDay(dayDateStr).setRelativeUrls(relativeUrls).setDayTimestamp(atStartOfDay.getTimestamp()); - - while (atStartOfDay.getTimestamp() < Math.min(now.getTimestamp(), - end.getTimestamp())) { - relativeUrls.add(controllerMapping + "/exposed" + "/" + atStartOfDay.getTimestamp()); - atStartOfDay = atStartOfDay.plus(this.releaseBucketDuration); - } - - return ResponseEntity.ok(dayBuckets); - } - - private void normalizeRequestTime(long now) { - long after = UTCInstant.now().getTimestamp(); - long duration = after - now; - try { - Thread.sleep(Math.max(requestTime.minusMillis(duration).toMillis(), 0)); - } catch (Exception ex) { - logger.error("Couldn't equalize request time: {}", ex.toString()); - } - } - - private void insertIntoDatabaseIfJWTIsNotFake(GaenKey key, String userAgent, Object principal, UTCInstant now) throws KeyIsNotBase64Exception { - List keys = new ArrayList<>(); - keys.add(key); - insertIntoDatabaseIfJWTIsNotFake(keys, userAgent, principal, now); - } - - private void insertIntoDatabaseIfJWTIsNotFake(List keys, String userAgent, Object principal, UTCInstant now) throws KeyIsNotBase64Exception { - try { - insertManager.insertIntoDatabase(keys, userAgent, principal, now); - } - catch(KeyIsNotBase64Exception ex) { - throw ex; - } - catch(InsertException ex){ - logger.info("Unknown exception thrown: ", ex); - } - } - - @ExceptionHandler({DelayedKeyDateClaimIsWrong.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ResponseEntity delayedClaimIsWrong() { - return ResponseEntity.badRequest().body("DelayedKeyDateClaim is wrong"); - } - - @ExceptionHandler({DelayedKeyDateIsInvalid.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ResponseEntity delayedKeyDateIsInvalid() { - return ResponseEntity.badRequest().body("DelayedKeyDate must be between yesterday and tomorrow"); - } - - @ExceptionHandler({IllegalArgumentException.class, InvalidDateException.class, JsonProcessingException.class, - MethodArgumentNotValidException.class, BadBatchReleaseTimeException.class, DateTimeParseException.class, ClaimIsBeforeOnsetException.class, KeyIsNotBase64Exception.class}) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ResponseEntity invalidArguments() { - return ResponseEntity.badRequest().build(); - } - - @ExceptionHandler({WrongScopeException.class}) - @ResponseStatus(HttpStatus.FORBIDDEN) - public ResponseEntity forbidden() { - return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); - } - -} \ No newline at end of file + private static final Logger logger = LoggerFactory.getLogger(GaenController.class); + + // releaseBucketDuration is used to delay the publishing of Exposed Keys by splitting the database + // up into batches of keys + // in releaseBucketDuration duration. The current batch is never published, only previous batches + // are published. + private final Duration releaseBucketDuration; + + private final Duration requestTime; + private final ValidateRequest validateRequest; + private final ValidationUtils validationUtils; + private final InsertManager insertManager; + private final GAENDataService dataService; + private final FakeKeyService fakeKeyService; + private final Duration exposedListCacheControl; + private final PrivateKey secondDayKey; + private final ProtoSignature gaenSigner; + + public GaenController( + InsertManager insertManager, + GAENDataService dataService, + FakeKeyService fakeKeyService, + ValidateRequest validateRequest, + ProtoSignature gaenSigner, + ValidationUtils validationUtils, + Duration releaseBucketDuration, + Duration requestTime, + Duration exposedListCacheControl, + PrivateKey secondDayKey) { + this.insertManager = insertManager; + this.dataService = dataService; + this.fakeKeyService = fakeKeyService; + this.releaseBucketDuration = releaseBucketDuration; + this.validateRequest = validateRequest; + this.requestTime = requestTime; + this.validationUtils = validationUtils; + this.exposedListCacheControl = exposedListCacheControl; + this.secondDayKey = secondDayKey; + this.gaenSigner = gaenSigner; + } + + @PostMapping(value = "/exposed") + @Documentation( + description = + "Send exposed keys to server - includes a fix for the fact that GAEN doesn't give access" + + " to the current day's exposed key", + responses = { + "200=>The exposed keys have been stored in the database", + "400=>Invalid base64 encoding in GaenRequest", + "403=>Authentication failed" + }) + public @ResponseBody Callable> addExposed( + @Valid + @RequestBody + @Documentation( + description = + "The GaenRequest contains the SecretKey from the guessed infection date, the" + + " infection date itself, and some authentication data to verify the test" + + " result") + GaenRequest gaenRequest, + @RequestHeader(value = "User-Agent") + @Documentation( + description = + "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS)" + + " + OS-Version", + example = "ch.ubique.android.starsdk;1.0;iOS;13.3") + String userAgent, + @AuthenticationPrincipal + @Documentation(description = "JWT token that can be verified by the backend server") + Object principal) + throws WrongScopeException, KeyIsNotBase64Exception, DelayedKeyDateIsInvalid { + var now = UTCInstant.now(); + + this.validateRequest.isValid(principal); + + // Filter out non valid keys and insert them into the database (c.f. InsertManager and + // configured Filters in the WSBaseConfig) + insertIntoDatabaseIfJWTIsNotFake(gaenRequest.getGaenKeys(), userAgent, principal, now); + + this.validationUtils.validateDelayedKeyDate( + now, UTCInstant.of(gaenRequest.getDelayedKeyDate(), GaenUnit.TenMinutes)); + + var responseBuilder = ResponseEntity.ok(); + if (principal instanceof Jwt) { + var originalJWT = (Jwt) principal; + var jwtBuilder = + Jwts.builder() + .setId(UUID.randomUUID().toString()) + .setIssuedAt(now.getDate()) + .setIssuer("dpppt-sdk-backend") + .setSubject(originalJWT.getSubject()) + .setExpiration(now.plusDays(2).getDate()) + .claim("scope", "currentDayExposed") + .claim("delayedKeyDate", gaenRequest.getDelayedKeyDate()); + if (originalJWT.containsClaim("fake")) { + jwtBuilder.claim("fake", originalJWT.getClaim("fake")); + } + String jwt = jwtBuilder.signWith(secondDayKey).compact(); + responseBuilder.header("Authorization", "Bearer " + jwt); + } + Callable> cb = + () -> { + normalizeRequestTime(now.getTimestamp()); + return responseBuilder.body("OK"); + }; + return cb; + } + + @PostMapping(value = "/exposednextday") + @Documentation( + description = + "Allows the client to send the last exposed key of the infection to the backend server." + + " The JWT must come from a previous call to /exposed", + responses = { + "200=>The exposed key has been stored in the backend", + "400=>" + + "- Ivnalid base64 encoded Temporary Exposure Key" + + "- TEK-date does not match delayedKeyDAte claim in Jwt", + "403=>No delayedKeyDate claim in authentication" + }) + public @ResponseBody Callable> addExposedSecond( + @Valid @RequestBody @Documentation(description = "The last exposed key of the user") + GaenSecondDay gaenSecondDay, + @Documentation( + description = + "App Identifier (PackageName/BundleIdentifier) + App-Version + OS (Android/iOS)" + + " + OS-Version", + example = "ch.ubique.android.starsdk;1.0;iOS;13.3") + @RequestHeader(value = "User-Agent") + String userAgent, + @AuthenticationPrincipal + @Documentation( + description = + "JWT token that can be verified by the backend server, must have been created by" + + " /v1/gaen/exposed and contain the delayedKeyDate") + Object principal) + throws KeyIsNotBase64Exception, DelayedKeyDateClaimIsWrong { + var now = UTCInstant.now(); + + validationUtils.checkForDelayedKeyDateClaim(principal, gaenSecondDay.getDelayedKey()); + + // Filter out non valid keys and insert them into the database (c.f. InsertManager and + // configured Filters in the WSBaseConfig) + insertIntoDatabaseIfJWTIsNotFake(gaenSecondDay.getDelayedKey(), userAgent, principal, now); + + return () -> { + normalizeRequestTime(now.getTimestamp()); + return ResponseEntity.ok().body("OK"); + }; + } + + @GetMapping(value = "/exposed/{keyDate}", produces = "application/zip") + @Documentation( + description = "Request the exposed key from a given date", + responses = { + "200=>zipped export.bin and export.sig of all keys in that interval", + "404=>" + + "- invalid starting key date, doesn't point to midnight UTC" + + "- _publishedAfter_ is not at the beginning of a batch release time, currently 2h", + }) + public @ResponseBody ResponseEntity getExposedKeys( + @PathVariable + @Documentation( + description = + "Requested date for Exposed Keys retrieval, in milliseconds since Unix epoch" + + " (1970-01-01). It must indicate the beginning of a TEKRollingPeriod," + + " currently midnight UTC.", + example = "1593043200000") + long keyDate, + @RequestParam(required = false) + @Documentation( + description = + "Restrict returned Exposed Keys to dates after this parameter. Given in" + + " milliseconds since Unix epoch (1970-01-01).", + example = "1593043200000") + Long publishedafter) + throws BadBatchReleaseTimeException, IOException, InvalidKeyException, SignatureException, + NoSuchAlgorithmException { + var now = UTCInstant.now(); + if (!validationUtils.isValidKeyDate(UTCInstant.ofEpochMillis(keyDate))) { + return ResponseEntity.notFound().build(); + } + if (publishedafter != null + && !validationUtils.isValidBatchReleaseTime( + UTCInstant.ofEpochMillis(publishedafter), now)) { + return ResponseEntity.notFound().build(); + } + + // calculate exposed until bucket + long publishedUntil = + now.getTimestamp() - (now.getTimestamp() % releaseBucketDuration.toMillis()); + + var exposedKeys = + dataService.getSortedExposedForKeyDate(keyDate, publishedafter, publishedUntil); + exposedKeys = fakeKeyService.fillUpKeys(exposedKeys, publishedafter, keyDate); + if (exposedKeys.isEmpty()) { + return ResponseEntity.noContent() + .cacheControl(CacheControl.maxAge(exposedListCacheControl)) + .header("X-PUBLISHED-UNTIL", Long.toString(publishedUntil)) + .build(); + } + + ProtoSignatureWrapper payload = gaenSigner.getPayload(exposedKeys); + + return ResponseEntity.ok() + .cacheControl(CacheControl.maxAge(exposedListCacheControl)) + .header("X-PUBLISHED-UNTIL", Long.toString(publishedUntil)) + .body(payload.getZip()); + } + + @GetMapping(value = "/buckets/{dayDateStr}") + @Documentation( + description = "Request the available release batch times for a given day", + responses = { + "200=>zipped export.bin and export.sig of all keys in that interval", + "404=>invalid starting key date, points outside of the retention range" + }) + public @ResponseBody ResponseEntity getBuckets( + @PathVariable + @Documentation( + description = "Starting date for exposed key retrieval, as ISO-8601 format", + example = "2020-06-27") + String dayDateStr) { + var atStartOfDay = UTCInstant.parseDate(dayDateStr); + var end = atStartOfDay.plusDays(1); + var now = UTCInstant.now(); + if (!validationUtils.isDateInRange(atStartOfDay, now)) { + return ResponseEntity.notFound().build(); + } + var relativeUrls = new ArrayList(); + var dayBuckets = new DayBuckets(); + + String controllerMapping = this.getClass().getAnnotation(RequestMapping.class).value()[0]; + dayBuckets + .setDay(dayDateStr) + .setRelativeUrls(relativeUrls) + .setDayTimestamp(atStartOfDay.getTimestamp()); + + while (atStartOfDay.getTimestamp() < Math.min(now.getTimestamp(), end.getTimestamp())) { + relativeUrls.add(controllerMapping + "/exposed" + "/" + atStartOfDay.getTimestamp()); + atStartOfDay = atStartOfDay.plus(this.releaseBucketDuration); + } + + return ResponseEntity.ok(dayBuckets); + } + + private void normalizeRequestTime(long now) { + long after = UTCInstant.now().getTimestamp(); + long duration = after - now; + try { + Thread.sleep(Math.max(requestTime.minusMillis(duration).toMillis(), 0)); + } catch (Exception ex) { + logger.error("Couldn't equalize request time: {}", ex.toString()); + } + } + + private void insertIntoDatabaseIfJWTIsNotFake( + GaenKey key, String userAgent, Object principal, UTCInstant now) + throws KeyIsNotBase64Exception { + List keys = new ArrayList<>(); + keys.add(key); + insertIntoDatabaseIfJWTIsNotFake(keys, userAgent, principal, now); + } + + private void insertIntoDatabaseIfJWTIsNotFake( + List keys, String userAgent, Object principal, UTCInstant now) + throws KeyIsNotBase64Exception { + try { + insertManager.insertIntoDatabase(keys, userAgent, principal, now); + } catch (KeyIsNotBase64Exception ex) { + throw ex; + } catch (InsertException ex) { + logger.info("Unknown exception thrown: ", ex); + } + } + + @ExceptionHandler({DelayedKeyDateClaimIsWrong.class}) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity delayedClaimIsWrong() { + return ResponseEntity.badRequest().body("DelayedKeyDateClaim is wrong"); + } + + @ExceptionHandler({DelayedKeyDateIsInvalid.class}) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity delayedKeyDateIsInvalid() { + return ResponseEntity.badRequest() + .body("DelayedKeyDate must be between yesterday and tomorrow"); + } + + @ExceptionHandler({ + IllegalArgumentException.class, + InvalidDateException.class, + JsonProcessingException.class, + MethodArgumentNotValidException.class, + BadBatchReleaseTimeException.class, + DateTimeParseException.class, + ClaimIsBeforeOnsetException.class, + KeyIsNotBase64Exception.class + }) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity invalidArguments() { + return ResponseEntity.badRequest().build(); + } + + @ExceptionHandler({WrongScopeException.class}) + @ResponseStatus(HttpStatus.FORBIDDEN) + public ResponseEntity forbidden() { + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/filter/ResponseWrapperFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/filter/ResponseWrapperFilter.java index 0f113737..48b97d74 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/filter/ResponseWrapperFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/filter/ResponseWrapperFilter.java @@ -15,7 +15,6 @@ import java.security.PublicKey; import java.security.Security; import java.util.List; - import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.Filter; @@ -24,64 +23,68 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; - import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.dpppt.backend.sdk.ws.security.signature.SignatureResponseWrapper; public class ResponseWrapperFilter implements Filter { - private final KeyPair pair; - private final int retentionDays; - private final List protectedHeaders; - private final boolean setDebugHeaders; + private final KeyPair pair; + private final int retentionDays; + private final List protectedHeaders; + private final boolean setDebugHeaders; + + public PublicKey getPublicKey() { + return pair.getPublic(); + } + + public ResponseWrapperFilter( + KeyPair pair, int retentionDays, List protectedHeaders, boolean setDebugHeaders) { + Security.addProvider(new BouncyCastleProvider()); + Security.setProperty("crypto.policy", "unlimited"); + this.pair = pair; + this.retentionDays = retentionDays; + this.protectedHeaders = protectedHeaders; + this.setDebugHeaders = setDebugHeaders; + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletResponse httpResponse = (HttpServletResponse) response; - public PublicKey getPublicKey() { - return pair.getPublic(); - } + SignatureResponseWrapper wrapper = + new SignatureResponseWrapper( + httpResponse, pair, retentionDays, protectedHeaders, setDebugHeaders); + chain.doFilter(request, wrapper); + try { + request + .getAsyncContext() + .addListener( + new AsyncListener() { + @Override + public void onComplete(AsyncEvent event) throws IOException { + wrapper.outputData(httpResponse.getOutputStream()); + } - public ResponseWrapperFilter(KeyPair pair, int retentionDays, List protectedHeaders, - boolean setDebugHeaders) { - Security.addProvider(new BouncyCastleProvider()); - Security.setProperty("crypto.policy", "unlimited"); - this.pair = pair; - this.retentionDays = retentionDays; - this.protectedHeaders = protectedHeaders; - this.setDebugHeaders = setDebugHeaders; - } + @Override + public void onTimeout(AsyncEvent event) throws IOException { + /// We ignore this function, since the signature is anyways only valid if the + // request succeeds. + } - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - HttpServletResponse httpResponse = (HttpServletResponse) response; - - SignatureResponseWrapper wrapper = new SignatureResponseWrapper(httpResponse, pair, retentionDays, - protectedHeaders, setDebugHeaders); - chain.doFilter(request, wrapper); - try{ - request.getAsyncContext().addListener(new AsyncListener() { - @Override - public void onComplete(AsyncEvent event) throws IOException { - wrapper.outputData(httpResponse.getOutputStream()); - } + @Override + public void onError(AsyncEvent event) throws IOException { + /// We ignore this function, since the signature is anyways only valid if the + // request succeeds. + } - @Override - public void onTimeout(AsyncEvent event) throws IOException { - /// We ignore this function, since the signature is anyways only valid if the request succeeds. - } - - @Override - public void onError(AsyncEvent event) throws IOException { - /// We ignore this function, since the signature is anyways only valid if the request succeeds. - } - - @Override - public void onStartAsync(AsyncEvent event) throws IOException { - /// We ignore this function. We don't need any preparation. - } - }); - } - catch(Exception ex) { - wrapper.outputData(httpResponse.getOutputStream()); - } - } -} \ No newline at end of file + @Override + public void onStartAsync(AsyncEvent event) throws IOException { + /// We ignore this function. We don't need any preparation. + } + }); + } catch (Exception ex) { + wrapper.outputData(httpResponse.getOutputStream()); + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertException.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertException.java index 8a145183..43564ac3 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertException.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertException.java @@ -2,9 +2,6 @@ public class InsertException extends Exception { - /** - * - */ - private static final long serialVersionUID = 6476089262577182680L; - -} \ No newline at end of file + /** */ + private static final long serialVersionUID = 6476089262577182680L; +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManager.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManager.java index 704cd43d..22d31582 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManager.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManager.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; - import org.dpppt.backend.sdk.data.gaen.GAENDataService; import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; @@ -14,114 +13,111 @@ import org.slf4j.LoggerFactory; /** - * The insertion manager is responsible for inserting keys uploaded by clients - * into the database. To make sure we only have valid keys in the database, a - * list of {@link KeyInsertionModifier} is applied, and then a list of - * {@Link KeyInsertionFilter} is applied to the given list of keys. The - * remaining keys are then inserted into the database. If any of the modifiers - * filters throws an {@Link InsertException} the process of insertions is - * aborted and the exception is propagated back to the caller, which is - * responsible for handling the exception. - * + * The insertion manager is responsible for inserting keys uploaded by clients into the database. To + * make sure we only have valid keys in the database, a list of {@link KeyInsertionModifier} is + * applied, and then a list of {@Link KeyInsertionFilter} is applied to the given list of keys. The + * remaining keys are then inserted into the database. If any of the modifiers filters throws an + * {@Link InsertException} the process of insertions is aborted and the exception is propagated back + * to the caller, which is responsible for handling the exception. */ public class InsertManager { - private final List filterList = new ArrayList<>(); - private final List modifierList = new ArrayList<>(); - - private final GAENDataService dataService; - private final ValidationUtils validationUtils; - - private static final Logger logger = LoggerFactory.getLogger(InsertManager.class); - - public InsertManager(GAENDataService dataService, ValidationUtils validationUtils) { - this.dataService = dataService; - this.validationUtils = validationUtils; - } - - public void addFilter(KeyInsertionFilter filter) { - this.filterList.add(filter); - } - - public void addModifier(KeyInsertionModifier modifier) { - this.modifierList.add(modifier); - } - - /** - * Inserts the keys into the database. The additional parameters are supplied to - * the configured modifiers and filters. - * - * @param keys the list of keys from the client - * @param header request header from client - * @param principal key upload authorization, for example a JWT token. - * @param now current timestamp to work with. - * @throws InsertException filters are allowed to throw errors, for example to - * signal client errors in the key upload - */ - public void insertIntoDatabase(List keys, String header, Object principal, UTCInstant now) - throws InsertException { - - if (keys == null || keys.isEmpty()) { - return; - } - - var internalKeys = keys; - var headerParts = header.split(";"); - if (headerParts.length != 5) { - headerParts = List.of("org.example.dp3t", "1.0.0", "0", "Android", "29").toArray(new String[0]); - logger.error("We received an invalid header, setting default."); - } - - // Map the given headers to os type, os version and app version. Examples are: - // ch.admin.bag.dp36;1.0.7;200724.1105.215;iOS;13.6 - // ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29 - var osType = exctractOS(headerParts[3]); - var osVersion = extractOsVersion(headerParts[4]); - var appVersion = extractAppVersion(headerParts[1], headerParts[2]); - - for (KeyInsertionModifier modifier : modifierList) { - internalKeys = modifier.modify(now, internalKeys, osType, osVersion, appVersion, principal); - } - - for (KeyInsertionFilter filter : filterList) { - internalKeys = filter.filter(now, internalKeys, osType, osVersion, appVersion, principal); - } - - // if no keys remain or this is a fake request, just return. Else, insert the - // remaining keys. - if (internalKeys.isEmpty() || validationUtils.jwtIsFake(principal)) { - return; - } else { - dataService.upsertExposees(internalKeys, now); - } - } - - /** - * Extracts the {@link OSType} from the osString that is given by the client - * request. - * - * @param osString - * @return - */ - private OSType exctractOS(String osString) { - var result = OSType.ANDROID; - switch (osString.toLowerCase()) { - case "ios": - result = OSType.IOS; - break; - case "android": - break; - default: - result = OSType.ANDROID; - } - return result; - } - - private Version extractOsVersion(String osVersionString) { - return new Version(osVersionString); - } - - private Version extractAppVersion(String osAppVersionString, String osMetaInfo) { - return new Version(osAppVersionString + "+" + osMetaInfo); - } -} \ No newline at end of file + private final List filterList = new ArrayList<>(); + private final List modifierList = new ArrayList<>(); + + private final GAENDataService dataService; + private final ValidationUtils validationUtils; + + private static final Logger logger = LoggerFactory.getLogger(InsertManager.class); + + public InsertManager(GAENDataService dataService, ValidationUtils validationUtils) { + this.dataService = dataService; + this.validationUtils = validationUtils; + } + + public void addFilter(KeyInsertionFilter filter) { + this.filterList.add(filter); + } + + public void addModifier(KeyInsertionModifier modifier) { + this.modifierList.add(modifier); + } + + /** + * Inserts the keys into the database. The additional parameters are supplied to the configured + * modifiers and filters. + * + * @param keys the list of keys from the client + * @param header request header from client + * @param principal key upload authorization, for example a JWT token. + * @param now current timestamp to work with. + * @throws InsertException filters are allowed to throw errors, for example to signal client + * errors in the key upload + */ + public void insertIntoDatabase( + List keys, String header, Object principal, UTCInstant now) throws InsertException { + + if (keys == null || keys.isEmpty()) { + return; + } + + var internalKeys = keys; + var headerParts = header.split(";"); + if (headerParts.length != 5) { + headerParts = + List.of("org.example.dp3t", "1.0.0", "0", "Android", "29").toArray(new String[0]); + logger.error("We received an invalid header, setting default."); + } + + // Map the given headers to os type, os version and app version. Examples are: + // ch.admin.bag.dp36;1.0.7;200724.1105.215;iOS;13.6 + // ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29 + var osType = exctractOS(headerParts[3]); + var osVersion = extractOsVersion(headerParts[4]); + var appVersion = extractAppVersion(headerParts[1], headerParts[2]); + + for (KeyInsertionModifier modifier : modifierList) { + internalKeys = modifier.modify(now, internalKeys, osType, osVersion, appVersion, principal); + } + + for (KeyInsertionFilter filter : filterList) { + internalKeys = filter.filter(now, internalKeys, osType, osVersion, appVersion, principal); + } + + // if no keys remain or this is a fake request, just return. Else, insert the + // remaining keys. + if (internalKeys.isEmpty() || validationUtils.jwtIsFake(principal)) { + return; + } else { + dataService.upsertExposees(internalKeys, now); + } + } + + /** + * Extracts the {@link OSType} from the osString that is given by the client request. + * + * @param osString + * @return + */ + private OSType exctractOS(String osString) { + var result = OSType.ANDROID; + switch (osString.toLowerCase()) { + case "ios": + result = OSType.IOS; + break; + case "android": + break; + default: + result = OSType.ANDROID; + } + return result; + } + + private Version extractOsVersion(String osVersionString) { + return new Version(osVersionString); + } + + private Version extractAppVersion(String osAppVersionString, String osMetaInfo) { + return new Version(osAppVersionString + "+" + osMetaInfo); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/OSType.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/OSType.java index 9a4a51bb..c910d4e9 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/OSType.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/OSType.java @@ -1,15 +1,18 @@ package org.dpppt.backend.sdk.ws.insertmanager; public enum OSType { - ANDROID, - IOS; + ANDROID, + IOS; - @Override - public String toString() { - switch(this) { - case ANDROID: return "Android"; - case IOS: return "iOS"; - default: return "Unknown"; - } + @Override + public String toString() { + switch (this) { + case ANDROID: + return "Android"; + case IOS: + return "iOS"; + default: + return "Unknown"; } -} \ No newline at end of file + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/Base64Filter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/Base64Filter.java index 685c9431..63587dfc 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/Base64Filter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/Base64Filter.java @@ -1,7 +1,6 @@ package org.dpppt.backend.sdk.ws.insertmanager.insertionfilters; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; @@ -10,43 +9,45 @@ import org.dpppt.backend.sdk.ws.util.ValidationUtils; /** - * All keys must be valid Base64 encoded. Non valid Base64 keys are not allowed - * and are filtered out. This filter rejects the whole submitted batch of keys, - * if any of the keys is not valid Base64, as this is a client error. - * + * All keys must be valid Base64 encoded. Non valid Base64 keys are not allowed and are filtered + * out. This filter rejects the whole submitted batch of keys, if any of the keys is not valid + * Base64, as this is a client error. */ public class Base64Filter implements KeyInsertionFilter { - private final ValidationUtils validationUtils; - - public Base64Filter(ValidationUtils validationUtils) { - this.validationUtils = validationUtils; - } - - /** - * Loop through all keys and check for Base64 validity using - * {@link ValidationUtils#isValidBase64Key(String)} and count the number of - * invalid keys. If the count is > 0, a {@link KeyIsNotBase64Exception} is - * thrown which results in a client error. - */ - @Override - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) throws InsertException { - - var numberOfInvalidKeys = content.stream().filter(key -> !validationUtils.isValidBase64Key(key.getKeyData())).count(); - - if (numberOfInvalidKeys > 0) { - throw new KeyIsNotBase64Exception(); - } - return content; - } - - public class KeyIsNotBase64Exception extends InsertException { - - /** - * - */ - private static final long serialVersionUID = -918099046973553472L; - - } -} \ No newline at end of file + private final ValidationUtils validationUtils; + + public Base64Filter(ValidationUtils validationUtils) { + this.validationUtils = validationUtils; + } + + /** + * Loop through all keys and check for Base64 validity using {@link + * ValidationUtils#isValidBase64Key(String)} and count the number of invalid keys. If the count is + * > 0, a {@link KeyIsNotBase64Exception} is thrown which results in a client error. + */ + @Override + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) + throws InsertException { + + var numberOfInvalidKeys = + content.stream().filter(key -> !validationUtils.isValidBase64Key(key.getKeyData())).count(); + + if (numberOfInvalidKeys > 0) { + throw new KeyIsNotBase64Exception(); + } + return content; + } + + public class KeyIsNotBase64Exception extends InsertException { + + /** */ + private static final long serialVersionUID = -918099046973553472L; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeyInsertionFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeyInsertionFilter.java index fc64160e..7e385884 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeyInsertionFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeyInsertionFilter.java @@ -1,7 +1,6 @@ package org.dpppt.backend.sdk.ws.insertmanager.insertionfilters; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; @@ -9,29 +8,29 @@ import org.dpppt.backend.sdk.ws.insertmanager.InsertManager; import org.dpppt.backend.sdk.ws.insertmanager.OSType; -/** - * Interface for filters than can be configured in the {@link InsertManager} - * - */ +/** Interface for filters than can be configured in the {@link InsertManager} */ public interface KeyInsertionFilter { - /** - * The {@link InsertManager} goes through all configured filters and calls them - * with a list of {@link GaenKey} where the filters are applied before inserting - * into the database. - * - * @param now current timestamp - * @param content the list of new gaen keys for insertion - * @param osType the os type of the client which uploaded the keys - * @param osVersion the os version of the client which uploaded the keys - * @param appVersion the app version of the client which uploaded the keys - * @param principal the authorization context which belongs to the uploaded - * keys. Depending on the configured system, this could be a - * JWT token for example. - * @return - * @throws InsertException - */ - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) throws InsertException; - -} \ No newline at end of file + /** + * The {@link InsertManager} goes through all configured filters and calls them with a list of + * {@link GaenKey} where the filters are applied before inserting into the database. + * + * @param now current timestamp + * @param content the list of new gaen keys for insertion + * @param osType the os type of the client which uploaded the keys + * @param osVersion the os version of the client which uploaded the keys + * @param appVersion the app version of the client which uploaded the keys + * @param principal the authorization context which belongs to the uploaded keys. Depending on the + * configured system, this could be a JWT token for example. + * @return + * @throws InsertException + */ + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) + throws InsertException; +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeysMatchingJWTFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeysMatchingJWTFilter.java index bbe4c707..a831f6f2 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeysMatchingJWTFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/KeysMatchingJWTFilter.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.stream.Collectors; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.GaenUnit; import org.dpppt.backend.sdk.semver.Version; @@ -16,54 +15,60 @@ import org.dpppt.backend.sdk.ws.util.ValidationUtils.DelayedKeyDateIsInvalid; /** - * This filter compares the supplied keys with information found in the JWT - * token. During the `exposed` request, the onset date, which will be set by the - * health authority and inserted as a claim into the JWT is the lower bound for - * allowed key dates. For the `exposednextday` the JWT contains the previously - * submitted and checked `delayedKeyDate`, which is compared to the actual + * This filter compares the supplied keys with information found in the JWT token. During the + * `exposed` request, the onset date, which will be set by the health authority and inserted as a + * claim into the JWT is the lower bound for allowed key dates. For the `exposednextday` the JWT + * contains the previously submitted and checked `delayedKeyDate`, which is compared to the actual * supplied key. - * */ public class KeysMatchingJWTFilter implements KeyInsertionFilter { - private final ValidateRequest validateRequest; - private final ValidationUtils validationUtils; - - public KeysMatchingJWTFilter(ValidateRequest validateRequest, ValidationUtils utils) { - this.validateRequest = validateRequest; - this.validationUtils = utils; - } + private final ValidateRequest validateRequest; + private final ValidationUtils validationUtils; - @Override - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - return content.stream().filter(key -> { - try { - validationUtils.checkForDelayedKeyDateClaim(principal, key); - var delayedKeyDate = UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); - return isValidDelayedKeyDate(now, delayedKeyDate); - } catch (DelayedKeyDateClaimIsWrong ex) { - return isValidKeyDate(key, principal, now); - } - }).collect(Collectors.toList()); - } + public KeysMatchingJWTFilter(ValidateRequest validateRequest, ValidationUtils utils) { + this.validateRequest = validateRequest; + this.validationUtils = utils; + } - private boolean isValidKeyDate(GaenKey key, Object principal, UTCInstant now) { - try { - validateRequest.validateKeyDate(now, principal, key); - return true; - } catch (InvalidDateException | ClaimIsBeforeOnsetException es) { - return false; - } - } + @Override + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + return content.stream() + .filter( + key -> { + try { + validationUtils.checkForDelayedKeyDateClaim(principal, key); + var delayedKeyDate = + UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); + return isValidDelayedKeyDate(now, delayedKeyDate); + } catch (DelayedKeyDateClaimIsWrong ex) { + return isValidKeyDate(key, principal, now); + } + }) + .collect(Collectors.toList()); + } - private boolean isValidDelayedKeyDate(UTCInstant now, UTCInstant delayedKeyDate) { - try { - validationUtils.validateDelayedKeyDate(now, delayedKeyDate); - return true; - } catch (DelayedKeyDateIsInvalid ex) { - return false; - } - } + private boolean isValidKeyDate(GaenKey key, Object principal, UTCInstant now) { + try { + validateRequest.validateKeyDate(now, principal, key); + return true; + } catch (InvalidDateException | ClaimIsBeforeOnsetException es) { + return false; + } + } -} \ No newline at end of file + private boolean isValidDelayedKeyDate(UTCInstant now, UTCInstant delayedKeyDate) { + try { + validationUtils.validateDelayedKeyDate(now, delayedKeyDate); + return true; + } catch (DelayedKeyDateIsInvalid ex) { + return false; + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/NonFakeKeysFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/NonFakeKeysFilter.java index da269471..063f3977 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/NonFakeKeysFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/NonFakeKeysFilter.java @@ -2,27 +2,29 @@ import java.util.List; import java.util.stream.Collectors; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.insertmanager.OSType; /** - * Filters out fake keys from fake upload requests. Only Non-Fake keys are - * inserted into the database. - * + * Filters out fake keys from fake upload requests. Only Non-Fake keys are inserted into the + * database. */ public class NonFakeKeysFilter implements KeyInsertionFilter { - /** - * Loops through the list of given keys and checks the fake flag. Only return - * keys that have fake flag set to 0 - */ - @Override - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - return content.stream().filter(key -> key.getFake().equals(0)).collect(Collectors.toList()); - } - -} \ No newline at end of file + /** + * Loops through the list of given keys and checks the fake flag. Only return keys that have fake + * flag set to 0 + */ + @Override + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + return content.stream().filter(key -> key.getFake().equals(0)).collect(Collectors.toList()); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberAfterDayAfterTomorrowFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberAfterDayAfterTomorrowFilter.java index 159bd6df..c45af883 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberAfterDayAfterTomorrowFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberAfterDayAfterTomorrowFilter.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.stream.Collectors; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.GaenUnit; import org.dpppt.backend.sdk.semver.Version; @@ -10,24 +9,30 @@ import org.dpppt.backend.sdk.ws.insertmanager.OSType; /** - * Checks if a key has rolling start number after the day after tomorrow. If so, - * the key is filtered out, as this is not allowed by the system to insert keys - * too far in the future. - * + * Checks if a key has rolling start number after the day after tomorrow. If so, the key is filtered + * out, as this is not allowed by the system to insert keys too far in the future. */ public class RollingStartNumberAfterDayAfterTomorrowFilter implements KeyInsertionFilter { - /** - * Loops through all the keys and converts the rolling start number to a - * timstamp. The it is checked if the timestamp is before now + 2 days. - */ - @Override - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - return content.stream().filter(key -> { - var rollingStartNumberInstant = UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); - return rollingStartNumberInstant.isBeforeDateOf(now.plusDays(2)); - }).collect(Collectors.toList()); - } - -} \ No newline at end of file + /** + * Loops through all the keys and converts the rolling start number to a timstamp. The it is + * checked if the timestamp is before now + 2 days. + */ + @Override + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + return content.stream() + .filter( + key -> { + var rollingStartNumberInstant = + UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); + return rollingStartNumberInstant.isBeforeDateOf(now.plusDays(2)); + }) + .collect(Collectors.toList()); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberInRetentionPeriodFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberInRetentionPeriodFilter.java index 13ab8c22..2d5f52bc 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberInRetentionPeriodFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/RollingStartNumberInRetentionPeriodFilter.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.stream.Collectors; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.GaenUnit; import org.dpppt.backend.sdk.semver.Version; @@ -11,32 +10,36 @@ import org.dpppt.backend.sdk.ws.util.ValidationUtils; /** - * Checks if a key is in the configured retention period. If a key is before the - * retention period it is filtered out, as it will not be relevant for the - * system anymore. - * + * Checks if a key is in the configured retention period. If a key is before the retention period it + * is filtered out, as it will not be relevant for the system anymore. */ public class RollingStartNumberInRetentionPeriodFilter implements KeyInsertionFilter { - private final ValidationUtils validationUtils; + private final ValidationUtils validationUtils; - public RollingStartNumberInRetentionPeriodFilter(ValidationUtils validationUtils) { - this.validationUtils = validationUtils; - } + public RollingStartNumberInRetentionPeriodFilter(ValidationUtils validationUtils) { + this.validationUtils = validationUtils; + } - /** - * Loops through all the keys and converts the rolling start number to a - * timestamp. Using - * {@link ValidationUtils#isBeforeRetention(UTCInstant, UTCInstant)} only keys - * are accepted that are not before the retention period. Keys before the - * retention period are filtered out. - */ - @Override - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - return content.stream().filter(key -> { - var timestamp = UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); - return !validationUtils.isBeforeRetention(timestamp, now); - }).collect(Collectors.toList()); - } -} \ No newline at end of file + /** + * Loops through all the keys and converts the rolling start number to a timestamp. Using {@link + * ValidationUtils#isBeforeRetention(UTCInstant, UTCInstant)} only keys are accepted that are not + * before the retention period. Keys before the retention period are filtered out. + */ + @Override + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + return content.stream() + .filter( + key -> { + var timestamp = UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); + return !validationUtils.isBeforeRetention(timestamp, now); + }) + .collect(Collectors.toList()); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/ValidRollingPeriodFilter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/ValidRollingPeriodFilter.java index 11c5e030..5b4610cc 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/ValidRollingPeriodFilter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionfilters/ValidRollingPeriodFilter.java @@ -2,31 +2,30 @@ import java.util.List; import java.util.stream.Collectors; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.insertmanager.OSType; /** - * This filter checks for valid rolling period. The rolling period must always - * be in [1..144], otherwise the key is not valid and is filtered out. See - * EN documentation - * */ public class ValidRollingPeriodFilter implements KeyInsertionFilter { - /** - * Loop through given keys and filter out keys which have rolling period < 1 or - * > 144. - */ - @Override - public List filter(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - return content.stream().filter(key -> key.getRollingPeriod() >= 1 && key.getRollingPeriod() <= 144) - .collect(Collectors.toList()); - } - -} \ No newline at end of file + /** Loop through given keys and filter out keys which have rolling period < 1 or > 144. */ + @Override + public List filter( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + return content.stream() + .filter(key -> key.getRollingPeriod() >= 1 && key.getRollingPeriod() <= 144) + .collect(Collectors.toList()); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/IOSLegacyProblemRPLT144Modifier.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/IOSLegacyProblemRPLT144Modifier.java index 91a37e7a..9d255562 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/IOSLegacyProblemRPLT144Modifier.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/IOSLegacyProblemRPLT144Modifier.java @@ -1,29 +1,31 @@ package org.dpppt.backend.sdk.ws.insertmanager.insertionmodifier; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.insertmanager.OSType; /** - * This key modifier makes sure, that rolling period is always set to 144. Default - * value according to EN is 144, so just set it to that. This allows to check - * for the Google-TEKs also on iOS. Because the Rolling Proximity Identifier is - * based on the TEK and the unix epoch, this should work. The only downside is - * that iOS will not be able to optimize verification of the TEKs, because it - * will have to consider each TEK for a whole day. - * + * This key modifier makes sure, that rolling period is always set to 144. Default value according + * to EN is 144, so just set it to that. This allows to check for the Google-TEKs also on iOS. + * Because the Rolling Proximity Identifier is based on the TEK and the unix epoch, this should + * work. The only downside is that iOS will not be able to optimize verification of the TEKs, + * because it will have to consider each TEK for a whole day. */ public class IOSLegacyProblemRPLT144Modifier implements KeyInsertionModifier { - @Override - public List modify(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - for (GaenKey key : content) { - key.setRollingPeriod(144); - } - return content; - } -} \ No newline at end of file + @Override + public List modify( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + for (GaenKey key : content) { + key.setRollingPeriod(144); + } + return content; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/KeyInsertionModifier.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/KeyInsertionModifier.java index 3d5b6899..e83c1eb7 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/KeyInsertionModifier.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/KeyInsertionModifier.java @@ -1,7 +1,6 @@ package org.dpppt.backend.sdk.ws.insertmanager.insertionmodifier; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; @@ -9,29 +8,29 @@ import org.dpppt.backend.sdk.ws.insertmanager.InsertManager; import org.dpppt.backend.sdk.ws.insertmanager.OSType; -/** - * Interface for key modifiers than can be configured in the {@link InsertManager} - * - */ +/** Interface for key modifiers than can be configured in the {@link InsertManager} */ public interface KeyInsertionModifier { - /** - * The {@link InsertManager} goes through all configured key modifiers and calls them - * with a list of {@link GaenKey} where the modifieres are applied before inserting - * into the database. - * - * @param now current timestamp - * @param content the list of new gaen keys for modification - * @param osType the os type of the client which uploaded the keys - * @param osVersion the os version of the client which uploaded the keys - * @param appVersion the app version of the client which uploaded the keys - * @param principal the authorization context which belongs to the uploaded - * keys. Depending on the configured system, this could be a - * JWT token for example. - * @return - * @throws InsertException - */ - public List modify(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) throws InsertException; - -} \ No newline at end of file + /** + * The {@link InsertManager} goes through all configured key modifiers and calls them with a list + * of {@link GaenKey} where the modifieres are applied before inserting into the database. + * + * @param now current timestamp + * @param content the list of new gaen keys for modification + * @param osType the os type of the client which uploaded the keys + * @param osVersion the os version of the client which uploaded the keys + * @param appVersion the app version of the client which uploaded the keys + * @param principal the authorization context which belongs to the uploaded keys. Depending on the + * configured system, this could be a JWT token for example. + * @return + * @throws InsertException + */ + public List modify( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) + throws InsertException; +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/OldAndroid0RPModifier.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/OldAndroid0RPModifier.java index 202e38a2..731711b9 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/OldAndroid0RPModifier.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/insertmanager/insertionmodifier/OldAndroid0RPModifier.java @@ -1,7 +1,6 @@ package org.dpppt.backend.sdk.ws.insertmanager.insertionmodifier; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; @@ -10,35 +9,38 @@ import org.slf4j.LoggerFactory; /** - * Some early builds of Google's Exposure Notification API returned TEKs with - * rolling period set to '0'. According to the specification, this is invalid - * and will cause both Android and iOS to drop/ignore the key. To mitigate - * ignoring TEKs from these builds altogether, the rolling period is increased - * to '144' (one full day). This should not happen anymore and can be removed in - * the near future. Until then we are going to log whenever this happens to be - * able to monitor this problem. + * Some early builds of Google's Exposure Notification API returned TEKs with rolling period set to + * '0'. According to the specification, this is invalid and will cause both Android and iOS to + * drop/ignore the key. To mitigate ignoring TEKs from these builds altogether, the rolling period + * is increased to '144' (one full day). This should not happen anymore and can be removed in the + * near future. Until then we are going to log whenever this happens to be able to monitor this + * problem. */ public class OldAndroid0RPModifier implements KeyInsertionModifier { - - private static final Logger logger = LoggerFactory.getLogger(OldAndroid0RPModifier.class); - /** - * Loop through all the given keys and check if the rolling period is equal to - * 0. If so, set to 144. In case a key with rolling period 0 is received from an - * iOS client, an error log is printed. - */ - @Override - public List modify(UTCInstant now, List content, OSType osType, Version osVersion, - Version appVersion, Object principal) { - for (GaenKey gaenKey : content) { - if (gaenKey.getRollingPeriod().equals(0)) { - if (osType.equals(OSType.IOS)) { - logger.error("We got a rollingPeriod of 0 ({},{},{})", osType, osVersion, appVersion); - } - gaenKey.setRollingPeriod(144); - } - } - return content; - } + private static final Logger logger = LoggerFactory.getLogger(OldAndroid0RPModifier.class); -} \ No newline at end of file + /** + * Loop through all the given keys and check if the rolling period is equal to 0. If so, set to + * 144. In case a key with rolling period 0 is received from an iOS client, an error log is + * printed. + */ + @Override + public List modify( + UTCInstant now, + List content, + OSType osType, + Version osVersion, + Version appVersion, + Object principal) { + for (GaenKey gaenKey : content) { + if (gaenKey.getRollingPeriod().equals(0)) { + if (osType.equals(OSType.IOS)) { + logger.error("We got a rollingPeriod of 0 ({},{},{})", osType, osVersion, appVersion); + } + gaenKey.setRollingPeriod(144); + } + } + return content; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/interceptor/HeaderInjector.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/interceptor/HeaderInjector.java index 160ccee7..bed318cf 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/interceptor/HeaderInjector.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/interceptor/HeaderInjector.java @@ -1,26 +1,25 @@ package org.dpppt.backend.sdk.ws.interceptor; import java.util.Map; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - import org.springframework.web.servlet.HandlerInterceptor; public class HeaderInjector implements HandlerInterceptor { - private final Map headers; - public HeaderInjector(Map headers) { - this.headers = headers; - } + private final Map headers; + + public HeaderInjector(Map headers) { + this.headers = headers; + } - @Override - public boolean preHandle( - HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - if(headers != null){ - for(var header : headers.keySet()){ - response.setHeader(header, headers.get(header)); - } - } - return true; + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + if (headers != null) { + for (var header : headers.keySet()) { + response.setHeader(header, headers.get(header)); } -} \ No newline at end of file + } + return true; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/DPPTJwtDecoder.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/DPPTJwtDecoder.java index 249ac74c..e4c152d5 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/DPPTJwtDecoder.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/DPPTJwtDecoder.java @@ -10,54 +10,52 @@ package org.dpppt.backend.sdk.ws.security; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtParser; +import io.jsonwebtoken.Jwts; import java.security.PublicKey; - import org.springframework.security.oauth2.core.OAuth2TokenValidator; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtException; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.JwtParser; -import io.jsonwebtoken.Jwts; - public class DPPTJwtDecoder implements JwtDecoder { - private final JwtParser parser; - private OAuth2TokenValidator validator; - - public DPPTJwtDecoder(PublicKey publicKey) { - parser = Jwts.parserBuilder().setSigningKey(publicKey).build(); - } - - public void setJwtValidator(OAuth2TokenValidator validator) { - this.validator = validator; - } - - @Override - public Jwt decode(String token) throws JwtException { - try { - var t = parser.parseClaimsJws(token); - - var headers = t.getHeader(); - var claims = (Claims) t.getBody(); - var iat = claims.getIssuedAt(); - - var springJwt = new Jwt(token, iat.toInstant(), claims.getExpiration().toInstant(), headers, claims); - - if (validator != null) { - var validationResult = validator.validate(springJwt); - if (validationResult.hasErrors()) { - String errorMessage = ""; - for (var error : validationResult.getErrors()) { - errorMessage += error.getDescription() + "\n"; - } - throw new JwtException(errorMessage); - } - } - return springJwt; - } catch (io.jsonwebtoken.JwtException | IllegalArgumentException ex) { - throw new JwtException(ex.getMessage()); - } - - } -} \ No newline at end of file + private final JwtParser parser; + private OAuth2TokenValidator validator; + + public DPPTJwtDecoder(PublicKey publicKey) { + parser = Jwts.parserBuilder().setSigningKey(publicKey).build(); + } + + public void setJwtValidator(OAuth2TokenValidator validator) { + this.validator = validator; + } + + @Override + public Jwt decode(String token) throws JwtException { + try { + var t = parser.parseClaimsJws(token); + + var headers = t.getHeader(); + var claims = (Claims) t.getBody(); + var iat = claims.getIssuedAt(); + + var springJwt = + new Jwt(token, iat.toInstant(), claims.getExpiration().toInstant(), headers, claims); + + if (validator != null) { + var validationResult = validator.validate(springJwt); + if (validationResult.hasErrors()) { + String errorMessage = ""; + for (var error : validationResult.getErrors()) { + errorMessage += error.getDescription() + "\n"; + } + throw new JwtException(errorMessage); + } + } + return springJwt; + } catch (io.jsonwebtoken.JwtException | IllegalArgumentException ex) { + throw new JwtException(ex.getMessage()); + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTClaimSetConverter.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTClaimSetConverter.java index 218d0ddd..ab99d7a1 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTClaimSetConverter.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTClaimSetConverter.java @@ -12,23 +12,23 @@ import java.util.Collections; import java.util.Map; - import org.springframework.core.convert.converter.Converter; import org.springframework.security.oauth2.jwt.MappedJwtClaimSetConverter; public class JWTClaimSetConverter implements Converter, Map> { - private final MappedJwtClaimSetConverter delegate = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); + private final MappedJwtClaimSetConverter delegate = + MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap()); - public Map convert(Map claims) { - Map convertedClaims = this.delegate.convert(claims); - if(convertedClaims.containsKey("onset")) { - convertedClaims.put("onset", convertedClaims.get("onset")); - } - if(convertedClaims.containsKey("delayedKeyDate")) { - convertedClaims.put("delayedKeyDate", convertedClaims.get("delayedKeyDate")); - } + public Map convert(Map claims) { + Map convertedClaims = this.delegate.convert(claims); + if (convertedClaims.containsKey("onset")) { + convertedClaims.put("onset", convertedClaims.get("onset")); + } + if (convertedClaims.containsKey("delayedKeyDate")) { + convertedClaims.put("delayedKeyDate", convertedClaims.get("delayedKeyDate")); + } - return convertedClaims; - } -} \ No newline at end of file + return convertedClaims; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidateRequest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidateRequest.java index 1806aec3..8cdc74b1 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidateRequest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidateRequest.java @@ -17,68 +17,68 @@ import org.springframework.security.oauth2.jwt.Jwt; public class JWTValidateRequest implements ValidateRequest { - private final ValidationUtils validationUtils; - public JWTValidateRequest(ValidationUtils validationUtils) { - this.validationUtils = validationUtils; - } + private final ValidationUtils validationUtils; - @Override - public boolean isValid(Object authObject) { - if (authObject instanceof Jwt) { - Jwt token = (Jwt) authObject; - return token.containsClaim("scope") && token.getClaim("scope").equals("exposed"); - } - return false; - } + public JWTValidateRequest(ValidationUtils validationUtils) { + this.validationUtils = validationUtils; + } - @Override - public long validateKeyDate(UTCInstant now, Object authObject, Object others) throws InvalidDateException, ClaimIsBeforeOnsetException { - if (authObject instanceof Jwt) { - Jwt token = (Jwt) authObject; - var jwtKeyDate = UTCInstant.parseDate(token.getClaim("onset")); - if (others instanceof ExposeeRequest) { - ExposeeRequest request = (ExposeeRequest) others; - var requestKeyDate = UTCInstant.ofEpochMillis(request.getKeyDate()); - if (!validationUtils.isDateInRange(requestKeyDate, now)) - { - throw new InvalidDateException(); - } else if (requestKeyDate.isBeforeEpochMillisOf(jwtKeyDate)) { - throw new ClaimIsBeforeOnsetException(); - } - jwtKeyDate = UTCInstant.ofEpochMillis(request.getKeyDate()); - } - return jwtKeyDate.getTimestamp(); - } - throw new IllegalArgumentException(); - } + @Override + public boolean isValid(Object authObject) { + if (authObject instanceof Jwt) { + Jwt token = (Jwt) authObject; + return token.containsClaim("scope") && token.getClaim("scope").equals("exposed"); + } + return false; + } - @Override - public boolean isFakeRequest(Object authObject, Object others) { - if (authObject instanceof Jwt && others instanceof ExposeeRequest) { - Jwt token = (Jwt) authObject; - ExposeeRequest request = (ExposeeRequest) others; - boolean fake = false; - if (token.containsClaim("fake") && token.getClaimAsString("fake").equals("1")) { - fake = true; - } - if (request.isFake() == 1) { - fake = true; - } - return fake; - } - if(authObject instanceof Jwt && others instanceof ExposeeRequestList) { - Jwt token = (Jwt) authObject; - ExposeeRequestList request = (ExposeeRequestList) others; - boolean fake = false; - if (token.containsClaim("fake") && token.getClaimAsString("fake").equals("1")) { - fake = true; - } - if (request.isFake() == 1) { - fake = true; - } - return fake; - } - throw new IllegalArgumentException(); - } + @Override + public long validateKeyDate(UTCInstant now, Object authObject, Object others) + throws InvalidDateException, ClaimIsBeforeOnsetException { + if (authObject instanceof Jwt) { + Jwt token = (Jwt) authObject; + var jwtKeyDate = UTCInstant.parseDate(token.getClaim("onset")); + if (others instanceof ExposeeRequest) { + ExposeeRequest request = (ExposeeRequest) others; + var requestKeyDate = UTCInstant.ofEpochMillis(request.getKeyDate()); + if (!validationUtils.isDateInRange(requestKeyDate, now)) { + throw new InvalidDateException(); + } else if (requestKeyDate.isBeforeEpochMillisOf(jwtKeyDate)) { + throw new ClaimIsBeforeOnsetException(); + } + jwtKeyDate = UTCInstant.ofEpochMillis(request.getKeyDate()); + } + return jwtKeyDate.getTimestamp(); + } + throw new IllegalArgumentException(); + } -} \ No newline at end of file + @Override + public boolean isFakeRequest(Object authObject, Object others) { + if (authObject instanceof Jwt && others instanceof ExposeeRequest) { + Jwt token = (Jwt) authObject; + ExposeeRequest request = (ExposeeRequest) others; + boolean fake = false; + if (token.containsClaim("fake") && token.getClaimAsString("fake").equals("1")) { + fake = true; + } + if (request.isFake() == 1) { + fake = true; + } + return fake; + } + if (authObject instanceof Jwt && others instanceof ExposeeRequestList) { + Jwt token = (Jwt) authObject; + ExposeeRequestList request = (ExposeeRequestList) others; + boolean fake = false; + if (token.containsClaim("fake") && token.getClaimAsString("fake").equals("1")) { + fake = true; + } + if (request.isFake() == 1) { + fake = true; + } + return fake; + } + throw new IllegalArgumentException(); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidator.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidator.java index 02f0e9ba..95c2c2e6 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidator.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/JWTValidator.java @@ -11,7 +11,6 @@ package org.dpppt.backend.sdk.ws.security; import java.time.Duration; - import org.dpppt.backend.sdk.data.RedeemDataService; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.OAuth2ErrorCodes; @@ -19,34 +18,33 @@ import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.security.oauth2.jwt.Jwt; - public class JWTValidator implements OAuth2TokenValidator { - public static final String UUID_CLAIM = "jti"; + public static final String UUID_CLAIM = "jti"; + private RedeemDataService dataService; + private Duration maxJwtValidity; - private RedeemDataService dataService; - private Duration maxJwtValidity; + public JWTValidator(RedeemDataService dataService, Duration maxJwtValidity) { + this.dataService = dataService; + this.maxJwtValidity = maxJwtValidity; + } - public JWTValidator(RedeemDataService dataService, Duration maxJwtValidity) { - this.dataService = dataService; - this.maxJwtValidity = maxJwtValidity; + @Override + public OAuth2TokenValidatorResult validate(Jwt token) { + if (token.containsClaim("fake") && token.getClaimAsString("fake").equals("1")) { + // it is a fakte token, but we still assume it is valid + return OAuth2TokenValidatorResult.success(); } - - @Override - public OAuth2TokenValidatorResult validate(Jwt token) { - if(token.containsClaim("fake") && token.getClaimAsString("fake").equals("1")){ - //it is a fakte token, but we still assume it is valid - return OAuth2TokenValidatorResult.success(); - } - //make sure the token has an expiration date AND is not valid for more than maxJwtValidity - if (token.getExpiresAt() == null || token.getIssuedAt().plus(maxJwtValidity).isBefore(token.getExpiresAt())) { - return OAuth2TokenValidatorResult.failure(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST)); - } - if(token.containsClaim(UUID_CLAIM) && this.dataService.checkAndInsertPublishUUID(token.getClaim(UUID_CLAIM))) { - return OAuth2TokenValidatorResult.success(); - } - return OAuth2TokenValidatorResult.failure(new OAuth2Error(OAuth2ErrorCodes.INVALID_SCOPE)); + // make sure the token has an expiration date AND is not valid for more than maxJwtValidity + if (token.getExpiresAt() == null + || token.getIssuedAt().plus(maxJwtValidity).isBefore(token.getExpiresAt())) { + return OAuth2TokenValidatorResult.failure(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST)); } - -} \ No newline at end of file + if (token.containsClaim(UUID_CLAIM) + && this.dataService.checkAndInsertPublishUUID(token.getClaim(UUID_CLAIM))) { + return OAuth2TokenValidatorResult.success(); + } + return OAuth2TokenValidatorResult.failure(new OAuth2Error(OAuth2ErrorCodes.INVALID_SCOPE)); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/KeyVault.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/KeyVault.java index 67f8bb47..a1c37658 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/KeyVault.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/KeyVault.java @@ -30,220 +30,218 @@ import java.util.Base64; import java.util.HashMap; import java.util.List; - import org.bouncycastle.util.io.pem.PemReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class KeyVault { - private static final Logger logger = LoggerFactory.getLogger(KeyVault.class); - private final HashMap pairVault = new HashMap<>(); - - private final static List externalPublicProviders = new ArrayList<>(); - private final static List externalPrivateProviders = new ArrayList<>(); - - public static boolean registerNewPublicEncodingProvider(Class clazz, String functionName) { - try { - var method = clazz.getDeclaredMethod(functionName, String.class, String.class); - if (!Modifier.isStatic(method.getModifiers())) - return false; - if (!method.getReturnType().isAssignableFrom(PublicKey.class)) - return false; - externalPublicProviders.add(method); - return true; - } catch (NoSuchMethodException | SecurityException e) { - logger.error("Exception registering new public encoding provider", e); - return false; - } - } - - public static boolean registerNewPrivateEncodingProvider(Class clazz, String functionName) { - try { - var method = clazz.getDeclaredMethod(functionName, String.class, String.class); - if (!Modifier.isStatic(method.getModifiers())) - return false; - if (!method.getReturnType().isAssignableFrom(PrivateKey.class)) - return false; - - externalPrivateProviders.add(method); - return true; - } catch (NoSuchMethodException | SecurityException e) { - logger.error("Exception registering new private encoding provider", e); - return false; - } - } - - public static void registerDefaultProviders() { - // private providers - registerNewPrivateEncodingProvider(KeyVault.class, "loadPrivateKeyFromJavaEncoding"); - registerNewPrivateEncodingProvider(KeyVault.class, "loadPrivateKeyFromPem"); - - // public providers - registerNewPublicEncodingProvider(KeyVault.class, "loadPublicKeyFromJavaEncoding"); - registerNewPublicEncodingProvider(KeyVault.class, "loadPublicKeyFromPem"); - registerNewPublicEncodingProvider(KeyVault.class, "loadPublicKeyFromX509Certificate"); - } - - public KeyVault(KeyVaultEntry... entries) - throws PrivateKeyNoSuitableEncodingFoundException, PublicKeyNoSuitableEncodingFoundException { - registerDefaultProviders(); - - for (KeyVaultEntry entry : entries) { - var kp = loadKeyPairFromString(entry); - this.pairVault.put(entry.pairKey, kp); - } - } - - public KeyVault(KeyVaultKeyPair... pairs) { - registerDefaultProviders(); - for (var pair : pairs) { - this.pairVault.put(pair.pairKey, pair.keyPair); - } - } - - public KeyPair get(String key) { - return this.pairVault.get(key); - } - - public void add(KeyVaultEntry entry) - throws PrivateKeyNoSuitableEncodingFoundException, PublicKeyNoSuitableEncodingFoundException { - var kp = loadKeyPairFromString(entry); - if (kp != null) { - this.pairVault.put(entry.pairKey, kp); - } - } - - public void add(KeyVaultKeyPair pair) { - this.pairVault.put(pair.pairKey, pair.keyPair); - } - - private KeyPair loadKeyPairFromString(KeyVaultEntry entry) - throws PrivateKeyNoSuitableEncodingFoundException, PublicKeyNoSuitableEncodingFoundException { - PrivateKey privateKey = loadPrivateKey(entry.privatePart, entry.algorithm); - PublicKey publicKey = loadPublicKey(entry.publicPart, entry.algorithm); - - return new KeyPair(publicKey, privateKey); - } - - public static PrivateKey loadPrivateKey(String privatePart, String algorithm) - throws PrivateKeyNoSuitableEncodingFoundException { - PrivateKey key = null; - for (var provider : externalPrivateProviders) { - try { - key = (PrivateKey) provider.invoke(null, privatePart, algorithm); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - logger.warn("Could not decode key as {}", algorithm); - } - if (key != null) { - return key; - } - } - throw new PrivateKeyNoSuitableEncodingFoundException(); - } - - public static PrivateKey loadPrivateKeyFromJavaEncoding(String privatePart, String algorithm) { - try { - return KeyFactory.getInstance(algorithm) - .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privatePart))); - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - logger.warn("Exception loading private key from java encoding ", e); - return null; - } - } - - public static PrivateKey loadPrivateKeyFromPem(String privatePart, String algorithm) { - try { - var reader = new StringReader(privatePart); - var readerPem = new PemReader(reader); - var obj = readerPem.readPemObject(); - readerPem.close(); - return KeyFactory.getInstance(algorithm).generatePrivate(new PKCS8EncodedKeySpec(obj.getContent())); - } catch (InvalidKeySpecException | NoSuchAlgorithmException | IOException e) { - logger.warn("Exception loading private key from PEM ", e); - return null; - } - } - - public static PublicKey loadPublicKey(String publicPart, String algorithm) - throws PublicKeyNoSuitableEncodingFoundException { - PublicKey key = null; - for (var provider : externalPublicProviders) { - try { - key = (PublicKey) provider.invoke(null, publicPart, algorithm); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - logger.warn("Could not decode key as {}", algorithm); - } - if (key != null) { - return key; - } - } - throw new PublicKeyNoSuitableEncodingFoundException(); - } - - public static PublicKey loadPublicKeyFromJavaEncoding(String publicPart, String algorithm) { - try { - return KeyFactory.getInstance(algorithm) - .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicPart))); - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - logger.warn("Exception loading public key from java encoding", e); - return null; - } - } - - public static PublicKey loadPublicKeyFromPem(String publicPart, String algorithm) { - try { - var reader = new StringReader(publicPart); - var readerPem = new PemReader(reader); - var obj = readerPem.readPemObject(); - readerPem.close(); - return KeyFactory.getInstance(algorithm).generatePublic(new X509EncodedKeySpec(obj.getContent())); - } catch (InvalidKeySpecException | NoSuchAlgorithmException | IOException e) { - logger.warn("Exception loading public key from PEM", e); - return null; - } - } - - public static PublicKey loadPublicKeyFromX509Certificate(String publicPart, String algorithm) { - try { - return CertificateFactory.getInstance("X.509") - .generateCertificate(new ByteArrayInputStream(publicPart.getBytes())).getPublicKey(); - } catch (CertificateException e) { - logger.warn("Exception loading public key from X509 certificate", e); - return null; - } - } - - public static class KeyVaultEntry { - private final String pairKey; - private final String algorithm; - private final String privatePart; - private final String publicPart; - - public KeyVaultEntry(String pairKey, String privatePart, String publicPart, String algorithm) { - this.pairKey = pairKey; - this.privatePart = privatePart; - this.publicPart = publicPart; - this.algorithm = algorithm; - } - } - - public static class KeyVaultKeyPair { - private final String pairKey; - private final KeyPair keyPair; - - public KeyVaultKeyPair(String pairKey, KeyPair keyPair) { - this.pairKey = pairKey; - this.keyPair = keyPair; - } - } - - public static class PrivateKeyNoSuitableEncodingFoundException extends Exception { - - private static final long serialVersionUID = 1623575762871663224L; - } - - public static class PublicKeyNoSuitableEncodingFoundException extends Exception { - - private static final long serialVersionUID = -1286647270505904967L; - } + private static final Logger logger = LoggerFactory.getLogger(KeyVault.class); + private final HashMap pairVault = new HashMap<>(); + + private static final List externalPublicProviders = new ArrayList<>(); + private static final List externalPrivateProviders = new ArrayList<>(); + + public static boolean registerNewPublicEncodingProvider(Class clazz, String functionName) { + try { + var method = clazz.getDeclaredMethod(functionName, String.class, String.class); + if (!Modifier.isStatic(method.getModifiers())) return false; + if (!method.getReturnType().isAssignableFrom(PublicKey.class)) return false; + externalPublicProviders.add(method); + return true; + } catch (NoSuchMethodException | SecurityException e) { + logger.error("Exception registering new public encoding provider", e); + return false; + } + } + + public static boolean registerNewPrivateEncodingProvider(Class clazz, String functionName) { + try { + var method = clazz.getDeclaredMethod(functionName, String.class, String.class); + if (!Modifier.isStatic(method.getModifiers())) return false; + if (!method.getReturnType().isAssignableFrom(PrivateKey.class)) return false; + + externalPrivateProviders.add(method); + return true; + } catch (NoSuchMethodException | SecurityException e) { + logger.error("Exception registering new private encoding provider", e); + return false; + } + } + + public static void registerDefaultProviders() { + // private providers + registerNewPrivateEncodingProvider(KeyVault.class, "loadPrivateKeyFromJavaEncoding"); + registerNewPrivateEncodingProvider(KeyVault.class, "loadPrivateKeyFromPem"); + + // public providers + registerNewPublicEncodingProvider(KeyVault.class, "loadPublicKeyFromJavaEncoding"); + registerNewPublicEncodingProvider(KeyVault.class, "loadPublicKeyFromPem"); + registerNewPublicEncodingProvider(KeyVault.class, "loadPublicKeyFromX509Certificate"); + } + + public KeyVault(KeyVaultEntry... entries) + throws PrivateKeyNoSuitableEncodingFoundException, PublicKeyNoSuitableEncodingFoundException { + registerDefaultProviders(); + + for (KeyVaultEntry entry : entries) { + var kp = loadKeyPairFromString(entry); + this.pairVault.put(entry.pairKey, kp); + } + } + + public KeyVault(KeyVaultKeyPair... pairs) { + registerDefaultProviders(); + for (var pair : pairs) { + this.pairVault.put(pair.pairKey, pair.keyPair); + } + } + + public KeyPair get(String key) { + return this.pairVault.get(key); + } + + public void add(KeyVaultEntry entry) + throws PrivateKeyNoSuitableEncodingFoundException, PublicKeyNoSuitableEncodingFoundException { + var kp = loadKeyPairFromString(entry); + if (kp != null) { + this.pairVault.put(entry.pairKey, kp); + } + } + + public void add(KeyVaultKeyPair pair) { + this.pairVault.put(pair.pairKey, pair.keyPair); + } + + private KeyPair loadKeyPairFromString(KeyVaultEntry entry) + throws PrivateKeyNoSuitableEncodingFoundException, PublicKeyNoSuitableEncodingFoundException { + PrivateKey privateKey = loadPrivateKey(entry.privatePart, entry.algorithm); + PublicKey publicKey = loadPublicKey(entry.publicPart, entry.algorithm); + + return new KeyPair(publicKey, privateKey); + } + + public static PrivateKey loadPrivateKey(String privatePart, String algorithm) + throws PrivateKeyNoSuitableEncodingFoundException { + PrivateKey key = null; + for (var provider : externalPrivateProviders) { + try { + key = (PrivateKey) provider.invoke(null, privatePart, algorithm); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + logger.warn("Could not decode key as {}", algorithm); + } + if (key != null) { + return key; + } + } + throw new PrivateKeyNoSuitableEncodingFoundException(); + } + + public static PrivateKey loadPrivateKeyFromJavaEncoding(String privatePart, String algorithm) { + try { + return KeyFactory.getInstance(algorithm) + .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privatePart))); + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + logger.warn("Exception loading private key from java encoding ", e); + return null; + } + } + + public static PrivateKey loadPrivateKeyFromPem(String privatePart, String algorithm) { + try { + var reader = new StringReader(privatePart); + var readerPem = new PemReader(reader); + var obj = readerPem.readPemObject(); + readerPem.close(); + return KeyFactory.getInstance(algorithm) + .generatePrivate(new PKCS8EncodedKeySpec(obj.getContent())); + } catch (InvalidKeySpecException | NoSuchAlgorithmException | IOException e) { + logger.warn("Exception loading private key from PEM ", e); + return null; + } + } + + public static PublicKey loadPublicKey(String publicPart, String algorithm) + throws PublicKeyNoSuitableEncodingFoundException { + PublicKey key = null; + for (var provider : externalPublicProviders) { + try { + key = (PublicKey) provider.invoke(null, publicPart, algorithm); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + logger.warn("Could not decode key as {}", algorithm); + } + if (key != null) { + return key; + } + } + throw new PublicKeyNoSuitableEncodingFoundException(); + } + + public static PublicKey loadPublicKeyFromJavaEncoding(String publicPart, String algorithm) { + try { + return KeyFactory.getInstance(algorithm) + .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicPart))); + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + logger.warn("Exception loading public key from java encoding", e); + return null; + } + } + + public static PublicKey loadPublicKeyFromPem(String publicPart, String algorithm) { + try { + var reader = new StringReader(publicPart); + var readerPem = new PemReader(reader); + var obj = readerPem.readPemObject(); + readerPem.close(); + return KeyFactory.getInstance(algorithm) + .generatePublic(new X509EncodedKeySpec(obj.getContent())); + } catch (InvalidKeySpecException | NoSuchAlgorithmException | IOException e) { + logger.warn("Exception loading public key from PEM", e); + return null; + } + } + + public static PublicKey loadPublicKeyFromX509Certificate(String publicPart, String algorithm) { + try { + return CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(publicPart.getBytes())) + .getPublicKey(); + } catch (CertificateException e) { + logger.warn("Exception loading public key from X509 certificate", e); + return null; + } + } + + public static class KeyVaultEntry { + private final String pairKey; + private final String algorithm; + private final String privatePart; + private final String publicPart; + + public KeyVaultEntry(String pairKey, String privatePart, String publicPart, String algorithm) { + this.pairKey = pairKey; + this.privatePart = privatePart; + this.publicPart = publicPart; + this.algorithm = algorithm; + } + } + + public static class KeyVaultKeyPair { + private final String pairKey; + private final KeyPair keyPair; + + public KeyVaultKeyPair(String pairKey, KeyPair keyPair) { + this.pairKey = pairKey; + this.keyPair = keyPair; + } + } + + public static class PrivateKeyNoSuitableEncodingFoundException extends Exception { + + private static final long serialVersionUID = 1623575762871663224L; + } + + public static class PublicKeyNoSuitableEncodingFoundException extends Exception { + + private static final long serialVersionUID = -1286647270505904967L; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/NoValidateRequest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/NoValidateRequest.java index e04fdc27..fa86570f 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/NoValidateRequest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/NoValidateRequest.java @@ -17,49 +17,52 @@ import org.dpppt.backend.sdk.ws.util.ValidationUtils; public class NoValidateRequest implements ValidateRequest { - private final ValidationUtils validationUtils; - public NoValidateRequest(ValidationUtils validationUtils){ - this.validationUtils = validationUtils; - } - @Override - public boolean isValid(Object authObject) { - return true; - } + private final ValidationUtils validationUtils; - @Override - public long validateKeyDate(UTCInstant now, Object authObject, Object others) throws ClaimIsBeforeOnsetException,InvalidDateException { - if (others instanceof ExposeeRequest) { - ExposeeRequest request = ((ExposeeRequest) others); - var requestKeyDate = new UTCInstant(request.getKeyDate()); - checkDateIsInBounds(requestKeyDate, now); - return request.getKeyDate(); - } - if (others instanceof GaenKey) { - GaenKey key = ((GaenKey) others); - var requestKeyDate = UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); - checkDateIsInBounds(requestKeyDate, now); - return requestKeyDate.getTimestamp(); - } - throw new IllegalArgumentException(); - } + public NoValidateRequest(ValidationUtils validationUtils) { + this.validationUtils = validationUtils; + } - private void checkDateIsInBounds(UTCInstant requestKeyDate, UTCInstant now) throws InvalidDateException { - if (!validationUtils.isDateInRange(requestKeyDate, now)) { - throw new InvalidDateException(); - } - } + @Override + public boolean isValid(Object authObject) { + return true; + } - @Override - public boolean isFakeRequest(Object authObject, Object others) { - if (others instanceof ExposeeRequest) { - ExposeeRequest request = ((ExposeeRequest) others); - return request.isFake() == 1; - } - if (others instanceof GaenKey) { - GaenKey request = ((GaenKey) others); - return request.getFake() == 1; - } - throw new IllegalArgumentException(); - } + @Override + public long validateKeyDate(UTCInstant now, Object authObject, Object others) + throws ClaimIsBeforeOnsetException, InvalidDateException { + if (others instanceof ExposeeRequest) { + ExposeeRequest request = ((ExposeeRequest) others); + var requestKeyDate = new UTCInstant(request.getKeyDate()); + checkDateIsInBounds(requestKeyDate, now); + return request.getKeyDate(); + } + if (others instanceof GaenKey) { + GaenKey key = ((GaenKey) others); + var requestKeyDate = UTCInstant.of(key.getRollingStartNumber(), GaenUnit.TenMinutes); + checkDateIsInBounds(requestKeyDate, now); + return requestKeyDate.getTimestamp(); + } + throw new IllegalArgumentException(); + } -} \ No newline at end of file + private void checkDateIsInBounds(UTCInstant requestKeyDate, UTCInstant now) + throws InvalidDateException { + if (!validationUtils.isDateInRange(requestKeyDate, now)) { + throw new InvalidDateException(); + } + } + + @Override + public boolean isFakeRequest(Object authObject, Object others) { + if (others instanceof ExposeeRequest) { + ExposeeRequest request = ((ExposeeRequest) others); + return request.isFake() == 1; + } + if (others instanceof GaenKey) { + GaenKey request = ((GaenKey) others); + return request.getFake() == 1; + } + throw new IllegalArgumentException(); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/ValidateRequest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/ValidateRequest.java index 148cc9e8..60fdbf89 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/ValidateRequest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/ValidateRequest.java @@ -14,25 +14,30 @@ public interface ValidateRequest { - public boolean isValid(Object authObject) throws WrongScopeException; - - // authObject is the Principal, given from Springboot - // others can be any object (currently it is the ExposeeRequest, since we want - // to allow no auth without the jwt profile) - public long validateKeyDate(UTCInstant now, Object authObject, Object others) throws ClaimIsBeforeOnsetException, InvalidDateException; - public boolean isFakeRequest(Object authObject, Object others); - - public class InvalidDateException extends Exception { - - private static final long serialVersionUID = 5886601055826066148L; - } - public class ClaimDoesNotMatchKeyDateException extends Exception { - private static final long serialVersionUID = 5886601055826066149L; - } - public class ClaimIsBeforeOnsetException extends Exception { - private static final long serialVersionUID = 5886601055826066150L; - } - public class WrongScopeException extends Exception { - private static final long serialVersionUID = 5886601055826066151L; - } + public boolean isValid(Object authObject) throws WrongScopeException; + + // authObject is the Principal, given from Springboot + // others can be any object (currently it is the ExposeeRequest, since we want + // to allow no auth without the jwt profile) + public long validateKeyDate(UTCInstant now, Object authObject, Object others) + throws ClaimIsBeforeOnsetException, InvalidDateException; + + public boolean isFakeRequest(Object authObject, Object others); + + public class InvalidDateException extends Exception { + + private static final long serialVersionUID = 5886601055826066148L; + } + + public class ClaimDoesNotMatchKeyDateException extends Exception { + private static final long serialVersionUID = 5886601055826066149L; + } + + public class ClaimIsBeforeOnsetException extends Exception { + private static final long serialVersionUID = 5886601055826066150L; + } + + public class WrongScopeException extends Exception { + private static final long serialVersionUID = 5886601055826066151L; + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/gaen/JWTValidateRequest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/gaen/JWTValidateRequest.java index d713607e..17aadccd 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/gaen/JWTValidateRequest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/gaen/JWTValidateRequest.java @@ -18,54 +18,56 @@ import org.springframework.security.oauth2.jwt.Jwt; public class JWTValidateRequest implements ValidateRequest { - - public JWTValidateRequest(ValidationUtils validationUtils) {} - @Override - public boolean isValid(Object authObject) throws WrongScopeException { - if (authObject instanceof Jwt) { - Jwt token = (Jwt) authObject; - if(Boolean.TRUE.equals(token.containsClaim("scope")) && token.getClaim("scope").equals("exposed")) { - return true; - } - throw new WrongScopeException(); - } - return false; - } + public JWTValidateRequest(ValidationUtils validationUtils) {} - @Override - public long validateKeyDate(UTCInstant now, Object authObject, Object others) throws ClaimIsBeforeOnsetException { - if (authObject instanceof Jwt) { - Jwt token = (Jwt) authObject; - var jwtKeyDate = UTCInstant.parseDate(token.getClaim("onset")); - if (others instanceof GaenKey) { - GaenKey request = (GaenKey) others; - var keyDate = UTCInstant.of(request.getRollingStartNumber(), GaenUnit.TenMinutes); - if (keyDate.isBeforeEpochMillisOf(jwtKeyDate)) { - throw new ClaimIsBeforeOnsetException(); - } - jwtKeyDate = keyDate; - } - return jwtKeyDate.getTimestamp(); - } - throw new IllegalArgumentException(); - } + @Override + public boolean isValid(Object authObject) throws WrongScopeException { + if (authObject instanceof Jwt) { + Jwt token = (Jwt) authObject; + if (Boolean.TRUE.equals(token.containsClaim("scope")) + && token.getClaim("scope").equals("exposed")) { + return true; + } + throw new WrongScopeException(); + } + return false; + } - @Override - public boolean isFakeRequest(Object authObject, Object others) { - if (authObject instanceof Jwt && others instanceof GaenKey) { - Jwt token = (Jwt) authObject; - GaenKey request = (GaenKey) others; - boolean fake = false; - if (Boolean.TRUE.equals(token.containsClaim("fake")) && token.getClaimAsString("fake").equals("1")) { - fake = true; - } - if (request.getFake() == 1) { - fake = true; - } - return fake; - } - throw new IllegalArgumentException(); - } + @Override + public long validateKeyDate(UTCInstant now, Object authObject, Object others) + throws ClaimIsBeforeOnsetException { + if (authObject instanceof Jwt) { + Jwt token = (Jwt) authObject; + var jwtKeyDate = UTCInstant.parseDate(token.getClaim("onset")); + if (others instanceof GaenKey) { + GaenKey request = (GaenKey) others; + var keyDate = UTCInstant.of(request.getRollingStartNumber(), GaenUnit.TenMinutes); + if (keyDate.isBeforeEpochMillisOf(jwtKeyDate)) { + throw new ClaimIsBeforeOnsetException(); + } + jwtKeyDate = keyDate; + } + return jwtKeyDate.getTimestamp(); + } + throw new IllegalArgumentException(); + } -} \ No newline at end of file + @Override + public boolean isFakeRequest(Object authObject, Object others) { + if (authObject instanceof Jwt && others instanceof GaenKey) { + Jwt token = (Jwt) authObject; + GaenKey request = (GaenKey) others; + boolean fake = false; + if (Boolean.TRUE.equals(token.containsClaim("fake")) + && token.getClaimAsString("fake").equals("1")) { + fake = true; + } + if (request.getFake() == 1) { + fake = true; + } + return fake; + } + throw new IllegalArgumentException(); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/ProtoSignature.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/ProtoSignature.java index 09d2ba67..26d51067 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/ProtoSignature.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/ProtoSignature.java @@ -9,6 +9,7 @@ */ package org.dpppt.backend.sdk.ws.security.signature; +import com.google.protobuf.ByteString; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.InvalidKeyException; @@ -27,222 +28,242 @@ import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.GaenUnit; import org.dpppt.backend.sdk.model.gaen.proto.TemporaryExposureKeyFormat; import org.dpppt.backend.sdk.model.gaen.proto.TemporaryExposureKeyFormat.SignatureInfo; import org.dpppt.backend.sdk.utils.UTCInstant; -import com.google.protobuf.ByteString; - public class ProtoSignature { - private static final byte[] EXPORT_MAGIC = { 0x45, 0x4B, 0x20, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x76, 0x31, - 0x20, 0x20, 0x20, 0x20 }; // "EK Export v1 " - - private final String algorithm; - private final KeyPair keyPair; - private final String appBundleId; - private final String apkPackage; - private final String keyVersion; - private final String keyVerificationId; - private final String gaenRegion; - private final Duration releaseBucketDuration; - - public Map oidToJavaSignature = Map.of("1.2.840.10045.4.3.2", "SHA256withECDSA"); - - public ProtoSignature(String algorithm, KeyPair keyPair, String appBundleId, String apkPackage, String keyVersion, - String keyVerificationId, String gaenRegion, Duration releaseBucketDuration) { - this.keyPair = keyPair; - this.algorithm = algorithm.trim(); - this.appBundleId = appBundleId; - this.apkPackage = apkPackage; - this.keyVerificationId = keyVerificationId; - this.keyVersion = keyVersion; - this.gaenRegion = gaenRegion; - this.releaseBucketDuration = releaseBucketDuration; - } - - /** - * Creates a ZIP file containing the given keys and the corresponding signature. - * - * @param keys - * @return - * @throws IOException - * @throws InvalidKeyException - * @throws SignatureException - * @throws NoSuchAlgorithmException - */ - public ProtoSignatureWrapper getPayload(List keys) - throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { - if(keys.isEmpty()) { - throw new IOException("Keys should not be empty"); - } - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - ZipOutputStream zip = new ZipOutputStream(byteOut); - ByteArrayOutputStream hashOut = new ByteArrayOutputStream(); - var digest = MessageDigest.getInstance("SHA256"); - var keyDate = Duration.of(keys.get(0).getRollingStartNumber(), GaenUnit.TenMinutes); - var protoFile = getProtoKey(keys, keyDate); - - zip.putNextEntry(new ZipEntry("export.bin")); - byte[] protoFileBytes = protoFile.toByteArray(); - byte[] exportBin = new byte[EXPORT_MAGIC.length + protoFileBytes.length]; - System.arraycopy(EXPORT_MAGIC, 0, exportBin, 0, EXPORT_MAGIC.length); - System.arraycopy(protoFileBytes, 0, exportBin, EXPORT_MAGIC.length, protoFileBytes.length); - zip.write(exportBin); - zip.closeEntry(); - - var signatureList = getSignatureObject(exportBin); - digest.update(exportBin); - digest.update(keyPair.getPublic().getEncoded()); - hashOut.write(digest.digest()); - - byte[] exportSig = signatureList.toByteArray(); - zip.putNextEntry(new ZipEntry("export.sig")); - zip.write(exportSig); - zip.closeEntry(); - - zip.flush(); - zip.close(); - byteOut.flush(); - byteOut.close(); - hashOut.flush(); - hashOut.close(); - - return new ProtoSignatureWrapper(hashOut.toByteArray(), byteOut.toByteArray()); - } - - private byte[] sign(byte[] data) throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { - Signature signature = Signature.getInstance(oidToJavaSignature.get(algorithm)); - signature.initSign(keyPair.getPrivate()); - signature.update(data); - return signature.sign(); - } - - private TemporaryExposureKeyFormat.TEKSignatureList getSignatureObject(byte[] keyExport) - throws InvalidKeyException, SignatureException, NoSuchAlgorithmException { - byte[] exportSignature = sign(keyExport); - var signatureList = TemporaryExposureKeyFormat.TEKSignatureList.newBuilder(); - var theSignature = TemporaryExposureKeyFormat.TEKSignature.newBuilder(); - theSignature.setSignatureInfo(tekSignature()).setSignature(ByteString.copyFrom(exportSignature)).setBatchNum(1) - .setBatchSize(1); - signatureList.addSignatures(theSignature); - return signatureList.build(); - } - - private SignatureInfo tekSignature() { - var tekSignature = TemporaryExposureKeyFormat.SignatureInfo.newBuilder(); - tekSignature.setAppBundleId(appBundleId).setVerificationKeyVersion(keyVersion) - .setVerificationKeyId(keyVerificationId).setSignatureAlgorithm(algorithm); - return tekSignature.build(); - } - - public PublicKey getPublicKey() { - return keyPair.getPublic(); - } - - public byte[] getPayload(Map> groupedBuckets) - throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { - ByteArrayOutputStream byteOutCollection = new ByteArrayOutputStream(); - ZipOutputStream zipCollection = new ZipOutputStream(byteOutCollection); - - for (var keyGroup : groupedBuckets.entrySet()) { - var keys = keyGroup.getValue(); - var group = keyGroup.getKey(); - if (keys.isEmpty()) { - continue; - } - - var keyDate = Duration.of(keys.get(0).getRollingStartNumber(), GaenUnit.TenMinutes); - var protoFile = getProtoKey(keys, keyDate); - var zipFileName = new StringBuilder(); - - zipFileName.append("key_export_").append(group); - - zipCollection.putNextEntry(new ZipEntry(zipFileName.toString())); - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - ZipOutputStream zip = new ZipOutputStream(byteOut); - - zip.putNextEntry(new ZipEntry("export.bin")); - byte[] protoFileBytes = protoFile.toByteArray(); - byte[] exportBin = new byte[EXPORT_MAGIC.length + protoFileBytes.length]; - System.arraycopy(EXPORT_MAGIC, 0, exportBin, 0, EXPORT_MAGIC.length); - System.arraycopy(protoFileBytes, 0, exportBin, EXPORT_MAGIC.length, protoFileBytes.length); - zip.write(exportBin); - zip.closeEntry(); - - var signatureList = getSignatureObject(exportBin); - - byte[] exportSig = signatureList.toByteArray(); - zip.putNextEntry(new ZipEntry("export.sig")); - zip.write(exportSig); - zip.closeEntry(); - zip.flush(); - zip.close(); - byteOut.flush(); - byteOut.close(); - zipCollection.write(byteOut.toByteArray()); - - zipCollection.closeEntry(); - } - zipCollection.flush(); - zipCollection.close(); - byteOutCollection.close(); - return byteOutCollection.toByteArray(); - } - - public byte[] getPayload(Collection> buckets) - throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { - Map> grouped = new HashMap>(); - for (var keys : buckets) { - if (keys.isEmpty()) - continue; - var keyLocalDate = UTCInstant.of(keys.get(0).getRollingStartNumber(), GaenUnit.TenMinutes).getLocalDate().toString(); - grouped.put(keyLocalDate, keys); - } - return getPayload(grouped); - } - - private TemporaryExposureKeyFormat.TemporaryExposureKeyExport getProtoKey(List exposedKeys, - Duration batchReleaseTimeDuration) { - var file = TemporaryExposureKeyFormat.TemporaryExposureKeyExport.newBuilder(); - - var tekList = new ArrayList(); - for (var key : exposedKeys) { - var protoKey = TemporaryExposureKeyFormat.TemporaryExposureKey.newBuilder() - .setKeyData(ByteString.copyFrom(Base64.getDecoder().decode(key.getKeyData()))) - .setRollingPeriod(key.getRollingPeriod()).setRollingStartIntervalNumber(key.getRollingStartNumber()) - .setTransmissionRiskLevel(key.getTransmissionRiskLevel()).build(); - tekList.add(protoKey); - } - - file.addAllKeys(tekList); - - file.setRegion(gaenRegion).setBatchNum(1).setBatchSize(1) - .setStartTimestamp(batchReleaseTimeDuration.toSeconds()) - .setEndTimestamp(batchReleaseTimeDuration.toSeconds() + releaseBucketDuration.toSeconds()); - - file.addSignatureInfos(tekSignature()); - - return file.build(); - } - - public class ProtoSignatureWrapper { - private final byte[] hash; - private final byte[] zip; - public ProtoSignatureWrapper(byte[] hash, byte[] zip) { - this.hash = hash; - this.zip = zip; - } - - public byte[] getHash() { - return hash; - } - public byte[] getZip() { - return zip; - } - } - -} \ No newline at end of file + private static final byte[] EXPORT_MAGIC = { + 0x45, 0x4B, 0x20, 0x45, 0x78, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x76, 0x31, 0x20, 0x20, 0x20, 0x20 + }; // "EK Export v1 " + + private final String algorithm; + private final KeyPair keyPair; + private final String appBundleId; + private final String apkPackage; + private final String keyVersion; + private final String keyVerificationId; + private final String gaenRegion; + private final Duration releaseBucketDuration; + + public Map oidToJavaSignature = Map.of("1.2.840.10045.4.3.2", "SHA256withECDSA"); + + public ProtoSignature( + String algorithm, + KeyPair keyPair, + String appBundleId, + String apkPackage, + String keyVersion, + String keyVerificationId, + String gaenRegion, + Duration releaseBucketDuration) { + this.keyPair = keyPair; + this.algorithm = algorithm.trim(); + this.appBundleId = appBundleId; + this.apkPackage = apkPackage; + this.keyVerificationId = keyVerificationId; + this.keyVersion = keyVersion; + this.gaenRegion = gaenRegion; + this.releaseBucketDuration = releaseBucketDuration; + } + + /** + * Creates a ZIP file containing the given keys and the corresponding signature. + * + * @param keys + * @return + * @throws IOException + * @throws InvalidKeyException + * @throws SignatureException + * @throws NoSuchAlgorithmException + */ + public ProtoSignatureWrapper getPayload(List keys) + throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { + if (keys.isEmpty()) { + throw new IOException("Keys should not be empty"); + } + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(byteOut); + ByteArrayOutputStream hashOut = new ByteArrayOutputStream(); + var digest = MessageDigest.getInstance("SHA256"); + var keyDate = Duration.of(keys.get(0).getRollingStartNumber(), GaenUnit.TenMinutes); + var protoFile = getProtoKey(keys, keyDate); + + zip.putNextEntry(new ZipEntry("export.bin")); + byte[] protoFileBytes = protoFile.toByteArray(); + byte[] exportBin = new byte[EXPORT_MAGIC.length + protoFileBytes.length]; + System.arraycopy(EXPORT_MAGIC, 0, exportBin, 0, EXPORT_MAGIC.length); + System.arraycopy(protoFileBytes, 0, exportBin, EXPORT_MAGIC.length, protoFileBytes.length); + zip.write(exportBin); + zip.closeEntry(); + + var signatureList = getSignatureObject(exportBin); + digest.update(exportBin); + digest.update(keyPair.getPublic().getEncoded()); + hashOut.write(digest.digest()); + + byte[] exportSig = signatureList.toByteArray(); + zip.putNextEntry(new ZipEntry("export.sig")); + zip.write(exportSig); + zip.closeEntry(); + + zip.flush(); + zip.close(); + byteOut.flush(); + byteOut.close(); + hashOut.flush(); + hashOut.close(); + + return new ProtoSignatureWrapper(hashOut.toByteArray(), byteOut.toByteArray()); + } + + private byte[] sign(byte[] data) + throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { + Signature signature = Signature.getInstance(oidToJavaSignature.get(algorithm)); + signature.initSign(keyPair.getPrivate()); + signature.update(data); + return signature.sign(); + } + + private TemporaryExposureKeyFormat.TEKSignatureList getSignatureObject(byte[] keyExport) + throws InvalidKeyException, SignatureException, NoSuchAlgorithmException { + byte[] exportSignature = sign(keyExport); + var signatureList = TemporaryExposureKeyFormat.TEKSignatureList.newBuilder(); + var theSignature = TemporaryExposureKeyFormat.TEKSignature.newBuilder(); + theSignature + .setSignatureInfo(tekSignature()) + .setSignature(ByteString.copyFrom(exportSignature)) + .setBatchNum(1) + .setBatchSize(1); + signatureList.addSignatures(theSignature); + return signatureList.build(); + } + + private SignatureInfo tekSignature() { + var tekSignature = TemporaryExposureKeyFormat.SignatureInfo.newBuilder(); + tekSignature + .setAppBundleId(appBundleId) + .setVerificationKeyVersion(keyVersion) + .setVerificationKeyId(keyVerificationId) + .setSignatureAlgorithm(algorithm); + return tekSignature.build(); + } + + public PublicKey getPublicKey() { + return keyPair.getPublic(); + } + + public byte[] getPayload(Map> groupedBuckets) + throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { + ByteArrayOutputStream byteOutCollection = new ByteArrayOutputStream(); + ZipOutputStream zipCollection = new ZipOutputStream(byteOutCollection); + + for (var keyGroup : groupedBuckets.entrySet()) { + var keys = keyGroup.getValue(); + var group = keyGroup.getKey(); + if (keys.isEmpty()) { + continue; + } + + var keyDate = Duration.of(keys.get(0).getRollingStartNumber(), GaenUnit.TenMinutes); + var protoFile = getProtoKey(keys, keyDate); + var zipFileName = new StringBuilder(); + + zipFileName.append("key_export_").append(group); + + zipCollection.putNextEntry(new ZipEntry(zipFileName.toString())); + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(byteOut); + + zip.putNextEntry(new ZipEntry("export.bin")); + byte[] protoFileBytes = protoFile.toByteArray(); + byte[] exportBin = new byte[EXPORT_MAGIC.length + protoFileBytes.length]; + System.arraycopy(EXPORT_MAGIC, 0, exportBin, 0, EXPORT_MAGIC.length); + System.arraycopy(protoFileBytes, 0, exportBin, EXPORT_MAGIC.length, protoFileBytes.length); + zip.write(exportBin); + zip.closeEntry(); + + var signatureList = getSignatureObject(exportBin); + + byte[] exportSig = signatureList.toByteArray(); + zip.putNextEntry(new ZipEntry("export.sig")); + zip.write(exportSig); + zip.closeEntry(); + zip.flush(); + zip.close(); + byteOut.flush(); + byteOut.close(); + zipCollection.write(byteOut.toByteArray()); + + zipCollection.closeEntry(); + } + zipCollection.flush(); + zipCollection.close(); + byteOutCollection.close(); + return byteOutCollection.toByteArray(); + } + + public byte[] getPayload(Collection> buckets) + throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { + Map> grouped = new HashMap>(); + for (var keys : buckets) { + if (keys.isEmpty()) continue; + var keyLocalDate = + UTCInstant.of(keys.get(0).getRollingStartNumber(), GaenUnit.TenMinutes) + .getLocalDate() + .toString(); + grouped.put(keyLocalDate, keys); + } + return getPayload(grouped); + } + + private TemporaryExposureKeyFormat.TemporaryExposureKeyExport getProtoKey( + List exposedKeys, Duration batchReleaseTimeDuration) { + var file = TemporaryExposureKeyFormat.TemporaryExposureKeyExport.newBuilder(); + + var tekList = new ArrayList(); + for (var key : exposedKeys) { + var protoKey = + TemporaryExposureKeyFormat.TemporaryExposureKey.newBuilder() + .setKeyData(ByteString.copyFrom(Base64.getDecoder().decode(key.getKeyData()))) + .setRollingPeriod(key.getRollingPeriod()) + .setRollingStartIntervalNumber(key.getRollingStartNumber()) + .setTransmissionRiskLevel(key.getTransmissionRiskLevel()) + .build(); + tekList.add(protoKey); + } + + file.addAllKeys(tekList); + + file.setRegion(gaenRegion) + .setBatchNum(1) + .setBatchSize(1) + .setStartTimestamp(batchReleaseTimeDuration.toSeconds()) + .setEndTimestamp(batchReleaseTimeDuration.toSeconds() + releaseBucketDuration.toSeconds()); + + file.addSignatureInfos(tekSignature()); + + return file.build(); + } + + public class ProtoSignatureWrapper { + private final byte[] hash; + private final byte[] zip; + + public ProtoSignatureWrapper(byte[] hash, byte[] zip) { + this.hash = hash; + this.zip = zip; + } + + public byte[] getHash() { + return hash; + } + + public byte[] getZip() { + return zip; + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapper.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapper.java index c76ec341..feb75e09 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapper.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapper.java @@ -10,6 +10,8 @@ package org.dpppt.backend.sdk.ws.security.signature; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -20,12 +22,10 @@ import java.security.MessageDigest; import java.util.Base64; import java.util.List; - import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; - import org.apache.commons.codec.binary.Hex; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemWriter; @@ -33,174 +33,173 @@ import org.springframework.http.HttpStatus; import org.springframework.util.Base64Utils; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; - public class SignatureResponseWrapper extends HttpServletResponseWrapper { - // after number of days days the list and hence the signature is invalid - public final int retentionPeriod; - - private final MessageDigest digest; - private final ByteArrayOutputStream output; - private final KeyPair pair; - private final List protectedHeaders; - private final boolean setDebugHeaders; - - private HashStream stream; - private PrintWriter writer; - - private static final String HEADER_SIGNATURE = "Signature"; - private static final String HEADER_PUBLIC_KEY = "X-Public-Key"; - private static final String HEADER_DIGEST = "Digest"; - private static final String ISSUER_DP3T = "dp3t"; - private static final String CLAIM_HASH_ALG = "hash-alg"; - private static final String CLAIM_CONTENT_HASH = "content-hash"; - - public SignatureResponseWrapper(HttpServletResponse response, KeyPair pair, int retentionDays, - List protectedHeaders, boolean setDebugHeaders) { - super(response); - this.pair = pair; - this.protectedHeaders = protectedHeaders; - this.setDebugHeaders = setDebugHeaders; - try { - this.output = new ByteArrayOutputStream(response.getBufferSize()); - this.digest = MessageDigest.getInstance("SHA-256"); - this.stream = new HashStream(this.digest, this.output); - this.retentionPeriod = retentionDays; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - @Override - public ServletOutputStream getOutputStream() throws IOException { - if (stream == null) { - stream = new HashStream(this.digest, this.output); - } - return stream; - } - - public byte[] getHash() throws IOException { - return this.stream.getHash(); - } - - @Override - public PrintWriter getWriter() throws IOException { - if (output != null) { - throw new IllegalStateException("getOutputStream() has already been called on this response."); - } - - if (writer == null) { - writer = new PrintWriter(new OutputStreamWriter(this.output, getCharacterEncoding())); - } - - return writer; - } - - @Override - public void flushBuffer() throws IOException { - this.setSignature(); - super.flushBuffer(); - if (writer != null) { - writer.flush(); - } else if (output != null) { - output.flush(); - } - } - - public void outputData(OutputStream httpOutput) throws IOException { - this.setSignature(); - httpOutput.write(this.output.toByteArray()); - } - - private void setSignature() throws IOException { - switch(HttpStatus.valueOf(this.getStatus())) { - //only setsignature for 200 and 204 - case OK: - case NO_CONTENT: - break; - - default: - return; - } - - byte[] theHash = this.getHash(); - var now = UTCInstant.now(); - - Claims claims = Jwts.claims(); - claims.put(CLAIM_CONTENT_HASH, Base64.getEncoder().encodeToString(theHash)); - claims.put(CLAIM_HASH_ALG, "sha-256"); - - claims.setIssuer(ISSUER_DP3T); - claims.setIssuedAt(now.getDate()); - claims.setExpiration(now.plusDays(retentionPeriod).getDate()); - for (String header : protectedHeaders) { - if (!this.containsHeader(header)) { - continue; - } - - String normalizedHeader = header.toLowerCase().replace("x-", ""); - String headerValue = this.getHeader(header); - claims.put(normalizedHeader, headerValue); - if (normalizedHeader.equals("batch-release-time")) { - var issueDate = UTCInstant.ofEpochMillis(Long.parseLong(headerValue)); - claims.setIssuedAt(issueDate.getDate()); - claims.setExpiration(issueDate.plusDays(retentionPeriod).getDate()); - } - } - String signature = Jwts.builder().setClaims(claims).signWith(pair.getPrivate()).compact(); - - if (this.setDebugHeaders) { - this.setHeader(HEADER_DIGEST, "sha-256=" + Hex.encodeHexString(theHash)); - this.setHeader(HEADER_PUBLIC_KEY, getPublicKeyAsPEM()); - } - this.setHeader(HEADER_SIGNATURE, signature); - } - - private String getPublicKeyAsPEM() throws IOException { - StringWriter writer = new StringWriter(); - PemWriter pemWriter = new PemWriter(writer); - pemWriter.writeObject(new PemObject("PUBLIC KEY", pair.getPublic().getEncoded())); - pemWriter.flush(); - pemWriter.close(); - return Base64Utils.encodeToUrlSafeString(writer.toString().trim().getBytes()); - } - - private class HashStream extends ServletOutputStream { - - private MessageDigest digest; - private ByteArrayOutputStream output; - - public HashStream(MessageDigest digest, ByteArrayOutputStream outputStream) { - this.digest = digest; - this.output = outputStream; - } - - @Override - public boolean isReady() { - return false; - } - - @Override - public void setWriteListener(WriteListener listener) { - - } - - @Override - public void write(int b) throws IOException { - this.digest.update((byte) b); - this.output.write(b); - } - - @Override - public void close() throws IOException { - this.output.close(); - } - - public byte[] getHash() throws IOException { - return this.digest.digest(); - } - } - -} \ No newline at end of file + // after number of days days the list and hence the signature is invalid + public final int retentionPeriod; + + private final MessageDigest digest; + private final ByteArrayOutputStream output; + private final KeyPair pair; + private final List protectedHeaders; + private final boolean setDebugHeaders; + + private HashStream stream; + private PrintWriter writer; + + private static final String HEADER_SIGNATURE = "Signature"; + private static final String HEADER_PUBLIC_KEY = "X-Public-Key"; + private static final String HEADER_DIGEST = "Digest"; + private static final String ISSUER_DP3T = "dp3t"; + private static final String CLAIM_HASH_ALG = "hash-alg"; + private static final String CLAIM_CONTENT_HASH = "content-hash"; + + public SignatureResponseWrapper( + HttpServletResponse response, + KeyPair pair, + int retentionDays, + List protectedHeaders, + boolean setDebugHeaders) { + super(response); + this.pair = pair; + this.protectedHeaders = protectedHeaders; + this.setDebugHeaders = setDebugHeaders; + try { + this.output = new ByteArrayOutputStream(response.getBufferSize()); + this.digest = MessageDigest.getInstance("SHA-256"); + this.stream = new HashStream(this.digest, this.output); + this.retentionPeriod = retentionDays; + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + if (stream == null) { + stream = new HashStream(this.digest, this.output); + } + return stream; + } + + public byte[] getHash() throws IOException { + return this.stream.getHash(); + } + + @Override + public PrintWriter getWriter() throws IOException { + if (output != null) { + throw new IllegalStateException( + "getOutputStream() has already been called on this response."); + } + + if (writer == null) { + writer = new PrintWriter(new OutputStreamWriter(this.output, getCharacterEncoding())); + } + + return writer; + } + + @Override + public void flushBuffer() throws IOException { + this.setSignature(); + super.flushBuffer(); + if (writer != null) { + writer.flush(); + } else if (output != null) { + output.flush(); + } + } + + public void outputData(OutputStream httpOutput) throws IOException { + this.setSignature(); + httpOutput.write(this.output.toByteArray()); + } + + private void setSignature() throws IOException { + switch (HttpStatus.valueOf(this.getStatus())) { + // only setsignature for 200 and 204 + case OK: + case NO_CONTENT: + break; + + default: + return; + } + + byte[] theHash = this.getHash(); + var now = UTCInstant.now(); + + Claims claims = Jwts.claims(); + claims.put(CLAIM_CONTENT_HASH, Base64.getEncoder().encodeToString(theHash)); + claims.put(CLAIM_HASH_ALG, "sha-256"); + + claims.setIssuer(ISSUER_DP3T); + claims.setIssuedAt(now.getDate()); + claims.setExpiration(now.plusDays(retentionPeriod).getDate()); + for (String header : protectedHeaders) { + if (!this.containsHeader(header)) { + continue; + } + + String normalizedHeader = header.toLowerCase().replace("x-", ""); + String headerValue = this.getHeader(header); + claims.put(normalizedHeader, headerValue); + if (normalizedHeader.equals("batch-release-time")) { + var issueDate = UTCInstant.ofEpochMillis(Long.parseLong(headerValue)); + claims.setIssuedAt(issueDate.getDate()); + claims.setExpiration(issueDate.plusDays(retentionPeriod).getDate()); + } + } + String signature = Jwts.builder().setClaims(claims).signWith(pair.getPrivate()).compact(); + + if (this.setDebugHeaders) { + this.setHeader(HEADER_DIGEST, "sha-256=" + Hex.encodeHexString(theHash)); + this.setHeader(HEADER_PUBLIC_KEY, getPublicKeyAsPEM()); + } + this.setHeader(HEADER_SIGNATURE, signature); + } + + private String getPublicKeyAsPEM() throws IOException { + StringWriter writer = new StringWriter(); + PemWriter pemWriter = new PemWriter(writer); + pemWriter.writeObject(new PemObject("PUBLIC KEY", pair.getPublic().getEncoded())); + pemWriter.flush(); + pemWriter.close(); + return Base64Utils.encodeToUrlSafeString(writer.toString().trim().getBytes()); + } + + private class HashStream extends ServletOutputStream { + + private MessageDigest digest; + private ByteArrayOutputStream output; + + public HashStream(MessageDigest digest, ByteArrayOutputStream outputStream) { + this.digest = digest; + this.output = outputStream; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener listener) {} + + @Override + public void write(int b) throws IOException { + this.digest.update((byte) b); + this.output.write(b); + } + + @Override + public void close() throws IOException { + this.output.close(); + } + + public byte[] getHash() throws IOException { + return this.digest.digest(); + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/KeyHelper.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/KeyHelper.java index 293c5e9c..f0b1d5ca 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/KeyHelper.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/KeyHelper.java @@ -10,26 +10,21 @@ package org.dpppt.backend.sdk.ws.util; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.net.URL; - import org.dpppt.backend.sdk.model.keycloak.KeyCloakPublicKey; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * @author bachmann created on 22.04.20 - **/ +/** @author bachmann created on 22.04.20 */ public class KeyHelper { - private static ObjectMapper objectMapper = new ObjectMapper(); + private static ObjectMapper objectMapper = new ObjectMapper(); - private KeyHelper() { - } + private KeyHelper() {} - public static String getPublicKeyFromKeycloak(String url) throws IOException { - URL jsonUrl = new URL(url); - KeyCloakPublicKey publicKey = objectMapper.readValue(jsonUrl, KeyCloakPublicKey.class); - return publicKey.getPublicKey(); - } + public static String getPublicKeyFromKeycloak(String url) throws IOException { + URL jsonUrl = new URL(url); + KeyCloakPublicKey publicKey = objectMapper.readValue(jsonUrl, KeyCloakPublicKey.class); + return publicKey.getPublicKey(); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/ValidationUtils.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/ValidationUtils.java index 1da4fdef..8e849d25 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/ValidationUtils.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/main/java/org/dpppt/backend/sdk/ws/util/ValidationUtils.java @@ -11,143 +11,139 @@ import java.time.Duration; import java.util.Base64; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.utils.UTCInstant; import org.springframework.security.oauth2.jwt.Jwt; -/** - * Offers a set of methods to validate the incoming requests from the mobile devices. - */ +/** Offers a set of methods to validate the incoming requests from the mobile devices. */ public class ValidationUtils { - private final int KEY_LENGTH_BYTES; - private final Duration retentionPeriod; - private final Long releaseBucketDuration; - - /** - * Initialize the validator with the current parameters in use. - * - * @param keyLengthBytes how long the exposed keys are, in bytes - * @param retentionPeriod period during which the exposed keys are stored, before they are deleted - * @param releaseBucketDuration maximum time in milliseconds that exposed keys are hidden before being served, in order to prevent timing attacks - */ - public ValidationUtils(int keyLengthBytes, Duration retentionPeriod, Long releaseBucketDuration) { - this.KEY_LENGTH_BYTES = keyLengthBytes; - this.retentionPeriod = retentionPeriod; - this.releaseBucketDuration = releaseBucketDuration; - } - - /** - * Check the validty of a base64 value - * - * @param value representation of a base64 value - * @return if _value_ is a valid representation - */ - public boolean isValidBase64Key(String value) { - try { - byte[] key = Base64.getDecoder().decode(value); - if (key.length != KEY_LENGTH_BYTES) { - return false; - } - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Check if the given date is in the range of [now - retentionPeriod ... now], inclusive - * - * @param timestamp to verify - * @return if the date is in the range - */ - public boolean isDateInRange(UTCInstant timestamp, UTCInstant now) { - var retention = now.minus(retentionPeriod); - // This should use timestamp.isAfterOrEqual(retention), but this method does not exist. - // Because _now_ has a resolution of 1 millisecond, this precision is acceptable. - return timestamp.isAfterEpochMillisOf(retention) && timestamp.isBeforeEpochMillisOf(now); - } - /** - * Check if the given date is before now - retentionPeriod ... now - * - * @param timestamp to verify - * @return if the date is in the range - */ - public boolean isBeforeRetention(UTCInstant timestamp, UTCInstant now){ - return timestamp.isBeforeDateOf(now.minus(retentionPeriod)); - } - - /** - * Check if the given timestamp is a valid key date: Must be midnight UTC. - * - * @param keyDate as a UTCInstant - * @return if keyDate represents midnight UTC - */ - public boolean isValidKeyDate(UTCInstant keyDate) { - return keyDate.isMidnight(); - } - - /** - * Check if the given batchReleaseTime is the beginning of a batch, and if it is between - * [now - retentionPeriod ... now], inclusive. - * - * @param batchReleaseTime in milliseconds since Unix epoch (1970-01-01) - * @return if batchReleaseTime is in range - * @throws BadBatchReleaseTimeException if batchReleaseTime is not on a batch boundary - */ - public boolean isValidBatchReleaseTime(UTCInstant batchReleaseTime, UTCInstant now) throws BadBatchReleaseTimeException { - if (batchReleaseTime.getTimestamp() % releaseBucketDuration != 0) { - throw new BadBatchReleaseTimeException(); - } - return this.isDateInRange(batchReleaseTime, now); - } - - public void validateDelayedKeyDate(UTCInstant now, UTCInstant delayedKeyDate) throws DelayedKeyDateIsInvalid{ - if (delayedKeyDate.isBeforeDateOf(now.getLocalDate().minusDays(1)) - || delayedKeyDate.isAfterDateOf(now.getLocalDate().plusDays(1))) { - throw new DelayedKeyDateIsInvalid(); - } - } - public void checkForDelayedKeyDateClaim(Object principal, GaenKey delayedKey) throws DelayedKeyDateClaimIsWrong { - if (principal instanceof Jwt && Boolean.FALSE.equals(((Jwt) principal).containsClaim("delayedKeyDate"))) { - throw new DelayedKeyDateClaimIsWrong(); - } - if (principal instanceof Jwt) { - var jwt = (Jwt) principal; - var claimKeyDate = Integer.parseInt(jwt.getClaimAsString("delayedKeyDate")); - if (!delayedKey.getRollingStartNumber().equals(claimKeyDate)) { - throw new DelayedKeyDateClaimIsWrong(); - } - } - } - - public boolean jwtIsFake(Object principal) { - return principal instanceof Jwt - && Boolean.TRUE.equals(((Jwt) principal).containsClaim("fake")) - && ((Jwt) principal).getClaim("fake").equals("1"); - } - - - public class BadBatchReleaseTimeException extends Exception { - - private static final long serialVersionUID = 618376703047108588L; - - } - public class DelayedKeyDateIsInvalid extends Exception { - - /** - * - */ - private static final long serialVersionUID = -2667236967819549686L; - - } - public class DelayedKeyDateClaimIsWrong extends Exception { - - /** - * - */ - private static final long serialVersionUID = 4683923905451080793L; - - } - -} \ No newline at end of file + private final int KEY_LENGTH_BYTES; + private final Duration retentionPeriod; + private final Long releaseBucketDuration; + + /** + * Initialize the validator with the current parameters in use. + * + * @param keyLengthBytes how long the exposed keys are, in bytes + * @param retentionPeriod period during which the exposed keys are stored, before they are deleted + * @param releaseBucketDuration maximum time in milliseconds that exposed keys are hidden before + * being served, in order to prevent timing attacks + */ + public ValidationUtils(int keyLengthBytes, Duration retentionPeriod, Long releaseBucketDuration) { + this.KEY_LENGTH_BYTES = keyLengthBytes; + this.retentionPeriod = retentionPeriod; + this.releaseBucketDuration = releaseBucketDuration; + } + + /** + * Check the validty of a base64 value + * + * @param value representation of a base64 value + * @return if _value_ is a valid representation + */ + public boolean isValidBase64Key(String value) { + try { + byte[] key = Base64.getDecoder().decode(value); + if (key.length != KEY_LENGTH_BYTES) { + return false; + } + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Check if the given date is in the range of [now - retentionPeriod ... now], inclusive + * + * @param timestamp to verify + * @return if the date is in the range + */ + public boolean isDateInRange(UTCInstant timestamp, UTCInstant now) { + var retention = now.minus(retentionPeriod); + // This should use timestamp.isAfterOrEqual(retention), but this method does not exist. + // Because _now_ has a resolution of 1 millisecond, this precision is acceptable. + return timestamp.isAfterEpochMillisOf(retention) && timestamp.isBeforeEpochMillisOf(now); + } + /** + * Check if the given date is before now - retentionPeriod ... now + * + * @param timestamp to verify + * @return if the date is in the range + */ + public boolean isBeforeRetention(UTCInstant timestamp, UTCInstant now) { + return timestamp.isBeforeDateOf(now.minus(retentionPeriod)); + } + + /** + * Check if the given timestamp is a valid key date: Must be midnight UTC. + * + * @param keyDate as a UTCInstant + * @return if keyDate represents midnight UTC + */ + public boolean isValidKeyDate(UTCInstant keyDate) { + return keyDate.isMidnight(); + } + + /** + * Check if the given batchReleaseTime is the beginning of a batch, and if it is between [now - + * retentionPeriod ... now], inclusive. + * + * @param batchReleaseTime in milliseconds since Unix epoch (1970-01-01) + * @return if batchReleaseTime is in range + * @throws BadBatchReleaseTimeException if batchReleaseTime is not on a batch boundary + */ + public boolean isValidBatchReleaseTime(UTCInstant batchReleaseTime, UTCInstant now) + throws BadBatchReleaseTimeException { + if (batchReleaseTime.getTimestamp() % releaseBucketDuration != 0) { + throw new BadBatchReleaseTimeException(); + } + return this.isDateInRange(batchReleaseTime, now); + } + + public void validateDelayedKeyDate(UTCInstant now, UTCInstant delayedKeyDate) + throws DelayedKeyDateIsInvalid { + if (delayedKeyDate.isBeforeDateOf(now.getLocalDate().minusDays(1)) + || delayedKeyDate.isAfterDateOf(now.getLocalDate().plusDays(1))) { + throw new DelayedKeyDateIsInvalid(); + } + } + + public void checkForDelayedKeyDateClaim(Object principal, GaenKey delayedKey) + throws DelayedKeyDateClaimIsWrong { + if (principal instanceof Jwt + && Boolean.FALSE.equals(((Jwt) principal).containsClaim("delayedKeyDate"))) { + throw new DelayedKeyDateClaimIsWrong(); + } + if (principal instanceof Jwt) { + var jwt = (Jwt) principal; + var claimKeyDate = Integer.parseInt(jwt.getClaimAsString("delayedKeyDate")); + if (!delayedKey.getRollingStartNumber().equals(claimKeyDate)) { + throw new DelayedKeyDateClaimIsWrong(); + } + } + } + + public boolean jwtIsFake(Object principal) { + return principal instanceof Jwt + && Boolean.TRUE.equals(((Jwt) principal).containsClaim("fake")) + && ((Jwt) principal).getClaim("fake").equals("1"); + } + + public class BadBatchReleaseTimeException extends Exception { + + private static final long serialVersionUID = 618376703047108588L; + } + + public class DelayedKeyDateIsInvalid extends Exception { + + /** */ + private static final long serialVersionUID = -2667236967819549686L; + } + + public class DelayedKeyDateClaimIsWrong extends Exception { + + /** */ + private static final long serialVersionUID = 4683923905451080793L; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/config/TestConfig.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/config/TestConfig.java index 5e6cbeb7..495ff731 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/config/TestConfig.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/config/TestConfig.java @@ -1,7 +1,6 @@ package org.dpppt.backend.sdk.ws.config; import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,11 +9,11 @@ @Configuration("test-config") public class TestConfig { - @Autowired - DataSource dataSource; - @Bean - public PlatformTransactionManager testTransactionManager() throws Exception { - DataSourceTransactionManager dstm = new DataSourceTransactionManager(dataSource); - return dstm; - } -} \ No newline at end of file + @Autowired DataSource dataSource; + + @Bean + public PlatformTransactionManager testTransactionManager() throws Exception { + DataSourceTransactionManager dstm = new DataSourceTransactionManager(dataSource); + return dstm; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerNoSecurityTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerNoSecurityTest.java index 7f076f06..40015091 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerNoSecurityTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerNoSecurityTest.java @@ -10,8 +10,11 @@ package org.dpppt.backend.sdk.ws.controller; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import java.io.IOException; - import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -23,37 +26,36 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "dev" }) -@TestPropertySource(properties = { "ws.app.source=org.dpppt.demo", }) +@ActiveProfiles({"dev"}) +@TestPropertySource( + properties = { + "ws.app.source=org.dpppt.demo", + }) public abstract class BaseControllerNoSecurityTest { - protected MockMvc mockMvc; - - protected final String jwtToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1LVJxcVRUWW9tZnBWejA2VlJFT2ZyYmNxYTVXdTJkX1g4MnZfWlRNLVZVIn0.eyJqdGkiOiI4ZmE5MWRlMi03YmYwLTRhNmYtOWIzZC1hNzdiZDM3ZDdiMTMiLCJleHAiOjE1ODczMTYzMTgsIm5iZiI6MCwiaWF0IjoxNTg3MzE2MDE4LCJpc3MiOiJodHRwczovL2lkZW50aXR5LXIuYml0LmFkbWluLmNoL3JlYWxtcy9iYWctcHRzIiwic3ViIjoiMWVmYTliZWYtOWU5ZC00MjNjLTkxMjctZmQwYjAxNWQxOTY2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHRhLWFwcC1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZGVjYzQ3Y2YtMmUyZi00NjZlLThiNTAtZmQ4MTAzZmQ4ZDNhIiwiYWNyIjoiMSIsInNjb3BlIjoiZXhwb3NlZCIsIm9uc2V0IjoiMjAyMC0wNS0yNSJ9.J5beGE6GjgRWEZfwzB9_G6X1uTZcZdm7Mkng8od5Fr3UPT4BbkKgPbpGRscouiAPBjOlZDCs3rcT_qiioX5wAZ0UjqLTe370K53vb1I_f4nQKfTMBYfzvdpS5i5V64LoKbXHpF7PLsGSiox6dA8g5Ssqf5uoTHz1_NY-6GvVq-LmFozV6_1zzYkBVZCLVh0gsqcG9EH2peuhEt9akv_Jmc1Ls0lZQeU1szeRmsk44mg8_FbG33yB3F0azhs0pfEuuYCzGbAqdFCU2RDnRCOXXr7o8Z_klrKE6NArWgbHbk8CE0a-3UwEdi6zw0xm1VNwbnMtjxVcyxECw7V2bSNu9A"; - - protected final String wrongToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1LVJxcVRUWW9tZnBWejA2VlJFT2ZyYmNxYTVXdTJkX1g4MnZfWlRNLVZVIn0.eyJqdGkiOiI4ZmE5MWRlMi03YmYwLTRhNmYtOWIzZC1hNzdiZDM3ZDdiMTMiLCJleHAiOjE1ODczMTYzMTgsIm5iZiI6MCwiaWF0IjoxNTg3MzE2MDE4LCJpc3MiOiJodHRwczovL2lkZW50aXR5LXIuYml0LmFkbWluLmNoL3JlYWxtcy9iYWctcHRzIiwic3ViIjoiMWVmYTliZWYtOWU5ZC00MjNjLkxMjctZmQwYjAxNWQxOTY2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHRhLWFwcC1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZGVjYzQ3Y2YtMmUyZi00NjZlLThiNTAtZmQ4MTAzZmQ4ZDNhIiwiYWNyIjoiMSIsInNjb3BlIjoiZXhwb3NlZCIsIm9uc2V0IjoiMjAyMC0wNS0yNSJ9.J5beGE6GjgRWEZfwzB9_G6X1uTZcZdm7Mkng8od5Fr3UPT4BbkKgPbpGRscouiAPBjOlZDCs3rcT_qiioX5wAZ0UjqLTe370K53vb1I_f4nQKfTMBYfzvdpS5i5V64LoKbXHpF7PLsGSiox6dA8g5Ssqf5uoTHz1_NY-6GvVq-LmFozV6_1zzYkBVZCLVh0gsqcG9EH2peuhEt9akv_Jmc1Ls0lZQeU1szeRmsk44mg8_FbG33yB3F0azhs0pfEuuYCzGbAqdFCU2RDnRCOXXr7o8Z_klrKE6NArWgbHbk8CE0a-3UwEdi6zw0xm1VNwbnMtjxVcyxECw7V2bSNu9A"; - - @Autowired - private WebApplicationContext webApplicationContext; - protected ObjectMapper objectMapper; - - @Before - public void setup() throws Exception { - this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); - this.objectMapper = new ObjectMapper(new JsonFactory()); - this.objectMapper.registerModule(new JavaTimeModule()); - // this makes sure, that the objectmapper does not fail, when a filter - // is not provided. - this.objectMapper.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false)); - } - - protected String json(Object o) throws IOException { - return objectMapper.writeValueAsString(o); - } -} \ No newline at end of file + protected MockMvc mockMvc; + + protected final String jwtToken = + "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1LVJxcVRUWW9tZnBWejA2VlJFT2ZyYmNxYTVXdTJkX1g4MnZfWlRNLVZVIn0.eyJqdGkiOiI4ZmE5MWRlMi03YmYwLTRhNmYtOWIzZC1hNzdiZDM3ZDdiMTMiLCJleHAiOjE1ODczMTYzMTgsIm5iZiI6MCwiaWF0IjoxNTg3MzE2MDE4LCJpc3MiOiJodHRwczovL2lkZW50aXR5LXIuYml0LmFkbWluLmNoL3JlYWxtcy9iYWctcHRzIiwic3ViIjoiMWVmYTliZWYtOWU5ZC00MjNjLTkxMjctZmQwYjAxNWQxOTY2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHRhLWFwcC1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZGVjYzQ3Y2YtMmUyZi00NjZlLThiNTAtZmQ4MTAzZmQ4ZDNhIiwiYWNyIjoiMSIsInNjb3BlIjoiZXhwb3NlZCIsIm9uc2V0IjoiMjAyMC0wNS0yNSJ9.J5beGE6GjgRWEZfwzB9_G6X1uTZcZdm7Mkng8od5Fr3UPT4BbkKgPbpGRscouiAPBjOlZDCs3rcT_qiioX5wAZ0UjqLTe370K53vb1I_f4nQKfTMBYfzvdpS5i5V64LoKbXHpF7PLsGSiox6dA8g5Ssqf5uoTHz1_NY-6GvVq-LmFozV6_1zzYkBVZCLVh0gsqcG9EH2peuhEt9akv_Jmc1Ls0lZQeU1szeRmsk44mg8_FbG33yB3F0azhs0pfEuuYCzGbAqdFCU2RDnRCOXXr7o8Z_klrKE6NArWgbHbk8CE0a-3UwEdi6zw0xm1VNwbnMtjxVcyxECw7V2bSNu9A"; + + protected final String wrongToken = + "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1LVJxcVRUWW9tZnBWejA2VlJFT2ZyYmNxYTVXdTJkX1g4MnZfWlRNLVZVIn0.eyJqdGkiOiI4ZmE5MWRlMi03YmYwLTRhNmYtOWIzZC1hNzdiZDM3ZDdiMTMiLCJleHAiOjE1ODczMTYzMTgsIm5iZiI6MCwiaWF0IjoxNTg3MzE2MDE4LCJpc3MiOiJodHRwczovL2lkZW50aXR5LXIuYml0LmFkbWluLmNoL3JlYWxtcy9iYWctcHRzIiwic3ViIjoiMWVmYTliZWYtOWU5ZC00MjNjLkxMjctZmQwYjAxNWQxOTY2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHRhLWFwcC1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZGVjYzQ3Y2YtMmUyZi00NjZlLThiNTAtZmQ4MTAzZmQ4ZDNhIiwiYWNyIjoiMSIsInNjb3BlIjoiZXhwb3NlZCIsIm9uc2V0IjoiMjAyMC0wNS0yNSJ9.J5beGE6GjgRWEZfwzB9_G6X1uTZcZdm7Mkng8od5Fr3UPT4BbkKgPbpGRscouiAPBjOlZDCs3rcT_qiioX5wAZ0UjqLTe370K53vb1I_f4nQKfTMBYfzvdpS5i5V64LoKbXHpF7PLsGSiox6dA8g5Ssqf5uoTHz1_NY-6GvVq-LmFozV6_1zzYkBVZCLVh0gsqcG9EH2peuhEt9akv_Jmc1Ls0lZQeU1szeRmsk44mg8_FbG33yB3F0azhs0pfEuuYCzGbAqdFCU2RDnRCOXXr7o8Z_klrKE6NArWgbHbk8CE0a-3UwEdi6zw0xm1VNwbnMtjxVcyxECw7V2bSNu9A"; + + @Autowired private WebApplicationContext webApplicationContext; + protected ObjectMapper objectMapper; + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + this.objectMapper = new ObjectMapper(new JsonFactory()); + this.objectMapper.registerModule(new JavaTimeModule()); + // this makes sure, that the objectmapper does not fail, when a filter + // is not provided. + this.objectMapper.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false)); + } + + protected String json(Object o) throws IOException { + return objectMapper.writeValueAsString(o); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerTest.java index 816fce79..e466bfbf 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/BaseControllerTest.java @@ -10,6 +10,11 @@ package org.dpppt.backend.sdk.ws.controller; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; import java.io.IOException; import java.io.InputStream; import java.security.Key; @@ -21,14 +26,8 @@ import java.time.ZoneOffset; import java.util.Base64; import java.util.UUID; - import javax.servlet.Filter; import javax.sql.DataSource; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - import org.apache.commons.io.IOUtils; import org.dpppt.backend.sdk.utils.UTCInstant; import org.dpppt.backend.sdk.ws.filter.ResponseWrapperFilter; @@ -45,113 +44,144 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; - @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "dev", "jwt", "debug", "test-config" }) -@TestPropertySource(properties = { "ws.app.source=org.dpppt.demo" }) +@ActiveProfiles({"dev", "jwt", "debug", "test-config"}) +@TestPropertySource(properties = {"ws.app.source=org.dpppt.demo"}) public abstract class BaseControllerTest { - protected MockMvc mockMvc; - - protected final String jwtToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1LVJxcVRUWW9tZnBWejA2VlJFT2ZyYmNxYTVXdTJkX1g4MnZfWlRNLVZVIn0.eyJqdGkiOiI4ZmE5MWRlMi03YmYwLTRhNmYtOWIzZC1hNzdiZDM3ZDdiMTMiLCJleHAiOjE1ODczMTYzMTgsIm5iZiI6MCwiaWF0IjoxNTg3MzE2MDE4LCJpc3MiOiJodHRwczovL2lkZW50aXR5LXIuYml0LmFkbWluLmNoL3JlYWxtcy9iYWctcHRzIiwic3ViIjoiMWVmYTliZWYtOWU5ZC00MjNjLTkxMjctZmQwYjAxNWQxOTY2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHRhLWFwcC1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZGVjYzQ3Y2YtMmUyZi00NjZlLThiNTAtZmQ4MTAzZmQ4ZDNhIiwiYWNyIjoiMSIsInNjb3BlIjoiZXhwb3NlZCIsIm9uc2V0IjoiMjAyMC0wNS0yNSJ9.J5beGE6GjgRWEZfwzB9_G6X1uTZcZdm7Mkng8od5Fr3UPT4BbkKgPbpGRscouiAPBjOlZDCs3rcT_qiioX5wAZ0UjqLTe370K53vb1I_f4nQKfTMBYfzvdpS5i5V64LoKbXHpF7PLsGSiox6dA8g5Ssqf5uoTHz1_NY-6GvVq-LmFozV6_1zzYkBVZCLVh0gsqcG9EH2peuhEt9akv_Jmc1Ls0lZQeU1szeRmsk44mg8_FbG33yB3F0azhs0pfEuuYCzGbAqdFCU2RDnRCOXXr7o8Z_klrKE6NArWgbHbk8CE0a-3UwEdi6zw0xm1VNwbnMtjxVcyxECw7V2bSNu9A"; - - @Autowired - private WebApplicationContext webApplicationContext; - protected ObjectMapper objectMapper; - - @Autowired - private Filter springSecurityFilterChain; - - @Autowired - private ResponseWrapperFilter filter; - - @Autowired - DataSource dataSource; - - protected TestJDBCGaen testGaenDataService; - - @Before - public void setup() throws Exception { - loadPrivateKey(); - this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilter(springSecurityFilterChain).addFilter(filter, "/*").build(); - this.objectMapper = new ObjectMapper(new JsonFactory()); - this.objectMapper.registerModule(new JavaTimeModule()); - this.testGaenDataService = new TestJDBCGaen("hsqldb", dataSource); - } - - private void loadPrivateKey() throws Exception { - InputStream inputStream = new ClassPathResource("generated_private.pem").getInputStream(); - String key = IOUtils.toString(inputStream); - PKCS8EncodedKeySpec keySpecX509 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key)); - KeyFactory kf = KeyFactory.getInstance("RSA"); - privateKey = (PrivateKey) kf.generatePrivate(keySpecX509); - } - - protected String json(Object o) throws IOException { - return objectMapper.writeValueAsString(o); - } - - protected PublicKey publicKey; - protected PrivateKey privateKey; - - protected String createToken(UTCInstant expiresAt) { - Claims claims = Jwts.claims(); - claims.put("scope", "exposed"); - claims.put("onset", "2020-04-20"); - claims.put("fake", "0"); - return Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString()) - .setSubject("test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()).setExpiration(expiresAt.getDate()) - .setIssuedAt(UTCInstant.now().getDate()).signWith((Key) privateKey).compact(); - } - protected String createToken(UTCInstant expiresAt, String onset) { - Claims claims = Jwts.claims(); - claims.put("scope", "exposed"); - claims.put("fake", "0"); - claims.put("onset", onset); - return Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString()) - .setSubject("test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()).setExpiration(expiresAt.getDate()) - .setIssuedAt(UTCInstant.now().getDate()).signWith((Key) privateKey).compact(); - } - - protected String createToken(String subject, UTCInstant expiresAt) { - Claims claims = Jwts.claims(); - claims.put("scope", "exposed"); - claims.put("fake", "0"); - return Jwts.builder().setSubject(subject).setExpiration(expiresAt.getDate()).setClaims(claims) - .setId(UUID.randomUUID().toString()).signWith((Key) privateKey).compact(); - } - - protected String createToken(boolean fake, UTCInstant expiresAt) { - Claims claims = Jwts.claims(); - claims.put("scope", "exposed"); - claims.put("onset", "2020-04-20"); - claims.put("fake", fake? "1": "0"); - return Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString()) - .setSubject("test-subject" + UTCInstant.now().getOffsetDateTime().toString()) - .setExpiration(expiresAt.getDate()) - .setIssuedAt(UTCInstant.now().getDate()).signWith((Key) privateKey).compact(); - } - - protected String createTokenWithScope(UTCInstant expiresAt, String scope) { - Claims claims = Jwts.claims(); - claims.put("scope", scope); - claims.put("fake", "0"); - claims.put("onset", "2020-04-20"); - return Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString()) - .setSubject("test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()).setExpiration(expiresAt.getDate()) - .setIssuedAt(UTCInstant.now().getDate()).signWith((Key) privateKey).compact(); - } - protected String createMaliciousToken(UTCInstant expiresAt) { - Claims claims = Jwts.claims(); - claims.put("scope", "exposed"); - claims.put("onset", "2020-04-20"); - claims.put("fake", "0"); - return Jwts.builder().setClaims(claims).setId(UUID.randomUUID().toString()) - .setSubject("test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()).setExpiration(expiresAt.getDate()) - .setIssuedAt(UTCInstant.now().getDate()).compact(); - } - + protected MockMvc mockMvc; + + protected final String jwtToken = + "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI1LVJxcVRUWW9tZnBWejA2VlJFT2ZyYmNxYTVXdTJkX1g4MnZfWlRNLVZVIn0.eyJqdGkiOiI4ZmE5MWRlMi03YmYwLTRhNmYtOWIzZC1hNzdiZDM3ZDdiMTMiLCJleHAiOjE1ODczMTYzMTgsIm5iZiI6MCwiaWF0IjoxNTg3MzE2MDE4LCJpc3MiOiJodHRwczovL2lkZW50aXR5LXIuYml0LmFkbWluLmNoL3JlYWxtcy9iYWctcHRzIiwic3ViIjoiMWVmYTliZWYtOWU5ZC00MjNjLTkxMjctZmQwYjAxNWQxOTY2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoicHRhLWFwcC1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiZGVjYzQ3Y2YtMmUyZi00NjZlLThiNTAtZmQ4MTAzZmQ4ZDNhIiwiYWNyIjoiMSIsInNjb3BlIjoiZXhwb3NlZCIsIm9uc2V0IjoiMjAyMC0wNS0yNSJ9.J5beGE6GjgRWEZfwzB9_G6X1uTZcZdm7Mkng8od5Fr3UPT4BbkKgPbpGRscouiAPBjOlZDCs3rcT_qiioX5wAZ0UjqLTe370K53vb1I_f4nQKfTMBYfzvdpS5i5V64LoKbXHpF7PLsGSiox6dA8g5Ssqf5uoTHz1_NY-6GvVq-LmFozV6_1zzYkBVZCLVh0gsqcG9EH2peuhEt9akv_Jmc1Ls0lZQeU1szeRmsk44mg8_FbG33yB3F0azhs0pfEuuYCzGbAqdFCU2RDnRCOXXr7o8Z_klrKE6NArWgbHbk8CE0a-3UwEdi6zw0xm1VNwbnMtjxVcyxECw7V2bSNu9A"; + + @Autowired private WebApplicationContext webApplicationContext; + protected ObjectMapper objectMapper; + + @Autowired private Filter springSecurityFilterChain; + + @Autowired private ResponseWrapperFilter filter; + + @Autowired DataSource dataSource; + + protected TestJDBCGaen testGaenDataService; + + @Before + public void setup() throws Exception { + loadPrivateKey(); + this.mockMvc = + MockMvcBuilders.webAppContextSetup(webApplicationContext) + .addFilter(springSecurityFilterChain) + .addFilter(filter, "/*") + .build(); + this.objectMapper = new ObjectMapper(new JsonFactory()); + this.objectMapper.registerModule(new JavaTimeModule()); + this.testGaenDataService = new TestJDBCGaen("hsqldb", dataSource); + } + + private void loadPrivateKey() throws Exception { + InputStream inputStream = new ClassPathResource("generated_private.pem").getInputStream(); + String key = IOUtils.toString(inputStream); + PKCS8EncodedKeySpec keySpecX509 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key)); + KeyFactory kf = KeyFactory.getInstance("RSA"); + privateKey = (PrivateKey) kf.generatePrivate(keySpecX509); + } + + protected String json(Object o) throws IOException { + return objectMapper.writeValueAsString(o); + } + + protected PublicKey publicKey; + protected PrivateKey privateKey; + + protected String createToken(UTCInstant expiresAt) { + Claims claims = Jwts.claims(); + claims.put("scope", "exposed"); + claims.put("onset", "2020-04-20"); + claims.put("fake", "0"); + return Jwts.builder() + .setClaims(claims) + .setId(UUID.randomUUID().toString()) + .setSubject( + "test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()) + .setExpiration(expiresAt.getDate()) + .setIssuedAt(UTCInstant.now().getDate()) + .signWith((Key) privateKey) + .compact(); + } + + protected String createToken(UTCInstant expiresAt, String onset) { + Claims claims = Jwts.claims(); + claims.put("scope", "exposed"); + claims.put("fake", "0"); + claims.put("onset", onset); + return Jwts.builder() + .setClaims(claims) + .setId(UUID.randomUUID().toString()) + .setSubject( + "test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()) + .setExpiration(expiresAt.getDate()) + .setIssuedAt(UTCInstant.now().getDate()) + .signWith((Key) privateKey) + .compact(); + } + + protected String createToken(String subject, UTCInstant expiresAt) { + Claims claims = Jwts.claims(); + claims.put("scope", "exposed"); + claims.put("fake", "0"); + return Jwts.builder() + .setSubject(subject) + .setExpiration(expiresAt.getDate()) + .setClaims(claims) + .setId(UUID.randomUUID().toString()) + .signWith((Key) privateKey) + .compact(); + } + + protected String createToken(boolean fake, UTCInstant expiresAt) { + Claims claims = Jwts.claims(); + claims.put("scope", "exposed"); + claims.put("onset", "2020-04-20"); + claims.put("fake", fake ? "1" : "0"); + return Jwts.builder() + .setClaims(claims) + .setId(UUID.randomUUID().toString()) + .setSubject("test-subject" + UTCInstant.now().getOffsetDateTime().toString()) + .setExpiration(expiresAt.getDate()) + .setIssuedAt(UTCInstant.now().getDate()) + .signWith((Key) privateKey) + .compact(); + } + + protected String createTokenWithScope(UTCInstant expiresAt, String scope) { + Claims claims = Jwts.claims(); + claims.put("scope", scope); + claims.put("fake", "0"); + claims.put("onset", "2020-04-20"); + return Jwts.builder() + .setClaims(claims) + .setId(UUID.randomUUID().toString()) + .setSubject( + "test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()) + .setExpiration(expiresAt.getDate()) + .setIssuedAt(UTCInstant.now().getDate()) + .signWith((Key) privateKey) + .compact(); + } + + protected String createMaliciousToken(UTCInstant expiresAt) { + Claims claims = Jwts.claims(); + claims.put("scope", "exposed"); + claims.put("onset", "2020-04-20"); + claims.put("fake", "0"); + return Jwts.builder() + .setClaims(claims) + .setId(UUID.randomUUID().toString()) + .setSubject( + "test-subject" + OffsetDateTime.now().withOffsetSameInstant(ZoneOffset.UTC).toString()) + .setExpiration(expiresAt.getDate()) + .setIssuedAt(UTCInstant.now().getDate()) + .compact(); + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/CloudControllerTestPEM.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/CloudControllerTestPEM.java index 450d33b7..59197497 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/CloudControllerTestPEM.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/CloudControllerTestPEM.java @@ -15,12 +15,17 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwt; +import io.jsonwebtoken.Jwts; import java.io.IOException; import java.security.PublicKey; import java.time.LocalDate; import java.time.ZoneOffset; import java.util.Base64; - import org.dpppt.backend.sdk.model.ExposeeAuthData; import org.dpppt.backend.sdk.model.ExposeeRequest; import org.dpppt.backend.sdk.ws.filter.ResponseWrapperFilter; @@ -38,62 +43,69 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jwts; - @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "test-cloud" }) -@TestPropertySource(properties = { "ws.app.source=org.dpppt.demo", - "vcap.services.ecdsa_dev.credentials.publicKey=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNTRENDQWU2Z0F3SUJBZ0lVS3pEQlJIZlZVN2djRGZxUTBGUDFLTkJULzVJd0NnWUlLb1pJemowRUF3SXcKZXpFTE1Ba0dBMVVFQmhNQ1EwZ3hEVEFMQmdOVkJBZ01CRUpsY200eERUQUxCZ05WQkFjTUJFSmxjbTR4RERBSwpCZ05WQkFvTUEwSkpWREVNTUFvR0ExVUVDd3dEUlZkS01RMHdDd1lEVlFRRERBUlVaWE4wTVNNd0lRWUpLb1pJCmh2Y05BUWtCRmhSemRYQndiM0owUUdKcGRDNWhaRzFwYmk1amFEQWVGdzB5TURBME1qZ3hNakUwTlRGYUZ3MHkKTVRBME1qZ3hNakUwTlRGYU1Ic3hDekFKQmdOVkJBWVRBa05JTVEwd0N3WURWUVFJREFSQ1pYSnVNUTB3Q3dZRApWUVFIREFSQ1pYSnVNUXd3Q2dZRFZRUUtEQU5DU1ZReEREQUtCZ05WQkFzTUEwVlhTakVOTUFzR0ExVUVBd3dFClZHVnpkREVqTUNFR0NTcUdTSWIzRFFFSkFSWVVjM1Z3Y0c5eWRFQmlhWFF1WVdSdGFXNHVZMmd3VmpBUUJnY3EKaGtqT1BRSUJCZ1VyZ1FRQUNnTkNBQVRhc0ZoMEdLZWs1WTRKdXdnaTVIOEFrL3FmamtKQ3d6N1BYb0lVZWJnaQpzeTdUVlFMckltQlBVN2lnMDM3azBkb1V4aytYZEJLWDQzdi9yZEdZVUtmMW8xTXdVVEFkQmdOVkhRNEVGZ1FVCnVTS2lWSUdsRnpQdDdXd3Z1VGNicDNrckQ0UXdId1lEVlIwakJCZ3dGb0FVdVNLaVZJR2xGelB0N1d3dnVUY2IKcDNrckQ0UXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQkRteEJUQ3BZawphN0hFeUFEWnN4d3p3b2h0TjBwNTd5QllMYjZzQ3B3ODhBSWhBSXpTUDdCV0tGWmNDSmI5ZmhwcjZaTXpJd0tlCkhhSWpIK2E4elV2Nk1PaW8KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=", - "vcap.services.ecdsa_dev.credentials.privateKey=LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0VBZ0VBTUJBR0J5cUdTTTQ5QWdFR0JTdUJCQUFLQkcwd2F3SUJBUVFnMkRsai9lNW5rRlBtTk1MVjd1NjQKenFuOHdSeVgrUTgyc045RDRSWXlvNjJoUkFOQ0FBVGFzRmgwR0tlazVZNEp1d2dpNUg4QWsvcWZqa0pDd3o3UApYb0lVZWJnaXN5N1RWUUxySW1CUFU3aWcwMzdrMGRvVXhrK1hkQktYNDN2L3JkR1lVS2YxCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K" }) +@ActiveProfiles({"test-cloud"}) +@TestPropertySource( + properties = { + "ws.app.source=org.dpppt.demo", + "vcap.services.ecdsa_dev.credentials.publicKey=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNTRENDQWU2Z0F3SUJBZ0lVS3pEQlJIZlZVN2djRGZxUTBGUDFLTkJULzVJd0NnWUlLb1pJemowRUF3SXcKZXpFTE1Ba0dBMVVFQmhNQ1EwZ3hEVEFMQmdOVkJBZ01CRUpsY200eERUQUxCZ05WQkFjTUJFSmxjbTR4RERBSwpCZ05WQkFvTUEwSkpWREVNTUFvR0ExVUVDd3dEUlZkS01RMHdDd1lEVlFRRERBUlVaWE4wTVNNd0lRWUpLb1pJCmh2Y05BUWtCRmhSemRYQndiM0owUUdKcGRDNWhaRzFwYmk1amFEQWVGdzB5TURBME1qZ3hNakUwTlRGYUZ3MHkKTVRBME1qZ3hNakUwTlRGYU1Ic3hDekFKQmdOVkJBWVRBa05JTVEwd0N3WURWUVFJREFSQ1pYSnVNUTB3Q3dZRApWUVFIREFSQ1pYSnVNUXd3Q2dZRFZRUUtEQU5DU1ZReEREQUtCZ05WQkFzTUEwVlhTakVOTUFzR0ExVUVBd3dFClZHVnpkREVqTUNFR0NTcUdTSWIzRFFFSkFSWVVjM1Z3Y0c5eWRFQmlhWFF1WVdSdGFXNHVZMmd3VmpBUUJnY3EKaGtqT1BRSUJCZ1VyZ1FRQUNnTkNBQVRhc0ZoMEdLZWs1WTRKdXdnaTVIOEFrL3FmamtKQ3d6N1BYb0lVZWJnaQpzeTdUVlFMckltQlBVN2lnMDM3azBkb1V4aytYZEJLWDQzdi9yZEdZVUtmMW8xTXdVVEFkQmdOVkhRNEVGZ1FVCnVTS2lWSUdsRnpQdDdXd3Z1VGNicDNrckQ0UXdId1lEVlIwakJCZ3dGb0FVdVNLaVZJR2xGelB0N1d3dnVUY2IKcDNrckQ0UXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QUtCZ2dxaGtqT1BRUURBZ05JQURCRkFpQkRteEJUQ3BZawphN0hFeUFEWnN4d3p3b2h0TjBwNTd5QllMYjZzQ3B3ODhBSWhBSXpTUDdCV0tGWmNDSmI5ZmhwcjZaTXpJd0tlCkhhSWpIK2E4elV2Nk1PaW8KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=", + "vcap.services.ecdsa_dev.credentials.privateKey=LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0VBZ0VBTUJBR0J5cUdTTTQ5QWdFR0JTdUJCQUFLQkcwd2F3SUJBUVFnMkRsai9lNW5rRlBtTk1MVjd1NjQKenFuOHdSeVgrUTgyc045RDRSWXlvNjJoUkFOQ0FBVGFzRmgwR0tlazVZNEp1d2dpNUg4QWsvcWZqa0pDd3o3UApYb0lVZWJnaXN5N1RWUUxySW1CUFU3aWcwMzdrMGRvVXhrK1hkQktYNDN2L3JkR1lVS2YxCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K" + }) public class CloudControllerTestPEM { - protected MockMvc mockMvc; - @Autowired - private WebApplicationContext webApplicationContext; - protected ObjectMapper objectMapper; - - @Autowired - private ResponseWrapperFilter filter; - // private String publicKey = - // "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc6n1FNz6RnwNeNM9H+KxaPckrBxgKU799v+DTy8ivc1ZM3nDyXq5zU2AFXvgvLFzWxU9z9FCcDPGTcN7cvOyXw=="; - private PublicKey publicKey; + protected MockMvc mockMvc; + @Autowired private WebApplicationContext webApplicationContext; + protected ObjectMapper objectMapper; - @Before - public void setup() throws Exception { - this.publicKey = filter.getPublicKey(); - this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilter(filter, "/*").build(); - this.objectMapper = new ObjectMapper(new JsonFactory()); - this.objectMapper.registerModule(new JavaTimeModule()); + @Autowired private ResponseWrapperFilter filter; + // private String publicKey = + // "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc6n1FNz6RnwNeNM9H+KxaPckrBxgKU799v+DTy8ivc1ZM3nDyXq5zU2AFXvgvLFzWxU9z9FCcDPGTcN7cvOyXw=="; + private PublicKey publicKey; - } + @Before + public void setup() throws Exception { + this.publicKey = filter.getPublicKey(); + this.mockMvc = + MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilter(filter, "/*").build(); + this.objectMapper = new ObjectMapper(new JsonFactory()); + this.objectMapper.registerModule(new JavaTimeModule()); + } - @Test - public void testJWT() throws Exception { + @Test + public void testJWT() throws Exception { - ExposeeRequest exposeeRequest = new ExposeeRequest(); - exposeeRequest.setAuthData(new ExposeeAuthData()); - exposeeRequest.setKeyDate(LocalDate.now().atStartOfDay().atOffset(ZoneOffset.UTC).toInstant().toEpochMilli()); - exposeeRequest.setKey(Base64.getEncoder().encodeToString("testKey32Bytes--testKey32Bytes--".getBytes("UTF-8"))); - MockHttpServletResponse response = mockMvc.perform(post("/v1/exposed").contentType(MediaType.APPLICATION_JSON) - .header("User-Agent", "MockMVC").content(json(exposeeRequest))).andExpect(status().is2xxSuccessful()) - .andReturn().getResponse(); - response = mockMvc.perform(get("/v1/")).andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - String content = response.getContentAsString(); - assertEquals("Hello from DP3T WS", content); - assertEquals("dp3t", response.getHeader("X-HELLO")); - String signature = response.getHeader("Signature"); - Jwt jwt = Jwts.parserBuilder().setSigningKey(publicKey).build().parse(signature); - Claims claims = (Claims) jwt.getBody(); - assertEquals("dp3t", claims.get("iss")); - } + ExposeeRequest exposeeRequest = new ExposeeRequest(); + exposeeRequest.setAuthData(new ExposeeAuthData()); + exposeeRequest.setKeyDate( + LocalDate.now().atStartOfDay().atOffset(ZoneOffset.UTC).toInstant().toEpochMilli()); + exposeeRequest.setKey( + Base64.getEncoder().encodeToString("testKey32Bytes--testKey32Bytes--".getBytes("UTF-8"))); + MockHttpServletResponse response = + mockMvc + .perform( + post("/v1/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("User-Agent", "MockMVC") + .content(json(exposeeRequest))) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + response = + mockMvc + .perform(get("/v1/")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + String content = response.getContentAsString(); + assertEquals("Hello from DP3T WS", content); + assertEquals("dp3t", response.getHeader("X-HELLO")); + String signature = response.getHeader("Signature"); + Jwt jwt = Jwts.parserBuilder().setSigningKey(publicKey).build().parse(signature); + Claims claims = (Claims) jwt.getBody(); + assertEquals("dp3t", claims.get("iss")); + } - protected String json(Object o) throws IOException { - return objectMapper.writeValueAsString(o); - } -} \ No newline at end of file + protected String json(Object o) throws IOException { + return objectMapper.writeValueAsString(o); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerNoFilledZipsTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerNoFilledZipsTest.java index b07b1e86..6e15d563 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerNoFilledZipsTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerNoFilledZipsTest.java @@ -1,36 +1,41 @@ package org.dpppt.backend.sdk.ws.controller; -import org.junit.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.transaction.annotation.Transactional; - - import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.dpppt.backend.sdk.utils.UTCInstant; +import org.junit.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.transaction.annotation.Transactional; -@SpringBootTest(properties = { - "ws.app.jwt.publickey=classpath://generated_pub.pem", - "logging.level.org.springframework.security=DEBUG", "ws.exposedlist.releaseBucketDuration=7200000", - "ws.gaen.randomkeysenabled=false" }) +@SpringBootTest( + properties = { + "ws.app.jwt.publickey=classpath://generated_pub.pem", + "logging.level.org.springframework.security=DEBUG", + "ws.exposedlist.releaseBucketDuration=7200000", + "ws.gaen.randomkeysenabled=false" + }) public class GaenControllerNoFilledZipsTest extends BaseControllerTest { - @Test - @Transactional - public void testEmptyResponseWhenNoZipFill() throws Exception { - MockHttpServletResponse response = mockMvc - .perform(get("/v1/gaen/exposed/" + UTCInstant.today().minusDays(8).getTimestamp()) - .header("User-Agent", "MockMVC")) - .andExpect(status().isNoContent()).andReturn().getResponse(); - - var etag = response.getHeader("ETag"); - var firstPublishUntil = response.getHeader("X-PUBLISHED-UNTIL"); - var signature = response.getHeader("Signature"); - assertNotNull(signature); - assertNotNull(firstPublishUntil); - assertNull(etag); - } -} \ No newline at end of file + @Test + @Transactional + public void testEmptyResponseWhenNoZipFill() throws Exception { + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + UTCInstant.today().minusDays(8).getTimestamp()) + .header("User-Agent", "MockMVC")) + .andExpect(status().isNoContent()) + .andReturn() + .getResponse(); + + var etag = response.getHeader("ETag"); + var firstPublishUntil = response.getHeader("X-PUBLISHED-UNTIL"); + var signature = response.getHeader("Signature"); + assertNotNull(signature); + assertNotNull(firstPublishUntil); + assertNull(etag); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTest.java index 6db04dce..cc64a56e 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTest.java @@ -21,6 +21,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import io.jsonwebtoken.Jwt; +import io.jsonwebtoken.Jwts; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.InvalidKeyException; @@ -37,8 +39,6 @@ import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; - - import org.dpppt.backend.sdk.data.gaen.GAENDataService; import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.GaenRequest; @@ -60,1095 +60,1414 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.transaction.annotation.Transactional; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jwts; - -@ActiveProfiles({ "actuator-security" }) -@SpringBootTest(properties = { "ws.app.jwt.publickey=classpath://generated_pub.pem", - "logging.level.org.springframework.security=DEBUG", "ws.exposedlist.releaseBucketDuration=7200000", - "ws.gaen.randomkeysenabled=true", "ws.monitor.prometheus.user=prometheus", - "ws.monitor.prometheus.password=prometheus", "management.endpoints.enabled-by-default=true", - "management.endpoints.web.exposure.include=*" }) +@ActiveProfiles({"actuator-security"}) +@SpringBootTest( + properties = { + "ws.app.jwt.publickey=classpath://generated_pub.pem", + "logging.level.org.springframework.security=DEBUG", + "ws.exposedlist.releaseBucketDuration=7200000", + "ws.gaen.randomkeysenabled=true", + "ws.monitor.prometheus.user=prometheus", + "ws.monitor.prometheus.password=prometheus", + "management.endpoints.enabled-by-default=true", + "management.endpoints.web.exposure.include=*" + }) @Transactional public class GaenControllerTest extends BaseControllerTest { - @Autowired - ProtoSignature signer; - @Autowired - KeyVault keyVault; - @Autowired - GAENDataService gaenDataService; - Long releaseBucketDuration = 7200000L; - - private static final Logger logger = LoggerFactory.getLogger(GaenControllerTest.class); - - @Test - public void testHello() throws Exception { - MockHttpServletResponse response = mockMvc.perform(get("/v1")).andExpect(status().is2xxSuccessful()).andReturn() - .getResponse(); - - assertNotNull(response); - assertEquals("Hello from DP3T WS", response.getContentAsString()); - } - - @Test - public void testActuatorSecurity() throws Exception { - var response = mockMvc.perform(get("/actuator/health")).andExpect(status().is2xxSuccessful()).andReturn() - .getResponse(); - response = mockMvc.perform(get("/actuator/loggers")).andExpect(status().is(401)).andReturn().getResponse(); - response = mockMvc - .perform(get("/actuator/loggers").header("Authorization", "Basic cHJvbWV0aGV1czpwcm9tZXRoZXVz")) - .andExpect(status().isOk()).andReturn().getResponse(); - response = mockMvc.perform(get("/actuator/prometheus")).andExpect(status().is(401)).andReturn().getResponse(); - response = mockMvc - .perform(get("/actuator/prometheus").header("Authorization", "Basic cHJvbWV0aGV1czpwcm9tZXRoZXVz")) - .andExpect(status().isOk()).andReturn().getResponse(); - } - - private void testNKeys(UTCInstant now, int n, boolean shouldSucceed) throws Exception { - var requestList = new GaenRequest(); - var gaenKey1 = new GaenKey(); - gaenKey1.setRollingStartNumber((int) now.atStartOfDay().minusDays(1).get10MinutesSince1970()); - gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes01".getBytes("UTF-8"))); - gaenKey1.setRollingPeriod(144); - gaenKey1.setFake(0); - gaenKey1.setTransmissionRiskLevel(0); - var gaenKey2 = new GaenKey(); - gaenKey2.setRollingStartNumber((int) now.atStartOfDay().minusDays(1).get10MinutesSince1970()); - gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes02".getBytes("UTF-8"))); - gaenKey2.setRollingPeriod(144); - gaenKey2.setFake(0); - gaenKey2.setTransmissionRiskLevel(0); - List exposedKeys = new ArrayList<>(); - exposedKeys.add(gaenKey1); - exposedKeys.add(gaenKey2); - for (int i = 0; i < n - 2; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) now.atStartOfDay().get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - exposedKeys.add(tmpKey); - } - requestList.setGaenKeys(exposedKeys); - var duration = now.atStartOfDay().plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - gaenKey1.setFake(0); - String token = createToken(now.plusMinutes(5)); - var requestBuilder = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))); - MvcResult response; - - if (shouldSucceed) { - response = requestBuilder.andExpect(request().asyncStarted()).andReturn(); - mockMvc.perform(asyncDispatch(response)).andExpect(status().is2xxSuccessful()); - } else { - response = requestBuilder.andExpect(status().is(400)).andReturn(); - return; - } - response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(request().asyncNotStarted()).andExpect(content().string("")) - .andReturn(); - - var result = gaenDataService.getSortedExposedForKeyDate(now.atStartOfDay().minusDays(1).getTimestamp(), null, - (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); - assertEquals(2, result.size()); - for (var key : result) { - assertEquals(Integer.valueOf(144), key.getRollingPeriod()); - } - - result = gaenDataService.getSortedExposedForKeyDate(now.atStartOfDay().minusDays(1).getTimestamp(), null, - (now.getTimestamp() / releaseBucketDuration) * releaseBucketDuration); - assertEquals(0, result.size()); - } - - @Test - public void testAllKeysWrongButStill200() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - var requestList = new GaenRequest(); - var gaenKey1 = new GaenKey(); - - gaenKey1.setRollingStartNumber((int) midnight.minusDays(30).get10MinutesSince1970()); - gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes01".getBytes("UTF-8"))); - gaenKey1.setRollingPeriod(0); - gaenKey1.setFake(0); - gaenKey1.setTransmissionRiskLevel(0); - var gaenKey2 = new GaenKey(); - gaenKey2.setRollingStartNumber((int) midnight.minusDays(1).get10MinutesSince1970()); - gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes02".getBytes("UTF-8"))); - gaenKey2.setRollingPeriod(-10); - gaenKey2.setFake(0); - gaenKey2.setTransmissionRiskLevel(0); - List exposedKeys = new ArrayList<>(); - exposedKeys.add(gaenKey1); - exposedKeys.add(gaenKey2); - for (int i = 0; i < 12; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) midnight.plusDays(10).get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - exposedKeys.add(tmpKey); - } - requestList.setGaenKeys(exposedKeys); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - gaenKey1.setFake(0); - String token = createToken(now.plusMinutes(5)); - MvcResult response = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncStarted()) - .andReturn(); - - mockMvc.perform(asyncDispatch(response)).andExpect(status().is2xxSuccessful()); - response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(request().asyncNotStarted()).andExpect(content().string("")) - .andReturn(); - - var result = gaenDataService.getSortedExposedForKeyDate(midnight.minusDays(1).getTimestamp(), null, - (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); - // all keys are in compatible - assertEquals(0, result.size()); - } - - @Transactional - public void testMultipleKeyUpload() throws Exception { - testNKeys(UTCInstant.now(), 14, true); - } - - @Test - @Transactional - public void testCanUploadMoreThan14Keys() throws Exception { - testNKeys(UTCInstant.now(), 30, true); - } - - @Test - @Transactional - public void testCannotUploadMoreThan30Keys() throws Exception { - testNKeys(UTCInstant.now(), 31, false); - testNKeys(UTCInstant.now(), 100, false); - testNKeys(UTCInstant.now(), 1000, false); - } - - private Map headers = Map.of("X-Content-Type-Options", "nosniff", "X-Frame-Options", "DENY", - "X-Xss-Protection", "1; mode=block"); - - @Test - public void testSecurityHeaders() throws Exception { - MockHttpServletResponse response = mockMvc.perform(get("/v1")).andExpect(status().is2xxSuccessful()).andReturn() - .getResponse(); - for (var header : headers.keySet()) { - assertTrue(response.containsHeader(header)); - assertEquals(headers.get(header), response.getHeader(header)); - } - var now = UTCInstant.now(); - var midnight = UTCInstant.today(); - response = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - for(var header : headers.keySet()) { - assertTrue(response.containsHeader(header)); - assertEquals(headers.get(header), response.getHeader(header)); - } - } - - @Test - public void testUploadWithNegativeRollingPeriodFails() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - var requestList = new GaenRequest(); - var gaenKey1 = new GaenKey(); - gaenKey1.setRollingStartNumber((int) midnight.get10MinutesSince1970()); - gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey1.setRollingPeriod(-1); - gaenKey1.setFake(0); - gaenKey1.setTransmissionRiskLevel(0); - var gaenKey2 = new GaenKey(); - gaenKey2.setRollingStartNumber((int) midnight.minusDays(1).get10MinutesSince1970()); - gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey2.setRollingPeriod(-5); - gaenKey2.setFake(0); - gaenKey2.setTransmissionRiskLevel(0); - List exposedKeys = new ArrayList<>(); - exposedKeys.add(gaenKey1); - exposedKeys.add(gaenKey2); - for (int i = 0; i < 12; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - exposedKeys.add(tmpKey); - } - requestList.setGaenKeys(exposedKeys); - var duration = (int) midnight.plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - gaenKey1.setFake(0); - String token = createToken(now.plusMinutes(5)); - MvcResult response = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncStarted()) - .andReturn(); - - mockMvc.perform(asyncDispatch(response)).andExpect(status().is(200)); - - var result = gaenDataService.getSortedExposedForKeyDate(midnight.minusDays(1).getTimestamp(), null, - (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); - // all keys are invalid - assertEquals(0, result.size()); - result = gaenDataService.getSortedExposedForKeyDate(midnight.getTimestamp(), null, - (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); - // all keys are invalid - assertEquals(0, result.size()); - } - - @Test - public void testMultipleKeyUploadFake() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - var requestList = new GaenRequest(); - var gaenKey1 = new GaenKey(); - gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey1.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - gaenKey1.setRollingPeriod(144); - gaenKey1.setTransmissionRiskLevel(0); - var gaenKey2 = new GaenKey(); - gaenKey2.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey2.setRollingPeriod(144); - gaenKey2.setTransmissionRiskLevel(0); - - gaenKey1.setFake(1); - gaenKey2.setFake(1); - - List exposedKeys = new ArrayList<>(); - exposedKeys.add(gaenKey1); - exposedKeys.add(gaenKey2); - for (int i = 0; i < 12; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - exposedKeys.add(tmpKey); - } - requestList.setGaenKeys(exposedKeys); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - - String token = createToken(true, now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncStarted()) - .andReturn(); - mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is2xxSuccessful()); - MockHttpServletResponse response = mockMvc - .perform(post("/v1/gaen/exposedlist").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(content().string("")).andReturn().getResponse(); - } - - @Test - public void testMultipleKeyUploadFakeAllKeysNeedToBeFake() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - var requestList = new GaenRequest(); - var gaenKey1 = new GaenKey(); - gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey1.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - gaenKey1.setRollingPeriod(144); - gaenKey1.setTransmissionRiskLevel(0); - var gaenKey2 = new GaenKey(); - gaenKey2.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey2.setRollingPeriod(144); - gaenKey2.setTransmissionRiskLevel(0); - - gaenKey1.setFake(0); - gaenKey2.setFake(1); - - List exposedKeys = new ArrayList<>(); - exposedKeys.add(gaenKey1); - exposedKeys.add(gaenKey2); - for (int i = 0; i < 12; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - exposedKeys.add(tmpKey); - } - requestList.setGaenKeys(exposedKeys); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - - String token = createToken(true, now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncStarted()) - .andReturn(); - mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is2xxSuccessful()); - MockHttpServletResponse response = mockMvc - .perform(post("/v1/gaen/exposedlist").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(content().string("")).andReturn().getResponse(); - } - - @Test - public void testMultipleKeyUploadFakeIfJWTNotFakeAllKeysCanBeFake() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - var requestList = new GaenRequest(); - var gaenKey1 = new GaenKey(); - gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey1.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - gaenKey1.setRollingPeriod(144); - gaenKey1.setTransmissionRiskLevel(0); - var gaenKey2 = new GaenKey(); - gaenKey2.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - gaenKey2.setRollingPeriod(144); - gaenKey2.setTransmissionRiskLevel(0); - - gaenKey1.setFake(1); - gaenKey2.setFake(1); - - List exposedKeys = new ArrayList<>(); - exposedKeys.add(gaenKey1); - exposedKeys.add(gaenKey2); - for (int i = 0; i < 12; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - exposedKeys.add(tmpKey); - } - requestList.setGaenKeys(exposedKeys); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - - String token = createToken(false, now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncStarted()) - .andReturn(); - mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is2xxSuccessful()); - MockHttpServletResponse response = mockMvc - .perform(post("/v1/gaen/exposedlist").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(content().string("")).andReturn().getResponse(); - } - - @Test - public void testMultipleKeyNonEmptyUpload() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - var requestList = new GaenRequest(); - List exposedKeys = new ArrayList(); - requestList.setGaenKeys(exposedKeys); - String token = createToken(now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncNotStarted()).andExpect(status().is(400)).andReturn(); - - MockHttpServletResponse response = mockMvc - .perform(post("/v1/gaen/exposedlist").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(content().string("")).andReturn().getResponse(); - } - - @Test - public void testMultipleKeyNonNullUpload() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - var requestList = new GaenRequest(); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - requestList.setDelayedKeyDate((int) duration); - - String token = createToken(now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(requestList))).andExpect(request().asyncNotStarted()).andExpect(status().is(400)).andReturn(); - - MockHttpServletResponse response = mockMvc - .perform(post("/v1/gaen/exposedlist").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtToken).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(requestList))) - .andExpect(status().is(401)).andExpect(content().string("")).andReturn().getResponse(); - } - - @Test - public void keyNeedsToBeBase64() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate((int) duration); - GaenKey key = new GaenKey(); - key.setKeyData("00000000testKey32Bytes--"); - key.setRollingPeriod(144); - key.setRollingStartNumber((int) now.get10MinutesSince1970()); - key.setTransmissionRiskLevel(1); - key.setFake(0); - List keys = new ArrayList<>(); - keys.add(key); - for (int i = 0; i < 13; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - - String token = createToken(false, now.plusMinutes(5)); - mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(status().is(400)).andReturn(); - } - - @Test - public void testKeyDateBeforeOnsetIsNotInserted() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate((int) duration); - GaenKey key = new GaenKey(); - key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - key.setRollingPeriod(144); - key.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(2)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - key.setTransmissionRiskLevel(1); - key.setFake(0); - List keys = new ArrayList<>(); - keys.add(key); - for (int i = 0; i < 13; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) now.get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - - String token = createToken(now.plusMinutes(5), - now.getLocalDate().format(DateTimeFormatter.ISO_DATE)); - MvcResult response = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(request().asyncStarted()).andExpect(status().is(200)).andReturn(); - var result = gaenDataService.getSortedExposedForKeyDate(midnight.minusDays(2).getTimestamp(),null, (now.getTimestamp() / releaseBucketDuration + 1 )*releaseBucketDuration); - assertEquals(0, result.size()); - } - - @Test - public void cannotUseExpiredToken() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate((int) duration); - GaenKey key = new GaenKey(); - key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - key.setRollingPeriod(144); - key.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - key.setTransmissionRiskLevel(1); - key.setFake(1); - List keys = new ArrayList<>(); - keys.add(key); - for (int i = 0; i < 13; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - - String token = createToken(now.minusMinutes(5)); - - MvcResult response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + token).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(exposeeRequest))) - .andExpect(request().asyncNotStarted()).andExpect(status().is4xxClientError()).andReturn(); - } - - @Test - public void cannotUseKeyDateInFuture() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - exposeeRequest.setDelayedKeyDate((int) midnight.get10MinutesSince1970()); - GaenKey key = new GaenKey(); - key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes++".getBytes("UTF-8"))); - key.setRollingPeriod(144); - key.setRollingStartNumber((int) midnight.plusDays(2).get10MinutesSince1970()); - key.setTransmissionRiskLevel(1); - key.setFake(0); - List keys = new ArrayList<>(); - keys.add(key); - for (int i = 0; i < 13; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes++".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - - String token = createToken(now.plusMinutes(5)); - - MvcResult response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + token).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(exposeeRequest))).andExpect(status().is(200)).andReturn(); - var result = gaenDataService.getSortedExposedForKeyDate(midnight.plusDays(2).getTimestamp(),null, (now.getTimestamp() / releaseBucketDuration + 1 )*releaseBucketDuration); - assertEquals(0, result.size()); - } - - @Test - public void keyDateNotOlderThan21Days() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate((int) duration); - GaenKey key = new GaenKey(); - key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - key.setRollingPeriod(144); - key.setRollingStartNumber((int) midnight.minusDays(22).get10MinutesSince1970()); - key.setTransmissionRiskLevel(1); - key.setFake(0); - List keys = new ArrayList<>(); - keys.add(key); - for (int i = 0; i < 13; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber( - (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - - String token = createToken(now.plusMinutes(5), "2020-01-01"); - - MvcResult response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + token).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(exposeeRequest))) - .andExpect(request().asyncStarted()).andExpect(status().is(200)).andReturn(); - var result = gaenDataService.getSortedExposedForKeyDate(midnight.minusDays(22).getTimestamp(), null, - (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); - assertEquals(0, result.size()); - } - - @Test - public void cannotUseTokenWithWrongScope() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - var duration = midnight.plusDays(1).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate((int) duration); - GaenKey key = new GaenKey(); - key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - key.setRollingPeriod(144); - key.setRollingStartNumber((int) now.get10MinutesSince1970()); - key.setTransmissionRiskLevel(1); - key.setFake(1); - List keys = new ArrayList<>(); - keys.add(key); - for (int i = 0; i < 13; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) now.get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(1); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - - String token = createTokenWithScope(now.plusMinutes(5), "not-exposed"); - - MvcResult response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + token).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(exposeeRequest))) - .andExpect(status().is(403)) - .andReturn(); - - // Also for a 403 response, the token cannot be used a 2nd time - response = mockMvc - .perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + token).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(exposeeRequest))) - .andExpect(request().asyncNotStarted()).andExpect(status().is(401)).andExpect(content().string("")) - .andReturn(); - } - - @Test - public void uploadKeysAndUploadKeyNextDay() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - List keys = new ArrayList<>(); - for (int i = 0; i < 14; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - var delayedKeyDateSent = (int) midnight.get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); - exposeeRequest.setGaenKeys(keys); - String token = createToken(now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(request().asyncStarted()).andReturn(); - MockHttpServletResponse response = mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is(200)).andReturn().getResponse(); - assertTrue(response.containsHeader("Authorization"), "Authorization header not found in response"); - String jwtString = response.getHeader("Authorization").replace("Bearer ", ""); - Jwt jwtToken = Jwts.parserBuilder().setSigningKey(keyVault.get("nextDayJWT").getPublic()).build() - .parse(jwtString); - GaenSecondDay secondDay = new GaenSecondDay(); - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber(delayedKeyDateSent); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - secondDay.setDelayedKey(tmpKey); - responseAsync = mockMvc.perform(post("/v1/gaen/exposednextday").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtString).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(secondDay))).andExpect(request().asyncStarted()).andReturn(); - mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is(200)); - } - - //@Test - //TODO: Is this still a requirement? Currently the key just gets filtered out - public void uploadKeysAndUploadKeyNextDayWithNegativeRollingPeriodFails() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - List keys = new ArrayList<>(); - for (int i = 0; i < 14; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - var delayedKeyDateSent = (int) midnight.get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); - exposeeRequest.setGaenKeys(keys); - String token = createToken(now.plusMinutes(5)); - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(request().asyncStarted()).andReturn(); - MockHttpServletResponse response = mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is(200)).andReturn().getResponse(); - assertTrue(response.containsHeader("Authorization"), "Authorization header not found in response"); - String jwtString = response.getHeader("Authorization").replace("Bearer ", ""); - Jwt jwtToken = Jwts.parserBuilder().setSigningKey(keyVault.get("nextDayJWT").getPublic()).build() - .parse(jwtString); - GaenSecondDay secondDay = new GaenSecondDay(); - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber(delayedKeyDateSent); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(-1); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - secondDay.setDelayedKey(tmpKey); - responseAsync = mockMvc.perform(post("/v1/gaen/exposednextday").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + jwtString).header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") - .content(json(secondDay))).andExpect(request().asyncStarted()).andReturn(); - mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().isBadRequest()); - } - - @Test - public void delayedKeyDateBoundaryCheck() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - List keys = new ArrayList<>(); - for (int i = 0; i < 14; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) midnight.minusDays(1).get10MinutesSince1970()); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - - Map tests = Map.of( - -2, false, - -1, true, - 0, true, - 1, true, - 2, false); - - for (Map.Entry t : tests.entrySet()) { - Integer offset = t.getKey(); - Boolean pass = t.getValue(); - logger.info("Testing offset {} which should pass {}", offset, pass); - var delayedKeyDateSent = (int) midnight.plusDays(offset).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); - exposeeRequest.setGaenKeys(keys); - String token = createToken(now.plusMinutes(5)); - if (pass) { - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(request().asyncStarted()).andReturn(); - mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is(200)).andReturn().getResponse(); - } else { - MvcResult responseAsync = mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(status().is(400)).andReturn(); - - } - } - } - - @Test - public void testTokenValiditySurpassesMaxJwtValidity() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - GaenRequest exposeeRequest = new GaenRequest(); - List keys = new ArrayList<>(); - for (int i = 0; i < 14; i++) { - var tmpKey = new GaenKey(); - tmpKey.setRollingStartNumber((int) Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) - .dividedBy(Duration.ofMinutes(10))); - tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); - tmpKey.setRollingPeriod(144); - tmpKey.setFake(0); - tmpKey.setTransmissionRiskLevel(0); - keys.add(tmpKey); - } - exposeeRequest.setGaenKeys(keys); - var delayedKeyDateSent = (int) midnight.plusDays(1).get10MinutesSince1970(); - exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); - int maxJWTValidityInMinutes = 60; - String token = createToken(now.plusMinutes(maxJWTValidityInMinutes + 1)); - - mockMvc.perform(post("/v1/gaen/exposed") - .contentType(MediaType.APPLICATION_JSON).header("Authorization", "Bearer " + token) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").content(json(exposeeRequest))).andExpect(status().is(401)); -} - - @Test - public void testDebugController() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - // insert two times 10 keys per day for the last 14 days, with different - // received at. In total: 280 keys - insertNKeysPerDay(midnight, 14, 10, midnight.minusDays(1), true); - insertNKeysPerDay(midnight, 14, 10, midnight.minusHours(12), true); - - // Request keys which have been received in the last day, must be 280 in total. - // This is the debug controller, which returns keys based on the 'received at', - // not based on the key date. So this request should return all keys with - // 'received at' of the last day. - - MockHttpServletResponse response = mockMvc - .perform(get("/v1/debug/exposed/" - + midnight.getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - verifyZipInZipResponse(response, 280, 144); - } - - @Test - @Transactional - public void zipContainsFiles() throws Exception { - var now = UTCInstant.now(); - var clock = Clock.offset(Clock.systemUTC(), now.getDuration(now.atStartOfDay().plusHours(12))); - UTCInstant.setClock(clock); - now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - // Insert two times 5 keys per day for the last 14 days. the second batch has a - // different 'received at' timestamp. (+12 hours compared to the first) - insertNKeysPerDay(midnight, 14, 5, midnight.minusDays(1), false); - insertNKeysPerDay(midnight, 14, 5, midnight.minusHours(12), false); - - // request the keys with key date 8 days ago. no publish until. - MockHttpServletResponse response = mockMvc - .perform( - get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()).header("User-Agent", "MockMVC")) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - Long publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); - assertTrue(publishedUntil < now.getTimestamp(), "Published until must be in the past"); - - // must contain 20 keys: 5 from the first insert, 5 from the second insert and - // 10 random keys - verifyZipResponse(response, 20, 144); - - // request again the keys with date date 8 days ago. with publish until, so that - // we only get the second batch. - var bucketAfterSecondRelease = midnight.minusHours(12); - - MockHttpServletResponse responseWithPublishedAfter = mockMvc - .perform(get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()).header("User-Agent", "MockMVC") - .param("publishedafter", Long.toString(bucketAfterSecondRelease.getTimestamp()))) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - // must contain 15 keys: 5 from the second insert and 10 random keys - verifyZipResponse(responseWithPublishedAfter, 15, 144); - UTCInstant.resetClock(); - } - - @Test - @Transactional(transactionManager = "testTransactionManager") - public void testNonEmptyResponseAnd304() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - MockHttpServletResponse response = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - .andExpect(status().isOk()).andReturn().getResponse(); - verifyZipResponse(response, 10, 144); - } - - @Test - @Transactional(transactionManager = "testTransactionManager") - public void testTodayWeDontHaveKeys() throws Exception { - var midnight = UTCInstant.today(); - MockHttpServletResponse response = mockMvc - .perform(get("/v1/gaen/exposed/" + midnight.getTimestamp()).header("User-Agent", "MockMVC")) - .andExpect(status().is(204)).andReturn().getResponse(); - } - - // @Test - // @Transactional(transactionManager = "testTransactionManager") - public void testEtag() throws Exception { - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - insertNKeysPerDay(midnight, 14, 10, midnight.minusDays(1), false); - insertNKeysPerDay(midnight, 14, 10, midnight.minusHours(12), false); - - // request the keys with date date 1 day ago. no publish until. - MockHttpServletResponse response = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - Long publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); - assertTrue(publishedUntil < System.currentTimeMillis(), "Published until must be in the past"); - var expectedEtag = response.getHeader("etag"); - - response = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); - assertTrue(publishedUntil < System.currentTimeMillis(), "Published until must be in the past"); - assertEquals(expectedEtag, response.getHeader("etag")); - - insertNKeysPerDay(midnight, 14, 10, midnight.minusHours(12), false); - response = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); - assertTrue(publishedUntil < System.currentTimeMillis(), "Published until must be in the past"); - assertNotEquals(expectedEtag, response.getHeader("etag")); - } - - @Test - public void testMalciousTokenFails() throws Exception { - var requestList = new GaenRequest(); - List exposedKeys = new ArrayList(); - requestList.setGaenKeys(exposedKeys); - String token = createMaliciousToken(UTCInstant.now().plusMinutes(5)); - MvcResult response = mockMvc.perform(post("/v1/gaen/exposed").contentType(MediaType.APPLICATION_JSON) - .header("Authorization", "Bearer " + token).header("User-Agent", "MockMVC").content(json(requestList))) - .andExpect(request().asyncNotStarted()).andExpect(status().is(401)).andReturn(); - String authenticateError = response.getResponse().getHeader("www-authenticate"); - assertTrue(authenticateError.contains("Unsigned Claims JWTs are not supported.")); - } - - /** - * Verifies a zip in zip response, that each inner zip is again valid. - */ - private void verifyZipInZipResponse(MockHttpServletResponse response, int expectKeyCount, int expectedRollingPeriod) - throws Exception { - ByteArrayInputStream baisOuter = new ByteArrayInputStream(response.getContentAsByteArray()); - ZipInputStream zipOuter = new ZipInputStream(baisOuter); - ZipEntry entry = zipOuter.getNextEntry(); - while (entry != null) { - ZipInputStream zipInner = new ZipInputStream(new ByteArrayInputStream(zipOuter.readAllBytes())); - verifyKeyZip(zipInner, expectKeyCount, expectedRollingPeriod); - entry = zipOuter.getNextEntry(); - } - } - - /** - * Verifies a zip response, checks if keys and signature is correct. - */ - private void verifyZipResponse(MockHttpServletResponse response, int expectKeyCount, int expectedRollingPeriod) - throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { - ByteArrayInputStream baisZip = new ByteArrayInputStream(response.getContentAsByteArray()); - ZipInputStream keyZipInputstream = new ZipInputStream(baisZip); - verifyKeyZip(keyZipInputstream, expectKeyCount, expectedRollingPeriod); - } - - private void verifyKeyZip(ZipInputStream keyZipInputstream, int expectKeyCount, int expectedRollingPeriod) - throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { - ZipEntry entry = keyZipInputstream.getNextEntry(); - boolean foundData = false; - boolean foundSignature = false; - - byte[] signatureProto = null; - byte[] exportBin = null; - byte[] keyProto = null; - - while (entry != null) { - if (entry.getName().equals("export.bin")) { - foundData = true; - exportBin = keyZipInputstream.readAllBytes(); - keyProto = new byte[exportBin.length - 16]; - System.arraycopy(exportBin, 16, keyProto, 0, keyProto.length); - } - if (entry.getName().equals("export.sig")) { - foundSignature = true; - signatureProto = keyZipInputstream.readAllBytes(); - } - entry = keyZipInputstream.getNextEntry(); - } - - assertTrue(foundData, "export.bin not found in zip"); - assertTrue(foundSignature, "export.sig not found in zip"); - - TEKSignatureList list = TemporaryExposureKeyFormat.TEKSignatureList.parseFrom(signatureProto); - TemporaryExposureKeyExport export = TemporaryExposureKeyFormat.TemporaryExposureKeyExport.parseFrom(keyProto); - for (var key : export.getKeysList()) { - assertEquals(expectedRollingPeriod, key.getRollingPeriod()); - } - var sig = list.getSignatures(0); - java.security.Signature signatureVerifier = java.security.Signature - .getInstance(sig.getSignatureInfo().getSignatureAlgorithm().trim()); - signatureVerifier.initVerify(signer.getPublicKey()); - - signatureVerifier.update(exportBin); - assertTrue(signatureVerifier.verify(sig.getSignature().toByteArray()), - "Could not verify signature in zip file"); - assertEquals(expectKeyCount, export.getKeysCount()); - } - - /** - * Creates keysPerDay for every day: lastDay, lastDay-1, ..., lastDay - daysBack - * + 1 - * - * @param lastDay of the created keys - * @param daysBack of the key creation, counted including the lastDay - * @param keysPerDay that will be created for every day - * @param receivedAt as sent to the DB - * @param debug if true, inserts the keys in the debug table. - */ - private void insertNKeysPerDay(UTCInstant lastDay, int daysBack, int keysPerDay, UTCInstant receivedAt, - boolean debug) { - SecureRandom random = new SecureRandom(); - for (int d = 0; d < daysBack; d++) { - var currentKeyDate = lastDay.minusDays(d); - int currentRollingStartNumber = (int) currentKeyDate.get10MinutesSince1970(); - List keys = new ArrayList<>(); - for (int n = 0; n < keysPerDay; n++) { - GaenKey key = new GaenKey(); - byte[] keyBytes = new byte[16]; - random.nextBytes(keyBytes); - key.setKeyData(Base64.getEncoder().encodeToString(keyBytes)); - key.setRollingPeriod(144); - key.setRollingStartNumber(currentRollingStartNumber); - key.setTransmissionRiskLevel(1); - key.setFake(0); - keys.add(key); - } - if (debug) { - testGaenDataService.upsertExposeesDebug(keys, receivedAt); - } else { - testGaenDataService.upsertExposees(keys, receivedAt); - } - } - } - + @Autowired ProtoSignature signer; + @Autowired KeyVault keyVault; + @Autowired GAENDataService gaenDataService; + Long releaseBucketDuration = 7200000L; + + private static final Logger logger = LoggerFactory.getLogger(GaenControllerTest.class); + + @Test + public void testHello() throws Exception { + MockHttpServletResponse response = + mockMvc.perform(get("/v1")).andExpect(status().is2xxSuccessful()).andReturn().getResponse(); + + assertNotNull(response); + assertEquals("Hello from DP3T WS", response.getContentAsString()); + } + + @Test + public void testActuatorSecurity() throws Exception { + var response = + mockMvc + .perform(get("/actuator/health")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + response = + mockMvc + .perform(get("/actuator/loggers")) + .andExpect(status().is(401)) + .andReturn() + .getResponse(); + response = + mockMvc + .perform( + get("/actuator/loggers") + .header("Authorization", "Basic cHJvbWV0aGV1czpwcm9tZXRoZXVz")) + .andExpect(status().isOk()) + .andReturn() + .getResponse(); + response = + mockMvc + .perform(get("/actuator/prometheus")) + .andExpect(status().is(401)) + .andReturn() + .getResponse(); + response = + mockMvc + .perform( + get("/actuator/prometheus") + .header("Authorization", "Basic cHJvbWV0aGV1czpwcm9tZXRoZXVz")) + .andExpect(status().isOk()) + .andReturn() + .getResponse(); + } + + private void testNKeys(UTCInstant now, int n, boolean shouldSucceed) throws Exception { + var requestList = new GaenRequest(); + var gaenKey1 = new GaenKey(); + gaenKey1.setRollingStartNumber((int) now.atStartOfDay().minusDays(1).get10MinutesSince1970()); + gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes01".getBytes("UTF-8"))); + gaenKey1.setRollingPeriod(144); + gaenKey1.setFake(0); + gaenKey1.setTransmissionRiskLevel(0); + var gaenKey2 = new GaenKey(); + gaenKey2.setRollingStartNumber((int) now.atStartOfDay().minusDays(1).get10MinutesSince1970()); + gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes02".getBytes("UTF-8"))); + gaenKey2.setRollingPeriod(144); + gaenKey2.setFake(0); + gaenKey2.setTransmissionRiskLevel(0); + List exposedKeys = new ArrayList<>(); + exposedKeys.add(gaenKey1); + exposedKeys.add(gaenKey2); + for (int i = 0; i < n - 2; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber((int) now.atStartOfDay().get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + exposedKeys.add(tmpKey); + } + requestList.setGaenKeys(exposedKeys); + var duration = now.atStartOfDay().plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + gaenKey1.setFake(0); + String token = createToken(now.plusMinutes(5)); + var requestBuilder = + mockMvc.perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))); + MvcResult response; + + if (shouldSucceed) { + response = requestBuilder.andExpect(request().asyncStarted()).andReturn(); + mockMvc.perform(asyncDispatch(response)).andExpect(status().is2xxSuccessful()); + } else { + response = requestBuilder.andExpect(status().is(400)).andReturn(); + return; + } + response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(request().asyncNotStarted()) + .andExpect(content().string("")) + .andReturn(); + + var result = + gaenDataService.getSortedExposedForKeyDate( + now.atStartOfDay().minusDays(1).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + assertEquals(2, result.size()); + for (var key : result) { + assertEquals(Integer.valueOf(144), key.getRollingPeriod()); + } + + result = + gaenDataService.getSortedExposedForKeyDate( + now.atStartOfDay().minusDays(1).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration) * releaseBucketDuration); + assertEquals(0, result.size()); + } + + @Test + public void testAllKeysWrongButStill200() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + var requestList = new GaenRequest(); + var gaenKey1 = new GaenKey(); + + gaenKey1.setRollingStartNumber((int) midnight.minusDays(30).get10MinutesSince1970()); + gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes01".getBytes("UTF-8"))); + gaenKey1.setRollingPeriod(0); + gaenKey1.setFake(0); + gaenKey1.setTransmissionRiskLevel(0); + var gaenKey2 = new GaenKey(); + gaenKey2.setRollingStartNumber((int) midnight.minusDays(1).get10MinutesSince1970()); + gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes02".getBytes("UTF-8"))); + gaenKey2.setRollingPeriod(-10); + gaenKey2.setFake(0); + gaenKey2.setTransmissionRiskLevel(0); + List exposedKeys = new ArrayList<>(); + exposedKeys.add(gaenKey1); + exposedKeys.add(gaenKey2); + for (int i = 0; i < 12; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber((int) midnight.plusDays(10).get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + exposedKeys.add(tmpKey); + } + requestList.setGaenKeys(exposedKeys); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + gaenKey1.setFake(0); + String token = createToken(now.plusMinutes(5)); + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncStarted()) + .andReturn(); + + mockMvc.perform(asyncDispatch(response)).andExpect(status().is2xxSuccessful()); + response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(request().asyncNotStarted()) + .andExpect(content().string("")) + .andReturn(); + + var result = + gaenDataService.getSortedExposedForKeyDate( + midnight.minusDays(1).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + // all keys are in compatible + assertEquals(0, result.size()); + } + + @Transactional + public void testMultipleKeyUpload() throws Exception { + testNKeys(UTCInstant.now(), 14, true); + } + + @Test + @Transactional + public void testCanUploadMoreThan14Keys() throws Exception { + testNKeys(UTCInstant.now(), 30, true); + } + + @Test + @Transactional + public void testCannotUploadMoreThan30Keys() throws Exception { + testNKeys(UTCInstant.now(), 31, false); + testNKeys(UTCInstant.now(), 100, false); + testNKeys(UTCInstant.now(), 1000, false); + } + + private Map headers = + Map.of( + "X-Content-Type-Options", + "nosniff", + "X-Frame-Options", + "DENY", + "X-Xss-Protection", + "1; mode=block"); + + @Test + public void testSecurityHeaders() throws Exception { + MockHttpServletResponse response = + mockMvc.perform(get("/v1")).andExpect(status().is2xxSuccessful()).andReturn().getResponse(); + for (var header : headers.keySet()) { + assertTrue(response.containsHeader(header)); + assertEquals(headers.get(header), response.getHeader(header)); + } + var now = UTCInstant.now(); + var midnight = UTCInstant.today(); + response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + for (var header : headers.keySet()) { + assertTrue(response.containsHeader(header)); + assertEquals(headers.get(header), response.getHeader(header)); + } + } + + @Test + public void testUploadWithNegativeRollingPeriodFails() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + var requestList = new GaenRequest(); + var gaenKey1 = new GaenKey(); + gaenKey1.setRollingStartNumber((int) midnight.get10MinutesSince1970()); + gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey1.setRollingPeriod(-1); + gaenKey1.setFake(0); + gaenKey1.setTransmissionRiskLevel(0); + var gaenKey2 = new GaenKey(); + gaenKey2.setRollingStartNumber((int) midnight.minusDays(1).get10MinutesSince1970()); + gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey2.setRollingPeriod(-5); + gaenKey2.setFake(0); + gaenKey2.setTransmissionRiskLevel(0); + List exposedKeys = new ArrayList<>(); + exposedKeys.add(gaenKey1); + exposedKeys.add(gaenKey2); + for (int i = 0; i < 12; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + exposedKeys.add(tmpKey); + } + requestList.setGaenKeys(exposedKeys); + var duration = (int) midnight.plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + gaenKey1.setFake(0); + String token = createToken(now.plusMinutes(5)); + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncStarted()) + .andReturn(); + + mockMvc.perform(asyncDispatch(response)).andExpect(status().is(200)); + + var result = + gaenDataService.getSortedExposedForKeyDate( + midnight.minusDays(1).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + // all keys are invalid + assertEquals(0, result.size()); + result = + gaenDataService.getSortedExposedForKeyDate( + midnight.getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + // all keys are invalid + assertEquals(0, result.size()); + } + + @Test + public void testMultipleKeyUploadFake() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + var requestList = new GaenRequest(); + var gaenKey1 = new GaenKey(); + gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey1.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + gaenKey1.setRollingPeriod(144); + gaenKey1.setTransmissionRiskLevel(0); + var gaenKey2 = new GaenKey(); + gaenKey2.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey2.setRollingPeriod(144); + gaenKey2.setTransmissionRiskLevel(0); + + gaenKey1.setFake(1); + gaenKey2.setFake(1); + + List exposedKeys = new ArrayList<>(); + exposedKeys.add(gaenKey1); + exposedKeys.add(gaenKey2); + for (int i = 0; i < 12; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + exposedKeys.add(tmpKey); + } + requestList.setGaenKeys(exposedKeys); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + + String token = createToken(true, now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncStarted()) + .andReturn(); + mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is2xxSuccessful()); + MockHttpServletResponse response = + mockMvc + .perform( + post("/v1/gaen/exposedlist") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(content().string("")) + .andReturn() + .getResponse(); + } + + @Test + public void testMultipleKeyUploadFakeAllKeysNeedToBeFake() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + var requestList = new GaenRequest(); + var gaenKey1 = new GaenKey(); + gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey1.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + gaenKey1.setRollingPeriod(144); + gaenKey1.setTransmissionRiskLevel(0); + var gaenKey2 = new GaenKey(); + gaenKey2.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey2.setRollingPeriod(144); + gaenKey2.setTransmissionRiskLevel(0); + + gaenKey1.setFake(0); + gaenKey2.setFake(1); + + List exposedKeys = new ArrayList<>(); + exposedKeys.add(gaenKey1); + exposedKeys.add(gaenKey2); + for (int i = 0; i < 12; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + exposedKeys.add(tmpKey); + } + requestList.setGaenKeys(exposedKeys); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + + String token = createToken(true, now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncStarted()) + .andReturn(); + mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is2xxSuccessful()); + MockHttpServletResponse response = + mockMvc + .perform( + post("/v1/gaen/exposedlist") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(content().string("")) + .andReturn() + .getResponse(); + } + + @Test + public void testMultipleKeyUploadFakeIfJWTNotFakeAllKeysCanBeFake() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + var requestList = new GaenRequest(); + var gaenKey1 = new GaenKey(); + gaenKey1.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey1.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + gaenKey1.setRollingPeriod(144); + gaenKey1.setTransmissionRiskLevel(0); + var gaenKey2 = new GaenKey(); + gaenKey2.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + gaenKey2.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + gaenKey2.setRollingPeriod(144); + gaenKey2.setTransmissionRiskLevel(0); + + gaenKey1.setFake(1); + gaenKey2.setFake(1); + + List exposedKeys = new ArrayList<>(); + exposedKeys.add(gaenKey1); + exposedKeys.add(gaenKey2); + for (int i = 0; i < 12; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + exposedKeys.add(tmpKey); + } + requestList.setGaenKeys(exposedKeys); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + + String token = createToken(false, now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncStarted()) + .andReturn(); + mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is2xxSuccessful()); + MockHttpServletResponse response = + mockMvc + .perform( + post("/v1/gaen/exposedlist") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(content().string("")) + .andReturn() + .getResponse(); + } + + @Test + public void testMultipleKeyNonEmptyUpload() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + var requestList = new GaenRequest(); + List exposedKeys = new ArrayList(); + requestList.setGaenKeys(exposedKeys); + String token = createToken(now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncNotStarted()) + .andExpect(status().is(400)) + .andReturn(); + + MockHttpServletResponse response = + mockMvc + .perform( + post("/v1/gaen/exposedlist") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(content().string("")) + .andReturn() + .getResponse(); + } + + @Test + public void testMultipleKeyNonNullUpload() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + var requestList = new GaenRequest(); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + requestList.setDelayedKeyDate((int) duration); + + String token = createToken(now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(request().asyncNotStarted()) + .andExpect(status().is(400)) + .andReturn(); + + MockHttpServletResponse response = + mockMvc + .perform( + post("/v1/gaen/exposedlist") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtToken) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(requestList))) + .andExpect(status().is(401)) + .andExpect(content().string("")) + .andReturn() + .getResponse(); + } + + @Test + public void keyNeedsToBeBase64() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate((int) duration); + GaenKey key = new GaenKey(); + key.setKeyData("00000000testKey32Bytes--"); + key.setRollingPeriod(144); + key.setRollingStartNumber((int) now.get10MinutesSince1970()); + key.setTransmissionRiskLevel(1); + key.setFake(0); + List keys = new ArrayList<>(); + keys.add(key); + for (int i = 0; i < 13; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + + String token = createToken(false, now.plusMinutes(5)); + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(status().is(400)) + .andReturn(); + } + + @Test + public void testKeyDateBeforeOnsetIsNotInserted() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate((int) duration); + GaenKey key = new GaenKey(); + key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + key.setRollingPeriod(144); + key.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(2)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + key.setTransmissionRiskLevel(1); + key.setFake(0); + List keys = new ArrayList<>(); + keys.add(key); + for (int i = 0; i < 13; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber((int) now.get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + + String token = + createToken(now.plusMinutes(5), now.getLocalDate().format(DateTimeFormatter.ISO_DATE)); + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncStarted()) + .andExpect(status().is(200)) + .andReturn(); + var result = + gaenDataService.getSortedExposedForKeyDate( + midnight.minusDays(2).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + assertEquals(0, result.size()); + } + + @Test + public void cannotUseExpiredToken() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate((int) duration); + GaenKey key = new GaenKey(); + key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + key.setRollingPeriod(144); + key.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + key.setTransmissionRiskLevel(1); + key.setFake(1); + List keys = new ArrayList<>(); + keys.add(key); + for (int i = 0; i < 13; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + + String token = createToken(now.minusMinutes(5)); + + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncNotStarted()) + .andExpect(status().is4xxClientError()) + .andReturn(); + } + + @Test + public void cannotUseKeyDateInFuture() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + exposeeRequest.setDelayedKeyDate((int) midnight.get10MinutesSince1970()); + GaenKey key = new GaenKey(); + key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes++".getBytes("UTF-8"))); + key.setRollingPeriod(144); + key.setRollingStartNumber((int) midnight.plusDays(2).get10MinutesSince1970()); + key.setTransmissionRiskLevel(1); + key.setFake(0); + List keys = new ArrayList<>(); + keys.add(key); + for (int i = 0; i < 13; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes++".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + + String token = createToken(now.plusMinutes(5)); + + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(status().is(200)) + .andReturn(); + var result = + gaenDataService.getSortedExposedForKeyDate( + midnight.plusDays(2).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + assertEquals(0, result.size()); + } + + @Test + public void keyDateNotOlderThan21Days() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate((int) duration); + GaenKey key = new GaenKey(); + key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + key.setRollingPeriod(144); + key.setRollingStartNumber((int) midnight.minusDays(22).get10MinutesSince1970()); + key.setTransmissionRiskLevel(1); + key.setFake(0); + List keys = new ArrayList<>(); + keys.add(key); + for (int i = 0; i < 13; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) Duration.ofMillis(Instant.now().toEpochMilli()).dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + + String token = createToken(now.plusMinutes(5), "2020-01-01"); + + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncStarted()) + .andExpect(status().is(200)) + .andReturn(); + var result = + gaenDataService.getSortedExposedForKeyDate( + midnight.minusDays(22).getTimestamp(), + null, + (now.getTimestamp() / releaseBucketDuration + 1) * releaseBucketDuration); + assertEquals(0, result.size()); + } + + @Test + public void cannotUseTokenWithWrongScope() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + var duration = midnight.plusDays(1).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate((int) duration); + GaenKey key = new GaenKey(); + key.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + key.setRollingPeriod(144); + key.setRollingStartNumber((int) now.get10MinutesSince1970()); + key.setTransmissionRiskLevel(1); + key.setFake(1); + List keys = new ArrayList<>(); + keys.add(key); + for (int i = 0; i < 13; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber((int) now.get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(1); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + + String token = createTokenWithScope(now.plusMinutes(5), "not-exposed"); + + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(status().is(403)) + .andReturn(); + + // Also for a 403 response, the token cannot be used a 2nd time + response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncNotStarted()) + .andExpect(status().is(401)) + .andExpect(content().string("")) + .andReturn(); + } + + @Test + public void uploadKeysAndUploadKeyNextDay() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + List keys = new ArrayList<>(); + for (int i = 0; i < 14; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + var delayedKeyDateSent = (int) midnight.get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); + exposeeRequest.setGaenKeys(keys); + String token = createToken(now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncStarted()) + .andReturn(); + MockHttpServletResponse response = + mockMvc + .perform(asyncDispatch(responseAsync)) + .andExpect(status().is(200)) + .andReturn() + .getResponse(); + assertTrue( + response.containsHeader("Authorization"), "Authorization header not found in response"); + String jwtString = response.getHeader("Authorization").replace("Bearer ", ""); + Jwt jwtToken = + Jwts.parserBuilder() + .setSigningKey(keyVault.get("nextDayJWT").getPublic()) + .build() + .parse(jwtString); + GaenSecondDay secondDay = new GaenSecondDay(); + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber(delayedKeyDateSent); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + secondDay.setDelayedKey(tmpKey); + responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposednextday") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtString) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(secondDay))) + .andExpect(request().asyncStarted()) + .andReturn(); + mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().is(200)); + } + + // @Test + // TODO: Is this still a requirement? Currently the key just gets filtered out + public void uploadKeysAndUploadKeyNextDayWithNegativeRollingPeriodFails() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + List keys = new ArrayList<>(); + for (int i = 0; i < 14; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + var delayedKeyDateSent = (int) midnight.get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); + exposeeRequest.setGaenKeys(keys); + String token = createToken(now.plusMinutes(5)); + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncStarted()) + .andReturn(); + MockHttpServletResponse response = + mockMvc + .perform(asyncDispatch(responseAsync)) + .andExpect(status().is(200)) + .andReturn() + .getResponse(); + assertTrue( + response.containsHeader("Authorization"), "Authorization header not found in response"); + String jwtString = response.getHeader("Authorization").replace("Bearer ", ""); + Jwt jwtToken = + Jwts.parserBuilder() + .setSigningKey(keyVault.get("nextDayJWT").getPublic()) + .build() + .parse(jwtString); + GaenSecondDay secondDay = new GaenSecondDay(); + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber(delayedKeyDateSent); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(-1); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + secondDay.setDelayedKey(tmpKey); + responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposednextday") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + jwtString) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(secondDay))) + .andExpect(request().asyncStarted()) + .andReturn(); + mockMvc.perform(asyncDispatch(responseAsync)).andExpect(status().isBadRequest()); + } + + @Test + public void delayedKeyDateBoundaryCheck() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + List keys = new ArrayList<>(); + for (int i = 0; i < 14; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber((int) midnight.minusDays(1).get10MinutesSince1970()); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + + Map tests = + Map.of( + -2, false, + -1, true, + 0, true, + 1, true, + 2, false); + + for (Map.Entry t : tests.entrySet()) { + Integer offset = t.getKey(); + Boolean pass = t.getValue(); + logger.info("Testing offset {} which should pass {}", offset, pass); + var delayedKeyDateSent = (int) midnight.plusDays(offset).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); + exposeeRequest.setGaenKeys(keys); + String token = createToken(now.plusMinutes(5)); + if (pass) { + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header( + "User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(request().asyncStarted()) + .andReturn(); + mockMvc + .perform(asyncDispatch(responseAsync)) + .andExpect(status().is(200)) + .andReturn() + .getResponse(); + } else { + MvcResult responseAsync = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header( + "User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(status().is(400)) + .andReturn(); + } + } + } + + @Test + public void testTokenValiditySurpassesMaxJwtValidity() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + GaenRequest exposeeRequest = new GaenRequest(); + List keys = new ArrayList<>(); + for (int i = 0; i < 14; i++) { + var tmpKey = new GaenKey(); + tmpKey.setRollingStartNumber( + (int) + Duration.ofMillis(Instant.now().minus(Duration.ofDays(1)).toEpochMilli()) + .dividedBy(Duration.ofMinutes(10))); + tmpKey.setKeyData(Base64.getEncoder().encodeToString("testKey32Bytes--".getBytes("UTF-8"))); + tmpKey.setRollingPeriod(144); + tmpKey.setFake(0); + tmpKey.setTransmissionRiskLevel(0); + keys.add(tmpKey); + } + exposeeRequest.setGaenKeys(keys); + var delayedKeyDateSent = (int) midnight.plusDays(1).get10MinutesSince1970(); + exposeeRequest.setDelayedKeyDate(delayedKeyDateSent); + int maxJWTValidityInMinutes = 60; + String token = createToken(now.plusMinutes(maxJWTValidityInMinutes + 1)); + + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .content(json(exposeeRequest))) + .andExpect(status().is(401)); + } + + @Test + public void testDebugController() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + // insert two times 10 keys per day for the last 14 days, with different + // received at. In total: 280 keys + insertNKeysPerDay(midnight, 14, 10, midnight.minusDays(1), true); + insertNKeysPerDay(midnight, 14, 10, midnight.minusHours(12), true); + + // Request keys which have been received in the last day, must be 280 in total. + // This is the debug controller, which returns keys based on the 'received at', + // not based on the key date. So this request should return all keys with + // 'received at' of the last day. + + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/debug/exposed/" + midnight.getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + verifyZipInZipResponse(response, 280, 144); + } + + @Test + @Transactional + public void zipContainsFiles() throws Exception { + var now = UTCInstant.now(); + var clock = Clock.offset(Clock.systemUTC(), now.getDuration(now.atStartOfDay().plusHours(12))); + UTCInstant.setClock(clock); + now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + // Insert two times 5 keys per day for the last 14 days. the second batch has a + // different 'received at' timestamp. (+12 hours compared to the first) + insertNKeysPerDay(midnight, 14, 5, midnight.minusDays(1), false); + insertNKeysPerDay(midnight, 14, 5, midnight.minusHours(12), false); + + // request the keys with key date 8 days ago. no publish until. + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "MockMVC")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + Long publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); + assertTrue(publishedUntil < now.getTimestamp(), "Published until must be in the past"); + + // must contain 20 keys: 5 from the first insert, 5 from the second insert and + // 10 random keys + verifyZipResponse(response, 20, 144); + + // request again the keys with date date 8 days ago. with publish until, so that + // we only get the second batch. + var bucketAfterSecondRelease = midnight.minusHours(12); + + MockHttpServletResponse responseWithPublishedAfter = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "MockMVC") + .param( + "publishedafter", Long.toString(bucketAfterSecondRelease.getTimestamp()))) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + // must contain 15 keys: 5 from the second insert and 10 random keys + verifyZipResponse(responseWithPublishedAfter, 15, 144); + UTCInstant.resetClock(); + } + + @Test + @Transactional(transactionManager = "testTransactionManager") + public void testNonEmptyResponseAnd304() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().isOk()) + .andReturn() + .getResponse(); + verifyZipResponse(response, 10, 144); + } + + @Test + @Transactional(transactionManager = "testTransactionManager") + public void testTodayWeDontHaveKeys() throws Exception { + var midnight = UTCInstant.today(); + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.getTimestamp()).header("User-Agent", "MockMVC")) + .andExpect(status().is(204)) + .andReturn() + .getResponse(); + } + + // @Test + // @Transactional(transactionManager = "testTransactionManager") + public void testEtag() throws Exception { + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + insertNKeysPerDay(midnight, 14, 10, midnight.minusDays(1), false); + insertNKeysPerDay(midnight, 14, 10, midnight.minusHours(12), false); + + // request the keys with date date 1 day ago. no publish until. + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + Long publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); + assertTrue(publishedUntil < System.currentTimeMillis(), "Published until must be in the past"); + var expectedEtag = response.getHeader("etag"); + + response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); + assertTrue(publishedUntil < System.currentTimeMillis(), "Published until must be in the past"); + assertEquals(expectedEtag, response.getHeader("etag")); + + insertNKeysPerDay(midnight, 14, 10, midnight.minusHours(12), false); + response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); + assertTrue(publishedUntil < System.currentTimeMillis(), "Published until must be in the past"); + assertNotEquals(expectedEtag, response.getHeader("etag")); + } + + @Test + public void testMalciousTokenFails() throws Exception { + var requestList = new GaenRequest(); + List exposedKeys = new ArrayList(); + requestList.setGaenKeys(exposedKeys); + String token = createMaliciousToken(UTCInstant.now().plusMinutes(5)); + MvcResult response = + mockMvc + .perform( + post("/v1/gaen/exposed") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .header("User-Agent", "MockMVC") + .content(json(requestList))) + .andExpect(request().asyncNotStarted()) + .andExpect(status().is(401)) + .andReturn(); + String authenticateError = response.getResponse().getHeader("www-authenticate"); + assertTrue(authenticateError.contains("Unsigned Claims JWTs are not supported.")); + } + + /** Verifies a zip in zip response, that each inner zip is again valid. */ + private void verifyZipInZipResponse( + MockHttpServletResponse response, int expectKeyCount, int expectedRollingPeriod) + throws Exception { + ByteArrayInputStream baisOuter = new ByteArrayInputStream(response.getContentAsByteArray()); + ZipInputStream zipOuter = new ZipInputStream(baisOuter); + ZipEntry entry = zipOuter.getNextEntry(); + while (entry != null) { + ZipInputStream zipInner = + new ZipInputStream(new ByteArrayInputStream(zipOuter.readAllBytes())); + verifyKeyZip(zipInner, expectKeyCount, expectedRollingPeriod); + entry = zipOuter.getNextEntry(); + } + } + + /** Verifies a zip response, checks if keys and signature is correct. */ + private void verifyZipResponse( + MockHttpServletResponse response, int expectKeyCount, int expectedRollingPeriod) + throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { + ByteArrayInputStream baisZip = new ByteArrayInputStream(response.getContentAsByteArray()); + ZipInputStream keyZipInputstream = new ZipInputStream(baisZip); + verifyKeyZip(keyZipInputstream, expectKeyCount, expectedRollingPeriod); + } + + private void verifyKeyZip( + ZipInputStream keyZipInputstream, int expectKeyCount, int expectedRollingPeriod) + throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException { + ZipEntry entry = keyZipInputstream.getNextEntry(); + boolean foundData = false; + boolean foundSignature = false; + + byte[] signatureProto = null; + byte[] exportBin = null; + byte[] keyProto = null; + + while (entry != null) { + if (entry.getName().equals("export.bin")) { + foundData = true; + exportBin = keyZipInputstream.readAllBytes(); + keyProto = new byte[exportBin.length - 16]; + System.arraycopy(exportBin, 16, keyProto, 0, keyProto.length); + } + if (entry.getName().equals("export.sig")) { + foundSignature = true; + signatureProto = keyZipInputstream.readAllBytes(); + } + entry = keyZipInputstream.getNextEntry(); + } + + assertTrue(foundData, "export.bin not found in zip"); + assertTrue(foundSignature, "export.sig not found in zip"); + + TEKSignatureList list = TemporaryExposureKeyFormat.TEKSignatureList.parseFrom(signatureProto); + TemporaryExposureKeyExport export = + TemporaryExposureKeyFormat.TemporaryExposureKeyExport.parseFrom(keyProto); + for (var key : export.getKeysList()) { + assertEquals(expectedRollingPeriod, key.getRollingPeriod()); + } + var sig = list.getSignatures(0); + java.security.Signature signatureVerifier = + java.security.Signature.getInstance(sig.getSignatureInfo().getSignatureAlgorithm().trim()); + signatureVerifier.initVerify(signer.getPublicKey()); + + signatureVerifier.update(exportBin); + assertTrue( + signatureVerifier.verify(sig.getSignature().toByteArray()), + "Could not verify signature in zip file"); + assertEquals(expectKeyCount, export.getKeysCount()); + } + + /** + * Creates keysPerDay for every day: lastDay, lastDay-1, ..., lastDay - daysBack + 1 + * + * @param lastDay of the created keys + * @param daysBack of the key creation, counted including the lastDay + * @param keysPerDay that will be created for every day + * @param receivedAt as sent to the DB + * @param debug if true, inserts the keys in the debug table. + */ + private void insertNKeysPerDay( + UTCInstant lastDay, int daysBack, int keysPerDay, UTCInstant receivedAt, boolean debug) { + SecureRandom random = new SecureRandom(); + for (int d = 0; d < daysBack; d++) { + var currentKeyDate = lastDay.minusDays(d); + int currentRollingStartNumber = (int) currentKeyDate.get10MinutesSince1970(); + List keys = new ArrayList<>(); + for (int n = 0; n < keysPerDay; n++) { + GaenKey key = new GaenKey(); + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + key.setKeyData(Base64.getEncoder().encodeToString(keyBytes)); + key.setRollingPeriod(144); + key.setRollingStartNumber(currentRollingStartNumber); + key.setTransmissionRiskLevel(1); + key.setFake(0); + keys.add(key); + } + if (debug) { + testGaenDataService.upsertExposeesDebug(keys, receivedAt); + } else { + testGaenDataService.upsertExposees(keys, receivedAt); + } + } + } } diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTestNotThreadSafe.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTestNotThreadSafe.java index c7b5bca5..4539495a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTestNotThreadSafe.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/GaenControllerTestNotThreadSafe.java @@ -18,7 +18,6 @@ import java.util.Map.Entry; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.model.gaen.proto.TemporaryExposureKeyFormat; import org.dpppt.backend.sdk.utils.UTCInstant; @@ -34,155 +33,177 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; -@ActiveProfiles({ "actuator-security" }) -@SpringBootTest(properties = { "ws.app.jwt.publickey=classpath://generated_pub.pem", - "logging.level.org.springframework.security=DEBUG", "ws.exposedlist.releaseBucketDuration=7200000", "ws.gaen.randomkeysenabled=true", - "ws.app.gaen.delayTodaysKeys=true", - "ws.monitor.prometheus.user=prometheus", - "ws.monitor.prometheus.password=prometheus", - "management.endpoints.enabled-by-default=true", - "management.endpoints.web.exposure.include=*"}) +@ActiveProfiles({"actuator-security"}) +@SpringBootTest( + properties = { + "ws.app.jwt.publickey=classpath://generated_pub.pem", + "logging.level.org.springframework.security=DEBUG", + "ws.exposedlist.releaseBucketDuration=7200000", + "ws.gaen.randomkeysenabled=true", + "ws.app.gaen.delayTodaysKeys=true", + "ws.monitor.prometheus.user=prometheus", + "ws.monitor.prometheus.password=prometheus", + "management.endpoints.enabled-by-default=true", + "management.endpoints.web.exposure.include=*" + }) @Transactional @Execution(ExecutionMode.SAME_THREAD) public class GaenControllerTestNotThreadSafe extends BaseControllerTest { - @Autowired - ProtoSignature signer; - - private static final Logger logger = LoggerFactory.getLogger(GaenControllerTest.class); - - @Test - @Transactional - public void zipContainsFiles() throws Exception { - var clockStartingAtMidnight = Clock.offset(Clock.systemUTC(), UTCInstant.now().getDuration(UTCInstant.today()).negated()); - UTCInstant.setClock(clockStartingAtMidnight); - var now = UTCInstant.now(); - var midnight = now.atStartOfDay(); - - // insert two times 5 keys per day for the last 14 days. the second batch has a - // different received at timestamp. (+6 hours) - insertNKeysPerDayInInterval(14, - midnight.minusDays(4), - now, now.minusDays(1)); - - insertNKeysPerDayInInterval(14, - midnight.minusDays(4), - now, now.minusDays(12)); - - // request the keys with date date 1 day ago. no publish until. - MockHttpServletResponse response = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - Long publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); - assertTrue(publishedUntil < now.getTimestamp()); - - verifyZipResponse(response, 20); - - // request again the keys with date date 1 day ago. with publish until, so that - // we only get the second batch. - var bucketAfterSecondRelease = Duration.ofMillis(midnight.getTimestamp()).minusDays(1).plusHours(12).dividedBy(Duration.ofHours(2)) * 2*60*60*1000; - MockHttpServletResponse responseWithPublishedAfter = mockMvc - .perform(get("/v1/gaen/exposed/" - + midnight.minusDays(8).getTimestamp()) - .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29").param("publishedafter", - Long.toString(bucketAfterSecondRelease))) - .andExpect(status().is2xxSuccessful()).andReturn().getResponse(); - - //we always have 10 - verifyZipResponse(responseWithPublishedAfter, 10); - UTCInstant.resetClock(); + @Autowired ProtoSignature signer; + + private static final Logger logger = LoggerFactory.getLogger(GaenControllerTest.class); + + @Test + @Transactional + public void zipContainsFiles() throws Exception { + var clockStartingAtMidnight = + Clock.offset(Clock.systemUTC(), UTCInstant.now().getDuration(UTCInstant.today()).negated()); + UTCInstant.setClock(clockStartingAtMidnight); + var now = UTCInstant.now(); + var midnight = now.atStartOfDay(); + + // insert two times 5 keys per day for the last 14 days. the second batch has a + // different received at timestamp. (+6 hours) + insertNKeysPerDayInInterval(14, midnight.minusDays(4), now, now.minusDays(1)); + + insertNKeysPerDayInInterval(14, midnight.minusDays(4), now, now.minusDays(12)); + + // request the keys with date date 1 day ago. no publish until. + MockHttpServletResponse response = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29")) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + Long publishedUntil = Long.parseLong(response.getHeader("X-PUBLISHED-UNTIL")); + assertTrue(publishedUntil < now.getTimestamp()); + + verifyZipResponse(response, 20); + + // request again the keys with date date 1 day ago. with publish until, so that + // we only get the second batch. + var bucketAfterSecondRelease = + Duration.ofMillis(midnight.getTimestamp()) + .minusDays(1) + .plusHours(12) + .dividedBy(Duration.ofHours(2)) + * 2 + * 60 + * 60 + * 1000; + MockHttpServletResponse responseWithPublishedAfter = + mockMvc + .perform( + get("/v1/gaen/exposed/" + midnight.minusDays(8).getTimestamp()) + .header("User-Agent", "ch.admin.bag.dp3t.dev;1.0.7;1595591959493;Android;29") + .param("publishedafter", Long.toString(bucketAfterSecondRelease))) + .andExpect(status().is2xxSuccessful()) + .andReturn() + .getResponse(); + + // we always have 10 + verifyZipResponse(responseWithPublishedAfter, 10); + UTCInstant.resetClock(); + } + + private void verifyZipResponse(MockHttpServletResponse response, int expectKeyCount) + throws Exception { + ByteArrayInputStream baisOuter = new ByteArrayInputStream(response.getContentAsByteArray()); + ZipInputStream zipOuter = new ZipInputStream(baisOuter); + ZipEntry entry = zipOuter.getNextEntry(); + boolean foundData = false; + boolean foundSignature = false; + + byte[] signatureProto = null; + byte[] exportBin = null; + byte[] keyProto = null; + + while (entry != null) { + if (entry.getName().equals("export.bin")) { + foundData = true; + exportBin = zipOuter.readAllBytes(); + keyProto = new byte[exportBin.length - 16]; + System.arraycopy(exportBin, 16, keyProto, 0, keyProto.length); + } + if (entry.getName().equals("export.sig")) { + foundSignature = true; + signatureProto = zipOuter.readAllBytes(); + } + entry = zipOuter.getNextEntry(); + } + + assertTrue(foundData); + assertTrue(foundSignature); + + var list = TemporaryExposureKeyFormat.TEKSignatureList.parseFrom(signatureProto); + var export = TemporaryExposureKeyFormat.TemporaryExposureKeyExport.parseFrom(keyProto); + for (var key : export.getKeysList()) { + assertNotEquals(0, key.getRollingPeriod()); } - - - private void verifyZipResponse(MockHttpServletResponse response, int expectKeyCount) - throws Exception { - ByteArrayInputStream baisOuter = new ByteArrayInputStream(response.getContentAsByteArray()); - ZipInputStream zipOuter = new ZipInputStream(baisOuter); - ZipEntry entry = zipOuter.getNextEntry(); - boolean foundData = false; - boolean foundSignature = false; - - byte[] signatureProto = null; - byte[] exportBin = null; - byte[] keyProto = null; - - while (entry != null) { - if (entry.getName().equals("export.bin")) { - foundData = true; - exportBin = zipOuter.readAllBytes(); - keyProto = new byte[exportBin.length-16]; - System.arraycopy(exportBin, 16, keyProto, 0, keyProto.length); - } - if (entry.getName().equals("export.sig")) { - foundSignature = true; - signatureProto = zipOuter.readAllBytes(); - } - entry = zipOuter.getNextEntry(); - } - - assertTrue(foundData); - assertTrue(foundSignature); - - var list = TemporaryExposureKeyFormat.TEKSignatureList.parseFrom(signatureProto); - var export = TemporaryExposureKeyFormat.TemporaryExposureKeyExport.parseFrom(keyProto); - for(var key : export.getKeysList()) { - assertNotEquals(0, key.getRollingPeriod()); - } - var sig = list.getSignatures(0); - java.security.Signature signatureVerifier = java.security.Signature - .getInstance(sig.getSignatureInfo().getSignatureAlgorithm().trim()); - signatureVerifier.initVerify(signer.getPublicKey()); - - signatureVerifier.update(exportBin); - assertTrue(signatureVerifier.verify(sig.getSignature().toByteArray())); - assertEquals(expectKeyCount, export.getKeysCount()); - } - - private void insertNKeysPerDayInIntervalWithDebugFlag(int n, UTCInstant start, UTCInstant end, UTCInstant receivedAt, boolean debug) throws Exception { - var current = start; - Map rollingToCount = new HashMap<>(); - while (current.isBeforeEpochMillisOf(end)) { - List keys = new ArrayList<>(); - SecureRandom random = new SecureRandom(); - int lastRolling = (int)start.get10MinutesSince1970(); - for (int i = 0; i < n; i++) { - GaenKey key = new GaenKey(); - byte[] keyBytes = new byte[16]; - random.nextBytes(keyBytes); - key.setKeyData(Base64.getEncoder().encodeToString(keyBytes)); - key.setRollingPeriod(144); - logger.info("Rolling Start number: " + lastRolling); - key.setRollingStartNumber(lastRolling); - key.setTransmissionRiskLevel(1); - key.setFake(0); - keys.add(key); - - Integer count = rollingToCount.get(lastRolling); - if (count == null) { - count = 0; - } - count = count + 1; - rollingToCount.put(lastRolling, count); - - lastRolling -= Duration.ofDays(1).dividedBy(Duration.ofMinutes(10)); - - } - if(debug) { - testGaenDataService.upsertExposeesDebug(keys, receivedAt); - } else { - testGaenDataService.upsertExposees(keys, receivedAt); - } - current = current.plusDays(1); - } - for (Entry entry: rollingToCount.entrySet()) { - logger.info("Rolling start number: " + entry.getKey() + " -> count: " + entry.getValue() + " (received at: " + receivedAt.toString() + ")"); - } - } - - private void insertNKeysPerDayInInterval(int n, UTCInstant start, UTCInstant end, UTCInstant receivedAt) - throws Exception { - insertNKeysPerDayInIntervalWithDebugFlag(n, start, end, receivedAt, false); - } -} \ No newline at end of file + var sig = list.getSignatures(0); + java.security.Signature signatureVerifier = + java.security.Signature.getInstance(sig.getSignatureInfo().getSignatureAlgorithm().trim()); + signatureVerifier.initVerify(signer.getPublicKey()); + + signatureVerifier.update(exportBin); + assertTrue(signatureVerifier.verify(sig.getSignature().toByteArray())); + assertEquals(expectKeyCount, export.getKeysCount()); + } + + private void insertNKeysPerDayInIntervalWithDebugFlag( + int n, UTCInstant start, UTCInstant end, UTCInstant receivedAt, boolean debug) + throws Exception { + var current = start; + Map rollingToCount = new HashMap<>(); + while (current.isBeforeEpochMillisOf(end)) { + List keys = new ArrayList<>(); + SecureRandom random = new SecureRandom(); + int lastRolling = (int) start.get10MinutesSince1970(); + for (int i = 0; i < n; i++) { + GaenKey key = new GaenKey(); + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + key.setKeyData(Base64.getEncoder().encodeToString(keyBytes)); + key.setRollingPeriod(144); + logger.info("Rolling Start number: " + lastRolling); + key.setRollingStartNumber(lastRolling); + key.setTransmissionRiskLevel(1); + key.setFake(0); + keys.add(key); + + Integer count = rollingToCount.get(lastRolling); + if (count == null) { + count = 0; + } + count = count + 1; + rollingToCount.put(lastRolling, count); + + lastRolling -= Duration.ofDays(1).dividedBy(Duration.ofMinutes(10)); + } + if (debug) { + testGaenDataService.upsertExposeesDebug(keys, receivedAt); + } else { + testGaenDataService.upsertExposees(keys, receivedAt); + } + current = current.plusDays(1); + } + for (Entry entry : rollingToCount.entrySet()) { + logger.info( + "Rolling start number: " + + entry.getKey() + + " -> count: " + + entry.getValue() + + " (received at: " + + receivedAt.toString() + + ")"); + } + } + + private void insertNKeysPerDayInInterval( + int n, UTCInstant start, UTCInstant end, UTCInstant receivedAt) throws Exception { + insertNKeysPerDayInIntervalWithDebugFlag(n, start, end, receivedAt, false); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/TestApplication.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/TestApplication.java index 340460ed..0bd9e9c6 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/TestApplication.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/controller/TestApplication.java @@ -10,11 +10,9 @@ package org.dpppt.backend.sdk.ws.controller; - import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @ComponentScan(basePackages = {"org.dpppt.backend.sdk.ws.config"}) @SpringBootApplication -public class TestApplication { -} +public class TestApplication {} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManagerTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManagerTest.java index be48aeba..382312f9 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManagerTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/InsertManagerTest.java @@ -3,10 +3,13 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; import java.time.Duration; import java.util.ArrayList; import java.util.List; - import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.semver.Version; import org.dpppt.backend.sdk.utils.UTCInstant; @@ -15,107 +18,116 @@ import org.junit.Test; import org.slf4j.LoggerFactory; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; - public class InsertManagerTest { - @Test - public void testOSEnumWorks() { - assertEquals("Android", OSType.ANDROID.toString()); - assertEquals("iOS", OSType.IOS.toString()); + @Test + public void testOSEnumWorks() { + assertEquals("Android", OSType.ANDROID.toString()); + assertEquals("iOS", OSType.IOS.toString()); + } + + @Test + public void emptyListShouldNotFail() { + Object theException = null; + try { + InsertManager manager = + new InsertManager( + new MockDataSource(), + new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); + manager.insertIntoDatabase(new ArrayList<>(), null, null, null); + } catch (Exception ex) { + theException = ex; } + assertNull(theException); + } - @Test - public void emptyListShouldNotFail(){ - Object theException = null; - try { - InsertManager manager = new InsertManager(new MockDataSource(), new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); - manager.insertIntoDatabase(new ArrayList<>(), null, null, null); - } catch(Exception ex) { - theException = ex; - } - assertNull(theException); + @Test + public void nullListShouldNotFail() throws Exception { + Object theException = null; + try { + InsertManager manager = + new InsertManager( + new MockDataSource(), + new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); + manager.insertIntoDatabase(null, null, null, null); + } catch (Exception ex) { + theException = ex; } - @Test - public void nullListShouldNotFail() throws Exception { - Object theException = null; - try { - InsertManager manager = new InsertManager(new MockDataSource(), new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); - manager.insertIntoDatabase(null, null, null, null); - } catch(Exception ex) { - theException = ex; - } - assertNull(theException); + assertNull(theException); + } + + @Test + public void wrongHeaderShouldNotFail() throws Exception { + Logger logger = (Logger) LoggerFactory.getLogger(InsertManager.class); + var appender = new TestAppender(); + appender.setContext(logger.getLoggerContext()); + appender.start(); + logger.addAppender(appender); + InsertManager manager = + new InsertManager( + new MockDataSource(), + new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); + var key = + new GaenKey("POSTMAN+POSTMAN+", (int) UTCInstant.now().get10MinutesSince1970(), 144, 0); + try { + manager.insertIntoDatabase(List.of(key), "test", null, UTCInstant.now()); + } catch (RuntimeException ex) { + if (!ex.getMessage().equals("UPSERT_EXPOSEES")) { + throw ex; + } } - @Test - public void wrongHeaderShouldNotFail() throws Exception { - Logger logger = (Logger)LoggerFactory.getLogger(InsertManager.class); - var appender = new TestAppender(); - appender.setContext(logger.getLoggerContext()); - appender.start(); - logger.addAppender(appender); - InsertManager manager = new InsertManager(new MockDataSource(), new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); - var key = new GaenKey("POSTMAN+POSTMAN+", (int)UTCInstant.now().get10MinutesSince1970(), 144, 0); - try { - manager.insertIntoDatabase(List.of(key), "test", null, UTCInstant.now()); - } catch(RuntimeException ex) { - if(!ex.getMessage().equals("UPSERT_EXPOSEES")) { - throw ex; - } - } - appender.stop(); - for(var event : appender.getLog()) { - assertEquals(Level.ERROR,event.getLevel()); - assertEquals("We received an invalid header, setting default.", event.getMessage()); - } + appender.stop(); + for (var event : appender.getLog()) { + assertEquals(Level.ERROR, event.getLevel()); + assertEquals("We received an invalid header, setting default.", event.getMessage()); } + } - @Test - public void iosRP0ShouldLog() throws Exception { - Logger logger = (Logger)LoggerFactory.getLogger(OldAndroid0RPModifier.class); - var appender = new TestAppender(); - appender.setContext(logger.getLoggerContext()); - appender.start(); - logger.addAppender(appender); - InsertManager manager = new InsertManager(new MockDataSource(), new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); - manager.addModifier(new OldAndroid0RPModifier()); - var key = new GaenKey("POSTMAN+POSTMAN+", (int)UTCInstant.now().get10MinutesSince1970(), 0, 0); - try { - manager.insertIntoDatabase(List.of(key), "org.dpppt.testrunner;1.0.0;1;iOS;29", null, UTCInstant.now()); - } catch(RuntimeException ex) { - if(!ex.getMessage().equals("UPSERT_EXPOSEES")) { - throw ex; - } - } - appender.stop(); - assertEquals(1, appender.getLog().size()); - for(var event : appender.getLog()) { - assertEquals(Level.ERROR,event.getLevel()); - assertEquals("We got a rollingPeriod of 0 ({},{},{})", event.getMessage()); - //osType, osVersion, appVersion - var osType = (OSType) event.getArgumentArray()[0]; - var osVersion = (Version)event.getArgumentArray()[1]; - var appVersion = (Version)event.getArgumentArray()[2]; - assertEquals(OSType.IOS, osType); - assertEquals("29.0.0", osVersion.toString()); - assertEquals("1.0.0+1", appVersion.toString()); - } + @Test + public void iosRP0ShouldLog() throws Exception { + Logger logger = (Logger) LoggerFactory.getLogger(OldAndroid0RPModifier.class); + var appender = new TestAppender(); + appender.setContext(logger.getLoggerContext()); + appender.start(); + logger.addAppender(appender); + InsertManager manager = + new InsertManager( + new MockDataSource(), + new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis())); + manager.addModifier(new OldAndroid0RPModifier()); + var key = new GaenKey("POSTMAN+POSTMAN+", (int) UTCInstant.now().get10MinutesSince1970(), 0, 0); + try { + manager.insertIntoDatabase( + List.of(key), "org.dpppt.testrunner;1.0.0;1;iOS;29", null, UTCInstant.now()); + } catch (RuntimeException ex) { + if (!ex.getMessage().equals("UPSERT_EXPOSEES")) { + throw ex; + } } + appender.stop(); + assertEquals(1, appender.getLog().size()); + for (var event : appender.getLog()) { + assertEquals(Level.ERROR, event.getLevel()); + assertEquals("We got a rollingPeriod of 0 ({},{},{})", event.getMessage()); + // osType, osVersion, appVersion + var osType = (OSType) event.getArgumentArray()[0]; + var osVersion = (Version) event.getArgumentArray()[1]; + var appVersion = (Version) event.getArgumentArray()[2]; + assertEquals(OSType.IOS, osType); + assertEquals("29.0.0", osVersion.toString()); + assertEquals("1.0.0+1", appVersion.toString()); + } + } - class TestAppender extends AppenderBase{ - private final List log = new ArrayList(); - - @Override - protected void append(ILoggingEvent eventObject) { - log.add(eventObject); - } + class TestAppender extends AppenderBase { + private final List log = new ArrayList(); - public List getLog() { - return log; - } - + @Override + protected void append(ILoggingEvent eventObject) { + log.add(eventObject); } -} \ No newline at end of file + public List getLog() { + return log; + } + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/MockDataSource.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/MockDataSource.java index 7878c925..a6b3773d 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/MockDataSource.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/insertmanager/MockDataSource.java @@ -2,35 +2,32 @@ import java.time.Duration; import java.util.List; - import org.dpppt.backend.sdk.data.gaen.GAENDataService; import org.dpppt.backend.sdk.model.gaen.GaenKey; import org.dpppt.backend.sdk.utils.UTCInstant; public class MockDataSource implements GAENDataService { - @Override - public void upsertExposees(List keys, UTCInstant now) { - throw new RuntimeException("UPSERT_EXPOSEES"); - } - - @Override - public void upsertExposeesDelayed(List keys, UTCInstant delayedReceivedAt, UTCInstant now) { - - } - - @Override - public int getMaxExposedIdForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { - return 0; - } - - @Override - public List getSortedExposedForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { - return null; - } - - @Override - public void cleanDB(Duration retentionPeriod) { - } - -} \ No newline at end of file + @Override + public void upsertExposees(List keys, UTCInstant now) { + throw new RuntimeException("UPSERT_EXPOSEES"); + } + + @Override + public void upsertExposeesDelayed( + List keys, UTCInstant delayedReceivedAt, UTCInstant now) {} + + @Override + public int getMaxExposedIdForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { + return 0; + } + + @Override + public List getSortedExposedForKeyDate( + Long keyDate, Long publishedAfter, Long publishedUntil) { + return null; + } + + @Override + public void cleanDB(Duration retentionPeriod) {} +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/KeyVaultTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/KeyVaultTest.java index 14b15521..ccae0f3f 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/KeyVaultTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/KeyVaultTest.java @@ -15,62 +15,80 @@ import java.security.PrivateKey; import java.security.PublicKey; import java.util.Base64; - import org.apache.commons.io.IOUtils; import org.junit.Test; import org.springframework.core.io.ClassPathResource; public class KeyVaultTest { - @Test - public void testProviderNeedsToBeStatic() throws Exception { - byte[] test = "EK Export v1 ".getBytes(); - assertFalse(KeyVault.registerNewPublicEncodingProvider(KeyVaultTest.class, "testFunctionPublic1")); - assertFalse(KeyVault.registerNewPrivateEncodingProvider(KeyVaultTest.class, "testFunctionPrivate1")); - } + @Test + public void testProviderNeedsToBeStatic() throws Exception { + byte[] test = "EK Export v1 ".getBytes(); + assertFalse( + KeyVault.registerNewPublicEncodingProvider(KeyVaultTest.class, "testFunctionPublic1")); + assertFalse( + KeyVault.registerNewPrivateEncodingProvider(KeyVaultTest.class, "testFunctionPrivate1")); + } + + @Test + public void returnValueNeedsToBeCorrect() throws Exception { + assertFalse( + KeyVault.registerNewPublicEncodingProvider(KeyVaultTest.class, "testFunctionPublic2")); + assertFalse( + KeyVault.registerNewPrivateEncodingProvider(KeyVaultTest.class, "testFunctionPrivate2")); + } + + @Test + public void functionNeedsToExist() throws Exception { + assertFalse( + KeyVault.registerNewPublicEncodingProvider(KeyVaultTest.class, "testFunctionPublic0")); + assertFalse( + KeyVault.registerNewPrivateEncodingProvider(KeyVaultTest.class, "testFunctionPrivate0")); + } - @Test - public void returnValueNeedsToBeCorrect() throws Exception { - assertFalse(KeyVault.registerNewPublicEncodingProvider(KeyVaultTest.class, "testFunctionPublic2")); - assertFalse(KeyVault.registerNewPrivateEncodingProvider(KeyVaultTest.class, "testFunctionPrivate2")); - } + @Test + public void testJavaEncodingFile() throws Exception { + var publicKey = + IOUtils.toString(new ClassPathResource("/generated_pub_2.pem").getInputStream()); + var privateKey = + IOUtils.toString(new ClassPathResource("/generated_private_2.pem").getInputStream()); - @Test - public void functionNeedsToExist() throws Exception { - assertFalse(KeyVault.registerNewPublicEncodingProvider(KeyVaultTest.class, "testFunctionPublic0")); - assertFalse(KeyVault.registerNewPrivateEncodingProvider(KeyVaultTest.class, "testFunctionPrivate0")); - } + var entry = + new KeyVault.KeyVaultEntry("test", new String(privateKey), new String(publicKey), "RSA"); + var keyVault = new KeyVault(entry); + assertNotNull(keyVault.get("test")); + } - @Test - public void testJavaEncodingFile() throws Exception { - var publicKey = IOUtils.toString(new ClassPathResource("/generated_pub_2.pem").getInputStream()); - var privateKey = IOUtils.toString(new ClassPathResource("/generated_private_2.pem").getInputStream()); + @Test + public void testPEMFile() throws Exception { + var publicKey = + Base64.getDecoder() + .decode( + IOUtils.toString(new ClassPathResource("/generated_pub_3.pem").getInputStream())); + var privateKey = + Base64.getDecoder() + .decode( + IOUtils.toString( + new ClassPathResource("/generated_private_3.pem").getInputStream())); - var entry = new KeyVault.KeyVaultEntry("test", new String(privateKey), new String(publicKey), "RSA"); - var keyVault = new KeyVault(entry); - assertNotNull(keyVault.get("test")); - } + var entry = + new KeyVault.KeyVaultEntry("test", new String(privateKey), new String(publicKey), "EC"); + var keyVault = new KeyVault(entry); + assertNotNull(keyVault.get("test")); + } - @Test - public void testPEMFile() throws Exception { - var publicKey = Base64.getDecoder().decode(IOUtils.toString(new ClassPathResource("/generated_pub_3.pem").getInputStream())); - var privateKey = Base64.getDecoder().decode(IOUtils.toString(new ClassPathResource("/generated_private_3.pem").getInputStream())); + public PublicKey testFunctionPublic1(String part, String algo) { + return null; + } - var entry = new KeyVault.KeyVaultEntry("test", new String(privateKey), new String(publicKey), "EC"); - var keyVault = new KeyVault(entry); - assertNotNull(keyVault.get("test")); - } + public PrivateKey testFunctionPrivate1(String part, String algo) { + return null; + } - public PublicKey testFunctionPublic1(String part, String algo) { - return null; - } - public PrivateKey testFunctionPrivate1(String part, String algo) { - return null; - } + public String testFunctionPublic2(String part, String algo) { + return null; + } - public String testFunctionPublic2(String part, String algo) { - return null; - } - public String testFunctionPrivate2(String part, String algo) { - return null; - } -} \ No newline at end of file + public String testFunctionPrivate2(String part, String algo) { + return null; + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapperTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapperTest.java index ec72c809..9ceda185 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapperTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/security/signature/SignatureResponseWrapperTest.java @@ -15,188 +15,185 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwt; +import io.jsonwebtoken.JwtParser; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; import java.io.IOException; import java.io.OutputStream; import java.security.KeyPair; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; - import java.util.ArrayList; import java.util.List; - import org.apache.commons.codec.binary.Hex; import org.dpppt.backend.sdk.utils.UTCInstant; import org.junit.Test; import org.springframework.mock.web.MockHttpServletResponse; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.JwtParser; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import io.jsonwebtoken.security.Keys; - -/** - * @author bachmann created on 24.04.20 - **/ +/** @author bachmann created on 24.04.20 */ public class SignatureResponseWrapperTest { - private MockHttpServletResponse response; - - @Test - public void testSignaturResponseWrapper() throws IOException, NoSuchAlgorithmException { - - response = new MockHttpServletResponse(); - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - - List protectedHeaders = new ArrayList(); - protectedHeaders.add("X-BATCH-RELEASE-TIME"); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - String digest = response.getHeader("Digest"); - String rawJWT = response.getHeader("Signature"); - assertNotNull(digest); - String expected = "sha-256=" - + Hex.encodeHexString(MessageDigest.getInstance("SHA-256").digest("TEST".getBytes())); - assertEquals(expected, digest); - - } - @Test - public void setSignatureOnlyFor200And204ButNotFor304() throws IOException { - response = new MockHttpServletResponse(); - response.setStatus(200); - - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - - List protectedHeaders = new ArrayList(); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - String rawJWT = response.getHeader("Signature"); - assertNotNull(rawJWT); - - response = new MockHttpServletResponse(); - response.setStatus(204); - signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - rawJWT = response.getHeader("Signature"); - assertNotNull(rawJWT); - - response = new MockHttpServletResponse(); - response.setStatus(304); - signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - rawJWT = response.getHeader("Signature"); - assertNull(rawJWT); - } - - @Test - public void testSignatureViaOutput() throws IOException, NoSuchAlgorithmException { - response = new MockHttpServletResponse(); - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - KeyPair wrongKey = Keys.keyPairFor(SignatureAlgorithm.ES256); - List protectedHeaders = new ArrayList(); - protectedHeaders.add("X-BATCH-RELEASE-TIME"); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - OutputStream stream = OutputStream.nullOutputStream(); - signatureResponseWrapper.outputData(stream); - String digest = response.getHeader("Digest"); - String rawJWT = response.getHeader("Signature"); - assertNotNull(digest); - String expected = "sha-256=" - + Hex.encodeHexString(MessageDigest.getInstance("SHA-256").digest("TEST".getBytes())); - assertEquals(expected, digest); - } - - @Test - public void testBatchReleaseTime() throws IOException, NoSuchAlgorithmException { - response = new MockHttpServletResponse(); - response.setHeader("X-BATCH-RELEASE-TIME", - Long.toString(UTCInstant.now().getTimestamp())); - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - KeyPair wrongKey = Keys.keyPairFor(SignatureAlgorithm.ES256); - List protectedHeaders = new ArrayList(); - protectedHeaders.add("X-BATCH-RELEASE-TIME"); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - String digest = response.getHeader("Digest"); - String rawJWT = response.getHeader("Signature"); - JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(keyPair.getPublic()).build(); - Jwt jwt = jwtParser.parse(rawJWT); - - assertTrue(response.containsHeader("X-BATCH-RELEASE-TIME")); - Claims claims = (Claims) jwt.getBody(); - assertTrue(claims.containsKey("batch-release-time")); - } - - @Test - public void testBatchReleaseTimeWithOutputStream() throws IOException, NoSuchAlgorithmException { - response = new MockHttpServletResponse(); - response.setHeader("X-BATCH-RELEASE-TIME", - Long.toString(UTCInstant.now().getTimestamp())); - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - KeyPair wrongKey = Keys.keyPairFor(SignatureAlgorithm.ES256); - List protectedHeaders = new ArrayList(); - protectedHeaders.add("X-BATCH-RELEASE-TIME"); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - OutputStream stream = OutputStream.nullOutputStream(); - signatureResponseWrapper.outputData(stream); - String digest = response.getHeader("Digest"); - String rawJWT = response.getHeader("Signature"); - JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(keyPair.getPublic()).build(); - Jwt jwt = jwtParser.parse(rawJWT); - - assertTrue(response.containsHeader("X-BATCH-RELEASE-TIME")); - Claims claims = (Claims) jwt.getBody(); - assertTrue(claims.containsKey("batch-release-time")); - } - - @Test - public void testSignaturResponseWrapperWithDebugHeaders() throws IOException, NoSuchAlgorithmException { - response = new MockHttpServletResponse(); - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - List protectedHeaders = new ArrayList(); - protectedHeaders.add("X-BATCH-RELEASE-TIME"); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, true); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - - String digest = response.getHeader("Digest"); - assertNotNull(digest); - - String publicKey = response.getHeader("X-Public-Key"); - assertNotNull(publicKey); - } - - @Test - public void testSignaturResponseWrapperWithoutDebugHeaders() throws IOException, NoSuchAlgorithmException { - response = new MockHttpServletResponse(); - KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); - List protectedHeaders = new ArrayList(); - protectedHeaders.add("X-BATCH-RELEASE-TIME"); - SignatureResponseWrapper signatureResponseWrapper = new SignatureResponseWrapper(response, keyPair, 21, - protectedHeaders, false); - signatureResponseWrapper.getOutputStream().print("TEST"); - signatureResponseWrapper.flushBuffer(); - - String digest = response.getHeader("Digest"); - assertNull(digest); - - String publicKey = response.getHeader("X-Public-Key"); - assertNull(publicKey); - } -} \ No newline at end of file + private MockHttpServletResponse response; + + @Test + public void testSignaturResponseWrapper() throws IOException, NoSuchAlgorithmException { + + response = new MockHttpServletResponse(); + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + + List protectedHeaders = new ArrayList(); + protectedHeaders.add("X-BATCH-RELEASE-TIME"); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + String digest = response.getHeader("Digest"); + String rawJWT = response.getHeader("Signature"); + assertNotNull(digest); + String expected = + "sha-256=" + + Hex.encodeHexString(MessageDigest.getInstance("SHA-256").digest("TEST".getBytes())); + assertEquals(expected, digest); + } + + @Test + public void setSignatureOnlyFor200And204ButNotFor304() throws IOException { + response = new MockHttpServletResponse(); + response.setStatus(200); + + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + + List protectedHeaders = new ArrayList(); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + String rawJWT = response.getHeader("Signature"); + assertNotNull(rawJWT); + + response = new MockHttpServletResponse(); + response.setStatus(204); + signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + rawJWT = response.getHeader("Signature"); + assertNotNull(rawJWT); + + response = new MockHttpServletResponse(); + response.setStatus(304); + signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + rawJWT = response.getHeader("Signature"); + assertNull(rawJWT); + } + + @Test + public void testSignatureViaOutput() throws IOException, NoSuchAlgorithmException { + response = new MockHttpServletResponse(); + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + KeyPair wrongKey = Keys.keyPairFor(SignatureAlgorithm.ES256); + List protectedHeaders = new ArrayList(); + protectedHeaders.add("X-BATCH-RELEASE-TIME"); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + OutputStream stream = OutputStream.nullOutputStream(); + signatureResponseWrapper.outputData(stream); + String digest = response.getHeader("Digest"); + String rawJWT = response.getHeader("Signature"); + assertNotNull(digest); + String expected = + "sha-256=" + + Hex.encodeHexString(MessageDigest.getInstance("SHA-256").digest("TEST".getBytes())); + assertEquals(expected, digest); + } + + @Test + public void testBatchReleaseTime() throws IOException, NoSuchAlgorithmException { + response = new MockHttpServletResponse(); + response.setHeader("X-BATCH-RELEASE-TIME", Long.toString(UTCInstant.now().getTimestamp())); + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + KeyPair wrongKey = Keys.keyPairFor(SignatureAlgorithm.ES256); + List protectedHeaders = new ArrayList(); + protectedHeaders.add("X-BATCH-RELEASE-TIME"); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + String digest = response.getHeader("Digest"); + String rawJWT = response.getHeader("Signature"); + JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(keyPair.getPublic()).build(); + Jwt jwt = jwtParser.parse(rawJWT); + + assertTrue(response.containsHeader("X-BATCH-RELEASE-TIME")); + Claims claims = (Claims) jwt.getBody(); + assertTrue(claims.containsKey("batch-release-time")); + } + + @Test + public void testBatchReleaseTimeWithOutputStream() throws IOException, NoSuchAlgorithmException { + response = new MockHttpServletResponse(); + response.setHeader("X-BATCH-RELEASE-TIME", Long.toString(UTCInstant.now().getTimestamp())); + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + KeyPair wrongKey = Keys.keyPairFor(SignatureAlgorithm.ES256); + List protectedHeaders = new ArrayList(); + protectedHeaders.add("X-BATCH-RELEASE-TIME"); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + OutputStream stream = OutputStream.nullOutputStream(); + signatureResponseWrapper.outputData(stream); + String digest = response.getHeader("Digest"); + String rawJWT = response.getHeader("Signature"); + JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(keyPair.getPublic()).build(); + Jwt jwt = jwtParser.parse(rawJWT); + + assertTrue(response.containsHeader("X-BATCH-RELEASE-TIME")); + Claims claims = (Claims) jwt.getBody(); + assertTrue(claims.containsKey("batch-release-time")); + } + + @Test + public void testSignaturResponseWrapperWithDebugHeaders() + throws IOException, NoSuchAlgorithmException { + response = new MockHttpServletResponse(); + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + List protectedHeaders = new ArrayList(); + protectedHeaders.add("X-BATCH-RELEASE-TIME"); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, true); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + + String digest = response.getHeader("Digest"); + assertNotNull(digest); + + String publicKey = response.getHeader("X-Public-Key"); + assertNotNull(publicKey); + } + + @Test + public void testSignaturResponseWrapperWithoutDebugHeaders() + throws IOException, NoSuchAlgorithmException { + response = new MockHttpServletResponse(); + KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.ES256); + List protectedHeaders = new ArrayList(); + protectedHeaders.add("X-BATCH-RELEASE-TIME"); + SignatureResponseWrapper signatureResponseWrapper = + new SignatureResponseWrapper(response, keyPair, 21, protectedHeaders, false); + signatureResponseWrapper.getOutputStream().print("TEST"); + signatureResponseWrapper.flushBuffer(); + + String digest = response.getHeader("Digest"); + assertNull(digest); + + String publicKey = response.getHeader("X-Public-Key"); + assertNull(publicKey); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/GaenUnitTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/GaenUnitTest.java index 196cfec6..1c71d7df 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/GaenUnitTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/GaenUnitTest.java @@ -12,15 +12,14 @@ import static org.junit.Assert.assertEquals; import java.time.Duration; - import org.dpppt.backend.sdk.model.gaen.GaenUnit; import org.junit.Test; public class GaenUnitTest { - @Test - public void testTenMinutesAre10Minutes() throws Exception { - var tenMinutes = Duration.of(1,GaenUnit.TenMinutes); - var t10Minutes = Duration.ofMinutes(10); - assertEquals(tenMinutes, t10Minutes); - } -} \ No newline at end of file + @Test + public void testTenMinutesAre10Minutes() throws Exception { + var tenMinutes = Duration.of(1, GaenUnit.TenMinutes); + var t10Minutes = Duration.ofMinutes(10); + assertEquals(tenMinutes, t10Minutes); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/SemverTests.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/SemverTests.java index 562246bc..5664739f 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/SemverTests.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/SemverTests.java @@ -1,119 +1,134 @@ package org.dpppt.backend.sdk.ws.util; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; import java.util.List; - import org.dpppt.backend.sdk.semver.Version; import org.junit.Test; public class SemverTests { - - @Test - public void testToString() throws Exception { - var v = new Version("ios-1.1.3-test+meta"); - assertEquals("1.1.3-test+meta", v.toString()); - v = new Version("1.1.3+meta"); - assertEquals("1.1.3+meta", v.toString()); - v = new Version("ios-1.1.3-meta"); - assertEquals("1.1.3-meta", v.toString()); - v = new Version("ios-1.1.3"); - assertEquals("1.1.3", v.toString()); - v = new Version("1.1.3"); - assertEquals("1.1.3", v.toString()); + @Test + public void testToString() throws Exception { + var v = new Version("ios-1.1.3-test+meta"); + assertEquals("1.1.3-test+meta", v.toString()); + v = new Version("1.1.3+meta"); + assertEquals("1.1.3+meta", v.toString()); + v = new Version("ios-1.1.3-meta"); + assertEquals("1.1.3-meta", v.toString()); + v = new Version("ios-1.1.3"); + assertEquals("1.1.3", v.toString()); + v = new Version("1.1.3"); + assertEquals("1.1.3", v.toString()); + } + + @Test + public void testVersionFromString() throws Exception { + var cases = + List.of( + new Version("ios-0.1.0"), + new Version("android-0.1.1"), + new Version("0.2.0"), + new Version("1.0.0-prerelease"), + new Version("1.0.0"), + new Version("1.0.1+ios")); + for (int i = 0; i < cases.size(); i++) { + var currentVersion = cases.get(i); + assertTrue(currentVersion.isSameVersionAs(currentVersion)); + for (int j = 0; j < i; j++) { + var olderVersion = cases.get(j); + assertTrue(currentVersion.isLargerVersionThan(olderVersion)); + } } - - @Test - public void testVersionFromString() throws Exception { - var cases = List.of(new Version("ios-0.1.0"),new Version("android-0.1.1"),new Version("0.2.0"),new Version("1.0.0-prerelease"),new Version("1.0.0"),new Version("1.0.1+ios")); - for(int i =0; i < cases.size(); i++) { - var currentVersion = cases.get(i); - assertTrue(currentVersion.isSameVersionAs(currentVersion)); - for(int j = 0; j < i; j++ ){ - var olderVersion = cases.get(j); - assertTrue(currentVersion.isLargerVersionThan(olderVersion)); - } - } - var releaseVersion = new Version("1.0.0"); - var metaInfoVersion = new Version("1.0.0+ios"); - assertTrue(releaseVersion.isSameVersionAs(metaInfoVersion)); - assertNotEquals(metaInfoVersion, releaseVersion); - var sameIosVersion = new Version("1.0.0+ios"); - assertEquals(sameIosVersion, metaInfoVersion); - } - - @Test - public void testPlatform() throws Exception { - var iosNonStandard = new Version("ios-1.0.0"); - var iosStandard = new Version("1.0.0+ios"); - assertTrue(iosNonStandard.isIOS()); - assertTrue(iosStandard.isIOS()); - assertFalse(iosNonStandard.isAndroid()); - assertFalse(iosStandard.isAndroid()); + var releaseVersion = new Version("1.0.0"); + var metaInfoVersion = new Version("1.0.0+ios"); + assertTrue(releaseVersion.isSameVersionAs(metaInfoVersion)); + assertNotEquals(metaInfoVersion, releaseVersion); + var sameIosVersion = new Version("1.0.0+ios"); + assertEquals(sameIosVersion, metaInfoVersion); + } - var androidNonStandard = new Version("android-1.0.0"); - var androidStandard = new Version("1.0.0+android"); - assertFalse(androidNonStandard.isIOS()); - assertFalse(androidStandard.isIOS()); - assertTrue(androidNonStandard.isAndroid()); - assertTrue(androidStandard.isAndroid()); + @Test + public void testPlatform() throws Exception { + var iosNonStandard = new Version("ios-1.0.0"); + var iosStandard = new Version("1.0.0+ios"); + assertTrue(iosNonStandard.isIOS()); + assertTrue(iosStandard.isIOS()); + assertFalse(iosNonStandard.isAndroid()); + assertFalse(iosStandard.isAndroid()); - var random = new Version("1.0.0"); - assertFalse( random.isAndroid()); - assertFalse( random.isIOS()); - } - - @Test - public void testVersionFromExplicit() throws Exception { - var cases = List.of(new Version(0,1,0),new Version(0,1,1),new Version(0,2,0),new Version(1,0,0,"prerelease", ""),new Version(1,0,0),new Version(1,0,1,"", "ios")); - for(int i =0; i < cases.size(); i++) { - var currentVersion = cases.get(i); - assertTrue(currentVersion.isSameVersionAs(currentVersion)); - for(int j = 0; j < i; j++ ){ - var olderVersion = cases.get(j); - assertTrue(currentVersion.isLargerVersionThan(olderVersion)); - } - } - var releaseVersion = new Version(1,0,0); - var metaInfoVersion = new Version(1,0,0,"", "ios"); - assertTrue(releaseVersion.isSameVersionAs(metaInfoVersion)); - assertNotEquals(metaInfoVersion, releaseVersion); - var sameIosVersion = new Version(1,0,0,"", "ios"); - assertEquals(sameIosVersion, metaInfoVersion); + var androidNonStandard = new Version("android-1.0.0"); + var androidStandard = new Version("1.0.0+android"); + assertFalse(androidNonStandard.isIOS()); + assertFalse(androidStandard.isIOS()); + assertTrue(androidNonStandard.isAndroid()); + assertTrue(androidStandard.isAndroid()); + + var random = new Version("1.0.0"); + assertFalse(random.isAndroid()); + assertFalse(random.isIOS()); + } + + @Test + public void testVersionFromExplicit() throws Exception { + var cases = + List.of( + new Version(0, 1, 0), + new Version(0, 1, 1), + new Version(0, 2, 0), + new Version(1, 0, 0, "prerelease", ""), + new Version(1, 0, 0), + new Version(1, 0, 1, "", "ios")); + for (int i = 0; i < cases.size(); i++) { + var currentVersion = cases.get(i); + assertTrue(currentVersion.isSameVersionAs(currentVersion)); + for (int j = 0; j < i; j++) { + var olderVersion = cases.get(j); + assertTrue(currentVersion.isLargerVersionThan(olderVersion)); + } } - - @Test - public void testMissingMinorOrPatch() throws Exception { - var apiLevel = "29"; - var iosVersion = "13.6"; - var apiLevelWithMeta = "29+test"; - var iosVersionWithMeta = "13.6+test"; - var apiLevelVersion = new Version(apiLevel); - assertTrue(apiLevelVersion.getMajor().equals(29) - && apiLevelVersion.getMinor().equals(0) - && apiLevelVersion.getPatch().equals(0)); + var releaseVersion = new Version(1, 0, 0); + var metaInfoVersion = new Version(1, 0, 0, "", "ios"); + assertTrue(releaseVersion.isSameVersionAs(metaInfoVersion)); + assertNotEquals(metaInfoVersion, releaseVersion); + var sameIosVersion = new Version(1, 0, 0, "", "ios"); + assertEquals(sameIosVersion, metaInfoVersion); + } - var iosVersionVersion = new Version(iosVersion); - assertTrue(iosVersionVersion.getMajor() == 13 - && iosVersionVersion.getMinor() == 6 - && iosVersionVersion.getPatch() == 0); + @Test + public void testMissingMinorOrPatch() throws Exception { + var apiLevel = "29"; + var iosVersion = "13.6"; + var apiLevelWithMeta = "29+test"; + var iosVersionWithMeta = "13.6+test"; + var apiLevelVersion = new Version(apiLevel); + assertTrue( + apiLevelVersion.getMajor().equals(29) + && apiLevelVersion.getMinor().equals(0) + && apiLevelVersion.getPatch().equals(0)); - var apiLevelWithMetaVersion = new Version(apiLevelWithMeta); - assertTrue(apiLevelWithMetaVersion.getMajor().equals(29) - && apiLevelWithMetaVersion.getMinor().equals(0) - && apiLevelWithMetaVersion.getPatch().equals(0) - && apiLevelWithMetaVersion.getMetaInfo().equals("test")); + var iosVersionVersion = new Version(iosVersion); + assertTrue( + iosVersionVersion.getMajor() == 13 + && iosVersionVersion.getMinor() == 6 + && iosVersionVersion.getPatch() == 0); - var iosVersionVersionMeta = new Version(iosVersionWithMeta); - - assertTrue(iosVersionVersionMeta.getMajor().equals(13) - && iosVersionVersionMeta.getMinor().equals(6) - && iosVersionVersionMeta.getPatch().equals(0) - && iosVersionVersionMeta.getMetaInfo().equals("test")); + var apiLevelWithMetaVersion = new Version(apiLevelWithMeta); + assertTrue( + apiLevelWithMetaVersion.getMajor().equals(29) + && apiLevelWithMetaVersion.getMinor().equals(0) + && apiLevelWithMetaVersion.getPatch().equals(0) + && apiLevelWithMetaVersion.getMetaInfo().equals("test")); - } -} \ No newline at end of file + var iosVersionVersionMeta = new Version(iosVersionWithMeta); + + assertTrue( + iosVersionVersionMeta.getMajor().equals(13) + && iosVersionVersionMeta.getMinor().equals(6) + && iosVersionVersionMeta.getPatch().equals(0) + && iosVersionVersionMeta.getMetaInfo().equals("test")); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/TestJDBCGaen.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/TestJDBCGaen.java index 33006e2f..49ac019a 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/TestJDBCGaen.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/TestJDBCGaen.java @@ -12,93 +12,113 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; - import javax.sql.DataSource; - import org.dpppt.backend.sdk.data.gaen.GaenKeyRowMapper; import org.dpppt.backend.sdk.model.gaen.GaenKey; -import org.dpppt.backend.sdk.model.gaen.GaenUnit; import org.dpppt.backend.sdk.utils.UTCInstant; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.transaction.annotation.Transactional; public class TestJDBCGaen { - private static final String PGSQL = "pgsql"; - private final String dbType; - private final NamedParameterJdbcTemplate jt; + private static final String PGSQL = "pgsql"; + private final String dbType; + private final NamedParameterJdbcTemplate jt; + + public TestJDBCGaen(String dbType, DataSource dataSource) { + this.dbType = dbType; + this.jt = new NamedParameterJdbcTemplate(dataSource); + } + + @Transactional(readOnly = true) + public List getSortedExposedForKeyDate( + Long keyDate, Long publishedAfter, Long publishedUntil) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue( + "rollingPeriodStartNumberStart", UTCInstant.ofEpochMillis(keyDate).get10MinutesSince1970()); + params.addValue( + "rollingPeriodStartNumberEnd", + UTCInstant.ofEpochMillis(keyDate).plusDays(1).get10MinutesSince1970()); + params.addValue("publishedUntil", new Date(publishedUntil)); + + String sql = + "select pk_exposed_id, key, rolling_start_number, rolling_period, transmission_risk_level" + + " from t_gaen_exposed where rolling_start_number >= :rollingPeriodStartNumberStart" + + " and rolling_start_number < :rollingPeriodStartNumberEnd and received_at <" + + " :publishedUntil"; + + if (publishedAfter != null) { + params.addValue("publishedAfter", new Date(publishedAfter)); + sql += " and received_at >= :publishedAfter"; + } + + sql += " order by pk_exposed_id desc"; - public TestJDBCGaen(String dbType, DataSource dataSource) { - this.dbType = dbType; - this.jt = new NamedParameterJdbcTemplate(dataSource); - } - - @Transactional(readOnly = true) - public List getSortedExposedForKeyDate(Long keyDate, Long publishedAfter, Long publishedUntil) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("rollingPeriodStartNumberStart",UTCInstant.ofEpochMillis(keyDate).get10MinutesSince1970()); - params.addValue("rollingPeriodStartNumberEnd", UTCInstant.ofEpochMillis(keyDate).plusDays(1).get10MinutesSince1970()); - params.addValue("publishedUntil", new Date(publishedUntil)); + return jt.query(sql, params, new GaenKeyRowMapper()); + } - String sql = "select pk_exposed_id, key, rolling_start_number, rolling_period, transmission_risk_level from t_gaen_exposed where" - + " rolling_start_number >= :rollingPeriodStartNumberStart" - + " and rolling_start_number < :rollingPeriodStartNumberEnd" - + " and received_at < :publishedUntil"; + @Transactional(readOnly = false) + public void upsertExposees(List gaenKeys, UTCInstant receivedAt) { + String sql = null; + if (dbType.equals(PGSQL)) { + sql = + "insert into t_gaen_exposed (key, rolling_start_number, rolling_period," + + " transmission_risk_level, received_at) values (:key, :rolling_start_number," + + " :rolling_period, :transmission_risk_level, :received_at) on conflict on" + + " constraint gaen_exposed_key do nothing"; + } else { + sql = + "merge into t_gaen_exposed using (values(cast(:key as varchar(24))," + + " :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at))" + + " as vals(key, rolling_start_number, rolling_period, transmission_risk_level," + + " received_at) on t_gaen_exposed.key = vals.key when not matched then insert (key," + + " rolling_start_number, rolling_period, transmission_risk_level, received_at)" + + " values (vals.key, vals.rolling_start_number, vals.rolling_period," + + " vals.transmission_risk_level, vals.received_at)"; + } + var parameterList = new ArrayList(); + for (var gaenKey : gaenKeys) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("key", gaenKey.getKeyData()); + params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); + params.addValue("rolling_period", gaenKey.getRollingPeriod()); + params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); + params.addValue("received_at", receivedAt.getDate()); + parameterList.add(params); + } + jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); + } - if (publishedAfter != null) { - params.addValue("publishedAfter", new Date(publishedAfter)); - sql += " and received_at >= :publishedAfter"; - } - - sql += " order by pk_exposed_id desc"; - - return jt.query(sql, params, new GaenKeyRowMapper()); - } - - @Transactional(readOnly = false) - public void upsertExposees(List gaenKeys, UTCInstant receivedAt) { - String sql = null; - if (dbType.equals(PGSQL)) { - sql = "insert into t_gaen_exposed (key, rolling_start_number, rolling_period, transmission_risk_level, received_at) values (:key, :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at)" - + " on conflict on constraint gaen_exposed_key do nothing"; - } else { - sql = "merge into t_gaen_exposed using (values(cast(:key as varchar(24)), :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at))" - + " as vals(key, rolling_start_number, rolling_period, transmission_risk_level, received_at) on t_gaen_exposed.key = vals.key" - + " when not matched then insert (key, rolling_start_number, rolling_period, transmission_risk_level, received_at) values (vals.key, vals.rolling_start_number, vals.rolling_period, vals.transmission_risk_level, vals.received_at)"; - } - var parameterList = new ArrayList(); - for(var gaenKey : gaenKeys) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("key", gaenKey.getKeyData()); - params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); - params.addValue("rolling_period", gaenKey.getRollingPeriod()); - params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); - params.addValue("received_at", receivedAt.getDate()); - parameterList.add(params); - } - jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); - } - @Transactional(readOnly = false) - public void upsertExposeesDebug(List gaenKeys, UTCInstant receivedAt) { - String sql = null; - if (dbType.equals(PGSQL)) { - sql = "insert into t_debug_gaen_exposed (key, rolling_start_number, rolling_period, transmission_risk_level, received_at, device_name) values (:key, :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at, 'test')" - + " on conflict on constraint debug_gaen_exposed_key do nothing"; - } else { - sql = "merge into t_debug_gaen_exposed using (values(cast(:key as varchar(24)), :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at, 'test'))" - + " as vals(key, rolling_start_number, rolling_period, transmission_risk_level, received_at, device_name) on t_debug_gaen_exposed.key = vals.key" - + " when not matched then insert (key, rolling_start_number, rolling_period, transmission_risk_level, received_at, device_name) values (vals.key, vals.rolling_start_number, vals.rolling_period, vals.transmission_risk_level, vals.received_at, vals.device_name)"; - } - var parameterList = new ArrayList(); - for(var gaenKey : gaenKeys) { - MapSqlParameterSource params = new MapSqlParameterSource(); - params.addValue("key", gaenKey.getKeyData()); - params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); - params.addValue("rolling_period", gaenKey.getRollingPeriod()); - params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); - params.addValue("received_at", receivedAt.getDate()); - parameterList.add(params); - } - jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); - } -} \ No newline at end of file + @Transactional(readOnly = false) + public void upsertExposeesDebug(List gaenKeys, UTCInstant receivedAt) { + String sql = null; + if (dbType.equals(PGSQL)) { + sql = + "insert into t_debug_gaen_exposed (key, rolling_start_number, rolling_period," + + " transmission_risk_level, received_at, device_name) values (:key," + + " :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at," + + " 'test') on conflict on constraint debug_gaen_exposed_key do nothing"; + } else { + sql = + "merge into t_debug_gaen_exposed using (values(cast(:key as varchar(24))," + + " :rolling_start_number, :rolling_period, :transmission_risk_level, :received_at," + + " 'test')) as vals(key, rolling_start_number, rolling_period," + + " transmission_risk_level, received_at, device_name) on t_debug_gaen_exposed.key =" + + " vals.key when not matched then insert (key, rolling_start_number," + + " rolling_period, transmission_risk_level, received_at, device_name) values" + + " (vals.key, vals.rolling_start_number, vals.rolling_period," + + " vals.transmission_risk_level, vals.received_at, vals.device_name)"; + } + var parameterList = new ArrayList(); + for (var gaenKey : gaenKeys) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("key", gaenKey.getKeyData()); + params.addValue("rolling_start_number", gaenKey.getRollingStartNumber()); + params.addValue("rolling_period", gaenKey.getRollingPeriod()); + params.addValue("transmission_risk_level", gaenKey.getTransmissionRiskLevel()); + params.addValue("received_at", receivedAt.getDate()); + parameterList.add(params); + } + jt.batchUpdate(sql, parameterList.toArray(new MapSqlParameterSource[0])); + } +} diff --git a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/ValidationUtilsTest.java b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/ValidationUtilsTest.java index b4dba039..9b93b128 100644 --- a/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/ValidationUtilsTest.java +++ b/dpppt-backend-sdk/dpppt-backend-sdk-ws/src/test/java/org/dpppt/backend/sdk/ws/util/ValidationUtilsTest.java @@ -3,24 +3,23 @@ import static org.junit.Assert.assertEquals; import java.time.Duration; - import org.dpppt.backend.sdk.utils.UTCInstant; - import org.junit.Test; public class ValidationUtilsTest { - @Test - public void testOnlyMidnightIsValid() throws Exception { - var validationUtils = new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis()); - var midnight = UTCInstant.today(); - assertEquals(true, validationUtils.isValidKeyDate(midnight)); - assertEquals(false, validationUtils.isValidKeyDate(midnight.minusSeconds(1))); - assertEquals(false, validationUtils.isValidKeyDate(midnight.minusMinutes(1))); - assertEquals(false, validationUtils.isValidKeyDate(midnight.minusHours(1))); - assertEquals(false, validationUtils.isValidKeyDate(midnight.plusSeconds(1))); - assertEquals(false, validationUtils.isValidKeyDate(midnight.plusMinutes(1))); - assertEquals(false, validationUtils.isValidKeyDate(midnight.plusHours(1))); - - assertEquals(true, UTCInstant.today().hasSameDateAs(midnight)); - } -} \ No newline at end of file + @Test + public void testOnlyMidnightIsValid() throws Exception { + var validationUtils = + new ValidationUtils(16, Duration.ofDays(14), Duration.ofHours(2).toMillis()); + var midnight = UTCInstant.today(); + assertEquals(true, validationUtils.isValidKeyDate(midnight)); + assertEquals(false, validationUtils.isValidKeyDate(midnight.minusSeconds(1))); + assertEquals(false, validationUtils.isValidKeyDate(midnight.minusMinutes(1))); + assertEquals(false, validationUtils.isValidKeyDate(midnight.minusHours(1))); + assertEquals(false, validationUtils.isValidKeyDate(midnight.plusSeconds(1))); + assertEquals(false, validationUtils.isValidKeyDate(midnight.plusMinutes(1))); + assertEquals(false, validationUtils.isValidKeyDate(midnight.plusHours(1))); + + assertEquals(true, UTCInstant.today().hasSameDateAs(midnight)); + } +}