pyxecm 2.0.2__py3-none-any.whl → 2.0.3__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.
Potentially problematic release.
This version of pyxecm might be problematic. Click here for more details.
- pyxecm/__init__.py +3 -2
- pyxecm/avts.py +3 -1
- pyxecm/customizer/api/app.py +2 -2
- pyxecm/customizer/api/auth/functions.py +37 -30
- pyxecm/customizer/api/common/functions.py +54 -0
- pyxecm/customizer/api/common/router.py +50 -3
- pyxecm/customizer/api/settings.py +5 -3
- pyxecm/customizer/api/terminal/router.py +43 -18
- pyxecm/customizer/api/v1_csai/models.py +18 -0
- pyxecm/customizer/api/v1_csai/router.py +26 -1
- pyxecm/customizer/api/v1_payload/functions.py +9 -3
- pyxecm/customizer/browser_automation.py +506 -199
- pyxecm/customizer/customizer.py +123 -22
- pyxecm/customizer/guidewire.py +170 -37
- pyxecm/customizer/payload.py +614 -257
- pyxecm/customizer/settings.py +21 -3
- pyxecm/helper/xml.py +1 -1
- pyxecm/otawp.py +10 -6
- pyxecm/otca.py +187 -21
- pyxecm/otcs.py +495 -205
- pyxecm/otds.py +1 -0
- pyxecm/otkd.py +1369 -0
- pyxecm/otmm.py +190 -66
- {pyxecm-2.0.2.dist-info → pyxecm-2.0.3.dist-info}/METADATA +2 -2
- {pyxecm-2.0.2.dist-info → pyxecm-2.0.3.dist-info}/RECORD +28 -26
- {pyxecm-2.0.2.dist-info → pyxecm-2.0.3.dist-info}/WHEEL +1 -1
- {pyxecm-2.0.2.dist-info → pyxecm-2.0.3.dist-info}/licenses/LICENSE +0 -0
- {pyxecm-2.0.2.dist-info → pyxecm-2.0.3.dist-info}/top_level.txt +0 -0
pyxecm/customizer/customizer.py
CHANGED
|
@@ -12,7 +12,6 @@ import sys
|
|
|
12
12
|
import tempfile
|
|
13
13
|
import time
|
|
14
14
|
from datetime import datetime, timezone
|
|
15
|
-
from typing import TYPE_CHECKING
|
|
16
15
|
|
|
17
16
|
import requests
|
|
18
17
|
|
|
@@ -20,15 +19,12 @@ import requests
|
|
|
20
19
|
import yaml
|
|
21
20
|
from pydantic import HttpUrl
|
|
22
21
|
|
|
23
|
-
from pyxecm import AVTS, OTAC, OTAWP, OTCS, OTDS, OTIV, OTPD, CoreShare
|
|
22
|
+
from pyxecm import AVTS, OTAC, OTAWP, OTCA, OTCS, OTDS, OTIV, OTKD, OTPD, CoreShare
|
|
24
23
|
from pyxecm.customizer.k8s import K8s
|
|
25
24
|
from pyxecm.customizer.m365 import M365
|
|
26
25
|
from pyxecm.customizer.payload import Payload
|
|
27
26
|
from pyxecm.customizer.settings import Settings
|
|
28
27
|
|
|
29
|
-
if TYPE_CHECKING:
|
|
30
|
-
from pyxecm.customizer.browser_automation import BrowserAutomation
|
|
31
|
-
|
|
32
28
|
default_logger = logging.getLogger("pyxecm.customizer")
|
|
33
29
|
|
|
34
30
|
|
|
@@ -71,8 +67,9 @@ class Customizer:
|
|
|
71
67
|
self.k8s_object: K8s | None = None
|
|
72
68
|
self.m365_object: M365 | None = None
|
|
73
69
|
self.core_share_object: CoreShare | None = None
|
|
74
|
-
self.browser_automation_object: BrowserAutomation | None = None
|
|
75
70
|
self.otawp_object: OTAWP | None = None
|
|
71
|
+
self.otca_object: OTCA | None = None
|
|
72
|
+
self.otkd_object: OTKD | None = None
|
|
76
73
|
self.avts_object: AVTS | None = None
|
|
77
74
|
|
|
78
75
|
# end initializer
|
|
@@ -383,8 +380,87 @@ class Customizer:
|
|
|
383
380
|
|
|
384
381
|
# end method definition
|
|
385
382
|
|
|
383
|
+
def init_otca(self) -> OTCA:
|
|
384
|
+
"""Initialize the Content Aviator object we use to talk to the CSAI REST API.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
None
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
OTCA object:
|
|
391
|
+
Content Aviator object or None if the object couldn't be created or
|
|
392
|
+
the authentication fails.
|
|
393
|
+
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
self.logger.info(
|
|
397
|
+
"Content Aviator Chat URL = %s",
|
|
398
|
+
self.settings.aviator.chat_svc_url,
|
|
399
|
+
)
|
|
400
|
+
self.logger.info(
|
|
401
|
+
"Content Aviator Embed URL = %s",
|
|
402
|
+
self.settings.aviator.embed_svc_url,
|
|
403
|
+
)
|
|
404
|
+
self.logger.info(
|
|
405
|
+
"Content Aviator Client ID = %s",
|
|
406
|
+
self.settings.aviator.oauth_client,
|
|
407
|
+
)
|
|
408
|
+
self.logger.debug(
|
|
409
|
+
"Content Aviator Client Secret = %s",
|
|
410
|
+
self.settings.aviator.oauth_secret,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
return OTCA(
|
|
414
|
+
chat_url=str(self.settings.aviator.chat_svc_url),
|
|
415
|
+
embed_url=str(self.settings.aviator.embed_svc_url),
|
|
416
|
+
client_id=self.settings.avts.client_id,
|
|
417
|
+
client_secret=self.settings.avts.client_secret,
|
|
418
|
+
otds_url=str(self.settings.otds.url),
|
|
419
|
+
otcs_object=self.otcs_backend_object,
|
|
420
|
+
logger=self.logger,
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
# end method definition
|
|
424
|
+
|
|
425
|
+
def init_otkd(self) -> OTKD:
|
|
426
|
+
"""Initialize the Knowledge Discovery object we use to talk to the Nifi REST API.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
None
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
OTKD object:
|
|
433
|
+
Knowledge Discovery (Nifi) object or None if the object couldn't be created or
|
|
434
|
+
the authentication fails.
|
|
435
|
+
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
self.logger.info(
|
|
439
|
+
"Knowledge Discovery Nifi URL = %s",
|
|
440
|
+
self.settings.otkd.url,
|
|
441
|
+
)
|
|
442
|
+
self.logger.info(
|
|
443
|
+
"Knowledge Discovery User Name = %s",
|
|
444
|
+
self.settings.otkd.username,
|
|
445
|
+
)
|
|
446
|
+
self.logger.debug(
|
|
447
|
+
"Knowledge Discovery Password = %s",
|
|
448
|
+
self.settings.otkd.password.get_secret_value(),
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
return OTKD(
|
|
452
|
+
protocol=self.settings.otkd.url.scheme,
|
|
453
|
+
hostname=self.settings.otkd.url.host,
|
|
454
|
+
port=self.settings.otkd.url.port,
|
|
455
|
+
username=self.settings.otkd.username,
|
|
456
|
+
password=self.settings.otkd.password.get_secret_value(),
|
|
457
|
+
logger=self.logger,
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
# end method definition
|
|
461
|
+
|
|
386
462
|
def init_avts(self) -> AVTS:
|
|
387
|
-
"""Initialize the
|
|
463
|
+
"""Initialize the Aviator Search object we use to talk to the REST API.
|
|
388
464
|
|
|
389
465
|
Args:
|
|
390
466
|
None
|
|
@@ -418,7 +494,7 @@ class Customizer:
|
|
|
418
494
|
)
|
|
419
495
|
self.logger.debug(
|
|
420
496
|
"Aviator Search User Password = %s",
|
|
421
|
-
self.settings.avts.password,
|
|
497
|
+
self.settings.avts.password.get_secret_value(),
|
|
422
498
|
)
|
|
423
499
|
|
|
424
500
|
return AVTS(
|
|
@@ -426,7 +502,7 @@ class Customizer:
|
|
|
426
502
|
client_id=self.settings.avts.client_id,
|
|
427
503
|
client_secret=self.settings.avts.client_secret,
|
|
428
504
|
username=self.settings.avts.username,
|
|
429
|
-
password=self.settings.avts.password,
|
|
505
|
+
password=self.settings.avts.password.get_secret_value(),
|
|
430
506
|
otds_url=str(self.settings.otds.url),
|
|
431
507
|
logger=self.logger,
|
|
432
508
|
)
|
|
@@ -467,7 +543,11 @@ class Customizer:
|
|
|
467
543
|
)
|
|
468
544
|
self.logger.debug(
|
|
469
545
|
"Core Share Password = %s",
|
|
470
|
-
(
|
|
546
|
+
(
|
|
547
|
+
self.settings.coreshare.password.get_secret_value()
|
|
548
|
+
if self.settings.coreshare.password.get_secret_value() != ""
|
|
549
|
+
else "<not configured>"
|
|
550
|
+
),
|
|
471
551
|
)
|
|
472
552
|
|
|
473
553
|
core_share_object = CoreShare(
|
|
@@ -591,7 +671,7 @@ class Customizer:
|
|
|
591
671
|
self.logger.info("OTDS Public URL = %s", self.settings.otds.url.host)
|
|
592
672
|
self.logger.info("OTDS Public Port = %s", self.settings.otds.url.port)
|
|
593
673
|
self.logger.info("OTDS Admin User = %s", self.settings.otds.username)
|
|
594
|
-
self.logger.debug("OTDS Admin Password = %s", self.settings.otds.password)
|
|
674
|
+
self.logger.debug("OTDS Admin Password = %s", self.settings.otds.password.get_secret_value())
|
|
595
675
|
self.logger.debug("OTDS Ticket = %s", self.settings.otds.ticket)
|
|
596
676
|
self.logger.info(
|
|
597
677
|
"OTDS Admin Partition = %s",
|
|
@@ -655,7 +735,7 @@ class Customizer:
|
|
|
655
735
|
self.logger.info("OTAC URL = %s", str(self.settings.otac.url))
|
|
656
736
|
self.logger.info("OTAC URL internal = %s", str(self.settings.otac.url_internal))
|
|
657
737
|
self.logger.info("OTAC Admin User = %s", self.settings.otac.username)
|
|
658
|
-
self.logger.debug("OTAC Admin Password = %s", self.settings.otac.password)
|
|
738
|
+
self.logger.debug("OTAC Admin Password = %s", self.settings.otac.password.get_secret_value())
|
|
659
739
|
self.logger.info(
|
|
660
740
|
"OTAC Known Server = %s",
|
|
661
741
|
(self.settings.otac.known_server if self.settings.otac.known_server != "" else "<not configured>"),
|
|
@@ -752,7 +832,7 @@ class Customizer:
|
|
|
752
832
|
self.logger.info("OTCS Admin User = %s", self.settings.otcs.username)
|
|
753
833
|
self.logger.debug(
|
|
754
834
|
"OTCS Admin Password = %s",
|
|
755
|
-
self.settings.otcs.password,
|
|
835
|
+
self.settings.otcs.password.get_secret_value(),
|
|
756
836
|
)
|
|
757
837
|
self.logger.info(
|
|
758
838
|
"OTCS User Partition = %s",
|
|
@@ -972,7 +1052,7 @@ class Customizer:
|
|
|
972
1052
|
self.settings.otpd.url.host,
|
|
973
1053
|
self.settings.otpd.url.port,
|
|
974
1054
|
self.settings.otpd.username,
|
|
975
|
-
self.settings.otpd.password,
|
|
1055
|
+
self.settings.otpd.password.get_secret_value(),
|
|
976
1056
|
logger=self.logger,
|
|
977
1057
|
)
|
|
978
1058
|
|
|
@@ -1026,13 +1106,13 @@ class Customizer:
|
|
|
1026
1106
|
self.settings.otawp.access_role_name,
|
|
1027
1107
|
)
|
|
1028
1108
|
self.logger.info("OTAWP Admin User = %s", self.settings.otawp.username)
|
|
1029
|
-
self.logger.debug("OTAWP Password = %s", self.settings.otawp.password)
|
|
1109
|
+
self.logger.debug("OTAWP Password = %s", self.settings.otawp.password.get_secret_value())
|
|
1030
1110
|
self.logger.info("OTAWP Organization = %s", self.settings.otawp.organization)
|
|
1031
1111
|
self.logger.info("OTAWP K8s Stateful Set = %s", self.settings.k8s.sts_otawp)
|
|
1032
1112
|
self.logger.info("OTAWP K8s Config Map = %s", self.settings.k8s.cm_otawp)
|
|
1033
1113
|
|
|
1034
1114
|
self.logger.info(
|
|
1035
|
-
"Wait for OTCS to create its OTDS resource
|
|
1115
|
+
"Wait for OTCS to create its OTDS resource -> '%s'...",
|
|
1036
1116
|
self.settings.otcs.resource_name,
|
|
1037
1117
|
)
|
|
1038
1118
|
|
|
@@ -1472,7 +1552,7 @@ class Customizer:
|
|
|
1472
1552
|
)
|
|
1473
1553
|
self.k8s_object.update_ingress_backend_services(
|
|
1474
1554
|
self.settings.k8s.ingress_otxecm,
|
|
1475
|
-
|
|
1555
|
+
self.settings.otcs.url.host,
|
|
1476
1556
|
self.settings.k8s.maintenance_service_name,
|
|
1477
1557
|
self.settings.k8s.maintenance_service_port,
|
|
1478
1558
|
)
|
|
@@ -1489,7 +1569,7 @@ class Customizer:
|
|
|
1489
1569
|
)
|
|
1490
1570
|
self.k8s_object.update_ingress_backend_services(
|
|
1491
1571
|
self.settings.k8s.ingress_otxecm,
|
|
1492
|
-
|
|
1572
|
+
self.settings.otcs.url.host,
|
|
1493
1573
|
self.settings.otcs.url_frontend.host,
|
|
1494
1574
|
self.settings.otcs.url_frontend.port,
|
|
1495
1575
|
)
|
|
@@ -1620,11 +1700,31 @@ class Customizer:
|
|
|
1620
1700
|
self.logger.info("Microsoft 365 is disabled or credentials are missing.")
|
|
1621
1701
|
self.m365_object = None
|
|
1622
1702
|
|
|
1703
|
+
if self.settings.aviator.enabled:
|
|
1704
|
+
self.log_header("Initialize Content Aviator")
|
|
1705
|
+
self.otca_object = self.init_otca()
|
|
1706
|
+
if not self.otca_object:
|
|
1707
|
+
self.logger.error("Failed to initialize Content Aviator!")
|
|
1708
|
+
return False
|
|
1709
|
+
else:
|
|
1710
|
+
self.logger.info("Content Aviator is disabled.")
|
|
1711
|
+
self.otca_object = None
|
|
1712
|
+
|
|
1713
|
+
if self.settings.otkd.enabled:
|
|
1714
|
+
self.log_header("Initialize Knowledge Discovery")
|
|
1715
|
+
self.otkd_object = self.init_otkd()
|
|
1716
|
+
if not self.otkd_object:
|
|
1717
|
+
self.logger.error("Failed to initialize Knowledge Discovery!")
|
|
1718
|
+
return False
|
|
1719
|
+
else:
|
|
1720
|
+
self.logger.info("Knowledge Discovery is disabled.")
|
|
1721
|
+
self.otkd_object = None
|
|
1722
|
+
|
|
1623
1723
|
if self.settings.avts.enabled:
|
|
1624
1724
|
self.log_header("Initialize Aviator Search")
|
|
1625
1725
|
self.avts_object = self.init_avts()
|
|
1626
1726
|
if not self.avts_object:
|
|
1627
|
-
self.logger.error("Failed to initialize Aviator Search")
|
|
1727
|
+
self.logger.error("Failed to initialize Aviator Search!")
|
|
1628
1728
|
return False
|
|
1629
1729
|
else:
|
|
1630
1730
|
self.logger.info("Aviator Search is disabled.")
|
|
@@ -1708,7 +1808,6 @@ class Customizer:
|
|
|
1708
1808
|
otpd_object=self.otpd_object,
|
|
1709
1809
|
m365_object=self.m365_object,
|
|
1710
1810
|
core_share_object=self.core_share_object,
|
|
1711
|
-
browser_automation_object=self.browser_automation_object,
|
|
1712
1811
|
browser_headless=self.settings.headless_browser,
|
|
1713
1812
|
placeholder_values=self.settings.placeholder_values, # this dict includes placeholder replacements for the Ressource IDs of OTAWP and OTCS
|
|
1714
1813
|
log_header_callback=self.log_header,
|
|
@@ -1716,6 +1815,8 @@ class Customizer:
|
|
|
1716
1815
|
aviator_enabled=self.settings.aviator.enabled,
|
|
1717
1816
|
upload_status_files=self.settings.otcs.upload_status_files,
|
|
1718
1817
|
otawp_object=self.otawp_object,
|
|
1818
|
+
otca_object=self.otca_object,
|
|
1819
|
+
otkd_object=self.otkd_object,
|
|
1719
1820
|
avts_object=self.avts_object,
|
|
1720
1821
|
logger=self.logger,
|
|
1721
1822
|
)
|
|
@@ -1736,7 +1837,7 @@ class Customizer:
|
|
|
1736
1837
|
|
|
1737
1838
|
# Upload payload file for later review to Enterprise Workspace
|
|
1738
1839
|
if self.settings.otcs.upload_config_files:
|
|
1739
|
-
self.log_header("Upload Payload file to
|
|
1840
|
+
self.log_header("Upload Payload file to OpenText Content Management")
|
|
1740
1841
|
response = self.otcs_backend_object.get_node_from_nickname(
|
|
1741
1842
|
nickname=self.settings.cust_target_folder_nickname,
|
|
1742
1843
|
)
|
|
@@ -1845,7 +1946,7 @@ class Customizer:
|
|
|
1845
1946
|
# Upload log file for later review to "Deployment" folder
|
|
1846
1947
|
# in "Administration" folder in OTCS Enterprise volume:
|
|
1847
1948
|
if os.path.exists(self.settings.cust_log_file) and self.settings.otcs.upload_log_file:
|
|
1848
|
-
self.log_header("Upload log file to
|
|
1949
|
+
self.log_header("Upload log file to OpenText Content Management")
|
|
1849
1950
|
response = self.otcs_backend_object.get_node_from_nickname(
|
|
1850
1951
|
nickname=self.settings.cust_target_folder_nickname,
|
|
1851
1952
|
)
|
pyxecm/customizer/guidewire.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Guidewire Module to interact with the Guidewire REST API ("Cloud API").
|
|
2
2
|
|
|
3
|
-
See:
|
|
3
|
+
See:
|
|
4
|
+
https://www.guidewire.com/de/developers/apis/cloud-apis
|
|
5
|
+
https://docs.guidewire.com/cloud/pc/202407/apiref/
|
|
4
6
|
"""
|
|
5
7
|
|
|
6
8
|
__author__ = "Dr. Marc Diefenbruch"
|
|
@@ -41,16 +43,18 @@ class Guidewire:
|
|
|
41
43
|
_config: dict
|
|
42
44
|
_scope = None
|
|
43
45
|
_access_token = None
|
|
46
|
+
logger: logging.Logger = default_logger
|
|
44
47
|
|
|
45
48
|
def __init__(
|
|
46
49
|
self,
|
|
47
50
|
base_url: str,
|
|
48
|
-
auth_type: str,
|
|
51
|
+
auth_type: str = "",
|
|
49
52
|
client_id: str = "",
|
|
50
53
|
client_secret: str = "",
|
|
51
54
|
username: str = "",
|
|
52
55
|
password: str = "",
|
|
53
56
|
scope: str = "",
|
|
57
|
+
token_url: str = "",
|
|
54
58
|
logger: logging.Logger = default_logger,
|
|
55
59
|
) -> None:
|
|
56
60
|
"""Initialize the Guidewire API client.
|
|
@@ -60,16 +64,31 @@ class Guidewire:
|
|
|
60
64
|
The base URL of the Guidewire Cloud API.
|
|
61
65
|
auth_type (str):
|
|
62
66
|
The authorization type, either "oauth" or "basic".
|
|
63
|
-
client_id (str):
|
|
64
|
-
The Client ID for authentication (
|
|
65
|
-
client_secret (str):
|
|
66
|
-
The Client Secret for authentication (
|
|
67
|
-
username (str):
|
|
68
|
-
The username for authentication (
|
|
69
|
-
password (str):
|
|
70
|
-
The password for authentication (
|
|
71
|
-
scope (str):
|
|
72
|
-
The OAuth2 scope
|
|
67
|
+
client_id (str, optional):
|
|
68
|
+
The Client ID for authentication (required for client credential flow).
|
|
69
|
+
client_secret (str, optional):
|
|
70
|
+
The Client Secret for authentication (required for client credential flow).
|
|
71
|
+
username (str, optional):
|
|
72
|
+
The username for authentication (required for password-based authentication).
|
|
73
|
+
password (str, optional):
|
|
74
|
+
The password for authentication (required for password-based authentication).
|
|
75
|
+
scope (str, optional):
|
|
76
|
+
The OAuth2 scope(s). Multiple scopes needs to be separated by spaces.
|
|
77
|
+
Typical scopes for Guidewire:
|
|
78
|
+
"grantedAuthorities",
|
|
79
|
+
"groups",
|
|
80
|
+
"openid",
|
|
81
|
+
"profile",
|
|
82
|
+
"email",
|
|
83
|
+
"address",
|
|
84
|
+
"phone",
|
|
85
|
+
"offline_access",
|
|
86
|
+
"device_sso"
|
|
87
|
+
You can get the IDP configuration via the IDP URL - like this for OKTA:
|
|
88
|
+
https://guidewire-hub.okta.com/oauth2/default/.well-known/openid-configuration
|
|
89
|
+
token_url (str, optional):
|
|
90
|
+
If native OAuth2 is not enabled in Guidewire but an external IDP (like OKTA) ist used
|
|
91
|
+
then the IDP token URL can to be provided via this parameter.
|
|
73
92
|
logger:
|
|
74
93
|
The logging object used for all log messages. Default is default_logger.
|
|
75
94
|
|
|
@@ -91,7 +110,11 @@ class Guidewire:
|
|
|
91
110
|
guidewire_config["username"] = username
|
|
92
111
|
guidewire_config["password"] = password
|
|
93
112
|
guidewire_config["restUrl"] = guidewire_config["baseUrl"] + "/rest" # "/api/v1"
|
|
94
|
-
guidewire_config["tokenUrl"] = guidewire_config["restUrl"] + "/oauth2/token"
|
|
113
|
+
# guidewire_config["tokenUrl"] = guidewire_config["restUrl"] + "/oauth2/token"
|
|
114
|
+
if token_url:
|
|
115
|
+
guidewire_config["tokenUrl"] = token_url
|
|
116
|
+
else:
|
|
117
|
+
guidewire_config["tokenUrl"] = guidewire_config["baseUrl"] + "/oauth2/token"
|
|
95
118
|
|
|
96
119
|
guidewire_config["adminUrl"] = guidewire_config["restUrl"] + "/admin/v1"
|
|
97
120
|
guidewire_config["claimUrl"] = guidewire_config["restUrl"] + "/claim/v1"
|
|
@@ -116,11 +139,11 @@ class Guidewire:
|
|
|
116
139
|
|
|
117
140
|
# end method definition
|
|
118
141
|
|
|
119
|
-
def authenticate(self, auth_type: str) -> HTTPBasicAuth | str | None:
|
|
142
|
+
def authenticate(self, auth_type: str | None = None) -> HTTPBasicAuth | str | None:
|
|
120
143
|
"""Authenticate with the Guidewire API using either client credentials or username/password.
|
|
121
144
|
|
|
122
145
|
Args:
|
|
123
|
-
auth_type (str):
|
|
146
|
+
auth_type (str | None):
|
|
124
147
|
The Authorization type. This can be "basic" or "oauth".
|
|
125
148
|
|
|
126
149
|
Returns:
|
|
@@ -129,7 +152,11 @@ class Guidewire:
|
|
|
129
152
|
|
|
130
153
|
"""
|
|
131
154
|
|
|
132
|
-
self.
|
|
155
|
+
header = self.request_header()
|
|
156
|
+
self._session.headers.update(header)
|
|
157
|
+
|
|
158
|
+
if auth_type is None:
|
|
159
|
+
auth_type = self.config()["authType"]
|
|
133
160
|
|
|
134
161
|
if auth_type == "basic":
|
|
135
162
|
username = self.config()["username"]
|
|
@@ -141,13 +168,21 @@ class Guidewire:
|
|
|
141
168
|
|
|
142
169
|
request_url = self.config()["tokenUrl"]
|
|
143
170
|
|
|
144
|
-
if
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
# Check if both Resource Owner credentials (username/password) AND client credentials (clientId/clientSecret) are provided
|
|
172
|
+
if (
|
|
173
|
+
self.config()["username"]
|
|
174
|
+
and self.config()["password"]
|
|
175
|
+
and self.config()["clientId"]
|
|
176
|
+
and self.config()["clientSecret"]
|
|
177
|
+
):
|
|
178
|
+
# Use the OAuth2 "Resource Owner Password Credentials Grant" (ROPC)
|
|
179
|
+
# This flow is suitable when the application has direct access to the user's credentials (e.g., in highly trusted apps).
|
|
180
|
+
# It's generally discouraged in modern apps due to security concerns.
|
|
181
|
+
# Required parameters:
|
|
182
|
+
# - grant_type: must be "password"
|
|
183
|
+
# - username: the resource owner (user)'s username
|
|
184
|
+
# - password: the resource owner (user)'s password
|
|
185
|
+
# - client_id/client_secret: the app's credentials issued by the authorization server
|
|
151
186
|
auth_data = {
|
|
152
187
|
"grant_type": "password",
|
|
153
188
|
"username": self.config()["username"],
|
|
@@ -155,17 +190,39 @@ class Guidewire:
|
|
|
155
190
|
"client_id": self.config()["clientId"], # Required for some OAuth2 flows
|
|
156
191
|
"client_secret": self.config()["clientSecret"], # Required for some OAuth2 flows
|
|
157
192
|
}
|
|
193
|
+
# If only clientId and clientSecret are provided, use the Client Credentials Grant
|
|
194
|
+
elif self.config()["clientId"] and self.config()["clientSecret"]:
|
|
195
|
+
# Use the OAuth2 "Client Credentials Grant"
|
|
196
|
+
# This flow is used when the application (client) is acting on its own behalf, not on behalf of a user.
|
|
197
|
+
# Suitable for service-to-service interactions or background jobs (no user context).
|
|
198
|
+
# Required parameters:
|
|
199
|
+
# - grant_type: must be "client_credentials"
|
|
200
|
+
# - client_id/client_secret: the app's credentials issued by the authorization server
|
|
201
|
+
auth_data = {
|
|
202
|
+
"grant_type": "client_credentials",
|
|
203
|
+
"client_id": self.config()["clientId"],
|
|
204
|
+
"client_secret": self.config()["clientSecret"],
|
|
205
|
+
}
|
|
206
|
+
# If neither of the above combinations is satisfied, authentication can't proceed
|
|
158
207
|
else:
|
|
208
|
+
# Log an error if required credentials are missing
|
|
209
|
+
# Either username/password AND client credentials (for ROPC)
|
|
210
|
+
# OR just client credentials (for Client Credentials Grant)
|
|
159
211
|
self.logger.error("Authentication requires either client credentials or username/password.")
|
|
160
212
|
return False
|
|
161
213
|
|
|
162
214
|
if self._scope:
|
|
163
215
|
auth_data["scope"] = self._scope
|
|
164
216
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
217
|
+
try:
|
|
218
|
+
response = requests.post(request_url, data=auth_data)
|
|
219
|
+
if response.status_code == 200:
|
|
220
|
+
self.token = response.json().get("access_token")
|
|
221
|
+
return True
|
|
222
|
+
else:
|
|
223
|
+
self.logger.error("OAuth2 authentication failed: %s - %s", response.status_code, response.text)
|
|
224
|
+
except requests.RequestException as e:
|
|
225
|
+
self.logger.error("OAuth2 token request failed; error -> %s", str(e))
|
|
169
226
|
|
|
170
227
|
return False
|
|
171
228
|
|
|
@@ -190,10 +247,7 @@ class Guidewire:
|
|
|
190
247
|
"Content-Type": content_type,
|
|
191
248
|
}
|
|
192
249
|
|
|
193
|
-
if self.config()["authType"] == "oauth":
|
|
194
|
-
if not self._access_token:
|
|
195
|
-
self.logger.error("Authentication required. Call authenticate() first.")
|
|
196
|
-
return None
|
|
250
|
+
if self.config()["authType"] == "oauth" and self._access_token:
|
|
197
251
|
request_header["Authorization"] = ("Bearer {}".format(self._access_token),)
|
|
198
252
|
|
|
199
253
|
return request_header
|
|
@@ -717,7 +771,7 @@ class Guidewire:
|
|
|
717
771
|
"""Retrieve details of a specific user.
|
|
718
772
|
|
|
719
773
|
Args:
|
|
720
|
-
user_id:
|
|
774
|
+
user_id (str):
|
|
721
775
|
The unique identifier of the group.
|
|
722
776
|
|
|
723
777
|
Returns:
|
|
@@ -785,9 +839,9 @@ class Guidewire:
|
|
|
785
839
|
"""Update an existing user.
|
|
786
840
|
|
|
787
841
|
Args:
|
|
788
|
-
user_id:
|
|
842
|
+
user_id (str):
|
|
789
843
|
The unique identifier of the user.
|
|
790
|
-
user_data:
|
|
844
|
+
user_data (dict):
|
|
791
845
|
Dictionary containing updated user information.
|
|
792
846
|
|
|
793
847
|
Returns:
|
|
@@ -888,6 +942,48 @@ class Guidewire:
|
|
|
888
942
|
for account in accounts:
|
|
889
943
|
logger.info("Traversing Guidewire account -> '%s'...", account.get("attributes", {}).get("displayName"))
|
|
890
944
|
|
|
945
|
+
Args:
|
|
946
|
+
fields (list):
|
|
947
|
+
The list of fields in the results. If None, all default
|
|
948
|
+
fields are returned.
|
|
949
|
+
Fields for Guidewire accounts:
|
|
950
|
+
- *all = return all fields
|
|
951
|
+
- *default = return just the default list of fields
|
|
952
|
+
- *summary = return the fields defined for giving a summary
|
|
953
|
+
- *detail = details
|
|
954
|
+
- accountNumber
|
|
955
|
+
- accountHolder
|
|
956
|
+
- accountStatus
|
|
957
|
+
- businessOperationsDescription
|
|
958
|
+
- createdDate
|
|
959
|
+
- frozen
|
|
960
|
+
- id
|
|
961
|
+
- industryCode
|
|
962
|
+
- organizationType
|
|
963
|
+
- preferredCoverageCurrency
|
|
964
|
+
- preferredSettlementCurrency
|
|
965
|
+
- primaryLanguage
|
|
966
|
+
- primaryLocale
|
|
967
|
+
- primaryLocation
|
|
968
|
+
- producerCodes
|
|
969
|
+
filters (list):
|
|
970
|
+
List of dictionaries with three keys each:
|
|
971
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
972
|
+
- "op" - operator:
|
|
973
|
+
* eq - equal
|
|
974
|
+
* ne - not equal
|
|
975
|
+
* lt - less than - also usable for dates (before)
|
|
976
|
+
* gt - greater than - also usable for dates (after)
|
|
977
|
+
* le - less or equal
|
|
978
|
+
* ge - greater or equal
|
|
979
|
+
* in - is in list
|
|
980
|
+
* ni - is NOT in list
|
|
981
|
+
* sw - starts with
|
|
982
|
+
* cn - contains
|
|
983
|
+
- "value": the filue to filter for. Either literal or list of values
|
|
984
|
+
page_size (int, optional):
|
|
985
|
+
The maximum number of groups to return.
|
|
986
|
+
|
|
891
987
|
Returns:
|
|
892
988
|
iter:
|
|
893
989
|
A generator yielding one Guidewire account per iteration.
|
|
@@ -1007,6 +1103,7 @@ class Guidewire:
|
|
|
1007
1103
|
) -> dict | None:
|
|
1008
1104
|
"""Retrieve a list of claims.
|
|
1009
1105
|
|
|
1106
|
+
Args:
|
|
1010
1107
|
fields (list):
|
|
1011
1108
|
The list of fields in the results. If None, all default
|
|
1012
1109
|
fields are returned.
|
|
@@ -1075,6 +1172,42 @@ class Guidewire:
|
|
|
1075
1172
|
for claim in claims:
|
|
1076
1173
|
logger.info("Traversing Guidewire claim -> '%s'...", claim.get("attributes", {}).get("displayName"))
|
|
1077
1174
|
|
|
1175
|
+
Args:
|
|
1176
|
+
fields (list):
|
|
1177
|
+
The list of fields in the results. If None, all default
|
|
1178
|
+
fields are returned.
|
|
1179
|
+
Fields for Guidewire accounts:
|
|
1180
|
+
- *all = return all fields
|
|
1181
|
+
- *default = return just the default list of fields
|
|
1182
|
+
- *summary = return the fields defined for giving a summary
|
|
1183
|
+
- *detail = details
|
|
1184
|
+
- displayName
|
|
1185
|
+
- groupType
|
|
1186
|
+
- id
|
|
1187
|
+
- loadFactor
|
|
1188
|
+
- name
|
|
1189
|
+
- organization
|
|
1190
|
+
- parent
|
|
1191
|
+
- securityZone
|
|
1192
|
+
- supervisor
|
|
1193
|
+
filters (list):
|
|
1194
|
+
List of dictionaries with three keys each:
|
|
1195
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
1196
|
+
- "op" - operator:
|
|
1197
|
+
* eq - equal
|
|
1198
|
+
* ne - not equal
|
|
1199
|
+
* lt - less than - also usable for dates (before)
|
|
1200
|
+
* gt - greater than - also usable for dates (after)
|
|
1201
|
+
* le - less or equal
|
|
1202
|
+
* ge - greater or equal
|
|
1203
|
+
* in - is in list
|
|
1204
|
+
* ni - is NOT in list
|
|
1205
|
+
* sw - starts with
|
|
1206
|
+
* cn - contains
|
|
1207
|
+
- "value": the value to filter for. Either literal or list of values
|
|
1208
|
+
page_size (int, optional):
|
|
1209
|
+
The maximum number of groups to return.
|
|
1210
|
+
|
|
1078
1211
|
Returns:
|
|
1079
1212
|
iter:
|
|
1080
1213
|
A generator yielding one Guidewire claim per iteration.
|
|
@@ -1111,7 +1244,7 @@ class Guidewire:
|
|
|
1111
1244
|
"""Retrieve details of a specific claim.
|
|
1112
1245
|
|
|
1113
1246
|
Args:
|
|
1114
|
-
claim_id:
|
|
1247
|
+
claim_id (str):
|
|
1115
1248
|
The unique identifier of the claim.
|
|
1116
1249
|
|
|
1117
1250
|
Returns:
|
|
@@ -1149,9 +1282,9 @@ class Guidewire:
|
|
|
1149
1282
|
"""Update an existing claim.
|
|
1150
1283
|
|
|
1151
1284
|
Args:
|
|
1152
|
-
claim_id:
|
|
1285
|
+
claim_id (str):
|
|
1153
1286
|
The unique identifier of the claim.
|
|
1154
|
-
claim_data:
|
|
1287
|
+
claim_data (dict):
|
|
1155
1288
|
Dictionary containing updated claim information.
|
|
1156
1289
|
|
|
1157
1290
|
Returns:
|