File manager - Edit - /usr/local/cpanel/whostmgr/docroot/templates/transfer_tool/controllers/AccountTableController.js
Back
// Copyright 2025 WebPros International, LLC // All rights reserved. // copyright@cpanel.net http://cpanel.net // This code is subject to the cPanel license. Unauthorized copying is prohibited. /* # templates/transfer_tool/controllers/AccountTableController.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, PAGE */ /* jshint -W003 */ /* jshint -W098*/ define( [ "angular", "cjt/util/locale", "cjt/util/parse", "app/services/workerNodes", "app/filters/startFromFilter", "app/filters/cpLimitToFilter", "app/filters/accountFilter", "app/filters/advanceAccountFilter", "cjt/services/whm/nvDataService", ], function(angular, LOCALE, PARSE, WorkerNodesService) { "use strict"; var DEFAULT_CUSTOMIZED_LABEL = LOCALE.maketext("Default"); var CUSTOM_CUSTOMIZED_LABEL = LOCALE.maketext("Custom"); var SKIP_FLAG_DEFAULTS = { "copy_homedir": 1, "copy_databases": 1, "copy_bwdata": 1, "copy_reseller_privs": 0, "copy_integration_links": 0, }; var CONTROLLER_INJECTABLES = ["$scope", "$rootScope", WorkerNodesService.serviceName, "$filter", "$uibModal", "PAGE", "nvDataService", "OVERWRITE_OPTIONS", "OVERWRITE_STATES", "OVERWRITE_DESCRIPTION_TEMPLATE"]; /** * @class Controller class for the account table. Used in the angular app with 'controller as'. This contains most logic pertaining to accounts. * @param {object} $scope * @param {object} $filter */ var AccountTableController = function($scope, $rootScope, $workerNodesService, $filter, $uibModal, PAGE, nvDataService, OVERWRITE_OPTIONS, OVERWRITE_STATES, OVERWRITE_DESCRIPTION_TEMPLATE) { var _this = this; _this.PAGE = PAGE; _this.disableLiveTransfers = _this.PAGE.disable_live_transfers; _this.isRestrictedRestore = _this.PAGE.restricted_restore; _this.isRTL = PAGE.locale_is_rtl.toString() === "1"; _this.overwriteOptions = OVERWRITE_OPTIONS; _this.reservedUsernamePatterns = _this.PAGE.local.reserved_username_patterns; _this.localUserHash = Object.create(null); _this.reservedUsernames = {}; _this.localPartialUsernames = {}; _this.defaultWorkerOptions = $workerNodesService.getDefaultWorkerOptions(); _this.workerOptionTypes = $workerNodesService.getWorkerOptionTypes(); _this.control_overwrite = _this.overwriteOptions[0]; _this.overwriteStates = OVERWRITE_STATES; _this.accountFilterText = ""; _this.acctTable = { currentPage: 1, pageSize: 10, reverse: false, order: "remote_user", advSearchOptions: { domain: "", user: "", owner: [], dedicated_ip: -1, }, activeAdvFilter: null, }; _this.getDedicatedIPDomains = function() { return _this.PAGE.domainsWithDedicatedIp; }; // This will require more logic as the banner messages that can reset dedicated // IP addresses so for now we are returning the status // quo of always displaying the column. _this.showDedicatedIPColumn = true; var supportsExpressTransfers = PAGE.remote ? PARSE.parsePerlBoolean(PAGE.remote.supports_express_transfers) : false; var supportsLiveTransfers = PAGE.remote ? PARSE.parsePerlBoolean(PAGE.remote.supports_live_transfers) : false; $scope.supportsTempDomains = PAGE.local ? PARSE.parsePerlBoolean(PAGE.local.supports_temp_domains) : false; // If we support live transfers, it defaults to on // Unless it has been disabled var PROXY_FLAG_DEFAULT = supportsLiveTransfers && !_this.disableLiveTransfers; $scope.supportsLiveTransfers = supportsLiveTransfers; $scope.liveTransfersNoticeIsDismissed = PAGE.liveTransfersNoticeIsDismissed; $scope.liveTransfersPre90NoticeIsDismissed = PAGE.liveTransfersPre90NoticeIsDismissed; $scope.isAcctTabActive = true; // Overload the live transfer support. This gets set when the hostname is invalid. // We also need to overload and hide the notifications for live transfers if (_this.disableLiveTransfers) { $scope.liveTransfersNoticeIsDismissed = true; } $scope.dismissLiveTransfersNotice = function dismissLiveTransfersNotice() { $scope.liveTransfersNoticeIsDismissed = true; nvDataService.set("live_transfers_notice_is_dismissed", 1); }; $scope.dismissLiveTransfersPre90Notice = function dismissLiveTransfersPre90Notice() { $scope.liveTransfersPre90NoticeIsDismissed = true; $scope.liveTransfersNoticeIsDismissed = true; nvDataService.set("live_transfers_pre_90_notice_is_dismissed", 1); }; $rootScope.showTable = function showTable() { return !$scope.isAcctTabActive || (!$scope.supportsLiveTransfers || ($scope.supportsLiveTransfers && $scope.liveTransfersNoticeIsDismissed)); }; $rootScope.setAcctTabActive = function(isAcctTabActive) { $scope.isAcctTabActive = isAcctTabActive; }; _this.createUser = function(obj, index) { obj.initialindex = index; obj.copy_homedir = SKIP_FLAG_DEFAULTS["copy_homedir"]; obj.copy_databases = SKIP_FLAG_DEFAULTS["copy_databases"]; obj.copy_bwdata = SKIP_FLAG_DEFAULTS["copy_bwdata"]; obj.copy_reseller_privs = SKIP_FLAG_DEFAULTS["copy_reseller_privs"]; obj.copy_integration_links = SKIP_FLAG_DEFAULTS["copy_integration_links"]; obj.copy_proxy_option = PROXY_FLAG_DEFAULT; obj.proxyOption = { id: "proxy_option", modelKey: "copy_proxy_option", value: PROXY_FLAG_DEFAULT, default: PROXY_FLAG_DEFAULT, supports_live_transfers: PROXY_FLAG_DEFAULT, supports_express_transfers: supportsExpressTransfers, }; obj.selected = 0; obj.overwrite_type = _this.overwriteOptions[0]; obj.overwrite_account = 0; obj.overwrite_with_delete = 0; obj.updateDNSZone = true; obj.userCheckStates = { duplicate: false, reserved: false, existing: false, }; obj.dedicated_ip = (obj.dedicated_ip || _this.getDedicatedIPDomains()[obj.domain]) ? 1 : 0; obj.existing_dedicated_ip = obj.dedicated_ip; obj.oldlocaluser = obj.user; obj.localuser = obj.user; obj.invalidDomain = _this.PAGE.local.domains[obj.domain] && _this.PAGE.local.domains[obj.domain] !== obj.user ? 1 : 0; obj.is_reseller = _this.PAGE.remote.resellers && _this.PAGE.remote.resellers[obj.remote_user] ? 1 : 0; obj.invalidUser = _this.PAGE.local.users[obj.remote_user] ? 1 : 0; obj.isCustomized = false; obj.workerNodes = obj.worker_nodes || {}; obj.isTempDomain = obj.is_temp_domain || 0; obj.serverSupportsTempDomains = $scope.supportsTempDomains; // This is done in the service because it's done in multiple controllers $workerNodesService.resetAccountToDefaults(obj); }; _this.expandedAccount = false; _this.PAGE.items.accounts.forEach(_this.createUser); var accountFilter = $filter("accountFilter"), advanceAccountFilter = $filter("advanceAccountFilter"), startFrom = $filter("startFrom"), orderBy = $filter("orderBy"), limitTo = $filter("cpLimitTo"); // To better understand what these assignments are look at updateFilteredAccounts and updateViewableAccounts _this.filteredAccounts = accountFilter(advanceAccountFilter(this.PAGE.items.accounts, _this.acctTable.activeAdvFilter), _this.accountFilterText); _this.viewableAccounts = limitTo(startFrom(orderBy(_this.filteredAccounts, _this.acctTable.order, _this.acctTable.reverse), (_this.acctTable.currentPage - 1) * _this.acctTable.pageSize), _this.acctTable.pageSize); /** * Reapplies filters for the filteredAccounts array * Array -> Filtered by advanced -> filtered by basic * accounts | advanceAccountFilter:activeAdvFilter | accountFilter:accountFilterText */ _this.updateFilteredAccounts = function() { _this.filteredAccounts = accountFilter( advanceAccountFilter(this.PAGE.items.accounts, _this.acctTable.activeAdvFilter), _this.accountFilterText); }; /** * Reapplies filteres for the viewableAccounts array. * FilteredArray -> Ordered by(reverse?) -> start based on page # -> limit to page size * filteredAccounts | orderBy: acctTable.order:acctTable.reverse | startFrom:(acctTable.currentPage - 1 ) * acctTable.pageSize | limitTo: acctTable.pageSize */ _this.updateViewableAccounts = function() { var pageSize = _this.acctTable.pageSize; var accounts = orderBy(_this.filteredAccounts, _this.acctTable.order, _this.acctTable.reverse); accounts = limitTo(startFrom(accounts, (_this.acctTable.currentPage - 1) * pageSize), pageSize); _this.viewableAccounts = accounts; }; _this.getUsernamePattern = function(key) { if (key === "TRIM_PATTERN") { return new RegExp(_this.PAGE.UN_TRIM_REG_EXP); } else if (key === "TRANSFER_USER_RESTRICT") { return new RegExp(_this.PAGE.USERNAME_TRANSFER_REGEXP); } else if (key === "NONTRANSFER_USER_RESTRICT") { return new RegExp(_this.PAGE.USERNAME_REGEXP); } else { return null; } }; $scope.$on("recheckUsersCalled", function(eo, args) { angular.forEach(args.dataset, function(acct) { // Always skip forcing selection, since "Select None" will cause this to just get re-selected _this.updateOverwriteFlags(acct, false, true); _this.updateUserCheckStates(acct); _this.checkAccountForDuplicateLocals(acct); _this.updateAccountsControlRow(); }); }); $scope.$on("selectedAccountsEmptied", function() { _this.acct_checkbox_control = false; _this.updateAccountsControlRow(); }); $scope.$watch(function() { return _this.acctTable; }, function() { _this.updateViewableAccounts(); }, true); $scope.$watch(function() { return _this.viewableAccounts; }, function() { _this.updateAccountsControlRow(); }, true); for (var rUi = 0; rUi < _this.PAGE.local.reserved_usernames.length; rUi++) { var reservedUsername = _this.PAGE.local.reserved_usernames[rUi].toLowerCase(); _this.reservedUsernames[reservedUsername] = 1; } /* used to check the eight v 16 restrictions of (no same first USERNAME_UNIQUE_LENGTH characters) */ /* pre processed for big lists */ angular.forEach(_this.PAGE.local.users, function(value, lUsername) { var plUsername = _this.makeUsernamePartial(lUsername, true); this[plUsername] = lUsername; }, _this.localPartialUsernames); angular.forEach(_this.PAGE.items.accounts, function(acct, key) { /* store local user hash */ _this.storeLocalUserHash(acct.initialindex, acct.oldlocaluser, acct.localuser); }); // Set the columnWidth _this.numberOfColumns = 9; ["bytesused", "owner", "dedicated_ip"].forEach(function(key) { if (!_this.showColumn(key)) { _this.numberOfColumns--; } }); _this.skipOptions = [ { id: "copy_homedir_for", label: LOCALE.maketext("Home Directory"), modelKey: "copy_homedir", default: SKIP_FLAG_DEFAULTS["copy_homedir"] }, // Disable reseller privileges skipOption for restricted restores { id: "reseller_privs_for", label: LOCALE.maketext("Reseller Privileges"), modelKey: "copy_reseller_privs", default: SKIP_FLAG_DEFAULTS["copy_reseller_privs"], disabled: _this.isRestrictedRestore }, { id: "copy_acctdb_for", label: LOCALE.maketext("Databases"), modelKey: "copy_databases", default: SKIP_FLAG_DEFAULTS["copy_databases"] }, { id: "copy_bwdata_for", label: LOCALE.maketext("Bandwidth Data"), modelKey: "copy_bwdata", default: SKIP_FLAG_DEFAULTS["copy_bwdata"] }, { id: "integration_links_for", label: LOCALE.maketext("Integration Links"), modelKey: "copy_integration_links", default: SKIP_FLAG_DEFAULTS["copy_integration_links"] }, ]; _this.openModal = $uibModal.open.bind($uibModal); _this.overwriteDescriptionTemplate = OVERWRITE_DESCRIPTION_TEMPLATE; this._workerOptionAltered = $workerNodesService.checkWorkerOptionsAltered.bind($workerNodesService); return _this; }; angular.extend(AccountTableController.prototype, { /** * Stores hashed usernames for duplication checks on large amounts of usernames */ storeLocalUserHash: function storeLocalUserHash(index, oldValue, newValue) { var _this = this; var newValuePartial = this.makeUsernamePartial(newValue, true); var oldValuePartial = this.makeUsernamePartial(oldValue, true); _this.localUserHash[oldValuePartial] = _this.localUserHash[oldValuePartial] || []; angular.forEach(_this.localUserHash[oldValuePartial], function(value, key) { if (value === index) { _this.localUserHash[oldValuePartial].splice(key, 1); } }); _this.localUserHash[newValuePartial] = _this.localUserHash[newValuePartial] || []; _this.localUserHash[newValuePartial].push(index); }, /** * Calls functions that update filtered and viewable accounts */ updateAccounts: function updateAccounts() { this.updateFilteredAccounts(); this.updateViewableAccounts(); }, /** * Returns class corresponding to glyph for account. Account must be selected and not have a domain conflict. * @param {object} acct * @return {?string} */ getGlyphClass: function getGlyphClass(acct) { if (!acct.selected || acct.domainConflict) { return; } if (acct.invalidUser) { return "glyphicon-exclamation-sign"; } else { return "glyphicon-ok"; } }, /** * Returns class for button that corresponds to what choice for dedicated ip was selected. Used in advance search form to indicate selection similar to radio button. * @param {int} thisVal * @return {string|Boolean} */ dedicatedIpClass: function dedicatedIpClass(thisVal) { return thisVal === this.acctTable.advSearchOptions.dedicated_ip ? "btn-primary" : "btn-default"; }, /** * Check the state of the various control columns * * @param {object[]} accounts list of accounts to build the value based on * @param {string} param parameter on account to check * @returns {*} current value of control column. Various values possible. */ _getColumnControlState: function _getColumnControlState(accounts, param) { // If there are no accounts, return false if (!accounts.length) { return false; } // If any are not checked, return false for (var i = 0; i < accounts.length; i++) { var account = accounts[i]; if (!account[param]) { return false; } } // If all are checked, return true return true; }, /** * Check the state of the overwrite control column * * @param {object[]} accounts list of accounts to build the value based on * @param {string} param parameter on account to check * @returns {object|null} value of the parameter for accounts if the same. Undefined otherwise. */ _getOverwriteColumnControlState: function _getOverwriteColumnControlState(accounts, param) { // Update only based on selected accounts in list // If there are no accounts, return false if (!accounts.length) { return this.overwriteOptions[0]; } var currentValue; for (var i = 0; i < accounts.length; i++) { var account = accounts[i]; if (!this.canNeedOverwrite(account)) { // Only ones that might need overwrite should be considered continue; } // Store the first value as a baseline if (!currentValue) { currentValue = account[param]; } // If any are different from one another, default to undef (to allow setting it) if (account[param].value !== currentValue.value) { return; } } // If all are one of the two overwrite values [1,2], use that value // If no value was determined, then no overwrite-capable items were found, use the zero option return currentValue ? currentValue : this.overwriteOptions[0]; }, /** * Called to check and adjust control row check boxes based on viewable account params */ updateAccountsControlRow: function updateAccountsControlRow() { var checks = [{ param: "selected", controlModel: "acct_checkbox_control", checkFunction: this._getColumnControlState.bind(this), }, { param: "dedicated_ip", controlModel: "control_dedicated_ip", onlySelected: true, checkFunction: this._getColumnControlState.bind(this), }, { param: "overwrite_type", controlModel: "control_overwrite", onlySelected: true, checkFunction: this._getOverwriteColumnControlState.bind(this), }]; var selectedAccounts = this.viewableAccounts.filter(function(account) { return !!account.selected; }); angular.forEach(checks, function(check) { var accounts = check.onlySelected ? selectedAccounts : this.viewableAccounts; this[check.controlModel] = check.checkFunction(accounts, check.param); }, this); }, /** * Sets the advance search($scope.acctTable.advSearchOptions) to either be a copy of the object passed in or if no object, to the default value. We set it this way * because otherwise Angular will bind the object directily causing any updates to be instantaneous, breaking the experience. * @param {object} obj */ setAdvanceSearch: function setAdvanceSearch(obj) { this.acctTable.activeAdvFilter = angular.copy(obj); this.updateAccounts(); if (!obj) { this.acctTable.advSearchOptions = { domain: "", user: "", owner: [], dedicated_ip: -1, }; } }, /** * Goes over array of accounts and sets the dedicated_ip flag if the destination domain already has a dedicated ip. * @param {array} dataset */ handleDedicatedIpForArray: function handleDedicatedIpForArray(dataset) { var _self = this; angular.forEach(dataset, function(acct) { if (_self.getDedicatedIPDomains()[acct.domain]) { acct.dedicated_ip = 1; } }); }, /** * Returns true if the account has a destination domain with a dedicated ip already or if there are no available IP addresses. * @param {object} acct * @return {Boolean} */ isDedicatedIpDisabled: function isDedicatedIpDisabled(acct) { return this.getDedicatedIPDomains()[acct.domain] ? true : !this.PAGE.local.available_ips.length; }, /** * Returns true for account that can be overwritten * @param {object} item * @return {Boolean} */ overwriteFilter: function overwriteFilter(item) { return this.PAGE.local.users[item.user] || this.PAGE.local.users[item.localuser] || (this.PAGE.local.domains[item.domain] === item.localuser); }, /** * Updates account username checks and stores then on acct.userCheckStates * then updates calls updateLocalUserStatus() to reset acct.invalidUser * * @method validateAccount * @param acct {Object} angular user account object */ validateAccount: function validateAccount(acct) { // update account localuser hash for duplicate validation /* which large accounts this was the only feasible option. */ /* deep watch expressions were far too cumbersome. */ this.storeLocalUserHash(acct.initialindex, acct.oldlocaluser, acct.localuser); /* must be called before oldusername is reset to reset duplication on old set */ this.checkAccountForDuplicateLocals(acct); acct.oldlocaluser = acct.localuser; this.updateUserCheckStates(acct); }, /** * Seperate function allows independent updates to userCheckStates * used in ToggleCheckAll * * @method updateuserCheckStatus * @param acct {Object} angular user account object */ updateUserCheckStates: function updateUserCheckStates(acct) { /* response is now in the form of false, or failure object */ acct.userCheckStates.reserved = this.isReservedUsername(acct); acct.userCheckStates.existing = this.isExistingLocalUser(acct); /* refers to the specific makeup of the new username (does it match the regexp) */ acct.userCheckStates.invalid = !this.isLocalUsernameValid(acct); acct.overwrite_type = acct.selected ? acct.overwrite_type : this.overwriteOptions[0]; this.updateLocalUserStatus(acct); }, /** * updates 'invalidUser' based on state check flags * * @method updateLocalUserStatus * @param acct {Object} angular user account object */ updateLocalUserStatus: function updateLocalUserStatus(acct) { if ((acct.userCheckStates.existing !== false && acct.overwrite_type.value === this.overwriteStates.NO_OVERWRITE ) || acct.userCheckStates.duplicate !== false || acct.userCheckStates.invalid !== false || acct.userCheckStates.reserved !== false) { acct.invalidUser = true; } else { acct.invalidUser = false; } }, /** * Returns the class to be used for input field highlighting. * @param {object} acct * @return {?string} */ getInputClass: function getInputClass(acct) { if (!acct.selected || acct.domainConflict) { return; } if (acct.invalidUser) { return "has-error"; } else { return "has-success"; } }, /** * Returns username converted from account as as string * * @method getUserNameFromAcct * @param acct {Object} angular user account object * @return {String} value of username */ getUserNameFromAcct: function getUserNameFromAcct(acct) { var username = acct.localuser || ""; if (!username.length) { username = acct.remote_user; } return username; }, /** * Returns Array of accounts that the username matches (can be partial match). * * @method findAccountsByUsername * @param username {String} angular user account object * @param matchFirstNChars {int} number of matching characters defaults to all * passing -1 will be treated as a 'match all characters' * @param startingIndex {int} which account to begin the interation from (faster) * @return {Array} of acct indexes that match */ findAccountsByUsername: function findAccountsByUsername(username, matchFirstNChars, startingIndex) { /* if matchFirstNChars > 0 use matchFirstNChars | else use -1 (interpretted as all) */ matchFirstNChars = Number(matchFirstNChars) || -1; startingIndex = Number(startingIndex) || 0; if (matchFirstNChars !== -1) { username = username.substr(0, matchFirstNChars); } var matchedAccounts = []; var otherAccount; for (var i = startingIndex; i < this.PAGE.items.accounts.length; i++) { otherAccount = this.PAGE.items.accounts[i]; if (otherAccount.localuser.toLowerCase().indexOf(username) === 0) { if (username.length < matchFirstNChars && otherAccount.localuser.length > username.length) { /* this means that the otherAccount has additional characters in the NChars range so it is no longer enough matching characters */ continue; } /* username was found in it */ if (matchFirstNChars === -1 && username.length !== otherAccount.localuser.length) { /* matchFirstNChars is set to default (match all), but lengths of the usernames */ continue; } /* good length, good first n chars */ matchedAccounts.push(i); } } return matchedAccounts; }, /** * finds accounts by username, then returns selected accounts * * @method findSelectedAccountsByUsername * see: findAccountsByUsername for @params */ findSelectedAccountsByUsername: function findSelectedAccountsByUsername( /* inherit from findAccountsByUsername */ ) { var usernames = this.findAccountsByUsername.apply(this, arguments); var selected = []; if (usernames === false) { return selected; } var uIndex; for (var i = 0; i < usernames.length; i++) { uIndex = usernames[i]; if (this.PAGE.items.accounts[uIndex].selected) { selected.push(uIndex); } } return selected; }, /** * Checks one local account for duplicates and marks userCheckStates.duplicate accordingly * * @method checkAccountForDuplicateLocals */ checkAccountForDuplicateLocals: function checkAccountForDuplicateLocals(acct) { /* clear status flag */ acct.userCheckStates.duplicate = false; /* get oldlocaluser and reset old duplicates */ var oldUsernamePartial = this.makeUsernamePartial(acct.oldlocaluser, true); /* recheck old username set to update their duplicate flag */ if (this.localUserHash[oldUsernamePartial] && this.localUserHash[oldUsernamePartial].length === 1) { var previousDuplicateUser = this.localUserHash[oldUsernamePartial][0]; this.PAGE.items.accounts[previousDuplicateUser].userCheckStates.duplicate = false; this.updateLocalUserStatus(this.PAGE.items.accounts[previousDuplicateUser]); } /* no local username entered? Ignore it! */ if (!acct.localuser) { return; } var username = acct.localuser; var trimmedUsername = this.makeUsernamePartial(username, true); var accountIndexOrObject; var accountIndex; var selectedOthers = []; /* reset all, store still selected items for next loop */ for (var i = 0; i < this.localUserHash[trimmedUsername].length; i++) { accountIndex = this.localUserHash[trimmedUsername][i]; accountIndexOrObject = this.PAGE.items.accounts[accountIndex]; accountIndexOrObject.userCheckStates.duplicate = false; this.updateLocalUserStatus(accountIndexOrObject); /* items that aren't selected are ignored */ if (!accountIndexOrObject.selected) { continue; } selectedOthers.push(accountIndexOrObject); } /* if multiple items remain selected in this hash, set them as duplicates */ if (selectedOthers.length > 1) { for (i = 0; i < selectedOthers.length; i++) { accountIndexOrObject = selectedOthers[i]; accountIndexOrObject.userCheckStates.duplicate = true; this.updateLocalUserStatus(accountIndexOrObject); } } }, /** * Checks all local accounts for duplicates and marks userCheckStates.duplicate accordingly * * @method checkForDuplicateLocals */ checkForDuplicateLocals: function checkForDuplicateLocals() { /* check this username against other usernames that have been checked for transfer */ var i, otherAccount; /* reset all initially to allow faster parsing later in function*/ for (i = 0; i < this.PAGE.items.accounts.length; i++) { otherAccount = this.PAGE.items.accounts[i]; otherAccount.userCheckStates.duplicate = false; this.updateLocalUserStatus(otherAccount); } /* iterate through all, skip already set duplicates, */ for (i = 0; i < this.PAGE.items.accounts.length; i++) { otherAccount = this.PAGE.items.accounts[i]; if (otherAccount.userCheckStates.duplicate) { /* because of forward iteration nature of this, this has been cleared and marked as a set for another item */ continue; } this.checkAccountForDuplicateLocals(otherAccount); } }, /** * Returns Boolean defining whether account username is considered reserved. * * @method isReservedUsername * @param acct {Object} angular user account object * @return {Boolean} true if username is reserved */ isReservedUsername: function isReservedUsername(acct) { var username = this.getUserNameFromAcct(acct); /* trim spaces from ends of username */ var trimmedUsername = username.replace(/^\s*(.+)\s*$/i, "$1"); /* check against reserved system names to see if this on exists */ if (trimmedUsername in this.reservedUsernames) { return true; } /* interim list of restricted partial names (reg ex patterns) */ /* list cannot contain these specific parts */ /* matches names, or parts of names dependent on need <[name]>$ matches a <[name]> at the end of a username ^<[name]> matches a <[name]> at the beginning of the username ^<[name]>$ matches exactly that <[name]> with no trailing or begining characters */ var currentRegExp, reservedNamePattern; for (var i = 0; i < this.reservedUsernamePatterns.length; i++) { reservedNamePattern = this.reservedUsernamePatterns[i]; /* build dynamic regular expression */ currentRegExp = new RegExp(reservedNamePattern, "gi"); if (trimmedUsername.match(currentRegExp) !== null) { return true; } } return false; }, /** * Returns Boolean representing whether acct.username exists on local machine * in part or fully (only first USERNAME_UNIQUE_LENGTH characters need to match) * * @method isExistingLocalUser * @param acct {Object} angular user account object * @return {Boolean} dependent on user existing on local server */ isExistingLocalUser: function isExistingLocalUser(acct) { var username = this.getUserNameFromAcct(acct); var trimmedUsername = this.makeUsernamePartial(username, true); if (trimmedUsername in this.localPartialUsernames) { acct.similarLocalUser = this.localPartialUsernames[trimmedUsername]; return true; } return false; }, /** * Tests username against globally established regexp * uses the transfer specific regexp if remote_user === localuser * uses the non-transfer regexp otherwise * * @method isLocalUsernameValid * @param acct {Object} angular user account object * @return {Boolean} true or false based on regexp.test */ isLocalUsernameValid: function isLocalUsernameValid(acct) { var re = this.getUsernamePattern("TRANSFER_USER_RESTRICT"); var partial = this.makeUsernamePartial(acct.localuser, true); if (!partial.replace(/\-/gi, "").length) { return false; } return re.test(acct.localuser); }, makeUsernamePartial: function makeUsernamePartial(username, removeSpecialCharacters) { if (removeSpecialCharacters) { username = username.replace(/[\_\.]/gi, ""); } return username.replace(this.getUsernamePattern("TRIM_PATTERN"), "$1").toLowerCase(); }, /** * Get the classes for each account row * * @param {object} account user account to check against * @returns {string} if the item is selected, and either the domain or user is invalid, else nothing */ getAccountRowClasses: function getAccountRowClasses(account) { if (!account.selected) { return ""; } if (!account.invalidUser && !account.invalidDomain) { return "success"; } return "danger"; }, /** * Determine whether a column should show based on the key * * @param {string} columnName account key to check * @returns {boolean} qwhether to show the column * */ showColumn: function showColumn(columnName) { switch (columnName) { case "bytesused": return !!this.PAGE.remote.has_disk_used; case "owner": return !!this.PAGE.remote.has_owners; case "dedicated_ip": return !!this.showDedicatedIPColumn; default: return true; } }, /** * For Each account, determine the current chevron icon state * * @param {*} account account to check * @returns {string} if the account is expanded, 'fa-chevron-down', else a left or right based on the RTL settings of LOCALE */ getChevronClasses: function getChevronClasses(account) { var collapsedClass = this.isRTL ? "fa-chevron-left" : "fa-chevron-right"; return this.isAccountExpanded(account) ? "fa-chevron-down" : collapsedClass; }, /** * Update the isCustomized value for an account based on skipOptions states * * @param {object} account account to check */ updateCustomizedFlag: function updateCustomizedFlag(account) { account.isCustomized = this._skipOptionsAltered(account) || this._workerOptionAltered(account) || this._proxyOptionAltered(account) || this._updateDNSZoneAltered(account); }, _skipOptionsAltered: function _skipOptionsAltered(account) { var skipKeys = Object.keys(SKIP_FLAG_DEFAULTS); for (var i = 0; i < skipKeys.length; i++) { var skipKey = skipKeys[i]; if (account[skipKey] !== SKIP_FLAG_DEFAULTS[skipKey]) { return true; } } return false; }, /** * Check if Live Transfer option has be altered * * @param {object} account account to check */ _proxyOptionAltered: function _proxyOptionAltered(account) { if (account.proxyOption.value !== account.proxyOption.default) { return true; } return false; }, /** * Check if updateDNSZone option has been altered from default * * @param {object} account account to check * @returns {boolean} true if altered, false if default */ _updateDNSZoneAltered: function _updateDNSZoneAltered(account) { return account.updateDNSZone !== true; }, /** * Check if the account is expanded * * @param {object} account account to check * @returns {boolean} true|false state of account expansion */ isAccountExpanded: function isAccountExpanded(account) { return this.expandedAccount === account; }, /** * Expand the account * * @param {object} account account to expand */ expandAccount: function expandAccount(account) { if (this.expandedAccount) { this.collapseAccount(this.expandedAccount); } this.expandedAccount = account; this.accountSettingUpdated(account, true); }, /** * Collapse the account * * @param {object} account account to collapse */ collapseAccount: function collapseAccount(account) { this.expandedAccount = false; }, /** * Toggle the expanded state of an account * * @param {object} account account to toggle */ toggleAccountExpansion: function toggleAccountExpansion(account) { if ( this.isAccountExpanded(account) ) { this.collapseAccount(account); } else { this.expandAccount(account); } }, /** * Get the label based on the isCustomized value of the account * * @param {object} account account to check */ getCustomizeLabel: function getCustomizeLabel(account) { return account.isCustomized ? CUSTOM_CUSTOMIZED_LABEL : DEFAULT_CUSTOMIZED_LABEL; }, /** * Called from the view when the expanded panel of an account change * * @param {object} account that changed * @param {string} key what option changed * @param {*} value what is the new value of that option */ onExpandPanelOptionChanged: function onExpandPanelOptionChanged(account, key, value) { this.updateAccountSetting(account, key, value); }, /** * Called from the view when "apply to all" is emmitted * * @param {object} fromAccount source account to copy from * @param {object[]} toAccounts destination accounts to copy to * @param {object[]} skipOptions which skip options to update * @param {object} workerOptions which worker options to update * @param {object} proxyOption proxy option to update * @param {boolean} updateDNSZone update DNS zone setting to copy */ onExpandPanelApplyToAll: function onExpandPanelApplyToAll(fromAccount, toAccounts, skipOptions, workerOptions, proxyOption, updateDNSZone) { // Get Skip Model Keys Once var skipModelKeys = skipOptions.map(function(skipOption) { return skipOption.modelKey; }, this); // Get Worker Model Keys Once var workerModelKeys = workerOptions && Object.keys(workerOptions).map(function(workerOptionType) { return workerOptions[workerOptionType].modelKey; }, this) || []; // Include other options var modelKeys = ["dedicated_ip", "copy_proxy_option", "updateDNSZone"].concat(skipModelKeys, workerModelKeys); var copyOverwrite = this.canNeedOverwrite(fromAccount); // Update extra items and validate toAccounts.filter(function(toAccount) { if (toAccount === fromAccount) { return false; } return true; }).forEach(function(toAccount) { var myCopyOverwrite = copyOverwrite && this.canNeedOverwrite(toAccount); var myModelKeys = modelKeys.slice(); if (myCopyOverwrite) { myModelKeys.push("overwrite_type"); } myModelKeys.forEach(function(modelKey) { this.updateAccountSetting(toAccount, modelKey, fromAccount[modelKey], false); }, this); // If, but only if, both accounts are need-overwrite // we should copy the overwrite setting. if (myCopyOverwrite) { this.updateOverwriteFlags(toAccount, false); } this.validateAccount(toAccount); }, this); }, /** * Update an account setting and update settings based on it. * * @param {object} account account on which to update the setting * @param {string} key setting to update * @param {*} value new value * @param {boolean} validate validate after update */ updateAccountSetting: function updateAccountSetting(account, key, value, validate) { if (!validate && key === "copy_proxy_option") { account.proxyOption.value = value; } account[key] = value; this.accountSettingUpdated(account, validate); }, /** * Called when any account setting is updated. Optionally validates the account based on state. * * @param {object} account account that had the update occur * @param {boolean} validate when true, validateAccount() will be called */ accountSettingUpdated: function accountSettingUpdated(account, validate, skipForceSelect) { var callUpdate; if (!skipForceSelect && !account.selected) { account.selected = 1; callUpdate = true; } this.updateCustomizedFlag(account); if (validate) { this.validateAccount(account); } if (callUpdate) { this.updateSelectedAccounts(); } }, /** * Set a function to call when the selected accounts change * * @param {function} func function to call when the selected accounts change */ setUpdateSelectedAccountsFunction: function setUpdateSelectedAccountsFunction(func) { this._updateSelectedAccounts = func; }, /** * Called when selected accounts change, if set by setUpdateSelectedAccountsFunction() a callback function will be called too * */ updateSelectedAccounts: function updateSelectedAccounts() { if (this._updateSelectedAccounts) { this._updateSelectedAccounts(); } }, /** * Called by the view when an accounts selection changes * * @param {object} account the account that changed. Unused by the function. */ accountSelectionUpdated: function accountSelectionUpdated(account) { this.updateSelectedAccounts(); }, /** * Check if an account is eligible for the overwrite dropdown * * @param {object} account account to be checked * @returns {boolean} whether or not the account could ever need overwriting */ canNeedOverwrite: function canNeedOverwrite(account) { var localUsers = this.PAGE.local.users; var localDomains = this.PAGE.local.domains; return localUsers[account.user] || localUsers[account.localuser] || (localDomains[account.domain] === account.localuser); }, /** * Update the specific overwrite flags based on the overwrite_type of the account * accountSettingUpdate is then called, passing along the validate value * * @param {object} account account to be updated * @param {boolean} validate whether to validate during the accountSettingUpdated phase */ updateOverwriteFlags: function updateOverwriteFlags(account, validate, skipForceSelect) { account.overwrite_account = 0; account.overwrite_with_delete = 0; switch (account.overwrite_type.value) { case this.overwriteStates.OVERWRITE_WITH_DELETE: account.overwrite_with_delete = 1; // fall through here is intentional as we want it to set overwrite_account as well when we set overwrite_with_delete case this.overwriteStates.OVERWRITE: account.overwrite_account = 1; break; } this.accountSettingUpdated(account, validate, skipForceSelect); }, openOverwriteDescriptionModal: function openOverwriteDescriptionModal() { var self = this; self.overwriteModal = this.openModal({ templateUrl: this.overwriteDescriptionTemplate, controller: ["$scope", function($scope) { $scope.close = function() { self.closeOverwriteDescriptionModal(); }; }], }); }, closeOverwriteDescriptionModal: function closeOverwriteDescriptionModal() { if (this.overwriteModal) { this.overwriteModal.close(); this.overwriteModal = null; } }, }); // Retrieve the current application var app; try { app = angular.module("App"); // For runtime app.value("PAGE", PAGE); } catch (e) { app = angular.module("App", []); // Fall-back for unit testing } AccountTableController.$inject = CONTROLLER_INJECTABLES; var controller = app.controller("AccountTableController", AccountTableController); return controller; } );
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Generation time: 0.04 |
proxy
|
phpinfo
|
Settings