From 035006a8397f67b7bd7189b3b5f62247cdc5a3ec Mon Sep 17 00:00:00 2001 From: Carles Arnal Date: Thu, 19 Dec 2024 09:08:24 +0100 Subject: [PATCH 1/3] Fix the owner related features in kafka sql --- .../rest/v7/impl/AbstractResource.java | 15 +- .../limits/RegistryStorageLimitsEnforcer.java | 10 +- .../registry/rest/v2/GroupsResourceImpl.java | 14 +- .../registry/rest/v3/GroupsResourceImpl.java | 13 +- .../registry/storage/RegistryStorage.java | 4 +- .../ReadOnlyRegistryStorageDecorator.java | 9 +- .../RegistryStorageDecoratorBase.java | 9 +- .../AbstractReadOnlyRegistryStorage.java | 5 +- .../kafkasql/KafkaSqlRegistryStorage.java | 13 +- .../messages/CreateArtifact10Message.java | 3 +- .../messages/CreateArtifact11Message.java | 56 ++++++ .../messages/CreateArtifact9Message.java | 2 +- .../CreateArtifactVersion10Message.java | 54 ++++++ .../CreateArtifactVersion8Message.java | 2 +- .../CreateArtifactVersion9Message.java | 3 +- .../kafkasql/serde/KafkaSqlMessageIndex.java | 72 +------- .../impl/sql/AbstractSqlRegistryStorage.java | 6 +- .../storage/AbstractRegistryStorageTest.java | 120 ++++++------ .../RegistryStoragePerformanceTest.java | 2 +- .../storage/RegistryStorageSmokeTest.java | 14 +- .../impl/kafkasql/KafkaSqlAuthTest.java | 17 ++ .../readonly/ReadOnlyRegistryStorageTest.java | 8 +- .../tools/kafka-compose/kafka-ingress.yaml | 18 ++ examples/tools/kafka-compose/kafka.yaml | 86 +++++++++ .../io/apicurio/tests/auth/SimpleAuthIT.java | 172 ++++++++++++++++++ .../utils/tests/KafkasqlAuthTestProfile.java | 29 +++ 26 files changed, 574 insertions(+), 182 deletions(-) create mode 100644 app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact11Message.java create mode 100644 app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion10Message.java create mode 100644 app/src/test/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlAuthTest.java create mode 100644 examples/tools/kafka-compose/kafka-ingress.yaml create mode 100644 examples/tools/kafka-compose/kafka.yaml create mode 100644 utils/tests/src/main/java/io/apicurio/registry/utils/tests/KafkasqlAuthTestProfile.java diff --git a/app/src/main/java/io/apicurio/registry/ccompat/rest/v7/impl/AbstractResource.java b/app/src/main/java/io/apicurio/registry/ccompat/rest/v7/impl/AbstractResource.java index a83f313d1c..56f7fa21c3 100644 --- a/app/src/main/java/io/apicurio/registry/ccompat/rest/v7/impl/AbstractResource.java +++ b/app/src/main/java/io/apicurio/registry/ccompat/rest/v7/impl/AbstractResource.java @@ -32,6 +32,7 @@ import io.apicurio.registry.types.VersionState; import io.apicurio.registry.types.provider.ArtifactTypeUtilProvider; import io.apicurio.registry.types.provider.ArtifactTypeUtilProviderFactory; +import io.quarkus.security.identity.SecurityIdentity; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; import org.apache.avro.AvroTypeException; @@ -67,6 +68,9 @@ public abstract class AbstractResource { @Inject ArtifactTypeUtilProviderFactory factory; + @Inject + SecurityIdentity securityIdentity; + protected String toSubjectWithGroupConcat(String groupId, String artifactId) { return (groupId == null ? "" : groupId) + cconfig.groupConcatSeparator + artifactId; } @@ -107,6 +111,9 @@ protected ArtifactVersionMetaDataDto createOrUpdateArtifact(String artifactId, S .collect(Collectors.toList()); final Map resolvedReferences = RegistryContentUtils .recursivelyResolveReferences(parsedReferences, storage::getContentByReference); + + String owner = securityIdentity.getPrincipal().getName(); + try { ContentHandle schemaContent; schemaContent = ContentHandle.create(schema); @@ -126,8 +133,10 @@ protected ArtifactVersionMetaDataDto createOrUpdateArtifact(String artifactId, S ContentWrapperDto firstVersionContent = ContentWrapperDto.builder().content(schemaContent) .contentType(contentType).references(parsedReferences).build(); - res = storage.createArtifact(groupId, artifactId, artifactType, artifactMetaData, null, - firstVersionContent, firstVersionMetaData, null, false, false).getValue(); + res = storage + .createArtifact(groupId, artifactId, artifactType, artifactMetaData, null, + firstVersionContent, firstVersionMetaData, null, false, false, owner) + .getValue(); } else { TypedContent typedSchemaContent = TypedContent.create(schemaContent, contentType); rulesService.applyRules(groupId, artifactId, artifactType, typedSchemaContent, @@ -135,7 +144,7 @@ protected ArtifactVersionMetaDataDto createOrUpdateArtifact(String artifactId, S ContentWrapperDto versionContent = ContentWrapperDto.builder().content(schemaContent) .contentType(contentType).references(parsedReferences).build(); res = storage.createArtifactVersion(groupId, artifactId, null, artifactType, versionContent, - EditableVersionMetaDataDto.builder().build(), List.of(), false, false); + EditableVersionMetaDataDto.builder().build(), List.of(), false, false, owner); } } catch (RuleViolationException ex) { if (ex.getRuleType() == RuleType.VALIDITY) { diff --git a/app/src/main/java/io/apicurio/registry/limits/RegistryStorageLimitsEnforcer.java b/app/src/main/java/io/apicurio/registry/limits/RegistryStorageLimitsEnforcer.java index 033eb1ec4b..92ffe22fd9 100644 --- a/app/src/main/java/io/apicurio/registry/limits/RegistryStorageLimitsEnforcer.java +++ b/app/src/main/java/io/apicurio/registry/limits/RegistryStorageLimitsEnforcer.java @@ -60,12 +60,13 @@ public int order() { public Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean versionIsDraft, boolean dryRun) + List versionBranches, boolean versionIsDraft, boolean dryRun, String owner) throws RegistryStorageException { Pair rval = withLimitsCheck( () -> limitsService.canCreateArtifact(artifactMetaData, versionContent, versionMetaData)) .execute(() -> super.createArtifact(groupId, artifactId, artifactType, artifactMetaData, - version, versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun)); + version, versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun, + owner)); limitsService.artifactCreated(); return rval; } @@ -73,11 +74,12 @@ public Pair createArtifact(Stri @Override public ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto content, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) throws RegistryStorageException { + List branches, boolean isDraft, boolean dryRun, String owner) + throws RegistryStorageException { ArtifactVersionMetaDataDto dto = withLimitsCheck( () -> limitsService.canCreateArtifactVersion(groupId, artifactId, null, content.getContent())) .execute(() -> super.createArtifactVersion(groupId, artifactId, version, artifactType, - content, metaData, branches, isDraft, dryRun)); + content, metaData, branches, isDraft, dryRun, owner)); limitsService.artifactVersionCreated(groupId, artifactId); return dto; } diff --git a/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java b/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java index 70c1879440..021dbeb4e8 100644 --- a/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java +++ b/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java @@ -1098,6 +1098,8 @@ private ArtifactMetaData createArtifactWithRefs(String groupId, String xRegistry String ct = getContentType(); try { + + String owner = securityIdentity.getPrincipal().getName(); String artifactId = xRegistryArtifactId; if (artifactId == null || artifactId.trim().isEmpty()) { @@ -1140,7 +1142,7 @@ private ArtifactMetaData createArtifactWithRefs(String groupId, String xRegistry Pair createResult = storage.createArtifact( defaultGroupIdToNull(groupId), artifactId, artifactType, metaData, xRegistryVersion, - contentDto, versionMetaData, List.of(), false, false); + contentDto, versionMetaData, List.of(), false, false, owner); return V2ApiUtil.dtoToMetaData(groupId, artifactId, artifactType, createResult.getRight()); } catch (ArtifactAlreadyExistsException ex) { @@ -1258,6 +1260,8 @@ private VersionMetaData createArtifactVersionWithRefs(String groupId, String art final Map resolvedReferences = RegistryContentUtils .recursivelyResolveReferences(referencesAsDtos, storage::getContentByReference); + final String owner = securityIdentity.getPrincipal().getName(); + String artifactType = lookupArtifactType(groupId, artifactId); TypedContent typedContent = TypedContent.create(content, ct); rulesService.applyRules(defaultGroupIdToNull(groupId), artifactId, artifactType, typedContent, @@ -1266,7 +1270,8 @@ private VersionMetaData createArtifactVersionWithRefs(String groupId, String art ContentWrapperDto contentDto = ContentWrapperDto.builder().content(content).contentType(ct) .references(referencesAsDtos).build(); ArtifactVersionMetaDataDto vmdDto = storage.createArtifactVersion(defaultGroupIdToNull(groupId), - artifactId, xRegistryVersion, artifactType, contentDto, metaData, List.of(), false, false); + artifactId, xRegistryVersion, artifactType, contentDto, metaData, List.of(), false, false, + owner); return V2ApiUtil.dtoToVersionMetaData(defaultGroupIdToNull(groupId), artifactId, artifactType, vmdDto); } @@ -1396,13 +1401,16 @@ private ArtifactMetaData updateArtifactInternal(String groupId, String artifactI if (description != null && description.trim().isEmpty()) { artifactMD.setDescription(description); } + + final String owner = securityIdentity.getPrincipal().getName(); + EditableVersionMetaDataDto metaData = EditableVersionMetaDataDto.builder().name(artifactMD.getName()) .description(artifactMD.getDescription()).labels(artifactMD.getLabels()).build(); ContentWrapperDto contentDto = ContentWrapperDto.builder().content(content).contentType(contentType) .references(referencesAsDtos).build(); ArtifactVersionMetaDataDto dto = storage.createArtifactVersion(defaultGroupIdToNull(groupId), - artifactId, version, artifactType, contentDto, metaData, List.of(), false, false); + artifactId, version, artifactType, contentDto, metaData, List.of(), false, false, owner); // Note: if the version was created, we need to update the artifact metadata as well, because // those are the semantics of the v2 API. :( diff --git a/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java b/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java index 40e9f3cbb4..164c59cda5 100644 --- a/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java +++ b/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java @@ -913,6 +913,8 @@ public CreateArtifactResponse createArtifact(String groupId, IfArtifactExists if String artifactType = ArtifactTypeUtil.determineArtifactType(typedContent, data.getArtifactType(), factory); + final String owner = securityIdentity.getPrincipal().getName(); + // Create the artifact (with optional first version) EditableArtifactMetaDataDto artifactMetaData = EditableArtifactMetaDataDto.builder() .description(data.getDescription()).name(data.getName()).labels(data.getLabels()).build(); @@ -951,7 +953,7 @@ public CreateArtifactResponse createArtifact(String groupId, IfArtifactExists if Pair storageResult = storage.createArtifact( new GroupId(groupId).getRawGroupIdWithNull(), artifactId, artifactType, artifactMetaData, firstVersion, firstVersionContent, firstVersionMetaData, firstVersionBranches, - firstVersionIsDraft, dryRun != null && dryRun); + firstVersionIsDraft, dryRun != null && dryRun, owner); // Now return both the artifact metadata and (if available) the version metadata CreateArtifactResponse rval = CreateArtifactResponse.builder() @@ -1035,6 +1037,9 @@ public VersionMetaData createArtifactVersion(String groupId, String artifactId, typedContent, RuleApplicationType.UPDATE, data.getContent().getReferences(), resolvedReferences); } + + final String owner = securityIdentity.getPrincipal().getName(); + EditableVersionMetaDataDto metaDataDto = EditableVersionMetaDataDto.builder() .description(data.getDescription()).name(data.getName()).labels(data.getLabels()).build(); ContentWrapperDto contentDto = ContentWrapperDto.builder().contentType(ct).content(content) @@ -1042,7 +1047,7 @@ public VersionMetaData createArtifactVersion(String groupId, String artifactId, ArtifactVersionMetaDataDto vmd = storage.createArtifactVersion( new GroupId(groupId).getRawGroupIdWithNull(), artifactId, data.getVersion(), artifactType, - contentDto, metaDataDto, data.getBranches(), isDraft, dryRun != null && dryRun); + contentDto, metaDataDto, data.getBranches(), isDraft, dryRun != null && dryRun, owner); return V3ApiUtil.dtoToVersionMetaData(vmd); } @@ -1289,6 +1294,8 @@ private CreateArtifactResponse updateArtifactInternal(String groupId, String art String artifactType = lookupArtifactType(groupId, artifactId); + final String owner = securityIdentity.getPrincipal().getName(); + // Transform the given references into dtos and set the contentId, this will also detect if any of the // passed references does not exist. final List referencesAsDtos = toReferenceDtos(references); @@ -1307,7 +1314,7 @@ private CreateArtifactResponse updateArtifactInternal(String groupId, String art ContentWrapperDto contentDto = ContentWrapperDto.builder().contentType(contentType).content(content) .references(referencesAsDtos).build(); ArtifactVersionMetaDataDto vmdDto = storage.createArtifactVersion(groupId, artifactId, version, - artifactType, contentDto, metaData, branches, isDraftVersion, false); + artifactType, contentDto, metaData, branches, isDraftVersion, false, owner); VersionMetaData vmd = V3ApiUtil.dtoToVersionMetaData(vmdDto); // Need to also return the artifact metadata diff --git a/app/src/main/java/io/apicurio/registry/storage/RegistryStorage.java b/app/src/main/java/io/apicurio/registry/storage/RegistryStorage.java index 713ed7e25c..a1c95eade7 100644 --- a/app/src/main/java/io/apicurio/registry/storage/RegistryStorage.java +++ b/app/src/main/java/io/apicurio/registry/storage/RegistryStorage.java @@ -112,7 +112,7 @@ public interface RegistryStorage extends DynamicConfigStorage { Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean versionIsDraft, boolean dryRun) + List versionBranches, boolean versionIsDraft, boolean dryRun, String owner) throws ArtifactAlreadyExistsException, RegistryStorageException; /** @@ -190,7 +190,7 @@ ContentWrapperDto getContentByHash(String contentHash) */ ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto content, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) + List branches, boolean isDraft, boolean dryRun, String owner) throws ArtifactNotFoundException, VersionAlreadyExistsException, RegistryStorageException; /** diff --git a/app/src/main/java/io/apicurio/registry/storage/decorator/ReadOnlyRegistryStorageDecorator.java b/app/src/main/java/io/apicurio/registry/storage/decorator/ReadOnlyRegistryStorageDecorator.java index 63f7a3146f..e60c600be5 100644 --- a/app/src/main/java/io/apicurio/registry/storage/decorator/ReadOnlyRegistryStorageDecorator.java +++ b/app/src/main/java/io/apicurio/registry/storage/decorator/ReadOnlyRegistryStorageDecorator.java @@ -76,11 +76,11 @@ public boolean isReadOnly() { public Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean isVersionDraft, boolean dryRun) + List versionBranches, boolean isVersionDraft, boolean dryRun, String owner) throws RegistryStorageException { checkReadOnly(); return delegate.createArtifact(groupId, artifactId, artifactType, artifactMetaData, version, - versionContent, versionMetaData, versionBranches, isVersionDraft, dryRun); + versionContent, versionMetaData, versionBranches, isVersionDraft, dryRun, owner); } @Override @@ -99,10 +99,11 @@ public void deleteArtifacts(String groupId) throws RegistryStorageException { @Override public ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto content, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) throws RegistryStorageException { + List branches, boolean isDraft, boolean dryRun, String owner) + throws RegistryStorageException { checkReadOnly(); return delegate.createArtifactVersion(groupId, artifactId, version, artifactType, content, metaData, - branches, isDraft, dryRun); + branches, isDraft, dryRun, owner); } @Override diff --git a/app/src/main/java/io/apicurio/registry/storage/decorator/RegistryStorageDecoratorBase.java b/app/src/main/java/io/apicurio/registry/storage/decorator/RegistryStorageDecoratorBase.java index c7acfca589..1bcb9a2d55 100644 --- a/app/src/main/java/io/apicurio/registry/storage/decorator/RegistryStorageDecoratorBase.java +++ b/app/src/main/java/io/apicurio/registry/storage/decorator/RegistryStorageDecoratorBase.java @@ -42,10 +42,10 @@ protected RegistryStorageDecoratorBase() { public Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean versionIsDraft, boolean dryRun) + List versionBranches, boolean versionIsDraft, boolean dryRun, String owner) throws RegistryStorageException { return delegate.createArtifact(groupId, artifactId, artifactType, artifactMetaData, version, - versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun); + versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun, owner); } @Override @@ -62,9 +62,10 @@ public void deleteArtifacts(String groupId) throws RegistryStorageException { @Override public ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto content, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) throws RegistryStorageException { + List branches, boolean isDraft, boolean dryRun, String owner) + throws RegistryStorageException { return delegate.createArtifactVersion(groupId, artifactId, version, artifactType, content, metaData, - branches, isDraft, dryRun); + branches, isDraft, dryRun, owner); } @Override diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/gitops/AbstractReadOnlyRegistryStorage.java b/app/src/main/java/io/apicurio/registry/storage/impl/gitops/AbstractReadOnlyRegistryStorage.java index 7247b144ac..a1e22b57eb 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/gitops/AbstractReadOnlyRegistryStorage.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/gitops/AbstractReadOnlyRegistryStorage.java @@ -52,7 +52,7 @@ public boolean isReadOnly() { public Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean versionIsDraft, boolean dryRun) + List versionBranches, boolean versionIsDraft, boolean dryRun, String owner) throws RegistryStorageException { readOnlyViolation(); return null; @@ -61,7 +61,8 @@ public Pair createArtifact(Stri @Override public ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto content, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) throws RegistryStorageException { + List branches, boolean isDraft, boolean dryRun, String owner) + throws RegistryStorageException { readOnlyViolation(); return null; } diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlRegistryStorage.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlRegistryStorage.java index b9c751bd02..09dabd0bc0 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlRegistryStorage.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlRegistryStorage.java @@ -386,15 +386,15 @@ public void deleteConfigProperty(String propertyName) { public Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean versionIsDraft, boolean dryRun) + List versionBranches, boolean versionIsDraft, boolean dryRun, String owner) throws RegistryStorageException { String content = versionContent != null ? versionContent.getContent().content() : null; String contentType = versionContent != null ? versionContent.getContentType() : null; List references = versionContent != null ? versionContent.getReferences() : null; - var message = new CreateArtifact10Message(groupId, artifactId, artifactType, artifactMetaData, + var message = new CreateArtifact11Message(groupId, artifactId, artifactType, artifactMetaData, version, contentType, content, references, versionMetaData, versionBranches, versionIsDraft, - dryRun); + dryRun, owner); var uuid = ConcurrentUtil.get(submitter.submitMessage(message)); Pair createdArtifact = (Pair) coordinator @@ -436,12 +436,13 @@ public void deleteArtifacts(String groupId) throws RegistryStorageException { @Override public ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto contentDto, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) throws RegistryStorageException { + List branches, boolean isDraft, boolean dryRun, String owner) + throws RegistryStorageException { String content = contentDto != null ? contentDto.getContent().content() : null; String contentType = contentDto != null ? contentDto.getContentType() : null; List references = contentDto != null ? contentDto.getReferences() : null; - var message = new CreateArtifactVersion9Message(groupId, artifactId, version, artifactType, - contentType, content, references, metaData, branches, isDraft, dryRun); + var message = new CreateArtifactVersion10Message(groupId, artifactId, version, artifactType, + contentType, content, references, metaData, branches, isDraft, dryRun, owner); var uuid = ConcurrentUtil.get(submitter.submitMessage(message)); ArtifactVersionMetaDataDto versionMetaDataDto = (ArtifactVersionMetaDataDto) coordinator .waitForResponse(uuid); diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact10Message.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact10Message.java index be63137be8..e462930140 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact10Message.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact10Message.java @@ -24,6 +24,7 @@ @Setter @EqualsAndHashCode(callSuper = false) @ToString +@Deprecated public class CreateArtifact10Message extends AbstractMessage { private String groupId; @@ -49,7 +50,7 @@ public Object dispatchTo(RegistryStorage storage) { .contentType(contentType).content(handle).references(references).build() : null; return storage.createArtifact(groupId, artifactId, artifactType, artifactMetaDataDto, version, - versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun); + versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun, null); } } diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact11Message.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact11Message.java new file mode 100644 index 0000000000..634d346f8b --- /dev/null +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact11Message.java @@ -0,0 +1,56 @@ +package io.apicurio.registry.storage.impl.kafkasql.messages; + +import io.apicurio.registry.content.ContentHandle; +import io.apicurio.registry.storage.RegistryStorage; +import io.apicurio.registry.storage.dto.ArtifactReferenceDto; +import io.apicurio.registry.storage.dto.ContentWrapperDto; +import io.apicurio.registry.storage.dto.EditableArtifactMetaDataDto; +import io.apicurio.registry.storage.dto.EditableVersionMetaDataDto; +import io.apicurio.registry.storage.impl.kafkasql.AbstractMessage; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@ToString +public class CreateArtifact11Message extends AbstractMessage { + + private String groupId; + private String artifactId; + private String artifactType; + private EditableArtifactMetaDataDto artifactMetaDataDto; + private String version; + private String contentType; + private String content; + private List references; + private EditableVersionMetaDataDto versionMetaData; + private List versionBranches; + private boolean versionIsDraft; + private boolean dryRun; + private String owner; + + /** + * @see io.apicurio.registry.storage.impl.kafkasql.KafkaSqlMessage#dispatchTo(RegistryStorage) + */ + @Override + public Object dispatchTo(RegistryStorage storage) { + ContentHandle handle = content != null ? ContentHandle.create(content) : null; + ContentWrapperDto versionContent = content != null ? ContentWrapperDto.builder() + .contentType(contentType).content(handle).references(references).build() + : null; + return storage.createArtifact(groupId, artifactId, artifactType, artifactMetaDataDto, version, + versionContent, versionMetaData, versionBranches, versionIsDraft, dryRun, owner); + } + +} diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact9Message.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact9Message.java index e385bf2e61..a25ae7866c 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact9Message.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifact9Message.java @@ -49,7 +49,7 @@ public Object dispatchTo(RegistryStorage storage) { .contentType(contentType).content(handle).references(references).build() : null; return storage.createArtifact(groupId, artifactId, artifactType, artifactMetaDataDto, version, - versionContent, versionMetaData, versionBranches, false, dryRun); + versionContent, versionMetaData, versionBranches, false, dryRun, null); } } diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion10Message.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion10Message.java new file mode 100644 index 0000000000..72e0c6d19b --- /dev/null +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion10Message.java @@ -0,0 +1,54 @@ +package io.apicurio.registry.storage.impl.kafkasql.messages; + +import io.apicurio.registry.content.ContentHandle; +import io.apicurio.registry.storage.RegistryStorage; +import io.apicurio.registry.storage.dto.ArtifactReferenceDto; +import io.apicurio.registry.storage.dto.ContentWrapperDto; +import io.apicurio.registry.storage.dto.EditableVersionMetaDataDto; +import io.apicurio.registry.storage.impl.kafkasql.AbstractMessage; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +@Setter +@EqualsAndHashCode(callSuper = false) +@ToString +public class CreateArtifactVersion10Message extends AbstractMessage { + + private String groupId; + private String artifactId; + private String version; + private String artifactType; + private String contentType; + private String content; + private List references; + private EditableVersionMetaDataDto metaData; + private List branches; + private boolean isDraft; + private boolean dryRun; + private String owner; + + /** + * @see io.apicurio.registry.storage.impl.kafkasql.KafkaSqlMessage#dispatchTo(RegistryStorage) + */ + @Override + public Object dispatchTo(RegistryStorage storage) { + ContentHandle handle = content != null ? ContentHandle.create(content) : null; + ContentWrapperDto contentDto = content != null ? ContentWrapperDto.builder().contentType(contentType) + .content(handle).references(references).build() + : null; + return storage.createArtifactVersion(groupId, artifactId, version, artifactType, contentDto, metaData, + branches, isDraft, dryRun, owner); + } + +} diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion8Message.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion8Message.java index 6b3e9ca73f..fcfbba4d7d 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion8Message.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion8Message.java @@ -47,7 +47,7 @@ public Object dispatchTo(RegistryStorage storage) { .content(handle).references(references).build() : null; return storage.createArtifactVersion(groupId, artifactId, version, artifactType, contentDto, metaData, - branches, false, dryRun); + branches, false, dryRun, null); } } diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion9Message.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion9Message.java index 46bc5b48e1..697af5b63f 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion9Message.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/messages/CreateArtifactVersion9Message.java @@ -23,6 +23,7 @@ @Setter @EqualsAndHashCode(callSuper = false) @ToString +@Deprecated public class CreateArtifactVersion9Message extends AbstractMessage { private String groupId; @@ -47,7 +48,7 @@ public Object dispatchTo(RegistryStorage storage) { .content(handle).references(references).build() : null; return storage.createArtifactVersion(groupId, artifactId, version, artifactType, contentDto, metaData, - branches, isDraft, dryRun); + branches, isDraft, dryRun, null); } } diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/serde/KafkaSqlMessageIndex.java b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/serde/KafkaSqlMessageIndex.java index 33d917c7c6..c03e210189 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/serde/KafkaSqlMessageIndex.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/kafkasql/serde/KafkaSqlMessageIndex.java @@ -1,67 +1,7 @@ package io.apicurio.registry.storage.impl.kafkasql.serde; import io.apicurio.registry.storage.impl.kafkasql.KafkaSqlMessage; -import io.apicurio.registry.storage.impl.kafkasql.messages.AppendVersionToBranch3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ConsumeDownload1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateArtifact10Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateArtifact9Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateArtifactRule4Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateArtifactVersion8Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateArtifactVersion9Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateArtifactVersionComment4Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateBranch4Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateDownload1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateGlobalRule2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateGroup1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateGroupRule3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateRoleMapping3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.CreateSnapshot1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteAllExpiredDownloads0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteAllUserData0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteArtifact2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteArtifactRule3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteArtifactRules2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteArtifactVersion3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteArtifactVersionComment4Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteArtifacts1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteBranch2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteConfigProperty1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteGlobalRule1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteGlobalRules0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteGroup1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteGroupRule2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteGroupRules1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.DeleteRoleMapping1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ExecuteSqlStatement1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportArtifact1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportArtifactRule1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportArtifactVersion1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportBranch1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportComment1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportContent1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportGlobalRule1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportGroup1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ImportGroupRule1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.NextCommentId0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.NextContentId0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.NextGlobalId0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ReplaceBranchVersions3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ResetCommentId0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ResetContentId0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.ResetGlobalId0Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.SetConfigProperty1Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateArtifactMetaData3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateArtifactRule4Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateArtifactVersionComment5Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateArtifactVersionContent5Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateArtifactVersionMetaData4Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateArtifactVersionState5Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateBranchMetaData3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateContentCanonicalHash3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateGlobalRule2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateGroupMetaData2Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateGroupRule3Message; -import io.apicurio.registry.storage.impl.kafkasql.messages.UpdateRoleMapping2Message; +import io.apicurio.registry.storage.impl.kafkasql.messages.*; import jakarta.enterprise.context.ApplicationScoped; import java.util.HashMap; @@ -85,12 +25,12 @@ private static void indexMessageClasses(Class... mcla static { indexMessageClasses(AppendVersionToBranch3Message.class, ConsumeDownload1Message.class, - CreateArtifact9Message.class, CreateArtifact10Message.class, + CreateArtifact9Message.class, CreateArtifact10Message.class, CreateArtifact11Message.class, CreateArtifactVersion8Message.class, CreateArtifactVersion9Message.class, - CreateArtifactRule4Message.class, CreateGroupRule3Message.class, - CreateArtifactVersionComment4Message.class, CreateBranch4Message.class, - CreateDownload1Message.class, CreateGlobalRule2Message.class, CreateGroup1Message.class, - CreateRoleMapping3Message.class, CreateSnapshot1Message.class, + CreateArtifactVersion10Message.class, CreateArtifactRule4Message.class, + CreateGroupRule3Message.class, CreateArtifactVersionComment4Message.class, + CreateBranch4Message.class, CreateDownload1Message.class, CreateGlobalRule2Message.class, + CreateGroup1Message.class, CreateRoleMapping3Message.class, CreateSnapshot1Message.class, DeleteAllExpiredDownloads0Message.class, DeleteAllUserData0Message.class, DeleteArtifact2Message.class, DeleteArtifactRule3Message.class, DeleteArtifactRules2Message.class, DeleteArtifacts1Message.class, diff --git a/app/src/main/java/io/apicurio/registry/storage/impl/sql/AbstractSqlRegistryStorage.java b/app/src/main/java/io/apicurio/registry/storage/impl/sql/AbstractSqlRegistryStorage.java index 06aba595c7..dd9193014d 100644 --- a/app/src/main/java/io/apicurio/registry/storage/impl/sql/AbstractSqlRegistryStorage.java +++ b/app/src/main/java/io/apicurio/registry/storage/impl/sql/AbstractSqlRegistryStorage.java @@ -523,11 +523,10 @@ public List getEnabledArtifactContentIds(String groupId, String artifactId public Pair createArtifact(String groupId, String artifactId, String artifactType, EditableArtifactMetaDataDto artifactMetaData, String version, ContentWrapperDto versionContent, EditableVersionMetaDataDto versionMetaData, - List versionBranches, boolean versionIsDraft, boolean dryRun) + List versionBranches, boolean versionIsDraft, boolean dryRun, String owner) throws RegistryStorageException { log.debug("Inserting an artifact row for: {} {}", groupId, artifactId); - String owner = securityIdentity.getPrincipal().getName(); Date createdOn = new Date(); EditableArtifactMetaDataDto amd = artifactMetaData == null @@ -888,11 +887,10 @@ public void deleteArtifacts(String groupId) throws RegistryStorageException { @Override public ArtifactVersionMetaDataDto createArtifactVersion(String groupId, String artifactId, String version, String artifactType, ContentWrapperDto content, EditableVersionMetaDataDto metaData, - List branches, boolean isDraft, boolean dryRun) + List branches, boolean isDraft, boolean dryRun, String owner) throws VersionAlreadyExistsException, RegistryStorageException { log.debug("Creating new artifact version for {} {} (version {}).", groupId, artifactId, version); - String owner = securityIdentity.getPrincipal().getName(); Date createdOn = new Date(); // Put the content in the DB and get the unique content ID back. diff --git a/app/src/test/java/io/apicurio/registry/noprofile/storage/AbstractRegistryStorageTest.java b/app/src/test/java/io/apicurio/registry/noprofile/storage/AbstractRegistryStorageTest.java index b08a9ae0ab..1461f629e8 100644 --- a/app/src/test/java/io/apicurio/registry/noprofile/storage/AbstractRegistryStorageTest.java +++ b/app/src/test/java/io/apicurio/registry/noprofile/storage/AbstractRegistryStorageTest.java @@ -63,12 +63,10 @@ public void testGetArtifactIds() throws Exception { for (int idx = 1; idx <= 10; idx++) { String artifactId = artifactIdPrefix + idx; ContentHandle content = ContentHandle.create(OPENAPI_CONTENT); - ArtifactVersionMetaDataDto dto = storage() - .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, - ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) - .content(content).build(), - null, Collections.emptyList(), false, false) - .getValue(); + ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, + ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder() + .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), + null, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -96,7 +94,7 @@ public void testCreateArtifact() throws Exception { ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, artifactMetaDataDto, null, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), - versionMetaDataDto, Collections.emptyList(), false, false).getValue(); + versionMetaDataDto, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -154,12 +152,10 @@ public void testCreateArtifactWithMetaData() throws Exception { EditableArtifactMetaDataDto artifactMetaDataDto = new EditableArtifactMetaDataDto("NAME", "DESCRIPTION", null, Collections.singletonMap("KEY", "VALUE")); - ArtifactVersionMetaDataDto dto = storage() - .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, artifactMetaDataDto, null, - ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) - .content(content).build(), - metaData, Collections.emptyList(), false, false) - .getValue(); + ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, + artifactMetaDataDto, null, ContentWrapperDto.builder() + .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), + metaData, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -194,12 +190,10 @@ public void testCreateArtifactWithLargeMetaData() throws Exception { metaData.setDescription(generateString(2000)); metaData.setLabels(new HashMap<>()); metaData.getLabels().put("key-" + generateString(300), "value-" + generateString(2000)); - ArtifactVersionMetaDataDto dto = storage() - .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, - ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) - .content(content).build(), - metaData, Collections.emptyList(), false, false) - .getValue(); + ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, + null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) + .content(content).build(), + metaData, Collections.emptyList(), false, false, null).getValue(); dto = storage().getArtifactVersionMetaData(dto.getGlobalId()); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -219,18 +213,16 @@ public void testCreateDuplicateArtifact() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); // Should throw error for duplicate artifact. Assertions.assertThrows(ArtifactAlreadyExistsException.class, () -> { - storage() - .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, - ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) - .content(content).build(), - null, Collections.emptyList(), false, false) - .getValue(); + storage().createArtifact( + GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder() + .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), + null, Collections.emptyList(), false, false, null).getValue(); }); } @@ -264,7 +256,7 @@ public void testCreateArtifactVersion() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -279,7 +271,7 @@ public void testCreateArtifactVersion() throws Exception { ArtifactVersionMetaDataDto dtov2 = storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtov2); Assertions.assertEquals(GROUP_ID, dtov2.getGroupId()); Assertions.assertEquals(artifactId, dtov2.getArtifactId()); @@ -299,7 +291,7 @@ public void testGetArtifactVersions() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -327,7 +319,7 @@ public void testGetArtifactVersions() throws Exception { ArtifactVersionMetaDataDto dtov2 = storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtov2); Assertions.assertEquals(GROUP_ID, dtov2.getGroupId()); Assertions.assertEquals(artifactId, dtov2.getArtifactId()); @@ -386,7 +378,7 @@ public void testCreateArtifactVersionWithMetaData() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -403,7 +395,7 @@ public void testCreateArtifactVersionWithMetaData() throws Exception { ArtifactVersionMetaDataDto dtov2 = storage().createArtifactVersion( GROUP_ID, artifactId, "2", ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), - metaData, Collections.emptyList(), false, false); + metaData, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtov2); Assertions.assertEquals(GROUP_ID, dtov2.getGroupId()); Assertions.assertEquals(artifactId, dtov2.getArtifactId()); @@ -432,7 +424,7 @@ public void testGetArtifactMetaDataByGlobalId() throws Exception { ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - versionMetaDataDto, Collections.emptyList(), false, false).getValue(); + versionMetaDataDto, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -462,7 +454,7 @@ public void testUpdateArtifactMetaData() throws Exception { ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - versionMetaDataDto, Collections.emptyList(), false, false).getValue(); + versionMetaDataDto, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -494,7 +486,7 @@ public void testUpdateArtifactVersionState() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); @@ -502,7 +494,7 @@ public void testUpdateArtifactVersionState() throws Exception { ArtifactVersionMetaDataDto dtov2 = storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); ; Assertions.assertNotNull(dtov2); Assertions.assertEquals(GROUP_ID, dtov2.getGroupId()); @@ -529,7 +521,7 @@ public void testUpdateArtifactVersionMetaData() throws Exception { ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - versionMetaDataDto, Collections.emptyList(), false, false).getValue(); + versionMetaDataDto, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -561,7 +553,7 @@ public void testDeleteArtifact() throws Exception { ArtifactVersionMetaDataDto dto = storage().createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - versionMetaDataDto, Collections.emptyList(), false, false).getValue(); + versionMetaDataDto, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); Assertions.assertEquals(artifactId, dto.getArtifactId()); @@ -598,7 +590,7 @@ public void testDeleteArtifactVersion() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals("1", dto.getVersion()); @@ -624,7 +616,7 @@ public void testDeleteArtifactVersion() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals("1", dto.getVersion()); @@ -633,7 +625,7 @@ public void testDeleteArtifactVersion() throws Exception { ArtifactVersionMetaDataDto dtov2 = storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtov2); Assertions.assertEquals("2", dtov2.getVersion()); @@ -654,7 +646,7 @@ public void testDeleteArtifactVersion() throws Exception { ArtifactVersionMetaDataDto dtov3 = storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtov3); Assertions.assertEquals("3", dtov3.getVersion()); @@ -673,12 +665,10 @@ public void testDeleteArtifactVersion() throws Exception { // Delete the latest version artifactId = "testDeleteArtifactVersion-3"; content = ContentHandle.create(OPENAPI_CONTENT); - dto = storage() - .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, - ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) - .content(contentv2).build(), - null, Collections.emptyList(), false, false) - .getValue(); + dto = storage().createArtifact( + GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder() + .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), + null, Collections.emptyList(), false, false, null).getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals("1", dto.getVersion()); @@ -687,7 +677,7 @@ public void testDeleteArtifactVersion() throws Exception { dtov2 = storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(contentv2).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtov2); final String aid3 = artifactId; @@ -730,7 +720,7 @@ public void testCreateArtifactRule() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -758,7 +748,7 @@ public void testUpdateArtifactRule() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -787,7 +777,7 @@ public void testDeleteArtifactRule() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -815,7 +805,7 @@ public void testDeleteAllArtifactRules() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -941,12 +931,10 @@ public void testSearchArtifacts() throws Exception { Map labels = Collections.singletonMap("key", "value-" + idx); EditableArtifactMetaDataDto metaData = new EditableArtifactMetaDataDto(artifactId + "-name", artifactId + "-description", null, labels); - storage() - .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, metaData, null, - ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) - .content(content).build(), - null, Collections.emptyList(), false, false) - .getValue(); + storage().createArtifact( + GROUP_ID, artifactId, ArtifactType.OPENAPI, metaData, null, ContentWrapperDto.builder() + .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), + null, Collections.emptyList(), false, false, null).getValue(); } @@ -1002,7 +990,7 @@ public void testSearchVersions() throws Exception { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -1016,7 +1004,7 @@ public void testSearchVersions() throws Exception { storage().createArtifactVersion( GROUP_ID, artifactId, null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), - metaData, Collections.emptyList(), false, false); + metaData, Collections.emptyList(), false, false, null); } @@ -1051,7 +1039,7 @@ private void createSomeUserData() { .createArtifact(group1, artifactId1, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); storage().createArtifactRule(group1, artifactId1, RuleType.VALIDITY, RuleConfigurationDto.builder().configuration("FULL").build()); @@ -1060,7 +1048,7 @@ private void createSomeUserData() { EditableArtifactMetaDataDto.builder().name("test").build(), null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); storage().createGlobalRule(RuleType.VALIDITY, @@ -1151,7 +1139,7 @@ public void testComments() { .createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dto); Assertions.assertEquals(GROUP_ID, dto.getGroupId()); @@ -1194,7 +1182,7 @@ public void testBranches() { .createArtifact(GROUP_ID, ga.getRawArtifactId(), ArtifactType.OPENAPI, null, null, ContentWrapperDto.builder().contentType(ContentTypes.APPLICATION_JSON) .content(content).build(), - null, Collections.emptyList(), false, false) + null, Collections.emptyList(), false, false, null) .getValue(); Assertions.assertNotNull(dtoV1); @@ -1223,7 +1211,7 @@ public void testBranches() { var dtoV2 = storage().createArtifactVersion(ga.getRawGroupIdWithDefaultString(), ga.getRawArtifactId(), null, ArtifactType.OPENAPI, ContentWrapperDto.builder() .contentType(ContentTypes.APPLICATION_JSON).content(content).build(), - null, Collections.emptyList(), false, false); + null, Collections.emptyList(), false, false, null); Assertions.assertNotNull(dtoV2); Assertions.assertEquals(ga.getRawGroupIdWithDefaultString(), dtoV2.getGroupId()); Assertions.assertEquals(ga.getRawArtifactId(), dtoV2.getArtifactId()); diff --git a/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStoragePerformanceTest.java b/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStoragePerformanceTest.java index f95fef6f85..75a3c8fb51 100644 --- a/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStoragePerformanceTest.java +++ b/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStoragePerformanceTest.java @@ -74,7 +74,7 @@ public void testStoragePerformance() throws Exception { EditableVersionMetaDataDto versionMetaData = EditableVersionMetaDataDto.builder().name(title) .description(description).build(); storage.createArtifact(GROUP_ID, artifactId, ArtifactType.OPENAPI, metaData, null, versionContent, - versionMetaData, List.of(), false, false); + versionMetaData, List.of(), false, false, null); System.out.print("."); if (idx % 100 == 0) { diff --git a/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStorageSmokeTest.java b/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStorageSmokeTest.java index ce378fb540..cd037543cc 100644 --- a/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStorageSmokeTest.java +++ b/app/src/test/java/io/apicurio/registry/noprofile/storage/RegistryStorageSmokeTest.java @@ -92,11 +92,11 @@ public void testArtifactsAndMeta() throws Exception { EditableVersionMetaDataDto versionMetaData1 = EditableVersionMetaDataDto.builder().build(); ArtifactVersionMetaDataDto vmdDto1_1 = getStorage() .createArtifact(GROUP_ID, artifactId1, ArtifactType.JSON, artifactMetaData1, null, - versionContent1, versionMetaData1, List.of(), false, false) + versionContent1, versionMetaData1, List.of(), false, false, null) .getRight(); // Create version 2 (for artifact 1) ArtifactVersionMetaDataDto vmdDto1_2 = getStorage().createArtifactVersion(GROUP_ID, artifactId1, null, - ArtifactType.JSON, versionContent1, versionMetaData1, List.of(), false, false); + ArtifactType.JSON, versionContent1, versionMetaData1, List.of(), false, false, null); // Create artifact 2 EditableArtifactMetaDataDto artifactMetaData2 = EditableArtifactMetaDataDto.builder().build(); @@ -104,7 +104,7 @@ public void testArtifactsAndMeta() throws Exception { .content(ContentHandle.create("content2")).contentType(ContentTypes.APPLICATION_JSON).build(); EditableVersionMetaDataDto versionMetaData2 = EditableVersionMetaDataDto.builder().build(); getStorage().createArtifact(GROUP_ID, artifactId2, ArtifactType.AVRO, artifactMetaData2, null, - versionContent2, versionMetaData2, List.of(), false, false).getRight(); + versionContent2, versionMetaData2, List.of(), false, false, null).getRight(); assertEquals(size + 2, getStorage().getArtifactIds(null).size()); assertTrue(getStorage().getArtifactIds(null).contains(artifactId1)); @@ -166,7 +166,7 @@ public void testRules() throws Exception { .content(ContentHandle.create("content1")).contentType(ContentTypes.APPLICATION_JSON).build(); EditableVersionMetaDataDto versionMetaData = EditableVersionMetaDataDto.builder().build(); getStorage().createArtifact(GROUP_ID, artifactId, ArtifactType.JSON, artifactMetaData, null, - versionContent1, versionMetaData, List.of(), false, false).getRight(); + versionContent1, versionMetaData, List.of(), false, false, null).getRight(); assertEquals(0, getStorage().getArtifactRules(GROUP_ID, artifactId).size()); assertEquals(0, getStorage().getGlobalRules().size()); @@ -200,15 +200,15 @@ public void testLimitGetArtifactIds() throws Exception { .contentType(ContentTypes.APPLICATION_JSON).build(); getStorage().createArtifact(GROUP_ID, testId0, ArtifactType.JSON, null, null, content, null, - List.of(), false, false); + List.of(), false, false, null); int size = getStorage().getArtifactIds(null).size(); // Create 2 artifacts getStorage().createArtifact(GROUP_ID, testId1, ArtifactType.JSON, null, null, content, null, - List.of(), false, false); + List.of(), false, false, null); getStorage().createArtifact(GROUP_ID, testId2, ArtifactType.JSON, null, null, content, null, - List.of(), false, false); + List.of(), false, false, null); int newSize = getStorage().getArtifactIds(null).size(); int limitedSize = getStorage().getArtifactIds(1).size(); diff --git a/app/src/test/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlAuthTest.java b/app/src/test/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlAuthTest.java new file mode 100644 index 0000000000..a42e7f7f18 --- /dev/null +++ b/app/src/test/java/io/apicurio/registry/storage/impl/kafkasql/KafkaSqlAuthTest.java @@ -0,0 +1,17 @@ +package io.apicurio.registry.storage.impl.kafkasql; + +import io.apicurio.registry.auth.SimpleAuthTest; +import io.apicurio.registry.utils.tests.ApicurioTestTags; +import io.apicurio.registry.utils.tests.KafkasqlAuthTestProfile; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import jakarta.enterprise.inject.Typed; +import org.junit.jupiter.api.Tag; + +@QuarkusTest +@TestProfile(KafkasqlAuthTestProfile.class) +@Tag(ApicurioTestTags.SLOW) +@Typed(KafkaSqlAuthTest.class) +public class KafkaSqlAuthTest extends SimpleAuthTest { + +} diff --git a/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java b/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java index 31839057a7..2a10017b13 100644 --- a/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java +++ b/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java @@ -45,8 +45,10 @@ public class ReadOnlyRegistryStorageTest { new State(false, s -> s.countActiveArtifactVersions(null, null))), entry("countTotalArtifactVersions0", new State(false, RegistryStorage::countTotalArtifactVersions)), - entry("createArtifact10", new State(true, - s -> s.createArtifact(null, null, null, null, null, null, null, null, false, false))), + entry("createArtifact10", + new State(true, + s -> s.createArtifact(null, null, null, null, null, null, null, null, false, + false, null))), entry("createArtifactRule4", new State(true, s -> s.createArtifactRule(null, null, null, null))), entry("createArtifactVersionComment4", @@ -54,7 +56,7 @@ public class ReadOnlyRegistryStorageTest { entry("createArtifactVersion9", new State(true, s -> s.createArtifactVersion(null, null, null, null, null, null, null, false, - false))), + false, null))), entry("createBranch4", new State(true, s -> s.createBranch(null, null, null, null))), entry("createDownload1", new State(true, s -> s.createDownload(null))), entry("createGlobalRule2", new State(true, s -> s.createGlobalRule(null, null))), diff --git a/examples/tools/kafka-compose/kafka-ingress.yaml b/examples/tools/kafka-compose/kafka-ingress.yaml new file mode 100644 index 0000000000..1d153a08da --- /dev/null +++ b/examples/tools/kafka-compose/kafka-ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: kafka-ingress + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "false" +spec: + rules: + - host: kafka.local + http: + paths: + - path: / + pathType: ImplementationSpecific + backend: + service: + name: kafka + port: + number: 9092 diff --git a/examples/tools/kafka-compose/kafka.yaml b/examples/tools/kafka-compose/kafka.yaml new file mode 100644 index 0000000000..aff9eb4b18 --- /dev/null +++ b/examples/tools/kafka-compose/kafka.yaml @@ -0,0 +1,86 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: kafka-config + namespace: default +data: + server.properties: | + process.roles=broker,controller + node.id=1 + controller.quorum.voters=1@localhost:9093 + listeners=PLAINTEXT://0.0.0.0:9092,DOCKER://0.0.0.0:9094,CONTROLLER://0.0.0.0:9093 + advertised.listeners=PLAINTEXT://127.0.0.1:9092,DOCKER://kafka.local:9094 + controller.listener.names=CONTROLLER + listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT,DOCKER:PLAINTEXT + inter.broker.listener.name=PLAINTEXT + log.dirs=/tmp/kafka-logs + num.network.threads=3 + num.io.threads=8 + log.retention.hours=168 + log.segment.bytes=1073741824 + log.retention.check.interval.ms=300000 + offsets.topic.replication.factor=1 + transaction.state.log.replication.factor=1 + transaction.state.log.min.isr=1 + group.initial.rebalance.delay.ms=0 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kafka + namespace: default + labels: + app: kafka +spec: + replicas: 1 + selector: + matchLabels: + app: kafka + template: + metadata: + labels: + app: kafka + spec: + containers: + - name: kafka + image: quay.io/strimzi/kafka:latest-kafka-3.5.0 + command: + - /bin/sh + - -c + - | + export CLUSTER_ID=$(bin/kafka-storage.sh random-uuid) && \ + bin/kafka-storage.sh format -t $CLUSTER_ID -c /config/server.properties && \ + bin/kafka-server-start.sh /config/server.properties + env: + - name: LOG_DIR + value: /tmp/logs + volumeMounts: + - name: kafka-config + mountPath: /config + - name: kafka-data + mountPath: /tmp/kafka-logs + ports: + - containerPort: 9092 + - containerPort: 9093 + volumes: + - name: kafka-config + configMap: + name: kafka-config + - name: kafka-data + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: kafka + namespace: default +spec: + type: LoadBalancer + selector: + app: kafka + ports: + - name: kafka + protocol: TCP + port: 9092 + targetPort: 9092 + diff --git a/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java b/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java index 8602405986..0b181dc1ce 100644 --- a/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java +++ b/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java @@ -1,13 +1,17 @@ package io.apicurio.tests.auth; +import io.apicurio.registry.client.auth.VertXAuthFactory; import io.apicurio.registry.rest.client.RegistryClient; +import io.apicurio.registry.rest.client.models.ArtifactMetaData; import io.apicurio.registry.rest.client.models.CreateArtifact; import io.apicurio.registry.rest.client.models.CreateRule; import io.apicurio.registry.rest.client.models.CreateVersion; +import io.apicurio.registry.rest.client.models.EditableArtifactMetaData; import io.apicurio.registry.rest.client.models.RuleType; import io.apicurio.registry.rest.client.models.UserInfo; import io.apicurio.registry.rest.client.models.VersionContent; import io.apicurio.registry.rest.client.models.VersionMetaData; +import io.apicurio.registry.rules.compatibility.CompatibilityLevel; import io.apicurio.registry.rules.validity.ValidityLevel; import io.apicurio.registry.types.ArtifactType; import io.apicurio.registry.types.ContentTypes; @@ -26,7 +30,9 @@ import org.junit.jupiter.api.Test; import static io.apicurio.registry.client.auth.VertXAuthFactory.buildOIDCWebClient; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; @Tag(Constants.AUTH) @TestProfile(AuthTestProfile.class) @@ -189,6 +195,172 @@ public void testAdminRole() throws Exception { } } + @Test + public void testOwnerOnlyAuthorization() throws Exception { + var devAdapter = new VertXRequestAdapter(VertXAuthFactory.buildOIDCWebClient(vertx, + authServerUrlConfigured, JWKSMockServer.DEVELOPER_CLIENT_ID, "test1")); + devAdapter.setBaseUrl(getRegistryV3ApiUrl()); + RegistryClient clientDev = new RegistryClient(devAdapter); + + var adminAdapter = new VertXRequestAdapter(VertXAuthFactory.buildOIDCWebClient(vertx, + authServerUrlConfigured, JWKSMockServer.ADMIN_CLIENT_ID, "test1")); + adminAdapter.setBaseUrl(getRegistryV3ApiUrl()); + RegistryClient clientAdmin = new RegistryClient(adminAdapter); + + // Admin user will create an artifact + String artifactId = TestUtils.generateArtifactId(); + createArtifact.setArtifactId(artifactId); + clientAdmin.groups().byGroupId(groupId).artifacts().post(createArtifact); + + EditableArtifactMetaData updatedMetaData = new EditableArtifactMetaData(); + updatedMetaData.setName("Updated Name"); + // Dev user cannot edit the same artifact because Dev user is not the owner + var exception1 = Assertions.assertThrows(Exception.class, () -> { + clientDev.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).put(updatedMetaData); + }); + assertForbidden(exception1); + + // But the admin user CAN make the change. + clientAdmin.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).put(updatedMetaData); + + // Now the Dev user will create an artifact + String artifactId2 = TestUtils.generateArtifactId(); + createArtifact.setArtifactId(artifactId2); + clientDev.groups().byGroupId(groupId).artifacts().post(createArtifact); + + // And the Admin user will modify it (allowed because it's the Admin user) + CreateRule createRule = new CreateRule(); + createRule.setRuleType(RuleType.COMPATIBILITY); + createRule.setConfig(CompatibilityLevel.BACKWARD.name()); + clientAdmin.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId2).rules() + .post(createRule); + } + + @Test + public void testGetArtifactOwner() throws Exception { + var adapter = new VertXRequestAdapter(VertXAuthFactory.buildOIDCWebClient(vertx, + authServerUrlConfigured, JWKSMockServer.DEVELOPER_CLIENT_ID, "test1")); + adapter.setBaseUrl(getRegistryV3ApiUrl()); + RegistryClient client = new RegistryClient(adapter); + + // Preparation + final String groupId = "testGetArtifactOwner"; + final String artifactId = generateArtifactId(); + final String version = "1"; + + // Execution + createArtifact.setArtifactId(artifactId); + final VersionMetaData created = client.groups().byGroupId(groupId).artifacts().post(createArtifact) + .getVersion(); + + // Assertions + assertNotNull(created); + assertEquals(groupId, created.getGroupId()); + assertEquals(artifactId, created.getArtifactId()); + assertEquals(version, created.getVersion()); + assertEquals("developer-client", created.getOwner()); + + // Get the artifact owner via the REST API and verify it + ArtifactMetaData amd = client.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).get(); + assertEquals("developer-client", amd.getOwner()); + } + + @Test + public void testUpdateArtifactOwner() throws Exception { + var adapter = new VertXRequestAdapter(VertXAuthFactory.buildOIDCWebClient(vertx, + authServerUrlConfigured, JWKSMockServer.DEVELOPER_CLIENT_ID, "test1")); + adapter.setBaseUrl(getRegistryV3ApiUrl()); + RegistryClient client = new RegistryClient(adapter); + + // Preparation + final String groupId = "testUpdateArtifactOwner"; + final String artifactId = generateArtifactId(); + + final String version = "1.0"; + final String name = "testUpdateArtifactOwnerName"; + final String description = "testUpdateArtifactOwnerDescription"; + + // Execution + createArtifact.setArtifactId(artifactId); + createArtifact.getFirstVersion().setVersion(version); + createArtifact.getFirstVersion().setName(name); + createArtifact.getFirstVersion().setDescription(description); + final VersionMetaData created = client.groups().byGroupId(groupId).artifacts().post(createArtifact) + .getVersion(); + + // Assertions + assertNotNull(created); + assertEquals(groupId, created.getGroupId()); + assertEquals(artifactId, created.getArtifactId()); + assertEquals(version, created.getVersion()); + assertEquals("developer-client", created.getOwner()); + + // Get the artifact owner via the REST API and verify it + ArtifactMetaData amd = client.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).get(); + assertEquals("developer-client", amd.getOwner()); + + // Update the owner + EditableArtifactMetaData eamd = new EditableArtifactMetaData(); + eamd.setOwner("developer-2-client"); + client.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).put(eamd); + + // Check that the update worked + amd = client.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).get(); + assertEquals("developer-2-client", amd.getOwner()); + } + + @Test + public void testUpdateArtifactOwnerOnlyByOwner() throws Exception { + var adapter_dev1 = new VertXRequestAdapter(VertXAuthFactory.buildOIDCWebClient(vertx, + authServerUrlConfigured, JWKSMockServer.DEVELOPER_CLIENT_ID, "test1")); + adapter_dev1.setBaseUrl(getRegistryV3ApiUrl()); + RegistryClient client_dev1 = new RegistryClient(adapter_dev1); + var adapter_dev2 = new VertXRequestAdapter(VertXAuthFactory.buildOIDCWebClient(vertx, + authServerUrlConfigured, JWKSMockServer.DEVELOPER_2_CLIENT_ID, "test1")); + adapter_dev2.setBaseUrl(getRegistryV3ApiUrl()); + RegistryClient client_dev2 = new RegistryClient(adapter_dev2); + + // Preparation + final String groupId = "testUpdateArtifactOwnerOnlyByOwner"; + final String artifactId = generateArtifactId(); + + final String version = "1.0"; + final String name = "testUpdateArtifactOwnerOnlyByOwnerName"; + final String description = "testUpdateArtifactOwnerOnlyByOwnerDescription"; + + // Execution + createArtifact.setArtifactId(artifactId); + createArtifact.getFirstVersion().setVersion(version); + createArtifact.getFirstVersion().setName(name); + createArtifact.getFirstVersion().setDescription(description); + final VersionMetaData created = client_dev1.groups().byGroupId(groupId).artifacts() + .post(createArtifact).getVersion(); + + // Assertions + assertNotNull(created); + assertEquals(groupId, created.getGroupId()); + assertEquals(artifactId, created.getArtifactId()); + assertEquals(version, created.getVersion()); + assertEquals("developer-client", created.getOwner()); + + // Get the artifact owner via the REST API and verify it + ArtifactMetaData amd = client_dev1.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId) + .get(); + assertEquals("developer-client", amd.getOwner()); + + // Try to update the owner by dev2 (should fail) + var exception1 = assertThrows(Exception.class, () -> { + EditableArtifactMetaData eamd = new EditableArtifactMetaData(); + eamd.setOwner("developer-2-client"); + client_dev2.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).put(eamd); + }); + assertForbidden(exception1); + + // Should still be the original owner + amd = client_dev1.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId).get(); + assertEquals("developer-client", amd.getOwner()); + } + protected void assertArtifactNotFound(Exception exception) { Assertions.assertEquals(io.apicurio.registry.rest.client.models.ProblemDetails.class, exception.getClass()); diff --git a/utils/tests/src/main/java/io/apicurio/registry/utils/tests/KafkasqlAuthTestProfile.java b/utils/tests/src/main/java/io/apicurio/registry/utils/tests/KafkasqlAuthTestProfile.java new file mode 100644 index 0000000000..65523b4750 --- /dev/null +++ b/utils/tests/src/main/java/io/apicurio/registry/utils/tests/KafkasqlAuthTestProfile.java @@ -0,0 +1,29 @@ +package io.apicurio.registry.utils.tests; + +import io.quarkus.test.junit.QuarkusTestProfile; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class KafkasqlAuthTestProfile implements QuarkusTestProfile { + + @Override + public Map getConfigOverrides() { + return Map.of("apicurio.storage.kind", "kafkasql", "apicurio.rest.deletion.group.enabled", "true", + "apicurio.rest.deletion.artifact.enabled", "true", + "apicurio.rest.deletion.artifact-version.enabled", "true", "smallrye.jwt.sign.key.location", + "privateKey.jwk"); + } + + @Override + public List testResources() { + if (!Boolean.parseBoolean(System.getProperty("cluster.tests"))) { + return List.of(new TestResourceEntry(KafkaTestContainerManager.class), + new TestResourceEntry(JWKSMockServer.class)); + } else { + return Collections.emptyList(); + } + } + +} From bd4e6b58beab697b771034367cfcad632afd21d5 Mon Sep 17 00:00:00 2001 From: Carles Arnal Date: Thu, 19 Dec 2024 09:30:10 +0100 Subject: [PATCH 2/3] Fix scope --- .../apicurio/registry/client/auth/VertXAuthFactory.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java b/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java index e91bbbd251..95e019524f 100644 --- a/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java +++ b/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java @@ -27,11 +27,14 @@ public static WebClient buildOIDCWebClient(Vertx vertx, String tokenUrl, String String clientSecret, String scope) { WebClient webClient = WebClient.create(vertx); - OAuth2Auth oAuth2Options = OAuth2Auth.create(vertx, new OAuth2Options().setFlow(OAuth2FlowType.CLIENT) - .setClientId(clientId).setClientSecret(clientSecret).setTokenPath(tokenUrl)); + OAuth2Auth oAuth2Options = OAuth2Auth.create(vertx, new OAuth2Options() + .setFlow(OAuth2FlowType.CLIENT) + .setClientId(clientId) + .setClientSecret(clientSecret) + .setTokenPath(tokenUrl)); Oauth2Credentials oauth2Credentials = new Oauth2Credentials(); - + oauth2Credentials.addScope(scope); OAuth2WebClient oauth2WebClient = OAuth2WebClient.create(webClient, oAuth2Options); oauth2WebClient.withCredentials(oauth2Credentials); From a9deb03ad78dfb1932041660eb3c87f01d628147 Mon Sep 17 00:00:00 2001 From: Carles Arnal Date: Thu, 19 Dec 2024 13:59:08 +0100 Subject: [PATCH 3/3] Fix owner only updates --- .../registry/rest/v2/GroupsResourceImpl.java | 3 ++- .../registry/rest/v3/GroupsResourceImpl.java | 3 ++- .../registry/auth/SimpleAuthTest.java | 22 +++++++++++-------- .../readonly/ReadOnlyRegistryStorageTest.java | 4 ++-- .../tests/ApicurioRegistryBaseIT.java | 1 - .../io/apicurio/tests/auth/SimpleAuthIT.java | 22 +++++++++++-------- .../client/auth/VertXAuthFactory.java | 11 +++++----- 7 files changed, 37 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java b/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java index 021dbeb4e8..634230f276 100644 --- a/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java +++ b/app/src/main/java/io/apicurio/registry/rest/v2/GroupsResourceImpl.java @@ -1371,7 +1371,8 @@ private ArtifactMetaData handleIfExistsReturnOrUpdate(String groupId, String art content, contentType, references); } - private ArtifactMetaData updateArtifactInternal(String groupId, String artifactId, String version, + @Authorized(style = AuthorizedStyle.GroupAndArtifact, level = AuthorizedLevel.Write) + protected ArtifactMetaData updateArtifactInternal(String groupId, String artifactId, String version, String name, String description, ContentHandle content, String contentType, List references) { diff --git a/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java b/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java index 164c59cda5..efa20cb51f 100644 --- a/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java +++ b/app/src/main/java/io/apicurio/registry/rest/v3/GroupsResourceImpl.java @@ -1280,7 +1280,8 @@ private CreateArtifactResponse handleIfExistsReturnOrUpdate(String groupId, Stri return updateArtifactInternal(groupId, artifactId, theVersion); } - private CreateArtifactResponse updateArtifactInternal(String groupId, String artifactId, + @Authorized(style = AuthorizedStyle.GroupAndArtifact, level = AuthorizedLevel.Write) + protected CreateArtifactResponse updateArtifactInternal(String groupId, String artifactId, CreateVersion theVersion) { String version = theVersion.getVersion(); String name = theVersion.getName(); diff --git a/app/src/test/java/io/apicurio/registry/auth/SimpleAuthTest.java b/app/src/test/java/io/apicurio/registry/auth/SimpleAuthTest.java index 471ad430e6..f20a071926 100644 --- a/app/src/test/java/io/apicurio/registry/auth/SimpleAuthTest.java +++ b/app/src/test/java/io/apicurio/registry/auth/SimpleAuthTest.java @@ -4,15 +4,7 @@ import io.apicurio.registry.AbstractResourceTestBase; import io.apicurio.registry.client.auth.VertXAuthFactory; import io.apicurio.registry.rest.client.RegistryClient; -import io.apicurio.registry.rest.client.models.ArtifactMetaData; -import io.apicurio.registry.rest.client.models.CreateArtifact; -import io.apicurio.registry.rest.client.models.CreateRule; -import io.apicurio.registry.rest.client.models.CreateVersion; -import io.apicurio.registry.rest.client.models.EditableArtifactMetaData; -import io.apicurio.registry.rest.client.models.RuleType; -import io.apicurio.registry.rest.client.models.UserInfo; -import io.apicurio.registry.rest.client.models.VersionContent; -import io.apicurio.registry.rest.client.models.VersionMetaData; +import io.apicurio.registry.rest.client.models.*; import io.apicurio.registry.rules.compatibility.CompatibilityLevel; import io.apicurio.registry.rules.validity.ValidityLevel; import io.apicurio.registry.types.ArtifactType; @@ -310,6 +302,18 @@ public void testOwnerOnlyAuthorization() throws Exception { createRule.setConfig(CompatibilityLevel.BACKWARD.name()); clientAdmin.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId2).rules() .post(createRule); + + // Admin user will create an artifact + String artifactId1 = TestUtils.generateArtifactId(); + createArtifact.setArtifactId(artifactId1); + clientAdmin.groups().byGroupId(groupId).artifacts().post(createArtifact); + + // Dev user cannot update with ifExists the same artifact because Dev user is not the owner + Assertions.assertThrows(Exception.class, () -> { + clientDev.groups().byGroupId(groupId).artifacts().post(createArtifact, config -> { + config.queryParameters.ifExists = IfArtifactExists.CREATE_VERSION; + }); + }); } @Test diff --git a/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java b/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java index 2a10017b13..4153cdcabe 100644 --- a/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java +++ b/app/src/test/java/io/apicurio/registry/storage/impl/readonly/ReadOnlyRegistryStorageTest.java @@ -45,7 +45,7 @@ public class ReadOnlyRegistryStorageTest { new State(false, s -> s.countActiveArtifactVersions(null, null))), entry("countTotalArtifactVersions0", new State(false, RegistryStorage::countTotalArtifactVersions)), - entry("createArtifact10", + entry("createArtifact11", new State(true, s -> s.createArtifact(null, null, null, null, null, null, null, null, false, false, null))), @@ -53,7 +53,7 @@ public class ReadOnlyRegistryStorageTest { new State(true, s -> s.createArtifactRule(null, null, null, null))), entry("createArtifactVersionComment4", new State(true, s -> s.createArtifactVersionComment(null, null, null, null))), - entry("createArtifactVersion9", + entry("createArtifactVersion10", new State(true, s -> s.createArtifactVersion(null, null, null, null, null, null, null, false, false, null))), diff --git a/integration-tests/src/test/java/io/apicurio/tests/ApicurioRegistryBaseIT.java b/integration-tests/src/test/java/io/apicurio/tests/ApicurioRegistryBaseIT.java index a176ca890e..483b0a5285 100644 --- a/integration-tests/src/test/java/io/apicurio/tests/ApicurioRegistryBaseIT.java +++ b/integration-tests/src/test/java/io/apicurio/tests/ApicurioRegistryBaseIT.java @@ -609,7 +609,6 @@ protected void assertNotAuthorized(Exception exception) { } protected void assertForbidden(Exception exception) { - assertNotNull(exception); Assertions.assertEquals(ApiException.class, exception.getClass()); Assertions.assertEquals(403, ((ApiException) exception).getResponseStatusCode()); } diff --git a/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java b/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java index 0b181dc1ce..7342f76b29 100644 --- a/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java +++ b/integration-tests/src/test/java/io/apicurio/tests/auth/SimpleAuthIT.java @@ -2,15 +2,7 @@ import io.apicurio.registry.client.auth.VertXAuthFactory; import io.apicurio.registry.rest.client.RegistryClient; -import io.apicurio.registry.rest.client.models.ArtifactMetaData; -import io.apicurio.registry.rest.client.models.CreateArtifact; -import io.apicurio.registry.rest.client.models.CreateRule; -import io.apicurio.registry.rest.client.models.CreateVersion; -import io.apicurio.registry.rest.client.models.EditableArtifactMetaData; -import io.apicurio.registry.rest.client.models.RuleType; -import io.apicurio.registry.rest.client.models.UserInfo; -import io.apicurio.registry.rest.client.models.VersionContent; -import io.apicurio.registry.rest.client.models.VersionMetaData; +import io.apicurio.registry.rest.client.models.*; import io.apicurio.registry.rules.compatibility.CompatibilityLevel; import io.apicurio.registry.rules.validity.ValidityLevel; import io.apicurio.registry.types.ArtifactType; @@ -234,6 +226,18 @@ public void testOwnerOnlyAuthorization() throws Exception { createRule.setConfig(CompatibilityLevel.BACKWARD.name()); clientAdmin.groups().byGroupId(groupId).artifacts().byArtifactId(artifactId2).rules() .post(createRule); + + // Admin user will create an artifact + String artifactId1 = TestUtils.generateArtifactId(); + createArtifact.setArtifactId(artifactId1); + clientAdmin.groups().byGroupId(groupId).artifacts().post(createArtifact); + + // Dev user cannot update with ifExists the same artifact because Dev user is not the owner + Assertions.assertThrows(Exception.class, () -> { + clientDev.groups().byGroupId(groupId).artifacts().post(createArtifact, config -> { + config.queryParameters.ifExists = IfArtifactExists.CREATE_VERSION; + }); + }); } @Test diff --git a/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java b/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java index 95e019524f..e25432bd1e 100644 --- a/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java +++ b/java-sdk/src/main/java/io/apicurio/registry/client/auth/VertXAuthFactory.java @@ -27,14 +27,13 @@ public static WebClient buildOIDCWebClient(Vertx vertx, String tokenUrl, String String clientSecret, String scope) { WebClient webClient = WebClient.create(vertx); - OAuth2Auth oAuth2Options = OAuth2Auth.create(vertx, new OAuth2Options() - .setFlow(OAuth2FlowType.CLIENT) - .setClientId(clientId) - .setClientSecret(clientSecret) - .setTokenPath(tokenUrl)); + OAuth2Auth oAuth2Options = OAuth2Auth.create(vertx, new OAuth2Options().setFlow(OAuth2FlowType.CLIENT) + .setClientId(clientId).setClientSecret(clientSecret).setTokenPath(tokenUrl)); Oauth2Credentials oauth2Credentials = new Oauth2Credentials(); - oauth2Credentials.addScope(scope); + if (scope != null) { + oauth2Credentials.addScope(scope); + } OAuth2WebClient oauth2WebClient = OAuth2WebClient.create(webClient, oAuth2Options); oauth2WebClient.withCredentials(oauth2Credentials);