Skip to content

Commit

Permalink
Check for existing Mod UUID
Browse files Browse the repository at this point in the history
Fixes #99
  • Loading branch information
micheljung committed Jun 4, 2017
1 parent ab131ff commit 64ced79
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .idea/runConfigurations/FafApiApplication.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions src/main/java/com/faforever/api/error/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public enum ErrorCode {
@Deprecated
MOD_UI_ONLY_MISSING(122, "Missing mod type", "The file mod_info.lua must contain a property 'ui_only'."),
MOD_NAME_TOO_LONG(123, "Invalid mod name", "The mod name must not exceed {0} characters, was: {1}"),
MOD_NOT_ORIGINAL_AUTHOR(124, "Permission denied", "Only the original author is allowed to upload new versions of mod: {0}."),
MOD_VERSION_EXISTS(125, "Duplicate mod version", "Mod ''{0}'' with version ''{1}'' already exists."),
MOD_NOT_ORIGINAL_AUTHOR(124, "Permission denied", "Only the original author ''{0}'' is allowed to upload new versions of mod ''{1}''."),
MOD_VERSION_EXISTS(125, "Duplicate mod version", "A mod with name ''{0}'' and version ''{1}'' already exists."),
MOD_AUTHOR_MISSING(126, "Missing mod author", "The file mod_info.lua must contain a property 'author'."),
QUERY_INVALID_RATING_TYPE(127, "Invalid rating type", "Rating type is not valid: {0}. Please pick '1v1' or 'global'."),
LOGIN_DENIED_BANNED(128, "Login denied", "You are currently banned: {0}"),
Expand Down Expand Up @@ -64,7 +64,8 @@ public enum ErrorCode {
CLAN_GENERATE_LINK_PLAYER_NOT_FOUND(155, "Player not found", "Cannot find player with id ''{0}'' who should be invited to the clan"),
CLAN_NAME_EXISTS(156, "Clan Name already in use", "The clan name ''{0}'' is already in use. Please choose a different clan name."),
CLAN_TAG_EXISTS(157, "Clan Tag already in use", "The clan tag ''{0}'' is already in use. Please choose a different clan tag."),
VALIDATION_FAILED(158, "Validation failed", "{0}");
VALIDATION_FAILED(158, "Validation failed", "{0}"),
MOD_UID_EXISTS(159, "Duplicate mod UID", "A mod with UID ''{0}'' already exists.");

private final int code;
private final String title;
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/com/faforever/api/mod/ModService.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,18 @@ public void processUploadedMod(Path uploadedFile, Player uploader) {
short version = (short) Integer.parseInt(modInfo.getVersion().toString());

if (!canUploadMod(displayName, uploader)) {
throw new ApiException(new Error(ErrorCode.MOD_NOT_ORIGINAL_AUTHOR));
Mod mod = modRepository.findOneByDisplayName(displayName)
.orElseThrow(() -> new IllegalStateException("Mod could not be found"));
throw new ApiException(new Error(ErrorCode.MOD_NOT_ORIGINAL_AUTHOR, mod.getAuthor(), displayName));
}

if (modExists(displayName, version)) {
throw new ApiException(new Error(ErrorCode.MOD_VERSION_EXISTS));
throw new ApiException(new Error(ErrorCode.MOD_VERSION_EXISTS, displayName, version));
}

String uuid = modInfo.getUid();
if (modUidExists(uuid)) {
throw new ApiException(new Error(ErrorCode.MOD_UID_EXISTS, uuid));
}

String zipFileName = generateZipFileName(displayName, version);
Expand Down Expand Up @@ -99,9 +106,14 @@ private boolean modExists(String displayName, short version) {
.setMod(new Mod()
.setDisplayName(displayName)
);

return modVersionRepository.exists(Example.of(probe, ExampleMatcher.matching().withIgnoreCase()));
}

private boolean modUidExists(String uuid) {
return modVersionRepository.existsByUid(uuid);
}

private boolean canUploadMod(String displayName, Player uploader) {
return !modRepository.existsByDisplayNameIgnoreCaseAndUploaderIsNot(displayName, uploader);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@

@Repository
public interface ModVersionRepository extends JpaRepository<ModVersion, Integer> {
boolean existsByUid(String uid);
}
52 changes: 48 additions & 4 deletions src/test/java/com/faforever/api/mod/ModServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@
import com.faforever.api.data.domain.Mod;
import com.faforever.api.data.domain.ModVersion;
import com.faforever.api.data.domain.Player;
import com.faforever.api.error.ApiExceptionWithCode;
import com.faforever.api.error.ErrorCode;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.domain.Example;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
Expand All @@ -29,8 +36,11 @@
public class ModServiceTest {

private static final String TEST_MOD = "/mods/No Friendly Fire.zip";

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Rule
public ExpectedException expectedException = ExpectedException.none();

private ModService instance;

Expand All @@ -51,11 +61,9 @@ public void setUp() throws Exception {
}

@Test
@SuppressWarnings("unchecked")
public void processUploadedMod() throws Exception {
Path uploadedFile = temporaryFolder.getRoot().toPath().resolve("uploaded-mod.zip");
try (InputStream inputStream = new BufferedInputStream(getClass().getResourceAsStream(TEST_MOD))) {
Files.copy(inputStream, uploadedFile);
}
Path uploadedFile = prepareMod();

Player uploader = new Player();

Expand Down Expand Up @@ -83,6 +91,42 @@ public void processUploadedMod() throws Exception {
assertThat(savedModVersion.getMod(), is(savedMod));
assertThat(savedModVersion.isRanked(), is(false));
assertThat(savedModVersion.isHidden(), is(false));

ArgumentCaptor<Example<ModVersion>> exampleCaptor = ArgumentCaptor.forClass((Class) ModVersion.class);
verify(modVersionRepository).exists(exampleCaptor.capture());
verify(modVersionRepository).existsByUid("26778D4E-BA75-5CC2-CBA8-63795BDE74AA");
}

@Test
public void testExistingUid() throws Exception {
Path uploadedFile = prepareMod();

when(modVersionRepository.existsByUid("26778D4E-BA75-5CC2-CBA8-63795BDE74AA")).thenReturn(true);
expectedException.expect(ApiExceptionWithCode.apiExceptionWithCode(ErrorCode.MOD_UID_EXISTS));

instance.processUploadedMod(uploadedFile, new Player());
}

@Test
public void testNotOriginalUploader() throws Exception {
Path uploadedFile = prepareMod();

Player uploader = new Player();
when(modRepository.existsByDisplayNameIgnoreCaseAndUploaderIsNot("No Friendly Fire", uploader)).thenReturn(true);
when(modRepository.findOneByDisplayName("No Friendly Fire")).thenReturn(Optional.of(new Mod()));

expectedException.expect(ApiExceptionWithCode.apiExceptionWithCode(ErrorCode.MOD_NOT_ORIGINAL_AUTHOR));

instance.processUploadedMod(uploadedFile, uploader);
}

@NotNull
private Path prepareMod() throws IOException {
Path uploadedFile = temporaryFolder.getRoot().toPath().resolve("uploaded-mod.zip");
try (InputStream inputStream = new BufferedInputStream(getClass().getResourceAsStream(TEST_MOD))) {
Files.copy(inputStream, uploadedFile);
}
return uploadedFile;
}

// TODO test error cases
Expand Down

0 comments on commit 64ced79

Please sign in to comment.