Source code for gpxity.auth
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Wolfgang Rohdewald <wolfgang@rohdewald.de>
# See LICENSE for details.
"""This module defines :class:`~gpxity.auth.Authenticate`."""
import os
import logging
from configparser import ConfigParser
__all__ = ['Authenticate']
[docs]class Authenticate:
"""
Get password and / or Url from auth.cfg.
If nothing is useable, sets them to None.
auth.cfg is expected in :literal:`~/.config/Gpxity/auth.cfg`
.. DANGER::
auth.cfg is not encrypted. Better not use this unless you know what you are doing!
Args:
backend (~gpxity.backend.Backend): The backend
username (str): For the wanted account in the backend. You can also pass
dict(). In that case, the config file is not read at all, only this dict() will
be used.
Attributes:
path (str): The name for the auth file. Class variable, to be changed before
Authenticate() is instantiated.
auth (tuple(str,str)): (username, password). Both are either str or None.
url: If given, overrides the url given to the backend
For every specific account in a backend, auth.cfg has a section. Its name is
case sensitive: The ClassName must match exactly.
* [ClassName.username]
A section can define
* Username overrides username (the wanted account in the backend, see above)
* Password
* Url
* Mysql, used by WPTrackserver
An example for user gpxitytest on gpsies.com:
.. code-block:: guess
[GPSIES:gpxitytest]
Password = the_unencrypted_password
A mail account:
.. code-block:: guess
[Mailer:gpxitytest]
Url = tester@test.test
"""
# pylint: disable=too-few-public-methods
path = '~/.config/Gpxity/auth.cfg'
def __init__(self, backend, url, username: str = None):
"""See class docstring."""
self.__config = ConfigParser()
if isinstance(username, dict):
self.__section_name = '{}:from_dict'.format(backend.__class__.__name__)
self.__config[self.__section_name] = {}
self.section = self.__config[self.__section_name]
for key, value in username.items():
self.section[key.lower()] = str(value)
else:
self.__section_name = '{}:{}'.format(backend.__class__.__name__, username)
self.__path = os.path.expanduser(self.path)
logging.info('Using auth data from %s', self.__path)
if os.path.exists(self.__path):
with open(self.__path) as auth_file:
self.__config.read_string(auth_file.read())
if self.__section_name not in self.__config:
if backend.needs_config:
raise KeyError('Section [{}] not found in {}'.format(self.__section_name, self.__path))
self.__config[self.__section_name] = {}
self.section = self.__config[self.__section_name]
if 'Username' not in self.section:
self.section['username'] = username or ''
else:
logging.info('%s not found', self.__path)
self.section = dict()
if self.section.get('username', None) == 'wrong_user':
raise KeyError
if 'url' not in self.section:
self.section['url'] = url or ''
self._check_url()
def _check_url(self):
"""Check syntax for url."""
_ = self.url
if _ and _.endswith('/') and _ != '/':
raise Exception('url {} must not end with /'.format(_))
def __getattr__(self, key):
"""Only called if key is not an existing attribute.
Returns: The value
"""
return self.section[key.lower()] if key.lower() in self.section else None