Source code for wmflib.idm

"""Base module IDM related classes and functions."""

from abc import ABC, abstractmethod
from argparse import ArgumentParser, Namespace
from logging import getLogger
from typing import List, Optional

from wmflib.exceptions import WmflibError


[docs] class IdmValueError(WmflibError): """Raised by the IDM module value errors."""
# We make the description optional to deal with the following issue # https://github.com/python/mypy/issues/9170
[docs] def logoutd_args(description: Optional[str] = None, args: Optional[List] = None) -> Namespace: """Logout scripts common CLI for parsing the command line arguments. When not using the higher level API :py:class:`wmflib.idm.LogoutdBase`, a user could just implement their own script still using the same command line arguments processing, of the form:: from wmflib.idm import logoutd_args args = logoutd_args('Some description') # write your own script Arguments: description (str): the description to use args (list): A list of arguments to use (used for testing) Returns: `argparse.Namespace`: The parsed argparser Namespace """ if description is None: raise IdmValueError('Must provide a string description') parser = ArgumentParser(description=description) parser.add_argument('-v', '--verbose', action='count', default=0) sub = parser.add_subparsers(dest='command', required=True) query = sub.add_parser('query', help='display the status of logged-in users') query.add_argument( '-u', '--uid', required=True, help='The uid of the user to use', ) query.add_argument('-c', '--cn', required=True, help='The cn of the user to use') sub.add_parser( 'logout', parents=[query], add_help=False, help='display the status of logged in users', ) sub.add_parser('list', help='list all active sessions') return parser.parse_args(args)
[docs] class LogoutdBase(ABC): # noqa: D300,D301 See https://github.com/PyCQA/pydocstyle/issues/542 """Base class for a standardized API for logout scripts. A simple logout.d python script would then be of the form:: from wmflib.idm import LogoutdBase class MyLogoutd(LogoutdBase): \"\"\"Some description.\"\"\" def logout_user(self, user): # logout the given user def query_user(self, user): # check the login status of a given user def list(self): # list all active login sessions logoutd = MyLogoutd() raise SystemExit(logoutd.run()) # This includes the parsing of command line arguments. """ user_identifier: str = 'cn' def __init__(self, args: Optional[List] = None) -> None: """Init function. Arguments: args (list): A list of arguments to use (used for testing) """ self._args = logoutd_args(self.__doc__, args) self._logger = getLogger('.'.join((self.__module__, self.__class__.__name__))) @property def user(self) -> str: """Return either common_name or uid with a preference for common_name. Returns: (str): representing the user """ return getattr(self._args, self.user_identifier)
[docs] @abstractmethod def logout_user(self, user: str) -> int: """Log out the specified user. Arguments: user (User): object representing the user Returns: (int): 0 if the users session was successfully cleared otherwise 1 """
[docs] @abstractmethod def query_user(self, user: str) -> int: """Return status of logged in user. Arguments: user (User): object representing the user Returns: (int): 1 if the user is logged in otherwise 0 """
[docs] @abstractmethod def list(self) -> int: """Return data of all logged in users. Returns: (int): 0 on success non-zero on fail """
[docs] def run(self) -> int: """Execute the correct action. Returns: (int): exit code depends on command """ self._logger.debug('Running action: %s', self._args.command) if self._args.command == 'query': return self.query_user(self.user) if self._args.command == 'logout': return self.logout_user(self.user) return self.list()