Refactor models

This commit is contained in:
2026-01-27 15:40:55 +01:00
parent 9cf25a4351
commit 39bb599219
61 changed files with 176 additions and 118 deletions

36
AGENTS.md Normal file
View File

@@ -0,0 +1,36 @@
# Repository Guidelines
## Project Structure & Module Organization
- Java Spring Boot service under `src/main/java` (controllers, services, repositories, models); configuration in `src/main/resources`.
- Frontend overlays and admin UI assets live in `src/main/resources/static/js` and `src/main/resources/templates` (Thymeleaf).
- Tests are in `src/test/java`; sample assets and previews are stored under `assets/` and `previews/` when running locally.
- Marketplace seed content (if used) sits at the path pointed to `IMGFLOAT_MARKETPLACE_SCRIPTS_PATH`, each with `metadata.json`, `source.js`, optional `logo.png`, and `attachments/`.
## Build, Test, and Development Commands
- `make build` / `mvn compile`: compile the application.
- `make run`: load `.env` (if present) and start the Spring Boot app on port 8080 with required env vars.
- `make watch`: recompile on source changes (needs `entr`); restart browser manually.
- `make test` / `mvn test`: run the full test suite.
- `make package`: clean build a runnable JAR.
## Coding Style & Naming Conventions
- Java 17, Spring Boot 3.x. Follow standard Java conventions: 4-space indentation, `UpperCamelCase` for types, `lowerCamelCase` for methods/fields, constants in `UPPER_SNAKE_CASE`.
- Keep controllers thin, delegate logic to services, and favor immutable DTOs/records where possible.
- Place web assets next to related features (`static/js` modules, matching templates). Use descriptive filenames (e.g., `broadcast/renderer.js`).
- Prefer constructor injection for Spring components; avoid field injection.
## Testing Guidelines
- Use JUnit 5 with Mockito for unit tests; keep tests under `src/test/java` mirroring package paths.
- Name tests descriptively (`ClassNameTest`, method names expressing behavior).
- For changes touching overlays or asset handling, add tests for repository/service logic and handle edge cases (missing files, bad metadata).
- Run `make test` before opening a PR; add targeted integration tests when altering controllers or WebSocket flows.
## Commit & Pull Request Guidelines
- Commits: concise, present-tense summaries (`Fix script import domain validation`). Group related changes; avoid noisy churn.
- PRs: include a clear summary, linked issue (if any), test results, and screenshots/GIFs when UI changes affect admin or broadcast overlays.
- Call out any config/env changes (new required vars such as `IMGFLOAT_*`) and migration steps.
## Security & Configuration Tips
- Store secrets via environment variables (`.env` only for local dev). Required paths: `IMGFLOAT_ASSETS_PATH`, `IMGFLOAT_PREVIEWS_PATH`, `IMGFLOAT_DB_PATH`, `IMGFLOAT_AUDIT_DB_PATH`.
- When seeding marketplace scripts, ensure `metadata.json` is well-formed; attachment filenames must be unique per script.
- Keep OAuth keys and token encryption keys (`IMGFLOAT_TOKEN_ENCRYPTION_KEY`) in a secret manager for non-local environments.

View File

@@ -51,7 +51,7 @@ public class AuditLogDataSourceConfig {
) { ) {
return builder return builder
.dataSource(dataSource) .dataSource(dataSource)
.packages("dev.kruhlmann.imgfloat.audit.model") .packages("dev.kruhlmann.imgfloat.model.db.audit")
.properties(hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings())) .properties(hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()))
.persistenceUnit("audit") .persistenceUnit("audit")
.build(); .build();

View File

@@ -1,7 +1,7 @@
package dev.kruhlmann.imgfloat.controller; package dev.kruhlmann.imgfloat.controller;
import dev.kruhlmann.imgfloat.model.AuditLogEntryView; import dev.kruhlmann.imgfloat.model.api.response.AuditLogEntryView;
import dev.kruhlmann.imgfloat.model.AuditLogPageView; import dev.kruhlmann.imgfloat.model.api.response.AuditLogPageView;
import dev.kruhlmann.imgfloat.model.OauthSessionUser; import dev.kruhlmann.imgfloat.model.OauthSessionUser;
import dev.kruhlmann.imgfloat.service.AuditLogService; import dev.kruhlmann.imgfloat.service.AuditLogService;
import dev.kruhlmann.imgfloat.service.AuthorizationService; import dev.kruhlmann.imgfloat.service.AuthorizationService;

View File

@@ -4,17 +4,17 @@ import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN; import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.springframework.http.HttpStatus.NOT_FOUND;
import dev.kruhlmann.imgfloat.model.AdminRequest; import dev.kruhlmann.imgfloat.model.api.request.AdminRequest;
import dev.kruhlmann.imgfloat.model.AssetView; import dev.kruhlmann.imgfloat.model.api.response.AssetView;
import dev.kruhlmann.imgfloat.model.CanvasSettingsRequest; import dev.kruhlmann.imgfloat.model.api.request.CanvasSettingsRequest;
import dev.kruhlmann.imgfloat.model.ChannelScriptSettingsRequest; import dev.kruhlmann.imgfloat.model.api.request.ChannelScriptSettingsRequest;
import dev.kruhlmann.imgfloat.model.CodeAssetRequest; import dev.kruhlmann.imgfloat.model.api.request.CodeAssetRequest;
import dev.kruhlmann.imgfloat.model.OauthSessionUser; import dev.kruhlmann.imgfloat.model.OauthSessionUser;
import dev.kruhlmann.imgfloat.model.PlaybackRequest; import dev.kruhlmann.imgfloat.model.api.request.PlaybackRequest;
import dev.kruhlmann.imgfloat.model.ScriptAssetAttachmentView; import dev.kruhlmann.imgfloat.model.api.response.ScriptAssetAttachmentView;
import dev.kruhlmann.imgfloat.model.TransformRequest; import dev.kruhlmann.imgfloat.model.api.request.TransformRequest;
import dev.kruhlmann.imgfloat.model.TwitchUserProfile; import dev.kruhlmann.imgfloat.model.api.response.TwitchUserProfile;
import dev.kruhlmann.imgfloat.model.VisibilityRequest; import dev.kruhlmann.imgfloat.model.api.request.VisibilityRequest;
import dev.kruhlmann.imgfloat.service.AuthorizationService; import dev.kruhlmann.imgfloat.service.AuthorizationService;
import dev.kruhlmann.imgfloat.service.ChannelDirectoryService; import dev.kruhlmann.imgfloat.service.ChannelDirectoryService;
import dev.kruhlmann.imgfloat.service.TwitchUserLookupService; import dev.kruhlmann.imgfloat.service.TwitchUserLookupService;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.controller; package dev.kruhlmann.imgfloat.controller;
import dev.kruhlmann.imgfloat.model.ErrorResponse; import dev.kruhlmann.imgfloat.model.api.response.ErrorResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@@ -3,10 +3,10 @@ package dev.kruhlmann.imgfloat.controller;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.springframework.http.HttpStatus.NOT_FOUND;
import dev.kruhlmann.imgfloat.model.AssetView; import dev.kruhlmann.imgfloat.model.api.response.AssetView;
import dev.kruhlmann.imgfloat.model.OauthSessionUser; import dev.kruhlmann.imgfloat.model.OauthSessionUser;
import dev.kruhlmann.imgfloat.model.ScriptMarketplaceEntry; import dev.kruhlmann.imgfloat.model.api.response.ScriptMarketplaceEntry;
import dev.kruhlmann.imgfloat.model.ScriptMarketplaceImportRequest; import dev.kruhlmann.imgfloat.model.api.request.ScriptMarketplaceImportRequest;
import dev.kruhlmann.imgfloat.service.AuthorizationService; import dev.kruhlmann.imgfloat.service.AuthorizationService;
import dev.kruhlmann.imgfloat.service.ChannelDirectoryService; import dev.kruhlmann.imgfloat.service.ChannelDirectoryService;
import dev.kruhlmann.imgfloat.util.LogSanitizer; import dev.kruhlmann.imgfloat.util.LogSanitizer;

View File

@@ -1,7 +1,7 @@
package dev.kruhlmann.imgfloat.controller; package dev.kruhlmann.imgfloat.controller;
import dev.kruhlmann.imgfloat.model.OauthSessionUser; import dev.kruhlmann.imgfloat.model.OauthSessionUser;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import dev.kruhlmann.imgfloat.service.AuthorizationService; import dev.kruhlmann.imgfloat.service.AuthorizationService;
import dev.kruhlmann.imgfloat.service.SettingsService; import dev.kruhlmann.imgfloat.service.SettingsService;
import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirement;

View File

@@ -5,7 +5,7 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import dev.kruhlmann.imgfloat.model.OauthSessionUser; import dev.kruhlmann.imgfloat.model.OauthSessionUser;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import dev.kruhlmann.imgfloat.service.AuthorizationService; import dev.kruhlmann.imgfloat.service.AuthorizationService;
import dev.kruhlmann.imgfloat.service.ChannelDirectoryService; import dev.kruhlmann.imgfloat.service.ChannelDirectoryService;
import dev.kruhlmann.imgfloat.service.GitInfoService; import dev.kruhlmann.imgfloat.service.GitInfoService;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.Positive;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
public class ChannelScriptSettingsRequest { public class ChannelScriptSettingsRequest {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
public class PlaybackRequest { public class PlaybackRequest {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.DecimalMin;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.request;
public class VisibilityRequest { public class VisibilityRequest {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;

View File

@@ -1,9 +1,13 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import dev.kruhlmann.imgfloat.model.api.request.TransformRequest;
import dev.kruhlmann.imgfloat.model.db.imgfloat.AudioAsset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset;
/** /**
* Represents a partial update for an {@link Asset}. Only the fields that changed * Represents a partial update for an {@link dev.kruhlmann.imgfloat.model.db.imgfloat.Asset}. Only the fields that changed
* for a given operation are populated to reduce payload sizes sent over WebSocket. * for a given operation are populated to reduce payload sizes sent over WebSocket.
*/ */
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)

View File

@@ -1,8 +1,14 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import dev.kruhlmann.imgfloat.model.AssetType;
import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.AudioAsset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAsset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset;
public record AssetView( public record AssetView(
String id, String id,
String broadcaster, String broadcaster,

View File

@@ -1,8 +1,9 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import dev.kruhlmann.imgfloat.audit.model.AuditLogEntry;
import java.time.Instant; import java.time.Instant;
import dev.kruhlmann.imgfloat.model.db.audit.AuditLogEntry;
public record AuditLogEntryView(String id, String actor, String action, String details, Instant createdAt) { public record AuditLogEntryView(String id, String actor, String action, String details, Instant createdAt) {
public static AuditLogEntryView fromEntry(AuditLogEntry entry) { public static AuditLogEntryView fromEntry(AuditLogEntry entry) {
if (entry == null) { if (entry == null) {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import java.util.List; import java.util.List;

View File

@@ -1,5 +1,6 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import dev.kruhlmann.imgfloat.model.api.request.CanvasSettingsRequest;
public class CanvasEvent { public class CanvasEvent {
public enum Type { public enum Type {

View File

@@ -1,3 +1,3 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
public record ErrorResponse(int status, String message, String path) {} public record ErrorResponse(int status, String message, String path) {}

View File

@@ -1,5 +1,7 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
import dev.kruhlmann.imgfloat.model.AssetType;
import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetAttachment;
public record ScriptAssetAttachmentView( public record ScriptAssetAttachmentView(
String id, String id,
String scriptAssetId, String scriptAssetId,

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
public record ScriptMarketplaceEntry( public record ScriptMarketplaceEntry(
String id, String id,

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.api.response;
/** /**
* Minimal Twitch user details used for rendering avatars and display names. * Minimal Twitch user details used for rendering avatars and display names.

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.audit.model; package dev.kruhlmann.imgfloat.model.db.audit;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
@@ -12,6 +12,8 @@ import java.time.Instant;
import java.util.Locale; import java.util.Locale;
import java.util.UUID; import java.util.UUID;
import dev.kruhlmann.imgfloat.model.AssetType;
@Entity @Entity
@Table(name = "assets") @Table(name = "assets")
public class Asset { public class Asset {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.CollectionTable; import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column; import jakarta.persistence.Column;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.CollectionTable; import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
@@ -14,6 +14,8 @@ import jakarta.persistence.Transient;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import dev.kruhlmann.imgfloat.model.api.response.ScriptAssetAttachmentView;
@Entity @Entity
@Table(name = "script_assets") @Table(name = "script_assets")
public class ScriptAsset { public class ScriptAsset {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
@@ -10,6 +10,8 @@ import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.util.UUID; import java.util.UUID;
import dev.kruhlmann.imgfloat.model.AssetType;
@Entity @Entity
@Table(name = "script_asset_attachments") @Table(name = "script_asset_attachments")
public class ScriptAssetAttachment { public class ScriptAssetAttachment {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
@@ -11,6 +11,8 @@ import jakarta.persistence.Table;
import java.util.Locale; import java.util.Locale;
import java.util.UUID; import java.util.UUID;
import dev.kruhlmann.imgfloat.model.AssetType;
@Entity @Entity
@Table(name = "script_asset_files") @Table(name = "script_asset_files")
public class ScriptAssetFile { public class ScriptAssetFile {

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;

View File

@@ -1,4 +1,4 @@
package dev.kruhlmann.imgfloat.model; package dev.kruhlmann.imgfloat.model.db.imgfloat;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.Asset; import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.AudioAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.AudioAsset;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.Channel; import dev.kruhlmann.imgfloat.model.db.imgfloat.Channel;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,7 +1,7 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.MarketplaceScriptHeart; import dev.kruhlmann.imgfloat.model.db.imgfloat.MarketplaceScriptHeart;
import dev.kruhlmann.imgfloat.model.MarketplaceScriptHeartId; import dev.kruhlmann.imgfloat.model.db.imgfloat.MarketplaceScriptHeartId;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.ScriptAssetAttachment; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetAttachment;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.ScriptAssetFile; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.ScriptAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAsset;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
public interface SettingsRepository extends JpaRepository<Settings, Integer> {} public interface SettingsRepository extends JpaRepository<Settings, Integer> {}

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.SystemAdministrator; import dev.kruhlmann.imgfloat.model.db.imgfloat.SystemAdministrator;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository; package dev.kruhlmann.imgfloat.repository;
import dev.kruhlmann.imgfloat.model.VisualAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.repository.audit; package dev.kruhlmann.imgfloat.repository.audit;
import dev.kruhlmann.imgfloat.audit.model.AuditLogEntry; import dev.kruhlmann.imgfloat.model.db.audit.AuditLogEntry;
import java.util.List; import java.util.List;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;

View File

@@ -1,7 +1,7 @@
package dev.kruhlmann.imgfloat.service; package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.Asset; import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import dev.kruhlmann.imgfloat.model.ScriptAssetFile; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile;
import dev.kruhlmann.imgfloat.repository.AssetRepository; import dev.kruhlmann.imgfloat.repository.AssetRepository;
import dev.kruhlmann.imgfloat.repository.ChannelRepository; import dev.kruhlmann.imgfloat.repository.ChannelRepository;
import dev.kruhlmann.imgfloat.repository.MarketplaceScriptHeartRepository; import dev.kruhlmann.imgfloat.repository.MarketplaceScriptHeartRepository;

View File

@@ -1,8 +1,8 @@
package dev.kruhlmann.imgfloat.service; package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.Asset; import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import dev.kruhlmann.imgfloat.model.ScriptAssetAttachment; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAsset;
import dev.kruhlmann.imgfloat.model.ScriptAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetAttachment;
import dev.kruhlmann.imgfloat.repository.AssetRepository; import dev.kruhlmann.imgfloat.repository.AssetRepository;
import dev.kruhlmann.imgfloat.repository.ScriptAssetAttachmentRepository; import dev.kruhlmann.imgfloat.repository.ScriptAssetAttachmentRepository;
import dev.kruhlmann.imgfloat.repository.ScriptAssetRepository; import dev.kruhlmann.imgfloat.repository.ScriptAssetRepository;

View File

@@ -1,7 +1,7 @@
package dev.kruhlmann.imgfloat.service; package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.audit.model.AuditLogEntry; import dev.kruhlmann.imgfloat.model.db.audit.AuditLogEntry;
import dev.kruhlmann.imgfloat.model.AuditLogEntryView; import dev.kruhlmann.imgfloat.model.api.response.AuditLogEntryView;
import dev.kruhlmann.imgfloat.repository.audit.AuditLogRepository; import dev.kruhlmann.imgfloat.repository.audit.AuditLogRepository;
import dev.kruhlmann.imgfloat.util.LogSanitizer; import dev.kruhlmann.imgfloat.util.LogSanitizer;
import java.util.List; import java.util.List;

View File

@@ -3,28 +3,28 @@ package dev.kruhlmann.imgfloat.service;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.PAYLOAD_TOO_LARGE; import static org.springframework.http.HttpStatus.PAYLOAD_TOO_LARGE;
import dev.kruhlmann.imgfloat.model.Asset;
import dev.kruhlmann.imgfloat.model.AssetEvent;
import dev.kruhlmann.imgfloat.model.AssetPatch;
import dev.kruhlmann.imgfloat.model.AssetType; import dev.kruhlmann.imgfloat.model.AssetType;
import dev.kruhlmann.imgfloat.model.AssetView; import dev.kruhlmann.imgfloat.model.api.request.CanvasSettingsRequest;
import dev.kruhlmann.imgfloat.model.AudioAsset; import dev.kruhlmann.imgfloat.model.api.request.ChannelScriptSettingsRequest;
import dev.kruhlmann.imgfloat.model.CanvasEvent; import dev.kruhlmann.imgfloat.model.api.request.CodeAssetRequest;
import dev.kruhlmann.imgfloat.model.CanvasSettingsRequest; import dev.kruhlmann.imgfloat.model.api.request.PlaybackRequest;
import dev.kruhlmann.imgfloat.model.Channel; import dev.kruhlmann.imgfloat.model.api.request.TransformRequest;
import dev.kruhlmann.imgfloat.model.ChannelScriptSettingsRequest; import dev.kruhlmann.imgfloat.model.api.request.VisibilityRequest;
import dev.kruhlmann.imgfloat.model.CodeAssetRequest; import dev.kruhlmann.imgfloat.model.api.response.AssetEvent;
import dev.kruhlmann.imgfloat.model.MarketplaceScriptHeart; import dev.kruhlmann.imgfloat.model.api.response.AssetPatch;
import dev.kruhlmann.imgfloat.model.PlaybackRequest; import dev.kruhlmann.imgfloat.model.api.response.AssetView;
import dev.kruhlmann.imgfloat.model.ScriptAsset; import dev.kruhlmann.imgfloat.model.api.response.CanvasEvent;
import dev.kruhlmann.imgfloat.model.ScriptAssetAttachment; import dev.kruhlmann.imgfloat.model.api.response.ScriptAssetAttachmentView;
import dev.kruhlmann.imgfloat.model.ScriptAssetAttachmentView; import dev.kruhlmann.imgfloat.model.api.response.ScriptMarketplaceEntry;
import dev.kruhlmann.imgfloat.model.ScriptAssetFile; import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import dev.kruhlmann.imgfloat.model.ScriptMarketplaceEntry; import dev.kruhlmann.imgfloat.model.db.imgfloat.AudioAsset;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.db.imgfloat.Channel;
import dev.kruhlmann.imgfloat.model.TransformRequest; import dev.kruhlmann.imgfloat.model.db.imgfloat.MarketplaceScriptHeart;
import dev.kruhlmann.imgfloat.model.VisibilityRequest; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAsset;
import dev.kruhlmann.imgfloat.model.VisualAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetAttachment;
import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile;
import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset;
import dev.kruhlmann.imgfloat.repository.AssetRepository; import dev.kruhlmann.imgfloat.repository.AssetRepository;
import dev.kruhlmann.imgfloat.repository.AudioAssetRepository; import dev.kruhlmann.imgfloat.repository.AudioAssetRepository;
import dev.kruhlmann.imgfloat.repository.ChannelRepository; import dev.kruhlmann.imgfloat.repository.ChannelRepository;

View File

@@ -1,7 +1,7 @@
package dev.kruhlmann.imgfloat.service; package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.Channel; import dev.kruhlmann.imgfloat.model.db.imgfloat.Channel;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import dev.kruhlmann.imgfloat.repository.ChannelRepository; import dev.kruhlmann.imgfloat.repository.ChannelRepository;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.service; package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.ScriptMarketplaceEntry; import dev.kruhlmann.imgfloat.model.api.response.ScriptMarketplaceEntry;
import dev.kruhlmann.imgfloat.service.media.AssetContent; import dev.kruhlmann.imgfloat.service.media.AssetContent;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;

View File

@@ -2,9 +2,9 @@ package dev.kruhlmann.imgfloat.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import dev.kruhlmann.imgfloat.model.AudioAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.AudioAsset;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import dev.kruhlmann.imgfloat.model.VisualAsset; import dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset;
import dev.kruhlmann.imgfloat.repository.AudioAssetRepository; import dev.kruhlmann.imgfloat.repository.AudioAssetRepository;
import dev.kruhlmann.imgfloat.repository.SettingsRepository; import dev.kruhlmann.imgfloat.repository.SettingsRepository;
import dev.kruhlmann.imgfloat.repository.VisualAssetRepository; import dev.kruhlmann.imgfloat.repository.VisualAssetRepository;

View File

@@ -1,6 +1,6 @@
package dev.kruhlmann.imgfloat.service; package dev.kruhlmann.imgfloat.service;
import dev.kruhlmann.imgfloat.model.SystemAdministrator; import dev.kruhlmann.imgfloat.model.db.imgfloat.SystemAdministrator;
import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository; import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;

View File

@@ -2,7 +2,7 @@ package dev.kruhlmann.imgfloat.service;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import dev.kruhlmann.imgfloat.model.TwitchUserProfile; import dev.kruhlmann.imgfloat.model.api.response.TwitchUserProfile;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;

View File

@@ -12,7 +12,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import dev.kruhlmann.imgfloat.model.VisibilityRequest; import dev.kruhlmann.imgfloat.model.api.request.VisibilityRequest;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;

View File

@@ -5,7 +5,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import dev.kruhlmann.imgfloat.model.Channel; import dev.kruhlmann.imgfloat.model.db.imgfloat.Channel;
import dev.kruhlmann.imgfloat.repository.ChannelRepository; import dev.kruhlmann.imgfloat.repository.ChannelRepository;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@@ -9,16 +9,16 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import dev.kruhlmann.imgfloat.model.Asset;
import dev.kruhlmann.imgfloat.model.AssetView;
import dev.kruhlmann.imgfloat.model.AudioAsset;
import dev.kruhlmann.imgfloat.model.Channel;
import dev.kruhlmann.imgfloat.model.ScriptAsset;
import dev.kruhlmann.imgfloat.model.CodeAssetRequest;
import dev.kruhlmann.imgfloat.model.AssetType; import dev.kruhlmann.imgfloat.model.AssetType;
import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.model.api.request.CodeAssetRequest;
import dev.kruhlmann.imgfloat.model.TransformRequest; import dev.kruhlmann.imgfloat.model.api.request.TransformRequest;
import dev.kruhlmann.imgfloat.model.VisibilityRequest; import dev.kruhlmann.imgfloat.model.api.request.VisibilityRequest;
import dev.kruhlmann.imgfloat.model.api.response.AssetView;
import dev.kruhlmann.imgfloat.model.db.imgfloat.Asset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.AudioAsset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.Channel;
import dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAsset;
import dev.kruhlmann.imgfloat.model.db.imgfloat.Settings;
import dev.kruhlmann.imgfloat.repository.AssetRepository; import dev.kruhlmann.imgfloat.repository.AssetRepository;
import dev.kruhlmann.imgfloat.repository.AudioAssetRepository; import dev.kruhlmann.imgfloat.repository.AudioAssetRepository;
import dev.kruhlmann.imgfloat.repository.ChannelRepository; import dev.kruhlmann.imgfloat.repository.ChannelRepository;
@@ -215,7 +215,7 @@ class ChannelDirectoryServiceTest {
void includesDefaultMarketplaceScript() { void includesDefaultMarketplaceScript() {
when(scriptAssetRepository.findByIsPublicTrue()).thenReturn(List.of()); when(scriptAssetRepository.findByIsPublicTrue()).thenReturn(List.of());
List<dev.kruhlmann.imgfloat.model.ScriptMarketplaceEntry> entries = service.listMarketplaceScripts(null, null); List<dev.kruhlmann.imgfloat.model.api.response.ScriptMarketplaceEntry> entries = service.listMarketplaceScripts(null, null);
assertThat(entries) assertThat(entries)
.anyMatch((entry) -> "rotating-logo".equals(entry.id())); .anyMatch((entry) -> "rotating-logo".equals(entry.id()));
@@ -229,7 +229,7 @@ class ChannelDirectoryServiceTest {
request.setAllowedDomains(List.of("example.com")); request.setAllowedDomains(List.of("example.com"));
AssetView created = service.createCodeAsset("caster", request, "caster").orElseThrow(); AssetView created = service.createCodeAsset("caster", request, "caster").orElseThrow();
scriptAssetRepository.findById(created.id()).ifPresent((script) -> script.setSourceFileId(created.id())); scriptAssetRepository.findById(created.id()).ifPresent((script) -> script.setSourceFileId(created.id()));
scriptAssetFileRepository.save(new dev.kruhlmann.imgfloat.model.ScriptAssetFile("caster", AssetType.SCRIPT) { scriptAssetFileRepository.save(new dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile("caster", AssetType.SCRIPT) {
{ {
setId(created.id()); setId(created.id());
} }
@@ -271,10 +271,10 @@ class ChannelDirectoryServiceTest {
private void setupInMemoryPersistence() { private void setupInMemoryPersistence() {
Map<String, Channel> channels = new ConcurrentHashMap<>(); Map<String, Channel> channels = new ConcurrentHashMap<>();
Map<String, Asset> assets = new ConcurrentHashMap<>(); Map<String, Asset> assets = new ConcurrentHashMap<>();
Map<String, dev.kruhlmann.imgfloat.model.VisualAsset> visualAssets = new ConcurrentHashMap<>(); Map<String, dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset> visualAssets = new ConcurrentHashMap<>();
Map<String, AudioAsset> audioAssets = new ConcurrentHashMap<>(); Map<String, AudioAsset> audioAssets = new ConcurrentHashMap<>();
Map<String, ScriptAsset> scriptAssets = new ConcurrentHashMap<>(); Map<String, ScriptAsset> scriptAssets = new ConcurrentHashMap<>();
Map<String, dev.kruhlmann.imgfloat.model.ScriptAssetFile> scriptFiles = new ConcurrentHashMap<>(); Map<String, dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile> scriptFiles = new ConcurrentHashMap<>();
when(channelRepository.findById(anyString())).thenAnswer((invocation) -> when(channelRepository.findById(anyString())).thenAnswer((invocation) ->
Optional.ofNullable(channels.get(invocation.getArgument(0))) Optional.ofNullable(channels.get(invocation.getArgument(0)))
@@ -317,9 +317,9 @@ class ChannelDirectoryServiceTest {
.when(assetRepository) .when(assetRepository)
.delete(any(Asset.class)); .delete(any(Asset.class));
when(visualAssetRepository.save(any(dev.kruhlmann.imgfloat.model.VisualAsset.class))).thenAnswer( when(visualAssetRepository.save(any(dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset.class))).thenAnswer(
(invocation) -> { (invocation) -> {
dev.kruhlmann.imgfloat.model.VisualAsset visual = invocation.getArgument(0); dev.kruhlmann.imgfloat.model.db.imgfloat.VisualAsset visual = invocation.getArgument(0);
visualAssets.put(visual.getId(), visual); visualAssets.put(visual.getId(), visual);
return visual; return visual;
} }
@@ -388,9 +388,9 @@ class ChannelDirectoryServiceTest {
.when(scriptAssetRepository) .when(scriptAssetRepository)
.deleteById(anyString()); .deleteById(anyString());
when(scriptAssetFileRepository.save(any(dev.kruhlmann.imgfloat.model.ScriptAssetFile.class))).thenAnswer( when(scriptAssetFileRepository.save(any(dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile.class))).thenAnswer(
(invocation) -> { (invocation) -> {
dev.kruhlmann.imgfloat.model.ScriptAssetFile file = invocation.getArgument(0); dev.kruhlmann.imgfloat.model.db.imgfloat.ScriptAssetFile file = invocation.getArgument(0);
if (file.getId() == null) { if (file.getId() == null) {
file.setId(java.util.UUID.randomUUID().toString()); file.setId(java.util.UUID.randomUUID().toString());
} }