Add metadata generation

This commit is contained in:
Andreas Dinauer 2026-05-01 09:42:05 +02:00
parent 591b0e0b18
commit 5dea569bd8
27 changed files with 424 additions and 69 deletions

View File

@ -26,19 +26,23 @@ import org.jspecify.annotations.NonNull;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.SecureRandom;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Random;
import java.util.UUID; import java.util.UUID;
@ApplicationScoped @ApplicationScoped
@IfBuildProfile("dev") @IfBuildProfile("dev")
public class Dev public class Dev implements SecurityIdentityAugmentor
{ {
private static final BCrypt.Hasher HASHER = BCrypt.withDefaults(); private static final BCrypt.Hasher HASHER = BCrypt.withDefaults();
@Inject @Inject
TokenRepo tokenRepo; TokenRepo tokenRepo;
@Inject @Inject
MavenService mavenService; MavenService mavenService;
@ -59,6 +63,8 @@ public class Dev
uploadRelease_02(); uploadRelease_02();
uploadSnapshot_01(); uploadSnapshot_01();
uploadSnapshot_02(); uploadSnapshot_02();
uploadSnapshot_03();
uploadParent_01();
} }
private void uploadRelease_01() throws IOException private void uploadRelease_01() throws IOException
@ -89,8 +95,25 @@ public class Dev
mavenService.upload("/org/postgresql/postgresql/42.7.9-SNAPSHOT/postgresql-42.7.9-20250419.133456-1.pom", readFile("/jar/postgresql-42.7.9.pom")); mavenService.upload("/org/postgresql/postgresql/42.7.9-SNAPSHOT/postgresql-42.7.9-20250419.133456-1.pom", readFile("/jar/postgresql-42.7.9.pom"));
} }
private void uploadSnapshot_03() throws IOException
{
mavenService.upload("/org/postgresql/postgresql/42.7.10-SNAPSHOT/postgresql-42.7.10-20250419.123456-1.jar", readFile("/jar/postgresql-42.7.9.jar"));
mavenService.upload("/org/postgresql/postgresql/42.7.10-SNAPSHOT/postgresql-42.7.10-20250419.123456-1.pom", readFile("/jar/postgresql-42.7.9.pom"));
}
private byte[] readFile(String path) throws IOException private byte[] readFile(String path) throws IOException
{ {
return Objects.requireNonNull(getClass().getResourceAsStream(path)).readAllBytes(); return Objects.requireNonNull(getClass().getResourceAsStream(path)).readAllBytes();
} }
private void uploadParent_01() throws IOException
{
mavenService.upload("/dev/dinauer/maven-parent/1.0.0/maven-parent-1.0.0.pom", readFile("/jar/postgresql-42.7.9.pom"));
}
@Override
public Uni<SecurityIdentity> augment(SecurityIdentity identity, AuthenticationRequestContext context)
{
return Uni.createFrom().item(QuarkusSecurityIdentity.builder().setPrincipal(new QuarkusPrincipal("67f2814b-f8af-42b2-be9e-8a43cde383ec")).build());
}
} }

View File

@ -0,0 +1,15 @@
package dev.dinauer.maven;
import java.util.List;
public class Lists
{
public static <P> P getFirst(List<P> input)
{
if (input == null || input.isEmpty())
{
return null;
}
return input.getFirst();
}
}

View File

@ -25,9 +25,11 @@ public class ArtifactResource
@RestClient @RestClient
UserClient userClient; UserClient userClient;
@Inject
ResponseEnhancementService responseEnhancementService;
@GET @GET
public List<ArtifactId> get() public EnhancedResponse get()
{ {
return find(); return find();
} }
@ -47,15 +49,9 @@ public class ArtifactResource
artifactRepo.deleteById(id); artifactRepo.deleteById(id);
} }
private List<ArtifactId> find() private EnhancedResponse find()
{ {
List<ArtifactId> artifactIds = artifactRepo.listAll(); return responseEnhancementService.enhance(artifactRepo.listAll());
Map<String, User> accounts = getAccounts(artifactIds);
for (ArtifactId artifactId : artifactIds)
{
System.out.println("Skip setting user. Needs to be implemented");
}
return artifactIds;
} }
private Map<String, User> getAccounts(List<ArtifactId> artifactIds) private Map<String, User> getAccounts(List<ArtifactId> artifactIds)

View File

@ -0,0 +1,10 @@
package dev.dinauer.maven.app;
import dev.dinauer.maven.user.User;
import java.util.Map;
import java.util.Objects;
public record EnhancedResponse(Object data, Map<String, User> users)
{
}

View File

@ -6,6 +6,7 @@ import dev.dinauer.maven.event.Resource;
import dev.dinauer.maven.event.repo.EventRepo; import dev.dinauer.maven.event.repo.EventRepo;
import dev.dinauer.maven.maven.core.GroupRepo; import dev.dinauer.maven.maven.core.GroupRepo;
import dev.dinauer.maven.maven.core.GroupId; import dev.dinauer.maven.maven.core.GroupId;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.DELETE; import jakarta.ws.rs.DELETE;
@ -21,9 +22,13 @@ public class GroupResource
{ {
@Inject @Inject
GroupRepo groupRepo; GroupRepo groupRepo;
@Inject @Inject
EventRepo eventRepo; EventRepo eventRepo;
@Inject
SecurityIdentity securityIdentity;
@GET @GET
public List<GroupId> get() public List<GroupId> get()
{ {
@ -46,7 +51,7 @@ public class GroupResource
if (groupId != null) if (groupId != null)
{ {
groupRepo.delete(groupId); groupRepo.delete(groupId);
eventRepo.persist(new Event().setType(EventType.DELETE).setTimestamp(ZonedDateTime.now()).setResource(new Resource().setGroupId(groupId.getGroupId()))); eventRepo.persist(new Event().setUserId(securityIdentity.getPrincipal().getName()).setType(EventType.DELETE).setTimestamp(ZonedDateTime.now()).setResource(new Resource().setGroupId(groupId.getGroupId())));
} }
} }
} }

View File

@ -0,0 +1,22 @@
package dev.dinauer.maven.app;
import dev.dinauer.maven.shared.UserReferencing;
import dev.dinauer.maven.user.UserClient;
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@ApplicationScoped
public class ResponseEnhancementService
{
@RestClient
UserClient userClient;
public <P extends UserReferencing> EnhancedResponse enhance(Collection<P> data)
{
return new EnhancedResponse(data, userClient.get(data.stream().map(UserReferencing::getUserIds).flatMap(List::stream).collect(Collectors.toSet())));
}
}

View File

@ -1,14 +1,18 @@
package dev.dinauer.maven.event; package dev.dinauer.maven.event;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import dev.dinauer.maven.shared.UserReferencing;
import dev.dinauer.maven.user.User; import dev.dinauer.maven.user.User;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.List;
@Entity @Entity
@Table(name = "event") @Table(name = "event")
public class Event public class Event implements UserReferencing
{ {
@Id @Id
@GeneratedValue(strategy = GenerationType.UUID) @GeneratedValue(strategy = GenerationType.UUID)
@ -24,11 +28,8 @@ public class Event
private ZonedDateTime timestamp; private ZonedDateTime timestamp;
@Column(name = "accountId") @Column(name = "user_id")
private String accountId; private String userId;
@Transient
private User user;
public String getId() public String getId()
{ {
@ -74,25 +75,20 @@ public class Event
return this; return this;
} }
public String getAccountId() public String getUserId()
{ {
return accountId; return userId;
} }
public Event setAccountId(String userId) public Event setUserId(String userId)
{ {
this.accountId = userId; this.userId = userId;
return this; return this;
} }
public User getAccount() @Override
public List<String> getUserIds()
{ {
return user; return List.of(userId);
}
public Event setAccount(User user)
{
this.user = user;
return this;
} }
} }

View File

@ -1,5 +1,7 @@
package dev.dinauer.maven.event; package dev.dinauer.maven.event;
import dev.dinauer.maven.app.EnhancedResponse;
import dev.dinauer.maven.app.ResponseEnhancementService;
import dev.dinauer.maven.user.User; import dev.dinauer.maven.user.User;
import dev.dinauer.maven.event.repo.EventRepo; import dev.dinauer.maven.event.repo.EventRepo;
import dev.dinauer.maven.user.UserClient; import dev.dinauer.maven.user.UserClient;
@ -21,33 +23,12 @@ public class EventsResource
@Inject @Inject
EventRepo eventRepo; EventRepo eventRepo;
@RestClient
UserClient userClient;
@Inject @Inject
SecurityContext context; ResponseEnhancementService responseEnhancementService;
@GET @GET
public List<Event> get() public EnhancedResponse get()
{ {
return find(eventRepo.listAll(Sort.by("timestamp", Sort.Direction.Descending))); return responseEnhancementService.enhance(eventRepo.listAll(Sort.by("timestamp", Sort.Direction.Descending)));
}
private List<Event> find(List<Event> events)
{
Principal c = context.getUserPrincipal();
List<String> ids = new ArrayList<>();
for (Event event : events)
{
ids.add(event.getAccountId());
}
Map<String, User> accounts = userClient.get(ids);
for (Event event : events)
{
event.setAccount(accounts.get(event.getAccountId()));
}
return events;
} }
} }

View File

@ -1,21 +1,24 @@
package dev.dinauer.maven.maven.core; package dev.dinauer.maven.maven.core;
import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import dev.dinauer.maven.maven.core.release.ReleaseVersion; import dev.dinauer.maven.maven.core.release.ReleaseVersion;
import dev.dinauer.maven.maven.core.snapshot.SnapshotVersion; import dev.dinauer.maven.maven.core.snapshot.SnapshotVersion;
import dev.dinauer.maven.shared.UserReferencing;
import jakarta.persistence.*; import jakarta.persistence.*;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
@Entity @Entity
@Table(name = "artifact_id") @Table(name = "artifact_id")
public class ArtifactId public class ArtifactId implements UserReferencing
{ {
@Id @Id
@GeneratedValue(strategy = GenerationType.UUID) @GeneratedValue(strategy = GenerationType.UUID)
@ -109,6 +112,10 @@ public class ArtifactId
public ArtifactId setUpdatedAt(ZonedDateTime updatedAt) public ArtifactId setUpdatedAt(ZonedDateTime updatedAt)
{ {
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
if (this.group != null)
{
this.group.setUpdatedAt(updatedAt);
}
return this; return this;
} }
@ -146,7 +153,7 @@ public class ArtifactId
public List<ReleaseVersion> getReleaseVersions() public List<ReleaseVersion> getReleaseVersions()
{ {
return releaseVersions; return releaseVersions.stream().sorted(Comparator.comparing(item -> new DefaultArtifactVersion(item.getVersion()))).toList().reversed();
} }
public ArtifactId setReleaseVersions(List<ReleaseVersion> releaseVersions) public ArtifactId setReleaseVersions(List<ReleaseVersion> releaseVersions)
@ -154,4 +161,15 @@ public class ArtifactId
this.releaseVersions = releaseVersions; this.releaseVersions = releaseVersions;
return this; return this;
} }
@Override
public List<String> getUserIds()
{
List<String> userIds = new LinkedList<>();
for (ReleaseVersion releaseVersion : releaseVersions)
{
userIds.addAll(releaseVersion.getUserIds());
}
return userIds;
}
} }

View File

@ -1,5 +1,6 @@
package dev.dinauer.maven.maven.core; package dev.dinauer.maven.maven.core;
import dev.dinauer.maven.maven.core.artifact.metadata.ArtifactMetadataService;
import dev.dinauer.maven.maven.core.context.ArtifactContext; import dev.dinauer.maven.maven.core.context.ArtifactContext;
import dev.dinauer.maven.maven.core.context.ReleaseContext; import dev.dinauer.maven.maven.core.context.ReleaseContext;
import dev.dinauer.maven.maven.core.context.SnapshotContext; import dev.dinauer.maven.maven.core.context.SnapshotContext;
@ -36,6 +37,8 @@ public class MavenService
SnapshotService snapshotService; SnapshotService snapshotService;
@Inject @Inject
SnapshotMetadataService snapshotMetadataService; SnapshotMetadataService snapshotMetadataService;
@Inject
ArtifactMetadataService artifactMetadataService;
public void upload(String path, byte[] body) public void upload(String path, byte[] body)
{ {
@ -96,7 +99,14 @@ public class MavenService
} }
if (context.getClass() == ArtifactContext.class) if (context.getClass() == ArtifactContext.class)
{ {
return Response.status(404).build(); if (context.extensions().hashExt().isEmpty())
{
return Response.status(200).type(MediaType.APPLICATION_XML).entity(artifactMetadataService.generate(context)).build();
}
else
{
return Response.status(200).type(MediaType.TEXT_PLAIN).entity(artifactMetadataService.generateHash(context)).build();
}
} }
throw new BadRequestException(); throw new BadRequestException();
} }

View File

@ -0,0 +1,88 @@
package dev.dinauer.maven.maven.core.artifact.metadata;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import dev.dinauer.maven.Lists;
import dev.dinauer.maven.maven.core.ArtifactId;
import dev.dinauer.maven.maven.core.ArtifactRepo;
import dev.dinauer.maven.maven.core.Version;
import dev.dinauer.maven.maven.core.artifact.metadata.model.ArtifactMetadata;
import dev.dinauer.maven.maven.core.artifact.metadata.model.ArtifactVersioning;
import dev.dinauer.maven.maven.core.context.ArtifactContext;
import dev.dinauer.maven.maven.core.context.VersionContext;
import dev.dinauer.maven.maven.core.release.ReleaseVersion;
import dev.dinauer.maven.maven.core.snapshot.SnapshotBundle;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.Snapshot;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.SnapshotMetadata;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.SnapshotVersion;
import dev.dinauer.maven.maven.core.snapshot.metadata.model.SnapshotVersioning;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.NotFoundException;
import org.apache.commons.codec.digest.DigestUtils;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@ApplicationScoped
public class ArtifactMetadataService
{
private static final XmlMapper XML_MAPPER = new XmlMapper();
private final ArtifactRepo artifactRepo;
@Inject
public ArtifactMetadataService(ArtifactRepo artifactRepo)
{
this.artifactRepo = artifactRepo;
}
public String generate(ArtifactContext artifactContext)
{
try
{
return XML_MAPPER.writeValueAsString(generateMetadata(artifactContext));
}
catch (JsonProcessingException e)
{
throw new InternalServerErrorException();
}
}
private ArtifactMetadata generateMetadata(ArtifactContext artifactContext)
{
ArtifactId artifactId = artifactRepo.findOptionalByArtifactId(artifactContext.groupId(), artifactContext.artifactId()).orElseThrow(NotFoundException::new);
ZonedDateTime lastUpdated = artifactId.getUpdatedAt();
List<Version> versions = artifactId.getVersions();
Version latest = versions.getFirst();
String latestRelease = latestRelease(artifactId);
return new ArtifactMetadata(artifactId.getGroupId(), artifactId.getArtifactId(), new ArtifactVersioning(latest.getVersion(), latestRelease, versions.stream().map(Version::getVersion).toList().reversed(), lastUpdated.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))));
}
public String generateHash(ArtifactContext artifactContext)
{
switch (artifactContext.extensions().hashExt().orElseThrow())
{
case MD5 ->
{
return DigestUtils.md5Hex(generate(artifactContext));
}
case SHA256 ->
{
return DigestUtils.sha256Hex(generate(artifactContext));
}
}
throw new IllegalArgumentException();
}
private String latestRelease(ArtifactId artifactId)
{
ReleaseVersion releaseVersion = Lists.getFirst(artifactId.getReleaseVersions());
if (releaseVersion != null)
{
return releaseVersion.getVersion();
}
return null;
}
}

View File

@ -0,0 +1,8 @@
package dev.dinauer.maven.maven.core.artifact.metadata.model;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JacksonXmlRootElement(localName = "metadata")
public record ArtifactMetadata(String groupId, String artifactId, ArtifactVersioning versioning)
{
}

View File

@ -0,0 +1,11 @@
package dev.dinauer.maven.maven.core.artifact.metadata.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.util.List;
public record ArtifactVersioning(String latest, @JsonInclude(JsonInclude.Include.NON_NULL) String release, @JacksonXmlElementWrapper(localName = "versions") @JacksonXmlProperty(localName = "version") List<String> versions, String lastUpdated)
{
}

View File

@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.ZonedDateTime;
@Entity @Entity
@Table(name = "release_pom") @Table(name = "release_pom")
public class ReleasePom public class ReleasePom
@ -30,6 +32,9 @@ public class ReleasePom
@JsonBackReference @JsonBackReference
private ReleaseVersion releaseVersion; private ReleaseVersion releaseVersion;
@Column(name = "updated_at")
private ZonedDateTime updatedAt;
public String getId() public String getId()
{ {
return id; return id;
@ -106,4 +111,19 @@ public class ReleasePom
this.filename = filename; this.filename = filename;
return this; return this;
} }
public ZonedDateTime getUpdatedAt()
{
return updatedAt;
}
public ReleasePom setUpdatedAt(ZonedDateTime updatedAt)
{
this.updatedAt = updatedAt;
if (this.releaseVersion != null)
{
this.releaseVersion.setUpdatedAt(updatedAt);
}
return this;
}
} }

View File

@ -7,6 +7,7 @@ import dev.dinauer.maven.event.repo.EventRepo;
import dev.dinauer.maven.maven.core.context.ReleaseContext; import dev.dinauer.maven.maven.core.context.ReleaseContext;
import dev.dinauer.maven.maven.core.context.SnapshotContext; import dev.dinauer.maven.maven.core.context.SnapshotContext;
import dev.dinauer.maven.maven.core.model.FileHash; import dev.dinauer.maven.maven.core.model.FileHash;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.WebApplicationException;
@ -24,13 +25,17 @@ public class ReleasePomService
@Inject @Inject
ReleaseVersionService releaseVersionService; ReleaseVersionService releaseVersionService;
@Inject @Inject
EventRepo eventRepo; EventRepo eventRepo;
@Inject
SecurityIdentity securityIdentity;
public void store(ReleaseContext releaseContext, byte[] body) public void store(ReleaseContext releaseContext, byte[] body)
{ {
ReleasePom jar = releasePomRepo.find(releaseContext); ReleasePom pom = releasePomRepo.find(releaseContext);
if (jar == null) if (pom == null)
{ {
create(releaseContext, body); create(releaseContext, body);
createEvent(releaseContext); createEvent(releaseContext);
@ -65,11 +70,12 @@ public class ReleasePomService
releasePom.setMd5(DigestUtils.md5Hex(content)); releasePom.setMd5(DigestUtils.md5Hex(content));
releasePom.setSha1(DigestUtils.sha1Hex(content)); releasePom.setSha1(DigestUtils.sha1Hex(content));
releasePom.setFilename(releaseContext.filename()); releasePom.setFilename(releaseContext.filename());
releasePom.setUpdatedAt(ZonedDateTime.now());
releasePomRepo.persist(releasePom); releasePomRepo.persist(releasePom);
} }
private void createEvent(ReleaseContext releaseContext) private void createEvent(ReleaseContext releaseContext)
{ {
eventRepo.persist(new Event().setType(EventType.UPLOAD).setTimestamp(ZonedDateTime.now()).setResource(new Resource().setGroupId(releaseContext.groupId()).setArtifactId(releaseContext.artifactId()).setVersion(releaseContext.version()).setSnapshot(false))); eventRepo.persist(new Event().setUserId(securityIdentity.getPrincipal().getName()).setType(EventType.UPLOAD).setTimestamp(ZonedDateTime.now()).setResource(new Resource().setGroupId(releaseContext.groupId()).setArtifactId(releaseContext.artifactId()).setVersion(releaseContext.version()).setSnapshot(false)));
} }
} }

View File

@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import dev.dinauer.maven.maven.core.ArtifactId; import dev.dinauer.maven.maven.core.ArtifactId;
import dev.dinauer.maven.maven.core.Version; import dev.dinauer.maven.maven.core.Version;
import dev.dinauer.maven.shared.UserReferencing;
import dev.dinauer.maven.user.User; import dev.dinauer.maven.user.User;
import jakarta.persistence.*; import jakarta.persistence.*;
@ -14,7 +15,7 @@ import java.util.Optional;
@Entity @Entity
@Table(name = "release_version") @Table(name = "release_version")
public class ReleaseVersion implements Version public class ReleaseVersion implements Version, UserReferencing
{ {
@Id @Id
@GeneratedValue(strategy = GenerationType.UUID) @GeneratedValue(strategy = GenerationType.UUID)
@ -50,6 +51,9 @@ public class ReleaseVersion implements Version
@Column(name = "uploaded_by") @Column(name = "uploaded_by")
private String uploadedBy; private String uploadedBy;
@Column(name = "updated_at")
private ZonedDateTime updatedAt;
@Transient @Transient
private User uploadUser; private User uploadUser;
@ -191,6 +195,27 @@ public class ReleaseVersion implements Version
return Optional.empty(); return Optional.empty();
} }
public ZonedDateTime getUpdatedAt()
{
return updatedAt;
}
public ReleaseVersion setUpdatedAt(ZonedDateTime updatedAt)
{
this.updatedAt = updatedAt;
if (this.artifact != null)
{
artifact.setUpdatedAt(updatedAt);
}
return this;
}
@Override
public List<String> getUserIds()
{
return List.of(uploadedBy);
}
@Override @Override
public boolean isSnapshot() public boolean isSnapshot()
{ {

View File

@ -2,8 +2,10 @@ package dev.dinauer.maven.maven.core.release;
import dev.dinauer.maven.maven.core.ArtifactService; import dev.dinauer.maven.maven.core.ArtifactService;
import dev.dinauer.maven.maven.core.context.VersionContext; import dev.dinauer.maven.maven.core.context.VersionContext;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.core.SecurityContext;
@ApplicationScoped @ApplicationScoped
public class ReleaseVersionService public class ReleaseVersionService
@ -14,6 +16,9 @@ public class ReleaseVersionService
@Inject @Inject
ArtifactService artifactService; ArtifactService artifactService;
@Inject
SecurityIdentity securityIdentity;
public ReleaseVersion findOrCreate(VersionContext versionContext) public ReleaseVersion findOrCreate(VersionContext versionContext)
{ {
ReleaseVersion releaseVersion = releaseVersionRepo.findByGroupIdAndArtifactIdAndVersion(versionContext.groupId(), versionContext.artifactId(), versionContext.version()); ReleaseVersion releaseVersion = releaseVersionRepo.findByGroupIdAndArtifactIdAndVersion(versionContext.groupId(), versionContext.artifactId(), versionContext.version());
@ -26,6 +31,7 @@ public class ReleaseVersionService
ReleaseVersion created = new ReleaseVersion(); ReleaseVersion created = new ReleaseVersion();
created.setArtifact(artifactService.findOrCreate(versionContext.groupId(), versionContext.artifactId())); created.setArtifact(artifactService.findOrCreate(versionContext.groupId(), versionContext.artifactId()));
created.setVersion(versionContext.version()); created.setVersion(versionContext.version());
created.setUploadedBy(securityIdentity.getPrincipal().getName());
releaseVersionRepo.persist(created); releaseVersionRepo.persist(created);
return created; return created;
} }

View File

@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
@Entity @Entity
@ -34,6 +35,12 @@ public class SnapshotBundle
@JsonManagedReference @JsonManagedReference
private SnapshotPom pom; private SnapshotPom pom;
@Column(name = "updated_at")
private ZonedDateTime updatedAt;
@Column(name = "uploaded_by")
private String uploadedBy;
public String getId() public String getId()
{ {
return id; return id;
@ -115,4 +122,30 @@ public class SnapshotBundle
this.pom = pom; this.pom = pom;
return this; return this;
} }
public ZonedDateTime getUpdatedAt()
{
return updatedAt;
}
public SnapshotBundle setUpdatedAt(ZonedDateTime updatedAt)
{
this.updatedAt = updatedAt;
if (this.snapshotVersion != null)
{
this.snapshotVersion.setUpdatedAt(updatedAt);
}
return this;
}
public String getUploadedBy()
{
return uploadedBy;
}
public SnapshotBundle setUploadedBy(String uploadedBy)
{
this.uploadedBy = uploadedBy;
return this;
}
} }

View File

@ -1,6 +1,7 @@
package dev.dinauer.maven.maven.core.snapshot; package dev.dinauer.maven.maven.core.snapshot;
import dev.dinauer.maven.maven.core.context.SnapshotContext; import dev.dinauer.maven.maven.core.context.SnapshotContext;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
@ -14,6 +15,9 @@ public class SnapshotBundleService
@Inject @Inject
SnapshotVersionService snapshotVersionService; SnapshotVersionService snapshotVersionService;
@Inject
SecurityIdentity securityIdentity;
public SnapshotBundle findOrCreate(SnapshotContext snapshotContext) public SnapshotBundle findOrCreate(SnapshotContext snapshotContext)
{ {
SnapshotVersion snapshotVersion = snapshotVersionService.findOrCreate(snapshotContext); SnapshotVersion snapshotVersion = snapshotVersionService.findOrCreate(snapshotContext);
@ -29,6 +33,7 @@ public class SnapshotBundleService
created.setTime(snapshotContext.time()); created.setTime(snapshotContext.time());
created.setBuildNumber(snapshotContext.buildNumber()); created.setBuildNumber(snapshotContext.buildNumber());
created.setSnapshotVersion(snapshotVersion); created.setSnapshotVersion(snapshotVersion);
created.setUploadedBy(securityIdentity.getPrincipal().getName());
snapshotBundleRepo.persist(created); snapshotBundleRepo.persist(created);
return created; return created;
} }

View File

@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.ZonedDateTime;
@Entity @Entity
@Table(name = "snapshot_jar") @Table(name = "snapshot_jar")
public class SnapshotJar public class SnapshotJar

View File

@ -8,6 +8,8 @@ import jakarta.ws.rs.WebApplicationException;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.NotImplementedException;
import java.time.ZonedDateTime;
@ApplicationScoped @ApplicationScoped
public class SnapshotJarService public class SnapshotJarService
{ {

View File

@ -6,6 +6,7 @@ import dev.dinauer.maven.event.Resource;
import dev.dinauer.maven.event.repo.EventRepo; import dev.dinauer.maven.event.repo.EventRepo;
import dev.dinauer.maven.maven.core.context.ReleaseContext; import dev.dinauer.maven.maven.core.context.ReleaseContext;
import dev.dinauer.maven.maven.core.context.SnapshotContext; import dev.dinauer.maven.maven.core.context.SnapshotContext;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.WebApplicationException;
@ -27,6 +28,9 @@ public class SnapshotPomService
@Inject @Inject
SnapshotBundleService snapshotBundleService; SnapshotBundleService snapshotBundleService;
@Inject
SecurityIdentity securityIdentity;
public void store(SnapshotContext snapshotContext, byte[] body) public void store(SnapshotContext snapshotContext, byte[] body)
{ {
SnapshotBundle snapshotBundle = snapshotBundleService.findOrCreate(snapshotContext); SnapshotBundle snapshotBundle = snapshotBundleService.findOrCreate(snapshotContext);
@ -35,6 +39,7 @@ public class SnapshotPomService
{ {
create(snapshotBundle, body); create(snapshotBundle, body);
createEvent(snapshotContext); createEvent(snapshotContext);
snapshotBundle.setUpdatedAt(ZonedDateTime.now());
} }
else else
{ {
@ -72,6 +77,6 @@ public class SnapshotPomService
private void createEvent(SnapshotContext snapshotContext) private void createEvent(SnapshotContext snapshotContext)
{ {
eventRepo.persist(new Event().setType(EventType.UPLOAD).setTimestamp(ZonedDateTime.now()).setResource(new Resource().setGroupId(snapshotContext.groupId()).setArtifactId(snapshotContext.artifactId()).setVersion(snapshotContext.plainVersion()).setSnapshot(true))); eventRepo.persist(new Event().setUserId(securityIdentity.getPrincipal().getName()).setType(EventType.UPLOAD).setTimestamp(ZonedDateTime.now()).setResource(new Resource().setGroupId(snapshotContext.groupId()).setArtifactId(snapshotContext.artifactId()).setVersion(snapshotContext.plainVersion()).setSnapshot(true)));
} }
} }

View File

@ -6,6 +6,7 @@ import dev.dinauer.maven.maven.core.ArtifactId;
import dev.dinauer.maven.maven.core.Version; import dev.dinauer.maven.maven.core.Version;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
@Entity @Entity
@ -27,6 +28,9 @@ public class SnapshotVersion implements Version
@JsonManagedReference @JsonManagedReference
private List<SnapshotBundle> snapshotBundles; private List<SnapshotBundle> snapshotBundles;
@Column(name = "updated_at")
private ZonedDateTime updatedAt;
public String getId() public String getId()
{ {
return id; return id;
@ -71,6 +75,21 @@ public class SnapshotVersion implements Version
return this; return this;
} }
public ZonedDateTime getUpdatedAt()
{
return updatedAt;
}
public SnapshotVersion setUpdatedAt(ZonedDateTime updatedAt)
{
this.updatedAt = updatedAt;
if (this.artifact != null)
{
this.artifact.setUpdatedAt(updatedAt);
}
return this;
}
@Override @Override
public boolean isSnapshot() public boolean isSnapshot()
{ {

View File

@ -0,0 +1,11 @@
package dev.dinauer.maven.shared;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.List;
public interface UserReferencing
{
@JsonIgnore
List<String> getUserIds();
}

View File

@ -1,5 +1,12 @@
package dev.dinauer.maven.user; package dev.dinauer.maven.user;
import com.fasterxml.jackson.annotation.JsonProperty;
public record User(String id, String firstname, String lastname, String email) public record User(String id, String firstname, String lastname, String email)
{ {
@JsonProperty("displayName")
public String displayName()
{
return String.format("%s, %s", firstname, lastname);
}
} }

View File

@ -8,6 +8,7 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
@Path("/users") @Path("/users")
@OidcClientFilter @OidcClientFilter
@ -19,5 +20,5 @@ public interface UserClient
@POST @POST
@Path("/search") @Path("/search")
Map<String, User> get(List<String> ids); Map<String, User> get(Set<String> ids);
} }

View File

@ -8,6 +8,8 @@ create table group_id
primary key primary key
); );
alter table group_id owner to postgres;
create table artifact_id create table artifact_id
( (
created_at timestamp(6) with time zone, created_at timestamp(6) with time zone,
@ -22,10 +24,13 @@ create table artifact_id
primary key primary key
); );
alter table artifact_id owner to postgres;
create table release_version create table release_version
( (
pull_count integer, pull_count integer,
last_pulled timestamp(6) with time zone, last_pulled timestamp(6) with time zone,
updated_at timestamp(6) with time zone,
artifact_id varchar(255) artifact_id varchar(255)
constraint fk7c5hahrl7ws76sidh9d1434b8 constraint fk7c5hahrl7ws76sidh9d1434b8
references artifact_id, references artifact_id,
@ -38,6 +43,8 @@ create table release_version
version varchar(255) version varchar(255)
); );
alter table release_version owner to postgres;
create table release_jar create table release_jar
( (
classifier varchar(255), classifier varchar(255),
@ -54,8 +61,11 @@ create table release_jar
jar bytea jar bytea
); );
alter table release_jar owner to postgres;
create table release_pom create table release_pom
( (
updated_at timestamp(6) with time zone,
filename varchar(255), filename varchar(255),
id varchar(255) not null id varchar(255) not null
constraint release_pom_pkey constraint release_pom_pkey
@ -71,21 +81,24 @@ create table release_pom
url varchar(255) url varchar(255)
); );
alter table release_pom owner to postgres;
create table resource create table resource
( (
is_snapshot boolean,
artifact_id varchar(255), artifact_id varchar(255),
group_id varchar(255), group_id varchar(255),
is_snapshot boolean,
id varchar(255) not null id varchar(255) not null
constraint resource_pkey constraint resource_pkey
primary key, primary key,
version varchar(255) version varchar(255)
); );
alter table resource owner to postgres;
create table event create table event
( (
timestamp timestamp(6) with time zone, timestamp timestamp(6) with time zone,
accountid varchar(255),
id varchar(255) not null id varchar(255) not null
constraint event_pkey constraint event_pkey
primary key, primary key,
@ -96,11 +109,15 @@ create table event
references resource, references resource,
type varchar(255) type varchar(255)
constraint event_type_check constraint event_type_check
check ((type)::text = ANY ((ARRAY['UPLOAD'::character varying, 'DELETE'::character varying])::text[])) check ((type)::text = ANY ((ARRAY['UPLOAD'::character varying, 'DELETE'::character varying])::text[])),
); user_id varchar(255)
);
alter table event owner to postgres;
create table snapshot_version create table snapshot_version
( (
updated_at timestamp(6) with time zone,
artifact_id varchar(255) artifact_id varchar(255)
constraint fk64mje366563n82s8hy9bkfr14 constraint fk64mje366563n82s8hy9bkfr14
references artifact_id, references artifact_id,
@ -110,9 +127,12 @@ create table snapshot_version
version varchar(255) version varchar(255)
); );
alter table snapshot_version owner to postgres;
create table snapshot_bundle create table snapshot_bundle
( (
build_number integer, build_number integer,
updated_at timestamp(6) with time zone,
date varchar(255), date varchar(255),
id varchar(255) not null id varchar(255) not null
constraint snapshot_bundle_pkey constraint snapshot_bundle_pkey
@ -120,9 +140,12 @@ create table snapshot_bundle
snapshot_version_id varchar(255) snapshot_version_id varchar(255)
constraint fk3ve4wtmuywedyrri24dnqrpd9 constraint fk3ve4wtmuywedyrri24dnqrpd9
references snapshot_version, references snapshot_version,
time varchar(255) time varchar(255),
uploaded_by varchar(255)
); );
alter table snapshot_bundle owner to postgres;
create table snapshot_jar create table snapshot_jar
( (
classifier varchar(255), classifier varchar(255),
@ -137,6 +160,8 @@ create table snapshot_jar
jar bytea jar bytea
); );
alter table snapshot_jar owner to postgres;
create table snapshot_pom create table snapshot_pom
( (
id varchar(255) not null id varchar(255) not null
@ -152,6 +177,8 @@ create table snapshot_pom
references snapshot_bundle references snapshot_bundle
); );
alter table snapshot_pom owner to postgres;
create table token create table token
( (
expires_at date, expires_at date,
@ -163,3 +190,6 @@ create table token
token varchar(255), token varchar(255),
user_id varchar(255) user_id varchar(255)
); );
alter table token owner to postgres;