function loginController()

in guacamole/src/main/frontend/src/app/login/directives/login.js [62:265]


        function loginController($scope, $injector) {
        
        // Required types
        var Error = $injector.get('Error');
        var Field = $injector.get('Field');

        // Required services
        var $location             = $injector.get('$location');
        var $rootScope            = $injector.get('$rootScope');
        var $route                = $injector.get('$route');
        var authenticationService = $injector.get('authenticationService');
        var requestService        = $injector.get('requestService');

        /**
         * The initial value for all login fields. Note that this value must
         * not be null. If null, empty fields may not be submitted back to the
         * server at all, causing the request to misrepresent true login state.
         *
         * For example, if a user receives an insufficient credentials error
         * due to their password expiring, failing to provide that new password
         * should result in the user submitting their username, original
         * password, and empty new password. If only the username and original
         * password are sent, the invalid password reset request will be
         * indistinguishable from a normal login attempt.
         *
         * @constant
         * @type String
         */
        var DEFAULT_FIELD_VALUE = '';

        /**
         * A description of the error that occurred during login, if any.
         *
         * @type TranslatableMessage
         */
        $scope.loginError = null;

        /**
         * All form values entered by the user, as parameter name/value pairs.
         *
         * @type Object.<String, String>
         */
        $scope.enteredValues = {};

        /**
         * All form fields which have not yet been filled by the user.
         *
         * @type Field[]
         */
        $scope.remainingFields = [];

        /**
         * Whether an authentication attempt has been submitted. This will be
         * set to true once credentials have been submitted and will only be
         * reset to false once the attempt has been fully processed, including
         * rerouting the user to the requested page if the attempt succeeded.
         *
         * @type Boolean
         */
        $scope.submitted = false;

        /**
         * The field that is most relevant to the user.
         *
         * @type Field
         */
        $scope.relevantField = null;

        /**
         * Returns whether a previous login attempt is continuing.
         *
         * @return {Boolean}
         *     true if a previous login attempt is continuing, false otherwise.
         */
        $scope.isContinuation = function isContinuation() {

            // The login is continuing if any parameter values are provided
            for (var name in $scope.values)
                return true;

            return false;

        };

        // Ensure provided values are included within entered values, even if
        // they have no corresponding input fields
        $scope.$watch('values', function resetEnteredValues(values) {
            angular.extend($scope.enteredValues, values || {});
        });

        // Update field information when form is changed
        $scope.$watch('form', function resetRemainingFields(fields) {

            // If no fields are provided, then no fields remain
            if (!fields) {
                $scope.remainingFields = [];
                return;
            }

            // Filter provided fields against provided values
            $scope.remainingFields = fields.filter(function isRemaining(field) {
                return !(field.name in $scope.values);
            });

            // Set default values for all unset fields
            angular.forEach($scope.remainingFields, function setDefault(field) {
                if (!$scope.enteredValues[field.name])
                    $scope.enteredValues[field.name] = DEFAULT_FIELD_VALUE;
            });

            $scope.relevantField = getRelevantField();

        });

        /**
         * Submits the currently-specified fields to the authentication service,
         * as well as any URL parameters set for the current page, preferring
         * the values from the fields, and redirecting to the main view if
         * successful.
         */
        $scope.login = function login() {

            // Any values from URL paramters
            const urlValues = $location.search();

            // Values from the fields
            const fieldValues = $scope.enteredValues;

            // All the values to be submitted in the auth attempt, preferring
            // any values from fields over those in the URL
            const authParams = {...urlValues, ...fieldValues};

            authenticationService.authenticate(authParams)['catch'](requestService.IGNORE);
        };

        /**
         * Returns the field most relevant to the user given the current state
         * of the login process. This will normally be the first empty field.
         *
         * @return {Field}
         *     The field most relevant, null if there is no single most relevant
         *     field.
         */
        var getRelevantField = function getRelevantField() {

            for (var i = 0; i < $scope.remainingFields.length; i++) {
                var field = $scope.remainingFields[i];
                if (!$scope.enteredValues[field.name])
                    return field;
            }

            return null;

        };

        // Update UI to reflect in-progress auth status (clear any previous
        // errors, flag as pending)
        $rootScope.$on('guacLoginPending', function loginSuccessful() {
            $scope.submitted = true;
            $scope.loginError = null;
        });

        // Retry route upon success (entered values will be cleared only
        // after route change has succeeded as this can take time)
        $rootScope.$on('guacLogin', function loginSuccessful() {
            $route.reload();
        });

        // Reset upon failure
        $rootScope.$on('guacLoginFailed', function loginFailed(event, parameters, error) {

            // Initial submission is complete and has failed
            $scope.submitted = false;

            // Clear out passwords if the credentials were rejected for any reason
            if (error.type !== Error.Type.INSUFFICIENT_CREDENTIALS) {

                // Flag generic error for invalid login
                if (error.type === Error.Type.INVALID_CREDENTIALS)
                    $scope.loginError = {
                        'key' : 'LOGIN.ERROR_INVALID_LOGIN'
                    };

                // Display error if anything else goes wrong
                else
                    $scope.loginError = error.translatableMessage;

                // Reset all remaining fields to default values, but
                // preserve any usernames
                angular.forEach($scope.remainingFields, function clearEnteredValueIfPassword(field) {
                    if (field.type !== Field.Type.USERNAME && field.name in $scope.enteredValues)
                        $scope.enteredValues[field.name] = DEFAULT_FIELD_VALUE;
                });
            }

        });

        // Reset state after authentication and routing have succeeded
        $rootScope.$on('$routeChangeSuccess', function routeChanged() {
            $scope.enteredValues = {};
            $scope.submitted = false;
        });

    }];