AlkantarClanX12
Current Path : /opt/cloudlinux/venv/lib/python3.11/site-packages/clcommon/cpapi/plugins/ |
Current File : //opt/cloudlinux/venv/lib/python3.11/site-packages/clcommon/cpapi/plugins/backward_plugin.py |
# General class, implementing common methods, using all cpapi plugins by default import os from clcommon.features import Feature from clcommon.utils import exec_utility from collections import defaultdict from clcommon import ClPwd from clcommon.clcustomscript import lvectl_custompanel_script from clcommon.cpapi.GeneralPanel import GeneralPanelPluginV1 from clcommon.cpapi.cpapiexceptions import CPAPIExternalProgramFailed # This flag means that we use enchanced custom long script. # With keys, which aren't described in official documentation. USE_ENCHANCED_CUSTOM_LONG_SCRIPT = os.environ.get('USE_ENCHANCED_CUSTOM_LONG_SCRIPT') == '1' class PanelPlugin(GeneralPanelPluginV1): def __init__(self): super().__init__() self._custom_script_name = lvectl_custompanel_script() self._cp_name = "Unknown" def getCPName(self): """ Return panel name :return: """ return self._cp_name def get_cp_description(self): """ Retrieve panel name and it's version :return: dict: { 'name': 'panel_name', 'version': 'panel_version', 'additional_info': 'add_info'} or None if can't get info """ if self._custom_script_name is not None: return {'name': self._cp_name, 'version': '0', 'additional_info': None} # panel detect fail if custom script not found return None # proxy to avoid arguments-differ def cpinfo(self, cpuser=None, keyls=('cplogin', 'package', 'mail', 'reseller', 'dns', 'locale'), search_sys_users=True): return self._cpinfo(cpuser, keyls=keyls, search_sys_users=search_sys_users) def _cpinfo(self, cpuser=None, keyls=('cplogin', 'package', 'mail', 'reseller', 'dns', 'locale', 'uid'), search_sys_users=True, raise_exc=False): """ Retrives specified info about panel users :param str|unicode|list|tuple|None cpuser: user login :param keyls: List or cortege of data which is necessary to obtain the user, values can be: cplogin - name/login user control panel mail - Email users reseller - name reseller/owner users locale - localization of the user account package - User name of the package dns - domain of the user userid - uid :param search_sys_users: :param raise_exc: hack for clquota that raises exception in case of exit code != 0 :return: returns a tuple of tuples of data in the same sequence as specified keys in keylst Examples: cpinfo('cltest1') (('cltest1', 'default', '', 'root', 'cltest1.com', 'en'),) cpinfo() (('res1usr1', 'res1_pack1', '', 'res1', 'res1usr1.com', 'en'), ('res1', 'default', '', 'root', 'res1.com', 'en'), ('res2', 'default', '', 'res2', 'res2.com', 'en'), ('cltest1', 'default', '', 'root', 'cltest1.com', 'en'), ('system', 'undefined', None, 'root', '', 'en')) :rtype: tuple """ try: if USE_ENCHANCED_CUSTOM_LONG_SCRIPT: all_users_data = super().list_users(raise_exc=raise_exc) else: # all_users_data Example: # {1000: 'Package1', 1001: 'BusinessPackage'} all_users_data = self.list_all(raise_exc=raise_exc) except (OSError, IOError, IndexError, AttributeError, CPAPIExternalProgramFailed): all_users_data = {} cl_pwd = ClPwd() # Build full users data dict users_dict = defaultdict(dict) for uid, value in all_users_data.items(): try: user_name = cl_pwd.get_names(uid)[0] except ClPwd.NoSuchUserException: # user with uid absent in system, use some fictive name # We use : in username, because system does not allow this symbol in username user_name = f'::{uid}::' if isinstance(value, dict): package = value['package'] reseller = value['reseller'] else: package = value reseller = '' try: users_dict[user_name] = {'cplogin': user_name, 'package': package, 'mail': None, 'reseller': reseller, 'dns': None, 'locale': None, 'uid': uid, } except Exception: # we are ignoring all errors pass out_list = [] user_name_list = [] if isinstance(cpuser, str): user_name_list = [cpuser] elif isinstance(cpuser, (list, tuple)): user_name_list = list(cpuser) elif cpuser is None: user_name_list = list(users_dict.keys()) for user_name in user_name_list: # for case if users_dict has fictive user names if user_name not in users_dict: continue user_data = users_dict[user_name] user_data_list = [] for data_key in keyls: user_data_list.append(user_data[data_key]) out_list.append(tuple(user_data_list)) return tuple(out_list) # inherited implementation does not work because # old plugin does not contain resellers def reseller_package_by_uid(self, user_id): """ Retrieves reseller name and package name by uid :param user_id: User id :return: Cortege: (Reseller_name, Package_name) """ package_name = '' try: _, stdout = exec_utility(self._custom_script_name, ['--userid='+str(user_id)]) package_name = stdout.split('\n').pop(0) except (OSError, IOError, IndexError, AttributeError): pass return '', package_name # This is reseller method. # Key `--list-resellers-packages` of custom long script isn't # described in official documentation, so we use this method # only in tests and implement the key only in tests # for real client's custom long script we return empty result def resellers_packages(self, raise_exc=False): """ Return dictionary, contains available resellers packages, grouped by resellers :return: Dictionary. Example: {'res1': ['BusinessPackage', 'UltraPackage', 'Package'], 'res2': ['SimplePackage', 'Package'] } """ if not USE_ENCHANCED_CUSTOM_LONG_SCRIPT: return {} try: return super().resellers_packages(raise_exc=raise_exc) except (OSError, IOError, IndexError, AttributeError, CPAPIExternalProgramFailed): return {} # This is reseller method. # Key `--list-users` of custom long script isn't # described in official documentation, so we use this method # only in tests and implement the key only in tests # for real client's custom long script we return empty result def resellers(self): """ Generates a list of resellers in the control panel :return: list/tuple of cpusers registered in the control panel :rtype: tuple :raise: NotSupported """ if not USE_ENCHANCED_CUSTOM_LONG_SCRIPT: return tuple() resellers_list = [value['reseller'] for value in self.list_users().values()] return tuple(set(resellers_list)) def get_admin_emails_list(self): """ Gets admin emails list :rtype: List :return: List: ['admin1@mail.com', 'admin2@mail.com' ] """ return [] def docroot(self, domain): """ Return document root for domain :return: Cortege: (document_root, owner) """ return () def userdomains(self, cpuser): """ Return domain and document root pairs for control panel user first domain is main domain :param str|unicode cpuser: user login :rtype: List :return: list of tuples (domain_name, documen_root) """ return [] def homedirs(self): """ Detects and returns list of folders contained the home dirs of users of the cPanel :rtype: List :return: list of folders, which are parent of home dirs of users of the panel """ return [] def reseller_users(self, resellername=None): """ Return reseller users :param resellername: reseller name; autodetect name if None :rtype: List :return list[str]: user names list """ return [] def reseller_domains(self, resellername=None): """ Return reseller users and their main domains :param resellername: reseller name; autodetect name if None :rtype: List :return dict[str, str]: pairs user <==> domain """ return {} def get_user_login_url(self, domain): """ Get login url for current panel; :type domain: str :rtype: str :return: Panel login URL """ return "" def get_reseller_id_pairs(self): """ Get dict reseller => id Optional method for panels without hard link reseller <=> system user :rtype: dict[str,int] - {'res1': id1} :return: """ return {} # This is reseller method. # Key `--list-reseller-users` of custom long script isn't # described in official documentation, so we use this method # only in tests and implement the key only in tests # for real client's custom long script we return empty result def get_reseller_users(self, reseller): if not USE_ENCHANCED_CUSTOM_LONG_SCRIPT: return {} try: return super().get_reseller_users(reseller) except (OSError, IOError, IndexError, AttributeError, CPAPIExternalProgramFailed): return {} def list_users(self, raise_exc=False): """ Return list of <userid package reseller> triples :rtype: dict :return: Dictionary. Example: {1000: {'reseller': '', 'package': 'Package1'}, 1001: {'reseller': '', 'package': 'BusinessPackage'}, } """ packages_users = defaultdict(dict) users_info = self._cpinfo(keyls=('uid', 'reseller', 'package'), raise_exc=True) for uid, reseller, package in users_info: packages_users[uid] = {'reseller': reseller, 'package': package} return packages_users def get_unsupported_cl_features(self) -> tuple[Feature, ...]: """ Return list of cloudlinux features that can be used on current control panel. """ # empty list mostly for historical reasons return tuple()