diff --git a/pom.xml b/pom.xml
index 7a2e2fe..d0a3708 100644
--- a/pom.xml
+++ b/pom.xml
@@ -131,6 +131,12 @@
spring-security-test
test
+
+ org.jetbrains
+ annotations
+ 13.0
+ compile
+
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/AuditLogDataSourceConfig.java b/src/main/java/dev/kruhlmann/imgfloat/config/AuditLogDataSourceConfig.java
index f7e33c4..e6dfb2d 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/AuditLogDataSourceConfig.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/AuditLogDataSourceConfig.java
@@ -11,16 +11,18 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
-import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
+@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "dev.kruhlmann.imgfloat.repository.audit",
entityManagerFactoryRef = "auditEntityManagerFactory",
@@ -36,9 +38,7 @@ public class AuditLogDataSourceConfig {
@Bean
@ConfigurationProperties("imgfloat.audit.datasource.hikari")
- public HikariDataSource auditDataSource(
- @Qualifier("auditDataSourceProperties") DataSourceProperties properties
- ) {
+ public HikariDataSource auditDataSource(@Qualifier("auditDataSourceProperties") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/PrimaryDataSourceConfig.java b/src/main/java/dev/kruhlmann/imgfloat/config/PrimaryDataSourceConfig.java
index 0a3848f..4dad34a 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/PrimaryDataSourceConfig.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/PrimaryDataSourceConfig.java
@@ -27,9 +27,7 @@ import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableJpaRepositories(
basePackages = "dev.kruhlmann.imgfloat.repository",
- excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AuditLogRepository.class),
- entityManagerFactoryRef = "entityManagerFactory",
- transactionManagerRef = "transactionManager"
+ excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AuditLogRepository.class)
)
public class PrimaryDataSourceConfig {
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/SQLiteOAuth2AuthorizedClientService.java b/src/main/java/dev/kruhlmann/imgfloat/config/SQLiteOAuth2AuthorizedClientService.java
index c89d36f..f551fbd 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/SQLiteOAuth2AuthorizedClientService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/SQLiteOAuth2AuthorizedClientService.java
@@ -24,7 +24,6 @@ public class SQLiteOAuth2AuthorizedClientService implements OAuth2AuthorizedClie
private static final String TABLE_NAME = "oauth2_authorized_client";
private final JdbcOperations jdbcOperations;
- private final ClientRegistrationRepository clientRegistrationRepository;
private final RowMapper rowMapper;
private final OAuthTokenCipher tokenCipher;
@@ -41,7 +40,6 @@ public class SQLiteOAuth2AuthorizedClientService implements OAuth2AuthorizedClie
OAuthTokenCipher tokenCipher
) {
this.jdbcOperations = jdbcOperations;
- this.clientRegistrationRepository = clientRegistrationRepository;
this.tokenCipher = tokenCipher;
this.rowMapper = (rs, rowNum) -> {
String registrationId = rs.getString("client_registration_id");
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/SecurityConfig.java b/src/main/java/dev/kruhlmann/imgfloat/config/SecurityConfig.java
index d6e2562..e1f387f 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/SecurityConfig.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/SecurityConfig.java
@@ -4,6 +4,7 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
@@ -154,11 +155,12 @@ public class SecurityConfig {
@Bean
OncePerRequestFilter csrfTokenCookieFilter() {
return new OncePerRequestFilter() {
+ @NotNull
@Override
protected void doFilterInternal(
- HttpServletRequest request,
- HttpServletResponse response,
- FilterChain filterChain
+ @NotNull HttpServletRequest request,
+ @NotNull HttpServletResponse response,
+ @NotNull FilterChain filterChain
) throws java.io.IOException, jakarta.servlet.ServletException {
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
if (csrfToken == null) {
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/SystemEnvironmentValidator.java b/src/main/java/dev/kruhlmann/imgfloat/config/SystemEnvironmentValidator.java
index 3a3dbf0..2110cbf 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/SystemEnvironmentValidator.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/SystemEnvironmentValidator.java
@@ -52,9 +52,6 @@ public class SystemEnvironmentValidator {
@Value("${IMGFLOAT_GITHUB_CLIENT_VERSION:#{null}}")
private String githubClientVersion;
- private long maxUploadBytes;
- private long maxRequestBytes;
-
public SystemEnvironmentValidator(Environment environment) {
this.environment = environment;
}
@@ -72,8 +69,8 @@ public class SystemEnvironmentValidator {
StringBuilder missing = new StringBuilder();
- maxUploadBytes = DataSize.parse(springMaxFileSize).toBytes();
- maxRequestBytes = DataSize.parse(springMaxRequestSize).toBytes();
+ long maxUploadBytes = DataSize.parse(springMaxFileSize).toBytes();
+ long maxRequestBytes = DataSize.parse(springMaxRequestSize).toBytes();
checkUnsignedNumeric(maxUploadBytes, "SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE", missing);
checkUnsignedNumeric(maxRequestBytes, "SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE", missing);
checkString(twitchClientId, "TWITCH_CLIENT_ID", missing);
@@ -107,7 +104,7 @@ public class SystemEnvironmentValidator {
}
private void checkString(String value, String name, StringBuilder missing) {
- if (value != null && StringUtils.hasText(value)) {
+ if (StringUtils.hasText(value)) {
return;
}
missing.append(" - ").append(name).append("\n");
@@ -121,7 +118,7 @@ public class SystemEnvironmentValidator {
}
private String redact(String value) {
- if (value != null && StringUtils.hasText(value)) {
+ if (StringUtils.hasText(value)) {
return "**************";
}
return "";
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverter.java b/src/main/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverter.java
index a14f9f7..52ca7d9 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverter.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverter.java
@@ -27,6 +27,7 @@ final class TwitchAuthorizationCodeGrantRequestEntityConverter
@Override
public @Nullable RequestEntity> convert(@Nullable OAuth2AuthorizationCodeGrantRequest request) {
+ assert request != null;
RequestEntity> entity = delegate.convert(request);
if (entity == null || !(entity.getBody() instanceof MultiValueMap, ?> existingBody)) {
return entity;
diff --git a/src/main/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandler.java b/src/main/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandler.java
index 88659a3..03b78f1 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandler.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandler.java
@@ -3,6 +3,8 @@ package dev.kruhlmann.imgfloat.config;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.ClientHttpResponse;
@@ -58,26 +60,15 @@ class TwitchOAuth2ErrorResponseErrorHandler extends OAuth2ErrorResponseErrorHand
return new OAuth2AuthorizationException(oauth2Error, ex);
}
- private static final class CachedBodyClientHttpResponse implements ClientHttpResponse {
-
- private final ClientHttpResponse delegate;
- private final byte[] body;
-
- private CachedBodyClientHttpResponse(ClientHttpResponse delegate, byte[] body) {
- this.delegate = delegate;
- this.body = body;
- }
+ private record CachedBodyClientHttpResponse(ClientHttpResponse delegate, byte[] body) implements ClientHttpResponse {
+ @NotNull
@Override
public org.springframework.http.HttpStatusCode getStatusCode() throws IOException {
return delegate.getStatusCode();
}
- @Override
- public int getRawStatusCode() throws IOException {
- return delegate.getRawStatusCode();
- }
-
+ @NotNull
@Override
public String getStatusText() throws IOException {
return delegate.getStatusText();
@@ -88,11 +79,13 @@ class TwitchOAuth2ErrorResponseErrorHandler extends OAuth2ErrorResponseErrorHand
delegate.close();
}
+ @NotNull
@Override
- public java.io.InputStream getBody() throws IOException {
+ public java.io.InputStream getBody() {
return new ByteArrayInputStream(body);
}
+ @NotNull
@Override
public org.springframework.http.HttpHeaders getHeaders() {
return delegate.getHeaders();
diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/ChannelApiController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/ChannelApiController.java
index 52b1d0e..d6b8777 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/controller/ChannelApiController.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/controller/ChannelApiController.java
@@ -1,7 +1,6 @@
package dev.kruhlmann.imgfloat.controller;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
-import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import dev.kruhlmann.imgfloat.model.api.request.AdminRequest;
@@ -32,10 +31,13 @@ import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
+import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
+import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
+import org.springframework.security.oauth2.core.AbstractOAuth2Token;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -83,10 +85,10 @@ public class ChannelApiController {
String sessionUsername = OauthSessionUser.from(oauthToken).login();
String logBroadcaster = LogSanitizer.sanitize(broadcaster);
String logSessionUsername = LogSanitizer.sanitize(sessionUsername);
- String logRequestUsername = LogSanitizer.sanitize(request.getUsername());
+ String logRequestUsername = LogSanitizer.sanitize(request.username());
authorizationService.userMatchesSessionUsernameOrThrowHttpError(broadcaster, sessionUsername);
LOG.info("User {} adding admin {} to {}", logSessionUsername, logRequestUsername, logBroadcaster);
- boolean added = channelDirectoryService.addAdmin(broadcaster, request.getUsername(), sessionUsername);
+ boolean added = channelDirectoryService.addAdmin(broadcaster, request.username(), sessionUsername);
if (!added) {
LOG.info("User {} already admin for {} or could not be added", logRequestUsername, logBroadcaster);
}
@@ -106,14 +108,14 @@ public class ChannelApiController {
LOG.debug("Listing admins for {} by {}", logBroadcaster, logSessionUsername);
var channel = channelDirectoryService.getOrCreateChannel(broadcaster);
List admins = channel.getAdmins().stream().sorted(Comparator.naturalOrder()).toList();
- OAuth2AuthorizedClient authorizedClient = resolveAuthorizedClient(oauthToken, null, request);
+ OAuth2AuthorizedClient authorizedClient = resolveAuthorizedClient(oauthToken, request);
String accessToken = Optional.ofNullable(authorizedClient)
.map(OAuth2AuthorizedClient::getAccessToken)
- .map((token) -> token.getTokenValue())
+ .map(AbstractOAuth2Token::getTokenValue)
.orElse(null);
String clientId = Optional.ofNullable(authorizedClient)
.map(OAuth2AuthorizedClient::getClientRegistration)
- .map((registration) -> registration.getClientId())
+ .map(ClientRegistration::getClientId)
.orElse(null);
return twitchUserLookupService.fetchProfiles(admins, accessToken, clientId);
}
@@ -130,7 +132,7 @@ public class ChannelApiController {
authorizationService.userMatchesSessionUsernameOrThrowHttpError(broadcaster, sessionUsername);
LOG.debug("Listing admin suggestions for {} by {}", logBroadcaster, logSessionUsername);
var channel = channelDirectoryService.getOrCreateChannel(broadcaster);
- OAuth2AuthorizedClient authorizedClient = resolveAuthorizedClient(oauthToken, null, request);
+ OAuth2AuthorizedClient authorizedClient = resolveAuthorizedClient(oauthToken, request);
if (authorizedClient == null) {
LOG.warn(
@@ -140,13 +142,13 @@ public class ChannelApiController {
);
return List.of();
}
- String accessToken = Optional.ofNullable(authorizedClient)
+ String accessToken = Optional.of(authorizedClient)
.map(OAuth2AuthorizedClient::getAccessToken)
- .map((token) -> token.getTokenValue())
+ .map(AbstractOAuth2Token::getTokenValue)
.orElse(null);
- String clientId = Optional.ofNullable(authorizedClient)
+ String clientId = Optional.of(authorizedClient)
.map(OAuth2AuthorizedClient::getClientRegistration)
- .map((registration) -> registration.getClientId())
+ .map(ClientRegistration::getClientId)
.orElse(null);
if (accessToken == null || accessToken.isBlank() || clientId == null || clientId.isBlank()) {
LOG.warn(
@@ -406,7 +408,7 @@ public class ChannelApiController {
.contentType(MediaType.parseMediaType(content.mediaType()))
.body(content.bytes())
)
- .orElseThrow(() -> createAsset404());
+ .orElseThrow(this::createAsset404);
}
@GetMapping("/script-assets/{assetId}/attachments/{attachmentId}/content")
@@ -433,7 +435,7 @@ public class ChannelApiController {
.contentType(MediaType.parseMediaType(content.mediaType()))
.body(content.bytes())
)
- .orElseThrow(() -> createAsset404());
+ .orElseThrow(this::createAsset404);
}
@GetMapping("/assets/{assetId}/logo")
@@ -456,7 +458,7 @@ public class ChannelApiController {
.contentType(MediaType.parseMediaType(content.mediaType()))
.body(content.bytes())
)
- .orElseThrow(() -> createAsset404());
+ .orElseThrow(this::createAsset404);
}
@GetMapping("/assets/{assetId}/preview")
@@ -475,13 +477,12 @@ public class ChannelApiController {
.contentType(MediaType.parseMediaType(content.mediaType()))
.body(content.bytes())
)
- .orElseThrow(() -> createAsset404());
+ .orElseThrow(this::createAsset404);
}
private String contentDispositionFor(String mediaType) {
if (
- mediaType != null &&
- dev.kruhlmann.imgfloat.service.media.MediaDetectionService.isInlineDisplayType(mediaType)
+ dev.kruhlmann.imgfloat.service.media.MediaDetectionService.isInlineDisplayType(mediaType)
) {
return "inline";
}
@@ -616,14 +617,11 @@ public class ChannelApiController {
}
private OAuth2AuthorizedClient resolveAuthorizedClient(
- OAuth2AuthenticationToken oauthToken,
- OAuth2AuthorizedClient authorizedClient,
+ @Nullable OAuth2AuthenticationToken oauthToken,
HttpServletRequest request
) {
- if (authorizedClient != null) {
- return authorizedClient;
- }
if (oauthToken == null) {
+ LOG.error("Attempt to resolve authorized client without oauth token");
return null;
}
OAuth2AuthorizedClient sessionClient = authorizedClientRepository.loadAuthorizedClient(
diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/ScriptMarketplaceController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/ScriptMarketplaceController.java
index 07135b9..abc1621 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/controller/ScriptMarketplaceController.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/controller/ScriptMarketplaceController.java
@@ -78,14 +78,14 @@ public class ScriptMarketplaceController {
) {
String sessionUsername = OauthSessionUser.from(oauthToken).login();
authorizationService.userIsBroadcasterOrChannelAdminForBroadcasterOrThrowHttpError(
- request.getTargetBroadcaster(),
+ request.targetBroadcaster(),
sessionUsername
);
String logScriptId = LogSanitizer.sanitize(scriptId);
- String logTarget = LogSanitizer.sanitize(request.getTargetBroadcaster());
+ String logTarget = LogSanitizer.sanitize(request.targetBroadcaster());
LOG.info("Importing marketplace script {} into {}", logScriptId, logTarget);
return channelDirectoryService
- .importMarketplaceScript(request.getTargetBroadcaster(), scriptId, sessionUsername)
+ .importMarketplaceScript(request.targetBroadcaster(), scriptId, sessionUsername)
.map(ResponseEntity::ok)
.orElseThrow(() -> new ResponseStatusException(BAD_REQUEST, "Unable to import script"));
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java
index c869f3b..eb964eb 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java
@@ -39,7 +39,7 @@ public class SettingsApiController {
authorizationService.userIsSystemAdministratorOrThrowHttpError(sessionUsername);
Settings currentSettings = settingsService.get();
- LOG.info("Sytem administrator settings change request");
+ LOG.info("System administrator settings change request");
settingsService.logSettings("From: ", currentSettings);
settingsService.logSettings("To: ", newSettings);
diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java
index 6234ec0..94455a7 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java
@@ -83,14 +83,6 @@ public class ViewController {
return "index";
}
- @org.springframework.web.bind.annotation.GetMapping("/channels")
- public String channelDirectory(Model model) {
- LOG.info("Rendering channel directory");
- addStagingAttribute(model);
- addVersionAttributes(model);
- return "channels";
- }
-
@org.springframework.web.bind.annotation.GetMapping("/terms")
public String termsOfUse(Model model) {
LOG.info("Rendering terms of use");
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/AdminRequest.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/AdminRequest.java
index 81ea3a9..1968c78 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/AdminRequest.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/AdminRequest.java
@@ -2,16 +2,4 @@ package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.NotBlank;
-public class AdminRequest {
-
- @NotBlank
- private String username;
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-}
+public record AdminRequest(@NotBlank String username) {}
\ No newline at end of file
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CanvasSettingsRequest.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CanvasSettingsRequest.java
index 8eef4a2..e14e814 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CanvasSettingsRequest.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CanvasSettingsRequest.java
@@ -5,12 +5,10 @@ import jakarta.validation.constraints.Positive;
public class CanvasSettingsRequest {
@Positive
- private double width;
+ private final double width;
@Positive
- private double height;
-
- public CanvasSettingsRequest() {}
+ private final double height;
public CanvasSettingsRequest(double width, double height) {
this.width = width;
@@ -21,15 +19,8 @@ public class CanvasSettingsRequest {
return width;
}
- public void setWidth(double width) {
- this.width = width;
- }
-
public double getHeight() {
return height;
}
- public void setHeight(double height) {
- this.height = height;
- }
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ChannelScriptSettingsRequest.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ChannelScriptSettingsRequest.java
index 1ca47db..0483ee7 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ChannelScriptSettingsRequest.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ChannelScriptSettingsRequest.java
@@ -6,8 +6,6 @@ public class ChannelScriptSettingsRequest {
private boolean allowSevenTvEmotesForAssets = true;
private boolean allowScriptChatAccess = true;
- public ChannelScriptSettingsRequest() {}
-
public ChannelScriptSettingsRequest(
boolean allowChannelEmotesForAssets,
boolean allowSevenTvEmotesForAssets,
@@ -22,23 +20,12 @@ public class ChannelScriptSettingsRequest {
return allowChannelEmotesForAssets;
}
- public void setAllowChannelEmotesForAssets(boolean allowChannelEmotesForAssets) {
- this.allowChannelEmotesForAssets = allowChannelEmotesForAssets;
- }
-
public boolean isAllowSevenTvEmotesForAssets() {
return allowSevenTvEmotesForAssets;
}
- public void setAllowSevenTvEmotesForAssets(boolean allowSevenTvEmotesForAssets) {
- this.allowSevenTvEmotesForAssets = allowSevenTvEmotesForAssets;
- }
-
public boolean isAllowScriptChatAccess() {
return allowScriptChatAccess;
}
- public void setAllowScriptChatAccess(boolean allowScriptChatAccess) {
- this.allowScriptChatAccess = allowScriptChatAccess;
- }
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CodeAssetRequest.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CodeAssetRequest.java
index c2d7cf3..e12401c 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CodeAssetRequest.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/CodeAssetRequest.java
@@ -1,5 +1,6 @@
package dev.kruhlmann.imgfloat.model.api.request;
+import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotBlank;
public class CodeAssetRequest {
@@ -12,6 +13,7 @@ public class CodeAssetRequest {
private String description;
+ @Nullable
private Boolean isPublic;
private java.util.List allowedDomains;
@@ -40,14 +42,11 @@ public class CodeAssetRequest {
this.description = description;
}
+ @Nullable
public Boolean getIsPublic() {
return isPublic;
}
- public void setIsPublic(Boolean isPublic) {
- this.isPublic = isPublic;
- }
-
public java.util.List getAllowedDomains() {
return allowedDomains;
}
@@ -55,4 +54,8 @@ public class CodeAssetRequest {
public void setAllowedDomains(java.util.List allowedDomains) {
this.allowedDomains = allowedDomains;
}
+
+ public void setPublic(@Nullable Boolean aPublic) {
+ isPublic = aPublic;
+ }
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ScriptMarketplaceImportRequest.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ScriptMarketplaceImportRequest.java
index 4e74947..6c19f68 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ScriptMarketplaceImportRequest.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/ScriptMarketplaceImportRequest.java
@@ -2,16 +2,4 @@ package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.NotBlank;
-public class ScriptMarketplaceImportRequest {
-
- @NotBlank
- private String targetBroadcaster;
-
- public String getTargetBroadcaster() {
- return targetBroadcaster;
- }
-
- public void setTargetBroadcaster(String targetBroadcaster) {
- this.targetBroadcaster = targetBroadcaster;
- }
-}
+public record ScriptMarketplaceImportRequest(@NotBlank String targetBroadcaster) { }
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/TransformRequest.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/TransformRequest.java
index 7b13869..c6e6a3d 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/request/TransformRequest.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/request/TransformRequest.java
@@ -112,34 +112,18 @@ public class TransformRequest {
return audioLoop;
}
- public void setAudioLoop(Boolean audioLoop) {
- this.audioLoop = audioLoop;
- }
-
public Integer getAudioDelayMillis() {
return audioDelayMillis;
}
- public void setAudioDelayMillis(Integer audioDelayMillis) {
- this.audioDelayMillis = audioDelayMillis;
- }
-
public Double getAudioSpeed() {
return audioSpeed;
}
- public void setAudioSpeed(Double audioSpeed) {
- this.audioSpeed = audioSpeed;
- }
-
public Double getAudioPitch() {
return audioPitch;
}
- public void setAudioPitch(Double audioPitch) {
- this.audioPitch = audioPitch;
- }
-
public Double getAudioVolume() {
return audioVolume;
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/api/response/CanvasEvent.java b/src/main/java/dev/kruhlmann/imgfloat/model/api/response/CanvasEvent.java
index 3a62fb8..3af8118 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/api/response/CanvasEvent.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/api/response/CanvasEvent.java
@@ -19,15 +19,4 @@ public class CanvasEvent {
return event;
}
- public Type getType() {
- return type;
- }
-
- public String getChannel() {
- return channel;
- }
-
- public CanvasSettingsRequest getPayload() {
- return payload;
- }
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Asset.java b/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Asset.java
index d3f5984..39a23f0 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Asset.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Asset.java
@@ -83,26 +83,14 @@ public class Asset {
return assetType == null ? AssetType.OTHER : assetType;
}
- public void setAssetType(AssetType assetType) {
- this.assetType = assetType == null ? AssetType.OTHER : assetType;
- }
-
public Instant getCreatedAt() {
return createdAt;
}
- public void setCreatedAt(Instant createdAt) {
- this.createdAt = createdAt;
- }
-
public Instant getUpdatedAt() {
return updatedAt;
}
- public void setUpdatedAt(Instant updatedAt) {
- this.updatedAt = updatedAt;
- }
-
public Integer getDisplayOrder() {
return displayOrder;
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Channel.java b/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Channel.java
index dfe8cff..b30852f 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Channel.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/Channel.java
@@ -15,7 +15,6 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
-import java.util.stream.Collectors;
@Entity
@Table(name = "channels")
@@ -27,7 +26,7 @@ public class Channel {
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "channel_admins", joinColumns = @JoinColumn(name = "channel_id"))
@Column(name = "admin_username")
- private Set admins = new HashSet<>();
+ private final Set admins = new HashSet<>();
private double canvasWidth = 1920;
@@ -52,8 +51,6 @@ public class Channel {
public Channel(String broadcaster) {
this.broadcaster = normalize(broadcaster);
- this.canvasWidth = 1920;
- this.canvasHeight = 1080;
}
public String getBroadcaster() {
@@ -112,24 +109,6 @@ public class Channel {
this.allowScriptChatAccess = allowScriptChatAccess;
}
- @PrePersist
- @PreUpdate
- public void normalizeFields() {
- Instant now = Instant.now();
- if (createdAt == null) {
- createdAt = now;
- }
- updatedAt = now;
- this.broadcaster = normalize(broadcaster);
- this.admins = admins.stream().map(Channel::normalize).collect(Collectors.toSet());
- if (canvasWidth <= 0) {
- canvasWidth = 1920;
- }
- if (canvasHeight <= 0) {
- canvasHeight = 1080;
- }
- }
-
public Instant getCreatedAt() {
return createdAt;
}
@@ -138,6 +117,22 @@ public class Channel {
return updatedAt;
}
+ @PrePersist
+ private void ensureCreatedAt() {
+ Instant now = Instant.now();
+ if (createdAt == null) {
+ createdAt = now;
+ }
+ if (updatedAt == null) {
+ updatedAt = now;
+ }
+ }
+
+ @PreUpdate
+ private void touchUpdatedAt() {
+ updatedAt = Instant.now();
+ }
+
private static String normalize(String value) {
return value == null ? null : value.toLowerCase(Locale.ROOT);
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/MarketplaceScriptHeart.java b/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/MarketplaceScriptHeart.java
index 35b03ed..5113e62 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/MarketplaceScriptHeart.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/model/db/imgfloat/MarketplaceScriptHeart.java
@@ -30,10 +30,6 @@ public class MarketplaceScriptHeart {
return scriptId;
}
- public void setScriptId(String scriptId) {
- this.scriptId = scriptId;
- }
-
public String getUsername() {
return username;
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/repository/audit/AuditLogRepository.java b/src/main/java/dev/kruhlmann/imgfloat/repository/audit/AuditLogRepository.java
index a25514f..5d051a8 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/repository/audit/AuditLogRepository.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/repository/audit/AuditLogRepository.java
@@ -1,7 +1,6 @@
package dev.kruhlmann.imgfloat.repository.audit;
import dev.kruhlmann.imgfloat.model.db.audit.AuditLogEntry;
-import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -11,7 +10,6 @@ import org.springframework.stereotype.Repository;
@Repository
public interface AuditLogRepository extends JpaRepository {
- List findTop200ByBroadcasterOrderByCreatedAtDesc(String broadcaster);
@Query(
"""
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/AssetCleanupService.java b/src/main/java/dev/kruhlmann/imgfloat/service/AssetCleanupService.java
index 0f1bd35..2649606 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/AssetCleanupService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/AssetCleanupService.java
@@ -2,7 +2,6 @@ package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAsset;
-import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetAttachment;
import dev.kruhlmann.imgfloat.repository.AssetRepository;
import dev.kruhlmann.imgfloat.repository.ScriptAssetAttachmentRepository;
import dev.kruhlmann.imgfloat.repository.ScriptAssetRepository;
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/AssetStorageService.java b/src/main/java/dev/kruhlmann/imgfloat/service/AssetStorageService.java
index 12030f3..ebcbfc8 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/AssetStorageService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/AssetStorageService.java
@@ -73,7 +73,7 @@ public class AssetStorageService {
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE
);
- logger.info("Wrote asset to {}", file);
+ logger.info("Wrote asset preview to {}", file);
}
public Optional loadAssetFile(String broadcaster, String assetId, String mediaType) {
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/AuditLogService.java b/src/main/java/dev/kruhlmann/imgfloat/service/AuditLogService.java
index f284f43..e0b3f57 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/AuditLogService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/AuditLogService.java
@@ -1,10 +1,8 @@
package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.db.audit.AuditLogEntry;
-import dev.kruhlmann.imgfloat.model.api.response.AuditLogEntryView;
import dev.kruhlmann.imgfloat.repository.audit.AuditLogRepository;
import dev.kruhlmann.imgfloat.util.LogSanitizer;
-import java.util.List;
import java.util.Locale;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@@ -54,18 +52,6 @@ public class AuditLogService {
}
}
- public List listEntries(String broadcaster) {
- String normalizedBroadcaster = normalize(broadcaster);
- if (normalizedBroadcaster == null || normalizedBroadcaster.isBlank()) {
- return List.of();
- }
- return auditLogRepository
- .findTop200ByBroadcasterOrderByCreatedAtDesc(normalizedBroadcaster)
- .stream()
- .map(AuditLogEntryView::fromEntry)
- .toList();
- }
-
public Page listEntries(
String broadcaster,
String actor,
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/ChannelDirectoryService.java b/src/main/java/dev/kruhlmann/imgfloat/service/ChannelDirectoryService.java
index 1f415b9..610342e 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/ChannelDirectoryService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/ChannelDirectoryService.java
@@ -581,14 +581,14 @@ public class ChannelDirectoryService {
}
@Transactional
- public Optional clearScriptLogo(String broadcaster, String assetId, String actor) {
+ public void clearScriptLogo(String broadcaster, String assetId, String actor) {
Asset asset = requireScriptAssetForBroadcaster(broadcaster, assetId);
ScriptAsset script = scriptAssetRepository
.findById(asset.getId())
.orElseThrow(() -> new ResponseStatusException(BAD_REQUEST, "Asset is not a script"));
String previousLogoFileId = script.getLogoFileId();
if (previousLogoFileId == null) {
- return Optional.empty();
+ return;
}
script.setLogoFileId(null);
script.setAttachments(loadScriptAttachments(asset.getBroadcaster(), asset.getId(), null));
@@ -602,7 +602,6 @@ public class ChannelDirectoryService {
"SCRIPT_LOGO_CLEARED",
"Cleared script logo for " + script.getName() + " (" + asset.getId() + ")"
);
- return Optional.of(view);
}
public List listMarketplaceScripts(String query, String sessionUsername) {
@@ -804,7 +803,7 @@ public class ChannelDirectoryService {
.findById(scriptId)
.filter(ScriptAsset::isPublic)
.map(ScriptAsset::getLogoFileId)
- .flatMap((logoFileId) -> scriptAssetFileRepository.findById(logoFileId))
+ .flatMap(scriptAssetFileRepository::findById)
.flatMap((file) ->
assetStorageService.loadAssetFileSafely(file.getBroadcaster(), file.getId(), file.getMediaType())
);
@@ -1065,7 +1064,7 @@ public class ChannelDirectoryService {
.findById(asset.getId())
.orElseThrow(() -> new ResponseStatusException(BAD_REQUEST, "Asset is not a script"));
Integer beforeOrder = asset.getDisplayOrder();
- List orderUpdates = List.of();
+ List orderUpdates;
if (req.getOrder() != null) {
if (req.getOrder() < 1) {
throw new ResponseStatusException(BAD_REQUEST, "Order must be >= 1");
@@ -1514,7 +1513,7 @@ public class ChannelDirectoryService {
return scriptAssetRepository
.findById(asset.getId())
.map(ScriptAsset::getLogoFileId)
- .flatMap((logoFileId) -> scriptAssetFileRepository.findById(logoFileId))
+ .flatMap(scriptAssetFileRepository::findById)
.flatMap((file) ->
assetStorageService.loadAssetFileSafely(file.getBroadcaster(), file.getId(), file.getMediaType())
);
@@ -1723,7 +1722,7 @@ public class ChannelDirectoryService {
return assets
.stream()
.sorted(
- Comparator.comparingInt((Asset asset) -> displayOrderValue(asset))
+ Comparator.comparingInt(this::displayOrderValue)
.reversed()
.thenComparing(Asset::getCreatedAt, Comparator.nullsFirst(Comparator.naturalOrder()))
)
@@ -1761,7 +1760,7 @@ public class ChannelDirectoryService {
.stream()
.filter((asset) -> types.contains(asset.getAssetType()))
.sorted(
- Comparator.comparingInt((Asset asset) -> displayOrderValue(asset))
+ Comparator.comparingInt(this::displayOrderValue)
.reversed()
.thenComparing(Asset::getCreatedAt, Comparator.nullsFirst(Comparator.naturalOrder()))
)
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/EmoteSyncScheduler.java b/src/main/java/dev/kruhlmann/imgfloat/service/EmoteSyncScheduler.java
index a349408..1287ada 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/EmoteSyncScheduler.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/EmoteSyncScheduler.java
@@ -50,9 +50,10 @@ public class EmoteSyncScheduler implements SchedulingConfigurer {
private Trigger buildTrigger() {
return (TriggerContext triggerContext) -> {
- Instant lastCompletion = triggerContext.lastCompletionTime() == null
+ Instant lastCompletion = triggerContext.lastCompletion() == null
? Instant.now()
- : triggerContext.lastCompletionTime().toInstant();
+ : triggerContext.lastCompletion();
+ assert lastCompletion != null;
return lastCompletion.plus(Duration.ofMinutes(resolveIntervalMinutes()));
};
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/GitInfoService.java b/src/main/java/dev/kruhlmann/imgfloat/service/GitInfoService.java
index 4d4e7fe..3d69692 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/GitInfoService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/GitInfoService.java
@@ -41,10 +41,6 @@ public class GitInfoService {
this.commitUrlPrefix = normalize(commitUrlPrefix);
}
- public String getCommitSha() {
- return commitSha;
- }
-
public String getShortCommitSha() {
return shortCommitSha;
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/MarketplaceScriptSeedLoader.java b/src/main/java/dev/kruhlmann/imgfloat/service/MarketplaceScriptSeedLoader.java
index c35ff8b..2ec2251 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/MarketplaceScriptSeedLoader.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/MarketplaceScriptSeedLoader.java
@@ -134,10 +134,7 @@ public class MarketplaceScriptSeedLoader {
if (!Files.isDirectory(scriptDir)) {
continue;
}
- SeedScript script = loadScriptDirectory(scriptDir).orElse(null);
- if (script != null) {
- loaded.add(script);
- }
+ loadScriptDirectory(scriptDir).ifPresent(loaded::add);
}
} catch (IOException ex) {
logger.warn("Failed to read marketplace script directory {}", rootPath, ex);
@@ -179,7 +176,7 @@ public class MarketplaceScriptSeedLoader {
broadcaster,
sourceMediaType,
logoMediaType,
- Optional.ofNullable(sourcePath),
+ Optional.of(sourcePath),
Optional.ofNullable(logoPath),
allowedDomains,
attachments,
@@ -207,7 +204,7 @@ public class MarketplaceScriptSeedLoader {
attachments.add(
new SeedAttachment(
name,
- mediaType == null ? "application/octet-stream" : mediaType,
+ mediaType,
attachment,
new AtomicReference<>()
)
@@ -348,7 +345,7 @@ public class MarketplaceScriptSeedLoader {
}
try {
String content = Files.readString(path);
- return JsonSupport.read(content, ScriptSeedMetadata.class);
+ return JsonSupport.read(content);
} catch (IOException ex) {
logger.warn("Failed to read marketplace metadata {}", path, ex);
return null;
@@ -362,8 +359,8 @@ public class MarketplaceScriptSeedLoader {
private JsonSupport() {}
- static T read(String payload, Class type) throws IOException {
- return mapper().readValue(payload, type);
+ static T read(String payload) throws IOException {
+ return mapper().readValue(payload, (Class) ScriptSeedMetadata.class);
}
private static com.fasterxml.jackson.databind.ObjectMapper mapper() {
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/TwitchAppAccessTokenService.java b/src/main/java/dev/kruhlmann/imgfloat/service/TwitchAppAccessTokenService.java
index f517609..347344c 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/TwitchAppAccessTokenService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/TwitchAppAccessTokenService.java
@@ -42,12 +42,12 @@ public class TwitchAppAccessTokenService {
return Optional.empty();
}
AccessToken current = cachedToken;
- if (current != null && !current.isExpired()) {
+ if (current != null && current.isActive()) {
return Optional.of(current.token());
}
synchronized (this) {
AccessToken refreshed = cachedToken;
- if (refreshed != null && !refreshed.isExpired()) {
+ if (refreshed != null && refreshed.isActive()) {
return Optional.of(refreshed.token());
}
cachedToken = requestToken();
@@ -91,8 +91,8 @@ public class TwitchAppAccessTokenService {
}
private record AccessToken(String token, Instant expiresAt) {
- boolean isExpired() {
- return expiresAt == null || expiresAt.isBefore(Instant.now());
+ boolean isActive() {
+ return expiresAt != null && !expiresAt.isBefore(Instant.now());
}
}
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/VersionService.java b/src/main/java/dev/kruhlmann/imgfloat/service/VersionService.java
index a28db9b..be8e4fe 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/VersionService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/VersionService.java
@@ -1,14 +1,10 @@
package dev.kruhlmann.imgfloat.service;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@@ -17,32 +13,17 @@ import org.springframework.stereotype.Component;
public class VersionService {
private static final Logger LOG = LoggerFactory.getLogger(VersionService.class);
- private static final Pattern PACKAGE_VERSION_PATTERN = Pattern.compile("\"version\"\\s*:\\s*\"([^\"]+)\"");
private final String serverVersion;
- private final String releaseVersion;
- public VersionService() throws IOException {
+ public VersionService() {
this.serverVersion = resolveServerVersion();
- this.releaseVersion = normalizeReleaseVersion(serverVersion);
}
public String getVersion() {
return serverVersion;
}
- public String getReleaseVersion() {
- return releaseVersion;
- }
-
- public String getReleaseTag() {
- if (releaseVersion == null || releaseVersion.isBlank()) {
- throw new IllegalStateException("Release version is not available");
- }
- String normalized = releaseVersion.startsWith("v") ? releaseVersion.substring(1) : releaseVersion;
- return "v" + normalized;
- }
-
private String resolveServerVersion() {
String pomVersion = getPomVersion();
if (pomVersion != null && !pomVersion.isBlank()) {
@@ -57,16 +38,6 @@ public class VersionService {
throw new IllegalStateException("Release version is not available");
}
- private String normalizeReleaseVersion(String baseVersion) throws IllegalStateException {
- String normalized = baseVersion.trim();
- normalized = normalized.replaceFirst("(?i)^v", "");
- normalized = normalized.replaceFirst("-SNAPSHOT$", "");
- if (normalized.isBlank()) {
- throw new IllegalStateException("Invalid version: " + baseVersion);
- }
- return normalized;
- }
-
private String getPomVersion() {
try (
var inputStream = getClass().getResourceAsStream("/META-INF/maven/dev.kruhlmann/imgfloat/pom.properties")
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/media/AssetContent.java b/src/main/java/dev/kruhlmann/imgfloat/service/media/AssetContent.java
index 8c74c61..3475810 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/media/AssetContent.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/media/AssetContent.java
@@ -1,5 +1,7 @@
package dev.kruhlmann.imgfloat.service.media;
+import jakarta.validation.constraints.NotNull;
+
import java.util.Arrays;
import java.util.Objects;
@@ -19,6 +21,7 @@ public record AssetContent(byte[] bytes, String mediaType) {
return result;
}
+ @NotNull
@Override
public String toString() {
return "AssetContent{" + "bytes=" + Arrays.toString(bytes) + ", mediaType='" + mediaType + '\'' + '}';
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/media/MediaOptimizationService.java b/src/main/java/dev/kruhlmann/imgfloat/service/media/MediaOptimizationService.java
index bead9ac..dc03e39 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/media/MediaOptimizationService.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/media/MediaOptimizationService.java
@@ -42,11 +42,7 @@ public class MediaOptimizationService {
}
}
if (mediaType.startsWith("image/")) {
- OptimizedAsset imageAsset = optimizeImage(bytes, mediaType);
- if (imageAsset == null) {
- return null;
- }
- return imageAsset;
+ return optimizeImage(bytes, mediaType);
}
if (mediaType.startsWith("video/")) {
@@ -86,7 +82,7 @@ public class MediaOptimizationService {
return "image/png".equalsIgnoreCase(mediaType) && ApngDetector.isApng(bytes);
}
- private OptimizedAsset optimizeApng(byte[] bytes, String mediaType) throws IOException {
+ private OptimizedAsset optimizeApng(byte[] bytes, String mediaType) {
return ffmpegService
.transcodeApngToGif(bytes)
.map(this::transcodeGifToVideo)
diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/media/OptimizedAsset.java b/src/main/java/dev/kruhlmann/imgfloat/service/media/OptimizedAsset.java
index 7541b9f..5444313 100644
--- a/src/main/java/dev/kruhlmann/imgfloat/service/media/OptimizedAsset.java
+++ b/src/main/java/dev/kruhlmann/imgfloat/service/media/OptimizedAsset.java
@@ -1,5 +1,7 @@
package dev.kruhlmann.imgfloat.service.media;
+import jakarta.validation.constraints.NotNull;
+
import java.util.Arrays;
import java.util.Objects;
@@ -26,6 +28,7 @@ public record OptimizedAsset(byte[] bytes, String mediaType, int width, int heig
return result;
}
+ @NotNull
@Override
public String toString() {
return (
diff --git a/src/test/java/dev/kruhlmann/imgfloat/ChannelDirectoryServiceTest.java b/src/test/java/dev/kruhlmann/imgfloat/ChannelDirectoryServiceTest.java
index 7c2f6b8..b2a5062 100644
--- a/src/test/java/dev/kruhlmann/imgfloat/ChannelDirectoryServiceTest.java
+++ b/src/test/java/dev/kruhlmann/imgfloat/ChannelDirectoryServiceTest.java
@@ -64,12 +64,7 @@ class ChannelDirectoryServiceTest {
private VisualAssetRepository visualAssetRepository;
private AudioAssetRepository audioAssetRepository;
private ScriptAssetRepository scriptAssetRepository;
- private ScriptAssetAttachmentRepository scriptAssetAttachmentRepository;
private ScriptAssetFileRepository scriptAssetFileRepository;
- private MarketplaceScriptHeartRepository marketplaceScriptHeartRepository;
- private SettingsService settingsService;
- private MarketplaceScriptSeedLoader marketplaceScriptSeedLoader;
- private AuditLogService auditLogService;
@BeforeEach
void setup() throws Exception {
@@ -79,13 +74,13 @@ class ChannelDirectoryServiceTest {
visualAssetRepository = mock(VisualAssetRepository.class);
audioAssetRepository = mock(AudioAssetRepository.class);
scriptAssetRepository = mock(ScriptAssetRepository.class);
- scriptAssetAttachmentRepository = mock(ScriptAssetAttachmentRepository.class);
+ ScriptAssetAttachmentRepository scriptAssetAttachmentRepository = mock(ScriptAssetAttachmentRepository.class);
scriptAssetFileRepository = mock(ScriptAssetFileRepository.class);
- marketplaceScriptHeartRepository = mock(MarketplaceScriptHeartRepository.class);
- auditLogService = mock(AuditLogService.class);
+ MarketplaceScriptHeartRepository marketplaceScriptHeartRepository = mock(MarketplaceScriptHeartRepository.class);
+ AuditLogService auditLogService = mock(AuditLogService.class);
when(marketplaceScriptHeartRepository.countByScriptIds(any())).thenReturn(List.of());
when(marketplaceScriptHeartRepository.findByUsernameAndScriptIdIn(anyString(), any())).thenReturn(List.of());
- settingsService = mock(SettingsService.class);
+ SettingsService settingsService = mock(SettingsService.class);
when(settingsService.get()).thenReturn(Settings.defaults());
setupInMemoryPersistence();
Path assetRoot = Files.createTempDirectory("imgfloat-assets-test");
@@ -112,24 +107,24 @@ class ChannelDirectoryServiceTest {
Files.writeString(scriptRoot.resolve("source.js"), "console.log('seeded');");
Files.write(scriptRoot.resolve("logo.png"), samplePng());
Files.write(scriptRoot.resolve("attachments/rotate.png"), samplePng());
- marketplaceScriptSeedLoader = new MarketplaceScriptSeedLoader(marketplaceRoot.toString());
+ MarketplaceScriptSeedLoader marketplaceScriptSeedLoader = new MarketplaceScriptSeedLoader(marketplaceRoot.toString());
service = new ChannelDirectoryService(
channelRepository,
assetRepository,
visualAssetRepository,
audioAssetRepository,
scriptAssetRepository,
- scriptAssetAttachmentRepository,
+ scriptAssetAttachmentRepository,
scriptAssetFileRepository,
- marketplaceScriptHeartRepository,
+ marketplaceScriptHeartRepository,
messagingTemplate,
assetStorageService,
mediaDetectionService,
mediaOptimizationService,
- settingsService,
+ settingsService,
uploadLimitBytes,
- marketplaceScriptSeedLoader,
- auditLogService
+ marketplaceScriptSeedLoader,
+ auditLogService
);
}
@@ -195,9 +190,14 @@ class ChannelDirectoryServiceTest {
}
@Test
- void appliesBoundaryValues() throws Exception {
+ void appliesBoundaryValues() {
String channel = "caster";
- String id = createSampleAsset(channel);
+ String id = null;
+ try {
+ id = createSampleAsset(channel);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
TransformRequest transform = validTransform();
transform.setSpeed(0.1);
diff --git a/src/test/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverterTest.java b/src/test/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverterTest.java
index aeb3b1c..1068d0c 100644
--- a/src/test/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverterTest.java
+++ b/src/test/java/dev/kruhlmann/imgfloat/config/TwitchAuthorizationCodeGrantRequestEntityConverterTest.java
@@ -43,21 +43,25 @@ class TwitchAuthorizationCodeGrantRequestEntityConverterTest {
.state("state")
.build();
+ MultiValueMap body = getStringStringMultiValueMap(authorizationRequest, authorizationResponse, registration);
+
+ assertThat(body.getFirst(OAuth2ParameterNames.CLIENT_ID)).isEqualTo("twitch-id");
+ assertThat(body.getFirst(OAuth2ParameterNames.CLIENT_SECRET)).isEqualTo("twitch-secret");
+ }
+
+ private static MultiValueMap getStringStringMultiValueMap(OAuth2AuthorizationRequest authorizationRequest, OAuth2AuthorizationResponse authorizationResponse, ClientRegistration registration) {
OAuth2AuthorizationExchange exchange = new OAuth2AuthorizationExchange(
- authorizationRequest,
- authorizationResponse
+ authorizationRequest,
+ authorizationResponse
);
OAuth2AuthorizationCodeGrantRequest grantRequest = new OAuth2AuthorizationCodeGrantRequest(
- registration,
+ registration,
exchange
);
var converter = new TwitchAuthorizationCodeGrantRequestEntityConverter();
RequestEntity> requestEntity = converter.convert(grantRequest);
- MultiValueMap body = (MultiValueMap) requestEntity.getBody();
-
- assertThat(body.getFirst(OAuth2ParameterNames.CLIENT_ID)).isEqualTo("twitch-id");
- assertThat(body.getFirst(OAuth2ParameterNames.CLIENT_SECRET)).isEqualTo("twitch-secret");
+ return (MultiValueMap) requestEntity.getBody();
}
}
diff --git a/src/test/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandlerTest.java b/src/test/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandlerTest.java
index 1052da6..3b7845b 100644
--- a/src/test/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandlerTest.java
+++ b/src/test/java/dev/kruhlmann/imgfloat/config/TwitchOAuth2ErrorResponseErrorHandlerTest.java
@@ -22,7 +22,7 @@ class TwitchOAuth2ErrorResponseErrorHandlerTest {
private final TwitchOAuth2ErrorResponseErrorHandler handler = new TwitchOAuth2ErrorResponseErrorHandler();
@Test
- void fallsBackToSyntheticErrorWhenErrorBodyIsMissing() throws Exception {
+ void fallsBackToSyntheticErrorWhenErrorBodyIsMissing() {
MockClientHttpResponse response = new MockClientHttpResponse(new byte[0], HttpStatus.BAD_REQUEST);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);