🚧 Add file retrieval
This commit is contained in:
parent
9e28c1c7f3
commit
1545a2c70d
29
pom.xml
29
pom.xml
@ -12,7 +12,7 @@
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-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>
|
||||
<surefire-plugin.version>3.5.4</surefire-plugin.version>
|
||||
</properties>
|
||||
@ -64,16 +64,24 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-elytron-security</artifactId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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>
|
||||
<groupId>commons-io</groupId>
|
||||
<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>
|
||||
<groupId>commons-codec</groupId>
|
||||
@ -83,7 +91,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.20.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -94,12 +101,16 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-artifact</artifactId>
|
||||
<version>3.9.12</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -138,7 +149,7 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
|
||||
<argLine>@{argLine} --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
@ -157,7 +168,7 @@
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
|
||||
<argLine>@{argLine} --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
|
||||
<systemPropertyVariables>
|
||||
<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>
|
||||
|
||||
@ -27,8 +27,6 @@ import java.util.Base64;
|
||||
@ApplicationScoped
|
||||
public class CustomAuthenticationMechanism implements HttpAuthenticationMechanism
|
||||
{
|
||||
private static final String SESSION_COOKIE = "session";
|
||||
|
||||
@Override
|
||||
public Uni<SecurityIdentity> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager)
|
||||
{
|
||||
|
||||
@ -11,7 +11,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@ApplicationScoped
|
||||
@IfBuildProfile("test")
|
||||
@IfBuildProfile("x")
|
||||
public class Dev
|
||||
{
|
||||
@Inject
|
||||
|
||||
@ -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")
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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<UsernamePasswordAuthenticationRequest>
|
||||
{
|
||||
private static final BCrypt.Verifyer VERIFIER = BCrypt.verifyer();
|
||||
|
||||
@Inject
|
||||
TokenRepo tokenRepo;
|
||||
|
||||
@ -41,7 +42,7 @@ public class TokenIdentityProvider implements IdentityProvider<UsernamePasswordA
|
||||
String password = new String(request.getPassword().getPassword());
|
||||
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();
|
||||
if (!now.isAfter(token.getExpiresAt()))
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package dev.dinauer.maven.app;
|
||||
|
||||
import dev.dinauer.maven.jpa.maven.repo.VersionRepo;
|
||||
import dev.dinauer.maven.user.User;
|
||||
import dev.dinauer.maven.jpa.maven.Version;
|
||||
import dev.dinauer.maven.jpa.maven.repo.ArtifactRepo;
|
||||
@ -27,9 +26,6 @@ public class ArtifactResource
|
||||
@RestClient
|
||||
UserClient userClient;
|
||||
|
||||
@Inject
|
||||
VersionRepo versionRepo;
|
||||
|
||||
@GET
|
||||
public List<ArtifactId> get()
|
||||
{
|
||||
|
||||
72
src/main/java/dev/dinauer/maven/maven/core/JarService.java
Normal file
72
src/main/java/dev/dinauer/maven/maven/core/JarService.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
|
||||
47
src/main/java/dev/dinauer/maven/maven/core/PomService.java
Normal file
47
src/main/java/dev/dinauer/maven/maven/core/PomService.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@ -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<Jar> 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 ->
|
||||
{
|
||||
|
||||
@ -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<Version> 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()));
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -27,3 +24,6 @@ quarkus.oidc-client.client-id=backend
|
||||
quarkus.oidc-client.credentials.secret=backend
|
||||
|
||||
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
|
||||
101
src/main/resources/db/migration/V1.0.0__init.sql
Normal file
101
src/main/resources/db/migration/V1.0.0__init.sql
Normal 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
|
||||
);
|
||||
|
||||
52
src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java
Normal file
52
src/test/java/dev/dinauer/maven/maven/core/ResourceTest.java
Normal 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);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user