@Override
    public void upgrade() {
        Map<String, Set<String>> encryptedFieldsByInputType = getEncryptedFieldsByInputType();

        if (getMigratedField().equals(encryptedFieldsByInputType)) {
            LOG.debug("Migration already completed.");
            return;
        }

        final MongoCollection<Document> collection = getCollection();
        final FindIterable<Document> documents =
                collection.find(in(FIELD_TYPE, encryptedFieldsByInputType.keySet()));

        documents.forEach(doc -> {
            @SuppressWarnings("unchecked")
            final Map<String, Object> config =
                    new HashMap<>((Map<String, Object>) doc.getOrDefault(FIELD_CONFIGURATION, Map.of()));

            final Set<String> encryptedFields =
                    encryptedFieldsByInputType.getOrDefault((String) doc.get(FIELD_TYPE), Set.of());

            encryptedFields.forEach(fieldName -> {
                final Object value = config.get(fieldName);
                // Assume that in case of a Map, the value is already encrypted and doesn't need conversion.
                if (config.containsKey(fieldName) && !(value instanceof Map)) {
                    final EncryptedValue encryptedValue = objectMapper.convertValue(value, EncryptedValue.class);
                    config.put(fieldName, dbObjectMapper.convertValue(encryptedValue, TypeReferences.MAP_STRING_OBJECT));
                }
            });

            collection.updateOne(eq(FIELD_ID, doc.getObjectId(FIELD_ID)), Updates.set(FIELD_CONFIGURATION, config));
        });

        saveMigrationCompleted(encryptedFieldsByInputType);
    }
@SuppressWarnings("unchecked")
    @Test
    public void migrateUnencryptedSecret() {
        migration.upgrade();

        final Document migrated =
                collection.find(Filters.eq(FIELD_TITLE, "unencrypted-secret")).first();

        assertThat(migrated).isNotNull().satisfies(doc ->
                assertThat((Map<String, Object>) doc.get(FIELD_CONFIGURATION)).satisfies(config -> {
                    final Object sourceValue = config.get(ENCRYPTED_FIELD);
                    assertThat(sourceValue).isInstanceOf(Map.class);
                    final EncryptedValue encryptedValue = dbObjectMapper.convertValue(sourceValue, EncryptedValue.class);
                    assertThat(encryptedValueService.decrypt(encryptedValue)).isEqualTo("X-Encrypted-Header: secret");
                })
        );
    }