diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUser.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUser.java index 5a9e4b80f..9fdfae158 100644 --- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUser.java +++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUser.java @@ -19,8 +19,11 @@ package org.apache.guacamole.auth.totp.user; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.apache.guacamole.form.BooleanField; +import org.apache.guacamole.form.Form; import org.apache.guacamole.net.auth.DelegatingUser; import org.apache.guacamole.net.auth.User; @@ -41,6 +44,17 @@ public class TOTPUser extends DelegatingUser { */ public static final String TOTP_KEY_CONFIRMED_ATTRIBUTE_NAME = "guac-totp-key-confirmed"; + /** + * The form which contains all configurable properties for this user. + */ + public static final Form TOTP_CONFIG_FORM = new Form("totp-config-form", + Arrays.asList( + new BooleanField(TOTP_KEY_SECRET_ATTRIBUTE_NAME, ""), + new BooleanField(TOTP_KEY_CONFIRMED_ATTRIBUTE_NAME, "true") + ) + ); + + /** * Wraps the given User object, hiding and blocking access to the core * attributes used by TOTP. @@ -66,14 +80,8 @@ public class TOTPUser extends DelegatingUser { public Map getAttributes() { // Create independent, mutable copy of attributes - Map attributes = - new HashMap(super.getAttributes()); + Map attributes = new HashMap<>(super.getAttributes()); - // Do not expose any TOTP-related attributes outside this extension - attributes.remove(TOTP_KEY_SECRET_ATTRIBUTE_NAME); - attributes.remove(TOTP_KEY_CONFIRMED_ATTRIBUTE_NAME); - - // Expose only non-TOTP attributes return attributes; } @@ -82,13 +90,8 @@ public class TOTPUser extends DelegatingUser { public void setAttributes(Map attributes) { // Create independent, mutable copy of attributes - attributes = new HashMap(attributes); + attributes = new HashMap<>(attributes); - // Do not expose any TOTP-related attributes outside this extension - attributes.remove(TOTP_KEY_SECRET_ATTRIBUTE_NAME); - attributes.remove(TOTP_KEY_CONFIRMED_ATTRIBUTE_NAME); - - // Set only non-TOTP attributes super.setAttributes(attributes); } diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUserContext.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUserContext.java index 980bbf782..f4785193c 100644 --- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUserContext.java +++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/user/TOTPUserContext.java @@ -19,7 +19,11 @@ package org.apache.guacamole.auth.totp.user; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.form.Form; import org.apache.guacamole.net.auth.DecoratingDirectory; import org.apache.guacamole.net.auth.DelegatingUserContext; import org.apache.guacamole.net.auth.Directory; @@ -60,5 +64,12 @@ public class TOTPUserContext extends DelegatingUserContext { }; } + + @Override + public Collection
getUserAttributes() { + Collection userAttrs = new HashSet<>(super.getUserAttributes()); + userAttrs.add(TOTPUser.TOTP_CONFIG_FORM); + return Collections.unmodifiableCollection(userAttrs); + } } diff --git a/extensions/guacamole-auth-totp/src/main/resources/config/totpConfig.js b/extensions/guacamole-auth-totp/src/main/resources/config/totpConfig.js index 54bb56c08..0de357314 100644 --- a/extensions/guacamole-auth-totp/src/main/resources/config/totpConfig.js +++ b/extensions/guacamole-auth-totp/src/main/resources/config/totpConfig.js @@ -29,5 +29,12 @@ angular.module('guacTOTP').config(['formServiceProvider', controller : 'authenticationCodeFieldController', templateUrl : 'app/ext/totp/templates/authenticationCodeField.html' }); + + // Add field type for resetting TOTP data + formServiceProvider.registerFieldType('GUAC_TOTP_RESET', { + module : 'guacTOTP', + controller : 'totpResetFieldController', + templateUrl : 'app/form/templates/checkboxField.html' + }); }]); diff --git a/extensions/guacamole-auth-totp/src/main/resources/controllers/totpResetFieldController.js b/extensions/guacamole-auth-totp/src/main/resources/controllers/totpResetFieldController.js new file mode 100644 index 000000000..041772305 --- /dev/null +++ b/extensions/guacamole-auth-totp/src/main/resources/controllers/totpResetFieldController.js @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Controller for the "GUAC_TOTP_CODE" field which prompts the user to enter + * the code generated by their authentication device. + */ +angular.module('guacTOTP').controller('totpResetFieldController', ['$scope', '$window', + function totpResetFieldController($scope, $window) { + + var origValue = $scope.model; + + // Update typed value when model is changed + $scope.$watch('model', function modelChanged(model) { + if (!model || model === '') + $scope.typedValue = true; + else + $scope.typedValue = false; + }); + + // Update string value in model when typed value is changed + $scope.$watch('typedValue', function typedValueChanged(typedValue) { + if (typedValue && typedValue !== '') + $scope.model = ''; + + else + $scope.model = origValue; + }); + +}]); \ No newline at end of file diff --git a/extensions/guacamole-auth-totp/src/main/resources/translations/en.json b/extensions/guacamole-auth-totp/src/main/resources/translations/en.json index 6f73aa02d..be1e3b54b 100644 --- a/extensions/guacamole-auth-totp/src/main/resources/translations/en.json +++ b/extensions/guacamole-auth-totp/src/main/resources/translations/en.json @@ -29,6 +29,15 @@ "SECTION_HEADER_DETAILS" : "Details:" + }, + + "USER_ATTRIBUTES" : { + + "FIELD_HEADER_GUAC_TOTP_KEY_SECRET" : "Clear TOTP key:", + "FIELD_HEADER_GUAC_TOTP_KEY_CONFIRMED" : "TOTP key confirmed:", + + "SECTION_HEADER_TOTP_CONFIG_FORM" : "Configure TOTP" + } }