diff --git a/pom.xml b/pom.xml index 435e1ed..a06e341 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ UTF-8 quarkus-bom io.quarkus.platform - 3.30.8 + 3.34.3 true 3.5.4 @@ -64,16 +64,24 @@ io.quarkus - quarkus-elytron-security + quarkus-arc io.quarkus - quarkus-arc + quarkus-flyway + + + org.flywaydb + flyway-database-postgresql commons-io commons-io - 2.21.0 + + + at.favre.lib + bcrypt + 0.10.2 commons-codec @@ -83,7 +91,6 @@ org.apache.commons commons-lang3 - 3.20.0 compile @@ -94,12 +101,16 @@ org.apache.maven maven-artifact - 3.9.12 compile io.quarkus - quarkus-junit5 + quarkus-junit + test + + + io.quarkus + quarkus-test-security test @@ -138,7 +149,7 @@ maven-surefire-plugin ${surefire-plugin.version} - --add-opens java.base/java.lang=ALL-UNNAMED + @{argLine} --add-opens java.base/java.lang=ALL-UNNAMED org.jboss.logmanager.LogManager ${maven.home} @@ -157,7 +168,7 @@ - --add-opens java.base/java.lang=ALL-UNNAMED + @{argLine} --add-opens java.base/java.lang=ALL-UNNAMED ${project.build.directory}/${project.build.finalName}-runner org.jboss.logmanager.LogManager diff --git a/src/main/java/dev/dinauer/maven/CustomAuthenticationMechanism.java b/src/main/java/dev/dinauer/maven/CustomAuthenticationMechanism.java index 9ef46d6..d433b65 100644 --- a/src/main/java/dev/dinauer/maven/CustomAuthenticationMechanism.java +++ b/src/main/java/dev/dinauer/maven/CustomAuthenticationMechanism.java @@ -27,8 +27,6 @@ import java.util.Base64; @ApplicationScoped public class CustomAuthenticationMechanism implements HttpAuthenticationMechanism { - private static final String SESSION_COOKIE = "session"; - @Override public Uni authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) { diff --git a/src/main/java/dev/dinauer/maven/Dev.java b/src/main/java/dev/dinauer/maven/Dev.java index 622dd91..cb2f124 100644 --- a/src/main/java/dev/dinauer/maven/Dev.java +++ b/src/main/java/dev/dinauer/maven/Dev.java @@ -11,7 +11,7 @@ import java.nio.file.Files; import java.nio.file.Path; @ApplicationScoped -@IfBuildProfile("test") +@IfBuildProfile("x") public class Dev { @Inject diff --git a/src/main/java/dev/dinauer/maven/OidcCallback.java b/src/main/java/dev/dinauer/maven/OidcCallback.java deleted file mode 100644 index 05b37bd..0000000 --- a/src/main/java/dev/dinauer/maven/OidcCallback.java +++ /dev/null @@ -1,43 +0,0 @@ -package dev.dinauer.maven; - -import io.quarkus.oidc.client.NamedOidcClient; -import io.quarkus.oidc.client.OidcClient; -import io.quarkus.oidc.client.Tokens; -import jakarta.annotation.security.PermitAll; -import jakarta.inject.Inject; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.NewCookie; -import jakarta.ws.rs.core.Response; - -import java.net.URI; -import java.time.Instant; -import java.time.ZonedDateTime; -import java.util.Date; -import java.util.Map; - -@Path("/callback") -public class OidcCallback -{ - @Inject - @NamedOidcClient("ac") - OidcClient client; - - @GET - public Response callback(@QueryParam("code") String code) - { - Tokens tokens = client.getTokens(grantParams(code)).await().indefinitely(); - NewCookie cookie = new NewCookie.Builder("session").value(tokens.getAccessToken()).path("/").maxAge((int) (tokens.getAccessTokenExpiresAt() - ZonedDateTime.now().toEpochSecond())).secure(false).httpOnly(true).build(); - return Response.seeOther(URI.create("http://localhost:3000")).cookie(cookie).build(); - } - - private Map grantParams(String code) - { - return Map.ofEntries( - Map.entry("grant_type", "authorization_code"), - Map.entry("code", code), - Map.entry("redirect_uri", "redirectUri") - ); - } -} diff --git a/src/main/java/dev/dinauer/maven/TokenIdentityProvider.java b/src/main/java/dev/dinauer/maven/TokenIdentityProvider.java index 006d0ad..0de99b0 100644 --- a/src/main/java/dev/dinauer/maven/TokenIdentityProvider.java +++ b/src/main/java/dev/dinauer/maven/TokenIdentityProvider.java @@ -1,13 +1,12 @@ package dev.dinauer.maven; +import at.favre.lib.crypto.bcrypt.BCrypt; import dev.dinauer.maven.maven.token.TokenEntity; import dev.dinauer.maven.maven.token.TokenRepo; -import io.quarkus.elytron.security.common.BcryptUtil; import io.quarkus.security.AuthenticationFailedException; import io.quarkus.security.identity.AuthenticationRequestContext; import io.quarkus.security.identity.IdentityProvider; import io.quarkus.security.identity.SecurityIdentity; -import io.quarkus.security.identity.request.TokenAuthenticationRequest; import io.quarkus.security.identity.request.UsernamePasswordAuthenticationRequest; import io.quarkus.security.runtime.QuarkusPrincipal; import io.quarkus.security.runtime.QuarkusSecurityIdentity; @@ -17,12 +16,14 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.control.ActivateRequestContext; import jakarta.inject.Inject; +import java.nio.charset.StandardCharsets; import java.time.LocalDate; -import java.util.Base64; @ApplicationScoped public class TokenIdentityProvider implements IdentityProvider { + private static final BCrypt.Verifyer VERIFIER = BCrypt.verifyer(); + @Inject TokenRepo tokenRepo; @@ -41,7 +42,7 @@ public class TokenIdentityProvider implements IdentityProvider get() { diff --git a/src/main/java/dev/dinauer/maven/maven/core/JarService.java b/src/main/java/dev/dinauer/maven/maven/core/JarService.java new file mode 100644 index 0000000..9467ac1 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/JarService.java @@ -0,0 +1,72 @@ +package dev.dinauer.maven.maven.core; + +import dev.dinauer.maven.jpa.maven.Jar; +import dev.dinauer.maven.jpa.maven.Version; +import dev.dinauer.maven.maven.core.model.MavenContext; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.apache.commons.codec.digest.DigestUtils; + +import java.util.List; + +@ApplicationScoped +public class JarService +{ + @Inject + VersionService versionService; + + public Response store(MavenContext mavenContext, byte[] body) + { + String md5 = DigestUtils.md5Hex(body); + String sha1 = DigestUtils.sha1Hex(body); + Version version = versionService.findOrCreate(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()); + if (!existsJar(version.getJars(), mavenContext.file().getRaw())) + { + version.getJars().add(new Jar().setJar(body).setMd5(md5).setSha1(sha1).setVersion(version).setUrl(mavenContext.path()).setFilename(mavenContext.file().getRaw())); + versionService.persist(version); + return Response.status(Response.Status.CREATED).build(); + } + return Response.status(Response.Status.CONFLICT).build(); + } + + public Response find(MavenContext context) + { + return Response.status(Response.Status.OK).type(MediaType.APPLICATION_OCTET_STREAM).entity(findJar(context).getJar()).build(); + } + + public Response findHash(MavenContext context) + { + switch (context.file().getHash()) + { + case SHA1 -> + { + return Response.status(Response.Status.OK).type(MediaType.TEXT_PLAIN).entity(findJar(context).getSha1()).build(); + } + case MD5 -> + { + return Response.status(Response.Status.OK).type(MediaType.TEXT_PLAIN).entity(findJar(context).getMd5()).build(); + } + } + throw new BadRequestException(); + } + + private Jar findJar(MavenContext context) + { + return versionService.findOptional(context.groupId(), context.artifactId(), context.version().getRaw()).orElseThrow().getJarByFilename(context.file().getRaw()).orElseThrow(); + } + + private boolean existsJar(List jars, String filename) + { + for (Jar jar : jars) + { + if (filename.equals(jar.getFilename())) + { + return true; + } + } + return false; + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java b/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java index 32ca385..156147a 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java +++ b/src/main/java/dev/dinauer/maven/maven/core/MavenContextProvider.java @@ -15,12 +15,12 @@ public class MavenContextProvider case JAR, POM -> { MavenUrlParser parser = MavenUrlParser.parse(path); - return new MavenContext(parser.groupId(), parser.artifactId(), parser.version(), file); + return new MavenContext(path, parser.groupId(), parser.artifactId(), parser.version(), file); } case XML -> { MavenMetadataUrlParser parser = MavenMetadataUrlParser.parse(path); - return new MavenContext(parser.groupId(), parser.artifactId(), null, file); + return new MavenContext(path, parser.groupId(), parser.artifactId(), null, file); } } throw new RuntimeException(); diff --git a/src/main/java/dev/dinauer/maven/maven/core/PomService.java b/src/main/java/dev/dinauer/maven/maven/core/PomService.java new file mode 100644 index 0000000..e4f5873 --- /dev/null +++ b/src/main/java/dev/dinauer/maven/maven/core/PomService.java @@ -0,0 +1,47 @@ +package dev.dinauer.maven.maven.core; + +import dev.dinauer.maven.jpa.maven.Pom; +import dev.dinauer.maven.jpa.maven.Version; +import dev.dinauer.maven.maven.core.model.MavenContext; +import dev.dinauer.maven.maven.token.TokenService; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.apache.commons.codec.digest.DigestUtils; + +import java.time.ZonedDateTime; + +@ApplicationScoped +public class PomService +{ + @Inject + SecurityIdentity securityIdentity; + + @Inject + VersionService versionService; + + public Response store(MavenContext mavenContext, byte[] body) + { + String md5 = DigestUtils.md5Hex(body); + String sha1 = DigestUtils.sha1Hex(body); + Version version = versionService.findOrCreate(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()); + version.setUploadedBy(securityIdentity.getPrincipal().getName()); + if (version.getPom() == null) + { + version.setPom(new Pom().setPom(new String(body)).setMd5(md5).setSha1(sha1).setVersion(version).setUrl(mavenContext.path()).setFilename(mavenContext.file().getRaw())); + versionService.persist(version); + return Response.status(Response.Status.CREATED).build(); + } + return Response.status(Response.Status.CONFLICT).build(); + } + + public Response find(MavenContext mavenContext) + { + Version version = versionService.findOptional(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()).orElseThrow(); + version.setLastPulled(ZonedDateTime.now()); + version.incrementPullCount(); + return Response.status(Response.Status.OK).type(MediaType.APPLICATION_XML).entity(version.getPom().getPom()).build(); + } +} diff --git a/src/main/java/dev/dinauer/maven/maven/core/Service.java b/src/main/java/dev/dinauer/maven/maven/core/Service.java index 796d7db..4e76a73 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/Service.java +++ b/src/main/java/dev/dinauer/maven/maven/core/Service.java @@ -16,7 +16,9 @@ import jakarta.transaction.Transactional; import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import jdk.jshell.spi.ExecutionControl; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.NotImplementedException; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -32,7 +34,10 @@ public class Service ArtifactService artifactService; @Inject - TokenService tokenService; + JarService jarService; + + @Inject + PomService pomService; @Transactional public Response upload(String path, byte[] body) @@ -44,12 +49,7 @@ public class Service { if (FileHash.NONE.equals(mavenContext.file().getHash())) { - String md5 = DigestUtils.md5Hex(body); - String sha1 = DigestUtils.sha1Hex(body); - Version version = versionService.findOrCreate(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()); - version.getJars().add(new Jar().setJar(body).setMd5(md5).setSha1(sha1).setVersion(version).setUrl(path).setFilename(mavenContext.file().getRaw())); - versionService.persist(version); - return Response.status(Response.Status.CREATED).build(); + return jarService.store(mavenContext, body); } return Response.accepted().build(); } @@ -57,17 +57,7 @@ public class Service { if (FileHash.NONE.equals(mavenContext.file().getHash())) { - String md5 = DigestUtils.md5Hex(body); - String sha1 = DigestUtils.sha1Hex(body); - Version version = versionService.findOrCreate(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()); - version.setUploadedBy(tokenService.require()); - if (version.getPom() == null) - { - version.setPom(new Pom().setPom(new String(body)).setMd5(md5).setSha1(sha1).setVersion(version).setUrl(path).setFilename(mavenContext.file().getRaw())); - versionService.persist(version); - return Response.status(Response.Status.CREATED).build(); - } - return Response.status(Response.Status.CONFLICT).build(); + return pomService.store(mavenContext, body); } return Response.accepted().build(); } @@ -87,32 +77,19 @@ public class Service { case JAR -> { - Version version = versionService.findOptional(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()).orElseThrow(); - Optional optionalJar = version.getJarByFilename(mavenContext.file().getRaw()); - if (optionalJar.isEmpty()) + if (FileHash.NONE.equals(mavenContext.file().getHash())) { - throw new NotFoundException(); + return jarService.find(mavenContext); } - switch (mavenContext.file().getHash()) - { - case SHA1 -> - { - return Response.status(Response.Status.OK).type(MediaType.APPLICATION_OCTET_STREAM).entity(optionalJar.get().getSha1()).build(); - } - case MD5 -> - { - return Response.status(Response.Status.OK).type(MediaType.APPLICATION_OCTET_STREAM).entity(optionalJar.get().getMd5()).build(); - } - } - version.setLastPulled(ZonedDateTime.now()); - return Response.status(Response.Status.OK).type(MediaType.APPLICATION_OCTET_STREAM).entity(optionalJar.get().getJar()).build(); + return jarService.findHash(mavenContext); } case POM -> { - Version version = versionService.findOptional(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()).orElseThrow(); - version.setLastPulled(ZonedDateTime.now()); - version.incrementPullCount(); - return Response.status(Response.Status.OK).type(MediaType.APPLICATION_XML).entity(version.getPom().getPom()).build(); + if (FileHash.NONE.equals(mavenContext.file().getHash())) + { + return pomService.find(mavenContext); + } + throw new NotImplementedException(); } case XML -> { diff --git a/src/main/java/dev/dinauer/maven/maven/core/VersionService.java b/src/main/java/dev/dinauer/maven/maven/core/VersionService.java index 5fa37d9..7e0478f 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/VersionService.java +++ b/src/main/java/dev/dinauer/maven/maven/core/VersionService.java @@ -8,6 +8,7 @@ import dev.dinauer.maven.jpa.maven.ArtifactId; import dev.dinauer.maven.jpa.maven.Version; import dev.dinauer.maven.jpa.maven.repo.VersionRepo; import dev.dinauer.maven.maven.token.TokenService; +import io.quarkus.security.identity.SecurityIdentity; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -27,7 +28,7 @@ public class VersionService EventRepo eventRepo; @Inject - TokenService tokenService; + SecurityIdentity securityIdentity; public Optional findOptional(String groupId, String artifactId, String version) { @@ -52,6 +53,6 @@ public class VersionService public void persist(Version version) { versionRepo.persist(version); - eventRepo.persist(new Event().setAccountId(tokenService.require()).setType(EventType.UPLOAD).setResource(new Resource().setGroupId(version.getGroupId()).setArtifactId(version.getArtifactId()).setVersion(version.getVersion())).setTimestamp(ZonedDateTime.now())); + eventRepo.persist(new Event().setAccountId(securityIdentity.getPrincipal().getName()).setType(EventType.UPLOAD).setResource(new Resource().setGroupId(version.getGroupId()).setArtifactId(version.getArtifactId()).setVersion(version.getVersion())).setTimestamp(ZonedDateTime.now())); } } \ No newline at end of file diff --git a/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java b/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java index 8f80ba8..adedc59 100644 --- a/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java +++ b/src/main/java/dev/dinauer/maven/maven/core/model/MavenContext.java @@ -1,5 +1,5 @@ package dev.dinauer.maven.maven.core.model; -public record MavenContext(String groupId, String artifactId, Version version, File file) +public record MavenContext(String path, String groupId, String artifactId, Version version, File file) { } diff --git a/src/main/java/dev/dinauer/maven/maven/token/TokenService.java b/src/main/java/dev/dinauer/maven/maven/token/TokenService.java index 81eef2f..b4f7513 100644 --- a/src/main/java/dev/dinauer/maven/maven/token/TokenService.java +++ b/src/main/java/dev/dinauer/maven/maven/token/TokenService.java @@ -1,31 +1,24 @@ package dev.dinauer.maven.maven.token; +import at.favre.lib.crypto.bcrypt.BCrypt; import dev.dinauer.maven.maven.token.dto.TokenCreation; import dev.dinauer.maven.maven.token.dto.TokenSecret; -import io.quarkus.elytron.security.common.BcryptUtil; -import io.quarkus.security.UnauthorizedException; -import io.vertx.core.http.HttpHeaders; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import io.vertx.core.http.HttpServerRequest; import jakarta.transaction.Transactional; -import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.core.SecurityContext; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import java.time.LocalDate; import java.time.ZonedDateTime; -import java.util.Base64; import java.util.UUID; @ApplicationScoped public class TokenService { - @Inject - TokenRepo tokenRepo; + private static final BCrypt.Hasher HASHER = BCrypt.withDefaults(); @Inject - HttpServerRequest request; + TokenRepo tokenRepo; @Inject SecurityContext securityContext; @@ -36,7 +29,7 @@ public class TokenService String secret = UUID.randomUUID().toString(); TokenEntity entity = new TokenEntity() .setName(tokenCreation.name()) - .setToken(BcryptUtil.bcryptHash(secret)) + .setToken(HASHER.hashToString(11, secret.toCharArray())) .setUserId(securityContext.getUserPrincipal().getName()) .setExpiresAt(tokenCreation.expiresAt()) .setCreatedAt(ZonedDateTime.now()); @@ -53,37 +46,4 @@ public class TokenService tokenRepo.delete(token); } } - - public String require() - { - String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); - if (authHeader != null && !authHeader.isBlank()) - { - String[] sections = authHeader.split("\\s+"); - if (sections.length == 2 && sections[0].equals("Basic")) - { - String value = new String(Base64.getDecoder().decode(sections[1])); - String[] parts = value.split(":"); - if (parts.length == 2) - { - String username = parts[0]; - String password = parts[1]; - for (TokenEntity token : tokenRepo.findByUserId(username)) - { - if (BcryptUtil.matches(password, token.getToken())) - { - LocalDate now = LocalDate.now(); - if (now.equals(token.getExpiresAt()) || now.isBefore(token.getExpiresAt())) - { - return username; - } - } - } - throw new UnauthorizedException(); - } - } - throw new BadRequestException(); - } - throw new UnauthorizedException(); - } } diff --git a/src/main/java/dev/dinauer/maven/user/UserResource.java b/src/main/java/dev/dinauer/maven/user/UserResource.java index 1dd64f2..8ab895b 100644 --- a/src/main/java/dev/dinauer/maven/user/UserResource.java +++ b/src/main/java/dev/dinauer/maven/user/UserResource.java @@ -12,13 +12,9 @@ public class UserResource @RestClient UserClient userClient; - @Inject - SecurityIdentity identity; - @GET public Object get() { - System.out.println(identity.getPrincipal().getName()); return userClient.getUser(); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1569706..549dc68 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,20 +4,17 @@ %dev.quarkus.http.cors.origins=/.*/ %dev.quarkus.http.cors.access-control-allow-credentials=true quarkus.http.access-log.enabled=true + +%test.quarkus.http.test-port=9081 # Auth quarkus.http.auth.permission.authenticated.paths=/* quarkus.http.auth.permission.authenticated.policy=authenticated -quarkus.http.auth.permission.permit.paths=/callback -quarkus.http.auth.permission.permit.policy=permit # Postgres -%dev,test.quarkus.datasource.db-kind=postgresql -%dev,test.quarkus.hibernate-orm.schema-management.strategy=none -%dev,test.quarkus.datasource.username=postgres -%dev,test.quarkus.datasource.password=postgres -%dev,test.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres - -%prod.quarkus.hibernate-orm.schema-management.strategy=drop-and-create +quarkus.datasource.db-kind=postgresql +%dev.quarkus.datasource.username=postgres +%dev.quarkus.datasource.password=postgres +%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres quarkus.oidc.auth-server-url=http://localhost:8089/api/realms/maven quarkus.oidc.client-id=backend @@ -26,4 +23,7 @@ quarkus.oidc-client.auth-server-url=http://localhost:8089/api/realms/maven quarkus.oidc-client.client-id=backend quarkus.oidc-client.credentials.secret=backend -quarkus.rest-client.idp.url=http://localhost:8089/api/realms/maven \ No newline at end of file +quarkus.rest-client.idp.url=http://localhost:8089/api/realms/maven + +%dev,test.quarkus.flyway.clean-at-start=true +quarkus.flyway.migrate-at-start=true \ No newline at end of file diff --git a/src/main/resources/db/migration/V1.0.0__init.sql b/src/main/resources/db/migration/V1.0.0__init.sql new file mode 100644 index 0000000..f9c9d82 --- /dev/null +++ b/src/main/resources/db/migration/V1.0.0__init.sql @@ -0,0 +1,101 @@ +create table group_id +( + created_at timestamp(6) with time zone, + updated_at timestamp(6) with time zone, + group_id varchar(255), + id varchar(255) not null + primary key +); + +create table artifact_id +( + created_at timestamp(6) with time zone, + updated_at timestamp(6) with time zone, + artifact_id varchar(255), + group_id varchar(255) + constraint fkghhaxmc9rw9lhck83y9o6bp1o + references group_id, + group_id_long varchar(255), + id varchar(255) not null + primary key +); + +create table resource +( + artifact_id varchar(255), + group_id varchar(255), + id varchar(255) not null + primary key, + version varchar(255) +); + +create table event +( + timestamp timestamp(6) with time zone, + accountid varchar(255), + id varchar(255) not null + primary key, + resource_id varchar(255) + unique + constraint fkclx5xnhdf2y3l1g3ae6ygsjmf + references resource, + type varchar(255) + constraint event_type_check + check ((type)::text = ANY ((ARRAY ['UPLOAD'::character varying, 'DELETE'::character varying])::text[])) +); + +create table token +( + expires_at date, + created_at timestamp(6) with time zone, + id varchar(255) not null + primary key, + name varchar(255), + token varchar(255), + user_id varchar(255) +); + +create table version +( + pull_count integer, + last_pulled timestamp(6) with time zone, + artifact_id varchar(255) + constraint fklcnjnhvigubmjqng9wt7lcw71 + references artifact_id, + artifact_id_long varchar(255), + group_id_long varchar(255), + id varchar(255) not null + primary key, + uploaded_by varchar(255), + version varchar(255) +); + +create table jar +( + filename varchar(255), + id varchar(255) not null + primary key, + md5 varchar(255), + sha1 varchar(255), + url varchar(255), + version_id varchar(255) + constraint fkaf1ctqgugsre652w5465uhjbu + references version, + jar bytea +); + +create table pom +( + filename varchar(255), + id varchar(255) not null + primary key, + md5 varchar(255), + pom text, + sha1 varchar(255), + url varchar(255), + version_id varchar(255) + unique + constraint fker1jyb1nf0vpmyv5b6ooydplu + references version +); + diff --git a/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java b/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java new file mode 100644 index 0000000..85fd9fc --- /dev/null +++ b/src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java @@ -0,0 +1,52 @@ +package dev.dinauer.maven.maven.core; + +import dev.dinauer.maven.jpa.maven.Version; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.security.TestSecurity; +import io.restassured.RestAssured; +import jakarta.inject.Inject; +import org.flywaydb.core.Flyway; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.InputStream; +import java.util.Optional; + +@QuarkusTest +public class ResourceTest +{ + @Inject + Flyway flyway; + + @Inject + VersionService versionService; + + @BeforeEach + void before() + { + flyway.clean(); + flyway.migrate(); + } + + @Test + @TestSecurity(user = "user") + void test() + { + RestAssured.given().body(readFile("/jar/postgresql-42.7.9.jar")).put("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.jar"); + RestAssured.given().body(readFile("/jar/postgresql-42.7.9.pom")).put("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.pom"); + byte[] responseJar = RestAssured.given().get("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.jar").getBody().asByteArray(); + String responsePom = RestAssured.given().get("/maven2/org/postgresql/postgresql/42.7.9/postgresql-42.7.9.pom").getBody().asString(); + + Optional version = versionService.findOptional("org.postgresql", "postgresql", "42.7.9"); + + Assertions.assertTrue(version.isPresent()); + Assertions.assertTrue(responseJar.length > 0); + Assertions.assertTrue(responsePom !=null && responsePom.startsWith("