Skip to content

Commit d736cd8

Browse files
committed
Merge branch 'release/1.1.2'
2 parents 07b89f5 + 7e6d737 commit d736cd8

File tree

8 files changed

+55
-17
lines changed

8 files changed

+55
-17
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Windows-specific implementations of [integrations-api](https://github.com/crypto
66

77
This project uses the following JVM properties:
88
* `cryptomator.integrationsWin.autoStartShellLinkName` - Name of the shell link, which is placed in the Windows startup folder to start application on user login
9+
* `cryptomator.integrationsWin.keychainPaths` - Colon separated list of paths, which are checked for encrypted data
910

1011
## Building
1112

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>org.cryptomator</groupId>
77
<artifactId>integrations-win</artifactId>
8-
<version>1.1.1</version>
8+
<version>1.1.2</version>
99

1010
<name>Cryptomator Integrations for Windows</name>
1111
<description>Provides optional Windows services used by Cryptomator</description>

src/main/java/org/cryptomator/windows/keychain/WindowsProtectedKeychainAccess.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,15 @@
3737

3838
import static java.nio.charset.StandardCharsets.UTF_8;
3939

40+
/**
41+
* Windows implementation for the {@link KeychainAccessProvider} based on the <a href="https://en.wikipedia.org/wiki/Data_Protection_API">data protection API</a>.
42+
* The storage locations to check for encrypted data can be set with the JVM property {@value KEYCHAIN_PATHS_PROPERTY} as a colon({@value PATH_LIST_SEP}) separated list of paths.
43+
*/
4044
@Priority(1000)
4145
@OperatingSystem(OperatingSystem.Value.WINDOWS)
4246
public class WindowsProtectedKeychainAccess implements KeychainAccessProvider {
4347

48+
private static final String KEYCHAIN_PATHS_PROPERTY = "cryptomator.integrationsWin.keychainPaths";
4449
private static final Logger LOG = LoggerFactory.getLogger(WindowsProtectedKeychainAccess.class);
4550
private static final String PATH_LIST_SEP = ":";
4651
private static final Path USER_HOME_REL = Path.of("~");
@@ -67,16 +72,12 @@ public WindowsProtectedKeychainAccess() {
6772
}
6873

6974
private static List<Path> readKeychainPathsFromEnv() {
70-
String rawPaths = System.getProperty("cryptomator.keychainPath");
71-
if (rawPaths == null) {
72-
return List.of();
73-
} else {
74-
return Arrays.stream(rawPaths.split(PATH_LIST_SEP))
75-
.filter(Predicate.not(String::isEmpty))
76-
.map(Path::of)
77-
.map(WindowsProtectedKeychainAccess::resolveHomeDir)
78-
.collect(Collectors.toList());
79-
}
75+
return Optional.ofNullable(System.getProperty(KEYCHAIN_PATHS_PROPERTY))
76+
.stream().flatMap(rawPaths -> Arrays.stream(rawPaths.split(PATH_LIST_SEP)))
77+
.filter(Predicate.not(String::isEmpty))
78+
.map(Path::of)
79+
.map(WindowsProtectedKeychainAccess::resolveHomeDir)
80+
.collect(Collectors.toList());
8081
}
8182

8283
private static Path resolveHomeDir(Path path) {
@@ -176,13 +177,14 @@ private void loadKeychainEntriesIfNeeded() throws KeychainAccessException {
176177
}
177178
}
178179

179-
private Optional<Map<String, KeychainEntry>> loadKeychainEntries(Path keychainPath) throws KeychainAccessException {
180+
//visible for testing
181+
Optional<Map<String, KeychainEntry>> loadKeychainEntries(Path keychainPath) throws KeychainAccessException {
180182
LOG.debug("Attempting to load keychain from {}", keychainPath);
181183
Type type = new TypeToken<Map<String, KeychainEntry>>() {
182184
}.getType();
183185
try (InputStream in = Files.newInputStream(keychainPath, StandardOpenOption.READ); //
184186
Reader reader = new InputStreamReader(in, UTF_8)) {
185-
return Optional.of(GSON.fromJson(reader, type));
187+
return Optional.ofNullable(GSON.fromJson(reader, type));
186188
} catch (NoSuchFileException | JsonParseException e) {
187189
return Optional.empty();
188190
} catch (IOException e) {

src/main/resources/WinIntegrationsBundle_be.properties

Whitespace-only changes.

src/main/resources/WinIntegrationsBundle_si.properties

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.cryptomator.windows.keychain.displayName=Bảo vệ Dữ liệu Windows
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.cryptomator.windows.keychain.displayName=Windows 數據保護
Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,64 @@
11
package org.cryptomator.windows.keychain;
22

3+
import org.cryptomator.integrations.keychain.KeychainAccessException;
34
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
45
import org.junit.jupiter.api.Assertions;
5-
import org.junit.jupiter.api.Assumptions;
66
import org.junit.jupiter.api.BeforeAll;
7+
import org.junit.jupiter.api.BeforeEach;
78
import org.junit.jupiter.api.DisplayName;
9+
import org.junit.jupiter.api.Nested;
810
import org.junit.jupiter.api.Test;
911
import org.junit.jupiter.api.io.TempDir;
1012

13+
import java.io.IOException;
14+
import java.nio.file.Files;
1115
import java.nio.file.Path;
16+
import java.util.Objects;
1217

1318
public class KeychainAccessProviderTest {
1419

1520
@BeforeAll
1621
public static void setup(@TempDir Path tmpDir) {
1722
Path keychainPath = tmpDir.resolve("keychain.tmp");
18-
System.setProperty("cryptomator.keychainPath", keychainPath.toString());
23+
System.setProperty("cryptomator.integrationsWin.keychainPaths", keychainPath.toString());
1924
}
2025

2126
@Test
2227
@DisplayName("WindowsProtectedKeychainAccess can be loaded")
2328
public void testLoadWindowsProtectedKeychainAccess() {
24-
Assumptions.assumeFalse(System.getProperty("cryptomator.keychainPath", "").isBlank());
25-
2629
var windowsKeychainAccessProvider = KeychainAccessProvider.get().findAny();
30+
2731
Assertions.assertTrue(windowsKeychainAccessProvider.isPresent());
2832
Assertions.assertInstanceOf(WindowsProtectedKeychainAccess.class, windowsKeychainAccessProvider.get());
2933
}
3034

35+
@Nested
36+
public class LoadKeyChainEntries {
37+
38+
Path keychainPath;
39+
WindowsProtectedKeychainAccess keychainAccess;
40+
41+
@BeforeEach
42+
public void init(@TempDir Path tmpDir) {
43+
keychainPath = tmpDir.resolve("keychain.tmp");
44+
keychainAccess = (WindowsProtectedKeychainAccess) KeychainAccessProvider.get().findAny().get();
45+
}
46+
47+
@Test
48+
public void testNonExistingFileReturnsEmpty() throws KeychainAccessException, IOException {
49+
var result = keychainAccess.loadKeychainEntries(keychainPath);
50+
51+
Assertions.assertTrue(result.isEmpty());
52+
}
53+
54+
@Test
55+
public void testEmptyFileReturnsEmpty() throws KeychainAccessException, IOException {
56+
Files.write(keychainPath, new byte[] {});
57+
58+
var result = keychainAccess.loadKeychainEntries(keychainPath);
59+
60+
Assertions.assertTrue(result.isEmpty());
61+
}
62+
}
63+
3164
}

0 commit comments

Comments
 (0)