Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/faforever/api/error/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ public enum ErrorCode {
MALFORMED_URL(208, "Malformed URL", "Provided url ''{0}'' is malformed."),
NOT_ALLOWED_URL_HOST(209, "URL host not allowed", "Provided URL's host is not allowed. URL: ''{0}'', allowed hosts: ''{1}''."),
STEAM_LOGIN_VALIDATION_FAILED(210, "Login via Steam failed", "Invalid OpenID redirect code"),
MAP_VERSION_INVALID_RANGE(211, "Invalid map version", "The map version must be a whole number in range {0, number} to {1, number}."),
MOD_VERSION_INVALID_RANGE(212, "Invalid mod version", "The mod version must be a whole number in range {0, number} to {1, number}."),
;


Expand Down
12 changes: 11 additions & 1 deletion src/main/java/com/faforever/api/map/MapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.regex.Pattern;
import java.util.stream.Stream;

Expand All @@ -75,6 +76,8 @@ public class MapService {
private static final int MAP_NAME_MINUS_MAX_OCCURENCE = 3;
private static final int MAP_NAME_MIN_LENGTH = 4;
private static final int MAP_NAME_MAX_LENGTH = 50;
private static final int MAP_VERSION_MIN_VALUE = 1;
private static final int MAP_VERSION_MAX_VALUE = 9999;

private static final String[] ADAPTIVE_REQUIRED_FILES = new String[]{
"_options.lua",
Expand Down Expand Up @@ -311,8 +314,11 @@ private void validateScenarioLua(MapLuaAccessor mapLua, MapNameBuilder mapNameBu
errors.add(new Error(ErrorCode.MAP_SIZE_MISSING));
}

if (mapLua.getMapVersion().isEmpty()) {
final OptionalInt mapVersion = mapLua.getMapVersion();
if (mapVersion.isEmpty()) {
errors.add(new Error(ErrorCode.MAP_VERSION_MISSING));
} else if (!isMapVersionValidRange(mapVersion.getAsInt())) {
errors.add(new Error(ErrorCode.MAP_VERSION_INVALID_RANGE, MAP_VERSION_MIN_VALUE, MAP_VERSION_MAX_VALUE));
}

if (mapLua.getNoRushRadius().isEmpty()) {
Expand All @@ -325,6 +331,10 @@ private void validateScenarioLua(MapLuaAccessor mapLua, MapNameBuilder mapNameBu
}
}

private static boolean isMapVersionValidRange(int mapVersion) {
return mapVersion >= MAP_VERSION_MIN_VALUE && mapVersion <= MAP_VERSION_MAX_VALUE;
}

private Optional<Error> validateLuaPathVariable(MapLuaAccessor mapLua, String variableName, MapNameBuilder mapNameBuilder, String fileEnding) {
String mapFileName = mapNameBuilder.buildFileName(fileEnding);
String mapFolderNameWithoutVersion = mapNameBuilder.buildFolderNameWithoutVersion();
Expand Down
22 changes: 19 additions & 3 deletions src/main/java/com/faforever/api/mod/ModService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.luaj.vm2.LuaValue;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Example;
Expand Down Expand Up @@ -59,6 +60,9 @@ public class ModService {
*/
public static final String MOD_PATH_PREFIX = "mods/";
private static final Set<String> ALLOWED_REPOSITORY_HOSTS = Set.of("github.com", "gitlab.com");
private static final int MOD_VERSION_MIN_VALUE = 1;
private static final int MOD_VERSION_MAX_VALUE = 9999;

private final FafApiProperties properties;
private final ModRepository modRepository;
private final ModVersionRepository modVersionRepository;
Expand Down Expand Up @@ -235,12 +239,20 @@ private void validateModInfo(com.faforever.commons.mod.Mod modInfo) {
if (nullOrNil(modInfo.getUid())) {
errors.add(new Error(ErrorCode.MOD_UID_MISSING));
}
if (modInfo.getVersion() == null || nullOrNil(modInfo.getVersion().toString())) {

final ComparableVersion modVersion = modInfo.getVersion();
if (modVersion == null || nullOrNil(modVersion.toString())) {
errors.add(new Error(ErrorCode.MOD_VERSION_MISSING));
}
if (Ints.tryParse(modInfo.getVersion().toString()) == null) {
errors.add(new Error(ErrorCode.MOD_VERSION_NOT_A_NUMBER, modInfo.getVersion().toString()));
if (modVersion != null) {
final Integer versionInt = Ints.tryParse(modVersion.toString());
if (versionInt == null) {
errors.add(new Error(ErrorCode.MOD_VERSION_NOT_A_NUMBER, modVersion.toString()));
} else if (!isModVersionValidRange(versionInt)){
errors.add(new Error(ErrorCode.MOD_VERSION_INVALID_RANGE, MOD_VERSION_MIN_VALUE, MOD_VERSION_MAX_VALUE));
}
}

if (nullOrNil(modInfo.getDescription())) {
errors.add(new Error(ErrorCode.MOD_DESCRIPTION_MISSING));
}
Expand All @@ -253,6 +265,10 @@ private void validateModInfo(com.faforever.commons.mod.Mod modInfo) {
}
}

private static boolean isModVersionValidRange(int modVersion) {
return modVersion >= MOD_VERSION_MIN_VALUE && modVersion <= MOD_VERSION_MAX_VALUE;
}

@SneakyThrows
private Optional<Path> extractThumbnail(Path modZipFile, short version, String displayName, String icon) {
if (icon == null) {
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/com/faforever/api/map/MapServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,23 @@ void testScenarioLuaWrongMapLine() {
assertThat(mapLineError.getArgs()[0], is("map = '/maps/mirage/mirage.scmap'"));
}

@Test
void testScenarioLuaMapVersionOutOfRange() {
ApiException result = assertThrows(ApiException.class, () ->
instance.validateScenarioLua(loadMapAsString("scenario/invalid_lua_map_version_scenario.lua")));

assertThat(result, hasErrorCodes(
ErrorCode.MAP_VERSION_INVALID_RANGE
));

assertThat(result.getErrors().length, is(1));
Error mapLineError = Arrays.stream(result.getErrors())
.filter(error -> error.getErrorCode() == ErrorCode.MAP_VERSION_INVALID_RANGE)
.findFirst().get();

assertThat(mapLineError.getArgs().length, is(2));
}

@Test
void authorBannedFromVault() {
when(fafApiProperties.getMap()).thenReturn(new Map().setAllowedExtensions(Set.of("zip")));
Expand Down
10 changes: 10 additions & 0 deletions src/test/java/com/faforever/api/mod/ModServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
Expand Down Expand Up @@ -222,6 +224,14 @@ public void testVersionNotANumber() throws Exception {
assertThat(result, hasErrorCode(ErrorCode.MOD_VERSION_NOT_A_NUMBER));
}

@ParameterizedTest
@ValueSource(ints = {0, 10_000})
public void testVersionOutOfRange(final int testVersion) throws Exception {
Path uploadFile = prepareModDynamic(luaContent().setVersion(Integer.toString(testVersion)));
ApiException result = assertThrows(ApiException.class, () -> instance.processUploadedMod(uploadFile, TEST_MOD_FILENAME, new Player(), null, null));
assertThat(result, hasErrorCode(ErrorCode.MOD_VERSION_INVALID_RANGE));
}

@Test
public void testDescriptionMissing() throws Exception {
Path uploadFile = prepareModDynamic(luaContent().setDesc(null));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version = 3 -- Lua Version. Dont touch this
ScenarioInfo = {
name = "Mirage",
description = "Map By: Morax",
preview = '',
map_version = 10123,
type = 'skirmish',
starts = true,
size = {256, 256},
map = '/maps/mirage/mirage.scmap',
save = '/maps/mirage/mirage_save.lua',
script = '/maps/mirage/mirage_script.lua',
norushradius = 40,
Configurations = {
['standard'] = {
teams = {
{
name = 'FFA',
armies = {'ARMY_1', 'ARMY_2'}
},
},
customprops = {
['ExtraArmies'] = STRING( 'ARMY_17 NEUTRAL_CIVILIAN' ),
},
},
},
}
Loading