mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-20 03:31:27 +00:00
adjusted to new vault config format and unlock status codes
This commit is contained in:
@@ -42,6 +42,8 @@ module org.cryptomator.desktop {
|
||||
uses TrayIntegrationProvider;
|
||||
uses UiAppearanceProvider;
|
||||
|
||||
exports org.cryptomator.ui.keyloading.hub to com.fasterxml.jackson.databind;
|
||||
|
||||
opens org.cryptomator.common.settings to com.google.gson;
|
||||
|
||||
opens org.cryptomator.common to javafx.fxml;
|
||||
|
||||
@@ -17,6 +17,7 @@ public enum FxmlFile {
|
||||
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
|
||||
HUB_P12("/fxml/hub_p12.fxml"), //
|
||||
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
|
||||
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
|
||||
LOCK_FORCED("/fxml/lock_forced.fxml"), //
|
||||
LOCK_FAILED("/fxml/lock_failed.fxml"), //
|
||||
MAIN_WINDOW("/fxml/main_window.fxml"), //
|
||||
|
||||
@@ -46,15 +46,15 @@ class AuthFlow implements AutoCloseable {
|
||||
public static final Escaper QUERY_STRING_ESCAPER = new PercentEscaper("-_.!~*'()@:$,;/?", false);
|
||||
|
||||
private final AuthFlowReceiver receiver;
|
||||
private final URI authEndpoint;
|
||||
private final URI tokenEndpoint;
|
||||
private final String clientId;
|
||||
private final URI authEndpoint; // see https://datatracker.ietf.org/doc/html/rfc6749#section-3.1
|
||||
private final URI tokenEndpoint; // see https://datatracker.ietf.org/doc/html/rfc6749#section-3.2
|
||||
private final String clientId; // see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1
|
||||
|
||||
private AuthFlow(AuthFlowReceiver receiver, URI authEndpoint, URI tokenEndpoint, String clientId) {
|
||||
private AuthFlow(AuthFlowReceiver receiver, HubConfig hubConfig) {
|
||||
this.receiver = receiver;
|
||||
this.authEndpoint = authEndpoint;
|
||||
this.tokenEndpoint = tokenEndpoint;
|
||||
this.clientId = clientId;
|
||||
this.authEndpoint = URI.create(hubConfig.authEndpoint);
|
||||
this.tokenEndpoint = URI.create(hubConfig.tokenEndpoint);
|
||||
this.clientId = hubConfig.clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,15 +62,13 @@ class AuthFlow implements AutoCloseable {
|
||||
* <p>
|
||||
* This will start a loopback server, so make sure to {@link #close()} this resource.
|
||||
*
|
||||
* @param authEndpoint Address of the <a href="https://datatracker.ietf.org/doc/html/rfc6749#section-3.1">Authorization Endpoint</a>
|
||||
* @param tokenEndpoint Address of the <a href="https://datatracker.ietf.org/doc/html/rfc6749#section-3.2">Token Endpoint</a>
|
||||
* @param clientId The <a href="https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1"><code>client_id</code></a>
|
||||
* @param hubConfig A hub config object containing parameters required for this auth flow
|
||||
* @return An authorization flow
|
||||
* @throws Exception In case of any problems starting the server
|
||||
*/
|
||||
public static AuthFlow init(URI authEndpoint, URI tokenEndpoint, String clientId) throws Exception {
|
||||
var receiver = AuthFlowReceiver.start();
|
||||
return new AuthFlow(receiver, authEndpoint, tokenEndpoint, clientId);
|
||||
public static AuthFlow init(HubConfig hubConfig) throws Exception {
|
||||
var receiver = AuthFlowReceiver.start(hubConfig);
|
||||
return new AuthFlow(receiver, hubConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.ErrorComponent;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
@@ -24,7 +23,6 @@ import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -33,14 +31,11 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
public class AuthFlowController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AuthFlowController.class);
|
||||
private static final String JWT_KEY_AUTH_ENDPOINT = "authEndpoint";
|
||||
private static final String JWT_KEY_TOKEN_ENDPOINT = "tokenEndpoint";
|
||||
private static final String JWT_KEY_CLIENT_ID = "clientId";
|
||||
|
||||
private final Application application;
|
||||
private final Stage window;
|
||||
private final ExecutorService executor;
|
||||
private final Vault vault;
|
||||
private final HubConfig hubConfig;
|
||||
private final AtomicReference<String> tokenRef;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result;
|
||||
private final Lazy<Scene> receiveKeyScene;
|
||||
@@ -50,11 +45,11 @@ public class AuthFlowController implements FxController {
|
||||
private AuthFlowTask task;
|
||||
|
||||
@Inject
|
||||
public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, @KeyLoading Vault vault, @Named("bearerToken") AtomicReference<String> tokenRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy<Scene> receiveKeyScene, ErrorComponent.Builder errorComponent) {
|
||||
public AuthFlowController(Application application, @KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("bearerToken") AtomicReference<String> tokenRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_RECEIVE_KEY) Lazy<Scene> receiveKeyScene, ErrorComponent.Builder errorComponent) {
|
||||
this.application = application;
|
||||
this.window = window;
|
||||
this.executor = executor;
|
||||
this.vault = vault;
|
||||
this.hubConfig = hubConfig;
|
||||
this.tokenRef = tokenRef;
|
||||
this.result = result;
|
||||
this.receiveKeyScene = receiveKeyScene;
|
||||
@@ -67,15 +62,10 @@ public class AuthFlowController implements FxController {
|
||||
@FXML
|
||||
public void initialize() {
|
||||
assert task == null;
|
||||
try {
|
||||
task = setupTask();
|
||||
task.setOnFailed(this::authFailed);
|
||||
task.setOnSucceeded(this::authSucceeded);
|
||||
executor.submit(task);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Unreadable vault config", e);
|
||||
errorComponent.cause(e).window(window).build().showErrorScene();
|
||||
}
|
||||
task = new AuthFlowTask(hubConfig, this::setAuthUri);;
|
||||
task.setOnFailed(this::authFailed);
|
||||
task.setOnSucceeded(this::authSucceeded);
|
||||
executor.submit(task);
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -88,13 +78,6 @@ public class AuthFlowController implements FxController {
|
||||
window.close();
|
||||
}
|
||||
|
||||
private AuthFlowTask setupTask() throws IOException {
|
||||
var authUri = URI.create(vault.getUnverifiedVaultConfig().get(JWT_KEY_AUTH_ENDPOINT).asString());
|
||||
var tokenUri = URI.create(vault.getUnverifiedVaultConfig().get(JWT_KEY_TOKEN_ENDPOINT).asString());
|
||||
var clientId = vault.getUnverifiedVaultConfig().get(JWT_KEY_CLIENT_ID).asString();
|
||||
return new AuthFlowTask(authUri, tokenUri, clientId, this::setAuthUri);
|
||||
}
|
||||
|
||||
private void setAuthUri(URI uri) {
|
||||
authUri.set(uri);
|
||||
browse();
|
||||
@@ -138,4 +121,5 @@ public class AuthFlowController implements FxController {
|
||||
return uri.getAuthority().toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,18 +40,20 @@ class AuthFlowReceiver implements AutoCloseable {
|
||||
private final Server server;
|
||||
private final ServerConnector connector;
|
||||
private final CallbackServlet servlet;
|
||||
private final HubConfig hubConfig;
|
||||
|
||||
private AuthFlowReceiver(Server server, ServerConnector connector, CallbackServlet servlet) {
|
||||
private AuthFlowReceiver(Server server, ServerConnector connector, CallbackServlet servlet, HubConfig hubConfig) {
|
||||
this.server = server;
|
||||
this.connector = connector;
|
||||
this.servlet = servlet;
|
||||
this.hubConfig = hubConfig;
|
||||
}
|
||||
|
||||
public static AuthFlowReceiver start() throws Exception {
|
||||
public static AuthFlowReceiver start(HubConfig hubConfig) throws Exception {
|
||||
var server = new Server();
|
||||
var context = new ServletContextHandler();
|
||||
|
||||
var servlet = new CallbackServlet();
|
||||
var servlet = new CallbackServlet(hubConfig);
|
||||
context.addServlet(new ServletHolder(servlet), CALLBACK_PATH);
|
||||
|
||||
var connector = new ServerConnector(server);
|
||||
@@ -60,7 +62,7 @@ class AuthFlowReceiver implements AutoCloseable {
|
||||
server.setConnectors(new Connector[]{connector});
|
||||
server.setHandler(context);
|
||||
server.start();
|
||||
return new AuthFlowReceiver(server, connector, servlet);
|
||||
return new AuthFlowReceiver(server, connector, servlet, hubConfig);
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
@@ -81,6 +83,11 @@ class AuthFlowReceiver implements AutoCloseable {
|
||||
private static class CallbackServlet extends HttpServlet {
|
||||
|
||||
private final BlockingQueue<Callback> callback = new LinkedBlockingQueue<>();
|
||||
private final HubConfig hubConfig;
|
||||
|
||||
public CallbackServlet(HubConfig hubConfig) {
|
||||
this.hubConfig = hubConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
|
||||
@@ -88,14 +95,15 @@ class AuthFlowReceiver implements AutoCloseable {
|
||||
var code = req.getParameter("code");
|
||||
var state = req.getParameter("state");
|
||||
|
||||
// TODO 302 use redirect to configurable site
|
||||
res.setContentType("text/html;charset=utf-8");
|
||||
res.getWriter().write(HTML_SUCCESS);
|
||||
res.getWriter().flush();
|
||||
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
|
||||
if (error == null && code != null) {
|
||||
res.setHeader("Location", hubConfig.unlockSuccessUrl);
|
||||
} else {
|
||||
res.setHeader("Location", hubConfig.unlockErrorUrl);
|
||||
}
|
||||
|
||||
callback.add(new Callback(error, code, state));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,27 +7,25 @@ import java.util.function.Consumer;
|
||||
|
||||
class AuthFlowTask extends Task<String> {
|
||||
|
||||
private final URI authUri;
|
||||
private final URI tokenUri;
|
||||
private final String clientId;
|
||||
private final Consumer<URI> redirectUriConsumer;
|
||||
|
||||
/**
|
||||
* Spawns a server and waits for the redirectUri to be called.
|
||||
*
|
||||
* @param hubConfig Configuration object holding parameters required by {@link AuthFlow}
|
||||
* @param redirectUriConsumer A callback invoked with the redirectUri, as soon as the server has started
|
||||
*/
|
||||
public AuthFlowTask(URI authUri, URI tokenUri, String clientId, Consumer<URI> redirectUriConsumer) {
|
||||
this.authUri = authUri;
|
||||
this.tokenUri = tokenUri;
|
||||
this.clientId = clientId;
|
||||
public AuthFlowTask(HubConfig hubConfig, Consumer<URI> redirectUriConsumer) {
|
||||
this.hubConfig = hubConfig;
|
||||
this.redirectUriConsumer = redirectUriConsumer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String call() throws Exception {
|
||||
try (var authFlow = AuthFlow.init(authUri, tokenUri, clientId)) {
|
||||
try (var authFlow = AuthFlow.init(hubConfig)) {
|
||||
return authFlow.run(uri -> Platform.runLater(() -> redirectUriConsumer.accept(uri)));
|
||||
}
|
||||
}
|
||||
|
||||
private final HubConfig hubConfig;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
// needs to be accessible by JSON decoder
|
||||
public class HubConfig {
|
||||
|
||||
public String clientId;
|
||||
public String authEndpoint;
|
||||
public String tokenEndpoint;
|
||||
public String deviceRegistrationUrl;
|
||||
public String unlockSuccessUrl;
|
||||
public String unlockErrorUrl;
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import dagger.multibindings.StringKey;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
@@ -19,6 +20,8 @@ import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javafx.scene.Scene;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyPair;
|
||||
import java.util.ResourceBundle;
|
||||
@@ -33,6 +36,16 @@ public abstract class HubKeyLoadingModule {
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
@Provides
|
||||
@KeyLoadingScoped
|
||||
static HubConfig provideHubConfig(@KeyLoading Vault vault) {
|
||||
try {
|
||||
return vault.getUnverifiedVaultConfig().getHeader("hub", HubConfig.class);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@KeyLoadingScoped
|
||||
static AtomicReference<KeyPair> provideKeyPair() {
|
||||
@@ -92,6 +105,14 @@ public abstract class HubKeyLoadingModule {
|
||||
return fxmlLoaders.createScene(FxmlFile.HUB_RECEIVE_KEY);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.HUB_REGISTER_DEVICE)
|
||||
@KeyLoadingScoped
|
||||
static Scene provideHubRegisterDeviceScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE);
|
||||
}
|
||||
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(P12Controller.class)
|
||||
@@ -124,4 +145,9 @@ public abstract class HubKeyLoadingModule {
|
||||
@FxControllerKey(ReceiveKeyController.class)
|
||||
abstract FxController bindReceiveKeyController(ReceiveKeyController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(RegisterDeviceController.class)
|
||||
abstract FxController bindRegisterDeviceController(RegisterDeviceController controller);
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
|
||||
static final String SCHEME_HUB_HTTP = SCHEME_PREFIX + "http";
|
||||
static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https";
|
||||
|
||||
private final Vault vault;
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> p12LoadingScene;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> userInteraction;
|
||||
@@ -37,8 +36,7 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
|
||||
private final AtomicReference<EciesParams> eciesParams;
|
||||
|
||||
@Inject
|
||||
public HubKeyLoadingStrategy(@KeyLoading Vault vault, @KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_P12) Lazy<Scene> p12LoadingScene, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> userInteraction, AtomicReference<KeyPair> keyPairRef, AtomicReference<EciesParams> eciesParams) {
|
||||
this.vault = vault;
|
||||
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_P12) Lazy<Scene> p12LoadingScene, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> userInteraction, AtomicReference<KeyPair> keyPairRef, AtomicReference<EciesParams> eciesParams) {
|
||||
this.window = window;
|
||||
this.p12LoadingScene = p12LoadingScene;
|
||||
this.userInteraction = userInteraction;
|
||||
|
||||
@@ -5,9 +5,12 @@ import com.google.common.base.Strings;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.ErrorComponent;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||
@@ -23,6 +26,7 @@ import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
@@ -47,23 +51,20 @@ public class ReceiveKeyController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final String bearerToken;
|
||||
private final KeyPair keyPair;
|
||||
private final AtomicReference<EciesParams> eciesParamsRef;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result;
|
||||
private final Lazy<Scene> registerDeviceScene;
|
||||
private final ErrorComponent.Builder errorComponent;
|
||||
private final URI vaultBaseUri;
|
||||
private final ObjectProperty<ReceiveKeyState> state = new SimpleObjectProperty<>(ReceiveKeyState.LOADING);
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public TextField deviceName;
|
||||
|
||||
@Inject
|
||||
public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, AtomicReference<KeyPair> keyPairRef, @Named("bearerToken") AtomicReference<String> tokenRef, AtomicReference<EciesParams> eciesParamsRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, ErrorComponent.Builder errorComponent) {
|
||||
public ReceiveKeyController(@KeyLoading Vault vault, ExecutorService executor, @KeyLoading Stage window, AtomicReference<KeyPair> keyPairRef, @Named("bearerToken") AtomicReference<String> tokenRef, AtomicReference<EciesParams> eciesParamsRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result, @FxmlScene(FxmlFile.HUB_REGISTER_DEVICE) Lazy<Scene> registerDeviceScene, ErrorComponent.Builder errorComponent) {
|
||||
this.window = window;
|
||||
this.bearerToken = Objects.requireNonNull(tokenRef.get());
|
||||
this.keyPair = Objects.requireNonNull(keyPairRef.get());
|
||||
this.eciesParamsRef = eciesParamsRef;
|
||||
this.result = result;
|
||||
this.registerDeviceScene = registerDeviceScene;
|
||||
this.errorComponent = errorComponent;
|
||||
this.vaultBaseUri = getVaultBaseUri(vault);
|
||||
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
|
||||
@@ -87,41 +88,8 @@ public class ReceiveKeyController implements FxController {
|
||||
} else {
|
||||
switch (response.statusCode()) {
|
||||
case 200 -> retrievalSucceeded(response);
|
||||
case 404 -> state.set(ReceiveKeyState.NEEDS_REGISTRATION);
|
||||
default -> retrievalFailed(new IOException("Unexpected response " + response.statusCode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void register() {
|
||||
Preconditions.checkArgument(!Strings.isNullOrEmpty(deviceName.getText()), "device name must not be empty");
|
||||
var deviceKey = BaseEncoding.base64Url().omitPadding().encode(keyPair.getPublic().getEncoded());
|
||||
var json = """
|
||||
{
|
||||
"id": "desktop-app",
|
||||
"name": "%s",
|
||||
"publicKey": "%s"
|
||||
}
|
||||
""".formatted(deviceName.getText(), deviceKey); // TODO use gson
|
||||
|
||||
var regUri = URI.create("http://localhost:9090/devices/desktop-app"); // TODO read api base from vault config!
|
||||
var request = HttpRequest.newBuilder(regUri) //
|
||||
.header("Authorization", "Bearer " + bearerToken) //
|
||||
.header("Content-Type", "application/json; charset=UTF-8") //
|
||||
.PUT(HttpRequest.BodyPublishers.ofString(json)) //
|
||||
.build();
|
||||
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()) //
|
||||
.whenCompleteAsync(this::createdNewDevice, Platform::runLater);
|
||||
}
|
||||
|
||||
private void createdNewDevice(HttpResponse<InputStream> response, Throwable error) {
|
||||
if (error != null) {
|
||||
retrievalFailed(error);
|
||||
} else {
|
||||
switch (response.statusCode()) {
|
||||
case 201 -> LOG.info("TODO device created, waiting for authorization");
|
||||
case 409 -> LOG.info("TODO device already exists. still waiting for authorization");
|
||||
case 403 -> accessNotGranted();
|
||||
case 404 -> needsDeviceRegistration();
|
||||
default -> retrievalFailed(new IOException("Unexpected response " + response.statusCode()));
|
||||
}
|
||||
}
|
||||
@@ -143,6 +111,14 @@ public class ReceiveKeyController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
private void needsDeviceRegistration() {
|
||||
window.setScene(registerDeviceScene.get());
|
||||
}
|
||||
|
||||
private void accessNotGranted() {
|
||||
LOG.warn("unauthorized device"); // TODO
|
||||
}
|
||||
|
||||
private void retrievalFailed(Throwable cause) {
|
||||
result.interacted(HubKeyLoadingModule.HubLoadingResult.FAILED);
|
||||
LOG.error("Key retrieval failed", cause);
|
||||
@@ -183,13 +159,5 @@ public class ReceiveKeyController implements FxController {
|
||||
throw new IllegalStateException("URI constructed from params known to be valid", e);
|
||||
}
|
||||
}
|
||||
/* Getter/Setter */
|
||||
|
||||
public ObjectProperty<ReceiveKeyState> stateProperty() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public ReceiveKeyState getState() {
|
||||
return state.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
public enum ReceiveKeyState {
|
||||
LOADING,
|
||||
NEEDS_REGISTRATION
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.application.Application;
|
||||
import javafx.event.Event;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@KeyLoadingScoped
|
||||
public class RegisterDeviceController implements FxController {
|
||||
|
||||
private final Application application;
|
||||
private final Stage window;
|
||||
private final HubConfig hubConfig;
|
||||
private final KeyPair keyPair;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result;
|
||||
|
||||
@Inject
|
||||
public RegisterDeviceController(Application application, @KeyLoading Stage window, HubConfig hubConfig, AtomicReference<KeyPair> keyPairRef, UserInteractionLock<HubKeyLoadingModule.HubLoadingResult> result) {
|
||||
this.application = application;
|
||||
this.window = window;
|
||||
this.hubConfig = hubConfig;
|
||||
this.keyPair = Objects.requireNonNull(keyPairRef.get());
|
||||
this.result = result;
|
||||
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void browse() {
|
||||
var deviceKey = BaseEncoding.base64Url().omitPadding().encode(keyPair.getPublic().getEncoded());
|
||||
var url = hubConfig.deviceRegistrationUrl + "?device_key=" + deviceKey;
|
||||
// TODO append further params (including hmac of shown verification code)
|
||||
application.getHostServices().showDocument(url);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
private void windowClosed(WindowEvent windowEvent) {
|
||||
// if not already interacted, mark this workflow as cancelled:
|
||||
if (result.awaitingInteraction().get()) {
|
||||
result.interacted(HubKeyLoadingModule.HubLoadingResult.CANCELLED);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user