Mini Shell

Direktori : /lib/fixperms/
Upload File :
Current File : //lib/fixperms/fixperms_cli.py

"""fixperms sys.argv cli argument parsing"""
from dataclasses import dataclass
from logging import Logger
from argparse import ArgumentParser, ArgumentTypeError
import os
import pwd
import sys
from typing import Literal
import rads
import cwp


@dataclass
class Args:
    """Dataclass for more strict type hints for parse_args"""

    role: Literal['CWP', 'cPanel', 'WP3']
    users: set[str]
    skip: set[str]
    noop: bool
    procs: int
    skip_mail: bool
    preserve_exec: bool
    logger: Logger


class ArgValidator:
    """Validates custom args"""

    def __init__(self) -> None:
        self._all_cwp_users = set()
        if cwp.HAS_CWP:
            self.role = 'CWP'
            self._all_cwp_users = cwp.all_users()
            self.user = self._cwp_user
        elif rads.HAS_CPANEL:
            self.role = 'cPanel'
            self.user = self._cpanel_user
        elif os.path.exists('/etc/ansible/wordpress-ultrastack'):
            self.role = 'WP3'
            self.user = self._wp3_user
        else:
            sys.exit("fixperms requires a cPanel, CWP, or WP3 server")

    def _cwp_user(self, val: str) -> str:
        if val in self._all_cwp_users:
            return val
        raise ArgumentTypeError(f'{val} is not a valid CWP user')

    @staticmethod
    def _cpanel_user(val: str) -> str:
        if rads.is_cpuser(val):
            return val
        raise ArgumentTypeError(f'{val} is not a valid cPanel user')

    @staticmethod
    def _wp3_user(val: str) -> str:
        if val == 'wordpress':
            try:
                pwd.getpwnam(val)
                return val
            except KeyError:
                pass
        raise ArgumentTypeError(f'{val} is not a valid WP3 user')

    @staticmethod
    def positive(val: str) -> int:
        """Test an arg is an int >= 1"""
        val = int(val)
        if val >= 1:
            return val
        raise ArgumentTypeError(f'{val} must be >= 1')


def parse_args() -> Args:
    """Parse sys.argv"""
    # fmt: off
    custom_args = ArgValidator()
    parser = ArgumentParser(
        description="Safely corrects permission issues on a "
        f"{custom_args.role} user"
    )
    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        '-p', '--procs', type=custom_args.positive, default=4, metavar='NUM',
        help='max users to process at once, if multiple were requested '
        '(defaults to 4)'
    )
    group.add_argument(
        '-v', '--verbose', action='store_true',
        help='show verbose output of every permissions change',
    )
    group.add_argument(
        '-q', '--quiet', action='store_true', help='hide all output but errors'
    )
    parser.add_argument(
        '-n', '--noop', action='store_true',
        help='Test mode; Make no actual changes to the account',
    )
    parser.add_argument(
        '--skip', type=os.path.realpath, metavar='PATH', nargs='+', default=[],
        help='path(s) to skip changing permissions on. '
        'If you want to skip etc and mail, use --skip-mail instead',
    )
    parser.add_argument(
        '--no-preserve-exec', dest='preserve_exec', action='store_false',
        help="Don't preserve the execute bit on files",
    )
    if custom_args.role != 'WP3':
        parser.add_argument(
            '--skip-mail', action='store_true',
            help='Do not run mailperm to fix permissions on etc and mail dirs',
        )
    parser.add_argument(
        'users',
        nargs='+',
        metavar='USER',
        type=custom_args.user,
        help='cPanel user(s)',
    )
    # fmt: on
    args = parser.parse_args()
    if args.verbose:
        loglevel = 'DEBUG'
    elif args.quiet:
        loglevel = 'ERROR'
    else:
        loglevel = 'INFO'
    logger = rads.setup_verbosity(loglevel)
    return Args(
        role=custom_args.role,
        users=set(args.users),
        skip=set(args.skip),
        noop=args.noop,
        procs=args.procs,
        skip_mail=args.skip_mail if custom_args.role != 'WP3' else True,
        preserve_exec=args.preserve_exec,
        logger=logger,
    )

Zerion Mini Shell 1.0