Skip to content

Commit df576ef

Browse files
authored
fix: file param validation (#808)
1 parent 407150a commit df576ef

16 files changed

+73
-16
lines changed

src/main/java/com/crowdin/cli/client/CrowdinProjectClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.crowdin.cli.client;
22

3+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
34
import com.crowdin.cli.utils.Utils;
45
import com.crowdin.client.branches.model.*;
56
import com.crowdin.client.core.model.PatchRequest;
@@ -69,7 +70,7 @@ private void populateProjectWithStructure(CrowdinProjectFull project, String bra
6970
project.setBranches(this.listBranches());
7071
Optional.ofNullable(branchName)
7172
.map(name -> project.findBranchByName(name)
72-
.orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.not_found_branch")))
73+
.orElseThrow(() -> new ExitCodeExceptionMapper.NotFoundException(RESOURCE_BUNDLE.getString("error.not_found_branch")))
7374
)
7475
.ifPresent(project::setBranch);
7576
Long branchId = Optional.ofNullable(project.getBranch()).map(Branch::getId).orElse(null);

src/main/java/com/crowdin/cli/commands/actions/FileDeleteAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.crowdin.cli.client.ProjectClient;
55
import com.crowdin.cli.commands.NewAction;
66
import com.crowdin.cli.commands.Outputter;
7+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
78
import com.crowdin.cli.properties.ProjectProperties;
89
import com.crowdin.cli.utils.Utils;
910
import com.crowdin.cli.utils.console.ConsoleSpinner;
@@ -41,7 +42,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien
4142
FileInfo foundFile = projectFiles.stream()
4243
.filter(f -> Objects.equals(filePath, f.getPath()))
4344
.findFirst()
44-
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), filePath)));
45+
.orElseThrow(() -> new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), filePath)));
4546
client.deleteSource(foundFile.getId());
4647
out.println(ExecutionStatus.OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.file_deleted"), filePath)));
4748
}

src/main/java/com/crowdin/cli/commands/actions/FileDownloadAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.crowdin.cli.commands.Outputter;
77
import com.crowdin.cli.commands.functionality.FilesInterface;
88
import com.crowdin.cli.commands.functionality.FsFiles;
9+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
910
import com.crowdin.cli.properties.ProjectProperties;
1011
import com.crowdin.cli.utils.Utils;
1112
import com.crowdin.cli.utils.console.ConsoleSpinner;
@@ -50,7 +51,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien
5051
FileInfo foundFile = project.getFileInfos().stream()
5152
.filter(f -> Objects.equals(filePath, f.getPath()))
5253
.findFirst()
53-
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), filePath)));
54+
.orElseThrow(() -> new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), filePath)));
5455
ConsoleSpinner.execute(
5556
out,
5657
"message.spinner.downloading_file",

src/main/java/com/crowdin/cli/commands/actions/FileDownloadTranslationAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.crowdin.cli.commands.Outputter;
77
import com.crowdin.cli.commands.functionality.FilesInterface;
88
import com.crowdin.cli.commands.functionality.FsFiles;
9+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
910
import com.crowdin.cli.properties.ProjectProperties;
1011
import com.crowdin.cli.utils.PlaceholderUtil;
1112
import com.crowdin.cli.utils.Utils;
@@ -67,7 +68,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien
6768
FileInfo sourceFileInfo = project.getFileInfos().stream()
6869
.filter(fi -> Objects.equals(sourcePath, fi.getPath()))
6970
.findFirst()
70-
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), sourcePath)));
71+
.orElseThrow(() -> new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), sourcePath)));
7172
PlaceholderUtil placeholderUtil = new PlaceholderUtil(
7273
project.getSupportedLanguages(),
7374
project.getProjectLanguages(true),

src/main/java/com/crowdin/cli/commands/actions/FileUploadTranslationAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void act(Outputter out, ProjectProperties properties, ProjectClient clien
6262
FileInfo sourceFileInfo = project.getFileInfos().stream()
6363
.filter(fi -> Objects.equals(sourcePath, fi.getPath()))
6464
.findFirst()
65-
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), sourcePath)));
65+
.orElseThrow(() -> new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), sourcePath)));
6666

6767
UploadTranslationsRequest request = new UploadTranslationsRequest();
6868
Long storageId = getStorageId(client);

src/main/java/com/crowdin/cli/commands/actions/StatusAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.crowdin.cli.commands.NewAction;
66
import com.crowdin.cli.commands.Outputter;
77
import com.crowdin.cli.commands.functionality.BranchUtils;
8+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
89
import com.crowdin.cli.properties.ProjectProperties;
910
import com.crowdin.cli.utils.Utils;
1011
import com.crowdin.cli.utils.console.ConsoleSpinner;
@@ -45,7 +46,7 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) {
4546

4647
List<Branch> branches = client.listBranches();
4748
Long branchId = (branchName == null) ? null : BranchUtils.getBranch(branchName, branches)
48-
.orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.not_found_branch")))
49+
.orElseThrow(() -> new ExitCodeExceptionMapper.NotFoundException(RESOURCE_BUNDLE.getString("error.not_found_branch")))
4950
.getId();
5051

5152
List<LanguageProgress> progresses;

src/main/java/com/crowdin/cli/commands/functionality/FsFiles.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.crowdin.cli.commands.functionality;
22

3+
import com.crowdin.cli.commands.picocli.ExitCodeExceptionMapper;
34
import com.crowdin.cli.utils.file.FileUtils;
45
import net.lingala.zip4j.ZipFile;
56
import net.lingala.zip4j.model.FileHeader;
@@ -40,7 +41,7 @@ public List<File> extractZipArchive(File zipArchive, File dir) {
4041
try {
4142
zipFile = new ZipFile(zipArchive);
4243
} catch (IllegalArgumentException e) {
43-
throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.archive_not_exist"), zipArchive.getAbsolutePath()));
44+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.archive_not_exist"), zipArchive.getAbsolutePath()));
4445
}
4546
if (!dir.exists()) {
4647
try {
@@ -80,7 +81,7 @@ public List<String> zipArchiveContent(File zipArchive) {
8081
try {
8182
zipFile = new ZipFile(zipArchive);
8283
} catch (IllegalArgumentException e) {
83-
throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.archive_not_exist"), zipArchive.getAbsolutePath()));
84+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.archive_not_exist"), zipArchive.getAbsolutePath()));
8485
}
8586
try {
8687
List<FileHeader> fileHeaders = zipFile.getFileHeaders();

src/main/java/com/crowdin/cli/commands/picocli/ConfigurationFilesProperties.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public File getConfigFile() {
2424
configFile = this.getDefaultConfigFile();
2525
} else if (!configFile.exists()) {
2626
throw new ExitCodeExceptionMapper.NotFoundException(RESOURCE_BUNDLE.getString("error.configuration_file_not_exist"));
27+
} else if (configFile.isDirectory()) {
28+
throw new ExitCodeExceptionMapper.ValidationException(RESOURCE_BUNDLE.getString("error.file.is_folder"));
2729
}
2830
return configFile;
2931
}
@@ -33,6 +35,8 @@ public File getIdentityFile() {
3335
identityFile = this.getDefaultIdentityFile();
3436
} else if (!identityFile.exists()) {
3537
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.identity_file_not_exist"), identityFile.getAbsolutePath()));
38+
} else if (configFile.isDirectory()) {
39+
throw new ExitCodeExceptionMapper.ValidationException(RESOURCE_BUNDLE.getString("error.file.is_folder"));
3640
}
3741
return identityFile;
3842
}

src/main/java/com/crowdin/cli/commands/picocli/FileUploadSubcommand.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ class FileUploadSubcommand extends ActCommandProject {
6060

6161
@Override
6262
protected List<String> checkOptions() {
63+
if (!file.exists()) {
64+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), file));
65+
}
6366
List<String> errors = new ArrayList<>();
6467
if (parserVersion != null && type == null) {
6568
errors.add(RESOURCE_BUNDLE.getString("error.file.type_required"));
6669
}
70+
if (file.isDirectory()) {
71+
errors.add(RESOURCE_BUNDLE.getString("error.file.is_folder"));
72+
}
6773
return errors;
6874
}
6975

src/main/java/com/crowdin/cli/commands/picocli/GlossaryUploadSubcommand.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ protected NewAction<BaseProperties, ClientGlossary> getAction(Actions actions) {
4646
protected List<String> checkOptions() {
4747
List<String> errors = new ArrayList<>();
4848
if (!file.exists()) {
49-
errors.add(String.format("File '%s' doesn't exist", file));
49+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), file));
50+
}
51+
if (file.isDirectory()) {
52+
errors.add(RESOURCE_BUNDLE.getString("error.file.is_folder"));
5053
}
5154
if (!equalsAny(FilenameUtils.getExtension(file.getName()), "tbx", "csv", "xls", "xlsx")) {
5255
errors.add(RESOURCE_BUNDLE.getString("error.glossary.wrong_format"));

src/main/java/com/crowdin/cli/commands/picocli/ScreenshotUploadSubcommand.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,14 @@ protected NewAction<ProjectProperties, ClientScreenshot> getAction(Actions actio
5252

5353
@Override
5454
protected List<String> checkOptions() {
55+
if (!file.exists()) {
56+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), file));
57+
}
5558
List<String> errors = new ArrayList<>();
5659
String extension = FilenameUtils.getExtension(file.getName());
60+
if (file.isDirectory()) {
61+
errors.add(RESOURCE_BUNDLE.getString("error.file.is_folder"));
62+
}
5763
if (!equalsAny(extension, "jpeg", "jpg", "png", "gif")) {
5864
errors.add(RESOURCE_BUNDLE.getString("error.screenshot.wrong_format"));
5965
}

src/main/java/com/crowdin/cli/commands/picocli/TmUploadSubcommand.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ protected NewAction<BaseProperties, ClientTm> getAction(Actions actions) {
4646
protected List<String> checkOptions() {
4747
List<String> errors = new ArrayList<>();
4848
String extension = FilenameUtils.getExtension(file.getName());
49+
if (!file.exists()) {
50+
throw new ExitCodeExceptionMapper.NotFoundException(String.format(RESOURCE_BUNDLE.getString("error.file_not_found"), file));
51+
}
52+
if (file.isDirectory()) {
53+
errors.add(RESOURCE_BUNDLE.getString("error.file.is_folder"));
54+
}
4955
if (scheme == null && ("csv".equalsIgnoreCase(extension) || "xslx".equalsIgnoreCase(extension))) {
5056
errors.add(RESOURCE_BUNDLE.getString("error.tm.scheme_is_required"));
5157
}

src/main/resources/messages/messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ error.label.not_found=Couldn't find label by the specified title
583583

584584
error.file.dest_required='dest' parameter required to specify source file path
585585
error.file.type_required='--type' is required for '--parser-version' option
586+
error.file.is_folder=The specified file is a directory
586587
error.file.context_file_based_only='--context' parameter is only available for file-based projects
587588

588589
error.branch.clone=Failed to clone the branch

src/test/java/com/crowdin/cli/commands/picocli/FileUploadSubcommandTest.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@
22

33
import org.junit.jupiter.api.Test;
44

5+
import java.net.URISyntaxException;
6+
import java.nio.file.Path;
7+
58
import static org.mockito.ArgumentMatchers.any;
69
import static org.mockito.ArgumentMatchers.anyBoolean;
710
import static org.mockito.Mockito.verify;
811

912
class FileUploadSubcommandTest extends PicocliTestUtils {
1013

1114
@Test
12-
public void testFileUpload() {
13-
this.execute(CommandNames.FILE, CommandNames.FILE_UPLOAD, "file.txt");
15+
public void testFileUpload() throws URISyntaxException {
16+
var file = Path.of(this.getClass().getClassLoader().getResource("file.txt").toURI()).toFile();
17+
this.execute(CommandNames.FILE, CommandNames.FILE_UPLOAD, file.getAbsolutePath());
1418
verify(actionsMock).fileUpload(any(), any(), anyBoolean(), any(), any(), any(), any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean());
1519
this.check(true);
1620
}
1721

1822
@Test
19-
public void testFileUploadTranslations() {
20-
this.execute(CommandNames.FILE, CommandNames.FILE_UPLOAD, "file.txt", "--language", "uk");
23+
public void testFileUploadTranslations() throws URISyntaxException {
24+
var file = Path.of(this.getClass().getClassLoader().getResource("file.txt").toURI()).toFile();
25+
this.execute(CommandNames.FILE, CommandNames.FILE_UPLOAD, file.getAbsolutePath(), "--language", "uk");
2126
verify(actionsMock).fileUploadTranslation(any(), any(), any(), any(), anyBoolean());
2227
this.check(true);
2328
}

src/test/java/com/crowdin/cli/commands/picocli/ScreenshotUploadSubcommandTest.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import static org.hamcrest.MatcherAssert.assertThat;
1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818
import static org.junit.jupiter.params.provider.Arguments.arguments;
19+
import static org.mockito.Mockito.*;
1920

2021
public class ScreenshotUploadSubcommandTest extends PicocliTestUtils {
2122

@@ -28,14 +29,21 @@ public void testScreenshotUploadInvalidOptions() {
2829
@MethodSource
2930
public void testSubCommandCheckValidOptions(File file, boolean autoTag, String filePath, String branchName, String directoryPath) {
3031
ScreenshotUploadSubcommand screenshotUploadSubcommand = new ScreenshotUploadSubcommand();
31-
screenshotUploadSubcommand.file = file;
32+
var mockedFile = mock(File.class);
33+
screenshotUploadSubcommand.file = mockedFile;
3234
screenshotUploadSubcommand.autoTag = autoTag;
3335
screenshotUploadSubcommand.filePath = filePath;
3436
screenshotUploadSubcommand.branchName = branchName;
3537
screenshotUploadSubcommand.directoryPath = directoryPath;
3638

39+
when(mockedFile.exists()).thenReturn(true);
40+
when(mockedFile.getName()).thenReturn(file.getName());
41+
3742
List<String> errors = screenshotUploadSubcommand.checkOptions();
3843
assertEquals(Collections.emptyList(), errors);
44+
45+
verify(mockedFile).exists();
46+
verify(mockedFile).getName();
3947
}
4048

4149
public static Stream<Arguments> testSubCommandCheckValidOptions() {
@@ -50,14 +58,21 @@ public static Stream<Arguments> testSubCommandCheckValidOptions() {
5058
@MethodSource
5159
public void testSubCommandCheckInvalidOptions(File file, boolean autoTag, String filePath, String branchName, String directoryPath, List<String> expErrors) {
5260
ScreenshotUploadSubcommand screenshotUploadSubcommand = new ScreenshotUploadSubcommand();
53-
screenshotUploadSubcommand.file = file;
61+
var mockedFile = mock(File.class);
62+
screenshotUploadSubcommand.file = mockedFile;
5463
screenshotUploadSubcommand.autoTag = autoTag;
5564
screenshotUploadSubcommand.filePath = filePath;
5665
screenshotUploadSubcommand.branchName = branchName;
5766
screenshotUploadSubcommand.directoryPath = directoryPath;
5867

68+
when(mockedFile.exists()).thenReturn(true);
69+
when(mockedFile.getName()).thenReturn(file.getName());
70+
5971
List<String> errors = screenshotUploadSubcommand.checkOptions();
6072
assertThat(errors, Matchers.equalTo(expErrors));
73+
74+
verify(mockedFile).exists();
75+
verify(mockedFile).getName();
6176
}
6277

6378
public static Stream<Arguments> testSubCommandCheckInvalidOptions() {

src/test/java/com/crowdin/cli/commands/picocli/TmUploadSubcommandTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package com.crowdin.cli.commands.picocli;
22

3+
import lombok.SneakyThrows;
34
import org.junit.jupiter.api.Test;
45

6+
import java.nio.file.Path;
7+
58
import static org.mockito.ArgumentMatchers.*;
69
import static org.mockito.Mockito.verify;
710

811
public class TmUploadSubcommandTest extends PicocliTestUtils {
912

13+
@SneakyThrows
1014
@Test
1115
public void testTmUpload() {
12-
this.execute(CommandNames.TM, CommandNames.TM_UPLOAD, "file.tmx", "--id", "42", "--debug");
16+
var file = Path.of(this.getClass().getClassLoader().getResource("file.tmx").toURI()).toFile();
17+
this.execute(CommandNames.TM, CommandNames.TM_UPLOAD, file.getAbsolutePath(), "--id", "42", "--debug");
1318
verify(actionsMock)
1419
.tmUpload(any(), eq(42L), isNull(), isNull(), isNull(), anyBoolean());
1520
this.check(true);

0 commit comments

Comments
 (0)