mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-19 19:21:27 +00:00
Merge branch 'develop' into feature/mount-setting-per-vault
This commit is contained in:
@@ -76,6 +76,11 @@ public class DeviceKey {
|
||||
|
||||
private P384KeyPair createAndStoreNewKeyPair(char[] passphrase, Path p12File) throws IOException {
|
||||
var keyPair = P384KeyPair.generate();
|
||||
var tmpFile = p12File.resolveSibling(p12File.getFileName().toString() + ".tmp");
|
||||
if(Files.exists(tmpFile)) {
|
||||
LOG.debug("Leftover from devicekey creation detected. Deleting {}", tmpFile);
|
||||
Files.delete(tmpFile);
|
||||
}
|
||||
LOG.debug("Store new device key to {}", p12File);
|
||||
keyPair.store(p12File, passphrase);
|
||||
return keyPair;
|
||||
|
||||
@@ -176,7 +176,7 @@ public class CreateNewVaultPasswordController implements FxController {
|
||||
// 2. initialize vault:
|
||||
try {
|
||||
MasterkeyLoader loader = ignored -> masterkey.copy();
|
||||
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(CryptorProvider.Scheme.SIV_CTRMAC).withKeyLoader(loader).build();
|
||||
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(CryptorProvider.Scheme.SIV_GCM).withKeyLoader(loader).build();
|
||||
CryptoFileSystemProvider.initialize(path, fsProps, DEFAULT_KEY_ID);
|
||||
|
||||
// 3. write vault-internal readme file:
|
||||
|
||||
@@ -13,6 +13,7 @@ public enum FxmlFile {
|
||||
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
|
||||
HEALTH_START("/fxml/health_start.fxml"), //
|
||||
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
|
||||
HUB_NO_KEYCHAIN("/fxml/hub_no_keychain.fxml"), //
|
||||
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
|
||||
HUB_LICENSE_EXCEEDED("/fxml/hub_license_exceeded.fxml"), //
|
||||
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
|
||||
|
||||
@@ -87,6 +87,13 @@ public abstract class HubKeyLoadingModule {
|
||||
@StringKey(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)
|
||||
abstract KeyLoadingStrategy bindHubKeyLoadingStrategyToHubHttps(HubKeyLoadingStrategy strategy);
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.HUB_NO_KEYCHAIN)
|
||||
@KeyLoadingScoped
|
||||
static Scene provideHubNoKeychainScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene(FxmlFile.HUB_NO_KEYCHAIN);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.HUB_AUTH_FLOW)
|
||||
@KeyLoadingScoped
|
||||
@@ -136,6 +143,11 @@ public abstract class HubKeyLoadingModule {
|
||||
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(NoKeychainController.class)
|
||||
abstract FxController bindNoKeychainController(NoKeychainController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(AuthFlowController.class)
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.cryptomator.ui.keyloading.hub;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.nimbusds.jose.JWEObject;
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.keychain.KeychainManager;
|
||||
import org.cryptomator.common.keychain.NoKeychainAccessProviderException;
|
||||
import org.cryptomator.common.settings.DeviceKey;
|
||||
import org.cryptomator.cryptolib.api.Masterkey;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
|
||||
@@ -31,15 +33,19 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
|
||||
static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https";
|
||||
|
||||
private final Stage window;
|
||||
private final KeychainManager keychainManager;
|
||||
private final Lazy<Scene> authFlowScene;
|
||||
private final Lazy<Scene> noKeychainScene;
|
||||
private final CompletableFuture<JWEObject> result;
|
||||
private final DeviceKey deviceKey;
|
||||
|
||||
@Inject
|
||||
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey, @Named("windowTitle") String windowTitle) {
|
||||
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy<Scene> noKeychainScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle) {
|
||||
this.window = window;
|
||||
this.keychainManager = keychainManager;
|
||||
window.setTitle(windowTitle);
|
||||
this.authFlowScene = authFlowScene;
|
||||
this.noKeychainScene = noKeychainScene;
|
||||
this.result = result;
|
||||
this.deviceKey = deviceKey;
|
||||
}
|
||||
@@ -48,9 +54,16 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
|
||||
public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException {
|
||||
Preconditions.checkArgument(keyId.getScheme().startsWith(SCHEME_PREFIX));
|
||||
try {
|
||||
startAuthFlow();
|
||||
if (!keychainManager.isSupported()) {
|
||||
throw new NoKeychainAccessProviderException();
|
||||
}
|
||||
var keypair = deviceKey.get();
|
||||
showWindow(authFlowScene);
|
||||
var jwe = result.get();
|
||||
return JWEHelper.decrypt(jwe, deviceKey.get().getPrivate());
|
||||
return JWEHelper.decrypt(jwe, keypair.getPrivate());
|
||||
} catch (NoKeychainAccessProviderException e) {
|
||||
showWindow(noKeychainScene);
|
||||
throw new UnlockCancelledException("Unlock canceled due to missing prerequisites", e);
|
||||
} catch (DeviceKey.DeviceKeyRetrievalException e) {
|
||||
throw new MasterkeyLoadingFailedException("Failed to load keypair", e);
|
||||
} catch (CancellationException e) {
|
||||
@@ -63,9 +76,9 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
private void startAuthFlow() {
|
||||
private void showWindow(Lazy<Scene> scene) {
|
||||
Platform.runLater(() -> {
|
||||
window.setScene(authFlowScene.get());
|
||||
window.setScene(scene.get());
|
||||
window.show();
|
||||
Window owner = window.getOwner();
|
||||
if (owner != null) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class NoKeychainController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final FxApplicationWindows appWindows;
|
||||
|
||||
@Inject
|
||||
public NoKeychainController(@KeyLoading Stage window, FxApplicationWindows appWindows) {
|
||||
this.window = window;
|
||||
this.appWindows = appWindows;
|
||||
}
|
||||
|
||||
|
||||
public void cancel() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
public void openPreferences() {
|
||||
appWindows.showPreferencesWindow(SelectedPreferencesTab.GENERAL);
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
@@ -39,8 +39,8 @@ public class AwtTrayMenuController implements TrayMenuController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTrayIcon(byte[] rawImageData, Runnable defaultAction, String tooltip) throws TrayMenuException {
|
||||
var image = Toolkit.getDefaultToolkit().createImage(rawImageData);
|
||||
public void showTrayIcon(byte[] imageData, Runnable defaultAction, String tooltip) throws TrayMenuException {
|
||||
var image = Toolkit.getDefaultToolkit().createImage(imageData);
|
||||
trayIcon = new TrayIcon(image, tooltip, menu);
|
||||
|
||||
trayIcon.setImageAutoSize(true);
|
||||
@@ -56,6 +56,15 @@ public class AwtTrayMenuController implements TrayMenuController {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTrayIcon(byte[] imageData) {
|
||||
if (trayIcon == null) {
|
||||
throw new IllegalStateException("Failed to update the icon as it has not yet been added");
|
||||
}
|
||||
var image = Toolkit.getDefaultToolkit().createImage(imageData);
|
||||
trayIcon.setImage(image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTrayMenu(List<TrayMenuItem> items) {
|
||||
menu.removeAll();
|
||||
|
||||
@@ -33,7 +33,9 @@ public class TrayMenuBuilder {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TrayMenuBuilder.class);
|
||||
private static final String TRAY_ICON_MAC = "/img/tray_icon_mac@2x.png";
|
||||
private static final String TRAY_ICON = "/img/window_icon_32.png";
|
||||
private static final String TRAY_ICON_UNLOCKED_MAC = "/img/tray_icon_unlocked_mac@2x.png";
|
||||
private static final String TRAY_ICON = "/img/tray_icon.png";
|
||||
private static final String TRAY_ICON_UNLOCKED = "/img/tray_icon_unlocked.png";
|
||||
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final VaultService vaultService;
|
||||
@@ -62,8 +64,8 @@ public class TrayMenuBuilder {
|
||||
v.displayNameProperty().addListener(this::vaultListChanged);
|
||||
});
|
||||
|
||||
try (var image = getClass().getResourceAsStream(SystemUtils.IS_OS_MAC_OSX ? TRAY_ICON_MAC : TRAY_ICON)) {
|
||||
trayMenu.showTrayIcon(image.readAllBytes(), this::showMainWindow, "Cryptomator");
|
||||
try {
|
||||
trayMenu.showTrayIcon(getAppropriateTrayIconImage(), this::showMainWindow, "Cryptomator");
|
||||
trayMenu.onBeforeOpenMenu(() -> {
|
||||
for (Vault vault : vaults) {
|
||||
VaultListManager.redetermineVaultState(vault);
|
||||
@@ -71,8 +73,6 @@ public class TrayMenuBuilder {
|
||||
});
|
||||
rebuildMenu();
|
||||
initialized = true;
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to load embedded resource", e);
|
||||
} catch (TrayMenuException e) {
|
||||
LOG.error("Adding tray icon failed", e);
|
||||
}
|
||||
@@ -84,6 +84,7 @@ public class TrayMenuBuilder {
|
||||
|
||||
private void vaultListChanged(@SuppressWarnings("unused") Observable observable) {
|
||||
assert Platform.isFxApplicationThread();
|
||||
trayMenu.updateTrayIcon(getAppropriateTrayIconImage());
|
||||
rebuildMenu();
|
||||
}
|
||||
|
||||
@@ -154,4 +155,22 @@ public class TrayMenuBuilder {
|
||||
appWindows.showPreferencesWindow(SelectedPreferencesTab.ANY);
|
||||
}
|
||||
|
||||
private byte[] getAppropriateTrayIconImage() {
|
||||
boolean isAnyVaultUnlocked = vaults.stream().anyMatch(Vault::isUnlocked);
|
||||
|
||||
String resourceName;
|
||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||
resourceName = isAnyVaultUnlocked ? TRAY_ICON_UNLOCKED_MAC : TRAY_ICON_MAC;
|
||||
} else {
|
||||
resourceName = isAnyVaultUnlocked ? TRAY_ICON_UNLOCKED : TRAY_ICON;
|
||||
}
|
||||
|
||||
try (var image = getClass().getResourceAsStream(resourceName)) {
|
||||
assert image != null;
|
||||
return image.readAllBytes();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to load tray icon image: " + resourceName, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user