🎨 Add formatter and format
This commit is contained in:
parent
23667410a7
commit
b44c333ae4
37
format.xml
Normal file
37
format.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="format" version="12">
|
||||
<!-- General code formatting settings -->
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
|
||||
<!-- Braces in new line -->
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line"/>
|
||||
|
||||
<!-- Spaces after keywords -->
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_keyword_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_keyword_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_keyword_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_keyword_in_switch" value="insert"/>
|
||||
|
||||
<!-- Else-if-statement -->
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||
|
||||
<!-- Switch-statement -->
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
|
||||
<!-- No Line Wrapping -->
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="9999"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
18
pom.xml
18
pom.xml
@ -134,6 +134,24 @@
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.revelc.code.formatter</groupId>
|
||||
<artifactId>formatter-maven-plugin</artifactId>
|
||||
<version>2.29.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>format</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<configFile>format.xml</configFile>
|
||||
<lineEnding>LF</lineEnding>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@ -1,20 +1,14 @@
|
||||
package dev.dinauer.metrics.service;
|
||||
|
||||
import dev.dinauer.metrics.service.client.AuthenticationService;
|
||||
import dev.dinauer.metrics.service.client.auth.AuthenticationService;
|
||||
import dev.dinauer.metrics.service.model.BucketUnit;
|
||||
import dev.dinauer.metrics.service.model.Collection;
|
||||
import io.quarkus.security.UnauthorizedException;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import jakarta.ws.rs.*;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalLong;
|
||||
|
||||
@Path("/{resource}/{metric}")
|
||||
public class Resource
|
||||
|
||||
@ -1,113 +0,0 @@
|
||||
package dev.dinauer.metrics.service.client;
|
||||
|
||||
import io.quarkus.elytron.security.common.BcryptUtil;
|
||||
import io.quarkus.security.UnauthorizedException;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
@RequestScoped
|
||||
public class AuthenticationService
|
||||
{
|
||||
@Context
|
||||
HttpHeaders headers;
|
||||
|
||||
@Inject
|
||||
ClientRepo clientRepo;
|
||||
|
||||
public boolean canWrite()
|
||||
{
|
||||
AuthHeader authHeader = getAuthHeader();
|
||||
switch (authHeader.type())
|
||||
{
|
||||
case AuthType.BASIC ->
|
||||
{
|
||||
BasicAuthCredentials credentials = getCredentials(authHeader.credentials());
|
||||
Client client = getClient(credentials);
|
||||
return Permission.RW.equals(client.permission());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canRead()
|
||||
{
|
||||
AuthHeader authHeader = getAuthHeader();
|
||||
switch (authHeader.type())
|
||||
{
|
||||
case AuthType.BASIC ->
|
||||
{
|
||||
BasicAuthCredentials credentials = getCredentials(authHeader.credentials());
|
||||
Client client = getClient(credentials);
|
||||
return List.of(Permission.RO, Permission.RW).contains(client.permission());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private AuthHeader getAuthHeader()
|
||||
{
|
||||
String authHeader = headers.getHeaderString("Authorization");
|
||||
if (authHeader != null)
|
||||
{
|
||||
String[] sections = authHeader.split("\\s+");
|
||||
if (sections.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new AuthHeader(AuthType.valueOf(sections[0].toUpperCase()), sections[1]);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
private BasicAuthCredentials getCredentials(String base64Credentials)
|
||||
{
|
||||
String credentials = new String(Base64.getDecoder().decode(base64Credentials));
|
||||
String[] credentialSections = credentials.split(":");
|
||||
if (credentialSections.length == 2)
|
||||
{
|
||||
String clientId = credentialSections[0];
|
||||
String password = credentialSections[1];
|
||||
return new BasicAuthCredentials(clientId, password);
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
private Client getClient(BasicAuthCredentials credentials)
|
||||
{
|
||||
Client client = clientRepo.findById(credentials.clientId());
|
||||
if (client != null)
|
||||
{
|
||||
if (BcryptUtil.matches(credentials.password(), client.password()))
|
||||
{
|
||||
return client;
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
private record AuthHeader(AuthType type, String credentials)
|
||||
{
|
||||
}
|
||||
|
||||
private enum AuthType
|
||||
{
|
||||
BASIC, BEARER
|
||||
}
|
||||
|
||||
private record BasicAuthCredentials(String clientId, String password)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,7 @@ package dev.dinauer.metrics.service.client;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record Client(String id, String password, Permission permission)
|
||||
{
|
||||
public record Client(String id, String password, Permission permission) {
|
||||
@Override
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
|
||||
@ -13,7 +13,7 @@ import java.util.List;
|
||||
@ApplicationScoped
|
||||
public class ClientRepo
|
||||
{
|
||||
private final static String CLIENT_PROPERTY_PREFIX= "dev.dinauer.metrics-service.client";
|
||||
private final static String CLIENT_PROPERTY_PREFIX = "dev.dinauer.metrics-service.client";
|
||||
|
||||
List<Client> clients;
|
||||
|
||||
|
||||
@ -2,5 +2,5 @@ package dev.dinauer.metrics.service.client;
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
RW, RO
|
||||
RW, RO, WO
|
||||
}
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
package dev.dinauer.metrics.service.client.auth;
|
||||
|
||||
import dev.dinauer.metrics.service.client.Client;
|
||||
import dev.dinauer.metrics.service.client.Permission;
|
||||
import dev.dinauer.metrics.service.client.auth.utils.AuthHeader;
|
||||
import dev.dinauer.metrics.service.client.auth.utils.AuthType;
|
||||
import io.quarkus.security.UnauthorizedException;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RequestScoped
|
||||
public class AuthenticationService
|
||||
{
|
||||
private static final List<Permission> READ_PERMISSIONS = List.of(Permission.RO, Permission.RW);
|
||||
private static final List<Permission> WRITE_PERMISSIONS = List.of(Permission.WO, Permission.RW);
|
||||
|
||||
@Context
|
||||
HttpHeaders headers;
|
||||
|
||||
@Inject
|
||||
BasicAuthClientProvider basicAuthClientProvider;
|
||||
|
||||
@Inject
|
||||
BearerAuthClientProvider bearerAuthClientProvider;
|
||||
|
||||
public boolean canWrite()
|
||||
{
|
||||
return WRITE_PERMISSIONS.contains(getClient().permission());
|
||||
}
|
||||
|
||||
public boolean canRead()
|
||||
{
|
||||
return READ_PERMISSIONS.contains(getClient().permission());
|
||||
}
|
||||
|
||||
private Client getClient()
|
||||
{
|
||||
AuthHeader header = getAuthHeader();
|
||||
switch (header.type())
|
||||
{
|
||||
case BASIC -> {
|
||||
return basicAuthClientProvider.get(header.credentials());
|
||||
}
|
||||
case BEARER -> {
|
||||
return bearerAuthClientProvider.get(header.credentials());
|
||||
}
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
private AuthHeader getAuthHeader()
|
||||
{
|
||||
String authHeader = headers.getHeaderString("Authorization");
|
||||
if (authHeader != null)
|
||||
{
|
||||
String[] sections = authHeader.split("\\s+");
|
||||
if (sections.length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new AuthHeader(AuthType.valueOf(sections[0].toUpperCase()), sections[1]);
|
||||
} catch (IllegalArgumentException e)
|
||||
{
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package dev.dinauer.metrics.service.client.auth;
|
||||
|
||||
import dev.dinauer.metrics.service.client.Client;
|
||||
import dev.dinauer.metrics.service.client.ClientRepo;
|
||||
import dev.dinauer.metrics.service.client.auth.utils.BasicAuthCredentials;
|
||||
import io.quarkus.elytron.security.common.BcryptUtil;
|
||||
import io.quarkus.security.UnauthorizedException;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
@ApplicationScoped
|
||||
public class BasicAuthClientProvider
|
||||
{
|
||||
@Inject
|
||||
ClientRepo clientRepo;
|
||||
|
||||
public Client get(String credentials)
|
||||
{
|
||||
BasicAuthCredentials basicAuthCredentials = getCredentials(credentials);
|
||||
Client client = clientRepo.findById(basicAuthCredentials.clientId());
|
||||
if (client != null)
|
||||
{
|
||||
if (BcryptUtil.matches(basicAuthCredentials.password(), client.password()))
|
||||
{
|
||||
return client;
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
private BasicAuthCredentials getCredentials(String base64Credentials)
|
||||
{
|
||||
String credentials = new String(Base64.getDecoder().decode(base64Credentials));
|
||||
String[] credentialSections = credentials.split(":");
|
||||
if (credentialSections.length == 2)
|
||||
{
|
||||
String clientId = credentialSections[0];
|
||||
String password = credentialSections[1];
|
||||
return new BasicAuthCredentials(clientId, password);
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package dev.dinauer.metrics.service.client.auth;
|
||||
|
||||
import dev.dinauer.metrics.service.client.Client;
|
||||
import dev.dinauer.metrics.service.client.Permission;
|
||||
import io.quarkus.security.UnauthorizedException;
|
||||
import io.smallrye.jwt.auth.principal.JWTParser;
|
||||
import io.smallrye.jwt.auth.principal.ParseException;
|
||||
import io.smallrye.jwt.build.Jwt;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ApplicationScoped
|
||||
public class BearerAuthClientProvider
|
||||
{
|
||||
@Inject
|
||||
JWTParser parser;
|
||||
|
||||
@ConfigProperty(name = "dev.dinauer.metrics-service.jwt.client.field")
|
||||
String clientIdField;
|
||||
|
||||
public Client get(String credentials)
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonWebToken token = parser.parse(credentials);
|
||||
if (token != null)
|
||||
{
|
||||
Optional<String> user = token.claim(clientIdField);
|
||||
if (user.isPresent())
|
||||
{
|
||||
return new Client(user.get(), null, Permission.RO);
|
||||
}
|
||||
}
|
||||
throw new UnauthorizedException();
|
||||
} catch (ParseException e)
|
||||
{
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package dev.dinauer.metrics.service.client.auth.utils;
|
||||
|
||||
public record AuthHeader(AuthType type, String credentials) {
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
package dev.dinauer.metrics.service.client.auth.utils;
|
||||
|
||||
public enum AuthType
|
||||
{
|
||||
BASIC, BEARER
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package dev.dinauer.metrics.service.client.auth.utils;
|
||||
|
||||
public record BasicAuthCredentials(String clientId, String password) {
|
||||
}
|
||||
@ -84,8 +84,7 @@ public class Collection
|
||||
try
|
||||
{
|
||||
this.metrics = OBJECT_MAPPER.writeValueAsString(metrics);
|
||||
}
|
||||
catch (JsonProcessingException e)
|
||||
} catch (JsonProcessingException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -124,9 +123,10 @@ public class Collection
|
||||
{
|
||||
try
|
||||
{
|
||||
return OBJECT_MAPPER.readValue(metrics, new TypeReference<Map<String, Metric>>() {});
|
||||
}
|
||||
catch (JsonProcessingException e)
|
||||
return OBJECT_MAPPER.readValue(metrics, new TypeReference<Map<String, Metric>>()
|
||||
{
|
||||
});
|
||||
} catch (JsonProcessingException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@ -14,19 +14,19 @@ public class TimestampGenerator
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case BucketUnit.RAW ->
|
||||
case BucketUnit.RAW:
|
||||
{
|
||||
return timestamp.format(DateTimeFormatter.ISO_DATE_TIME).substring(0, 19);
|
||||
}
|
||||
case BucketUnit.HOURLY ->
|
||||
case BucketUnit.HOURLY:
|
||||
{
|
||||
return timestamp.format(DateTimeFormatter.ISO_DATE_TIME).substring(0, 13);
|
||||
}
|
||||
case BucketUnit.DAILY ->
|
||||
case BucketUnit.DAILY:
|
||||
{
|
||||
return timestamp.format(DateTimeFormatter.ISO_DATE_TIME).substring(0, 10);
|
||||
}
|
||||
case BucketUnit.WEEKLY ->
|
||||
case BucketUnit.WEEKLY:
|
||||
{
|
||||
String week = String.valueOf(timestamp.get(WeekFields.ISO.weekOfWeekBasedYear()));
|
||||
String year = String.valueOf(timestamp.get(WeekFields.ISO.weekBasedYear()));
|
||||
@ -35,15 +35,15 @@ public class TimestampGenerator
|
||||
String yearString = "0".repeat(4 - year.length()).concat(year);
|
||||
return String.format("%s-W%s", yearString, weekString);
|
||||
}
|
||||
case BucketUnit.MONTHLY ->
|
||||
case BucketUnit.MONTHLY:
|
||||
{
|
||||
return timestamp.format(DateTimeFormatter.ISO_DATE_TIME).substring(0, 7);
|
||||
}
|
||||
case BucketUnit.YEARLY ->
|
||||
case BucketUnit.YEARLY:
|
||||
{
|
||||
return timestamp.format(DateTimeFormatter.ISO_DATE_TIME).substring(0, 4);
|
||||
}
|
||||
case BucketUnit.TOTAL ->
|
||||
case BucketUnit.TOTAL:
|
||||
{
|
||||
return "TOTAL";
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ quarkus.http.root-path=/api/metrics
|
||||
dev.dinauer.metrics-service.buckets=RAW,HOURLY,DAILY,WEEKLY,MONTHLY,YEARLY,TOTAL
|
||||
|
||||
dev.dinauer.metrics-service.client.kubooboo.ro=3749832748923748923
|
||||
dev.dinauer.metrics-service.jwt.client.field=upn
|
||||
|
||||
# JWT
|
||||
mp.jwt.verify.publickey.location=dev/publicKey.pem
|
||||
|
||||
@ -3,6 +3,7 @@ package dev.dinauer;
|
||||
import io.quarkus.test.junit.QuarkusIntegrationTest;
|
||||
|
||||
@QuarkusIntegrationTest
|
||||
class GreetingResourceIT extends GreetingResourceTest {
|
||||
class GreetingResourceIT extends GreetingResourceTest
|
||||
{
|
||||
// Execute the same tests but in packaged mode.
|
||||
}
|
||||
|
||||
@ -7,14 +7,12 @@ import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
@QuarkusTest
|
||||
class GreetingResourceTest {
|
||||
class GreetingResourceTest
|
||||
{
|
||||
@Test
|
||||
void testHelloEndpoint() {
|
||||
given()
|
||||
.when().get("/hello")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("Hello from Quarkus REST"));
|
||||
void testHelloEndpoint()
|
||||
{
|
||||
given().when().get("/hello").then().statusCode(200).body(is("Hello from Quarkus REST"));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user