AlkantarClanX12

Your IP : 18.119.133.206


Current Path : /opt/cloudlinux/venv/lib/python3.11/site-packages/clcommon/cpapi/plugins/
Upload File :
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()