Test Failed
Push — master ( 6c71b5...01cf9e )
by Andreas
01:23
created

  F

Complexity

Total Complexity 113

Size/Duplication

Total Lines 583
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 583
rs 1.5789
wmc 113

70 Methods

Rating   Name   Duplication   Size   Complexity  
A onfigError.__init__() 0 3 1
F pmApi.__init__() 0 64 17
A onfigError.__str__() 0 2 1
A pmApi.set_favorite_password() 0 5 1
A pmApi.list_projects() 0 4 1
A pmApi.delete_project() 0 5 1
A pmApi.get_latest_version() 0 5 1
A pmApi.show_me() 0 5 1
A pmApi.deactivate_user() 0 5 1
A pmApi.list_users() 0 5 1
A pmApi.list_passwords_favorite() 0 4 1
A pmApi.list_passwords_search() 0 5 1
A pmApi.post() 0 3 1
A pmApi.create_group() 0 7 1
A pmApi.list_passwords_of_project() 0 5 1
A pmApi.collection() 0 6 2
A pmApi.delete() 0 3 1
A pmApi.show_password() 0 5 1
A pmApi.show_group() 0 5 1
A pmApi.lock_password() 0 5 1
A pmApi.update_group() 0 5 1
A pmApi.who_am_i() 0 3 1
A pmApi.update_security_of_project() 0 5 1
A pmApi.change_user_password() 0 5 1
A pmApi.unlock_password() 0 6 1
A pmApi.show_mypassword() 0 5 1
A pmApi.unarchive_project() 0 5 1
A pmApi.list_passwords() 0 4 1
A pmApi.create_project() 0 7 1
A pmApi.update_security_of_password() 0 5 1
A pmApi.archive_project() 0 5 1
A pmApi.update_custom_fields_of_password() 0 5 1
A pmApi.list_user_access_on_project() 0 5 1
A pmApi.show_project() 0 5 1
A pmApi.unset_favorite_project() 0 5 1
A pmApi.create_password() 0 7 1
A pmApi.delete_group() 0 5 1
A pmApi.update_user() 0 5 1
A pmApi.list_projects_favorite() 0 4 1
A pmApi.delete_password() 0 5 1
A pmApi.list_passwords_archived() 0 4 1
A pmApi.update_password() 0 5 1
A pmApi.generate_password() 0 5 1
A pmApi.add_user_to_group() 0 5 1
A pmApi.list_mypasswords() 0 5 1
A pmApi.put() 0 3 1
A pmApi.list_user_access_on_password() 0 5 1
A pmApi.create_user() 0 7 1
F pmApi.request() 0 93 23
A pmApi.unset_favorite_password() 0 5 1
A pmApi.up_to_date() 0 13 2
A pmApi.change_parent_of_project() 0 6 1
A pmApi.set_favorite_project() 0 5 1
A pmApi.list_groups() 0 5 1
A pmApi.show_user() 0 5 1
A pmApi.convert_user_to_ldap() 0 6 1
A pmApi.get() 0 3 1
A pmApi.update_mypassword() 0 5 1
A pmApi.convert_ldap_user_to_normal() 0 4 1
A pmApi.delete_user_from_group() 0 5 1
A pmApi.list_projects_archived() 0 4 1
A pmApi.delete_mypassword() 0 5 1
A pmApi.create_mypassword() 0 7 1
A pmApi.get_version() 0 5 1
A pmApi.activate_user() 0 5 1
A pmApi.update_project() 0 5 1
B pmApi.get_collection() 0 12 6
A pmApi.list_mypasswords_search() 0 6 1
A pmApi.delete_user() 0 5 1
A pmApi.list_projects_search() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#! /usr/bin/env python
2
"""Team Password Manager API
3
4
To simplify usage of Team Password Manager API.
5
6
You can authenticate with username and password
7
    >>> import tpm
8
    >>> URL = "https://mypasswordmanager.example.com"
9
    >>> USER = 'MyUser'
10
    >>> PASS = 'Secret'
11
    >>> tpmconn = tpm.TpmApiv4(URL, username=USER, password=PASS)
12
13
Or with Private/Public Key
14
    >>> pubkey = '3726d93f2a0e5f0fe2cc3a6e9e3ade964b43b07f897d579466c28b7f8ff51cd0'
15
    >>> privkey = '87324bedead51af96a45271d217b8ad5ef3f220da6c078a9bce4e4318729189c'
16
    >>> tpmconn = tpm.TpmApiv4(URL, private_key=privkey, public_key=pubkey)
17
18
With the connection object you can use all TPM functions, like list all passwords:
19
    >>> tpmconn.list_passwords()
20
21
All API functions from Team Password Manager are included.
22
see http://teampasswordmanager.com/docs/api/
23
24
:copyright: (c) 2017 by Andreas Hubert.
25
:license: The MIT License (MIT), see LICENSE for more details.
26
"""
27
28
__version__ = '3.4'
29
30
import hmac
31
import hashlib
32
import time
33
import requests
34
import re
35
import json
36
import logging
37
from future.standard_library import install_aliases
38
install_aliases()
39
40
from urllib.parse import quote_plus
41
42
# set logger
43
log = logging.getLogger(__name__)
44
# disable unsecure SSL warning
45
requests.packages.urllib3.disable_warnings()
46
47
48
class TPMException(Exception):
49
    pass
50
51
52
class TpmApi(object):
53
    """Settings needed for the connection to Team Password Manager."""
54
    class ConfigError(Exception):
55
        """To throw Exception based on wrong Settings."""
56
        def __init__(self, value):
57
            self.value = value
58
            log.critical(value)
59
60
        def __str__(self):
61
            return repr(self.value)
62
63
    def __init__(self, api, base_url, kwargs):
64
        """init thing."""
65
        # Check if API version is not bullshit
66
        REGEXurl = "^" \
67
                   "(?:(?:https?)://)" \
68
                   "(?:\\S+(?::\\S*)?@)?" \
69
                   "(?:" \
70
                   "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" \
71
                   "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" \
72
                   "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" \
73
                   "|" \
74
                   "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" \
75
                   "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" \
76
                   "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))?" \
77
                   ".?" \
78
                   ")" \
79
                   "(?::\\d{2,5})?" \
80
                   "(?:[/?#]\\S*)?" \
81
                   "$"
82
        self.apiurl = 'api/' + api + '/'
83
        log.debug('Set as apiurl: %s' % self.apiurl)
84
        self.api = self.apiurl
85
        # Check if URL is not bullshit
86
        if re.match(REGEXurl, base_url):
87
            self.base_url = base_url + '/index.php/'
88
            log.debug('Set Base URL to %s' % self.base_url)
89
            self.url = self.base_url + self.apiurl
90
            log.debug('Set URL to %s' % self.url)
91
        else:
92
            raise self.ConfigError('Invalid URL: %s' % base_url)
93
        # set headers
94
        self.headers = {'Content-Type': 'application/json; charset=utf-8',
95
                        'User-Agent': 'tpm.py/' + __version__
96
                        }
97
        log.debug('Set header to %s' % self.headers)
98
        # check kwargs for either keys or user credentials
99
        self.private_key = False
100
        self.public_key = False
101
        self.username = False
102
        self.password = False
103
        self.unlock_reason = False
104
        self.max_retries = 3
105
        for key in kwargs:
106
            if key == 'private_key':
107
                self.private_key = kwargs[key]
108
            elif key == 'public_key':
109
                self.public_key = kwargs[key]
110
            elif key == 'username':
111
                self.username = kwargs[key]
112
            elif key == 'password':
113
                self.password = kwargs[key]
114
            elif key == 'max_retries':
115
                self.max_retries = kwargs[key]
116
                if self.max_retries < 1:
117
                    raise self.ConfigError('Parameter max_retires should be at least 1')
118
        log.debug("Max retries on ValueError: {}".format(self.max_retries))
119
        if self.private_key is not False and self.public_key is not False and\
120
                self.username is False and self.password is False:
121
            log.debug('Using Private/Public Key authentication.')
122
        elif self.username is not False and self.password is not False and\
123
                self.private_key is False and self.public_key is False:
124
            log.debug('Using Basic authentication.')
125
        else:
126
            raise self.ConfigError('No authentication specified'
127
                                   ' (user/password or private/public key)')
128
129
    def request(self, path, action, data=''):
130
        """To make a request to the API."""
131
        # Check if the path includes URL or not.
132
        head = self.base_url
133
        if path.startswith(head):
134
            path = path[len(head):]
135
        if not path.startswith(self.api):
136
            path = self.api + path
137
        log.debug('Using path %s' % path)
138
139
        # If we have data, convert to JSON
140
        if data:
141
            data = json.dumps(data)
142
            log.debug('Data to sent: %s' % data)
143
        # In case of key authentication
144
        if self.private_key and self.public_key:
145
            timestamp = str(int(time.time()))
146
            log.debug('Using timestamp: {}'.format(timestamp))
147
            unhashed = path + timestamp + str(data)
148
            log.debug('Using message: {}'.format(unhashed))
149
            self.hash = hmac.new(str.encode(self.private_key),
150
                                 msg=unhashed.encode('utf-8'),
151
                                 digestmod=hashlib.sha256).hexdigest()
152
            log.debug('Authenticating with hash: %s' % self.hash)
153
            self.headers['X-Public-Key'] = self.public_key
154
            self.headers['X-Request-Hash'] = self.hash
155
            self.headers['X-Request-Timestamp'] = timestamp
156
            auth = False
157
        # In case of user credentials authentication
158
        elif self.username and self.password:
159
            auth = requests.auth.HTTPBasicAuth(self.username, self.password)
160
        # Set unlock reason
161
        if self.unlock_reason:
162
            self.headers['X-Unlock-Reason'] = self.unlock_reason
163
            log.info('Unlock Reason: %s' % self.unlock_reason)
164
        url = head + path
165
        # Try API request and handle Exceptions
166
        retries = 0
167
        while retries < self.max_retries:
168
            retries += 1
169
            log.debug("Try {} of {} to retrieve result.".format(retries, self.max_retries))
170
            try:
171
                if action == 'get':
172
                    log.debug('GET request %s' % url)
173
                    self.req = requests.get(url, headers=self.headers, auth=auth,
174
                                            verify=False)
175
                elif action == 'post':
176
                    log.debug('POST request %s' % url)
177
                    self.req = requests.post(url, headers=self.headers, auth=auth,
178
                                             verify=False, data=data)
179
                elif action == 'put':
180
                    log.debug('PUT request %s' % url)
181
                    self.req = requests.put(url, headers=self.headers,
182
                                            auth=auth, verify=False,
183
                                            data=data)
184
                elif action == 'delete':
185
                    log.debug('DELETE request %s' % url)
186
                    self.req = requests.delete(url, headers=self.headers,
187
                                               verify=False, auth=auth)
188
189
                if self.req.content == b'':
190
                    result = None
191
                    log.debug('No result returned.')
192
                else:
193
                    result = self.req.json()
194
                    if 'error' in result and result['error']:
195
                        raise TPMException(result['message'])
196
197
            except requests.exceptions.RequestException as e:
198
                log.critical("Connection error for " + str(e))
199
                raise TPMException("Connection error for " + str(e))
200
201
            except ValueError as e:
202
                if self.req.status_code == 403:
203
                    log.warning(url + " forbidden")
204
                    raise TPMException(url + " forbidden")
205
                elif self.req.status_code == 404:
206
                    log.warning(url + " forbidden")
207
                    raise TPMException(url + " not found")
208
                elif self.req.text.endswith('pre>'):
209
                    d = req.text.replace('<pre>','')
210
                    result = json.loads(d)
211
                    break
212
                else:
213
                    message = ('%s: %s %s' % (e, self.req.url, self.req.text))
214
                    log.debug(message)
215
                    if retries < self.max_retries:
216
                        continue
217
                    else:
218
                        raise ValueError(message)
219
            break
220
221
        return result
222
223
    def post(self, path, data=''):
224
        """For post based requests."""
225
        return self.request(path, 'post', data)
226
227
    def get(self, path):
228
        """For get based requests."""
229
        return self.request(path, 'get')
230
231
    def put(self, path, data=''):
232
        """For put based requests."""
233
        self.request(path, 'put', data)
234
235
    def delete(self, path):
236
        """For delete based requests."""
237
        self.request(path, 'delete')
238
239
    def get_collection(self, path):
240
        """To get pagewise data."""
241
        while True:
242
            items = self.get(path)
243
            req = self.req
244
            for item in items:
245
                yield item
246
            if req.links and req.links['next'] and\
247
                    req.links['next']['rel'] == 'next':
248
                path = req.links['next']['url']
249
            else:
250
                break
251
252
    def collection(self, path):
253
        """To return all items generated by get collection."""
254
        data = []
255
        for item in self.get_collection(path):
256
            data.append(item)
257
        return data
258
259
    # From now on, Functions that work that way in all API Versions.
260
261
    # http://teampasswordmanager.com/docs/api-projects/#list_projects
262
    def list_projects(self):
263
        """List projects."""
264
        log.debug('List all projects.')
265
        return self.collection('projects.json')
266
267
    def list_projects_archived(self):
268
        """List archived projects."""
269
        log.debug('List all archived projects.')
270
        return self.collection('projects/archived.json')
271
272
    def list_projects_favorite(self):
273
        """List favorite projects."""
274
        log.debug('List all favorite projects.')
275
        return self.collection('projects/favorite.json')
276
277
    def list_projects_search(self, searchstring):
278
        """List projects with searchstring."""
279
        log.debug('List all projects with: %s' % searchstring)
280
        return self.collection('projects/search/%s.json' %
281
                               quote_plus(searchstring))
282
283
    def show_project(self, ID):
284
        """Show a project."""
285
        # http://teampasswordmanager.com/docs/api-projects/#show_project
286
        log.debug('Show project info: %s' % ID)
287
        return self.get('projects/%s.json' % ID)
288
289
    def list_passwords_of_project(self, ID):
290
        """List passwords of project."""
291
        # http://teampasswordmanager.com/docs/api-projects/#list_pwds_prj
292
        log.debug('List passwords of project: %s' % ID)
293
        return self.collection('projects/%s/passwords.json' % ID)
294
295
    def list_user_access_on_project(self, ID):
296
        """List users who can access a project."""
297
        # http://teampasswordmanager.com/docs/api-projects/#list_users_prj
298
        log.debug('List User access on project: %s' % ID)
299
        return self.collection('projects/%s/security.json' % ID)
300
301
    def create_project(self, data):
302
        """Create a project."""
303
        # http://teampasswordmanager.com/docs/api-projects/#create_project
304
        log.info('Create project: %s' % data)
305
        NewID = self.post('projects.json', data).get('id')
306
        log.info('Project has been created with ID %s' % NewID)
307
        return NewID
308
309
    def update_project(self, ID, data):
310
        """Update a project."""
311
        # http://teampasswordmanager.com/docs/api-projects/#update_project
312
        log.info('Update project %s with %s' % (ID, data))
313
        self.put('projects/%s.json' % ID, data)
314
315
    def change_parent_of_project(self, ID, NewParrentID):
316
        """Change parent of project."""
317
        # http://teampasswordmanager.com/docs/api-projects/#change_parent
318
        log.info('Change parrent for project %s to %s' % (ID, NewParrentID))
319
        data = {'parent_id': NewParrentID}
320
        self.put('projects/%s/change_parent.json' % ID, data)
321
322
    def update_security_of_project(self, ID, data):
323
        """Update security of project."""
324
        # http://teampasswordmanager.com/docs/api-projects/#update_project_security
325
        log.info('Update project %s security %s' % (ID, data))
326
        self.put('projects/%s/security.json' % ID, data)
327
328
    def archive_project(self, ID):
329
        """Archive a project."""
330
        # http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project
331
        log.info('Archive project %s' % ID)
332
        self.put('projects/%s/archive.json' % ID)
333
334
    def unarchive_project(self, ID):
335
        """Un-Archive a project."""
336
        # http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project
337
        log.info('Unarchive project %s' % ID)
338
        self.put('projects/%s/unarchive.json' % ID)
339
340
    def delete_project(self, ID):
341
        """Delete a project."""
342
        # http://teampasswordmanager.com/docs/api-projects/#delete_project
343
        log.info('Delete project %s' % ID)
344
        self.delete('projects/%s.json' % ID)
345
346
    # http://teampasswordmanager.com/docs/api-passwords/#list_passwords
347
    def list_passwords(self):
348
        """List passwords."""
349
        log.debug('List all passwords.')
350
        return self.collection('passwords.json')
351
352
    def list_passwords_archived(self):
353
        """List archived passwords."""
354
        log.debug('List archived passwords.')
355
        return self.collection('passwords/archived.json')
356
357
    def list_passwords_favorite(self):
358
        """List favorite passwords."""
359
        log.debug('List favorite spasswords.')
360
        return self.collection('passwords/favorite.json')
361
362
    def list_passwords_search(self, searchstring):
363
        """List passwords with searchstring."""
364
        log.debug('List all passwords with: %s' % searchstring)
365
        return self.collection('passwords/search/%s.json' %
366
                               quote_plus(searchstring))
367
368
    def show_password(self, ID):
369
        """Show password."""
370
        # http://teampasswordmanager.com/docs/api-passwords/#show_password
371
        log.info('Show password info: %s' % ID)
372
        return self.get('passwords/%s.json' % ID)
373
374
    def list_user_access_on_password(self, ID):
375
        """List users who can access a password."""
376
        # http://teampasswordmanager.com/docs/api-passwords/#list_users_pwd
377
        log.debug('List user access on password %s' % ID)
378
        return self.collection('passwords/%s/security.json' % ID)
379
380
    def create_password(self, data):
381
        """Create a password."""
382
        # http://teampasswordmanager.com/docs/api-passwords/#create_password
383
        log.info('Create new password %s' % data)
384
        NewID = self.post('passwords.json', data).get('id')
385
        log.info('Password has been created with ID %s' % NewID)
386
        return NewID
387
388
    def update_password(self, ID, data):
389
        """Update a password."""
390
        # http://teampasswordmanager.com/docs/api-passwords/#update_password
391
        log.info('Update Password %s with %s' % (ID, data))
392
        self.put('passwords/%s.json' % ID, data)
393
394
    def update_security_of_password(self, ID, data):
395
        """Update security of a password."""
396
        # http://teampasswordmanager.com/docs/api-passwords/#update_security_password
397
        log.info('Update security of password %s with %s' % (ID, data))
398
        self.put('passwords/%s/security.json' % ID, data)
399
400
    def update_custom_fields_of_password(self, ID, data):
401
        """Update custom fields definitions of a password."""
402
        # http://teampasswordmanager.com/docs/api-passwords/#update_cf_password
403
        log.info('Update custom fields of password %s with %s' % (ID, data))
404
        self.put('passwords/%s/custom_fields.json' % ID, data)
405
406
    def delete_password(self, ID):
407
        """Delete a password."""
408
        # http://teampasswordmanager.com/docs/api-passwords/#delete_password
409
        log.info('Delete password %s' % ID)
410
        self.delete('passwords/%s.json' % ID)
411
412
    def lock_password(self, ID):
413
        """Lock a password."""
414
        # http://teampasswordmanager.com/docs/api-passwords/#lock_password
415
        log.info('Lock password %s' % ID)
416
        self.put('passwords/%s/lock.json' % ID)
417
418
    def unlock_password(self, ID, reason):
419
        """Unlock a password."""
420
        # http://teampasswordmanager.com/docs/api-passwords/#unlock_password
421
        log.info('Unlock password %s, Reason: %s' % (ID, reason))
422
        self.unlock_reason = reason
423
        self.put('passwords/%s/unlock.json' % ID)
424
425
    def list_mypasswords(self):
426
        """List my passwords."""
427
        # http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords
428
        log.debug('List MyPasswords')
429
        return self.collection('my_passwords.json')
430
431
    def list_mypasswords_search(self, searchstring):
432
        """List my passwords with searchstring."""
433
        # http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords
434
        log.debug('List MyPasswords with %s' % searchstring)
435
        return self.collection('my_passwords/search/%s.json' %
436
                               quote_plus(searchstring))
437
438
    def show_mypassword(self, ID):
439
        """Show my password."""
440
        # http://teampasswordmanager.com/docs/api-my-passwords/#show_password
441
        log.debug('Show MyPassword %s' % ID)
442
        return self.get('my_passwords/%s.json' % ID)
443
444
    def create_mypassword(self, data):
445
        """Create my password."""
446
        # http://teampasswordmanager.com/docs/api-my-passwords/#create_password
447
        log.info('Create MyPassword with %s' % data)
448
        NewID = self.post('my_passwords.json', data).get('id')
449
        log.info('MyPassword has been created with %s' % NewID)
450
        return NewID
451
452
    def update_mypassword(self, ID, data):
453
        """Update my password."""
454
        # http://teampasswordmanager.com/docs/api-my-passwords/#update_password
455
        log.info('Update MyPassword %s with %s' % (ID, data))
456
        self.put('my_passwords/%s.json' % ID, data)
457
458
    def delete_mypassword(self, ID):
459
        """Delete my password."""
460
        # http://teampasswordmanager.com/docs/api-my-passwords/#delete_password
461
        log.info('Delete password %s' % ID)
462
        self.delete('my_passwords/%s.json' % ID)
463
464
    def set_favorite_password(self, ID):
465
        """Set a password as favorite."""
466
        # http://teampasswordmanager.com/docs/api-favorites/#set_fav
467
        log.info('Set password %s as favorite' % ID)
468
        self.post('favorite_passwords/%s.json' % ID)
469
470
    def unset_favorite_password(self, ID):
471
        """Unet a password as favorite."""
472
        # http://teampasswordmanager.com/docs/api-favorites/#del_fav
473
        log.info('Unset password %s as favorite' % ID)
474
        self.delete('favorite_passwords/%s.json' % ID)
475
476
    def set_favorite_project(self, ID):
477
        """Set a project as favorite."""
478
        # http://teampasswordmanager.com/docs/api-favorites/#set_fav
479
        log.info('Set project %s as favorite' % ID)
480
        self.post('favorite_project/%s.json' % ID)
481
482
    def unset_favorite_project(self, ID):
483
        """Unet a project as favorite."""
484
        # http://teampasswordmanager.com/docs/api-favorites/#del_fav
485
        log.info('Unset project %s as favorite' % ID)
486
        self.delete('favorite_project/%s.json' % ID)
487
488
    def list_users(self):
489
        """List users."""
490
        # http://teampasswordmanager.com/docs/api-users/#list_users
491
        log.debug('List users')
492
        return self.collection('users.json')
493
494
    def show_user(self, ID):
495
        """Show a user."""
496
        # http://teampasswordmanager.com/docs/api-users/#show_user
497
        log.debug('Show user %s' % ID)
498
        return self.get('users/%s.json' % ID)
499
500
    def show_me(self):
501
        """Show me."""
502
        # http://teampasswordmanager.com/docs/api-users/#show_me
503
        log.debug('Show Info about own user')
504
        return self.get('users/me.json')
505
506
    def who_am_i(self):
507
        """Who am I."""
508
        return self.show_me()
509
510
    def create_user(self, data):
511
        """Create a User."""
512
        # http://teampasswordmanager.com/docs/api-users/#create_user
513
        log.info('Create user with %s' % data)
514
        NewID = self.post('users.json', data).get('id')
515
        log.info('User has been created with ID %s' % NewID)
516
        return NewID
517
518
    def update_user(self, ID, data):
519
        """Update a User."""
520
        # http://teampasswordmanager.com/docs/api-users/#update_user
521
        log.info('Update user %s with %s' % (ID, data))
522
        self.put('users/%s.json' % ID, data)
523
524
    def change_user_password(self, ID, data):
525
        """Change password of a User."""
526
        # http://teampasswordmanager.com/docs/api-users/#change_password
527
        log.info('Change user %s password' % ID)
528
        self.put('users/%s/change_password.json' % ID, data)
529
530
    def activate_user(self, ID):
531
        """Activate a User."""
532
        # http://teampasswordmanager.com/docs/api-users/#activate_deactivate
533
        log.info('Activate user %s' % ID)
534
        self.put('users/%s/activate.json' % ID)
535
536
    def deactivate_user(self, ID):
537
        """Dectivate a User."""
538
        # http://teampasswordmanager.com/docs/api-users/#activate_deactivate
539
        log.info('Deactivate user %s' % ID)
540
        self.put('users/%s/deactivate.json' % ID)
541
542
    def convert_user_to_ldap(self, ID, DN):
543
        """Convert a normal user to a LDAP user."""
544
        # http://teampasswordmanager.com/docs/api-users/#convert_to_ldap
545
        data = {'login_dn': DN}
546
        log.info('Convert User %s to LDAP DN %s' % (ID, DN))
547
        self.put('users/%s/convert_to_ldap.json' % ID, data)
548
549
    def convert_ldap_user_to_normal(self, ID):
550
        """Convert a LDAP user to a normal user."""
551
        log.info('Convert User %s from LDAP to normal user' % ID)
552
        self.put('users/%s/convert_to_normal.json' % ID)
553
554
    def delete_user(self, ID):
555
        """Delete a user."""
556
        # http://teampasswordmanager.com/docs/api-users/#delete_user
557
        log.info('Delete user %s' % ID)
558
        self.delete('users/%s.json' % ID)
559
560
    def list_groups(self):
561
        """List Groups."""
562
        # http://teampasswordmanager.com/docs/api-groups/#list_groups
563
        log.debug('List groups')
564
        return self.collection('groups.json')
565
566
    def show_group(self, ID):
567
        """Show a Group."""
568
        # http://teampasswordmanager.com/docs/api-groups/#show_group
569
        log.debug('Show group %s' % ID)
570
        return self.get('groups/%s.json' % ID)
571
572
    def create_group(self, data):
573
        """Create a Group."""
574
        # http://teampasswordmanager.com/docs/api-groups/#create_group
575
        log.info('Create group with %s' % data)
576
        NewID = self.post('groups.json', data).get('id')
577
        log.info('Group has been created with ID %s' % NewID)
578
        return NewID
579
580
    def update_group(self, ID, data):
581
        """Update a Group."""
582
        # http://teampasswordmanager.com/docs/api-groups/#update_group
583
        log.info('Update group %s with %s' % (ID, data))
584
        self.put('groups/%s.json' % ID, data)
585
586
    def add_user_to_group(self, GroupID, UserID):
587
        """Add a user to a group."""
588
        # http://teampasswordmanager.com/docs/api-groups/#add_user
589
        log.info('Add User %s to Group %s' % (UserID, GroupID))
590
        self.put('groups/%s/add_user/%s.json' % (GroupID, UserID))
591
592
    def delete_user_from_group(self, GroupID, UserID):
593
        """Delete a user from a group."""
594
        # http://teampasswordmanager.com/docs/api-groups/#del_user
595
        log.info('Delete user %s from group %s' % (UserID, GroupID))
596
        self.put('groups/%s/delete_user/%s.json' % (GroupID, UserID))
597
598
    def delete_group(self, ID):
599
        """Delete a group."""
600
        # http://teampasswordmanager.com/docs/api-groups/#delete_group
601
        log.info('Delete group %s' % ID)
602
        self.delete('groups/%s.json' % ID)
603
604
    def generate_password(self):
605
        """Generate a new random password."""
606
        # http://teampasswordmanager.com/docs/api-passwords-generator/
607
        log.debug('Generate new password')
608
        return self.get('generate_password.json')
609
610
    def get_version(self):
611
        """Get Version Information."""
612
        # http://teampasswordmanager.com/docs/api-version/
613
        log.debug('Get version information')
614
        return self.get('version.json')
615
616
    def get_latest_version(self):
617
        """Check for latest version."""
618
        # http://teampasswordmanager.com/docs/api-version/
619
        log.debug('Get latest version')
620
        return self.get('version/check_latest.json')
621
622
    def up_to_date(self):
623
        """Check if Team Password Manager is up to date."""
624
        VersionInfo = self.get_latest_version()
625
        CurrentVersion = VersionInfo.get('version')
626
        LatestVersion = VersionInfo.get('latest_version')
627
        if  CurrentVersion == LatestVersion:
628
            log.info('TeamPasswordManager is up-to-date!')
629
            log.debug('Current Version: {} Latest Version: {}'.format(LatestVersion, LatestVersion))
630
            return True
631
        else:
632
            log.warning('TeamPasswordManager is not up-to-date!')
633
            log.debug('Current Version: {} Latest Version: {}'.format(LatestVersion, LatestVersion))
634
            return False
635
636
637
class TpmApiv3(TpmApi):
638
    """API v3 based class."""
639
    def __init__(self, url, **kwargs):
640
        super(TpmApiv3, self).__init__('v3', url, kwargs)
641
    """From now on, Functions that only work with API v3."""
642
643
644
class TpmApiv4(TpmApi):
645
    """API v4 based class."""
646
    def __init__(self, url, **kwargs):
647
        super(TpmApiv4, self).__init__('v4', url, kwargs)
648
    """From now on, Functions that only work with API v4."""
649
650
    def list_subprojects(self, ID):
651
        """List subprojects."""
652
        # http://teampasswordmanager.com/docs/api-projects/#list_subprojects
653
        return self.collection('projects/%s/subprojects.json' % ID)
654
655
    def list_subprojects_action(self, ID, action):
656
        """List subprojects with allowed action."""
657
        return self.collection('projects/%s/subprojects/%s.json' %
658
                               (ID, action))
659