Viewing File: /usr/local/cpanel/base/frontend/jupiter/mail/greylisting/views/domains.js

/*
# mail/greylisting/views/domains.js               Copyright(c) 2020 cPanel, L.L.C.
#                                                           All rights reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
*/

/* global define: false, PAGE: true */
/* jshint -W100 */

define(
    [
        "angular",
        "lodash",
        "cjt/util/locale",
        "uiBootstrap",
        "cjt/decorators/paginationDecorator",
        "cjt/directives/toggleSortDirective",
        "cjt/directives/pageSizeDirective",
        "cjt/directives/validationItemDirective",
        "cjt/directives/spinnerDirective",
        "cjt/directives/autoFocus",
        "cjt/directives/alertList",
        "cjt/services/alertService",
        "cjt/filters/wrapFilter",
        "cjt/filters/breakFilter",
        "app/services/domainService"
    ],
    function(angular, _, LOCALE) {
        "use strict";

        // Retrieve the current application
        var app = angular.module("App");

        /**
         * Update the enabled and exception field in the list based on
         * the returned updates.
         *
         * @private
         * @method _updateStatus
         * @param  {Array} list    List of domains
         * @param  {Array} updates List of update records
         */
        var _updateStatus = function(list, updates) {
            for (var i = 0, l = list.length; i < l; i++) {
                var update = _findUpdateByDomain(updates, list[i].domain);
                if (update) {
                    list[i].enabled = update.enabled;
                    if (update.exception) {
                        list[i].exception = update.exception;
                    } else {
                        delete list[i].exception;
                    }
                } else {
                    if (list[i].exception) {
                        delete list[i].exception;
                    }
                }
            }
        };

        /**
         * Find an update record by the domain name
         *
         * @private
         * @method _findUpdateByDomain
         * @param  {Array} updates List of update records
         * @param  {String} domain Domain to look for in the update list.
         * @return {Object}        Update associated with the requested domain or nothing if not found.
         */
        var _findUpdateByDomain = function(updates, domain) {
            for (var i = 0, l = updates.length; i < l; i++) {
                if (updates[i].domain === domain) {
                    return updates[i];
                }
            }
            return;
        };

        // Setup the controller
        var controller = app.controller(
            "domainListController", [
                "$scope",
                "$routeParams",
                "$q",
                "DomainService",
                "spinnerAPI",
                "alertService",
                function(
                    $scope,
                    $routeParams,
                    $q,
                    DomainService,
                    spinnerAPI,
                    alertService
                ) {

                    /**
                     * Initialize the scope variables
                     *
                     * @private
                     * @method _initializeScope
                     */
                    var _initializeScope = function() {
                        $scope.activeSearch = false;
                        $scope.filteredData = false;
                        $scope.totalEnabled = 0;
                        $scope.totalDisabled = 0;
                        $scope.selectedRow = -1;

                        // Setup the enabled bits...
                        $scope.isEnabled = PAGE.enabled;
                        $scope.hasFeature  = PAGE.hasFeature;

                        if (!$scope.hasFeature) {
                            return;
                        }

                        // setup data structures for the view
                        $scope.domainList = [];
                        $scope.totalPages = 0;
                        $scope.totalItems = 0;
                        $scope.meta = {
                            filterBy: $routeParams.filterBy || "*",
                            filterCompare: $routeParams.filterCompare || "contains",
                            filterValue: $routeParams.filterValue || "",
                            pageSize: $routeParams.pageSize || 20,
                            pageNumber: $routeParams.pageNumber || 1,
                            sortDirection: $routeParams.sortDirection || "asc",
                            sortBy: $routeParams.sortBy || "domain",
                            sortType: $routeParams.sortType,
                            pageSizes: [20, 50, 100],
                            start: 0,
                            limit: 0
                        };
                    };

                    /**
                     * Are All Domains Currently Disabled
                     *
                     * @method allDomainsAreDisabled
                     * @return {boolean} True if all Domains are Disabled
                     */
                    $scope.allDomainsAreDisabled = function() {
                        return $scope.totalDisabled === $scope.totalItems;
                    };

                    /**
                     * Are All Domains Currently Enabled
                     *
                     * @method allDomainsAreEnabled
                     * @return {boolean} True if all Domains are Enabled
                     */
                    $scope.allDomainsAreEnabled = function() {
                        return $scope.totalEnabled === $scope.totalItems;
                    };

                    /**
                     * Does the logged in account have domains
                     *
                     * @method hasNoDomains
                     * @return {boolean} True if there are no domains associated with the logged in account
                     */
                    $scope.hasNoDomains = function() {
                        return $scope.totalItems === 0;
                    };

                    /**
                     * Clear the search query
                     *
                     * @method clearFilter
                     */
                    $scope.clearFilter = function() {
                        $scope.meta.filterValue = "";
                        $scope.activeSearch = false;
                        $scope.filteredData = false;
                        $scope.selectedRow = -1;
                        return $scope.fetch();
                    };

                    /**
                     * Start a search query
                     *
                     * @method startFilter
                     */
                    $scope.startFilter = function() {
                        $scope.activeSearch = true;
                        $scope.filteredData = false;
                        $scope.selectedRow = -1;
                        var defer = $q.defer();
                        defer.promise
                            .then(function() {

                                // select the first page of search results
                                $scope.selectPage(1);
                            })
                            .then(function() {
                                $scope.filteredData = true;
                            });
                        defer.resolve();
                    };


                    /**
                     * Selects a table row
                     *
                     * @method toggleRow
                     * @param  {Object} $event The Event object
                     * @param  {Number} index The index of selected row
                     */
                    $scope.toggleRow = function($event, index) {

                        // prevent the default action of the link
                        $event.preventDefault();

                        if ( index === $scope.selectedRow ) {

                            // collapse the row
                            $scope.selectedRow = -1;

                        } else {

                            // expand the selected row
                            $scope.selectedRow = index;
                        }

                    };

                    /**
                     * Change the page size
                     *
                     * @method selectPageSize
                     */
                    $scope.selectPageSize = function() {
                        $scope.selectPage(1);
                    };

                    /**
                     * Select a specific page
                     *
                     * @method selectPage
                     * @param  {Number} [page] Optional page number, if not provided will use the current
                     * page provided by the scope.meta.pageNumber.
                     * @return {Promise}
                     */
                    $scope.selectPage = function(page) {

                        // clear the selected row
                        $scope.selectedRow = -1;

                        // set the page if requested
                        if (page && angular.isNumber(page)) {
                            $scope.meta.pageNumber = page;
                        }

                        // fetch the page
                        return $scope.fetch();
                    };

                    /**
                     * Sort the list of domains
                     *
                     * @method sortList
                     * @param {Object} meta             An object with metadata properties of sortBy, sortDirection, and sortType.
                     * @param {Boolean} [defaultSort]   If true, this sort was not initiated by the user.
                     */
                    $scope.sortList = function(meta, defaultSort) {

                        // clear the selected row
                        $scope.selectedRow = -1;

                        if (!defaultSort) {
                            $scope.fetch();
                        }
                    };

                    /**
                     * Handles the keybinding for the clearing and searching.
                     * Esc clears the search field.
                     * Enter performs a search.
                     *
                     * @method triggerToggleSearch
                     * @param {Event} event - The event object
                     */
                    $scope.triggerToggleSearch = function(event) {

                        // clear on Esc
                        if (event.keyCode === 27) {
                            $scope.toggleSearch(true);
                        }

                        // filter on Enter
                        if (event.keyCode === 13) {
                            $scope.toggleSearch();
                        }
                    };

                    /**
                     * Toggles the clear button and conditionally performs a search.
                     * The expected behavior is if the user clicks the button or focuses the button and hits enter the button state rules.
                     * If the user hits <enter> in the field, its a submit action with just request the data.
                     * If the user hits <esc> behavior which will unconditionally clear.
                     *
                     * @method toggleSearch
                     * @param {Boolean} isClick Toggle button clicked.
                     */
                    $scope.toggleSearch = function(isClick) {
                        var filter = $scope.meta.filterValue;

                        if ( !filter && ($scope.activeSearch  || $scope.filteredData)) {

                            // no query in box, but we previously filtered or there is an active search
                            $scope.clearFilter();
                        } else if (isClick && $scope.activeSearch ) {

                            // User clicks clear
                            $scope.clearFilter();
                        } else if (filter) {
                            $scope.startFilter();
                        }
                    };

                    /**
                     * Fetch the list of domains from the server.
                     *
                     * @method fetch
                     * @return {Promise} Promise that when fulfilled will result in the list being loaded with the new criteria.
                     */
                    $scope.fetch = function() {
                        spinnerAPI.start("loadingSpinner");
                        return DomainService
                            .fetchList($scope.meta)
                            .then(function(results) {
                                $scope.domainList = results.items;
                                $scope.totalItems = results.totalItems;
                                $scope.totalPages = results.totalPages;
                                $scope.totalEnabled  = results.totalEnabled;
                                $scope.totalDisabled = results.totalDisabled;

                                $scope.meta.start = ($scope.meta.pageNumber - 1) * $scope.meta.pageSize + 1;
                                $scope.meta.limit = $scope.meta.pageNumber * $scope.meta.pageSize;

                                if ($scope.meta.limit > $scope.totalItems) {
                                    $scope.meta.limit = $scope.totalItems;
                                }

                                if ($scope.meta.limit === 0) {
                                    $scope.meta.start = 0;
                                }
                            }, function(error) {
                                alertService.add({
                                    type: "danger",
                                    message: error,
                                    closeable: true,
                                    replace: false,
                                    group: "greylisting"
                                });
                            })
                            .then(function() {
                                spinnerAPI.stop("loadingSpinner");
                            });
                    };

                    /**
                     * Sets the status of greylisting on the supplied domain.
                     *
                     * @method setDomain
                     * @param {Object} domain The domain with status to set
                     * @return {Promise} Promise that when fulfilled will result in the domains status being set in the API.
                     */
                    $scope.setDomain = function(domain) {
                        spinnerAPI.start("loadingSpinner");
                        if ( domain.enabled ) {
                            return DomainService
                                .enableDomains(domain.domain)
                                .then(function(result) {
                                    $scope.totalEnabled++;
                                    $scope.totalDisabled--;
                                    alertService.add({
                                        type: "success",
                                        message: LOCALE.maketext("Successfully enabled [asis,Greylisting] on “[output,class,_1,nobreak]”.", result.items[0].domain),
                                        closeable: true,
                                        replace: false,
                                        autoClose: 10000,
                                        group: "greylisting"
                                    });
                                }, function(results) {
                                    alertService.add({
                                        type: "danger",
                                        message: results.error,
                                        closeable: true,
                                        replace: false,
                                        group: "greylisting"
                                    });
                                })
                                .then(function() {
                                    spinnerAPI.stop("loadingSpinner");
                                });
                        } else {
                            return DomainService
                                .disableDomains(domain.domain)
                                .then(function(result) {
                                    $scope.totalDisabled++;
                                    $scope.totalEnabled--;
                                    alertService.add({
                                        type: "success",
                                        message: LOCALE.maketext("Successfully disabled [asis,Greylisting] on “[output,class,_1,nobreak]”.", result.items[0].domain),
                                        closeable: true,
                                        replace: false,
                                        autoClose: 10000,
                                        group: "greylisting"
                                    });
                                }, function(results) {
                                    alertService.add({
                                        type: "danger",
                                        message: results.error,
                                        closeable: true,
                                        replace: false,
                                        group: "greylisting"
                                    });
                                })
                                .then(function() {
                                    spinnerAPI.stop("loadingSpinner");
                                });
                        }
                    };

                    /**
                     * Enable greylisting on all domains
                     *
                     * @method enableAllDomains
                     * @param  {Object} $event The Event object
                     * @return {Promise} Promise that when fulfilled will result in the domains being enabled.
                     */
                    $scope.enableAllDomains = function($event) {
                        if ($scope.allDomainsAreEnabled()) {
                            return;
                        }

                        spinnerAPI.start("loadingSpinner");
                        return DomainService
                            .enableAllDomains()
                            .then(function(results) {
                                _updateStatus($scope.domainList, results.items);
                                $scope.totalItems = results.totalItems;
                                $scope.totalPages = results.totalPages;
                                $scope.totalEnabled = results.totalItems;
                                $scope.totalDisabled = 0;
                                alertService.add({
                                    type: "success",
                                    message: LOCALE.maketext("Successfully enabled [asis,Greylisting] on all domains."),
                                    closeable: true,
                                    replace: false,
                                    autoClose: 10000,
                                    group: "greylisting"
                                });
                            }, function(results) {
                                alertService.add({
                                    type: "danger",
                                    message: results.error,
                                    closeable: true,
                                    replace: false,
                                    group: "greylisting"
                                });
                            })
                            .then(function() {
                                spinnerAPI.stop("loadingSpinner");
                            });
                    };

                    /**
                     * Disable greylisting on all domains.
                     *
                     * @method disableAllDomains
                     * @param  {Object} $event The Event object
                     * @return {Promise} Promise that when fulfilled will result in the domains being enabled.
                     */
                    $scope.disableAllDomains = function($event) {
                        if ($scope.allDomainsAreDisabled()) {
                            return;
                        }

                        spinnerAPI.start("loadingSpinner");
                        return DomainService
                            .disableAllDomains()
                            .then(function(results) {
                                _updateStatus($scope.domainList, results.items);
                                $scope.totalItems = results.totalItems;
                                $scope.totalPages = results.totalPages;
                                $scope.totalDisabled = results.totalItems;
                                $scope.totalEnabled = 0;
                                alertService.add({
                                    type: "success",
                                    message: LOCALE.maketext("Successfully disabled [asis,Greylisting] on all domains."),
                                    closeable: true,
                                    replace: false,
                                    autoClose: 10000,
                                    group: "greylisting"
                                });
                            }, function(results) {
                                alertService.add({
                                    type: "danger",
                                    message: results.error,
                                    closeable: true,
                                    replace: false,
                                    group: "greylisting"
                                });
                            })
                            .finally(function() {
                                spinnerAPI.stop("loadingSpinner");
                            });
                    };

                    /**
                     * Check if there are any disabled domains
                     *
                     * @method hasDisabledDomains
                     * @return {Boolean} true if there are disabled domains, false otherwise
                     */
                    $scope.hasDisabledDomains = function() {
                        return $scope.totalDisabled > 0;
                    };

                    /**
                     * Initialize the view
                     *
                     * @private
                     * @method _initializeView
                     */
                    var _initializeView = function() {

                        // check for page data in the template if this is a first load
                        if (app.firstLoad.domainList && PAGE.domainList) {
                            app.firstLoad.domainList = false;
                            var results = DomainService.prepareList(PAGE.domainList);
                            $scope.meta.pageNumber = 1;
                            $scope.domainList = results.items;
                            $scope.totalItems = results.totalItems;
                            $scope.totalPages = results.totalPages;
                            $scope.totalEnabled = PAGE.domainList.meta.cPGreyList.total_enabled;
                            $scope.totalDisabled = PAGE.domainList.meta.cPGreyList.total_disabled;

                            $scope.meta.start = ($scope.meta.pageNumber - 1) * $scope.meta.pageSize + 1;
                            $scope.meta.limit = $scope.meta.pageNumber * $scope.meta.pageSize;


                            if ($scope.meta.limit > $scope.totalItems) {
                                $scope.meta.limit = $scope.totalItems;
                            }

                            if ($scope.meta.limit === 0) {
                                $scope.meta.start = 0;
                            }
                        } else {

                            // Otherwise, retrieve it via ajax
                            $scope.selectPage(1);
                        }
                    };

                    _initializeScope();

                    // if the user types something else in the search box, we change the button icon so they can search again.
                    $scope.$watch("meta.filterValue", function(oldValue, newValue) {
                        if (oldValue === newValue) {
                            return;
                        }
                        $scope.activeSearch = false;
                    });

                    _initializeView();

                }
            ]
        );

        return controller;
    }
);
Back to Directory File Manager