🚧 Add file retrieval

This commit is contained in:
Andreas Dinauer 2026-04-13 19:52:56 +02:00
parent 9e28c1c7f3
commit 1545a2c70d
17 changed files with 334 additions and 165 deletions

29
pom.xml
View File

@ -12,7 +12,7 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id> <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.30.8</quarkus.platform.version> <quarkus.platform.version>3.34.3</quarkus.platform.version>
<skipITs>true</skipITs> <skipITs>true</skipITs>
<surefire-plugin.version>3.5.4</surefire-plugin.version> <surefire-plugin.version>3.5.4</surefire-plugin.version>
</properties> </properties>
@ -64,16 +64,24 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-elytron-security</artifactId> <artifactId>quarkus-arc</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId> <artifactId>quarkus-flyway</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.21.0</version> </dependency>
<dependency>
<groupId>at.favre.lib</groupId>
<artifactId>bcrypt</artifactId>
<version>0.10.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-codec</groupId> <groupId>commons-codec</groupId>
@ -83,7 +91,6 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.20.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -94,12 +101,16 @@
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId> <artifactId>maven-artifact</artifactId>
<version>3.9.12</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId> <artifactId>quarkus-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -138,7 +149,7 @@
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version> <version>${surefire-plugin.version}</version>
<configuration> <configuration>
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine> <argLine>@{argLine} --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
<systemPropertyVariables> <systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home> <maven.home>${maven.home}</maven.home>
@ -157,7 +168,7 @@
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine> <argLine>@{argLine} --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
<systemPropertyVariables> <systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>

View File

@ -27,8 +27,6 @@ import java.util.Base64;
@ApplicationScoped @ApplicationScoped
public class CustomAuthenticationMechanism implements HttpAuthenticationMechanism public class CustomAuthenticationMechanism implements HttpAuthenticationMechanism
{ {
private static final String SESSION_COOKIE = "session";
@Override @Override
public Uni<SecurityIdentity> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) public Uni<SecurityIdentity> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager)
{ {

View File

@ -11,7 +11,7 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ApplicationScoped @ApplicationScoped
@IfBuildProfile("test") @IfBuildProfile("x")
public class Dev public class Dev
{ {
@Inject @Inject

View File

@ -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<String, String> grantParams(String code)
{
return Map.ofEntries(
Map.entry("grant_type", "authorization_code"),
Map.entry("code", code),
Map.entry("redirect_uri", "redirectUri")
);
}
}

View File

@ -1,13 +1,12 @@
package dev.dinauer.maven; package dev.dinauer.maven;
import at.favre.lib.crypto.bcrypt.BCrypt;
import dev.dinauer.maven.maven.token.TokenEntity; import dev.dinauer.maven.maven.token.TokenEntity;
import dev.dinauer.maven.maven.token.TokenRepo; import dev.dinauer.maven.maven.token.TokenRepo;
import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.security.AuthenticationFailedException; import io.quarkus.security.AuthenticationFailedException;
import io.quarkus.security.identity.AuthenticationRequestContext; import io.quarkus.security.identity.AuthenticationRequestContext;
import io.quarkus.security.identity.IdentityProvider; import io.quarkus.security.identity.IdentityProvider;
import io.quarkus.security.identity.SecurityIdentity; import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.request.TokenAuthenticationRequest;
import io.quarkus.security.identity.request.UsernamePasswordAuthenticationRequest; import io.quarkus.security.identity.request.UsernamePasswordAuthenticationRequest;
import io.quarkus.security.runtime.QuarkusPrincipal; import io.quarkus.security.runtime.QuarkusPrincipal;
import io.quarkus.security.runtime.QuarkusSecurityIdentity; import io.quarkus.security.runtime.QuarkusSecurityIdentity;
@ -17,12 +16,14 @@ import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.control.ActivateRequestContext; import jakarta.enterprise.context.control.ActivateRequestContext;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Base64;
@ApplicationScoped @ApplicationScoped
public class TokenIdentityProvider implements IdentityProvider<UsernamePasswordAuthenticationRequest> public class TokenIdentityProvider implements IdentityProvider<UsernamePasswordAuthenticationRequest>
{ {
private static final BCrypt.Verifyer VERIFIER = BCrypt.verifyer();
@Inject @Inject
TokenRepo tokenRepo; TokenRepo tokenRepo;
@ -41,7 +42,7 @@ public class TokenIdentityProvider implements IdentityProvider<UsernamePasswordA
String password = new String(request.getPassword().getPassword()); String password = new String(request.getPassword().getPassword());
for (TokenEntity token : tokenRepo.findByUserId(username)) for (TokenEntity token : tokenRepo.findByUserId(username))
{ {
if (BcryptUtil.matches(password, token.getToken())) if (VERIFIER.verify(password.getBytes(StandardCharsets.UTF_8), token.getToken().getBytes(StandardCharsets.UTF_8)).verified)
{ {
LocalDate now = LocalDate.now(); LocalDate now = LocalDate.now();
if (!now.isAfter(token.getExpiresAt())) if (!now.isAfter(token.getExpiresAt()))

View File

@ -1,6 +1,5 @@
package dev.dinauer.maven.app; package dev.dinauer.maven.app;
import dev.dinauer.maven.jpa.maven.repo.VersionRepo;
import dev.dinauer.maven.user.User; import dev.dinauer.maven.user.User;
import dev.dinauer.maven.jpa.maven.Version; import dev.dinauer.maven.jpa.maven.Version;
import dev.dinauer.maven.jpa.maven.repo.ArtifactRepo; import dev.dinauer.maven.jpa.maven.repo.ArtifactRepo;
@ -27,9 +26,6 @@ public class ArtifactResource
@RestClient @RestClient
UserClient userClient; UserClient userClient;
@Inject
VersionRepo versionRepo;
@GET @GET
public List<ArtifactId> get() public List<ArtifactId> get()
{ {

View File

@ -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<Jar> jars, String filename)
{
for (Jar jar : jars)
{
if (filename.equals(jar.getFilename()))
{
return true;
}
}
return false;
}
}

View File

@ -15,12 +15,12 @@ public class MavenContextProvider
case JAR, POM -> case JAR, POM ->
{ {
MavenUrlParser parser = MavenUrlParser.parse(path); 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 -> case XML ->
{ {
MavenMetadataUrlParser parser = MavenMetadataUrlParser.parse(path); 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(); throw new RuntimeException();

View File

@ -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();
}
}

View File

@ -16,7 +16,9 @@ import jakarta.transaction.Transactional;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import jdk.jshell.spi.ExecutionControl;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.NotImplementedException;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -32,7 +34,10 @@ public class Service
ArtifactService artifactService; ArtifactService artifactService;
@Inject @Inject
TokenService tokenService; JarService jarService;
@Inject
PomService pomService;
@Transactional @Transactional
public Response upload(String path, byte[] body) public Response upload(String path, byte[] body)
@ -44,12 +49,7 @@ public class Service
{ {
if (FileHash.NONE.equals(mavenContext.file().getHash())) if (FileHash.NONE.equals(mavenContext.file().getHash()))
{ {
String md5 = DigestUtils.md5Hex(body); return jarService.store(mavenContext, 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 Response.accepted().build(); return Response.accepted().build();
} }
@ -57,17 +57,7 @@ public class Service
{ {
if (FileHash.NONE.equals(mavenContext.file().getHash())) if (FileHash.NONE.equals(mavenContext.file().getHash()))
{ {
String md5 = DigestUtils.md5Hex(body); return pomService.store(mavenContext, 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 Response.accepted().build(); return Response.accepted().build();
} }
@ -87,32 +77,19 @@ public class Service
{ {
case JAR -> case JAR ->
{ {
Version version = versionService.findOptional(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()).orElseThrow(); if (FileHash.NONE.equals(mavenContext.file().getHash()))
Optional<Jar> optionalJar = version.getJarByFilename(mavenContext.file().getRaw());
if (optionalJar.isEmpty())
{ {
throw new NotFoundException(); return jarService.find(mavenContext);
} }
switch (mavenContext.file().getHash()) return jarService.findHash(mavenContext);
{
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();
} }
case POM -> case POM ->
{ {
Version version = versionService.findOptional(mavenContext.groupId(), mavenContext.artifactId(), mavenContext.version().getRaw()).orElseThrow(); if (FileHash.NONE.equals(mavenContext.file().getHash()))
version.setLastPulled(ZonedDateTime.now()); {
version.incrementPullCount(); return pomService.find(mavenContext);
return Response.status(Response.Status.OK).type(MediaType.APPLICATION_XML).entity(version.getPom().getPom()).build(); }
throw new NotImplementedException();
} }
case XML -> case XML ->
{ {

View File

@ -8,6 +8,7 @@ import dev.dinauer.maven.jpa.maven.ArtifactId;
import dev.dinauer.maven.jpa.maven.Version; import dev.dinauer.maven.jpa.maven.Version;
import dev.dinauer.maven.jpa.maven.repo.VersionRepo; import dev.dinauer.maven.jpa.maven.repo.VersionRepo;
import dev.dinauer.maven.maven.token.TokenService; import dev.dinauer.maven.maven.token.TokenService;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@ -27,7 +28,7 @@ public class VersionService
EventRepo eventRepo; EventRepo eventRepo;
@Inject @Inject
TokenService tokenService; SecurityIdentity securityIdentity;
public Optional<Version> findOptional(String groupId, String artifactId, String version) public Optional<Version> findOptional(String groupId, String artifactId, String version)
{ {
@ -52,6 +53,6 @@ public class VersionService
public void persist(Version version) public void persist(Version version)
{ {
versionRepo.persist(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()));
} }
} }

View File

@ -1,5 +1,5 @@
package dev.dinauer.maven.maven.core.model; 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)
{ {
} }

View File

@ -1,31 +1,24 @@
package dev.dinauer.maven.maven.token; 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.TokenCreation;
import dev.dinauer.maven.maven.token.dto.TokenSecret; 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.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerRequest;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.SecurityContext;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.time.LocalDate;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Base64;
import java.util.UUID; import java.util.UUID;
@ApplicationScoped @ApplicationScoped
public class TokenService public class TokenService
{ {
@Inject private static final BCrypt.Hasher HASHER = BCrypt.withDefaults();
TokenRepo tokenRepo;
@Inject @Inject
HttpServerRequest request; TokenRepo tokenRepo;
@Inject @Inject
SecurityContext securityContext; SecurityContext securityContext;
@ -36,7 +29,7 @@ public class TokenService
String secret = UUID.randomUUID().toString(); String secret = UUID.randomUUID().toString();
TokenEntity entity = new TokenEntity() TokenEntity entity = new TokenEntity()
.setName(tokenCreation.name()) .setName(tokenCreation.name())
.setToken(BcryptUtil.bcryptHash(secret)) .setToken(HASHER.hashToString(11, secret.toCharArray()))
.setUserId(securityContext.getUserPrincipal().getName()) .setUserId(securityContext.getUserPrincipal().getName())
.setExpiresAt(tokenCreation.expiresAt()) .setExpiresAt(tokenCreation.expiresAt())
.setCreatedAt(ZonedDateTime.now()); .setCreatedAt(ZonedDateTime.now());
@ -53,37 +46,4 @@ public class TokenService
tokenRepo.delete(token); 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();
}
} }

View File

@ -12,13 +12,9 @@ public class UserResource
@RestClient @RestClient
UserClient userClient; UserClient userClient;
@Inject
SecurityIdentity identity;
@GET @GET
public Object get() public Object get()
{ {
System.out.println(identity.getPrincipal().getName());
return userClient.getUser(); return userClient.getUser();
} }
} }

View File

@ -4,20 +4,17 @@
%dev.quarkus.http.cors.origins=/.*/ %dev.quarkus.http.cors.origins=/.*/
%dev.quarkus.http.cors.access-control-allow-credentials=true %dev.quarkus.http.cors.access-control-allow-credentials=true
quarkus.http.access-log.enabled=true quarkus.http.access-log.enabled=true
%test.quarkus.http.test-port=9081
# Auth # Auth
quarkus.http.auth.permission.authenticated.paths=/* quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.http.auth.permission.permit.paths=/callback
quarkus.http.auth.permission.permit.policy=permit
# Postgres # Postgres
%dev,test.quarkus.datasource.db-kind=postgresql quarkus.datasource.db-kind=postgresql
%dev,test.quarkus.hibernate-orm.schema-management.strategy=none %dev.quarkus.datasource.username=postgres
%dev,test.quarkus.datasource.username=postgres %dev.quarkus.datasource.password=postgres
%dev,test.quarkus.datasource.password=postgres %dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres
%dev,test.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres
%prod.quarkus.hibernate-orm.schema-management.strategy=drop-and-create
quarkus.oidc.auth-server-url=http://localhost:8089/api/realms/maven quarkus.oidc.auth-server-url=http://localhost:8089/api/realms/maven
quarkus.oidc.client-id=backend quarkus.oidc.client-id=backend
@ -27,3 +24,6 @@ quarkus.oidc-client.client-id=backend
quarkus.oidc-client.credentials.secret=backend quarkus.oidc-client.credentials.secret=backend
quarkus.rest-client.idp.url=http://localhost:8089/api/realms/maven 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

View File

@ -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
);

View File

@ -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> version = versionService.findOptional("org.postgresql", "postgresql", "42.7.9");
Assertions.assertTrue(version.isPresent());
Assertions.assertTrue(responseJar.length > 0);
Assertions.assertTrue(responsePom !=null && responsePom.startsWith("<?xml"));
}
private InputStream readFile(String path)
{
return getClass().getResourceAsStream(path);
}
}