pyPreservica 0.9.9__py3-none-any.whl → 3.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyPreservica/__init__.py +26 -8
- pyPreservica/adminAPI.py +877 -0
- pyPreservica/authorityAPI.py +229 -0
- pyPreservica/common.py +553 -94
- pyPreservica/contentAPI.py +331 -65
- pyPreservica/entityAPI.py +1805 -446
- pyPreservica/mdformsAPI.py +572 -0
- pyPreservica/monitorAPI.py +153 -0
- pyPreservica/opex.py +98 -0
- pyPreservica/parAPI.py +226 -0
- pyPreservica/retentionAPI.py +155 -44
- pyPreservica/settingsAPI.py +295 -0
- pyPreservica/uploadAPI.py +1120 -321
- pyPreservica/webHooksAPI.py +211 -0
- pyPreservica/workflowAPI.py +99 -47
- {pyPreservica-0.9.9.dist-info → pypreservica-3.3.4.dist-info}/METADATA +93 -66
- pypreservica-3.3.4.dist-info/RECORD +20 -0
- {pyPreservica-0.9.9.dist-info → pypreservica-3.3.4.dist-info}/WHEEL +5 -5
- pyPreservica-0.9.9.dist-info/RECORD +0 -12
- {pyPreservica-0.9.9.dist-info → pypreservica-3.3.4.dist-info/licenses}/LICENSE.txt +0 -0
- {pyPreservica-0.9.9.dist-info → pypreservica-3.3.4.dist-info}/top_level.txt +0 -0
pyPreservica/retentionAPI.py
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyPreservica RetentionAPI module definition
|
|
3
|
+
|
|
4
|
+
A client library for the Preservica Repository web services Entity API
|
|
5
|
+
https://us.preservica.com/api/entity/documentation.html
|
|
6
|
+
|
|
7
|
+
author: James Carr
|
|
8
|
+
licence: Apache License 2.0
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
|
|
1
12
|
import xml.etree.ElementTree
|
|
2
|
-
from typing import Set
|
|
13
|
+
from typing import Set, Callable
|
|
3
14
|
|
|
4
15
|
from pyPreservica.common import *
|
|
5
16
|
|
|
@@ -31,6 +42,9 @@ class RetentionPolicy:
|
|
|
31
42
|
self.start_date_field = ""
|
|
32
43
|
self.period = ""
|
|
33
44
|
self.expiry_action = ""
|
|
45
|
+
self.assignable = True
|
|
46
|
+
self.restriction = ""
|
|
47
|
+
self.period_unit = ""
|
|
34
48
|
|
|
35
49
|
def __str__(self):
|
|
36
50
|
return f"Ref:\t\t\t{self.reference}\n" \
|
|
@@ -43,17 +57,28 @@ class RetentionPolicy:
|
|
|
43
57
|
|
|
44
58
|
class RetentionAPI(AuthenticatedAPI):
|
|
45
59
|
|
|
46
|
-
def __init__(self, username=None, password=None, tenant=None, server=None, use_shared_secret=False
|
|
47
|
-
|
|
60
|
+
def __init__(self, username=None, password=None, tenant=None, server=None, use_shared_secret=False,
|
|
61
|
+
two_fa_secret_key: str = None, protocol: str = "https", request_hook: Callable = None, credentials_path: str = 'credentials.properties'):
|
|
62
|
+
super().__init__(username, password, tenant, server, use_shared_secret, two_fa_secret_key,
|
|
63
|
+
protocol, request_hook, credentials_path)
|
|
64
|
+
|
|
48
65
|
if self.major_version < 7 and self.minor_version < 2:
|
|
49
66
|
raise RuntimeError("Retention API is only available when connected to a v6.2 System")
|
|
50
67
|
|
|
51
68
|
def policy(self, reference: str) -> RetentionPolicy:
|
|
52
69
|
"""
|
|
53
|
-
|
|
54
|
-
|
|
70
|
+
Return a retention policy by reference
|
|
71
|
+
|
|
72
|
+
:param reference: The policy reference
|
|
73
|
+
:type reference: str
|
|
74
|
+
|
|
75
|
+
:return: The retention policy
|
|
76
|
+
:rtype: RetentionPolicy
|
|
77
|
+
|
|
78
|
+
"""
|
|
55
79
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
|
|
56
|
-
request =
|
|
80
|
+
request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}',
|
|
81
|
+
headers=headers)
|
|
57
82
|
if request.status_code == requests.codes.ok:
|
|
58
83
|
xml_response = str(request.content.decode('utf-8'))
|
|
59
84
|
logger.debug(xml_response)
|
|
@@ -67,22 +92,33 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
67
92
|
security_tag = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}SecurityTag').text
|
|
68
93
|
rp.security_tag = security_tag
|
|
69
94
|
start_date_field = entity_response.find(
|
|
70
|
-
f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}StartDateField')
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
95
|
+
f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}StartDateField')
|
|
96
|
+
if start_date_field is not None:
|
|
97
|
+
rp.start_date_field = start_date_field.text
|
|
98
|
+
else:
|
|
99
|
+
rp.start_date_field = None
|
|
100
|
+
period = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}Period')
|
|
101
|
+
if period is not None:
|
|
102
|
+
rp.period = period.text
|
|
103
|
+
else:
|
|
104
|
+
rp.period = None
|
|
105
|
+
period_unit = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}PeriodUnit')
|
|
106
|
+
if period_unit is not None:
|
|
107
|
+
rp.period_unit = period_unit.text
|
|
108
|
+
else:
|
|
109
|
+
rp.period_unit = None
|
|
110
|
+
expiry_action = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}ExpiryAction')
|
|
111
|
+
if expiry_action is not None:
|
|
112
|
+
rp.expiry_action = expiry_action.text
|
|
113
|
+
else:
|
|
114
|
+
rp.expiry_action = None
|
|
79
115
|
restriction = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}Restriction')
|
|
80
116
|
if restriction is not None:
|
|
81
117
|
rp.restriction = restriction.text
|
|
82
118
|
else:
|
|
83
119
|
rp.restriction = None
|
|
84
120
|
assignable = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy/{{{self.rm_ns}}}Assignable')
|
|
85
|
-
rp.assignable =
|
|
121
|
+
rp.assignable = strtobool(assignable.text)
|
|
86
122
|
return rp
|
|
87
123
|
elif request.status_code == requests.codes.unauthorized:
|
|
88
124
|
self.token = self.__token__()
|
|
@@ -92,10 +128,23 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
92
128
|
raise RuntimeError(request.status_code, "policy failed")
|
|
93
129
|
|
|
94
130
|
def assignable_policy(self, reference: str, status: bool):
|
|
131
|
+
"""
|
|
132
|
+
Make a policy assignable
|
|
133
|
+
|
|
134
|
+
:param reference: The policy ID
|
|
135
|
+
:type reference: str
|
|
136
|
+
|
|
137
|
+
:param status: The assignable status
|
|
138
|
+
:type status: bool
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
:return:
|
|
142
|
+
"""
|
|
95
143
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'text/plain;charset=UTF-8'}
|
|
96
144
|
data = str(status)
|
|
97
|
-
request =
|
|
98
|
-
|
|
145
|
+
request = self.session.put(
|
|
146
|
+
f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}/assignable',
|
|
147
|
+
headers=headers, data=data)
|
|
99
148
|
if request.status_code == requests.codes.ok:
|
|
100
149
|
pass
|
|
101
150
|
elif request.status_code == requests.codes.unauthorized:
|
|
@@ -190,16 +239,17 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
190
239
|
|
|
191
240
|
xml_request = xml.etree.ElementTree.tostring(retention_policy, encoding='utf-8')
|
|
192
241
|
|
|
193
|
-
request =
|
|
194
|
-
|
|
242
|
+
request = self.session.put(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}',
|
|
243
|
+
data=xml_request,
|
|
244
|
+
headers=headers)
|
|
195
245
|
if request.status_code == requests.codes.ok:
|
|
196
246
|
return self.policy(reference)
|
|
197
247
|
elif request.status_code == requests.codes.unauthorized:
|
|
198
248
|
self.token = self.__token__()
|
|
199
249
|
return self.update_policy(reference, **kwargs)
|
|
200
250
|
else:
|
|
201
|
-
|
|
202
|
-
raise RuntimeError(request.status_code, "update_policy failed")
|
|
251
|
+
logger.error(str(request.content.decode('utf-8')))
|
|
252
|
+
raise RuntimeError(request.status_code, "update_policy failed " + str(request.content.decode('utf-8')))
|
|
203
253
|
|
|
204
254
|
def create_policy(self, **kwargs):
|
|
205
255
|
"""
|
|
@@ -285,8 +335,8 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
285
335
|
|
|
286
336
|
xml_request = xml.etree.ElementTree.tostring(retention_policy, encoding='utf-8')
|
|
287
337
|
|
|
288
|
-
request =
|
|
289
|
-
|
|
338
|
+
request = self.session.post(f'{self.protocol}://{self.server}/api/entity/retention-policies', data=xml_request,
|
|
339
|
+
headers=headers)
|
|
290
340
|
if request.status_code == requests.codes.ok:
|
|
291
341
|
xml_response = str(request.content.decode('utf-8'))
|
|
292
342
|
entity_response = xml.etree.ElementTree.fromstring(xml_response)
|
|
@@ -304,9 +354,14 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
304
354
|
def delete_policy(self, reference: str):
|
|
305
355
|
"""
|
|
306
356
|
Delete a retention policy
|
|
357
|
+
|
|
358
|
+
:param reference: The policy reference
|
|
359
|
+
:type reference: str
|
|
360
|
+
|
|
307
361
|
"""
|
|
308
362
|
headers = {HEADER_TOKEN: self.token}
|
|
309
|
-
request =
|
|
363
|
+
request = self.session.delete(f'{self.protocol}://{self.server}/api/entity/retention-policies/{reference}',
|
|
364
|
+
headers=headers)
|
|
310
365
|
if request.status_code == requests.codes.no_content:
|
|
311
366
|
pass
|
|
312
367
|
elif request.status_code == requests.codes.unauthorized:
|
|
@@ -319,10 +374,18 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
319
374
|
def policy_by_name(self, name: str) -> RetentionPolicy:
|
|
320
375
|
"""
|
|
321
376
|
Return a retention policy by name
|
|
377
|
+
|
|
378
|
+
:param name: The policy name
|
|
379
|
+
:type name: str
|
|
380
|
+
|
|
381
|
+
:return: The retention policy
|
|
382
|
+
:rtype: RetentionPolicy
|
|
383
|
+
|
|
322
384
|
"""
|
|
323
385
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
|
|
324
386
|
data = {'start': str(0), 'max': "250"}
|
|
325
|
-
request =
|
|
387
|
+
request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies', data=data,
|
|
388
|
+
headers=headers)
|
|
326
389
|
if request.status_code == requests.codes.ok:
|
|
327
390
|
xml_response = str(request.content.decode('utf-8'))
|
|
328
391
|
logger.debug(xml_response)
|
|
@@ -338,28 +401,44 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
338
401
|
else:
|
|
339
402
|
raise RuntimeError(request.status_code, "policies failed")
|
|
340
403
|
|
|
341
|
-
def policies(self) ->
|
|
404
|
+
def policies(self, maximum: int = 250, next_page: str = None) -> PagedSet:
|
|
342
405
|
"""
|
|
343
406
|
Return a list of all retention policies
|
|
344
|
-
|
|
407
|
+
Returns a maximum of 250 policies by default
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
:return: Set of retention policies
|
|
411
|
+
:rtype: Set[RetentionPolicy]
|
|
412
|
+
|
|
345
413
|
"""
|
|
346
414
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
|
|
347
|
-
|
|
348
|
-
|
|
415
|
+
|
|
416
|
+
if next_page is None:
|
|
417
|
+
params = {'start': '0', 'max': str(maximum)}
|
|
418
|
+
request = self.session.get(f'{self.protocol}://{self.server}/api/entity/retention-policies', params=params,
|
|
419
|
+
headers=headers)
|
|
420
|
+
else:
|
|
421
|
+
request = self.session.get(next_page, headers=headers)
|
|
422
|
+
|
|
349
423
|
if request.status_code == requests.codes.ok:
|
|
350
424
|
xml_response = str(request.content.decode('utf-8'))
|
|
351
425
|
entity_response = xml.etree.ElementTree.fromstring(xml_response)
|
|
352
426
|
logger.debug(xml_response)
|
|
353
427
|
result = set()
|
|
428
|
+
next_url = entity_response.find(f'.//{{{self.entity_ns}}}Paging/{{{self.entity_ns}}}Next')
|
|
354
429
|
total_results = int(entity_response.find(
|
|
355
430
|
f'.//{{{self.entity_ns}}}TotalResults').text)
|
|
356
|
-
if total_results > 250:
|
|
357
|
-
logger.error("Not all retention policies have been returned.")
|
|
358
431
|
for assignment in entity_response.findall(f'.//{{{self.entity_ns}}}RetentionPolicy'):
|
|
359
432
|
ref = assignment.attrib['ref']
|
|
360
433
|
name = assignment.attrib['name']
|
|
361
434
|
result.add(self.policy(reference=ref))
|
|
362
|
-
|
|
435
|
+
has_more = True
|
|
436
|
+
url = None
|
|
437
|
+
if next_url is None:
|
|
438
|
+
has_more = False
|
|
439
|
+
else:
|
|
440
|
+
url = next_url.text
|
|
441
|
+
return PagedSet(result, has_more, total_results, url)
|
|
363
442
|
elif request.status_code == requests.codes.unauthorized:
|
|
364
443
|
self.token = self.__token__()
|
|
365
444
|
return self.policies()
|
|
@@ -368,7 +447,16 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
368
447
|
|
|
369
448
|
def add_assignments(self, entity: Entity, policy: RetentionPolicy) -> RetentionAssignment:
|
|
370
449
|
"""
|
|
371
|
-
|
|
450
|
+
Assign a retention policy to an Asset.
|
|
451
|
+
|
|
452
|
+
:param entity: The Preservica Entity to assign a policy to
|
|
453
|
+
:type entity: Entity
|
|
454
|
+
|
|
455
|
+
:param policy: The RetentionAssignment
|
|
456
|
+
:type policy: RetentionPolicy
|
|
457
|
+
|
|
458
|
+
:return: The RetentionAssignment
|
|
459
|
+
:rtype: RetentionAssignment
|
|
372
460
|
|
|
373
461
|
"""
|
|
374
462
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
|
|
@@ -379,8 +467,8 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
379
467
|
xml.etree.ElementTree.SubElement(assignment, "RetentionPolicy").text = policy.reference
|
|
380
468
|
xml_request = xml.etree.ElementTree.tostring(assignment, encoding='utf-8').decode('utf-8')
|
|
381
469
|
logger.debug(xml_request)
|
|
382
|
-
request =
|
|
383
|
-
f'
|
|
470
|
+
request = self.session.post(
|
|
471
|
+
f'{self.protocol}://{self.server}/api/entity/{entity.path}/{entity.reference}/retention-assignments',
|
|
384
472
|
headers=headers, data=xml_request)
|
|
385
473
|
|
|
386
474
|
if request.status_code == requests.codes.ok:
|
|
@@ -389,7 +477,11 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
389
477
|
api_id = entity_response.find(f'.//{{{self.rm_ns}}}ApiId').text
|
|
390
478
|
policy_ref = entity_response.find(f'.//{{{self.rm_ns}}}RetentionPolicy').text
|
|
391
479
|
entity_ref = entity_response.find(f'.//{{{self.rm_ns}}}Entity').text
|
|
392
|
-
start_date = entity_response.find(f'.//{{{self.rm_ns}}}StartDate')
|
|
480
|
+
start_date = entity_response.find(f'.//{{{self.rm_ns}}}StartDate')
|
|
481
|
+
if start_date is not None:
|
|
482
|
+
start_date = start_date.text
|
|
483
|
+
else:
|
|
484
|
+
start_date = None
|
|
393
485
|
assert entity_ref == entity.reference
|
|
394
486
|
assert policy_ref == policy.reference
|
|
395
487
|
return RetentionAssignment(entity_ref, policy_ref, api_id, start_date)
|
|
@@ -403,13 +495,21 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
403
495
|
|
|
404
496
|
def remove_assignments(self, retention_assignment: RetentionAssignment):
|
|
405
497
|
"""
|
|
406
|
-
|
|
407
|
-
|
|
498
|
+
Delete a retention policy from an asset
|
|
499
|
+
|
|
500
|
+
:param retention_assignment: The Preservica Entity to assign a policy to
|
|
501
|
+
:type retention_assignment: RetentionAssignment
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
:return: The Asset Reference
|
|
505
|
+
:rtype: str
|
|
506
|
+
|
|
507
|
+
"""
|
|
408
508
|
|
|
409
509
|
headers = {HEADER_TOKEN: self.token}
|
|
410
510
|
|
|
411
|
-
request =
|
|
412
|
-
f'
|
|
511
|
+
request = self.session.delete(
|
|
512
|
+
f'{self.protocol}://{self.server}/api/entity/information-objects/{retention_assignment.entity_reference}/retention'
|
|
413
513
|
f'-assignments/{retention_assignment.api_id}', headers=headers)
|
|
414
514
|
if request.status_code == requests.codes.no_content:
|
|
415
515
|
return retention_assignment.entity_reference
|
|
@@ -422,10 +522,17 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
422
522
|
def assignments(self, entity: Entity) -> Set[RetentionAssignment]:
|
|
423
523
|
"""
|
|
424
524
|
Return a list of retention policies for an entity.
|
|
525
|
+
|
|
526
|
+
:param entity: The entity to fetch assignments for
|
|
527
|
+
:type entity: class:`Entity`
|
|
528
|
+
|
|
529
|
+
:return: Set of policy assignments
|
|
530
|
+
:rtype: Set[RetentionAssignment]
|
|
531
|
+
|
|
425
532
|
"""
|
|
426
533
|
headers = {HEADER_TOKEN: self.token, 'Content-Type': 'application/xml;charset=UTF-8'}
|
|
427
|
-
request =
|
|
428
|
-
f'
|
|
534
|
+
request = self.session.get(
|
|
535
|
+
f'{self.protocol}://{self.server}/api/entity/{entity.path}/{entity.reference}/retention-assignments',
|
|
429
536
|
headers=headers)
|
|
430
537
|
if request.status_code == requests.codes.ok:
|
|
431
538
|
xml_response = str(request.content.decode('utf-8'))
|
|
@@ -435,7 +542,11 @@ class RetentionAPI(AuthenticatedAPI):
|
|
|
435
542
|
entity_ref = assignment.find(f'.//{{{self.rm_ns}}}Entity').text
|
|
436
543
|
assert entity_ref == entity.reference
|
|
437
544
|
policy = assignment.find(f'.//{{{self.rm_ns}}}RetentionPolicy').text
|
|
438
|
-
start_date = assignment.find(f'.//{{{self.rm_ns}}}StartDate')
|
|
545
|
+
start_date = assignment.find(f'.//{{{self.rm_ns}}}StartDate')
|
|
546
|
+
if start_date is not None:
|
|
547
|
+
start_date = start_date.text
|
|
548
|
+
else:
|
|
549
|
+
start_date = None
|
|
439
550
|
expired = bool(assignment.find(f'.//{{{self.rm_ns}}}Expired').text == 'true')
|
|
440
551
|
api_id = assignment.find(f'.//{{{self.rm_ns}}}ApiId').text
|
|
441
552
|
ra = RetentionAssignment(entity_ref, policy, api_id, start_date, expired)
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyPreservica Settings API module definition
|
|
3
|
+
|
|
4
|
+
API for retrieving information about configuration settings.
|
|
5
|
+
|
|
6
|
+
author: James Carr
|
|
7
|
+
licence: Apache License 2.0
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Callable
|
|
12
|
+
|
|
13
|
+
from pyPreservica.common import *
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SettingsAPI(AuthenticatedAPI):
|
|
19
|
+
"""
|
|
20
|
+
API for retrieving information about configuration settings.
|
|
21
|
+
|
|
22
|
+
Includes methods for:
|
|
23
|
+
|
|
24
|
+
* metadata-enrichment
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
username=None,
|
|
31
|
+
password=None,
|
|
32
|
+
tenant=None,
|
|
33
|
+
server=None,
|
|
34
|
+
use_shared_secret=False,
|
|
35
|
+
two_fa_secret_key: str = None,
|
|
36
|
+
protocol: str = "https",
|
|
37
|
+
request_hook: Callable = None,
|
|
38
|
+
credentials_path: str = "credentials.properties",
|
|
39
|
+
):
|
|
40
|
+
super().__init__(
|
|
41
|
+
username,
|
|
42
|
+
password,
|
|
43
|
+
tenant,
|
|
44
|
+
server,
|
|
45
|
+
use_shared_secret,
|
|
46
|
+
two_fa_secret_key,
|
|
47
|
+
protocol,
|
|
48
|
+
request_hook,
|
|
49
|
+
credentials_path,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if self.major_version < 7 and self.minor_version < 7:
|
|
53
|
+
raise RuntimeError(
|
|
54
|
+
"Settings API is only available when connected to a v7.7 System or higher"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
self.base_url = "api/settings"
|
|
58
|
+
|
|
59
|
+
def metadata_enrichment_rules(self, profile_id: str = None) -> dict:
|
|
60
|
+
"""
|
|
61
|
+
Returns a list of metadata enrichment rules.
|
|
62
|
+
An empty selection implies that the rule is applied to all content.
|
|
63
|
+
Rules define where particular behaviours, defined by profiles, will be applied.
|
|
64
|
+
Rules are evaluated in order, with the first matching rule being applied.
|
|
65
|
+
|
|
66
|
+
:param profile_id: The rules for a specific profile id, Set to None for all rules
|
|
67
|
+
:type profile_id: str
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
headers = {
|
|
71
|
+
HEADER_TOKEN: self.token,
|
|
72
|
+
"Accept": "application/json",
|
|
73
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
endpoint: str = "/metadata-enrichment/config/rules"
|
|
77
|
+
|
|
78
|
+
request = self.session.get(
|
|
79
|
+
f"{self.protocol}://{self.server}/{self.base_url}{endpoint}",
|
|
80
|
+
headers=headers)
|
|
81
|
+
|
|
82
|
+
if request.status_code == requests.codes.ok:
|
|
83
|
+
rules: dict = json.loads(request.content.decode("utf-8"))
|
|
84
|
+
if profile_id is None:
|
|
85
|
+
return rules
|
|
86
|
+
else:
|
|
87
|
+
profile_rules = []
|
|
88
|
+
for rule in rules["rules"]:
|
|
89
|
+
if rule["profileId"] == profile_id:
|
|
90
|
+
profile_rules.append(rule)
|
|
91
|
+
return {"rules": profile_rules}
|
|
92
|
+
else:
|
|
93
|
+
logger.debug(request.content.decode("utf-8"))
|
|
94
|
+
raise RuntimeError(request.status_code, f"metadata_enrichment_rules failed")
|
|
95
|
+
|
|
96
|
+
def metadata_enrichment_delete_rule(self, rule_id: str):
|
|
97
|
+
"""
|
|
98
|
+
Deletes a metadata enrichment rule.
|
|
99
|
+
|
|
100
|
+
:param rule_id: The rule id
|
|
101
|
+
:type rule_id: str
|
|
102
|
+
|
|
103
|
+
:return: No return value
|
|
104
|
+
:rtype: None
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
headers = {
|
|
108
|
+
HEADER_TOKEN: self.token,
|
|
109
|
+
"Accept": "application/json",
|
|
110
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
endpoint: str = f"/metadata-enrichment/config/rules/{rule_id}"
|
|
114
|
+
|
|
115
|
+
request = self.session.delete(
|
|
116
|
+
f"{self.protocol}://{self.server}/{self.base_url}{endpoint}", headers=headers)
|
|
117
|
+
|
|
118
|
+
if request.status_code == requests.codes.no_content:
|
|
119
|
+
return
|
|
120
|
+
else:
|
|
121
|
+
logger.debug(request.content.decode("utf-8"))
|
|
122
|
+
raise RuntimeError(request.status_code, f"metadata_enrichment_delete_rule failed")
|
|
123
|
+
|
|
124
|
+
def metadata_enrichment_add_rule(self, profile_id: str, priority: int = 1):
|
|
125
|
+
"""
|
|
126
|
+
Create a metadata enrichment rule to control when metadata enrichment profiles are applied and return it.
|
|
127
|
+
Rules define where particular behaviours, defined by profiles, will be applied.
|
|
128
|
+
Rules are evaluated in order, with the first matching rule being applied.
|
|
129
|
+
Note that not specifying, or specifying an empty selection implies that the rule will be applied to all content.
|
|
130
|
+
Currently only securityDescriptorSelector, representationSelector and hierarchySelector are supported selectors.
|
|
131
|
+
If a rule already exists for the requested priority, existing rules will be shifted down priority to accommodate the new entry.
|
|
132
|
+
|
|
133
|
+
:param profile_id: The profile id
|
|
134
|
+
:type profile_id: str
|
|
135
|
+
|
|
136
|
+
:param priority: The rule priority
|
|
137
|
+
:type priority: int
|
|
138
|
+
|
|
139
|
+
:return: The metadata enrichment rule
|
|
140
|
+
:rtype: dict
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
headers = {
|
|
144
|
+
HEADER_TOKEN: self.token,
|
|
145
|
+
"Accept": "application/json",
|
|
146
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
endpoint: str = "/metadata-enrichment/config/rules"
|
|
150
|
+
|
|
151
|
+
rule: dict = {
|
|
152
|
+
"profileId": profile_id,
|
|
153
|
+
"priority": str(priority),
|
|
154
|
+
"selectorSettings": {},
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
request = self.session.post(
|
|
158
|
+
f"{self.protocol}://{self.server}/{self.base_url}/{endpoint}",
|
|
159
|
+
headers=headers,
|
|
160
|
+
json=rule,
|
|
161
|
+
)
|
|
162
|
+
if request.status_code == requests.codes.created:
|
|
163
|
+
return json.loads(request.content.decode("utf-8"))
|
|
164
|
+
else:
|
|
165
|
+
logger.debug(request.content.decode("utf-8"))
|
|
166
|
+
raise RuntimeError(
|
|
167
|
+
request.status_code, f"metadata_enrichment_add_rule failed"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
def metadata_enrichment_add_profile(self, name: str, active: bool = True):
|
|
171
|
+
"""
|
|
172
|
+
Create a metadata enrichment profile to control automatic metadata enrichment of content and return it.
|
|
173
|
+
Profiles define a set of behaviours that will be applied when the profile is selected by a rule.
|
|
174
|
+
A profile has no effect if it is not used by a rule. Includes settings for PII identification.
|
|
175
|
+
PII detection tools may be run against the full text extracted from content.
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
:param name: The profile name
|
|
179
|
+
:type name: str
|
|
180
|
+
|
|
181
|
+
:param active: The profile active status
|
|
182
|
+
:type active: bool
|
|
183
|
+
|
|
184
|
+
:return: The metadata enrichment profile
|
|
185
|
+
:rtype: dict
|
|
186
|
+
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
headers = {
|
|
190
|
+
HEADER_TOKEN: self.token,
|
|
191
|
+
"Accept": "application/json",
|
|
192
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
endpoint: str = "/metadata-enrichment/config/profiles"
|
|
196
|
+
|
|
197
|
+
profile: dict = {"name": name, "piiSettings": {"active": str(active).lower()}}
|
|
198
|
+
|
|
199
|
+
request = self.session.post(
|
|
200
|
+
f"{self.protocol}://{self.server}/{self.base_url}{endpoint}",
|
|
201
|
+
headers=headers, json=profile)
|
|
202
|
+
|
|
203
|
+
if request.status_code == requests.codes.created:
|
|
204
|
+
return json.loads(request.content.decode("utf-8"))
|
|
205
|
+
else:
|
|
206
|
+
logger.debug(request.content.decode("utf-8"))
|
|
207
|
+
raise RuntimeError(request.status_code, f"metadata_enrichment_add_profile failed")
|
|
208
|
+
|
|
209
|
+
def metadata_enrichment_profile(self, profile_id: str) -> dict:
|
|
210
|
+
"""
|
|
211
|
+
Returns a single profile by its ID
|
|
212
|
+
Profiles define a set of behaviours that will be applied when the profile is selected by a rule.
|
|
213
|
+
A profile has no effect if it is not used by a rule. Includes settings for PII identification.
|
|
214
|
+
PII detection tools may be run against the full text extracted from content.
|
|
215
|
+
|
|
216
|
+
:param profile_id: The profile name
|
|
217
|
+
:type profile_id: str
|
|
218
|
+
|
|
219
|
+
:return: The metadata enrichment profile
|
|
220
|
+
:rtype: dict
|
|
221
|
+
|
|
222
|
+
"""
|
|
223
|
+
headers = {
|
|
224
|
+
HEADER_TOKEN: self.token,
|
|
225
|
+
"Accept": "application/json",
|
|
226
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
endpoint: str = f"/metadata-enrichment/config/profiles/{profile_id}"
|
|
230
|
+
|
|
231
|
+
request = self.session.get(
|
|
232
|
+
f"{self.protocol}://{self.server}/{self.base_url}{endpoint}", headers=headers)
|
|
233
|
+
|
|
234
|
+
if request.status_code == requests.codes.ok:
|
|
235
|
+
return json.loads(request.content.decode("utf-8"))
|
|
236
|
+
else:
|
|
237
|
+
logger.debug(request.content.decode("utf-8"))
|
|
238
|
+
raise RuntimeError(request.status_code, f"metadata_enrichment_profile failed")
|
|
239
|
+
|
|
240
|
+
def metadata_enrichment_delete_profile(self, profile_id: str) -> None:
|
|
241
|
+
"""
|
|
242
|
+
Deletes a metadata enrichment profile
|
|
243
|
+
|
|
244
|
+
:param profile_id: The profile name
|
|
245
|
+
:type profile_id: str
|
|
246
|
+
|
|
247
|
+
:return: No return value
|
|
248
|
+
:rtype: None
|
|
249
|
+
|
|
250
|
+
"""
|
|
251
|
+
headers = {
|
|
252
|
+
HEADER_TOKEN: self.token,
|
|
253
|
+
"Accept": "application/json",
|
|
254
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
endpoint: str = f"/metadata-enrichment/config/profiles/{profile_id}"
|
|
258
|
+
|
|
259
|
+
request = self.session.delete(
|
|
260
|
+
f"{self.protocol}://{self.server}/{self.base_url}{endpoint}", headers=headers)
|
|
261
|
+
|
|
262
|
+
if request.status_code == requests.codes.forbidden:
|
|
263
|
+
logger.debug(request.content.decode("utf-8"))
|
|
264
|
+
raise RuntimeError(request.status_code, f"Can't delete a profile with rules assigned")
|
|
265
|
+
|
|
266
|
+
if request.status_code == requests.codes.no_content:
|
|
267
|
+
return
|
|
268
|
+
else:
|
|
269
|
+
logger.debug(request.content.decode("utf-8"))
|
|
270
|
+
raise RuntimeError(request.status_code, f"metadata_enrichment_delete_profile failed")
|
|
271
|
+
|
|
272
|
+
def metadata_enrichment_profiles(self) -> dict:
|
|
273
|
+
"""
|
|
274
|
+
Returns the list of all metadata enrichment profiles.
|
|
275
|
+
Profiles define a set of behaviours that will be applied when the profile is selected by a rule.
|
|
276
|
+
A profile has no effect if it is not used by a rule. Includes settings for PII identification.
|
|
277
|
+
PII detection tools may be run against the full text extracted from content.
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
headers = {
|
|
281
|
+
HEADER_TOKEN: self.token,
|
|
282
|
+
"Accept": "application/json",
|
|
283
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
endpoint: str = "/metadata-enrichment/config/profiles"
|
|
287
|
+
|
|
288
|
+
request = self.session.get(
|
|
289
|
+
f"{self.protocol}://{self.server}/{self.base_url}{endpoint}", headers=headers)
|
|
290
|
+
|
|
291
|
+
if request.status_code == requests.codes.ok:
|
|
292
|
+
return json.loads(request.content.decode("utf-8"))
|
|
293
|
+
else:
|
|
294
|
+
logger.debug(request.content.decode("utf-8"))
|
|
295
|
+
raise RuntimeError(request.status_code, f"metadata_enrichment_profiles failed")
|