show archived vault dialog on unlock when Hub returns 410

This commit is contained in:
Jan-Peter Klein
2025-12-17 09:56:56 +01:00
parent 1e861ac187
commit 760e260eba
6 changed files with 124 additions and 3 deletions

View File

@@ -18,6 +18,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_ARCHIVED_VAULT("/fxml/hub_archived_vault.fxml"), //
HUB_NO_KEYCHAIN("/fxml/hub_no_keychain.fxml"), //
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_INVALID_LICENSE("/fxml/hub_invalid_license.fxml"), //

View File

@@ -0,0 +1,34 @@
package org.cryptomator.ui.keyloading.hub;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.util.concurrent.CompletableFuture;
@KeyLoadingScoped
public class ArchivedVaultController implements FxController {
private final Stage window;
private final CompletableFuture<ReceivedKey> result;
@Inject
public ArchivedVaultController(@KeyLoading Stage window, CompletableFuture<ReceivedKey> result) {
this.window = window;
this.result = result;
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
}
@FXML
public void close() {
window.close();
}
private void windowClosed(WindowEvent windowEvent) {
result.cancel(true);
}
}

View File

@@ -161,6 +161,13 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
}
@Provides
@FxmlScene(FxmlFile.HUB_ARCHIVED_VAULT)
@KeyLoadingScoped
static Scene provideHubArchivedVaultScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_ARCHIVED_VAULT);
}
@Provides
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT)
@KeyLoadingScoped
@@ -213,6 +220,11 @@ public abstract class HubKeyLoadingModule {
@FxControllerKey(RegisterFailedController.class)
abstract FxController bindRegisterFailedController(RegisterFailedController controller);
@Binds
@IntoMap
@FxControllerKey(ArchivedVaultController.class)
abstract FxController bindArchivedVaultController(ArchivedVaultController controller);
@Binds
@IntoMap
@FxControllerKey(UnauthorizedDeviceController.class)

View File

@@ -54,12 +54,25 @@ public class ReceiveKeyController implements FxController {
private final Lazy<Scene> registerDeviceScene;
private final Lazy<Scene> legacyRegisterDeviceScene;
private final Lazy<Scene> unauthorizedScene;
private final Lazy<Scene> archivedVaultScene;
private final Lazy<Scene> accountInitializationScene;
private final Lazy<Scene> invalidLicenseScene;
private final HttpClient httpClient;
@Inject
public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, HubConfig hubConfig, @Named("deviceId") String deviceId, @Named("bearerToken") AtomicReference<String> tokenRef, CompletableFuture<ReceivedKey> result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene, @FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene, @FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, @FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene, @FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene) {
public ReceiveKeyController(@KeyLoading Vault vault,
ExecutorService executor,
@KeyLoading Stage window,
HubConfig hubConfig,
@Named("deviceId") String deviceId,
@Named("bearerToken") AtomicReference<String> tokenRef,
CompletableFuture<ReceivedKey> result,
@FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene,
@FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene,
@FxmlScene(FxmlFile.HUB_ARCHIVED_VAULT) Lazy<Scene> archivedVaultScene,
@FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene,
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene,
@FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> 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)
@@ -69,6 +82,7 @@ public class ReceiveKeyController implements FxController {
this.registerDeviceScene = registerDeviceScene;
this.legacyRegisterDeviceScene = legacyRegisterDeviceScene;
this.unauthorizedScene = unauthorizedScene;
this.archivedVaultScene = archivedVaultScene;
this.accountInitializationScene = accountInitializationScene;
this.invalidLicenseScene = invalidLicenseScene;
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
@@ -184,7 +198,8 @@ public class ReceiveKeyController implements FxController {
switch (response.statusCode()) {
case 200 -> receivedBothEncryptedKeys(response.body(), encryptedUserKey);
case 402 -> licenseExceeded();
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access - TODO: add specific dialog?
case 403 -> accessNotGranted();
case 410 -> accessGoneVaultArchived();
case 449 -> accountInitializationRequired();
default -> throw new IllegalStateException("Unexpected response " + response.statusCode());
}
@@ -228,7 +243,8 @@ public class ReceiveKeyController implements FxController {
switch (response.statusCode()) {
case 200 -> receivedLegacyAccessTokenSuccess(response.body());
case 402 -> licenseExceeded();
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access
case 403 -> accessNotGranted();
case 410 -> accessGoneVaultArchived();
case 404 -> needsLegacyDeviceRegistration();
default -> throw new IOException("Unexpected response " + response.statusCode());
}
@@ -261,6 +277,10 @@ public class ReceiveKeyController implements FxController {
window.setScene(unauthorizedScene.get());
}
private void accessGoneVaultArchived() {
window.setScene(archivedVaultScene.get());
}
private void accountInitializationRequired() {
window.setScene(accountInitializationScene.get());
}

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.ArchivedVaultController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="BAN" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.archived.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.archived.description" wrapText="true"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<buttons>
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" onAction="#close"/>
</buttons>
</ButtonBar>
</VBox>
</children>
</HBox>

View File

@@ -178,6 +178,9 @@ hub.registerSuccess.legacy.description=To access the vault, your device needs to
hub.registerFailed.message=Device registration failed
hub.registerFailed.description.generic=An error was thrown in the registration process. For more details, look into the application log.
hub.registerFailed.description.deviceAlreadyExists=This device is already registered for a different user. Try to change the user account or use a different device.
### Archived
hub.archived.message=Vault is archived
hub.archived.description=This vault has been archived and is no longer accessible. Please contact the vault owner.
### Unauthorized
hub.unauthorized.message=Access denied
hub.unauthorized.description=You are not authorized to open this vault. Contact the vault's owner to request access.