kytos.utils.decorators.kytos_auth.authenticate()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 17
nop 1
dl 0
loc 24
rs 9.55
c 0
b 0
f 0
ccs 17
cts 17
cp 1
crap 3
1
"""Decorators for Kytos-utils."""
2 1
import logging
3 1
import os
4 1
from getpass import getpass
5
6 1
import requests
7
8 1
from kytos.utils.config import KytosConfig
9
10 1
LOG = logging.getLogger(__name__)
11
12
13
# This class is used as decorator, so this class name is lowercase and the
14
# invalid-name warning from pylint is disabled below.
15 1
class kytos_auth:  # pylint: disable=invalid-name
16
    """Class to be used as decorator to require authentication."""
17
18 1
    def __init__(self, func):
19
        """Init method.
20
21
        Save the function on the func attribute and bootstrap a new config.
22
        """
23 1
        self.func = func
24 1
        self.config = KytosConfig().config
25 1
        self.cls = None
26 1
        self.obj = None
27
28 1
    def __call__(self, *args, **kwargs):
29
        """Code run when func is called."""
30 1
        if not (self.config.has_option('napps', 'api') and
31
                self.config.has_option('napps', 'repo')):
32 1
            uri = input("Enter the kytos napps server address: ")
33 1
            self.config.set('napps', 'api', os.path.join(uri, 'api', ''))
34 1
            self.config.set('napps', 'repo', os.path.join(uri, 'repo', ''))
35
36 1
        if not self.config.has_option('auth', 'user'):
37 1
            user = input("Enter the username: ")
38 1
            self.config.set('auth', 'user', user)
39
        else:
40
            user = self.config.get('auth', 'user')
41
42 1
        if not self.config.has_option('auth', 'token'):
43 1
            token = self.authenticate()
44
        else:
45
            token = self.config.get('auth', 'token')
46
47
        # Ignore private attribute warning. We don't wanna make it public only
48
        # because of a decorator.
49 1
        config = self.obj._config  # pylint: disable=protected-access
50 1
        config.set('auth', 'user', user)
51 1
        config.set('auth', 'token', token)
52 1
        self.func.__call__(self.obj, *args, **kwargs)
53
54 1
    def __get__(self, instance, owner):
55
        """Deal with owner class."""
56 1
        self.cls = owner
57 1
        self.obj = instance
58
59 1
        return self.__call__
60
61
    # pylint: disable=inconsistent-return-statements
62 1
    def authenticate(self):
63
        """Check the user authentication."""
64 1
        endpoint = os.path.join(self.config.get('napps', 'api'), 'auth', '')
65 1
        username = self.config.get('auth', 'user')
66 1
        password = getpass('Enter the password for {}: '.format(username))
67 1
        response = requests.get(endpoint, auth=(username, password))
68
69
        # Check if it is unauthorized
70 1
        if response.status_code == 401:
71 1
            print(f'Error with status code: {response.status_code}.\n'
72
                  'Possible causes: incorrect credentials, the token was '
73
                  'not set or was expired.')
74
75 1
        if response.status_code != 201:
76 1
            LOG.error(response.content)
77 1
            LOG.error('ERROR: %s: %s', response.status_code, response.reason)
78 1
            print('Press Ctrl+C or CTRL+Z to stop the process.')
79 1
            user = input('Enter the username: ')
80 1
            self.config.set('auth', 'user', user)
81 1
            self.authenticate()
82
        else:
83 1
            data = response.json()
84 1
            KytosConfig().save_token(username, data.get('hash'))
85
            return data.get('hash')
86