Completed
Branch master (f07fc6)
by Andreas
04:29 queued 03:44
created

  F

Complexity

Total Complexity 110

Size/Duplication

Total Lines 570
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 570
rs 1.5789
wmc 110

71 Methods

Rating   Name   Duplication   Size   Complexity  
A onfigError.__init__() 0 3 1
A onfigError.__str__() 0 2 1
F pmApi.__init__() 0 60 16
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.unset_favorite_project() 0 5 1
A pmApi.show_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 74 18
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_url() 0 10 3
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.5'
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
        for key in kwargs:
105
            if key == 'private_key':
106
                self.private_key = kwargs[key]
107
            elif key == 'public_key':
108
                self.public_key = kwargs[key]
109
            elif key == 'username':
110
                self.username = kwargs[key]
111
            elif key == 'password':
112
                self.password = kwargs[key]
113
            elif key == 'unlock_reason':
114
                self.unlock_reason = kwargs[key]
115
        if self.private_key is not False and self.public_key is not False and\
116
                self.username is False and self.password is False:
117
            log.debug('Using Private/Public Key authentication.')
118
        elif self.username is not False and self.password is not False and\
119
                self.private_key is False and self.public_key is False:
120
            log.debug('Using Basic authentication.')
121
        else:
122
            raise self.ConfigError('No authentication specified'
123
                                   ' (user/password or private/public key)')
124
    def set_url(path):
125
        # Check if the path includes URL or not.
126
        head = self.base_url
127
        if path.startswith(head):
128
            path = path[len(head):]
129
        if not path.startswith(self.api):
130
            path = self.api + path
131
        url = head + path
132
        log.debug('Using path %s' % path)
133
        return head, url
134
                
135
    def request(self, path, action, data=''):
136
        """To make a request to the API."""
137
        head, url = set_url(path)
138
        # If we have data, convert to JSON
139
        if data:
140
            data = json.dumps(data)
141
            log.debug('Data to sent: %s' % data)
142
        # In case of key authentication
143
        if self.private_key and self.public_key:
144
            timestamp = str(int(time.time()))
145
            log.debug('Using timestamp: {}'.format(timestamp))
146
            unhashed = path + timestamp + str(data)
147
            log.debug('Using message: {}'.format(unhashed))
148
            self.hash = hmac.new(str.encode(self.private_key),
149
                                 msg=unhashed.encode('utf-8'),
150
                                 digestmod=hashlib.sha256).hexdigest()
151
            log.debug('Authenticating with hash: %s' % self.hash)
152
            self.headers['X-Public-Key'] = self.public_key
153
            self.headers['X-Request-Hash'] = self.hash
154
            self.headers['X-Request-Timestamp'] = timestamp
155
            auth = False
156
        # In case of user credentials authentication
157
        elif self.username and self.password:
158
            auth = requests.auth.HTTPBasicAuth(self.username, self.password)
159
        # Set unlock reason
160
        if self.unlock_reason:
161
            self.headers['X-Unlock-Reason'] = self.unlock_reason
162
            log.info('Unlock Reason: %s' % self.unlock_reason)
163
164
        # Try API request and handle Exceptions
165
        try:
166
            if action == 'get':
167
                log.debug('GET request %s' % url)
168
                self.req = requests.get(url, headers=self.headers, auth=auth,
169
                                        verify=False)
170
            elif action == 'post':
171
                log.debug('POST request %s' % url)
172
                self.req = requests.post(url, headers=self.headers, auth=auth,
173
                                         verify=False, data=data)
174
            elif action == 'put':
175
                log.debug('PUT request %s' % url)
176
                self.req = requests.put(url, headers=self.headers,
177
                                        auth=auth, verify=False,
178
                                        data=data)
179
            elif action == 'delete':
180
                log.debug('DELETE request %s' % url)
181
                self.req = requests.delete(url, headers=self.headers,
182
                                           verify=False, auth=auth)
183
184
            if self.req.content == b'':
185
                result = None
186
                log.debug('No result returned.')
187
            else:
188
                result = self.req.json()
189
                if 'error' in result and result['error']:
190
                    raise TPMException(result['message'])
191
192
        except requests.exceptions.RequestException as e:
193
            log.critical("Connection error for " + str(e))
194
            raise TPMException("Connection error for " + str(e))
195
196
        except ValueError as e:
197
            if self.req.status_code == 403:
198
                log.warning(url + " forbidden")
199
                raise TPMException(url + " forbidden")
200
            elif self.req.status_code == 404:
201
                log.warning(url + " forbidden")
202
                raise TPMException(url + " not found")
203
            else:
204
                message = ('%s: %s %s' % (e, self.req.url, self.req.text))
205
                log.debug(message)
206
                raise ValueError(message)
207
208
        return result
209
210
    def post(self, path, data=''):
211
        """For post based requests."""
212
        return self.request(path, 'post', data)
213
214
    def get(self, path):
215
        """For get based requests."""
216
        return self.request(path, 'get')
217
218
    def put(self, path, data=''):
219
        """For put based requests."""
220
        self.request(path, 'put', data)
221
222
    def delete(self, path):
223
        """For delete based requests."""
224
        self.request(path, 'delete')
225
226
    def get_collection(self, path):
227
        """To get pagewise data."""
228
        while True:
229
            items = self.get(path)
230
            req = self.req
231
            for item in items:
232
                yield item
233
            if req.links and req.links['next'] and\
234
                    req.links['next']['rel'] == 'next':
235
                path = req.links['next']['url']
236
            else:
237
                break
238
239
    def collection(self, path):
240
        """To return all items generated by get collection."""
241
        data = []
242
        for item in self.get_collection(path):
243
            data.append(item)
244
        return data
245
246
    # From now on, Functions that work that way in all API Versions.
247
248
    # http://teampasswordmanager.com/docs/api-projects/#list_projects
249
    def list_projects(self):
250
        """List projects."""
251
        log.debug('List all projects.')
252
        return self.collection('projects.json')
253
254
    def list_projects_archived(self):
255
        """List archived projects."""
256
        log.debug('List all archived projects.')
257
        return self.collection('projects/archived.json')
258
259
    def list_projects_favorite(self):
260
        """List favorite projects."""
261
        log.debug('List all favorite projects.')
262
        return self.collection('projects/favorite.json')
263
264
    def list_projects_search(self, searchstring):
265
        """List projects with searchstring."""
266
        log.debug('List all projects with: %s' % searchstring)
267
        return self.collection('projects/search/%s.json' %
268
                               quote_plus(searchstring))
269
270
    def show_project(self, ID):
271
        """Show a project."""
272
        # http://teampasswordmanager.com/docs/api-projects/#show_project
273
        log.debug('Show project info: %s' % ID)
274
        return self.get('projects/%s.json' % ID)
275
276
    def list_passwords_of_project(self, ID):
277
        """List passwords of project."""
278
        # http://teampasswordmanager.com/docs/api-projects/#list_pwds_prj
279
        log.debug('List passwords of project: %s' % ID)
280
        return self.collection('projects/%s/passwords.json' % ID)
281
282
    def list_user_access_on_project(self, ID):
283
        """List users who can access a project."""
284
        # http://teampasswordmanager.com/docs/api-projects/#list_users_prj
285
        log.debug('List User access on project: %s' % ID)
286
        return self.collection('projects/%s/security.json' % ID)
287
288
    def create_project(self, data):
289
        """Create a project."""
290
        # http://teampasswordmanager.com/docs/api-projects/#create_project
291
        log.info('Create project: %s' % data)
292
        NewID = self.post('projects.json', data).get('id')
293
        log.info('Project has been created with ID %s' % NewID)
294
        return NewID
295
296
    def update_project(self, ID, data):
297
        """Update a project."""
298
        # http://teampasswordmanager.com/docs/api-projects/#update_project
299
        log.info('Update project %s with %s' % (ID, data))
300
        self.put('projects/%s.json' % ID, data)
301
302
    def change_parent_of_project(self, ID, NewParrentID):
303
        """Change parent of project."""
304
        # http://teampasswordmanager.com/docs/api-projects/#change_parent
305
        log.info('Change parrent for project %s to %s' % (ID, NewParrentID))
306
        data = {'parent_id': NewParrentID}
307
        self.put('projects/%s/change_parent.json' % ID, data)
308
309
    def update_security_of_project(self, ID, data):
310
        """Update security of project."""
311
        # http://teampasswordmanager.com/docs/api-projects/#update_project_security
312
        log.info('Update project %s security %s' % (ID, data))
313
        self.put('projects/%s/security.json' % ID, data)
314
315
    def archive_project(self, ID):
316
        """Archive a project."""
317
        # http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project
318
        log.info('Archive project %s' % ID)
319
        self.put('projects/%s/archive.json' % ID)
320
321
    def unarchive_project(self, ID):
322
        """Un-Archive a project."""
323
        # http://teampasswordmanager.com/docs/api-projects/#arch_unarch_project
324
        log.info('Unarchive project %s' % ID)
325
        self.put('projects/%s/unarchive.json' % ID)
326
327
    def delete_project(self, ID):
328
        """Delete a project."""
329
        # http://teampasswordmanager.com/docs/api-projects/#delete_project
330
        log.info('Delete project %s' % ID)
331
        self.delete('projects/%s.json' % ID)
332
333
    # http://teampasswordmanager.com/docs/api-passwords/#list_passwords
334
    def list_passwords(self):
335
        """List passwords."""
336
        log.debug('List all passwords.')
337
        return self.collection('passwords.json')
338
339
    def list_passwords_archived(self):
340
        """List archived passwords."""
341
        log.debug('List archived passwords.')
342
        return self.collection('passwords/archived.json')
343
344
    def list_passwords_favorite(self):
345
        """List favorite passwords."""
346
        log.debug('List favorite spasswords.')
347
        return self.collection('passwords/favorite.json')
348
349
    def list_passwords_search(self, searchstring):
350
        """List passwords with searchstring."""
351
        log.debug('List all passwords with: %s' % searchstring)
352
        return self.collection('passwords/search/%s.json' %
353
                               quote_plus(searchstring))
354
355
    def show_password(self, ID):
356
        """Show password."""
357
        # http://teampasswordmanager.com/docs/api-passwords/#show_password
358
        log.info('Show password info: %s' % ID)
359
        return self.get('passwords/%s.json' % ID)
360
361
    def list_user_access_on_password(self, ID):
362
        """List users who can access a password."""
363
        # http://teampasswordmanager.com/docs/api-passwords/#list_users_pwd
364
        log.debug('List user access on password %s' % ID)
365
        return self.collection('passwords/%s/security.json' % ID)
366
367
    def create_password(self, data):
368
        """Create a password."""
369
        # http://teampasswordmanager.com/docs/api-passwords/#create_password
370
        log.info('Create new password %s' % data)
371
        NewID = self.post('passwords.json', data).get('id')
372
        log.info('Password has been created with ID %s' % NewID)
373
        return NewID
374
375
    def update_password(self, ID, data):
376
        """Update a password."""
377
        # http://teampasswordmanager.com/docs/api-passwords/#update_password
378
        log.info('Update Password %s with %s' % (ID, data))
379
        self.put('passwords/%s.json' % ID, data)
380
381
    def update_security_of_password(self, ID, data):
382
        """Update security of a password."""
383
        # http://teampasswordmanager.com/docs/api-passwords/#update_security_password
384
        log.info('Update security of password %s with %s' % (ID, data))
385
        self.put('passwords/%s/security.json' % ID, data)
386
387
    def update_custom_fields_of_password(self, ID, data):
388
        """Update custom fields definitions of a password."""
389
        # http://teampasswordmanager.com/docs/api-passwords/#update_cf_password
390
        log.info('Update custom fields of password %s with %s' % (ID, data))
391
        self.put('passwords/%s/custom_fields.json' % ID, data)
392
393
    def delete_password(self, ID):
394
        """Delete a password."""
395
        # http://teampasswordmanager.com/docs/api-passwords/#delete_password
396
        log.info('Delete password %s' % ID)
397
        self.delete('passwords/%s.json' % ID)
398
399
    def lock_password(self, ID):
400
        """Lock a password."""
401
        # http://teampasswordmanager.com/docs/api-passwords/#lock_password
402
        log.info('Lock password %s' % ID)
403
        self.put('passwords/%s/lock.json' % ID)
404
405
    def unlock_password(self, ID, reason):
406
        """Unlock a password."""
407
        # http://teampasswordmanager.com/docs/api-passwords/#unlock_password
408
        log.info('Unlock password %s, Reason: %s' % (ID, reason))
409
        self.unlock_reason = reason
410
        self.put('passwords/%s/unlock.json' % ID)
411
412
    def list_mypasswords(self):
413
        """List my passwords."""
414
        # http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords
415
        log.debug('List MyPasswords')
416
        return self.collection('my_passwords.json')
417
418
    def list_mypasswords_search(self, searchstring):
419
        """List my passwords with searchstring."""
420
        # http://teampasswordmanager.com/docs/api-my-passwords/#list_passwords
421
        log.debug('List MyPasswords with %s' % searchstring)
422
        return self.collection('my_passwords/search/%s.json' %
423
                               quote_plus(searchstring))
424
425
    def show_mypassword(self, ID):
426
        """Show my password."""
427
        # http://teampasswordmanager.com/docs/api-my-passwords/#show_password
428
        log.debug('Show MyPassword %s' % ID)
429
        return self.get('my_passwords/%s.json' % ID)
430
431
    def create_mypassword(self, data):
432
        """Create my password."""
433
        # http://teampasswordmanager.com/docs/api-my-passwords/#create_password
434
        log.info('Create MyPassword with %s' % data)
435
        NewID = self.post('my_passwords.json', data).get('id')
436
        log.info('MyPassword has been created with %s' % NewID)
437
        return NewID
438
439
    def update_mypassword(self, ID, data):
440
        """Update my password."""
441
        # http://teampasswordmanager.com/docs/api-my-passwords/#update_password
442
        log.info('Update MyPassword %s with %s' % (ID, data))
443
        self.put('my_passwords/%s.json' % ID, data)
444
445
    def delete_mypassword(self, ID):
446
        """Delete my password."""
447
        # http://teampasswordmanager.com/docs/api-my-passwords/#delete_password
448
        log.info('Delete password %s' % ID)
449
        self.delete('my_passwords/%s.json' % ID)
450
451
    def set_favorite_password(self, ID):
452
        """Set a password as favorite."""
453
        # http://teampasswordmanager.com/docs/api-favorites/#set_fav
454
        log.info('Set password %s as favorite' % ID)
455
        self.post('favorite_passwords/%s.json' % ID)
456
457
    def unset_favorite_password(self, ID):
458
        """Unet a password as favorite."""
459
        # http://teampasswordmanager.com/docs/api-favorites/#del_fav
460
        log.info('Unset password %s as favorite' % ID)
461
        self.delete('favorite_passwords/%s.json' % ID)
462
463
    def set_favorite_project(self, ID):
464
        """Set a project as favorite."""
465
        # http://teampasswordmanager.com/docs/api-favorites/#set_fav
466
        log.info('Set project %s as favorite' % ID)
467
        self.post('favorite_project/%s.json' % ID)
468
469
    def unset_favorite_project(self, ID):
470
        """Unet a project as favorite."""
471
        # http://teampasswordmanager.com/docs/api-favorites/#del_fav
472
        log.info('Unset project %s as favorite' % ID)
473
        self.delete('favorite_project/%s.json' % ID)
474
475
    def list_users(self):
476
        """List users."""
477
        # http://teampasswordmanager.com/docs/api-users/#list_users
478
        log.debug('List users')
479
        return self.collection('users.json')
480
481
    def show_user(self, ID):
482
        """Show a user."""
483
        # http://teampasswordmanager.com/docs/api-users/#show_user
484
        log.debug('Show user %s' % ID)
485
        return self.get('users/%s.json' % ID)
486
487
    def show_me(self):
488
        """Show me."""
489
        # http://teampasswordmanager.com/docs/api-users/#show_me
490
        log.debug('Show Info about own user')
491
        return self.get('users/me.json')
492
493
    def who_am_i(self):
494
        """Who am I."""
495
        return self.show_me()
496
497
    def create_user(self, data):
498
        """Create a User."""
499
        # http://teampasswordmanager.com/docs/api-users/#create_user
500
        log.info('Create user with %s' % data)
501
        NewID = self.post('users.json', data).get('id')
502
        log.info('User has been created with ID %s' % NewID)
503
        return NewID
504
505
    def update_user(self, ID, data):
506
        """Update a User."""
507
        # http://teampasswordmanager.com/docs/api-users/#update_user
508
        log.info('Update user %s with %s' % (ID, data))
509
        self.put('users/%s.json' % ID, data)
510
511
    def change_user_password(self, ID, data):
512
        """Change password of a User."""
513
        # http://teampasswordmanager.com/docs/api-users/#change_password
514
        log.info('Change user %s password' % ID)
515
        self.put('users/%s/change_password.json' % ID, data)
516
517
    def activate_user(self, ID):
518
        """Activate a User."""
519
        # http://teampasswordmanager.com/docs/api-users/#activate_deactivate
520
        log.info('Activate user %s' % ID)
521
        self.put('users/%s/activate.json' % ID)
522
523
    def deactivate_user(self, ID):
524
        """Dectivate a User."""
525
        # http://teampasswordmanager.com/docs/api-users/#activate_deactivate
526
        log.info('Deactivate user %s' % ID)
527
        self.put('users/%s/deactivate.json' % ID)
528
529
    def convert_user_to_ldap(self, ID, DN):
530
        """Convert a normal user to a LDAP user."""
531
        # http://teampasswordmanager.com/docs/api-users/#convert_to_ldap
532
        data = {'login_dn': DN}
533
        log.info('Convert User %s to LDAP DN %s' % (ID, DN))
534
        self.put('users/%s/convert_to_ldap.json' % ID, data)
535
536
    def convert_ldap_user_to_normal(self, ID):
537
        """Convert a LDAP user to a normal user."""
538
        log.info('Convert User %s from LDAP to normal user' % ID)
539
        self.put('users/%s/convert_to_normal.json' % ID)
540
541
    def delete_user(self, ID):
542
        """Delete a user."""
543
        # http://teampasswordmanager.com/docs/api-users/#delete_user
544
        log.info('Delete user %s' % ID)
545
        self.delete('users/%s.json' % ID)
546
547
    def list_groups(self):
548
        """List Groups."""
549
        # http://teampasswordmanager.com/docs/api-groups/#list_groups
550
        log.debug('List groups')
551
        return self.collection('groups.json')
552
553
    def show_group(self, ID):
554
        """Show a Group."""
555
        # http://teampasswordmanager.com/docs/api-groups/#show_group
556
        log.debug('Show group %s' % ID)
557
        return self.get('groups/%s.json' % ID)
558
559
    def create_group(self, data):
560
        """Create a Group."""
561
        # http://teampasswordmanager.com/docs/api-groups/#create_group
562
        log.info('Create group with %s' % data)
563
        NewID = self.post('groups.json', data).get('id')
564
        log.info('Group has been created with ID %s' % NewID)
565
        return NewID
566
567
    def update_group(self, ID, data):
568
        """Update a Group."""
569
        # http://teampasswordmanager.com/docs/api-groups/#update_group
570
        log.info('Update group %s with %s' % (ID, data))
571
        self.put('groups/%s.json' % ID, data)
572
573
    def add_user_to_group(self, GroupID, UserID):
574
        """Add a user to a group."""
575
        # http://teampasswordmanager.com/docs/api-groups/#add_user
576
        log.info('Add User %s to Group %s' % (UserID, GroupID))
577
        self.put('groups/%s/add_user/%s.json' % (GroupID, UserID))
578
579
    def delete_user_from_group(self, GroupID, UserID):
580
        """Delete a user from a group."""
581
        # http://teampasswordmanager.com/docs/api-groups/#del_user
582
        log.info('Delete user %s from group %s' % (UserID, GroupID))
583
        self.put('groups/%s/delete_user/%s.json' % (GroupID, UserID))
584
585
    def delete_group(self, ID):
586
        """Delete a group."""
587
        # http://teampasswordmanager.com/docs/api-groups/#delete_group
588
        log.info('Delete group %s' % ID)
589
        self.delete('groups/%s.json' % ID)
590
591
    def generate_password(self):
592
        """Generate a new random password."""
593
        # http://teampasswordmanager.com/docs/api-passwords-generator/
594
        log.debug('Generate new password')
595
        return self.get('generate_password.json')
596
597
    def get_version(self):
598
        """Get Version Information."""
599
        # http://teampasswordmanager.com/docs/api-version/
600
        log.debug('Get version information')
601
        return self.get('version.json')
602
603
    def get_latest_version(self):
604
        """Check for latest version."""
605
        # http://teampasswordmanager.com/docs/api-version/
606
        log.debug('Get latest version')
607
        return self.get('version/check_latest.json')
608
609
    def up_to_date(self):
610
        """Check if Team Password Manager is up to date."""
611
        VersionInfo = self.get_latest_version()
612
        CurrentVersion = VersionInfo.get('version')
613
        LatestVersion = VersionInfo.get('latest_version')
614
        if  CurrentVersion == LatestVersion:
615
            log.info('TeamPasswordManager is up-to-date!')
616
            log.debug('Current Version: {} Latest Version: {}'.format(LatestVersion, LatestVersion))
617
            return True
618
        else:
619
            log.warning('TeamPasswordManager is not up-to-date!')
620
            log.debug('Current Version: {} Latest Version: {}'.format(LatestVersion, LatestVersion))
621
            return False
622
623
624
class TpmApiv3(TpmApi):
625
    """API v3 based class."""
626
    def __init__(self, url, **kwargs):
627
        super(TpmApiv3, self).__init__('v3', url, kwargs)
628
    """From now on, Functions that only work with API v3."""
629
630
631
class TpmApiv4(TpmApi):
632
    """API v4 based class."""
633
    def __init__(self, url, **kwargs):
634
        super(TpmApiv4, self).__init__('v4', url, kwargs)
635
    """From now on, Functions that only work with API v4."""
636
637
    def list_subprojects(self, ID):
638
        """List subprojects."""
639
        # http://teampasswordmanager.com/docs/api-projects/#list_subprojects
640
        return self.collection('projects/%s/subprojects.json' % ID)
641
642
    def list_subprojects_action(self, ID, action):
643
        """List subprojects with allowed action."""
644
        return self.collection('projects/%s/subprojects/%s.json' %
645
                               (ID, action))
646