diff --git a/compose.yaml b/compose.yaml index 8cb21feab..a889acf94 100644 --- a/compose.yaml +++ b/compose.yaml @@ -16,7 +16,7 @@ services: - "3306:3306" faf-db-migrations: - image: faforever/faf-db-migrations:v140 + image: faforever/faf-db-migrations:v144 command: migrate environment: FLYWAY_URL: jdbc:mysql://faf-db/faf?useSSL=false @@ -35,7 +35,7 @@ services: condition: service_completed_successfully minio: - image: docker.io/bitnami/minio:2025 + image: docker.io/alpine/minio:latest-release ports: - '9000:9000' - '9001:9001' diff --git a/src/inttest/java/com/faforever/api/config/MainDbTestContainers.java b/src/inttest/java/com/faforever/api/config/MainDbTestContainers.java index 335e6bbea..c9866a4de 100644 --- a/src/inttest/java/com/faforever/api/config/MainDbTestContainers.java +++ b/src/inttest/java/com/faforever/api/config/MainDbTestContainers.java @@ -21,7 +21,7 @@ @Configuration public class MainDbTestContainers { private static final MariaDBContainer fafDBContainer = new MariaDBContainer<>("mariadb:11.7"); - private static final GenericContainer flywayMigrationsContainer = new GenericContainer<>("faforever/faf-db-migrations:v140"); + private static final GenericContainer flywayMigrationsContainer = new GenericContainer<>("faforever/faf-db-migrations:v144"); private static final Network sharedNetwork = Network.newNetwork(); @Bean diff --git a/src/inttest/resources/sql/prepMapData.sql b/src/inttest/resources/sql/prepMapData.sql index afabf4334..6f57debbe 100644 --- a/src/inttest/resources/sql/prepMapData.sql +++ b/src/inttest/resources/sql/prepMapData.sql @@ -2,9 +2,9 @@ INSERT INTO map (id, display_name, map_type, battle_type, author, license) VALUE (1, 'SCMP_001', 'FFA', 'skirmish', 1, 1), (2, 'SCMP_002', 'FFA', 'skirmish', 1, 1); -INSERT INTO map_version (id, description, max_players, width, height, version, filename, hidden, map_id) VALUES - (1, 'SCMP 001', 8, 5, 5, 1, 'maps/scmp_001.v0001.zip', 0, 1), - (2, 'SCMP 002', 8, 5, 5, 1, 'maps/scmp_002.v0001.zip', 0, 2); +INSERT INTO map_version (id, description, max_players, width, height, version, folder_name, hidden, map_id) VALUES + (1, 'SCMP 001', 8, 5, 5, 1, 'scmp_001.v0001', 0, 1), + (2, 'SCMP 002', 8, 5, 5, 1, 'scmp_002.v0001', 0, 2); INSERT INTO map_pool (id, name) VALUES (1, 'Ladder 1v1 <300'), diff --git a/src/inttest/resources/sql/prepMapVersion.sql b/src/inttest/resources/sql/prepMapVersion.sql index e384c87d0..ede6b0279 100644 --- a/src/inttest/resources/sql/prepMapVersion.sql +++ b/src/inttest/resources/sql/prepMapVersion.sql @@ -1,6 +1,6 @@ INSERT INTO map (id, display_name, map_type, battle_type, author, recommended, license) VALUES (1, 'display name', 'mtype', 'btype', 1, false, 1); -INSERT INTO map_version (id, description, max_players, width, height, version, filename, map_id, hidden, ranked) -VALUES (1, 'des', 2, 2, 2, 1, 'map/ghb.zip', 1, 0, 1); +INSERT INTO map_version (id, description, max_players, width, height, version, folder_name, map_id, hidden, ranked) +VALUES (1, 'des', 2, 2, 2, 1, 'ghb', 1, 0, 1); INSERT INTO map_reviews_summary (id, map_id, positive, negative, score, reviews, lower_bound) VALUES (1, 1, 0, 0, 2, 1, 0); INSERT INTO map_version_reviews_summary (id, map_version_id, positive, negative, score, reviews, lower_bound) diff --git a/src/main/java/com/faforever/api/data/domain/MapVersion.java b/src/main/java/com/faforever/api/data/domain/MapVersion.java index 5fab0d669..e8322c370 100644 --- a/src/main/java/com/faforever/api/data/domain/MapVersion.java +++ b/src/main/java/com/faforever/api/data/domain/MapVersion.java @@ -11,6 +11,8 @@ import com.yahoo.elide.annotation.Include; import com.yahoo.elide.annotation.UpdatePermission; import lombok.Setter; +import org.hibernate.annotations.Generated; +import org.hibernate.generator.EventType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -82,8 +84,10 @@ public int getVersion() { return version; } - @Column(name = "filename") - @NotNull + // DB-generated from folderName (CONCAT('maps/', folder_name, '.zip')); read-only here. + // No @NotNull: bean validation runs pre-insert before the DB populates this value. + @Column(name = "filename", insertable = false, updatable = false) + @Generated(event = EventType.INSERT) public String getFilename() { return filename; } @@ -138,8 +142,10 @@ public String getDownloadUrl() { return downloadUrl; } - @Transient - @ComputedAttribute + // Immutable after insert: the DB-generated filename and the derived download/ + // thumbnail URLs are all computed from this, so it must not change post-creation. + @Column(name = "folder_name", updatable = false) + @NotNull public String getFolderName() { return folderName; } diff --git a/src/main/java/com/faforever/api/data/listeners/MapVersionEnricher.java b/src/main/java/com/faforever/api/data/listeners/MapVersionEnricher.java index 8c1e6f230..49d628f55 100644 --- a/src/main/java/com/faforever/api/data/listeners/MapVersionEnricher.java +++ b/src/main/java/com/faforever/api/data/listeners/MapVersionEnricher.java @@ -25,11 +25,10 @@ public void init(FafApiProperties apiProperties, EntityCacheEvictor cacheEvictor @PostLoad public void enhance(MapVersion mapVersion) { - String filename = mapVersion.getFilename(); - mapVersion.setDownloadUrl(String.format(apiProperties.getMap().getDownloadUrlFormat(), filename.replace("maps/", ""))); - mapVersion.setThumbnailUrlLarge(String.format(apiProperties.getMap().getLargePreviewsUrlFormat(), filename.replace("maps/", "").replace(".zip", ".png"))); - mapVersion.setThumbnailUrlSmall(String.format(apiProperties.getMap().getSmallPreviewsUrlFormat(), filename.replace("maps/", "").replace(".zip", ".png"))); - mapVersion.setFolderName(filename.substring(filename.indexOf('/') + 1, filename.indexOf(".zip"))); + String folderName = mapVersion.getFolderName(); + mapVersion.setDownloadUrl(String.format(apiProperties.getMap().getDownloadUrlFormat(), folderName + ".zip")); + mapVersion.setThumbnailUrlLarge(String.format(apiProperties.getMap().getLargePreviewsUrlFormat(), folderName + ".png")); + mapVersion.setThumbnailUrlSmall(String.format(apiProperties.getMap().getSmallPreviewsUrlFormat(), folderName + ".png")); } @PostUpdate diff --git a/src/main/java/com/faforever/api/map/MapService.java b/src/main/java/com/faforever/api/map/MapService.java index 27bb1eb2b..683081eb4 100644 --- a/src/main/java/com/faforever/api/map/MapService.java +++ b/src/main/java/com/faforever/api/map/MapService.java @@ -85,7 +85,6 @@ public class MapService { }; private static final Charset MAP_CHARSET = StandardCharsets.ISO_8859_1; - private static final String LEGACY_FOLDER_PREFIX = "maps/"; private final FafApiProperties fafApiProperties; private final MapRepository mapRepository; private final LicenseRepository licenseRepository; @@ -413,7 +412,7 @@ private Map updateHibernateMapEntities(MapLuaAccessor mapLua, Optional exis .setMaxPlayers(standardTeamsConfig.get(CONFIGURATION_STANDARD_TEAMS_ARMIES).length()) .setVersion(mapLua.getMapVersion$()) .setMap(map) - .setFilename(LEGACY_FOLDER_PREFIX + mapNameBuilder.buildFinalZipName(mapLua.getMapVersion$())); + .setFolderName(mapNameBuilder.buildFolderName(mapLua.getMapVersion$())); map.getVersions().add(version); diff --git a/src/test/java/com/faforever/api/map/MapServiceTest.java b/src/test/java/com/faforever/api/map/MapServiceTest.java index adc4985c3..6b59fa828 100644 --- a/src/test/java/com/faforever/api/map/MapServiceTest.java +++ b/src/test/java/com/faforever/api/map/MapServiceTest.java @@ -410,7 +410,7 @@ void positiveUploadTest() throws Exception { assertEquals(256, mapVersion.getHeight()); assertEquals(256, mapVersion.getWidth()); assertEquals(8, mapVersion.getMaxPlayers()); - assertEquals("maps/command_conquer_rush.v0007.zip", mapVersion.getFilename()); + assertEquals("command_conquer_rush.v0007", mapVersion.getFolderName()); assertFalse(Files.exists(tmpDir));