diff --git a/pom.xml b/pom.xml
index 24f35de0a..75ecf99d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,7 +33,7 @@
org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents
- 2.9.0
+ 2.10.0-beta2
1.8.0-beta1
1.5.1
1.5.0-beta1
diff --git a/src/main/java/org/cryptomator/common/FilsystemOwnerSupplier.java b/src/main/java/org/cryptomator/common/FilsystemOwnerSupplier.java
new file mode 100644
index 000000000..addea85ba
--- /dev/null
+++ b/src/main/java/org/cryptomator/common/FilsystemOwnerSupplier.java
@@ -0,0 +1,16 @@
+package org.cryptomator.common;
+
+/**
+ * Objects which has some kind of owner.
+ */
+@FunctionalInterface
+public interface FilsystemOwnerSupplier {
+
+ /**
+ * Get the object owner.
+ *
+ * @return the object owner
+ */
+ String getOwner();
+
+}
diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java
index 75790507c..758ed99a3 100644
--- a/src/main/java/org/cryptomator/common/vaults/Vault.java
+++ b/src/main/java/org/cryptomator/common/vaults/Vault.java
@@ -10,7 +10,7 @@ package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
-import org.cryptomator.event.FileSystemEventAggregator;
+import org.cryptomator.common.FilsystemOwnerSupplier;
import org.cryptomator.common.mount.Mounter;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
@@ -23,6 +23,7 @@ import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.MasterkeyLoader;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
+import org.cryptomator.event.FileSystemEventAggregator;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException;
@@ -145,15 +146,17 @@ public class Vault {
LOG.warn("Limiting cleartext filename length on this device to {}.", vaultSettings.maxCleartextFilenameLength.get());
}
- CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() //
+ var fsPropsBuilder = CryptoFileSystemProperties.cryptoFileSystemProperties() //
.withKeyLoader(keyLoader) //
.withFlags(flags) //
.withMaxCleartextNameLength(vaultSettings.maxCleartextFilenameLength.get()) //
.withVaultConfigFilename(Constants.VAULTCONFIG_FILENAME) //
- .withFilesystemEventConsumer(this::consumeVaultEvent) //
- .withOwner(System.getProperty("user.name"))
- .build();
- return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
+ .withFilesystemEventConsumer(this::consumeVaultEvent);
+ if (keyLoader instanceof FilsystemOwnerSupplier oo) {
+ fsPropsBuilder.withOwnerGetter(oo::getOwner);
+ }
+
+ return CryptoFileSystemProvider.newFileSystem(getPath(), fsPropsBuilder.build());
}
private void destroyCryptoFileSystem() {
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java
index f8710b8c0..97ab2b394 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingModule.java
@@ -66,6 +66,13 @@ public abstract class HubKeyLoadingModule {
return new AtomicReference<>();
}
+ @Provides
+ @Named("userName")
+ @KeyLoadingScoped
+ static AtomicReference provideUserNameRef() {
+ return new AtomicReference<>();
+ }
+
@Provides
@KeyLoadingScoped
static CompletableFuture provideResult() {
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java
index 40f845a63..6bf4c0bff 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/HubKeyLoadingStrategy.java
@@ -2,6 +2,7 @@ package org.cryptomator.ui.keyloading.hub;
import com.google.common.base.Preconditions;
import dagger.Lazy;
+import org.cryptomator.common.FilsystemOwnerSupplier;
import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.keychain.NoKeychainAccessProviderException;
import org.cryptomator.common.settings.DeviceKey;
@@ -23,25 +24,28 @@ import java.net.URI;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
@KeyLoading
-public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
+public class HubKeyLoadingStrategy implements KeyLoadingStrategy, FilsystemOwnerSupplier {
- private static final String SCHEME_PREFIX = "hub+";
+ public static final String SCHEME_PREFIX = "hub+";
public static final String SCHEME_HUB_HTTP = SCHEME_PREFIX + "http";
public static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https";
private final Stage window;
private final KeychainManager keychainManager;
+ private final AtomicReference userName;
private final Lazy authFlowScene;
private final Lazy noKeychainScene;
private final CompletableFuture result;
private final DeviceKey deviceKey;
@Inject
- public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy noKeychainScene, CompletableFuture result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle) {
+ public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy noKeychainScene, CompletableFuture result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle, @Named("userName") AtomicReference userName) {
this.window = window;
this.keychainManager = keychainManager;
+ this.userName = userName;
window.setTitle(windowTitle);
window.setOnCloseRequest(_ -> result.cancel(true));
this.authFlowScene = authFlowScene;
@@ -90,4 +94,13 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
});
}
+ @Override
+ public String getOwner() {
+ var name = userName.get();
+ if (name == null) {
+ throw new IllegalStateException("Owner is not yet determined");
+ }
+ return name;
+ }
+
}
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
index f94d882fa..dd6ae3b68 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
@@ -41,7 +41,6 @@ import java.util.concurrent.atomic.AtomicReference;
public class ReceiveKeyController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(ReceiveKeyController.class);
- private static final String SCHEME_PREFIX = "hub+";
private static final ObjectMapper JSON = new ObjectMapper().setDefaultLeniency(true);
private static final Duration REQ_TIMEOUT = Duration.ofSeconds(10);
@@ -50,6 +49,7 @@ public class ReceiveKeyController implements FxController {
private final String vaultId;
private final String deviceId;
private final String bearerToken;
+ private final AtomicReference userName;
private final CompletableFuture result;
private final Lazy registerDeviceScene;
private final Lazy legacyRegisterDeviceScene;
@@ -59,12 +59,25 @@ public class ReceiveKeyController implements FxController {
private final HttpClient httpClient;
@Inject
- public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, HubConfig hubConfig, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference tokenRef, CompletableFuture result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy registerDeviceScene, @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy legacyRegisterDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy accountInitializationScene, @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy invalidLicenseScene) {
+ public ReceiveKeyController(@KeyLoading Vault vault, //
+ ExecutorService executor, //
+ @KeyLoading Stage window, //
+ HubConfig hubConfig, //
+ @Named("deviceId") String deviceId, //
+ @Named("bearerToken") AtomicReference tokenRef, //
+ @Named("userName") AtomicReference userName, //
+ CompletableFuture result, //
+ @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy registerDeviceScene, //
+ @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy legacyRegisterDeviceScene, //
+ @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy unauthorizedScene, //
+ @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy accountInitializationScene, //
+ @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy invalidLicenseScene) {
this.window = window;
this.hubConfig = hubConfig;
this.vaultId = extractVaultId(vault.getVaultConfigCache().getUnchecked().getKeyId()); // TODO: access vault config's JTI directly (requires changes in cryptofs)
this.deviceId = deviceId;
this.bearerToken = Objects.requireNonNull(tokenRef.get());
+ this.userName = userName;
this.result = result;
this.registerDeviceScene = registerDeviceScene;
this.legacyRegisterDeviceScene = legacyRegisterDeviceScene;
@@ -81,7 +94,34 @@ public class ReceiveKeyController implements FxController {
}
public void receiveKey() {
- requestApiConfig();
+ requestUserData();
+ }
+
+ private void requestUserData() {
+ var userUri = hubConfig.URIs.API.resolve("users/me?withDevices=false");
+ var request = HttpRequest.newBuilder(userUri) //
+ .header("Authorization", "Bearer " + bearerToken) //
+ .GET() //
+ .timeout(REQ_TIMEOUT) //
+ .build();
+ httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)) //
+ .thenAcceptAsync(this::receivedUserData) //
+ .exceptionally(this::retrievalFailed);
+ }
+
+ private void receivedUserData(HttpResponse response) {
+ LOG.debug("GET {} -> Status Code {}", response.request().uri(), response.statusCode());
+ try {
+ if (response.statusCode() == 200) {
+ var user = JSON.reader().readValue(response.body(), UserDto.class);
+ userName.set(user.name);
+ requestApiConfig();
+ } else {
+ throw new IllegalStateException("Unexpected response " + response.statusCode());
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
/**
@@ -289,11 +329,14 @@ public class ReceiveKeyController implements FxController {
}
private static String extractVaultId(URI vaultKeyUri) {
- assert vaultKeyUri.getScheme().startsWith(SCHEME_PREFIX);
+ assert vaultKeyUri.getScheme().startsWith(HubKeyLoadingStrategy.SCHEME_PREFIX);
var path = vaultKeyUri.getPath();
return path.substring(path.lastIndexOf('/') + 1);
}
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ private record UserDto(@JsonProperty(value = "name", required = true) String name) {}
+
@JsonIgnoreProperties(ignoreUnknown = true)
private record DeviceDto(@JsonProperty(value = "userPrivateKey", required = true) String userPrivateKey) {}