added registration key to preferences

This commit is contained in:
Sebastian Stenzel
2019-11-15 15:56:35 +01:00
parent 1717e20b61
commit b884ea7ddc
14 changed files with 154 additions and 38 deletions

View File

@@ -48,6 +48,12 @@
<artifactId>easybind</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<!-- Google -->
<dependency>
<groupId>com.google.guava</groupId>

View File

@@ -35,6 +35,17 @@ public abstract class CommonsModule {
private static final int NUM_SCHEDULER_THREADS = 4;
@Provides
@Singleton
@Named("licensePublicKey")
static String provideLicensePublicKey() {
// TODO replace
return "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ" //
+ "PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47" //
+ "6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM" //
+ "Al8G7CqwoJOsW7Kddns=";
}
@Provides
@Singleton
@Named("SemVer")

View File

@@ -1,4 +1,4 @@
package org.cryptomator.ui.preferences;
package org.cryptomator.common;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
@@ -9,6 +9,7 @@ import com.google.common.io.BaseEncoding;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
@@ -17,6 +18,7 @@ import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Optional;
@Singleton
public class LicenseChecker {
private final JWTVerifier verifier;

View File

@@ -1,28 +0,0 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.common;
import java.util.Optional;
import java.util.function.Function;
public final class Optionals {
private Optionals() {
}
/**
* Returns a function that is equivalent to the input function but immediately gets the value of the returned optional when invoked.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
* @param function An {@code Optional}-bearing input function {@code Function<Foo, Optional<Bar>>}
* @return A {@code Function<Foo, Bar>}, that may throw a NoSuchElementException, if the original function returns an empty optional.
*/
public static <T, R> Function<T, R> unwrap(Function<T, Optional<R>> function) {
return t -> function.apply(t).get();
}
}

View File

@@ -15,6 +15,8 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.NodeOrientation;
@@ -35,6 +37,7 @@ public class Settings {
public static final VolumeImpl DEFAULT_PREFERRED_VOLUME_IMPL = System.getProperty("os.name").toLowerCase().contains("windows") ? VolumeImpl.DOKANY : VolumeImpl.FUSE;
public static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
public static final NodeOrientation DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT;
private static final String DEFAULT_LICENSE_KEY = "";
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
private final BooleanProperty askedForUpdateCheck = new SimpleBooleanProperty(DEFAULT_ASKED_FOR_UPDATE_CHECK);
@@ -47,6 +50,7 @@ public class Settings {
private final ObjectProperty<VolumeImpl> preferredVolumeImpl = new SimpleObjectProperty<>(DEFAULT_PREFERRED_VOLUME_IMPL);
private final ObjectProperty<UiTheme> theme = new SimpleObjectProperty<>(DEFAULT_THEME);
private final ObjectProperty<NodeOrientation> userInterfaceOrientation = new SimpleObjectProperty<>(DEFAULT_USER_INTERFACE_ORIENTATION);
private final StringProperty licenseKey = new SimpleStringProperty(DEFAULT_LICENSE_KEY);
private Consumer<Settings> saveCmd;
@@ -126,4 +130,8 @@ public class Settings {
public ObjectProperty<NodeOrientation> userInterfaceOrientation() {
return userInterfaceOrientation;
}
public StringProperty licenseKey() {
return licenseKey;
}
}

View File

@@ -1,6 +1,7 @@
package org.cryptomator.ui.preferences;
package org.cryptomator.common;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.cryptomator.common.LicenseChecker;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@@ -38,12 +38,6 @@
<groupId>org.fxmisc.easybind</groupId>
<artifactId>easybind</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<!-- Google -->
<dependency>

View File

@@ -15,17 +15,18 @@ public enum FontAwesome5Icon {
EYE_SLASH("\uF070"), //
FILE_IMPORT("\uF56F"), //
FOLDER_OPEN("\uF07C"), //
HEART("\uF004"), //
HDD("\uF0A0"), //
KEY("\uF084"), //
LOCK_ALT("\uF30D"), //
LOCK_OPEN_ALT("\uF3C2"), //
MINUS("\uF068"), //
PLUS("\uF067"), //
QUESTION("\uF128"), //
SPARKLES("\uF890"), //
SPINNER("\uF110"), //
SYNC("\uF021"), //
TIMES("\uF00D"), //
USER_CHECK("\uf4fc"), //
WRENCH("\uF0AD"), //
;

View File

@@ -17,7 +17,6 @@ public class PreferencesController implements FxController {
private final Stage window;
private final BooleanBinding updateAvailable;
public TabPane tabPane;
public Tab generalTab;
public Tab updatesTab;
@Inject

View File

@@ -70,4 +70,9 @@ abstract class PreferencesModule {
@FxControllerKey(VolumePreferencesController.class)
abstract FxController bindVolumePreferencesController(VolumePreferencesController controller);
@Binds
@IntoMap
@FxControllerKey(RegistrationPreferencesController.class)
abstract FxController bindRegistrationPreferencesController(RegistrationPreferencesController controller);
}

View File

@@ -0,0 +1,77 @@
package org.cryptomator.ui.preferences;
import com.auth0.jwt.interfaces.DecodedJWT;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import org.cryptomator.common.LicenseChecker;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.ui.common.FxController;
import javax.inject.Inject;
import java.util.Optional;
@PreferencesScoped
public class RegistrationPreferencesController implements FxController {
private final Settings settings;
private final LicenseChecker licenseChecker;
private final ObjectProperty<DecodedJWT> validJwtClaims;
private final StringBinding licenseSubject;
private final BooleanBinding registeredProperty;
public TextArea registrationKeyField;
@Inject
RegistrationPreferencesController(Settings settings, LicenseChecker licenseChecker) {
this.settings = settings;
this.licenseChecker = licenseChecker;
this.validJwtClaims = new SimpleObjectProperty<>();
this.licenseSubject = Bindings.createStringBinding(this::getLicenseSubject, validJwtClaims);
this.registeredProperty = validJwtClaims.isNotNull();
Optional<DecodedJWT> claims = licenseChecker.check(settings.licenseKey().get());
validJwtClaims.set(claims.orElse(null));
}
@FXML
public void initialize() {
registrationKeyField.textProperty().addListener(this::registrationKeyChanged);
}
private void registrationKeyChanged(@SuppressWarnings("unused") ObservableValue<? extends String> observable, @SuppressWarnings("unused") String oldValue, String newValue) {
Optional<DecodedJWT> claims = licenseChecker.check(newValue);
validJwtClaims.set(claims.orElse(null));
if (claims.isPresent()) {
settings.licenseKey().set(newValue);
}
}
/* Observable Properties */
public StringBinding licenseSubjectProperty() {
return licenseSubject;
}
public String getLicenseSubject() {
DecodedJWT claims = validJwtClaims.get();
if (claims != null) {
return claims.getSubject();
} else {
return null;
}
}
public BooleanBinding registeredProperty() {
return registeredProperty;
}
public boolean isRegistered() {
return registeredProperty.get();
}
}

View File

@@ -35,5 +35,13 @@
<fx:include source="/fxml/preferences_updates.fxml"/>
</content>
</Tab>
<Tab fx:id="registrationTab" text="%preferences.registration">
<graphic>
<FontAwesome5IconView glyph="USER_CHECK"/>
</graphic>
<content>
<fx:include source="/fxml/preferences_registration.fxml"/>
</content>
</Tab>
</tabs>
</TabPane>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import org.cryptomator.ui.controls.FormattedLabel?>
<?import javafx.scene.control.TextArea?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.preferences.RegistrationPreferencesController"
spacing="18">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="NEVER" visible="${controller.registered}">
<StackPane alignment="CENTER" HBox.hgrow="NEVER">
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="HEART" glyphSize="24"/>
</StackPane>
<FormattedLabel format="%preferences.registration.registeredFor" arg1="${controller.licenseSubject}" textAlignment="CENTER" wrapText="true"/>
</HBox>
<TextArea fx:id="registrationKeyField" wrapText="true" VBox.vgrow="ALWAYS"/>
</children>
</VBox>

View File

@@ -123,6 +123,9 @@ preferences.updates.currentVersion=Current Version: %s
preferences.updates.autoUpdateCheck=Check for updates automatically
preferences.updates.checkNowBtn=Check Now
preferences.updates.updateAvailable=Update to version %s available.
## Registration
preferences.registration=Registration
preferences.registration.registeredFor=Registered for %s
# Main Window
main.closeBtn.tooltip=Close