pyxecm 1.5__py3-none-any.whl → 1.6__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 +2 -0
- pyxecm/avts.py +1065 -0
- pyxecm/coreshare.py +467 -571
- pyxecm/customizer/customizer.py +160 -19
- pyxecm/customizer/k8s.py +139 -25
- pyxecm/customizer/m365.py +694 -1498
- pyxecm/customizer/payload.py +2306 -485
- pyxecm/customizer/pht.py +547 -124
- pyxecm/customizer/salesforce.py +378 -443
- pyxecm/customizer/servicenow.py +379 -133
- pyxecm/helper/assoc.py +20 -0
- pyxecm/helper/data.py +237 -33
- pyxecm/helper/xml.py +1 -1
- pyxecm/otawp.py +1810 -0
- pyxecm/otcs.py +3180 -2938
- pyxecm/otds.py +1591 -1875
- pyxecm/otmm.py +131 -11
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/METADATA +3 -1
- pyxecm-1.6.dist-info/RECORD +32 -0
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/WHEEL +1 -1
- pyxecm-1.5.dist-info/RECORD +0 -30
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/LICENSE +0 -0
- {pyxecm-1.5.dist-info → pyxecm-1.6.dist-info}/top_level.txt +0 -0
pyxecm/customizer/salesforce.py
CHANGED
|
@@ -8,7 +8,9 @@ Methods:
|
|
|
8
8
|
__init__ : class initializer
|
|
9
9
|
config : Returns config data set
|
|
10
10
|
credentials: Returns the token data
|
|
11
|
+
|
|
11
12
|
request_header: Returns the request header for Salesforce API calls
|
|
13
|
+
do_request: Call an Salesforce REST API in a safe way
|
|
12
14
|
parse_request_response: Parse the REST API responses and convert
|
|
13
15
|
them to Python dict in a safe way
|
|
14
16
|
exist_result_item: Check if an dict item is in the response
|
|
@@ -56,8 +58,11 @@ __email__ = "mdiefenb@opentext.com"
|
|
|
56
58
|
import os
|
|
57
59
|
import json
|
|
58
60
|
import logging
|
|
61
|
+
import time
|
|
59
62
|
|
|
60
63
|
from typing import Optional, Union, Any
|
|
64
|
+
|
|
65
|
+
from http import HTTPStatus
|
|
61
66
|
import requests
|
|
62
67
|
|
|
63
68
|
logger = logging.getLogger("pyxecm.customizer.salesforce")
|
|
@@ -68,6 +73,9 @@ REQUEST_LOGIN_HEADERS = {
|
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
REQUEST_TIMEOUT = 60
|
|
76
|
+
REQUEST_RETRY_DELAY = 20
|
|
77
|
+
REQUEST_MAX_RETRIES = 3
|
|
78
|
+
|
|
71
79
|
SALESFORCE_API_VERSION = "v60.0"
|
|
72
80
|
|
|
73
81
|
class Salesforce(object):
|
|
@@ -205,6 +213,179 @@ class Salesforce(object):
|
|
|
205
213
|
|
|
206
214
|
# end method definition
|
|
207
215
|
|
|
216
|
+
def do_request(
|
|
217
|
+
self,
|
|
218
|
+
url: str,
|
|
219
|
+
method: str = "GET",
|
|
220
|
+
headers: dict | None = None,
|
|
221
|
+
data: dict | None = None,
|
|
222
|
+
json_data: dict | None = None,
|
|
223
|
+
files: dict | None = None,
|
|
224
|
+
params: dict | None = None,
|
|
225
|
+
timeout: int | None = REQUEST_TIMEOUT,
|
|
226
|
+
show_error: bool = True,
|
|
227
|
+
show_warning: bool = False,
|
|
228
|
+
warning_message: str = "",
|
|
229
|
+
failure_message: str = "",
|
|
230
|
+
success_message: str = "",
|
|
231
|
+
max_retries: int = REQUEST_MAX_RETRIES,
|
|
232
|
+
retry_forever: bool = False,
|
|
233
|
+
parse_request_response: bool = True,
|
|
234
|
+
stream: bool = False,
|
|
235
|
+
verify: bool = True,
|
|
236
|
+
) -> dict | None:
|
|
237
|
+
"""Call an Salesforce REST API in a safe way
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
url (str): URL to send the request to.
|
|
241
|
+
method (str, optional): HTTP method (GET, POST, etc.). Defaults to "GET".
|
|
242
|
+
headers (dict | None, optional): Request Headers. Defaults to None.
|
|
243
|
+
data (dict | None, optional): Request payload. Defaults to None
|
|
244
|
+
files (dict | None, optional): Dictionary of {"name": file-tuple} for multipart encoding upload.
|
|
245
|
+
file-tuple can be a 2-tuple ("filename", fileobj) or a 3-tuple ("filename", fileobj, "content_type")
|
|
246
|
+
params (dict | None, optional): Add key-value pairs to the query string of the URL.
|
|
247
|
+
When you use the params parameter, requests automatically appends
|
|
248
|
+
the key-value pairs to the URL as part of the query string
|
|
249
|
+
timeout (int | None, optional): Timeout for the request in seconds. Defaults to REQUEST_TIMEOUT.
|
|
250
|
+
show_error (bool, optional): Whether or not an error should be logged in case of a failed REST call.
|
|
251
|
+
If False, then only a warning is logged. Defaults to True.
|
|
252
|
+
warning_message (str, optional): Specific warning message. Defaults to "". If not given the error_message will be used.
|
|
253
|
+
failure_message (str, optional): Specific error message. Defaults to "".
|
|
254
|
+
success_message (str, optional): Specific success message. Defaults to "".
|
|
255
|
+
max_retries (int, optional): How many retries on Connection errors? Default is REQUEST_MAX_RETRIES.
|
|
256
|
+
retry_forever (bool, optional): Eventually wait forever - without timeout. Defaults to False.
|
|
257
|
+
parse_request_response (bool, optional): should the response.text be interpreted as json and loaded into a dictionary. True is the default.
|
|
258
|
+
stream (bool, optional): parameter is used to control whether the response content should be immediately downloaded or streamed incrementally
|
|
259
|
+
verify (bool, optional): specify whether or not SSL certificates should be verified when making an HTTPS request. Default = True
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
dict | None: Response of OTDS REST API or None in case of an error.
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
if headers is None:
|
|
266
|
+
logger.error("Missing request header. Cannot send request to Core Share!")
|
|
267
|
+
return None
|
|
268
|
+
|
|
269
|
+
# In case of an expired session we reauthenticate and
|
|
270
|
+
# try 1 more time. Session expiration should not happen
|
|
271
|
+
# twice in a row:
|
|
272
|
+
retries = 0
|
|
273
|
+
|
|
274
|
+
while True:
|
|
275
|
+
try:
|
|
276
|
+
response = requests.request(
|
|
277
|
+
method=method,
|
|
278
|
+
url=url,
|
|
279
|
+
data=data,
|
|
280
|
+
json=json_data,
|
|
281
|
+
files=files,
|
|
282
|
+
params=params,
|
|
283
|
+
headers=headers,
|
|
284
|
+
timeout=timeout,
|
|
285
|
+
stream=stream,
|
|
286
|
+
verify=verify,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
if response.ok:
|
|
290
|
+
if success_message:
|
|
291
|
+
logger.info(success_message)
|
|
292
|
+
if parse_request_response:
|
|
293
|
+
return self.parse_request_response(response)
|
|
294
|
+
else:
|
|
295
|
+
return response
|
|
296
|
+
# Check if Session has expired - then re-authenticate and try once more
|
|
297
|
+
elif response.status_code == 401 and retries == 0:
|
|
298
|
+
logger.debug("Session has expired - try to re-authenticate...")
|
|
299
|
+
self.authenticate(revalidate=True)
|
|
300
|
+
# Make sure to not change an existing content type
|
|
301
|
+
# the do_request() method is called with:
|
|
302
|
+
headers = self.request_header(
|
|
303
|
+
content_type=headers.get("Content-Type", None)
|
|
304
|
+
)
|
|
305
|
+
retries += 1
|
|
306
|
+
else:
|
|
307
|
+
# Handle plain HTML responses to not pollute the logs
|
|
308
|
+
content_type = response.headers.get("content-type", None)
|
|
309
|
+
if content_type == "text/html":
|
|
310
|
+
response_text = "HTML content (only printed in debug log)"
|
|
311
|
+
else:
|
|
312
|
+
response_text = response.text
|
|
313
|
+
|
|
314
|
+
if show_error:
|
|
315
|
+
logger.error(
|
|
316
|
+
"%s; status -> %s/%s; error -> %s",
|
|
317
|
+
failure_message,
|
|
318
|
+
response.status_code,
|
|
319
|
+
HTTPStatus(response.status_code).phrase,
|
|
320
|
+
response_text,
|
|
321
|
+
)
|
|
322
|
+
elif show_warning:
|
|
323
|
+
logger.warning(
|
|
324
|
+
"%s; status -> %s/%s; warning -> %s",
|
|
325
|
+
warning_message if warning_message else failure_message,
|
|
326
|
+
response.status_code,
|
|
327
|
+
HTTPStatus(response.status_code).phrase,
|
|
328
|
+
response_text,
|
|
329
|
+
)
|
|
330
|
+
if content_type == "text/html":
|
|
331
|
+
logger.debug(
|
|
332
|
+
"%s; status -> %s/%s; warning -> %s",
|
|
333
|
+
failure_message,
|
|
334
|
+
response.status_code,
|
|
335
|
+
HTTPStatus(response.status_code).phrase,
|
|
336
|
+
response.text,
|
|
337
|
+
)
|
|
338
|
+
return None
|
|
339
|
+
except requests.exceptions.Timeout:
|
|
340
|
+
if retries <= max_retries:
|
|
341
|
+
logger.warning(
|
|
342
|
+
"Request timed out. Retrying in %s seconds...",
|
|
343
|
+
str(REQUEST_RETRY_DELAY),
|
|
344
|
+
)
|
|
345
|
+
retries += 1
|
|
346
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
347
|
+
else:
|
|
348
|
+
logger.error(
|
|
349
|
+
"%s; timeout error",
|
|
350
|
+
failure_message,
|
|
351
|
+
)
|
|
352
|
+
if retry_forever:
|
|
353
|
+
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
354
|
+
logger.warning("Turn timeouts off and wait forever...")
|
|
355
|
+
timeout = None
|
|
356
|
+
else:
|
|
357
|
+
return None
|
|
358
|
+
except requests.exceptions.ConnectionError:
|
|
359
|
+
if retries <= max_retries:
|
|
360
|
+
logger.warning(
|
|
361
|
+
"Connection error. Retrying in %s seconds...",
|
|
362
|
+
str(REQUEST_RETRY_DELAY),
|
|
363
|
+
)
|
|
364
|
+
retries += 1
|
|
365
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
366
|
+
else:
|
|
367
|
+
logger.error(
|
|
368
|
+
"%s; connection error",
|
|
369
|
+
failure_message,
|
|
370
|
+
)
|
|
371
|
+
if retry_forever:
|
|
372
|
+
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
373
|
+
logger.warning("Turn timeouts off and wait forever...")
|
|
374
|
+
timeout = None
|
|
375
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
376
|
+
else:
|
|
377
|
+
return None
|
|
378
|
+
# end try
|
|
379
|
+
logger.debug(
|
|
380
|
+
"Retrying REST API %s call -> %s... (retry = %s)",
|
|
381
|
+
method,
|
|
382
|
+
url,
|
|
383
|
+
str(retries),
|
|
384
|
+
)
|
|
385
|
+
# end while True
|
|
386
|
+
|
|
387
|
+
# end method definition
|
|
388
|
+
|
|
208
389
|
def parse_request_response(
|
|
209
390
|
self,
|
|
210
391
|
response_object: requests.Response,
|
|
@@ -409,32 +590,20 @@ class Salesforce(object):
|
|
|
409
590
|
|
|
410
591
|
query = f"SELECT Id FROM {object_type} WHERE {name_field} = '{name}'"
|
|
411
592
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
self.authenticate(revalidate=True)
|
|
427
|
-
request_header = self.request_header()
|
|
428
|
-
retries += 1
|
|
429
|
-
else:
|
|
430
|
-
logger.error(
|
|
431
|
-
"Failed to get Salesforce object ID for object type -> '%s' and object name -> '%s'; status -> %s; error -> %s",
|
|
432
|
-
object_type,
|
|
433
|
-
name,
|
|
434
|
-
response.status_code,
|
|
435
|
-
response.text,
|
|
436
|
-
)
|
|
437
|
-
return None
|
|
593
|
+
response = self.do_request(
|
|
594
|
+
method="GET",
|
|
595
|
+
url=request_url,
|
|
596
|
+
headers=request_header,
|
|
597
|
+
params={"q": query},
|
|
598
|
+
timeout=REQUEST_TIMEOUT,
|
|
599
|
+
failure_message="Failed to get Salesforce object ID for object type -> '{}' and object name -> '{}'".format(
|
|
600
|
+
object_type, name
|
|
601
|
+
),
|
|
602
|
+
)
|
|
603
|
+
if not response:
|
|
604
|
+
return None
|
|
605
|
+
|
|
606
|
+
return self.get_result_value(response, "Id")
|
|
438
607
|
|
|
439
608
|
# end method definition
|
|
440
609
|
|
|
@@ -509,28 +678,15 @@ class Salesforce(object):
|
|
|
509
678
|
"Sending query -> %s to Salesforce; calling -> %s", query, request_url
|
|
510
679
|
)
|
|
511
680
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
self.authenticate(revalidate=True)
|
|
522
|
-
request_header = self.request_header()
|
|
523
|
-
retries += 1
|
|
524
|
-
else:
|
|
525
|
-
logger.error(
|
|
526
|
-
"Failed to retrieve Salesforce object -> %s with %s = %s; status -> %s; error -> %s",
|
|
527
|
-
object_type,
|
|
528
|
-
search_field,
|
|
529
|
-
search_value,
|
|
530
|
-
response.status_code,
|
|
531
|
-
response.text,
|
|
532
|
-
)
|
|
533
|
-
return None
|
|
681
|
+
return self.do_request(
|
|
682
|
+
method="GET",
|
|
683
|
+
url=request_url,
|
|
684
|
+
headers=request_header,
|
|
685
|
+
timeout=REQUEST_TIMEOUT,
|
|
686
|
+
failure_message="Failed to retrieve Salesforce object type -> '{}' with {} = {}".format(
|
|
687
|
+
object_type, search_field, search_value
|
|
688
|
+
),
|
|
689
|
+
)
|
|
534
690
|
|
|
535
691
|
# end method definition
|
|
536
692
|
|
|
@@ -654,26 +810,15 @@ class Salesforce(object):
|
|
|
654
810
|
"Get Salesforce group with ID -> %s; calling -> %s", group_id, request_url
|
|
655
811
|
)
|
|
656
812
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
self.authenticate(revalidate=True)
|
|
667
|
-
request_header = self.request_header()
|
|
668
|
-
retries += 1
|
|
669
|
-
else:
|
|
670
|
-
logger.error(
|
|
671
|
-
"Failed to get Salesforce group -> %s; status -> %s; error -> %s",
|
|
672
|
-
group_id,
|
|
673
|
-
response.status_code,
|
|
674
|
-
response.text,
|
|
675
|
-
)
|
|
676
|
-
return None
|
|
813
|
+
return self.do_request(
|
|
814
|
+
method="GET",
|
|
815
|
+
url=request_url,
|
|
816
|
+
headers=request_header,
|
|
817
|
+
timeout=REQUEST_TIMEOUT,
|
|
818
|
+
failure_message="Failed to get Salesforce group with ID -> {}".format(
|
|
819
|
+
group_id
|
|
820
|
+
),
|
|
821
|
+
)
|
|
677
822
|
|
|
678
823
|
# end method definition
|
|
679
824
|
|
|
@@ -710,29 +855,14 @@ class Salesforce(object):
|
|
|
710
855
|
"Adding Salesforce group -> %s; calling -> %s", group_name, request_url
|
|
711
856
|
)
|
|
712
857
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
if response.ok:
|
|
722
|
-
return self.parse_request_response(response)
|
|
723
|
-
elif response.status_code == 401 and retries == 0:
|
|
724
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
725
|
-
self.authenticate(revalidate=True)
|
|
726
|
-
request_header = self.request_header()
|
|
727
|
-
retries += 1
|
|
728
|
-
else:
|
|
729
|
-
logger.error(
|
|
730
|
-
"Failed to add Salesforce group -> %s; status -> %s; error -> %s",
|
|
731
|
-
group_name,
|
|
732
|
-
response.status_code,
|
|
733
|
-
response.text,
|
|
734
|
-
)
|
|
735
|
-
return None
|
|
858
|
+
return self.do_request(
|
|
859
|
+
method="POST",
|
|
860
|
+
url=request_url,
|
|
861
|
+
headers=request_header,
|
|
862
|
+
data=json.dumps(payload),
|
|
863
|
+
timeout=REQUEST_TIMEOUT,
|
|
864
|
+
failure_message="Failed to add Salesforce group -> '{}'".format(group_name),
|
|
865
|
+
)
|
|
736
866
|
|
|
737
867
|
# end method definition
|
|
738
868
|
|
|
@@ -740,7 +870,7 @@ class Salesforce(object):
|
|
|
740
870
|
self,
|
|
741
871
|
group_id: str,
|
|
742
872
|
update_data: dict,
|
|
743
|
-
) -> dict:
|
|
873
|
+
) -> dict | None:
|
|
744
874
|
"""Update a Salesforce group.
|
|
745
875
|
|
|
746
876
|
Args:
|
|
@@ -764,29 +894,16 @@ class Salesforce(object):
|
|
|
764
894
|
request_url,
|
|
765
895
|
)
|
|
766
896
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
elif response.status_code == 401 and retries == 0:
|
|
778
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
779
|
-
self.authenticate(revalidate=True)
|
|
780
|
-
request_header = self.request_header()
|
|
781
|
-
retries += 1
|
|
782
|
-
else:
|
|
783
|
-
logger.error(
|
|
784
|
-
"Failed to update Salesforce group -> %s; status -> %s; error -> %s",
|
|
785
|
-
group_id,
|
|
786
|
-
response.status_code,
|
|
787
|
-
response.text,
|
|
788
|
-
)
|
|
789
|
-
return None
|
|
897
|
+
return self.do_request(
|
|
898
|
+
method="PATCH",
|
|
899
|
+
url=request_url,
|
|
900
|
+
headers=request_header,
|
|
901
|
+
json_data=update_data,
|
|
902
|
+
timeout=REQUEST_TIMEOUT,
|
|
903
|
+
failure_message="Failed to update Salesforce group with ID -> {}".format(
|
|
904
|
+
group_id
|
|
905
|
+
),
|
|
906
|
+
)
|
|
790
907
|
|
|
791
908
|
# end method definition
|
|
792
909
|
|
|
@@ -831,29 +948,16 @@ class Salesforce(object):
|
|
|
831
948
|
request_url,
|
|
832
949
|
)
|
|
833
950
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
elif response.status_code == 401 and retries == 0:
|
|
845
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
846
|
-
self.authenticate(revalidate=True)
|
|
847
|
-
request_header = self.request_header()
|
|
848
|
-
retries += 1
|
|
849
|
-
else:
|
|
850
|
-
logger.error(
|
|
851
|
-
"Failed to retrieve members of Salesforce group with ID -> %s; status -> %s; error -> %s",
|
|
852
|
-
group_id,
|
|
853
|
-
response.status_code,
|
|
854
|
-
response.text,
|
|
855
|
-
)
|
|
856
|
-
return None
|
|
951
|
+
return self.do_request(
|
|
952
|
+
method="GET",
|
|
953
|
+
url=request_url,
|
|
954
|
+
headers=request_header,
|
|
955
|
+
params=params,
|
|
956
|
+
timeout=REQUEST_TIMEOUT,
|
|
957
|
+
failure_message="Failed to get members of Salesforce group with ID -> {}".format(
|
|
958
|
+
group_id
|
|
959
|
+
),
|
|
960
|
+
)
|
|
857
961
|
|
|
858
962
|
# end method definition
|
|
859
963
|
|
|
@@ -891,29 +995,16 @@ class Salesforce(object):
|
|
|
891
995
|
request_url,
|
|
892
996
|
)
|
|
893
997
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
elif response.status_code == 401 and retries == 0:
|
|
905
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
906
|
-
self.authenticate(revalidate=True)
|
|
907
|
-
request_header = self.request_header()
|
|
908
|
-
retries += 1
|
|
909
|
-
else:
|
|
910
|
-
logger.error(
|
|
911
|
-
"Failed to retrieve members of Salesforce group with ID -> %s; status -> %s; error -> %s",
|
|
912
|
-
group_id,
|
|
913
|
-
response.status_code,
|
|
914
|
-
response.text,
|
|
915
|
-
)
|
|
916
|
-
return None
|
|
998
|
+
return self.do_request(
|
|
999
|
+
method="POST",
|
|
1000
|
+
url=request_url,
|
|
1001
|
+
headers=request_header,
|
|
1002
|
+
json_data=payload,
|
|
1003
|
+
timeout=REQUEST_TIMEOUT,
|
|
1004
|
+
failure_message="Failed to add member with ID -> {} to Salesforce group with ID -> {}".format(
|
|
1005
|
+
member_id, group_id
|
|
1006
|
+
),
|
|
1007
|
+
)
|
|
917
1008
|
|
|
918
1009
|
# end method definition
|
|
919
1010
|
|
|
@@ -935,8 +1026,7 @@ class Salesforce(object):
|
|
|
935
1026
|
'url': '/services/data/v52.0/sobjects/Profile/00eDn000001msL8IAI'},
|
|
936
1027
|
'Id': '00eDn000001msL8IAI',
|
|
937
1028
|
'Name': 'Standard User',
|
|
938
|
-
'CreatedById':
|
|
939
|
-
'005Dn000001rRodIAE',
|
|
1029
|
+
'CreatedById': '005Dn000001rRodIAE',
|
|
940
1030
|
'CreatedDate': '2022-11-30T15:30:54.000+0000',
|
|
941
1031
|
'Description': None,
|
|
942
1032
|
'LastModifiedById': '005Dn000001rUacIAE',
|
|
@@ -958,28 +1048,14 @@ class Salesforce(object):
|
|
|
958
1048
|
|
|
959
1049
|
query = "SELECT Id, Name, CreatedById, CreatedDate, Description, LastModifiedById, LastModifiedDate, PermissionsCustomizeApplication, PermissionsEditTask, PermissionsImportLeads FROM Profile"
|
|
960
1050
|
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
if response.ok:
|
|
970
|
-
return self.parse_request_response(response)
|
|
971
|
-
elif response.status_code == 401 and retries == 0:
|
|
972
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
973
|
-
self.authenticate(revalidate=True)
|
|
974
|
-
request_header = self.request_header()
|
|
975
|
-
retries += 1
|
|
976
|
-
else:
|
|
977
|
-
logger.error(
|
|
978
|
-
"Failed to get Salesforce user profiles; status -> %s; error -> %s",
|
|
979
|
-
response.status_code,
|
|
980
|
-
response.text,
|
|
981
|
-
)
|
|
982
|
-
return None
|
|
1051
|
+
return self.do_request(
|
|
1052
|
+
method="GET",
|
|
1053
|
+
url=request_url,
|
|
1054
|
+
headers=request_header,
|
|
1055
|
+
params={"q": query},
|
|
1056
|
+
timeout=REQUEST_TIMEOUT,
|
|
1057
|
+
failure_message="Failed to get Salesforce user profiles",
|
|
1058
|
+
)
|
|
983
1059
|
|
|
984
1060
|
# end method definition
|
|
985
1061
|
|
|
@@ -1033,26 +1109,15 @@ class Salesforce(object):
|
|
|
1033
1109
|
"Get Salesforce user with ID -> %s; calling -> %s", user_id, request_url
|
|
1034
1110
|
)
|
|
1035
1111
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
self.authenticate(revalidate=True)
|
|
1046
|
-
request_header = self.request_header()
|
|
1047
|
-
retries += 1
|
|
1048
|
-
else:
|
|
1049
|
-
logger.error(
|
|
1050
|
-
"Failed to get Salesforce user -> %s; status -> %s; error -> %s",
|
|
1051
|
-
user_id,
|
|
1052
|
-
response.status_code,
|
|
1053
|
-
response.text,
|
|
1054
|
-
)
|
|
1055
|
-
return None
|
|
1112
|
+
return self.do_request(
|
|
1113
|
+
method="GET",
|
|
1114
|
+
url=request_url,
|
|
1115
|
+
headers=request_header,
|
|
1116
|
+
timeout=REQUEST_TIMEOUT,
|
|
1117
|
+
failure_message="Failed to get Salesforce user with ID -> {}".format(
|
|
1118
|
+
user_id
|
|
1119
|
+
),
|
|
1120
|
+
)
|
|
1056
1121
|
|
|
1057
1122
|
# end method definition
|
|
1058
1123
|
|
|
@@ -1125,29 +1190,14 @@ class Salesforce(object):
|
|
|
1125
1190
|
"Adding Salesforce user -> %s; calling -> %s", username, request_url
|
|
1126
1191
|
)
|
|
1127
1192
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
if response.ok:
|
|
1137
|
-
return self.parse_request_response(response)
|
|
1138
|
-
elif response.status_code == 401 and retries == 0:
|
|
1139
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1140
|
-
self.authenticate(revalidate=True)
|
|
1141
|
-
request_header = self.request_header()
|
|
1142
|
-
retries += 1
|
|
1143
|
-
else:
|
|
1144
|
-
logger.error(
|
|
1145
|
-
"Failed to add Salesforce user -> %s; status -> %s; error -> %s",
|
|
1146
|
-
username,
|
|
1147
|
-
response.status_code,
|
|
1148
|
-
response.text,
|
|
1149
|
-
)
|
|
1150
|
-
return None
|
|
1193
|
+
return self.do_request(
|
|
1194
|
+
method="POST",
|
|
1195
|
+
url=request_url,
|
|
1196
|
+
headers=request_header,
|
|
1197
|
+
data=json.dumps(payload),
|
|
1198
|
+
timeout=REQUEST_TIMEOUT,
|
|
1199
|
+
failure_message="Failed to add Salesforce user -> {}".format(username),
|
|
1200
|
+
)
|
|
1151
1201
|
|
|
1152
1202
|
# end method definition
|
|
1153
1203
|
|
|
@@ -1177,29 +1227,16 @@ class Salesforce(object):
|
|
|
1177
1227
|
"Update Salesforce user with ID -> %s; calling -> %s", user_id, request_url
|
|
1178
1228
|
)
|
|
1179
1229
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
elif response.status_code == 401 and retries == 0:
|
|
1191
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1192
|
-
self.authenticate(revalidate=True)
|
|
1193
|
-
request_header = self.request_header()
|
|
1194
|
-
retries += 1
|
|
1195
|
-
else:
|
|
1196
|
-
logger.error(
|
|
1197
|
-
"Failed to update Salesforce user -> %s; status -> %s; error -> %s",
|
|
1198
|
-
user_id,
|
|
1199
|
-
response.status_code,
|
|
1200
|
-
response.text,
|
|
1201
|
-
)
|
|
1202
|
-
return None
|
|
1230
|
+
return self.do_request(
|
|
1231
|
+
method="PATCH",
|
|
1232
|
+
url=request_url,
|
|
1233
|
+
headers=request_header,
|
|
1234
|
+
json_data=update_data,
|
|
1235
|
+
timeout=REQUEST_TIMEOUT,
|
|
1236
|
+
failure_message="Failed to update Salesforce user with ID -> {}".format(
|
|
1237
|
+
user_id
|
|
1238
|
+
),
|
|
1239
|
+
)
|
|
1203
1240
|
|
|
1204
1241
|
# end method definition
|
|
1205
1242
|
|
|
@@ -1233,29 +1270,16 @@ class Salesforce(object):
|
|
|
1233
1270
|
|
|
1234
1271
|
update_data = {"NewPassword": password}
|
|
1235
1272
|
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
elif response.status_code == 401 and retries == 0:
|
|
1247
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1248
|
-
self.authenticate(revalidate=True)
|
|
1249
|
-
request_header = self.request_header()
|
|
1250
|
-
retries += 1
|
|
1251
|
-
else:
|
|
1252
|
-
logger.error(
|
|
1253
|
-
"Failed to update password of Salesforce user -> %s; status -> %s; error -> %s",
|
|
1254
|
-
user_id,
|
|
1255
|
-
response.status_code,
|
|
1256
|
-
response.text,
|
|
1257
|
-
)
|
|
1258
|
-
return None
|
|
1273
|
+
return self.do_request(
|
|
1274
|
+
method="POST",
|
|
1275
|
+
url=request_url,
|
|
1276
|
+
headers=request_header,
|
|
1277
|
+
json_data=update_data,
|
|
1278
|
+
timeout=REQUEST_TIMEOUT,
|
|
1279
|
+
failure_message="Failed to update password of Salesforce user with ID -> {}".format(
|
|
1280
|
+
user_id
|
|
1281
|
+
),
|
|
1282
|
+
)
|
|
1259
1283
|
|
|
1260
1284
|
# end method definition
|
|
1261
1285
|
|
|
@@ -1292,6 +1316,8 @@ class Salesforce(object):
|
|
|
1292
1316
|
)
|
|
1293
1317
|
return None
|
|
1294
1318
|
|
|
1319
|
+
# Content Type = None is important as upload calls need
|
|
1320
|
+
# a multipart header that is automatically selected if None is used:
|
|
1295
1321
|
request_header = self.request_header(content_type=None)
|
|
1296
1322
|
|
|
1297
1323
|
data = {"json": json.dumps({"cropX": 0, "cropY": 0, "cropSize": 200})}
|
|
@@ -1310,31 +1336,18 @@ class Salesforce(object):
|
|
|
1310
1336
|
request_url,
|
|
1311
1337
|
)
|
|
1312
1338
|
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
)
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
elif response.status_code == 401 and retries == 0:
|
|
1326
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1327
|
-
self.authenticate(revalidate=True)
|
|
1328
|
-
request_header = self.request_header()
|
|
1329
|
-
retries += 1
|
|
1330
|
-
else:
|
|
1331
|
-
logger.error(
|
|
1332
|
-
"Failed to update profile photo of Salesforce user with ID -> %s; status -> %s; error -> %s",
|
|
1333
|
-
user_id,
|
|
1334
|
-
response.status_code,
|
|
1335
|
-
response.text,
|
|
1336
|
-
)
|
|
1337
|
-
return None
|
|
1339
|
+
return self.do_request(
|
|
1340
|
+
method="POST",
|
|
1341
|
+
url=request_url,
|
|
1342
|
+
headers=request_header,
|
|
1343
|
+
files=files,
|
|
1344
|
+
data=data,
|
|
1345
|
+
timeout=REQUEST_TIMEOUT,
|
|
1346
|
+
failure_message="Failed to update profile photo of Salesforce user with ID -> {}".format(
|
|
1347
|
+
user_id
|
|
1348
|
+
),
|
|
1349
|
+
verify=False,
|
|
1350
|
+
)
|
|
1338
1351
|
|
|
1339
1352
|
# end method definition
|
|
1340
1353
|
|
|
@@ -1383,32 +1396,22 @@ class Salesforce(object):
|
|
|
1383
1396
|
payload.update(kwargs) # Add additional fields from kwargs
|
|
1384
1397
|
|
|
1385
1398
|
logger.debug(
|
|
1386
|
-
"Adding Salesforce account -> %s; calling -> %s",
|
|
1399
|
+
"Adding Salesforce account -> '%s' (%s); calling -> %s",
|
|
1400
|
+
account_name,
|
|
1401
|
+
account_number,
|
|
1402
|
+
request_url,
|
|
1387
1403
|
)
|
|
1388
1404
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
elif response.status_code == 401 and retries == 0:
|
|
1400
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1401
|
-
self.authenticate(revalidate=True)
|
|
1402
|
-
request_header = self.request_header()
|
|
1403
|
-
retries += 1
|
|
1404
|
-
else:
|
|
1405
|
-
logger.error(
|
|
1406
|
-
"Failed to add Salesforce account -> %s; status -> %s; error -> %s",
|
|
1407
|
-
account_name,
|
|
1408
|
-
response.status_code,
|
|
1409
|
-
response.text,
|
|
1410
|
-
)
|
|
1411
|
-
return None
|
|
1405
|
+
return self.do_request(
|
|
1406
|
+
method="POST",
|
|
1407
|
+
url=request_url,
|
|
1408
|
+
headers=request_header,
|
|
1409
|
+
data=json.dumps(payload),
|
|
1410
|
+
timeout=REQUEST_TIMEOUT,
|
|
1411
|
+
failure_message="Failed to add Salesforce account -> '{}' ({})".format(
|
|
1412
|
+
account_name, account_number
|
|
1413
|
+
),
|
|
1414
|
+
)
|
|
1412
1415
|
|
|
1413
1416
|
# end method definition
|
|
1414
1417
|
|
|
@@ -1447,32 +1450,22 @@ class Salesforce(object):
|
|
|
1447
1450
|
payload.update(kwargs) # Add additional fields from kwargs
|
|
1448
1451
|
|
|
1449
1452
|
logger.debug(
|
|
1450
|
-
"Add Salesforce product -> %s; calling -> %s",
|
|
1453
|
+
"Add Salesforce product -> '%s' (%s); calling -> %s",
|
|
1454
|
+
product_name,
|
|
1455
|
+
product_code,
|
|
1456
|
+
request_url,
|
|
1451
1457
|
)
|
|
1452
1458
|
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
elif response.status_code == 401 and retries == 0:
|
|
1464
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1465
|
-
self.authenticate(revalidate=True)
|
|
1466
|
-
request_header = self.request_header()
|
|
1467
|
-
retries += 1
|
|
1468
|
-
else:
|
|
1469
|
-
logger.error(
|
|
1470
|
-
"Failed to add Salesforce product -> %s; status -> %s; error -> %s",
|
|
1471
|
-
product_name,
|
|
1472
|
-
response.status_code,
|
|
1473
|
-
response.text,
|
|
1474
|
-
)
|
|
1475
|
-
return None
|
|
1459
|
+
return self.do_request(
|
|
1460
|
+
method="POST",
|
|
1461
|
+
url=request_url,
|
|
1462
|
+
headers=request_header,
|
|
1463
|
+
data=json.dumps(payload),
|
|
1464
|
+
timeout=REQUEST_TIMEOUT,
|
|
1465
|
+
failure_message="Failed to add Salesforce product -> '{}' ({})".format(
|
|
1466
|
+
product_name, product_code
|
|
1467
|
+
),
|
|
1468
|
+
)
|
|
1476
1469
|
|
|
1477
1470
|
# end method definition
|
|
1478
1471
|
|
|
@@ -1520,32 +1513,17 @@ class Salesforce(object):
|
|
|
1520
1513
|
payload.update(kwargs) # Add additional fields from kwargs
|
|
1521
1514
|
|
|
1522
1515
|
logger.debug(
|
|
1523
|
-
"Add Salesforce opportunity -> %s; calling -> %s", name, request_url
|
|
1516
|
+
"Add Salesforce opportunity -> '%s'; calling -> %s", name, request_url
|
|
1524
1517
|
)
|
|
1525
1518
|
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
if response.ok:
|
|
1535
|
-
return self.parse_request_response(response)
|
|
1536
|
-
elif response.status_code == 401 and retries == 0:
|
|
1537
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1538
|
-
self.authenticate(revalidate=True)
|
|
1539
|
-
request_header = self.request_header()
|
|
1540
|
-
retries += 1
|
|
1541
|
-
else:
|
|
1542
|
-
logger.error(
|
|
1543
|
-
"Failed to add Salesforce opportunity -> %s; status -> %s; error -> %s",
|
|
1544
|
-
name,
|
|
1545
|
-
response.status_code,
|
|
1546
|
-
response.text,
|
|
1547
|
-
)
|
|
1548
|
-
return None
|
|
1519
|
+
return self.do_request(
|
|
1520
|
+
method="POST",
|
|
1521
|
+
url=request_url,
|
|
1522
|
+
headers=request_header,
|
|
1523
|
+
data=json.dumps(payload),
|
|
1524
|
+
timeout=REQUEST_TIMEOUT,
|
|
1525
|
+
failure_message="Failed to add Salesforce opportunity -> '{}'".format(name),
|
|
1526
|
+
)
|
|
1549
1527
|
|
|
1550
1528
|
# end method definition
|
|
1551
1529
|
|
|
@@ -1603,31 +1581,16 @@ class Salesforce(object):
|
|
|
1603
1581
|
payload["ProductId"] = product_id
|
|
1604
1582
|
payload.update(kwargs) # Add additional fields from kwargs
|
|
1605
1583
|
|
|
1606
|
-
logger.debug("Add Salesforce case -> %s; calling -> %s", subject, request_url)
|
|
1584
|
+
logger.debug("Add Salesforce case -> '%s'; calling -> %s", subject, request_url)
|
|
1607
1585
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
if response.ok:
|
|
1617
|
-
return self.parse_request_response(response)
|
|
1618
|
-
elif response.status_code == 401 and retries == 0:
|
|
1619
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1620
|
-
self.authenticate(revalidate=True)
|
|
1621
|
-
request_header = self.request_header()
|
|
1622
|
-
retries += 1
|
|
1623
|
-
else:
|
|
1624
|
-
logger.error(
|
|
1625
|
-
"Failed to add Salesforce case -> %s; status -> %s; error -> %s",
|
|
1626
|
-
subject,
|
|
1627
|
-
response.status_code,
|
|
1628
|
-
response.text,
|
|
1629
|
-
)
|
|
1630
|
-
return None
|
|
1586
|
+
return self.do_request(
|
|
1587
|
+
method="POST",
|
|
1588
|
+
url=request_url,
|
|
1589
|
+
headers=request_header,
|
|
1590
|
+
data=json.dumps(payload),
|
|
1591
|
+
timeout=REQUEST_TIMEOUT,
|
|
1592
|
+
failure_message="Failed to add Salesforce case -> '{}'".format(subject),
|
|
1593
|
+
)
|
|
1631
1594
|
|
|
1632
1595
|
# end method definition
|
|
1633
1596
|
|
|
@@ -1677,32 +1640,17 @@ class Salesforce(object):
|
|
|
1677
1640
|
payload.update(kwargs) # Add additional fields from kwargs
|
|
1678
1641
|
|
|
1679
1642
|
logger.debug(
|
|
1680
|
-
"Add Salesforce asset -> %s; calling -> %s", asset_name, request_url
|
|
1643
|
+
"Add Salesforce asset -> '%s'; calling -> %s", asset_name, request_url
|
|
1681
1644
|
)
|
|
1682
1645
|
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
if response.ok:
|
|
1692
|
-
return self.parse_request_response(response)
|
|
1693
|
-
elif response.status_code == 401 and retries == 0:
|
|
1694
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1695
|
-
self.authenticate(revalidate=True)
|
|
1696
|
-
request_header = self.request_header()
|
|
1697
|
-
retries += 1
|
|
1698
|
-
else:
|
|
1699
|
-
logger.error(
|
|
1700
|
-
"Failed to add Salesforce user -> %s; status -> %s; error -> %s",
|
|
1701
|
-
asset_name,
|
|
1702
|
-
response.status_code,
|
|
1703
|
-
response.text,
|
|
1704
|
-
)
|
|
1705
|
-
return None
|
|
1646
|
+
return self.do_request(
|
|
1647
|
+
method="POST",
|
|
1648
|
+
url=request_url,
|
|
1649
|
+
headers=request_header,
|
|
1650
|
+
data=json.dumps(payload),
|
|
1651
|
+
timeout=REQUEST_TIMEOUT,
|
|
1652
|
+
failure_message="Failed to add Salesforce asset -> '{}'".format(asset_name),
|
|
1653
|
+
)
|
|
1706
1654
|
|
|
1707
1655
|
# end method definition
|
|
1708
1656
|
|
|
@@ -1750,33 +1698,20 @@ class Salesforce(object):
|
|
|
1750
1698
|
payload.update(kwargs) # Add additional fields from kwargs
|
|
1751
1699
|
|
|
1752
1700
|
logger.debug(
|
|
1753
|
-
"Adding Salesforce contract for account ID -> %s; calling -> %s",
|
|
1701
|
+
"Adding Salesforce contract for account with ID -> %s; calling -> %s",
|
|
1754
1702
|
account_id,
|
|
1755
1703
|
request_url,
|
|
1756
1704
|
)
|
|
1757
1705
|
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
elif response.status_code == 401 and retries == 0:
|
|
1769
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1770
|
-
self.authenticate(revalidate=True)
|
|
1771
|
-
request_header = self.request_header()
|
|
1772
|
-
retries += 1
|
|
1773
|
-
else:
|
|
1774
|
-
logger.error(
|
|
1775
|
-
"Failed to add Salesforce contract for account ID -> %s; status -> %s; error -> %s",
|
|
1776
|
-
account_id,
|
|
1777
|
-
response.status_code,
|
|
1778
|
-
response.text,
|
|
1779
|
-
)
|
|
1780
|
-
return None
|
|
1706
|
+
return self.do_request(
|
|
1707
|
+
method="POST",
|
|
1708
|
+
url=request_url,
|
|
1709
|
+
headers=request_header,
|
|
1710
|
+
data=json.dumps(payload),
|
|
1711
|
+
timeout=REQUEST_TIMEOUT,
|
|
1712
|
+
failure_message="Failed to add Salesforce contract for account with ID -> {}".format(
|
|
1713
|
+
account_id
|
|
1714
|
+
),
|
|
1715
|
+
)
|
|
1781
1716
|
|
|
1782
1717
|
# end method definition
|