pyxecm 1.5__py3-none-any.whl → 2.0.0__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 +6 -2
- pyxecm/avts.py +1492 -0
- pyxecm/coreshare.py +1075 -960
- pyxecm/customizer/__init__.py +16 -4
- pyxecm/customizer/__main__.py +58 -0
- pyxecm/customizer/api/__init__.py +5 -0
- pyxecm/customizer/api/__main__.py +6 -0
- pyxecm/customizer/api/app.py +914 -0
- pyxecm/customizer/api/auth.py +154 -0
- pyxecm/customizer/api/metrics.py +92 -0
- pyxecm/customizer/api/models.py +13 -0
- pyxecm/customizer/api/payload_list.py +865 -0
- pyxecm/customizer/api/settings.py +103 -0
- pyxecm/customizer/browser_automation.py +332 -139
- pyxecm/customizer/customizer.py +1075 -1057
- pyxecm/customizer/exceptions.py +35 -0
- pyxecm/customizer/guidewire.py +322 -0
- pyxecm/customizer/k8s.py +787 -338
- pyxecm/customizer/log.py +107 -0
- pyxecm/customizer/m365.py +3424 -2270
- pyxecm/customizer/nhc.py +1169 -0
- pyxecm/customizer/openapi.py +258 -0
- pyxecm/customizer/payload.py +18201 -7030
- pyxecm/customizer/pht.py +1047 -210
- pyxecm/customizer/salesforce.py +836 -727
- pyxecm/customizer/sap.py +58 -41
- pyxecm/customizer/servicenow.py +851 -383
- pyxecm/customizer/settings.py +442 -0
- pyxecm/customizer/successfactors.py +408 -346
- pyxecm/customizer/translate.py +83 -48
- pyxecm/helper/__init__.py +5 -2
- pyxecm/helper/assoc.py +98 -38
- pyxecm/helper/data.py +2482 -742
- pyxecm/helper/logadapter.py +27 -0
- pyxecm/helper/web.py +229 -101
- pyxecm/helper/xml.py +528 -172
- pyxecm/maintenance_page/__init__.py +5 -0
- pyxecm/maintenance_page/__main__.py +6 -0
- pyxecm/maintenance_page/app.py +51 -0
- pyxecm/maintenance_page/settings.py +28 -0
- pyxecm/maintenance_page/static/favicon.avif +0 -0
- pyxecm/maintenance_page/templates/maintenance.html +165 -0
- pyxecm/otac.py +234 -140
- pyxecm/otawp.py +2689 -0
- pyxecm/otcs.py +12344 -7547
- pyxecm/otds.py +3166 -2219
- pyxecm/otiv.py +36 -21
- pyxecm/otmm.py +1363 -296
- pyxecm/otpd.py +231 -127
- pyxecm-2.0.0.dist-info/METADATA +145 -0
- pyxecm-2.0.0.dist-info/RECORD +54 -0
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info}/WHEEL +1 -1
- pyxecm-1.5.dist-info/METADATA +0 -51
- pyxecm-1.5.dist-info/RECORD +0 -30
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info/licenses}/LICENSE +0 -0
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info}/top_level.txt +0 -0
pyxecm/coreshare.py
CHANGED
|
@@ -1,92 +1,69 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
See:
|
|
1
|
+
"""CoreShare Module to interact with the Core Share API.
|
|
2
|
+
|
|
3
|
+
See:
|
|
4
|
+
- [Confluence](https://confluence.opentext.com/pages/viewpage.action?spaceKey=OTC&title=APIs+Consumption+based+on+roles)
|
|
5
|
+
- [swagger.otxlab.net](https://swagger.otxlab.net/ui/?branch=master&yaml=application-specific/core/core-api.yaml)
|
|
4
6
|
|
|
5
7
|
Authentication - get Client Secrets:
|
|
6
|
-
1. Login to Core Share as a Tenant Admin User
|
|
7
|
-
2. Navigate to Security
|
|
8
|
-
3. On OAuth Confidential Clients section provide Description and Redirect URLs. It will populate a
|
|
9
|
-
dialog with Client Secret.
|
|
10
|
-
4. Copy Client Secret as it will not be available anywhere once the dialog is closed.
|
|
11
|
-
|
|
12
|
-
Class: CoreShare
|
|
13
|
-
Methods:
|
|
14
|
-
|
|
15
|
-
__init__ : class initializer
|
|
16
|
-
config : Returns config data set
|
|
17
|
-
credentials: Get credentials (username + password)
|
|
18
|
-
set_credentials: Set the credentials for Core Share based on username and password.
|
|
19
|
-
request_header: Returns the request header for Core Share API calls
|
|
20
|
-
parse_request_response: Parse the REST API responses and convert
|
|
21
|
-
them to Python dict in a safe way
|
|
22
|
-
lookup_result_value: Lookup a property value based on a provided key / value pair in the response
|
|
23
|
-
properties of a Core Share REST API call
|
|
24
|
-
exist_result_item: Check if an dict item is in the response
|
|
25
|
-
of the Core Share API call
|
|
26
|
-
get_result_value: Check if a defined value (based on a key) is in the Core Share API response
|
|
27
|
-
|
|
28
|
-
authenticate_admin : Authenticates as Admin at Core Share API
|
|
29
|
-
authenticate_user : Authenticates as Service user at Core Share API
|
|
30
|
-
|
|
31
|
-
get_groups: Get Core Share groups.
|
|
32
|
-
add_group: Add a new Core Share group.
|
|
33
|
-
get_group_members: Get Core Share group members.
|
|
34
|
-
add_group_member: Add a Core Share user to a Cire Share group.
|
|
35
|
-
remove_group_member: Remove a Core Share user from a Core Share group.
|
|
36
|
-
get_group_by_id: Get a Core Share group by its ID.
|
|
37
|
-
get_group_by_name: Get Core Share group by its name.
|
|
38
|
-
search_groups: Search Core Share group(s) by name.
|
|
39
|
-
|
|
40
|
-
get_users: Get Core Share users.
|
|
41
|
-
get_user_by_id: Get a Core Share user by its ID.
|
|
42
|
-
get_user_by_name: Get Core Share user by its first and last name.
|
|
43
|
-
search_users: Search Core Share user(s) by name / property.
|
|
44
|
-
add_user: Add a new Core Share user. This requires a Tenent Admin authorization.
|
|
45
|
-
resend_user_invite: Resend the invite for a Core Share user.
|
|
46
|
-
update_user: Update a Core Share user.
|
|
47
|
-
add_user_access_role: Add an access role to a Core Share user.
|
|
48
|
-
remove_user_access_role: Remove an access role from a Core Share user.
|
|
49
|
-
update_user_access_roles: Define the access roles of a Core Share user.
|
|
50
|
-
update_user_password: Update the password of a Core Share user.
|
|
51
|
-
update_user_photo: Update the Core Share user photo.
|
|
52
|
-
|
|
53
|
-
get_folders: Get Core Share folders under a given parent ID.
|
|
54
|
-
unshare_folder: Unshare Core Share folder with a given resource ID.
|
|
55
|
-
delete_folder: Delete Core Share folder with a given resource ID.
|
|
56
|
-
delete_document: Delete Core Share document with a given resource ID.
|
|
57
|
-
leave_share: Remove a Core Share user from a share (i.e. the user leaves the share)
|
|
58
|
-
stop_share: Stop of share of a user.
|
|
59
|
-
cleanup_user_files: Cleanup all files of a user. This handles different types of resources.
|
|
60
|
-
get_group_shares: Get (incoming) shares of a Core Share group.
|
|
61
|
-
revoke_group_share: Revoke sharing of a folder with a group.
|
|
62
|
-
cleanup_group_shares: Cleanup all incoming shares of a group.
|
|
8
|
+
1. Login to Core Share as a Tenant Admin User.
|
|
9
|
+
2. Navigate to Security Page.
|
|
10
|
+
3. On OAuth Confidential Clients section provide Description and Redirect URLs. It will populate a
|
|
11
|
+
dialog with Client Secret.
|
|
12
|
+
4. Copy Client Secret as it will not be available anywhere once the dialog is closed.
|
|
63
13
|
"""
|
|
64
14
|
|
|
65
15
|
__author__ = "Dr. Marc Diefenbruch"
|
|
66
|
-
__copyright__ = "Copyright 2024, OpenText"
|
|
16
|
+
__copyright__ = "Copyright (C) 2024-2025, OpenText"
|
|
67
17
|
__credits__ = ["Kai-Philip Gatzweiler"]
|
|
68
18
|
__maintainer__ = "Dr. Marc Diefenbruch"
|
|
69
19
|
__email__ = "mdiefenb@opentext.com"
|
|
70
20
|
|
|
71
|
-
import os
|
|
72
21
|
import json
|
|
73
22
|
import logging
|
|
23
|
+
import os
|
|
24
|
+
import platform
|
|
25
|
+
import sys
|
|
26
|
+
import time
|
|
74
27
|
import urllib.parse
|
|
28
|
+
from http import HTTPStatus
|
|
29
|
+
from importlib.metadata import version
|
|
75
30
|
|
|
76
31
|
import requests
|
|
77
32
|
|
|
78
|
-
|
|
33
|
+
APP_NAME = "pyxecm"
|
|
34
|
+
APP_VERSION = version("pyxecm")
|
|
35
|
+
MODULE_NAME = APP_NAME + ".coreshare"
|
|
36
|
+
|
|
37
|
+
PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
38
|
+
OS_INFO = f"{platform.system()} {platform.release()}"
|
|
39
|
+
ARCH_INFO = platform.machine()
|
|
40
|
+
REQUESTS_VERSION = requests.__version__
|
|
41
|
+
|
|
42
|
+
USER_AGENT = (
|
|
43
|
+
f"{APP_NAME}/{APP_VERSION} ({MODULE_NAME}/{APP_VERSION}; "
|
|
44
|
+
f"Python/{PYTHON_VERSION}; {OS_INFO}; {ARCH_INFO}; Requests/{REQUESTS_VERSION})"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
default_logger = logging.getLogger(MODULE_NAME)
|
|
79
48
|
|
|
80
49
|
REQUEST_LOGIN_HEADERS = {
|
|
50
|
+
"User-Agent": USER_AGENT,
|
|
81
51
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
82
52
|
"Accept": "application/json",
|
|
83
53
|
}
|
|
84
54
|
|
|
85
55
|
REQUEST_TIMEOUT = 60
|
|
56
|
+
REQUEST_RETRY_DELAY = 20
|
|
57
|
+
REQUEST_MAX_RETRIES = 2
|
|
86
58
|
|
|
59
|
+
CONTENT_MANAGER_ROLE_ID = 5
|
|
60
|
+
GROUP_ADMIN_ROLE_ID = 3
|
|
87
61
|
|
|
88
|
-
|
|
89
|
-
|
|
62
|
+
|
|
63
|
+
class CoreShare:
|
|
64
|
+
"""Class CoreShare is used to retrieve and automate settings and objects (users, groups) in Core Share."""
|
|
65
|
+
|
|
66
|
+
logger: logging.Logger = default_logger
|
|
90
67
|
|
|
91
68
|
_config: dict
|
|
92
69
|
_access_token_user = None
|
|
@@ -100,17 +77,31 @@ class CoreShare(object):
|
|
|
100
77
|
client_secret: str,
|
|
101
78
|
username: str,
|
|
102
79
|
password: str,
|
|
103
|
-
|
|
104
|
-
|
|
80
|
+
logger: logging.Logger = default_logger,
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Initialize the CoreShare object.
|
|
105
83
|
|
|
106
84
|
Args:
|
|
107
|
-
base_url (str):
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
85
|
+
base_url (str):
|
|
86
|
+
The base URL of the Core Share tenant.
|
|
87
|
+
sso_url (str):
|
|
88
|
+
The single sign on URL of the Core Share tenant.
|
|
89
|
+
client_id (str):
|
|
90
|
+
The Core Share Client ID.
|
|
91
|
+
client_secret (str):
|
|
92
|
+
The Core Share client secret.
|
|
93
|
+
username (str):
|
|
94
|
+
The admin user name in Core Share.
|
|
95
|
+
password (str):
|
|
96
|
+
The admin password in Core Share.
|
|
97
|
+
logger (logging.Logger, optional):
|
|
98
|
+
The logging object to use for all log messages. Defaults to default_logger.
|
|
99
|
+
|
|
113
100
|
"""
|
|
101
|
+
if logger != default_logger:
|
|
102
|
+
self.logger = logger.getChild("coreshare")
|
|
103
|
+
for logfilter in logger.filters:
|
|
104
|
+
self.logger.addFilter(logfilter)
|
|
114
105
|
|
|
115
106
|
core_share_config = {}
|
|
116
107
|
|
|
@@ -131,22 +122,14 @@ class CoreShare(object):
|
|
|
131
122
|
core_share_config["invitesUrl"] = core_share_config["restUrlv1"] + "/invites"
|
|
132
123
|
core_share_config["foldersUrlv1"] = core_share_config["restUrlv1"] + "/folders"
|
|
133
124
|
core_share_config["foldersUrlv3"] = core_share_config["restUrlv3"] + "/folders"
|
|
134
|
-
core_share_config["documentsUrlv1"] =
|
|
135
|
-
|
|
136
|
-
)
|
|
137
|
-
core_share_config["documentsUrlv3"] = (
|
|
138
|
-
core_share_config["restUrlv3"] + "/documents"
|
|
139
|
-
)
|
|
125
|
+
core_share_config["documentsUrlv1"] = core_share_config["restUrlv1"] + "/documents"
|
|
126
|
+
core_share_config["documentsUrlv3"] = core_share_config["restUrlv3"] + "/documents"
|
|
140
127
|
core_share_config["searchUrl"] = core_share_config["baseUrl"] + "/search/v1"
|
|
141
128
|
core_share_config["searchUserUrl"] = core_share_config["searchUrl"] + "/user"
|
|
142
|
-
core_share_config["searchGroupUrl"] =
|
|
143
|
-
core_share_config["searchUrl"] + "/user/group-all"
|
|
144
|
-
)
|
|
129
|
+
core_share_config["searchGroupUrl"] = core_share_config["searchUrl"] + "/user/group-all"
|
|
145
130
|
|
|
146
131
|
core_share_config["sessionsUrl"] = core_share_config["restUrlv1"] + "/sessions"
|
|
147
|
-
core_share_config["tokenUrl"] =
|
|
148
|
-
core_share_config["ssoUrl"] + "/otdsws/oauth2/token"
|
|
149
|
-
)
|
|
132
|
+
core_share_config["tokenUrl"] = core_share_config["ssoUrl"] + "/otdsws/oauth2/token"
|
|
150
133
|
core_share_config["sessionsUrl"] = core_share_config["restUrlv1"] + "/sessions"
|
|
151
134
|
|
|
152
135
|
# Tenant Admin User Authentication information (Session URL):
|
|
@@ -186,21 +169,27 @@ class CoreShare(object):
|
|
|
186
169
|
# end method definition
|
|
187
170
|
|
|
188
171
|
def config(self) -> dict:
|
|
189
|
-
"""
|
|
172
|
+
"""Return the configuration dictionary.
|
|
190
173
|
|
|
191
174
|
Returns:
|
|
192
|
-
dict:
|
|
175
|
+
dict:
|
|
176
|
+
The configuration dictionary.
|
|
177
|
+
|
|
193
178
|
"""
|
|
179
|
+
|
|
194
180
|
return self._config
|
|
195
181
|
|
|
196
182
|
# end method definition
|
|
197
183
|
|
|
198
184
|
def credentials(self) -> dict:
|
|
199
|
-
"""Get credentials (username + password)
|
|
185
|
+
"""Get credentials (username + password).
|
|
200
186
|
|
|
201
187
|
Returns:
|
|
202
|
-
dict:
|
|
188
|
+
dict:
|
|
189
|
+
A dictionary with username and password.
|
|
190
|
+
|
|
203
191
|
"""
|
|
192
|
+
|
|
204
193
|
return {
|
|
205
194
|
"username": self.config()["username"],
|
|
206
195
|
"password": self.config()["password"],
|
|
@@ -208,15 +197,16 @@ class CoreShare(object):
|
|
|
208
197
|
|
|
209
198
|
# end method definition
|
|
210
199
|
|
|
211
|
-
def set_credentials(self, username: str = "admin", password: str = ""):
|
|
200
|
+
def set_credentials(self, username: str = "admin", password: str = "") -> None:
|
|
212
201
|
"""Set the credentials for Core Share based on username and password.
|
|
213
202
|
|
|
214
203
|
Args:
|
|
215
204
|
username (str, optional): Username. Defaults to "admin".
|
|
216
205
|
password (str, optional): Password of the user. Defaults to "".
|
|
206
|
+
|
|
217
207
|
"""
|
|
218
208
|
|
|
219
|
-
logger.info("Change Core Share credentials to user -> %s...", username)
|
|
209
|
+
self.logger.info("Change Core Share credentials to user -> %s...", username)
|
|
220
210
|
|
|
221
211
|
self.config()["username"] = username
|
|
222
212
|
self.config()["password"] = password
|
|
@@ -248,16 +238,27 @@ class CoreShare(object):
|
|
|
248
238
|
# end method definition
|
|
249
239
|
|
|
250
240
|
def request_header_admin(self, content_type: str = "application/json") -> dict:
|
|
251
|
-
"""
|
|
252
|
-
|
|
241
|
+
"""Return the request header used for application calls that require administrator credentials.
|
|
242
|
+
|
|
243
|
+
Consists of Bearer access token and Content Type
|
|
253
244
|
|
|
254
245
|
Args:
|
|
255
|
-
content_type (str, optional):
|
|
246
|
+
content_type (str, optional):
|
|
247
|
+
Custom content type for the request.
|
|
248
|
+
Typical values:
|
|
249
|
+
* application/json - Used for sending JSON-encoded data
|
|
250
|
+
* application/x-www-form-urlencoded - The default for HTML forms.
|
|
251
|
+
Data is sent as key-value pairs in the body of the request, similar to query parameters.
|
|
252
|
+
* multipart/form-data - Used for file uploads or when a form includes non-ASCII characters
|
|
253
|
+
|
|
256
254
|
Return:
|
|
257
|
-
dict:
|
|
255
|
+
dict:
|
|
256
|
+
The request header values.
|
|
257
|
+
|
|
258
258
|
"""
|
|
259
259
|
|
|
260
260
|
request_header = {
|
|
261
|
+
"User-Agent": USER_AGENT,
|
|
261
262
|
"Authorization": "Bearer {}".format(self._access_token_admin),
|
|
262
263
|
}
|
|
263
264
|
if content_type:
|
|
@@ -268,16 +269,22 @@ class CoreShare(object):
|
|
|
268
269
|
# end method definition
|
|
269
270
|
|
|
270
271
|
def request_header_user(self, content_type: str = "application/json") -> dict:
|
|
271
|
-
"""
|
|
272
|
-
|
|
272
|
+
"""Return the request header used for Application calls that require user (non-admin) credentials.
|
|
273
|
+
|
|
274
|
+
Consists of Bearer access token and Content Type
|
|
273
275
|
|
|
274
276
|
Args:
|
|
275
|
-
content_type (str, optional):
|
|
277
|
+
content_type (str, optional):
|
|
278
|
+
The content type for the request.
|
|
279
|
+
|
|
276
280
|
Return:
|
|
277
|
-
dict:
|
|
281
|
+
dict:
|
|
282
|
+
The request header values.
|
|
283
|
+
|
|
278
284
|
"""
|
|
279
285
|
|
|
280
286
|
request_header = {
|
|
287
|
+
"User-Agent": USER_AGENT,
|
|
281
288
|
"Authorization": "Bearer {}".format(self._access_token_user),
|
|
282
289
|
}
|
|
283
290
|
if content_type:
|
|
@@ -287,49 +294,261 @@ class CoreShare(object):
|
|
|
287
294
|
|
|
288
295
|
# end method definition
|
|
289
296
|
|
|
297
|
+
def do_request(
|
|
298
|
+
self,
|
|
299
|
+
url: str,
|
|
300
|
+
method: str = "GET",
|
|
301
|
+
headers: dict | None = None,
|
|
302
|
+
data: dict | None = None,
|
|
303
|
+
json_data: dict | None = None,
|
|
304
|
+
files: dict | None = None,
|
|
305
|
+
timeout: int | None = REQUEST_TIMEOUT,
|
|
306
|
+
show_error: bool = True,
|
|
307
|
+
show_warning: bool = False,
|
|
308
|
+
warning_message: str = "",
|
|
309
|
+
failure_message: str = "",
|
|
310
|
+
success_message: str = "",
|
|
311
|
+
max_retries: int = REQUEST_MAX_RETRIES,
|
|
312
|
+
retry_forever: bool = False,
|
|
313
|
+
parse_request_response: bool = True,
|
|
314
|
+
user_credentials: bool = False,
|
|
315
|
+
verify: bool = True,
|
|
316
|
+
) -> dict | None:
|
|
317
|
+
"""Call an OTDS REST API in a safe way.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
url (str):
|
|
321
|
+
The URL to send the request to.
|
|
322
|
+
method (str, optional):
|
|
323
|
+
HTTP method (GET, POST, etc.). Defaults to "GET".
|
|
324
|
+
headers (dict | None, optional):
|
|
325
|
+
Request Headers. Defaults to None.
|
|
326
|
+
data (dict | None, optional):
|
|
327
|
+
Request payload. Defaults to None
|
|
328
|
+
json_data (dict | None, optional):
|
|
329
|
+
Request payload for the JSON parameter. Defaults to None.
|
|
330
|
+
files (dict | None, optional):
|
|
331
|
+
Dictionary of {"name": file-tuple} for multipart encoding upload.
|
|
332
|
+
The file-tuple can be a 2-tuple ("filename", fileobj) or a 3-tuple ("filename", fileobj, "content_type")
|
|
333
|
+
timeout (int | None, optional):
|
|
334
|
+
Timeout for the request in seconds. Defaults to REQUEST_TIMEOUT.
|
|
335
|
+
show_error (bool, optional):
|
|
336
|
+
Whether or not an error should be logged in case of a failed REST call.
|
|
337
|
+
If False, then only a warning is logged. Defaults to True.
|
|
338
|
+
show_warning (bool, optional):
|
|
339
|
+
Whether or not an warning should be logged in case of a
|
|
340
|
+
failed REST call.
|
|
341
|
+
If False, then only a warning is logged. Defaults to True.
|
|
342
|
+
warning_message (str, optional):
|
|
343
|
+
Specific warning message. Defaults to "". If not given the error_message will be used.
|
|
344
|
+
failure_message (str, optional):
|
|
345
|
+
Specific error message. Defaults to "".
|
|
346
|
+
success_message (str, optional):
|
|
347
|
+
Specific success message. Defaults to "".
|
|
348
|
+
max_retries (int, optional):
|
|
349
|
+
How many retries on Connection errors? Default is REQUEST_MAX_RETRIES.
|
|
350
|
+
retry_forever (bool, optional):
|
|
351
|
+
Eventually wait forever - without timeout. Defaults to False.
|
|
352
|
+
parse_request_response (bool, optional):
|
|
353
|
+
If True the response.text will be interpreted as json and loaded into a dictionary.
|
|
354
|
+
True is the default.
|
|
355
|
+
user_credentials (bool, optional):
|
|
356
|
+
Defines if admin or user credentials are used for the REST API call.
|
|
357
|
+
Default = False = admin credentials
|
|
358
|
+
verify (bool, optional):
|
|
359
|
+
Specify whether or not SSL certificates should be verified when making an HTTPS request.
|
|
360
|
+
Default = True
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
dict | None:
|
|
364
|
+
Response of OTDS REST API or None in case of an error.
|
|
365
|
+
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
if headers is None:
|
|
369
|
+
self.logger.error(
|
|
370
|
+
"Missing request header. Cannot send request to Core Share!",
|
|
371
|
+
)
|
|
372
|
+
return None
|
|
373
|
+
|
|
374
|
+
# In case of an expired session we reauthenticate and
|
|
375
|
+
# try 1 more time. Session expiration should not happen
|
|
376
|
+
# twice in a row:
|
|
377
|
+
retries = 0
|
|
378
|
+
|
|
379
|
+
while True:
|
|
380
|
+
try:
|
|
381
|
+
response = requests.request(
|
|
382
|
+
method=method,
|
|
383
|
+
url=url,
|
|
384
|
+
data=data,
|
|
385
|
+
json=json_data,
|
|
386
|
+
files=files,
|
|
387
|
+
headers=headers,
|
|
388
|
+
timeout=timeout,
|
|
389
|
+
verify=verify,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
if response.ok:
|
|
393
|
+
if success_message:
|
|
394
|
+
self.logger.info(success_message)
|
|
395
|
+
if parse_request_response:
|
|
396
|
+
return self.parse_request_response(response)
|
|
397
|
+
else:
|
|
398
|
+
return response
|
|
399
|
+
# Check if Session has expired - then re-authenticate and try once more
|
|
400
|
+
elif response.status_code == 401 and retries == 0:
|
|
401
|
+
if user_credentials:
|
|
402
|
+
self.logger.debug(
|
|
403
|
+
"User session has expired - try to re-authenticate...",
|
|
404
|
+
)
|
|
405
|
+
self.authenticate_user(revalidate=True)
|
|
406
|
+
# Make sure to not change the content type:
|
|
407
|
+
headers = self.request_header_user(
|
|
408
|
+
content_type=headers.get("Content-Type", None),
|
|
409
|
+
)
|
|
410
|
+
else:
|
|
411
|
+
self.logger.warning(
|
|
412
|
+
"Admin session has expired - try to re-authenticate...",
|
|
413
|
+
)
|
|
414
|
+
self.authenticate_admin(revalidate=True)
|
|
415
|
+
# Make sure to not change the content type:
|
|
416
|
+
headers = self.request_header_admin(
|
|
417
|
+
content_type=headers.get("Content-Type", None),
|
|
418
|
+
)
|
|
419
|
+
retries += 1
|
|
420
|
+
else:
|
|
421
|
+
# Handle plain HTML responses to not pollute the logs
|
|
422
|
+
content_type = response.headers.get("content-type", None)
|
|
423
|
+
if content_type == "text/html":
|
|
424
|
+
response_text = "HTML content (only printed in debug log)"
|
|
425
|
+
elif "image" in content_type:
|
|
426
|
+
response_text = "Image content (not printed)"
|
|
427
|
+
else:
|
|
428
|
+
response_text = response.text
|
|
429
|
+
|
|
430
|
+
if show_error:
|
|
431
|
+
self.logger.error(
|
|
432
|
+
"%s; status -> %s/%s; error -> %s",
|
|
433
|
+
failure_message,
|
|
434
|
+
response.status_code,
|
|
435
|
+
HTTPStatus(response.status_code).phrase,
|
|
436
|
+
response_text,
|
|
437
|
+
)
|
|
438
|
+
elif show_warning:
|
|
439
|
+
self.logger.warning(
|
|
440
|
+
"%s; status -> %s/%s; warning -> %s",
|
|
441
|
+
warning_message if warning_message else failure_message,
|
|
442
|
+
response.status_code,
|
|
443
|
+
HTTPStatus(response.status_code).phrase,
|
|
444
|
+
response_text,
|
|
445
|
+
)
|
|
446
|
+
if content_type == "text/html":
|
|
447
|
+
self.logger.debug(
|
|
448
|
+
"%s; status -> %s/%s; warning -> %s",
|
|
449
|
+
failure_message,
|
|
450
|
+
response.status_code,
|
|
451
|
+
HTTPStatus(response.status_code).phrase,
|
|
452
|
+
response.text,
|
|
453
|
+
)
|
|
454
|
+
return None
|
|
455
|
+
except requests.exceptions.Timeout:
|
|
456
|
+
if retries <= max_retries:
|
|
457
|
+
self.logger.warning(
|
|
458
|
+
"Request timed out. Retrying in %s seconds...",
|
|
459
|
+
str(REQUEST_RETRY_DELAY),
|
|
460
|
+
)
|
|
461
|
+
retries += 1
|
|
462
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
463
|
+
else:
|
|
464
|
+
self.logger.error(
|
|
465
|
+
"%s; timeout error.",
|
|
466
|
+
failure_message,
|
|
467
|
+
)
|
|
468
|
+
if retry_forever:
|
|
469
|
+
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
470
|
+
self.logger.warning("Turn timeouts off and wait forever...")
|
|
471
|
+
timeout = None
|
|
472
|
+
else:
|
|
473
|
+
return None
|
|
474
|
+
except requests.exceptions.ConnectionError:
|
|
475
|
+
if retries <= max_retries:
|
|
476
|
+
self.logger.warning(
|
|
477
|
+
"Connection error. Retrying in %s seconds...",
|
|
478
|
+
str(REQUEST_RETRY_DELAY),
|
|
479
|
+
)
|
|
480
|
+
retries += 1
|
|
481
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
482
|
+
else:
|
|
483
|
+
self.logger.error(
|
|
484
|
+
"%s; connection error.",
|
|
485
|
+
failure_message,
|
|
486
|
+
)
|
|
487
|
+
if retry_forever:
|
|
488
|
+
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
489
|
+
self.logger.warning("Turn timeouts off and wait forever...")
|
|
490
|
+
timeout = None
|
|
491
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
492
|
+
else:
|
|
493
|
+
return None
|
|
494
|
+
# end try
|
|
495
|
+
self.logger.debug(
|
|
496
|
+
"Retrying REST API %s call -> %s... (retry = %s)",
|
|
497
|
+
method,
|
|
498
|
+
url,
|
|
499
|
+
str(retries),
|
|
500
|
+
)
|
|
501
|
+
# end while True
|
|
502
|
+
|
|
503
|
+
# end method definition
|
|
504
|
+
|
|
290
505
|
def parse_request_response(
|
|
291
506
|
self,
|
|
292
507
|
response_object: requests.Response,
|
|
293
508
|
additional_error_message: str = "",
|
|
294
509
|
show_error: bool = True,
|
|
295
510
|
) -> dict | None:
|
|
296
|
-
"""
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
511
|
+
"""Convert the request response to a dict in a safe way.
|
|
512
|
+
|
|
513
|
+
This also handles exceptions. It first tries to load the response.text
|
|
514
|
+
via json.loads() that produces a dict output. Only if response.text is
|
|
515
|
+
not set or is empty it just converts the response_object to a dict using
|
|
516
|
+
the vars() built-in method.
|
|
301
517
|
|
|
302
518
|
Args:
|
|
303
|
-
response_object (object):
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
519
|
+
response_object (object):
|
|
520
|
+
This is reponse object returned by the request call.
|
|
521
|
+
additional_error_message (str, optional):
|
|
522
|
+
Can be used to provide a more specific error message
|
|
523
|
+
in case an error occurs.
|
|
524
|
+
show_error (bool, optional):
|
|
525
|
+
True: write an error to the log file
|
|
526
|
+
False: write a warning to the log file
|
|
527
|
+
|
|
308
528
|
Returns:
|
|
309
529
|
dict: response information or None in case of an error
|
|
530
|
+
|
|
310
531
|
"""
|
|
311
532
|
|
|
312
533
|
if not response_object:
|
|
313
534
|
return None
|
|
314
535
|
|
|
315
536
|
try:
|
|
316
|
-
if response_object.text
|
|
317
|
-
dict_object = json.loads(response_object.text)
|
|
318
|
-
else:
|
|
319
|
-
dict_object = vars(response_object)
|
|
537
|
+
dict_object = json.loads(response_object.text) if response_object.text else vars(response_object)
|
|
320
538
|
except json.JSONDecodeError as exception:
|
|
321
539
|
if additional_error_message:
|
|
322
540
|
message = "Cannot decode response as JSon. {}; error -> {}".format(
|
|
323
|
-
additional_error_message,
|
|
541
|
+
additional_error_message,
|
|
542
|
+
exception,
|
|
324
543
|
)
|
|
325
544
|
else:
|
|
326
545
|
message = "Cannot decode response as JSon; error -> {}".format(
|
|
327
|
-
exception
|
|
546
|
+
exception,
|
|
328
547
|
)
|
|
329
548
|
if show_error:
|
|
330
|
-
logger.error(message)
|
|
549
|
+
self.logger.error(message)
|
|
331
550
|
else:
|
|
332
|
-
logger.warning(message)
|
|
551
|
+
self.logger.warning(message)
|
|
333
552
|
return None
|
|
334
553
|
else:
|
|
335
554
|
return dict_object
|
|
@@ -337,24 +556,34 @@ class CoreShare(object):
|
|
|
337
556
|
# end method definition
|
|
338
557
|
|
|
339
558
|
def lookup_result_value(
|
|
340
|
-
self,
|
|
559
|
+
self,
|
|
560
|
+
response: dict,
|
|
561
|
+
key: str,
|
|
562
|
+
value: str,
|
|
563
|
+
return_key: str,
|
|
341
564
|
) -> str | None:
|
|
342
|
-
"""Lookup a property value based on a provided key / value pair in the
|
|
343
|
-
response properties of an Extended ECM REST API call.
|
|
565
|
+
"""Lookup a property value based on a provided key / value pair in the response of an Core Share REST API call.
|
|
344
566
|
|
|
345
567
|
Args:
|
|
346
|
-
response (dict):
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
568
|
+
response (dict):
|
|
569
|
+
REST response from an Core Share REST Call
|
|
570
|
+
key (str):
|
|
571
|
+
The property name (key).
|
|
572
|
+
value (str):
|
|
573
|
+
The value to find in the item with the matching key.
|
|
574
|
+
return_key (str):
|
|
575
|
+
Determines which value to return based on the name of the dict key.
|
|
576
|
+
|
|
350
577
|
Returns:
|
|
351
|
-
str
|
|
352
|
-
|
|
578
|
+
str | None:
|
|
579
|
+
The value of the property with the key defined in "return_key"
|
|
580
|
+
or None if the lookup fails.
|
|
581
|
+
|
|
353
582
|
"""
|
|
354
583
|
|
|
355
584
|
if not response:
|
|
356
585
|
return None
|
|
357
|
-
if
|
|
586
|
+
if "results" not in response:
|
|
358
587
|
return None
|
|
359
588
|
|
|
360
589
|
results = response["results"]
|
|
@@ -370,16 +599,28 @@ class CoreShare(object):
|
|
|
370
599
|
# end method definition
|
|
371
600
|
|
|
372
601
|
def exist_result_item(
|
|
373
|
-
self,
|
|
602
|
+
self,
|
|
603
|
+
response: dict,
|
|
604
|
+
key: str,
|
|
605
|
+
value: str,
|
|
606
|
+
results_marker: str = "results",
|
|
374
607
|
) -> bool:
|
|
375
608
|
"""Check existence of key / value pair in the response properties of a Core Share API call.
|
|
376
609
|
|
|
377
610
|
Args:
|
|
378
|
-
response (dict):
|
|
379
|
-
|
|
380
|
-
|
|
611
|
+
response (dict):
|
|
612
|
+
REST response from a Core Share API call
|
|
613
|
+
key (str):
|
|
614
|
+
A property name (key)
|
|
615
|
+
value (str):
|
|
616
|
+
The value to find in the item with the matching key.
|
|
617
|
+
results_marker (str, optional):
|
|
618
|
+
The name of the data structure for the results.
|
|
619
|
+
|
|
381
620
|
Returns:
|
|
382
|
-
bool:
|
|
621
|
+
bool:
|
|
622
|
+
True, if the value was found, False otherwise.
|
|
623
|
+
|
|
383
624
|
"""
|
|
384
625
|
|
|
385
626
|
if not response:
|
|
@@ -394,7 +635,7 @@ class CoreShare(object):
|
|
|
394
635
|
if value == result[key]:
|
|
395
636
|
return True
|
|
396
637
|
else:
|
|
397
|
-
if not
|
|
638
|
+
if key not in response:
|
|
398
639
|
return False
|
|
399
640
|
if value == response[key]:
|
|
400
641
|
return True
|
|
@@ -412,12 +653,18 @@ class CoreShare(object):
|
|
|
412
653
|
"""Get value of a result property with a given key of a Core Share API call.
|
|
413
654
|
|
|
414
655
|
Args:
|
|
415
|
-
response (dict or list):
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
656
|
+
response (dict or list):
|
|
657
|
+
REST response from a Core Share REST Call
|
|
658
|
+
key (str):
|
|
659
|
+
The property name (key).
|
|
660
|
+
index (int, optional):
|
|
661
|
+
Index to use (1st element has index 0).
|
|
662
|
+
Defaults to 0.
|
|
663
|
+
|
|
419
664
|
Returns:
|
|
420
|
-
str:
|
|
665
|
+
str:
|
|
666
|
+
The value for the key, None in case of an error.
|
|
667
|
+
|
|
421
668
|
"""
|
|
422
669
|
|
|
423
670
|
if not response:
|
|
@@ -427,7 +674,7 @@ class CoreShare(object):
|
|
|
427
674
|
if isinstance(response, list):
|
|
428
675
|
if len(response) - 1 < index:
|
|
429
676
|
return None
|
|
430
|
-
if not
|
|
677
|
+
if key not in response[index]:
|
|
431
678
|
return None
|
|
432
679
|
value = response[index][key]
|
|
433
680
|
return value
|
|
@@ -437,17 +684,13 @@ class CoreShare(object):
|
|
|
437
684
|
if "results" in response:
|
|
438
685
|
# we expect results to be a list!
|
|
439
686
|
values = response["results"]
|
|
440
|
-
if (
|
|
441
|
-
not values
|
|
442
|
-
or not isinstance(values, list)
|
|
443
|
-
or len(values) - 1 < index
|
|
444
|
-
):
|
|
687
|
+
if not values or not isinstance(values, list) or len(values) - 1 < index:
|
|
445
688
|
return None
|
|
446
|
-
if not
|
|
689
|
+
if key not in values[index]:
|
|
447
690
|
return None
|
|
448
691
|
value = values[index][key]
|
|
449
692
|
else: # simple response as dictionary - try to find key in response directly:
|
|
450
|
-
if not
|
|
693
|
+
if key not in response:
|
|
451
694
|
return None
|
|
452
695
|
value = response[key]
|
|
453
696
|
|
|
@@ -464,15 +707,20 @@ class CoreShare(object):
|
|
|
464
707
|
"""Authenticate at Core Share as Tenant Admin.
|
|
465
708
|
|
|
466
709
|
Args:
|
|
467
|
-
revalidate (bool, optional):
|
|
468
|
-
|
|
710
|
+
revalidate (bool, optional):
|
|
711
|
+
Defines whether or not a re-athentication is enforced
|
|
712
|
+
(e.g. if session has timed out with 401 error).
|
|
713
|
+
|
|
469
714
|
Returns:
|
|
470
|
-
str:
|
|
715
|
+
str:
|
|
716
|
+
The access token. Also stores access token in self._access_token.
|
|
717
|
+
None in case of error.
|
|
718
|
+
|
|
471
719
|
"""
|
|
472
720
|
|
|
473
721
|
# Already authenticated and session still valid?
|
|
474
722
|
if self._access_token_admin and not revalidate:
|
|
475
|
-
logger.debug(
|
|
723
|
+
self.logger.debug(
|
|
476
724
|
"Session still valid - return existing access token -> %s",
|
|
477
725
|
str(self._access_token_admin),
|
|
478
726
|
)
|
|
@@ -482,7 +730,10 @@ class CoreShare(object):
|
|
|
482
730
|
|
|
483
731
|
request_header = REQUEST_LOGIN_HEADERS
|
|
484
732
|
|
|
485
|
-
logger.debug(
|
|
733
|
+
self.logger.debug(
|
|
734
|
+
"Requesting Core Share Admin Access Token from -> %s",
|
|
735
|
+
request_url,
|
|
736
|
+
)
|
|
486
737
|
|
|
487
738
|
response = None
|
|
488
739
|
self._access_token_admin = None
|
|
@@ -494,7 +745,7 @@ class CoreShare(object):
|
|
|
494
745
|
timeout=REQUEST_TIMEOUT,
|
|
495
746
|
)
|
|
496
747
|
except requests.exceptions.ConnectionError as exception:
|
|
497
|
-
logger.warning(
|
|
748
|
+
self.logger.warning(
|
|
498
749
|
"Unable to connect to -> %s : %s",
|
|
499
750
|
request_url,
|
|
500
751
|
exception,
|
|
@@ -517,13 +768,14 @@ class CoreShare(object):
|
|
|
517
768
|
|
|
518
769
|
# Store authentication access_token:
|
|
519
770
|
self._access_token_admin = access_token
|
|
520
|
-
logger.debug(
|
|
521
|
-
"Tenant Admin Access Token -> %s",
|
|
771
|
+
self.logger.debug(
|
|
772
|
+
"Tenant Admin Access Token -> %s",
|
|
773
|
+
self._access_token_admin,
|
|
522
774
|
)
|
|
523
775
|
else:
|
|
524
776
|
return None
|
|
525
777
|
else:
|
|
526
|
-
logger.error(
|
|
778
|
+
self.logger.error(
|
|
527
779
|
"Failed to request a Core Share Tenant Admin Access Token; error -> %s",
|
|
528
780
|
response.text,
|
|
529
781
|
)
|
|
@@ -534,37 +786,38 @@ class CoreShare(object):
|
|
|
534
786
|
# end method definition
|
|
535
787
|
|
|
536
788
|
def authenticate_user(
|
|
537
|
-
self,
|
|
789
|
+
self,
|
|
790
|
+
revalidate: bool = False,
|
|
791
|
+
grant_type: str = "password",
|
|
538
792
|
) -> str | None:
|
|
539
793
|
"""Authenticate at Core Share as Tenant Service User (TSU) with client ID and client secret.
|
|
540
794
|
|
|
541
795
|
Args:
|
|
542
|
-
revalidate (bool, optional):
|
|
543
|
-
|
|
544
|
-
|
|
796
|
+
revalidate (bool, optional):
|
|
797
|
+
Defines whether or not a re-athentication is enforced
|
|
798
|
+
(e.g. if session has timed out with 401 error).
|
|
799
|
+
grant_type (str, optional):
|
|
800
|
+
Can either be "client_credentials" (default) or "password".
|
|
801
|
+
|
|
545
802
|
Returns:
|
|
546
|
-
str:
|
|
803
|
+
str:
|
|
804
|
+
The access token. Also stores access token in self._access_token.
|
|
805
|
+
None in case of error.
|
|
806
|
+
|
|
547
807
|
"""
|
|
548
808
|
|
|
549
809
|
# Already authenticated and session still valid?
|
|
550
810
|
if self._access_token_user and not revalidate:
|
|
551
|
-
logger.debug(
|
|
811
|
+
self.logger.debug(
|
|
552
812
|
"Session still valid - return existing access token -> %s",
|
|
553
813
|
str(self._access_token_user),
|
|
554
814
|
)
|
|
555
815
|
return self._access_token_user
|
|
556
816
|
|
|
557
|
-
if grant_type == "client_credentials":
|
|
558
|
-
request_url = self.config()["authorizationUrlCredentials"]
|
|
559
|
-
elif grant_type == "password":
|
|
560
|
-
request_url = self.config()["authorizationUrlPassword"]
|
|
561
|
-
else:
|
|
562
|
-
logger.error("Illegal grant type - authorization not possible!")
|
|
563
|
-
return None
|
|
564
|
-
|
|
565
817
|
request_header = REQUEST_LOGIN_HEADERS
|
|
818
|
+
request_url = self.config()["tokenUrl"]
|
|
566
819
|
|
|
567
|
-
logger.debug(
|
|
820
|
+
self.logger.debug(
|
|
568
821
|
"Requesting Core Share Tenant Service User Access Token from -> %s",
|
|
569
822
|
request_url,
|
|
570
823
|
)
|
|
@@ -572,14 +825,25 @@ class CoreShare(object):
|
|
|
572
825
|
response = None
|
|
573
826
|
self._access_token_user = None
|
|
574
827
|
|
|
828
|
+
authentication_body_post = {
|
|
829
|
+
"grant_type": grant_type,
|
|
830
|
+
"client_id": self.config()["clientId"],
|
|
831
|
+
"client_secret": self.config()["clientSecret"],
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if grant_type == "password":
|
|
835
|
+
authentication_body_post["username"] = self.config()["username"]
|
|
836
|
+
authentication_body_post["password"] = self.config()["password"]
|
|
837
|
+
|
|
575
838
|
try:
|
|
576
839
|
response = requests.post(
|
|
577
840
|
request_url,
|
|
578
841
|
headers=request_header,
|
|
842
|
+
data=authentication_body_post,
|
|
579
843
|
timeout=REQUEST_TIMEOUT,
|
|
580
844
|
)
|
|
581
845
|
except requests.exceptions.ConnectionError as exception:
|
|
582
|
-
logger.warning(
|
|
846
|
+
self.logger.warning(
|
|
583
847
|
"Unable to connect to -> %s : %s",
|
|
584
848
|
request_url,
|
|
585
849
|
exception,
|
|
@@ -593,11 +857,12 @@ class CoreShare(object):
|
|
|
593
857
|
else:
|
|
594
858
|
# Store authentication access_token:
|
|
595
859
|
self._access_token_user = authenticate_dict["access_token"]
|
|
596
|
-
logger.debug(
|
|
597
|
-
"Tenant Service User Access Token -> %s",
|
|
860
|
+
self.logger.debug(
|
|
861
|
+
"Tenant Service User Access Token -> %s",
|
|
862
|
+
self._access_token_user,
|
|
598
863
|
)
|
|
599
864
|
else:
|
|
600
|
-
logger.error(
|
|
865
|
+
self.logger.error(
|
|
601
866
|
"Failed to request a Core Share Tenant Service User Access Token; error -> %s",
|
|
602
867
|
response.text,
|
|
603
868
|
)
|
|
@@ -611,11 +876,14 @@ class CoreShare(object):
|
|
|
611
876
|
"""Get Core Share groups.
|
|
612
877
|
|
|
613
878
|
Args:
|
|
614
|
-
offset (int, optional):
|
|
615
|
-
|
|
879
|
+
offset (int, optional):
|
|
880
|
+
The index of first group (for pagination). Defaults to 0.
|
|
881
|
+
count (int, optional):
|
|
882
|
+
The number of groups to return (page length). Defaults to 25.
|
|
616
883
|
|
|
617
884
|
Returns:
|
|
618
|
-
dict | None:
|
|
885
|
+
dict | None:
|
|
886
|
+
Dictionary with the Core Share group data or None if the request fails.
|
|
619
887
|
|
|
620
888
|
Example response:
|
|
621
889
|
{
|
|
@@ -640,6 +908,7 @@ class CoreShare(object):
|
|
|
640
908
|
}
|
|
641
909
|
]
|
|
642
910
|
}
|
|
911
|
+
|
|
643
912
|
"""
|
|
644
913
|
|
|
645
914
|
if not self._access_token_user:
|
|
@@ -647,30 +916,20 @@ class CoreShare(object):
|
|
|
647
916
|
|
|
648
917
|
request_header = self.request_header_user()
|
|
649
918
|
request_url = self.config()["groupsUrl"] + "?offset={}&count={}".format(
|
|
650
|
-
offset,
|
|
919
|
+
offset,
|
|
920
|
+
count,
|
|
651
921
|
)
|
|
652
922
|
|
|
653
|
-
logger.debug("Get Core Share groups; calling -> %s", request_url)
|
|
923
|
+
self.logger.debug("Get Core Share groups; calling -> %s", request_url)
|
|
654
924
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
664
|
-
self.authenticate_user(revalidate=True)
|
|
665
|
-
request_header = self.request_header_user()
|
|
666
|
-
retries += 1
|
|
667
|
-
else:
|
|
668
|
-
logger.error(
|
|
669
|
-
"Failed to get Core Share groups; status -> %s; error -> %s",
|
|
670
|
-
response.status_code,
|
|
671
|
-
response.text,
|
|
672
|
-
)
|
|
673
|
-
return None
|
|
925
|
+
return self.do_request(
|
|
926
|
+
url=request_url,
|
|
927
|
+
method="GET",
|
|
928
|
+
headers=request_header,
|
|
929
|
+
timeout=REQUEST_TIMEOUT,
|
|
930
|
+
failure_message="Failed to get Core Share groups",
|
|
931
|
+
user_credentials=True,
|
|
932
|
+
)
|
|
674
933
|
|
|
675
934
|
# end method definition
|
|
676
935
|
|
|
@@ -682,11 +941,14 @@ class CoreShare(object):
|
|
|
682
941
|
"""Add a new Core Share group. This requires a Tenent Admin authorization.
|
|
683
942
|
|
|
684
943
|
Args:
|
|
685
|
-
group_name (str):
|
|
686
|
-
|
|
944
|
+
group_name (str):
|
|
945
|
+
The name of the new Core Share group.
|
|
946
|
+
description (str, optional):
|
|
947
|
+
The description of the new Core Share group.
|
|
687
948
|
|
|
688
949
|
Returns:
|
|
689
|
-
dict | None:
|
|
950
|
+
dict | None:
|
|
951
|
+
Dictionary with the Core Share Group data or None if the request fails.
|
|
690
952
|
|
|
691
953
|
Example response:
|
|
692
954
|
{
|
|
@@ -706,6 +968,7 @@ class CoreShare(object):
|
|
|
706
968
|
"isSync": false,
|
|
707
969
|
"tenantId": "2157293035593927996"
|
|
708
970
|
}
|
|
971
|
+
|
|
709
972
|
"""
|
|
710
973
|
|
|
711
974
|
if not self._access_token_admin:
|
|
@@ -716,33 +979,21 @@ class CoreShare(object):
|
|
|
716
979
|
|
|
717
980
|
payload = {"name": group_name, "description": description}
|
|
718
981
|
|
|
719
|
-
logger.debug(
|
|
720
|
-
"Adding Core Share group -> %s; calling -> %s",
|
|
982
|
+
self.logger.debug(
|
|
983
|
+
"Adding Core Share group -> %s; calling -> %s",
|
|
984
|
+
group_name,
|
|
985
|
+
request_url,
|
|
721
986
|
)
|
|
722
987
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
return self.parse_request_response(response)
|
|
733
|
-
elif response.status_code == 401 and retries == 0:
|
|
734
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
735
|
-
self.authenticate_admin(revalidate=True)
|
|
736
|
-
request_header = self.request_header_admin()
|
|
737
|
-
retries += 1
|
|
738
|
-
else:
|
|
739
|
-
logger.error(
|
|
740
|
-
"Failed to add Core Share group -> %s; status -> %s; error -> %s",
|
|
741
|
-
group_name,
|
|
742
|
-
response.status_code,
|
|
743
|
-
response.text,
|
|
744
|
-
)
|
|
745
|
-
return None
|
|
988
|
+
return self.do_request(
|
|
989
|
+
url=request_url,
|
|
990
|
+
method="POST",
|
|
991
|
+
headers=request_header,
|
|
992
|
+
data=json.dumps(payload),
|
|
993
|
+
timeout=REQUEST_TIMEOUT,
|
|
994
|
+
failure_message="Failed to add Core Share group -> '{}'".format(group_name),
|
|
995
|
+
user_credentials=False,
|
|
996
|
+
)
|
|
746
997
|
|
|
747
998
|
# end method definition
|
|
748
999
|
|
|
@@ -750,10 +1001,12 @@ class CoreShare(object):
|
|
|
750
1001
|
"""Get Core Share group members.
|
|
751
1002
|
|
|
752
1003
|
Args:
|
|
753
|
-
group_id (str):
|
|
1004
|
+
group_id (str):
|
|
1005
|
+
The ID of the group to deliver the members for.
|
|
754
1006
|
|
|
755
1007
|
Returns:
|
|
756
|
-
dict | None:
|
|
1008
|
+
dict | None:
|
|
1009
|
+
Dictionary with the Core Share group membership data or None if the request fails.
|
|
757
1010
|
|
|
758
1011
|
Example response:
|
|
759
1012
|
{
|
|
@@ -782,54 +1035,54 @@ class CoreShare(object):
|
|
|
782
1035
|
],
|
|
783
1036
|
'count': 0
|
|
784
1037
|
}
|
|
1038
|
+
|
|
785
1039
|
"""
|
|
786
1040
|
|
|
787
1041
|
if not self._access_token_admin:
|
|
788
1042
|
self.authenticate_admin()
|
|
789
1043
|
|
|
790
|
-
request_header = self.
|
|
1044
|
+
request_header = self.request_header_admin()
|
|
791
1045
|
request_url = self.config()["groupsUrl"] + "/{}".format(group_id) + "/members"
|
|
792
1046
|
|
|
793
|
-
logger.debug(
|
|
794
|
-
"Get members for Core Share group -> %s; calling -> %s",
|
|
1047
|
+
self.logger.debug(
|
|
1048
|
+
"Get members for Core Share group with ID -> %s; calling -> %s",
|
|
795
1049
|
group_id,
|
|
796
1050
|
request_url,
|
|
797
1051
|
)
|
|
798
1052
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
request_header = self.request_header_admin()
|
|
810
|
-
retries += 1
|
|
811
|
-
else:
|
|
812
|
-
logger.error(
|
|
813
|
-
"Failed to get members of Core Share group -> %s; status -> %s; error -> %s",
|
|
814
|
-
group_id,
|
|
815
|
-
response.status_code,
|
|
816
|
-
response.text,
|
|
817
|
-
)
|
|
818
|
-
return None
|
|
1053
|
+
return self.do_request(
|
|
1054
|
+
url=request_url,
|
|
1055
|
+
method="GET",
|
|
1056
|
+
headers=request_header,
|
|
1057
|
+
timeout=REQUEST_TIMEOUT,
|
|
1058
|
+
failure_message="Failed to get members of Core Share group -> '{}'".format(
|
|
1059
|
+
group_id,
|
|
1060
|
+
),
|
|
1061
|
+
user_credentials=False,
|
|
1062
|
+
)
|
|
819
1063
|
|
|
820
1064
|
# end method definition
|
|
821
1065
|
|
|
822
1066
|
def add_group_member(
|
|
823
|
-
self,
|
|
1067
|
+
self,
|
|
1068
|
+
group_id: str,
|
|
1069
|
+
user_id: str,
|
|
1070
|
+
is_group_admin: bool = False,
|
|
824
1071
|
) -> list | None:
|
|
825
1072
|
"""Add a Core Share user to a Core Share group.
|
|
826
1073
|
|
|
827
1074
|
Args:
|
|
828
|
-
group_id (str):
|
|
829
|
-
|
|
1075
|
+
group_id (str):
|
|
1076
|
+
ID of the Core Share group.
|
|
1077
|
+
user_id (str):
|
|
1078
|
+
ID of the Core Share user.
|
|
1079
|
+
is_group_admin (bool, optional):
|
|
1080
|
+
Whether or not the member is a group administrator.
|
|
1081
|
+
Default is False.
|
|
830
1082
|
|
|
831
1083
|
Returns:
|
|
832
|
-
list | None:
|
|
1084
|
+
list | None:
|
|
1085
|
+
Dictionary with the Core Share group membership or None if the request fails.
|
|
833
1086
|
|
|
834
1087
|
Example Response ('errors' is only output if success = False):
|
|
835
1088
|
[
|
|
@@ -863,12 +1116,13 @@ class CoreShare(object):
|
|
|
863
1116
|
]
|
|
864
1117
|
}
|
|
865
1118
|
]
|
|
1119
|
+
|
|
866
1120
|
"""
|
|
867
1121
|
|
|
868
1122
|
if not self._access_token_admin:
|
|
869
1123
|
self.authenticate_admin()
|
|
870
1124
|
|
|
871
|
-
request_header = self.
|
|
1125
|
+
request_header = self.request_header_admin()
|
|
872
1126
|
request_url = self.config()["groupsUrl"] + "/{}".format(group_id) + "/members"
|
|
873
1127
|
|
|
874
1128
|
user = self.get_user_by_id(user_id=user_id)
|
|
@@ -876,8 +1130,8 @@ class CoreShare(object):
|
|
|
876
1130
|
|
|
877
1131
|
payload = {"members": [user_email], "specificGroupRole": is_group_admin}
|
|
878
1132
|
|
|
879
|
-
logger.debug(
|
|
880
|
-
"Add Core Share user -> %s (%s) as %s to Core Share group -> %s; calling -> %s",
|
|
1133
|
+
self.logger.debug(
|
|
1134
|
+
"Add Core Share user -> '%s' (%s) as %s to Core Share group with ID -> %s; calling -> %s",
|
|
881
1135
|
user_email,
|
|
882
1136
|
user_id,
|
|
883
1137
|
"group member" if not is_group_admin else "group admin",
|
|
@@ -885,44 +1139,41 @@ class CoreShare(object):
|
|
|
885
1139
|
request_url,
|
|
886
1140
|
)
|
|
887
1141
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
self.authenticate_admin(revalidate=True)
|
|
901
|
-
request_header = self.request_header_admin()
|
|
902
|
-
retries += 1
|
|
903
|
-
else:
|
|
904
|
-
logger.error(
|
|
905
|
-
"Failed to add Core Share user -> %s to Core Share group -> %s; status -> %s; error -> %s",
|
|
906
|
-
user_id,
|
|
907
|
-
group_id,
|
|
908
|
-
response.status_code,
|
|
909
|
-
response.text,
|
|
910
|
-
)
|
|
911
|
-
return None
|
|
1142
|
+
return self.do_request(
|
|
1143
|
+
url=request_url,
|
|
1144
|
+
method="POST",
|
|
1145
|
+
headers=request_header,
|
|
1146
|
+
json_data=payload,
|
|
1147
|
+
timeout=REQUEST_TIMEOUT,
|
|
1148
|
+
failure_message="Failed to add Core Share user -> '{}' to Core Share group with ID -> {}".format(
|
|
1149
|
+
user_email,
|
|
1150
|
+
group_id,
|
|
1151
|
+
),
|
|
1152
|
+
user_credentials=False,
|
|
1153
|
+
)
|
|
912
1154
|
|
|
913
1155
|
# end method definition
|
|
914
1156
|
|
|
915
1157
|
def remove_group_member(
|
|
916
|
-
self,
|
|
1158
|
+
self,
|
|
1159
|
+
group_id: str,
|
|
1160
|
+
user_id: str,
|
|
1161
|
+
is_group_admin: bool = False,
|
|
917
1162
|
) -> list | None:
|
|
918
1163
|
"""Remove a Core Share user from a Core Share group.
|
|
919
1164
|
|
|
920
1165
|
Args:
|
|
921
|
-
group_id (str):
|
|
922
|
-
|
|
1166
|
+
group_id (str):
|
|
1167
|
+
The ID of the Core Share Group.
|
|
1168
|
+
user_id (str):
|
|
1169
|
+
The ID of the Core Share User.
|
|
1170
|
+
is_group_admin (bool, optional):
|
|
1171
|
+
True, if the member is a group admin.
|
|
1172
|
+
Default is False.
|
|
923
1173
|
|
|
924
1174
|
Returns:
|
|
925
|
-
list | None:
|
|
1175
|
+
list | None:
|
|
1176
|
+
Dictionary with the Core Share group membership or None if the request fails.
|
|
926
1177
|
|
|
927
1178
|
Example Response ('errors' is only output if success = False):
|
|
928
1179
|
[
|
|
@@ -937,12 +1188,13 @@ class CoreShare(object):
|
|
|
937
1188
|
]
|
|
938
1189
|
}
|
|
939
1190
|
]
|
|
1191
|
+
|
|
940
1192
|
"""
|
|
941
1193
|
|
|
942
|
-
if not self.
|
|
943
|
-
self.
|
|
1194
|
+
if not self._access_token_admin:
|
|
1195
|
+
self.authenticate_admin()
|
|
944
1196
|
|
|
945
|
-
request_header = self.
|
|
1197
|
+
request_header = self.request_header_admin()
|
|
946
1198
|
request_url = self.config()["groupsUrl"] + "/{}".format(group_id) + "/members"
|
|
947
1199
|
|
|
948
1200
|
user = self.get_user_by_id(user_id=user_id)
|
|
@@ -950,8 +1202,8 @@ class CoreShare(object):
|
|
|
950
1202
|
|
|
951
1203
|
payload = {"members": [user_email], "specificGroupRole": is_group_admin}
|
|
952
1204
|
|
|
953
|
-
logger.debug(
|
|
954
|
-
"Remove Core Share user -> %s (%s) as %s from Core Share group -> %s; calling -> %s",
|
|
1205
|
+
self.logger.debug(
|
|
1206
|
+
"Remove Core Share user -> '%s' (%s) as %s from Core Share group with ID -> %s; calling -> %s",
|
|
955
1207
|
user_email,
|
|
956
1208
|
user_id,
|
|
957
1209
|
"group member" if not is_group_admin else "group admin",
|
|
@@ -959,30 +1211,19 @@ class CoreShare(object):
|
|
|
959
1211
|
request_url,
|
|
960
1212
|
)
|
|
961
1213
|
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
request_header = self.request_header_user()
|
|
976
|
-
retries += 1
|
|
977
|
-
else:
|
|
978
|
-
logger.error(
|
|
979
|
-
"Failed to remove Core Share user -> %s from Core Share group -> %s; status -> %s; error -> %s",
|
|
980
|
-
user_id,
|
|
981
|
-
group_id,
|
|
982
|
-
response.status_code,
|
|
983
|
-
response.text,
|
|
984
|
-
)
|
|
985
|
-
return None
|
|
1214
|
+
return self.do_request(
|
|
1215
|
+
url=request_url,
|
|
1216
|
+
method="DELETE",
|
|
1217
|
+
headers=request_header,
|
|
1218
|
+
json_data=payload,
|
|
1219
|
+
timeout=REQUEST_TIMEOUT,
|
|
1220
|
+
failure_message="Failed to remove Core Share user -> '{}' ({}) from Core Share group with ID -> {}".format(
|
|
1221
|
+
user_email,
|
|
1222
|
+
user_id,
|
|
1223
|
+
group_id,
|
|
1224
|
+
),
|
|
1225
|
+
user_credentials=False,
|
|
1226
|
+
)
|
|
986
1227
|
|
|
987
1228
|
# end method definition
|
|
988
1229
|
|
|
@@ -990,44 +1231,37 @@ class CoreShare(object):
|
|
|
990
1231
|
"""Get a Core Share group by its ID.
|
|
991
1232
|
|
|
992
1233
|
Args:
|
|
993
|
-
|
|
1234
|
+
group_id (str):
|
|
1235
|
+
The ID of the Core Share group.
|
|
994
1236
|
|
|
995
1237
|
Returns:
|
|
996
|
-
dict | None:
|
|
1238
|
+
dict | None:
|
|
1239
|
+
Dictionary with the Core Share group data or None if the request fails.
|
|
997
1240
|
|
|
998
|
-
Response example:
|
|
999
1241
|
"""
|
|
1000
1242
|
|
|
1001
|
-
if not self.
|
|
1002
|
-
self.
|
|
1243
|
+
if not self._access_token_admin:
|
|
1244
|
+
self.authenticate_admin()
|
|
1003
1245
|
|
|
1004
|
-
request_header = self.
|
|
1246
|
+
request_header = self.request_header_admin()
|
|
1005
1247
|
request_url = self.config()["groupsUrl"] + "/" + group_id
|
|
1006
1248
|
|
|
1007
|
-
logger.debug(
|
|
1008
|
-
"Get Core Share group with ID -> %s; calling -> %s",
|
|
1249
|
+
self.logger.debug(
|
|
1250
|
+
"Get Core Share group with ID -> %s; calling -> %s",
|
|
1251
|
+
group_id,
|
|
1252
|
+
request_url,
|
|
1009
1253
|
)
|
|
1010
1254
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
request_header = self.request_header_user()
|
|
1022
|
-
retries += 1
|
|
1023
|
-
else:
|
|
1024
|
-
logger.error(
|
|
1025
|
-
"Failed to get Core Share group with ID -> %s; status -> %s; error -> %s",
|
|
1026
|
-
group_id,
|
|
1027
|
-
response.status_code,
|
|
1028
|
-
response.text,
|
|
1029
|
-
)
|
|
1030
|
-
return None
|
|
1255
|
+
return self.do_request(
|
|
1256
|
+
url=request_url,
|
|
1257
|
+
method="GET",
|
|
1258
|
+
headers=request_header,
|
|
1259
|
+
timeout=REQUEST_TIMEOUT,
|
|
1260
|
+
failure_message="Failed to get Core Share group with ID -> {}".format(
|
|
1261
|
+
group_id,
|
|
1262
|
+
),
|
|
1263
|
+
user_credentials=False,
|
|
1264
|
+
)
|
|
1031
1265
|
|
|
1032
1266
|
# end method definition
|
|
1033
1267
|
|
|
@@ -1035,10 +1269,12 @@ class CoreShare(object):
|
|
|
1035
1269
|
"""Get Core Share group by its name.
|
|
1036
1270
|
|
|
1037
1271
|
Args:
|
|
1038
|
-
name (str):
|
|
1272
|
+
name (str):
|
|
1273
|
+
The name of the group to search.
|
|
1039
1274
|
|
|
1040
1275
|
Returns:
|
|
1041
|
-
dict | None:
|
|
1276
|
+
dict | None:
|
|
1277
|
+
Dictionary with the Core Share group data or None if the request fails.
|
|
1042
1278
|
|
|
1043
1279
|
Example result:
|
|
1044
1280
|
{
|
|
@@ -1060,6 +1296,7 @@ class CoreShare(object):
|
|
|
1060
1296
|
],
|
|
1061
1297
|
'total': 1
|
|
1062
1298
|
}
|
|
1299
|
+
|
|
1063
1300
|
"""
|
|
1064
1301
|
|
|
1065
1302
|
groups = self.search_groups(
|
|
@@ -1071,7 +1308,7 @@ class CoreShare(object):
|
|
|
1071
1308
|
# end method definition
|
|
1072
1309
|
|
|
1073
1310
|
def search_groups(self, query_string: str) -> dict | None:
|
|
1074
|
-
"""Search Core Share group(s)
|
|
1311
|
+
"""Search Core Share group(s) using a query string.
|
|
1075
1312
|
|
|
1076
1313
|
Args:
|
|
1077
1314
|
query_string(str): Query for the group name / property
|
|
@@ -1079,7 +1316,6 @@ class CoreShare(object):
|
|
|
1079
1316
|
Returns:
|
|
1080
1317
|
dict | None: Dictionary with the Core Share user data or None if the request fails.
|
|
1081
1318
|
|
|
1082
|
-
Example response:
|
|
1083
1319
|
"""
|
|
1084
1320
|
|
|
1085
1321
|
if not self._access_token_admin:
|
|
@@ -1088,30 +1324,22 @@ class CoreShare(object):
|
|
|
1088
1324
|
request_header = self.request_header_admin()
|
|
1089
1325
|
request_url = self.config()["searchGroupUrl"] + "?q=" + query_string
|
|
1090
1326
|
|
|
1091
|
-
logger.debug(
|
|
1092
|
-
"Search Core Share group by -> %s; calling -> %s",
|
|
1327
|
+
self.logger.debug(
|
|
1328
|
+
"Search Core Share group by -> %s; calling -> %s",
|
|
1329
|
+
query_string,
|
|
1330
|
+
request_url,
|
|
1093
1331
|
)
|
|
1094
1332
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
request_header = self.request_header_admin()
|
|
1106
|
-
retries += 1
|
|
1107
|
-
else:
|
|
1108
|
-
logger.error(
|
|
1109
|
-
"Cannot find Core Share group with name / property -> %s; status -> %s; error -> %s",
|
|
1110
|
-
query_string,
|
|
1111
|
-
response.status_code,
|
|
1112
|
-
response.text,
|
|
1113
|
-
)
|
|
1114
|
-
return None
|
|
1333
|
+
return self.do_request(
|
|
1334
|
+
url=request_url,
|
|
1335
|
+
method="GET",
|
|
1336
|
+
headers=request_header,
|
|
1337
|
+
timeout=REQUEST_TIMEOUT,
|
|
1338
|
+
failure_message="Cannot find Core Share group with name / property -> {}".format(
|
|
1339
|
+
query_string,
|
|
1340
|
+
),
|
|
1341
|
+
user_credentials=False,
|
|
1342
|
+
)
|
|
1115
1343
|
|
|
1116
1344
|
# end method definition
|
|
1117
1345
|
|
|
@@ -1122,7 +1350,8 @@ class CoreShare(object):
|
|
|
1122
1350
|
None
|
|
1123
1351
|
|
|
1124
1352
|
Returns:
|
|
1125
|
-
dict | None:
|
|
1353
|
+
dict | None:
|
|
1354
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1126
1355
|
|
|
1127
1356
|
Example response (it is a list!):
|
|
1128
1357
|
[
|
|
@@ -1187,6 +1416,7 @@ class CoreShare(object):
|
|
|
1187
1416
|
},
|
|
1188
1417
|
...
|
|
1189
1418
|
]
|
|
1419
|
+
|
|
1190
1420
|
"""
|
|
1191
1421
|
|
|
1192
1422
|
if not self._access_token_admin:
|
|
@@ -1195,27 +1425,16 @@ class CoreShare(object):
|
|
|
1195
1425
|
request_header = self.request_header_admin()
|
|
1196
1426
|
request_url = self.config()["usersUrlv1"]
|
|
1197
1427
|
|
|
1198
|
-
logger.debug("Get Core Share users; calling -> %s", request_url)
|
|
1428
|
+
self.logger.debug("Get Core Share users; calling -> %s", request_url)
|
|
1199
1429
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1209
|
-
self.authenticate_admin(revalidate=True)
|
|
1210
|
-
request_header = self.request_header_admin()
|
|
1211
|
-
retries += 1
|
|
1212
|
-
else:
|
|
1213
|
-
logger.error(
|
|
1214
|
-
"Failed to get Core Share users; status -> %s; error -> %s",
|
|
1215
|
-
response.status_code,
|
|
1216
|
-
response.text,
|
|
1217
|
-
)
|
|
1218
|
-
return None
|
|
1430
|
+
return self.do_request(
|
|
1431
|
+
url=request_url,
|
|
1432
|
+
method="GET",
|
|
1433
|
+
headers=request_header,
|
|
1434
|
+
timeout=REQUEST_TIMEOUT,
|
|
1435
|
+
failure_message="Failed to get Core Share users",
|
|
1436
|
+
user_credentials=False,
|
|
1437
|
+
)
|
|
1219
1438
|
|
|
1220
1439
|
# end method definition
|
|
1221
1440
|
|
|
@@ -1223,10 +1442,12 @@ class CoreShare(object):
|
|
|
1223
1442
|
"""Get a Core Share user by its ID.
|
|
1224
1443
|
|
|
1225
1444
|
Args:
|
|
1226
|
-
|
|
1445
|
+
user_id (str):
|
|
1446
|
+
The ID of the user.
|
|
1227
1447
|
|
|
1228
1448
|
Returns:
|
|
1229
|
-
dict | None:
|
|
1449
|
+
dict | None:
|
|
1450
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1230
1451
|
|
|
1231
1452
|
Response example:
|
|
1232
1453
|
{
|
|
@@ -1287,6 +1508,7 @@ class CoreShare(object):
|
|
|
1287
1508
|
'quota': 10737418240,
|
|
1288
1509
|
'usage': 0
|
|
1289
1510
|
}
|
|
1511
|
+
|
|
1290
1512
|
"""
|
|
1291
1513
|
|
|
1292
1514
|
if not self._access_token_user:
|
|
@@ -1295,50 +1517,50 @@ class CoreShare(object):
|
|
|
1295
1517
|
request_header = self.request_header_user()
|
|
1296
1518
|
request_url = self.config()["usersUrlv1"] + "/" + user_id
|
|
1297
1519
|
|
|
1298
|
-
logger.debug(
|
|
1299
|
-
"Get Core Share user with ID -> %s; calling -> %s",
|
|
1520
|
+
self.logger.debug(
|
|
1521
|
+
"Get Core Share user with ID -> %s; calling -> %s",
|
|
1522
|
+
user_id,
|
|
1523
|
+
request_url,
|
|
1300
1524
|
)
|
|
1301
1525
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
request_header = self.request_header_user()
|
|
1313
|
-
retries += 1
|
|
1314
|
-
else:
|
|
1315
|
-
logger.error(
|
|
1316
|
-
"Failed to get Core Share user with ID -> %s; status -> %s; error -> %s",
|
|
1317
|
-
user_id,
|
|
1318
|
-
response.status_code,
|
|
1319
|
-
response.text,
|
|
1320
|
-
)
|
|
1321
|
-
return None
|
|
1526
|
+
return self.do_request(
|
|
1527
|
+
url=request_url,
|
|
1528
|
+
method="GET",
|
|
1529
|
+
headers=request_header,
|
|
1530
|
+
timeout=REQUEST_TIMEOUT,
|
|
1531
|
+
failure_message="Failed to get Core Share user with ID -> {}".format(
|
|
1532
|
+
user_id,
|
|
1533
|
+
),
|
|
1534
|
+
user_credentials=True,
|
|
1535
|
+
)
|
|
1322
1536
|
|
|
1323
1537
|
# end method definition
|
|
1324
1538
|
|
|
1325
1539
|
def get_user_by_name(
|
|
1326
|
-
self,
|
|
1540
|
+
self,
|
|
1541
|
+
first_name: str,
|
|
1542
|
+
last_name: str,
|
|
1543
|
+
user_status: str = "internal-native",
|
|
1327
1544
|
) -> dict | None:
|
|
1328
1545
|
"""Get Core Share user by its first and last name.
|
|
1329
1546
|
|
|
1330
1547
|
Args:
|
|
1331
|
-
first_name (str):
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1548
|
+
first_name (str):
|
|
1549
|
+
First name of the users to search.
|
|
1550
|
+
last_name (str):
|
|
1551
|
+
Last name of the users to search.
|
|
1552
|
+
user_status (str, optional):
|
|
1553
|
+
Type of users. Possible values:
|
|
1554
|
+
* internal-enabled
|
|
1555
|
+
* internal-pending
|
|
1556
|
+
* internal-locked
|
|
1557
|
+
* internal-native (non-SSO)
|
|
1558
|
+
* internal-sso
|
|
1339
1559
|
|
|
1340
1560
|
Returns:
|
|
1341
|
-
dict | None:
|
|
1561
|
+
dict | None:
|
|
1562
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1563
|
+
|
|
1342
1564
|
"""
|
|
1343
1565
|
|
|
1344
1566
|
# Search the users with this first and last name (and hope this is unique ;-).
|
|
@@ -1352,21 +1574,27 @@ class CoreShare(object):
|
|
|
1352
1574
|
# end method definition
|
|
1353
1575
|
|
|
1354
1576
|
def get_user_by_email(
|
|
1355
|
-
self,
|
|
1577
|
+
self,
|
|
1578
|
+
email: str,
|
|
1579
|
+
user_status: str = "internal-native",
|
|
1356
1580
|
) -> dict | None:
|
|
1357
1581
|
"""Get Core Share user by its email address.
|
|
1358
1582
|
|
|
1359
1583
|
Args:
|
|
1360
|
-
email (str):
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1584
|
+
email (str):
|
|
1585
|
+
Email address of the users to search.
|
|
1586
|
+
user_status (str, optional):
|
|
1587
|
+
Type of users. Possible values:
|
|
1588
|
+
* internal-enabled
|
|
1589
|
+
* internal-pending
|
|
1590
|
+
* internal-locked
|
|
1591
|
+
* internal-native (non-SSO)
|
|
1592
|
+
* internal-sso
|
|
1367
1593
|
|
|
1368
1594
|
Returns:
|
|
1369
|
-
dict | None:
|
|
1595
|
+
dict | None:
|
|
1596
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1597
|
+
|
|
1370
1598
|
"""
|
|
1371
1599
|
|
|
1372
1600
|
# Search the users with this first and last name (and hope this is unique ;-).
|
|
@@ -1388,14 +1616,17 @@ class CoreShare(object):
|
|
|
1388
1616
|
"""Search Core Share user(s) by name / property. Needs to be a Tenant Administrator to do so.
|
|
1389
1617
|
|
|
1390
1618
|
Args:
|
|
1391
|
-
query_string (str):
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1619
|
+
query_string (str):
|
|
1620
|
+
The string to query the user(s).
|
|
1621
|
+
user_status (str, optional):
|
|
1622
|
+
The type of users. Possible values:
|
|
1623
|
+
* internal-enabled
|
|
1624
|
+
* internal-pending
|
|
1625
|
+
* internal-locked
|
|
1626
|
+
* internal-native (non-SSO)
|
|
1627
|
+
* internal-sso
|
|
1628
|
+
page_size (int, optional):
|
|
1629
|
+
The maximum number of results per page. We set the default to 100 (Web UI uses 25)
|
|
1399
1630
|
|
|
1400
1631
|
Returns:
|
|
1401
1632
|
dict | None: Dictionary with the Core Share user data or None if the request fails.
|
|
@@ -1434,6 +1665,7 @@ class CoreShare(object):
|
|
|
1434
1665
|
...
|
|
1435
1666
|
]
|
|
1436
1667
|
}
|
|
1668
|
+
|
|
1437
1669
|
"""
|
|
1438
1670
|
|
|
1439
1671
|
if not self._access_token_admin:
|
|
@@ -1449,30 +1681,22 @@ class CoreShare(object):
|
|
|
1449
1681
|
+ str(page_size)
|
|
1450
1682
|
)
|
|
1451
1683
|
|
|
1452
|
-
logger.debug(
|
|
1453
|
-
"Search Core Share user by -> %s; calling -> %s",
|
|
1684
|
+
self.logger.debug(
|
|
1685
|
+
"Search Core Share user by -> %s; calling -> %s",
|
|
1686
|
+
query_string,
|
|
1687
|
+
request_url,
|
|
1454
1688
|
)
|
|
1455
1689
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
request_header = self.request_header_admin()
|
|
1467
|
-
retries += 1
|
|
1468
|
-
else:
|
|
1469
|
-
logger.error(
|
|
1470
|
-
"Failed to search Core Share user with name / property -> %s; status -> %s; error -> %s",
|
|
1471
|
-
query_string,
|
|
1472
|
-
response.status_code,
|
|
1473
|
-
response.text,
|
|
1474
|
-
)
|
|
1475
|
-
return None
|
|
1690
|
+
return self.do_request(
|
|
1691
|
+
url=request_url,
|
|
1692
|
+
method="GET",
|
|
1693
|
+
headers=request_header,
|
|
1694
|
+
timeout=REQUEST_TIMEOUT,
|
|
1695
|
+
failure_message="Failed to search Core Share user with name / property -> {}".format(
|
|
1696
|
+
query_string,
|
|
1697
|
+
),
|
|
1698
|
+
user_credentials=False,
|
|
1699
|
+
)
|
|
1476
1700
|
|
|
1477
1701
|
# end method definition
|
|
1478
1702
|
|
|
@@ -1488,15 +1712,22 @@ class CoreShare(object):
|
|
|
1488
1712
|
"""Add a new Core Share user. This requires a Tenent Admin authorization.
|
|
1489
1713
|
|
|
1490
1714
|
Args:
|
|
1491
|
-
first_name (str):
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1715
|
+
first_name (str):
|
|
1716
|
+
First name of the new user
|
|
1717
|
+
last_name (str):
|
|
1718
|
+
Last name of the new user
|
|
1719
|
+
email (str):
|
|
1720
|
+
Email of the new Core Share user
|
|
1721
|
+
password (str | None, optional):
|
|
1722
|
+
Password of the new Core Share user
|
|
1723
|
+
title (str | None, optional):
|
|
1724
|
+
Title of the user
|
|
1725
|
+
company (str | None, optional):
|
|
1726
|
+
Name of the Company of the user
|
|
1497
1727
|
|
|
1498
1728
|
Returns:
|
|
1499
|
-
dict | None:
|
|
1729
|
+
dict | None:
|
|
1730
|
+
Dictionary with the Core Share User data or None if the request fails.
|
|
1500
1731
|
|
|
1501
1732
|
Example response:
|
|
1502
1733
|
{
|
|
@@ -1535,6 +1766,7 @@ class CoreShare(object):
|
|
|
1535
1766
|
"quota": 10737418240,
|
|
1536
1767
|
"usage": 0
|
|
1537
1768
|
}
|
|
1769
|
+
|
|
1538
1770
|
"""
|
|
1539
1771
|
|
|
1540
1772
|
if not self._access_token_admin:
|
|
@@ -1557,38 +1789,26 @@ class CoreShare(object):
|
|
|
1557
1789
|
if company:
|
|
1558
1790
|
payload["company"] = company
|
|
1559
1791
|
|
|
1560
|
-
logger.debug(
|
|
1792
|
+
self.logger.debug(
|
|
1561
1793
|
"Adding Core Share user -> %s %s; calling -> %s",
|
|
1562
1794
|
first_name,
|
|
1563
1795
|
last_name,
|
|
1564
1796
|
request_url,
|
|
1565
1797
|
)
|
|
1566
1798
|
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
request_header = self.request_header_admin()
|
|
1581
|
-
retries += 1
|
|
1582
|
-
else:
|
|
1583
|
-
logger.error(
|
|
1584
|
-
"Failed to add Core Share user -> %s %s (%s); status -> %s; error -> %s",
|
|
1585
|
-
first_name,
|
|
1586
|
-
last_name,
|
|
1587
|
-
email,
|
|
1588
|
-
response.status_code,
|
|
1589
|
-
response.text,
|
|
1590
|
-
)
|
|
1591
|
-
return None
|
|
1799
|
+
return self.do_request(
|
|
1800
|
+
url=request_url,
|
|
1801
|
+
method="POST",
|
|
1802
|
+
headers=request_header,
|
|
1803
|
+
json_data=payload,
|
|
1804
|
+
timeout=REQUEST_TIMEOUT,
|
|
1805
|
+
failure_message="Failed to add Core Share user -> '{} {}' ({})".format(
|
|
1806
|
+
first_name,
|
|
1807
|
+
last_name,
|
|
1808
|
+
email,
|
|
1809
|
+
),
|
|
1810
|
+
user_credentials=False,
|
|
1811
|
+
)
|
|
1592
1812
|
|
|
1593
1813
|
# end method definition
|
|
1594
1814
|
|
|
@@ -1596,10 +1816,13 @@ class CoreShare(object):
|
|
|
1596
1816
|
"""Resend the invite for a Core Share user.
|
|
1597
1817
|
|
|
1598
1818
|
Args:
|
|
1599
|
-
user_id (str):
|
|
1819
|
+
user_id (str):
|
|
1820
|
+
The Core Share user ID.
|
|
1600
1821
|
|
|
1601
1822
|
Returns:
|
|
1602
|
-
dict:
|
|
1823
|
+
dict:
|
|
1824
|
+
Response from the Core Share API.
|
|
1825
|
+
|
|
1603
1826
|
"""
|
|
1604
1827
|
|
|
1605
1828
|
if not self._access_token_admin:
|
|
@@ -1609,7 +1832,7 @@ class CoreShare(object):
|
|
|
1609
1832
|
|
|
1610
1833
|
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id)
|
|
1611
1834
|
|
|
1612
|
-
logger.debug(
|
|
1835
|
+
self.logger.debug(
|
|
1613
1836
|
"Resend invite for Core Share user with ID -> %s; calling -> %s",
|
|
1614
1837
|
user_id,
|
|
1615
1838
|
request_url,
|
|
@@ -1617,29 +1840,17 @@ class CoreShare(object):
|
|
|
1617
1840
|
|
|
1618
1841
|
update_data = {"resend": True}
|
|
1619
1842
|
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
logger.debug("Admin Session has expired - try to re-authenticate...")
|
|
1632
|
-
self.authenticate_admin(revalidate=True)
|
|
1633
|
-
request_header = self.request_header_admin()
|
|
1634
|
-
retries += 1
|
|
1635
|
-
else:
|
|
1636
|
-
logger.error(
|
|
1637
|
-
"Failed to resend invite for Core Share user -> %s; status -> %s; error -> %s",
|
|
1638
|
-
user_id,
|
|
1639
|
-
response.status_code,
|
|
1640
|
-
response.text,
|
|
1641
|
-
)
|
|
1642
|
-
return None
|
|
1843
|
+
return self.do_request(
|
|
1844
|
+
url=request_url,
|
|
1845
|
+
method="PUT",
|
|
1846
|
+
headers=request_header,
|
|
1847
|
+
json_data=update_data,
|
|
1848
|
+
timeout=REQUEST_TIMEOUT,
|
|
1849
|
+
failure_message="Failed to resend invite for Core Share user with ID -> {}".format(
|
|
1850
|
+
user_id,
|
|
1851
|
+
),
|
|
1852
|
+
user_credentials=False,
|
|
1853
|
+
)
|
|
1643
1854
|
|
|
1644
1855
|
# end method definition
|
|
1645
1856
|
|
|
@@ -1647,10 +1858,15 @@ class CoreShare(object):
|
|
|
1647
1858
|
"""Update a Core Share user.
|
|
1648
1859
|
|
|
1649
1860
|
Args:
|
|
1650
|
-
user_id (str):
|
|
1861
|
+
user_id (str):
|
|
1862
|
+
The ID of the Core Share user.
|
|
1863
|
+
update_data (dict):
|
|
1864
|
+
The updated user data.
|
|
1651
1865
|
|
|
1652
1866
|
Returns:
|
|
1653
|
-
dict:
|
|
1867
|
+
dict:
|
|
1868
|
+
REST response or None if the REST call has failed.
|
|
1869
|
+
|
|
1654
1870
|
"""
|
|
1655
1871
|
|
|
1656
1872
|
if not self._access_token_admin:
|
|
@@ -1660,40 +1876,28 @@ class CoreShare(object):
|
|
|
1660
1876
|
|
|
1661
1877
|
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id)
|
|
1662
1878
|
|
|
1663
|
-
logger.debug(
|
|
1879
|
+
self.logger.debug(
|
|
1664
1880
|
"Update data of Core Share user with ID -> %s; calling -> %s",
|
|
1665
1881
|
user_id,
|
|
1666
1882
|
request_url,
|
|
1667
1883
|
)
|
|
1668
1884
|
|
|
1669
|
-
if "email" in update_data and
|
|
1670
|
-
logger.warning(
|
|
1671
|
-
"Trying to update the email without providing the password. This is likely to fail..."
|
|
1885
|
+
if "email" in update_data and "password" not in update_data:
|
|
1886
|
+
self.logger.warning(
|
|
1887
|
+
"Trying to update the email without providing the password. This is likely to fail...",
|
|
1672
1888
|
)
|
|
1673
1889
|
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
logger.debug("Admin Session has expired - try to re-authenticate...")
|
|
1686
|
-
self.authenticate_admin(revalidate=True)
|
|
1687
|
-
request_header = self.request_header_admin()
|
|
1688
|
-
retries += 1
|
|
1689
|
-
else:
|
|
1690
|
-
logger.error(
|
|
1691
|
-
"Failed to update Core Share user -> %s; status -> %s; error -> %s",
|
|
1692
|
-
user_id,
|
|
1693
|
-
response.status_code,
|
|
1694
|
-
response.text,
|
|
1695
|
-
)
|
|
1696
|
-
return None
|
|
1890
|
+
return self.do_request(
|
|
1891
|
+
url=request_url,
|
|
1892
|
+
method="PUT",
|
|
1893
|
+
headers=request_header,
|
|
1894
|
+
json_data=update_data,
|
|
1895
|
+
timeout=REQUEST_TIMEOUT,
|
|
1896
|
+
failure_message="Failed to update Core Share user with ID -> {}".format(
|
|
1897
|
+
user_id,
|
|
1898
|
+
),
|
|
1899
|
+
user_credentials=False,
|
|
1900
|
+
)
|
|
1697
1901
|
|
|
1698
1902
|
# end method definition
|
|
1699
1903
|
|
|
@@ -1701,13 +1905,17 @@ class CoreShare(object):
|
|
|
1701
1905
|
"""Add an access role to a Core Share user.
|
|
1702
1906
|
|
|
1703
1907
|
Args:
|
|
1704
|
-
user_id (str):
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1908
|
+
user_id (str):
|
|
1909
|
+
The Core Share user ID.
|
|
1910
|
+
role_id (int):
|
|
1911
|
+
The role ID:
|
|
1912
|
+
- Content Manager = 5
|
|
1913
|
+
- Group Admin = 3
|
|
1708
1914
|
|
|
1709
1915
|
Returns:
|
|
1710
|
-
dict:
|
|
1916
|
+
dict:
|
|
1917
|
+
Response from the Core Share API.
|
|
1918
|
+
|
|
1711
1919
|
"""
|
|
1712
1920
|
|
|
1713
1921
|
if not self._access_token_admin:
|
|
@@ -1715,44 +1923,26 @@ class CoreShare(object):
|
|
|
1715
1923
|
|
|
1716
1924
|
request_header = self.request_header_admin()
|
|
1717
1925
|
|
|
1718
|
-
request_url = (
|
|
1719
|
-
self.config()["usersUrlv1"]
|
|
1720
|
-
+ "/{}".format(user_id)
|
|
1721
|
-
+ "/roles/"
|
|
1722
|
-
+ str(role_id)
|
|
1723
|
-
)
|
|
1926
|
+
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id) + "/roles/" + str(role_id)
|
|
1724
1927
|
|
|
1725
|
-
logger.debug(
|
|
1928
|
+
self.logger.debug(
|
|
1726
1929
|
"Add access role -> %s to Core Share user with ID -> %s; calling -> %s",
|
|
1727
1930
|
str(role_id),
|
|
1728
1931
|
user_id,
|
|
1729
1932
|
request_url,
|
|
1730
1933
|
)
|
|
1731
1934
|
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
logger.debug("Admin Session has expired - try to re-authenticate...")
|
|
1744
|
-
self.authenticate_admin(revalidate=True)
|
|
1745
|
-
request_header = self.request_header_admin()
|
|
1746
|
-
retries += 1
|
|
1747
|
-
else:
|
|
1748
|
-
logger.error(
|
|
1749
|
-
"Failed to add access role -> %s to Core Share user -> %s; status -> %s; error -> %s",
|
|
1750
|
-
str(role_id),
|
|
1751
|
-
user_id,
|
|
1752
|
-
response.status_code,
|
|
1753
|
-
response.text,
|
|
1754
|
-
)
|
|
1755
|
-
return None
|
|
1935
|
+
return self.do_request(
|
|
1936
|
+
url=request_url,
|
|
1937
|
+
method="PUT",
|
|
1938
|
+
headers=request_header,
|
|
1939
|
+
timeout=REQUEST_TIMEOUT,
|
|
1940
|
+
failure_message="Failed to add access role with ID -> {} to Core Share user with ID -> {}".format(
|
|
1941
|
+
role_id,
|
|
1942
|
+
user_id,
|
|
1943
|
+
),
|
|
1944
|
+
user_credentials=False,
|
|
1945
|
+
)
|
|
1756
1946
|
|
|
1757
1947
|
# end method definition
|
|
1758
1948
|
|
|
@@ -1760,13 +1950,17 @@ class CoreShare(object):
|
|
|
1760
1950
|
"""Remove an access role from a Core Share user.
|
|
1761
1951
|
|
|
1762
1952
|
Args:
|
|
1763
|
-
user_id (str):
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1953
|
+
user_id (str):
|
|
1954
|
+
The Core Share user ID.
|
|
1955
|
+
role_id (int):
|
|
1956
|
+
The role ID:
|
|
1957
|
+
* Content Manager = 5
|
|
1958
|
+
* Group Admin = 3
|
|
1767
1959
|
|
|
1768
1960
|
Returns:
|
|
1769
|
-
dict:
|
|
1961
|
+
dict:
|
|
1962
|
+
Response from the Core Share API.
|
|
1963
|
+
|
|
1770
1964
|
"""
|
|
1771
1965
|
|
|
1772
1966
|
if not self._access_token_admin:
|
|
@@ -1774,44 +1968,26 @@ class CoreShare(object):
|
|
|
1774
1968
|
|
|
1775
1969
|
request_header = self.request_header_admin()
|
|
1776
1970
|
|
|
1777
|
-
request_url = (
|
|
1778
|
-
self.config()["usersUrlv1"]
|
|
1779
|
-
+ "/{}".format(user_id)
|
|
1780
|
-
+ "/roles/"
|
|
1781
|
-
+ str(role_id)
|
|
1782
|
-
)
|
|
1971
|
+
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id) + "/roles/" + str(role_id)
|
|
1783
1972
|
|
|
1784
|
-
logger.debug(
|
|
1785
|
-
"Remove access role -> %s from Core Share user with ID -> %s; calling -> %s",
|
|
1973
|
+
self.logger.debug(
|
|
1974
|
+
"Remove access role with ID -> %s from Core Share user with ID -> %s; calling -> %s",
|
|
1786
1975
|
str(role_id),
|
|
1787
1976
|
user_id,
|
|
1788
1977
|
request_url,
|
|
1789
1978
|
)
|
|
1790
1979
|
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
logger.debug("Admin Session has expired - try to re-authenticate...")
|
|
1803
|
-
self.authenticate_admin(revalidate=True)
|
|
1804
|
-
request_header = self.request_header_admin()
|
|
1805
|
-
retries += 1
|
|
1806
|
-
else:
|
|
1807
|
-
logger.error(
|
|
1808
|
-
"Failed to remove access role -> %s from Core Share user -> %s; status -> %s; error -> %s",
|
|
1809
|
-
str(role_id),
|
|
1810
|
-
user_id,
|
|
1811
|
-
response.status_code,
|
|
1812
|
-
response.text,
|
|
1813
|
-
)
|
|
1814
|
-
return None
|
|
1980
|
+
return self.do_request(
|
|
1981
|
+
url=request_url,
|
|
1982
|
+
method="DELETE",
|
|
1983
|
+
headers=request_header,
|
|
1984
|
+
timeout=REQUEST_TIMEOUT,
|
|
1985
|
+
failure_message="Failed to remove access role with ID -> {} from Core Share user with ID -> {}".format(
|
|
1986
|
+
role_id,
|
|
1987
|
+
user_id,
|
|
1988
|
+
),
|
|
1989
|
+
user_credentials=False,
|
|
1990
|
+
)
|
|
1815
1991
|
|
|
1816
1992
|
# end method definition
|
|
1817
1993
|
|
|
@@ -1825,26 +2001,29 @@ class CoreShare(object):
|
|
|
1825
2001
|
"""Define the access roles of a Core Share user.
|
|
1826
2002
|
|
|
1827
2003
|
Args:
|
|
1828
|
-
user_id (str):
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
2004
|
+
user_id (str):
|
|
2005
|
+
The ID of the Core Share user.
|
|
2006
|
+
is_content_manager (bool | None, optional):
|
|
2007
|
+
Assign Content Manager Role if True.
|
|
2008
|
+
Removes Content Manager Role if False.
|
|
2009
|
+
Does nothing if None.
|
|
2010
|
+
Defaults to None.
|
|
2011
|
+
is_group_admin (bool | None, optional):
|
|
2012
|
+
Assign Group Admin Role if True.
|
|
2013
|
+
Removes Group Admin Role if False.
|
|
2014
|
+
Does nothing if None.
|
|
2015
|
+
Defaults to None.
|
|
2016
|
+
is_admin (bool | None, optional):
|
|
2017
|
+
Makes user Admin if True.
|
|
2018
|
+
Removes Admin rights if False.
|
|
2019
|
+
Does nothing if None.
|
|
2020
|
+
Defaults to None.
|
|
1841
2021
|
|
|
1842
2022
|
Returns:
|
|
1843
|
-
dict:
|
|
1844
|
-
|
|
2023
|
+
dict:
|
|
2024
|
+
Response from the Core Share API.
|
|
1845
2025
|
|
|
1846
|
-
|
|
1847
|
-
GROUP_ADMIN_ROLE_ID = 3
|
|
2026
|
+
"""
|
|
1848
2027
|
|
|
1849
2028
|
response = None
|
|
1850
2029
|
|
|
@@ -1858,21 +2037,25 @@ class CoreShare(object):
|
|
|
1858
2037
|
if is_content_manager is not None:
|
|
1859
2038
|
if is_content_manager:
|
|
1860
2039
|
response = self.add_user_access_role(
|
|
1861
|
-
user_id=user_id,
|
|
2040
|
+
user_id=user_id,
|
|
2041
|
+
role_id=CONTENT_MANAGER_ROLE_ID,
|
|
1862
2042
|
)
|
|
1863
2043
|
else:
|
|
1864
2044
|
response = self.remove_user_access_role(
|
|
1865
|
-
user_id=user_id,
|
|
2045
|
+
user_id=user_id,
|
|
2046
|
+
role_id=CONTENT_MANAGER_ROLE_ID,
|
|
1866
2047
|
)
|
|
1867
2048
|
|
|
1868
2049
|
if is_group_admin is not None:
|
|
1869
2050
|
if is_group_admin:
|
|
1870
2051
|
response = self.add_user_access_role(
|
|
1871
|
-
user_id=user_id,
|
|
2052
|
+
user_id=user_id,
|
|
2053
|
+
role_id=GROUP_ADMIN_ROLE_ID,
|
|
1872
2054
|
)
|
|
1873
2055
|
else:
|
|
1874
2056
|
response = self.remove_user_access_role(
|
|
1875
|
-
user_id=user_id,
|
|
2057
|
+
user_id=user_id,
|
|
2058
|
+
role_id=GROUP_ADMIN_ROLE_ID,
|
|
1876
2059
|
)
|
|
1877
2060
|
|
|
1878
2061
|
return response
|
|
@@ -1880,17 +2063,25 @@ class CoreShare(object):
|
|
|
1880
2063
|
# end method definition
|
|
1881
2064
|
|
|
1882
2065
|
def update_user_password(
|
|
1883
|
-
self,
|
|
2066
|
+
self,
|
|
2067
|
+
user_id: str,
|
|
2068
|
+
password: str,
|
|
2069
|
+
new_password: str,
|
|
1884
2070
|
) -> dict:
|
|
1885
2071
|
"""Update the password of a Core Share user.
|
|
1886
2072
|
|
|
1887
2073
|
Args:
|
|
1888
|
-
user_id (str):
|
|
1889
|
-
|
|
1890
|
-
|
|
2074
|
+
user_id (str):
|
|
2075
|
+
The Core Share user ID.
|
|
2076
|
+
password (str):
|
|
2077
|
+
The old user password.
|
|
2078
|
+
new_password (str):
|
|
2079
|
+
The new user password.
|
|
1891
2080
|
|
|
1892
2081
|
Returns:
|
|
1893
|
-
dict:
|
|
2082
|
+
dict:
|
|
2083
|
+
Response from the Core Share API.
|
|
2084
|
+
|
|
1894
2085
|
"""
|
|
1895
2086
|
|
|
1896
2087
|
if not self._access_token_admin:
|
|
@@ -1900,7 +2091,7 @@ class CoreShare(object):
|
|
|
1900
2091
|
|
|
1901
2092
|
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id)
|
|
1902
2093
|
|
|
1903
|
-
logger.debug(
|
|
2094
|
+
self.logger.debug(
|
|
1904
2095
|
"Update password of Core Share user with ID -> %s; calling -> %s",
|
|
1905
2096
|
user_id,
|
|
1906
2097
|
request_url,
|
|
@@ -1908,29 +2099,17 @@ class CoreShare(object):
|
|
|
1908
2099
|
|
|
1909
2100
|
update_data = {"password": password, "newpassword": new_password}
|
|
1910
2101
|
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
logger.debug("Admin Session has expired - try to re-authenticate...")
|
|
1923
|
-
self.authenticate_admin(revalidate=True)
|
|
1924
|
-
request_header = self.request_header_admin()
|
|
1925
|
-
retries += 1
|
|
1926
|
-
else:
|
|
1927
|
-
logger.error(
|
|
1928
|
-
"Failed to update password of Core Share user -> %s; status -> %s; error -> %s",
|
|
1929
|
-
user_id,
|
|
1930
|
-
response.status_code,
|
|
1931
|
-
response.text,
|
|
1932
|
-
)
|
|
1933
|
-
return None
|
|
2102
|
+
return self.do_request(
|
|
2103
|
+
url=request_url,
|
|
2104
|
+
method="PUT",
|
|
2105
|
+
headers=request_header,
|
|
2106
|
+
json_data=update_data,
|
|
2107
|
+
timeout=REQUEST_TIMEOUT,
|
|
2108
|
+
failure_message="Failed to update password of Core Share user with ID -> {}".format(
|
|
2109
|
+
user_id,
|
|
2110
|
+
),
|
|
2111
|
+
user_credentials=False,
|
|
2112
|
+
)
|
|
1934
2113
|
|
|
1935
2114
|
# end method definition
|
|
1936
2115
|
|
|
@@ -1938,14 +2117,22 @@ class CoreShare(object):
|
|
|
1938
2117
|
self,
|
|
1939
2118
|
user_id: str,
|
|
1940
2119
|
photo_path: str,
|
|
2120
|
+
mime_type: str = "image/jpeg",
|
|
1941
2121
|
) -> dict | None:
|
|
1942
2122
|
"""Update the Core Share user photo.
|
|
1943
2123
|
|
|
1944
2124
|
Args:
|
|
1945
|
-
user_id (str):
|
|
1946
|
-
|
|
2125
|
+
user_id (str):
|
|
2126
|
+
The Core Share user ID.
|
|
2127
|
+
photo_path (str):
|
|
2128
|
+
The file system path with the location of the photo.
|
|
2129
|
+
mime_type (str, optional):
|
|
2130
|
+
The mime type of the photo. Default is "image/jpeg".
|
|
2131
|
+
|
|
1947
2132
|
Returns:
|
|
1948
|
-
dict | None:
|
|
2133
|
+
dict | None:
|
|
2134
|
+
Dictionary with the Core Share User data or None if the request fails.
|
|
2135
|
+
|
|
1949
2136
|
"""
|
|
1950
2137
|
|
|
1951
2138
|
if not self._access_token_user:
|
|
@@ -1953,65 +2140,59 @@ class CoreShare(object):
|
|
|
1953
2140
|
|
|
1954
2141
|
# Check if the photo file exists
|
|
1955
2142
|
if not os.path.isfile(photo_path):
|
|
1956
|
-
logger.error("Photo file -> %s not found!", photo_path)
|
|
2143
|
+
self.logger.error("Photo file -> %s not found!", photo_path)
|
|
1957
2144
|
return None
|
|
1958
2145
|
|
|
1959
2146
|
try:
|
|
1960
2147
|
# Read the photo file as binary data
|
|
1961
2148
|
with open(photo_path, "rb") as image_file:
|
|
1962
2149
|
photo_data = image_file.read()
|
|
1963
|
-
except OSError
|
|
2150
|
+
except OSError:
|
|
1964
2151
|
# Handle any errors that occurred while reading the photo file
|
|
1965
|
-
logger.error(
|
|
1966
|
-
"Error reading photo file -> %s
|
|
2152
|
+
self.logger.error(
|
|
2153
|
+
"Error reading photo file -> %s",
|
|
2154
|
+
photo_path,
|
|
1967
2155
|
)
|
|
1968
2156
|
return None
|
|
1969
2157
|
|
|
1970
2158
|
request_url = self.config()["usersUrlv3"] + "/{}".format(user_id) + "/photo"
|
|
1971
2159
|
files = {
|
|
1972
|
-
"file": (photo_path, photo_data,
|
|
2160
|
+
"file": (photo_path, photo_data, mime_type),
|
|
1973
2161
|
}
|
|
1974
2162
|
|
|
1975
|
-
logger.debug(
|
|
2163
|
+
self.logger.debug(
|
|
1976
2164
|
"Update profile photo of Core Share user with ID -> %s; calling -> %s",
|
|
1977
2165
|
user_id,
|
|
1978
2166
|
request_url,
|
|
1979
2167
|
)
|
|
1980
2168
|
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
)
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
1994
|
-
self.authenticate_user(revalidate=True)
|
|
1995
|
-
retries += 1
|
|
1996
|
-
else:
|
|
1997
|
-
logger.error(
|
|
1998
|
-
"Failed to update profile photo of Core Share user with ID -> %s; status -> %s; error -> %s",
|
|
1999
|
-
user_id,
|
|
2000
|
-
response.status_code,
|
|
2001
|
-
response.text,
|
|
2002
|
-
)
|
|
2003
|
-
return None
|
|
2169
|
+
return self.do_request(
|
|
2170
|
+
url=request_url,
|
|
2171
|
+
method="POST",
|
|
2172
|
+
headers=self.request_header_user(content_type=""),
|
|
2173
|
+
files=files,
|
|
2174
|
+
timeout=REQUEST_TIMEOUT,
|
|
2175
|
+
failure_message="Failed to update profile photo of Core Share user with ID -> {}".format(
|
|
2176
|
+
user_id,
|
|
2177
|
+
),
|
|
2178
|
+
user_credentials=True,
|
|
2179
|
+
verify=False,
|
|
2180
|
+
)
|
|
2004
2181
|
|
|
2005
2182
|
# end method definition
|
|
2006
2183
|
|
|
2007
2184
|
def get_folders(self, parent_id: str) -> list | None:
|
|
2008
|
-
"""Get Core Share folders under a given parent ID.
|
|
2185
|
+
"""Get Core Share folders under a given parent ID.
|
|
2186
|
+
|
|
2187
|
+
This runs under user credentials (not admin!)
|
|
2009
2188
|
|
|
2010
2189
|
Args:
|
|
2011
|
-
parent_id (str):
|
|
2190
|
+
parent_id (str):
|
|
2191
|
+
ID of the parent folder or the root ID of a user
|
|
2012
2192
|
|
|
2013
2193
|
Returns:
|
|
2014
|
-
list | None:
|
|
2194
|
+
list | None:
|
|
2195
|
+
List with the Core Share folders data or None if the request fails.
|
|
2015
2196
|
|
|
2016
2197
|
Example response (it is a list!):
|
|
2017
2198
|
[
|
|
@@ -2061,10 +2242,11 @@ class CoreShare(object):
|
|
|
2061
2242
|
'contentOriginator': {
|
|
2062
2243
|
'id': '0D949C67-473D-448C-8F4B-B2CCA769F586',
|
|
2063
2244
|
'name': 'IDEA-TE-QA',
|
|
2064
|
-
'imageUri': '/api/v1/tenants/2595192600759637225/contentOriginator/images/0D949C67
|
|
2245
|
+
'imageUri': '/api/v1/tenants/2595192600759637225/contentOriginator/images/0D949C67'
|
|
2065
2246
|
}
|
|
2066
2247
|
}
|
|
2067
2248
|
]
|
|
2249
|
+
|
|
2068
2250
|
"""
|
|
2069
2251
|
|
|
2070
2252
|
if not self._access_token_user:
|
|
@@ -2078,32 +2260,22 @@ class CoreShare(object):
|
|
|
2078
2260
|
+ "?limit=25&order=lastModified:desc&filter=any"
|
|
2079
2261
|
)
|
|
2080
2262
|
|
|
2081
|
-
logger.debug(
|
|
2263
|
+
self.logger.debug(
|
|
2082
2264
|
"Get Core Share folders under parent -> %s; calling -> %s",
|
|
2083
2265
|
parent_id,
|
|
2084
2266
|
request_url,
|
|
2085
2267
|
)
|
|
2086
2268
|
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
request_header = self.request_header_user()
|
|
2098
|
-
retries += 1
|
|
2099
|
-
else:
|
|
2100
|
-
logger.error(
|
|
2101
|
-
"Failed to get Core Share folders under parent -> %s; status -> %s; error -> %s",
|
|
2102
|
-
parent_id,
|
|
2103
|
-
response.status_code,
|
|
2104
|
-
response.text,
|
|
2105
|
-
)
|
|
2106
|
-
return None
|
|
2269
|
+
return self.do_request(
|
|
2270
|
+
url=request_url,
|
|
2271
|
+
method="GET",
|
|
2272
|
+
headers=request_header,
|
|
2273
|
+
timeout=REQUEST_TIMEOUT,
|
|
2274
|
+
failure_message="Failed to get Core Share folders under parent -> {}".format(
|
|
2275
|
+
parent_id,
|
|
2276
|
+
),
|
|
2277
|
+
user_credentials=True,
|
|
2278
|
+
)
|
|
2107
2279
|
|
|
2108
2280
|
# end method definition
|
|
2109
2281
|
|
|
@@ -2111,48 +2283,37 @@ class CoreShare(object):
|
|
|
2111
2283
|
"""Unshare Core Share folder with a given resource ID.
|
|
2112
2284
|
|
|
2113
2285
|
Args:
|
|
2114
|
-
resource_id (str):
|
|
2286
|
+
resource_id (str):
|
|
2287
|
+
The ID of the folder (resource) to unshare with all collaborators.
|
|
2115
2288
|
|
|
2116
2289
|
Returns:
|
|
2117
|
-
dict | None:
|
|
2290
|
+
dict | None:
|
|
2291
|
+
Dictionary with the Core Share folders data or None if the request fails.
|
|
2118
2292
|
|
|
2119
|
-
Example response (it is a list!):
|
|
2120
2293
|
"""
|
|
2121
2294
|
|
|
2122
2295
|
if not self._access_token_user:
|
|
2123
2296
|
self.authenticate_user()
|
|
2124
2297
|
|
|
2125
2298
|
request_header = self.request_header_user()
|
|
2126
|
-
request_url = (
|
|
2127
|
-
self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2128
|
-
)
|
|
2299
|
+
request_url = self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2129
2300
|
|
|
2130
|
-
logger.debug(
|
|
2301
|
+
self.logger.debug(
|
|
2131
2302
|
"Unshare Core Share folder -> %s; calling -> %s",
|
|
2132
2303
|
resource_id,
|
|
2133
2304
|
request_url,
|
|
2134
2305
|
)
|
|
2135
2306
|
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
request_header = self.request_header_user()
|
|
2147
|
-
retries += 1
|
|
2148
|
-
else:
|
|
2149
|
-
logger.error(
|
|
2150
|
-
"Failed to unshare Core Share folder -> %s; status -> %s; error -> %s",
|
|
2151
|
-
resource_id,
|
|
2152
|
-
response.status_code,
|
|
2153
|
-
response.text,
|
|
2154
|
-
)
|
|
2155
|
-
return None
|
|
2307
|
+
return self.do_request(
|
|
2308
|
+
url=request_url,
|
|
2309
|
+
method="DELETE",
|
|
2310
|
+
headers=request_header,
|
|
2311
|
+
timeout=REQUEST_TIMEOUT,
|
|
2312
|
+
failure_message="Failed to unshare Core Share folder with ID -> {}".format(
|
|
2313
|
+
resource_id,
|
|
2314
|
+
),
|
|
2315
|
+
user_credentials=True,
|
|
2316
|
+
)
|
|
2156
2317
|
|
|
2157
2318
|
# end method definition
|
|
2158
2319
|
|
|
@@ -2160,12 +2321,13 @@ class CoreShare(object):
|
|
|
2160
2321
|
"""Delete Core Share folder with a given resource ID.
|
|
2161
2322
|
|
|
2162
2323
|
Args:
|
|
2163
|
-
resource_id (str):
|
|
2324
|
+
resource_id (str):
|
|
2325
|
+
The ID of the folder (resource) to delete.
|
|
2164
2326
|
|
|
2165
2327
|
Returns:
|
|
2166
|
-
dict | None:
|
|
2328
|
+
dict | None:
|
|
2329
|
+
Dictionary with the Core Share request data or None if the request fails.
|
|
2167
2330
|
|
|
2168
|
-
Example response (it is a list!):
|
|
2169
2331
|
"""
|
|
2170
2332
|
|
|
2171
2333
|
if not self._access_token_user:
|
|
@@ -2176,35 +2338,23 @@ class CoreShare(object):
|
|
|
2176
2338
|
|
|
2177
2339
|
payload = {"state": "deleted"}
|
|
2178
2340
|
|
|
2179
|
-
logger.debug(
|
|
2341
|
+
self.logger.debug(
|
|
2180
2342
|
"Delete Core Share folder -> %s; calling -> %s",
|
|
2181
2343
|
resource_id,
|
|
2182
2344
|
request_url,
|
|
2183
2345
|
)
|
|
2184
2346
|
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
2197
|
-
self.authenticate_user(revalidate=True)
|
|
2198
|
-
request_header = self.request_header_user()
|
|
2199
|
-
retries += 1
|
|
2200
|
-
else:
|
|
2201
|
-
logger.error(
|
|
2202
|
-
"Failed to delete Core Share folder -> %s; status -> %s; error -> %s",
|
|
2203
|
-
resource_id,
|
|
2204
|
-
response.status_code,
|
|
2205
|
-
response.text,
|
|
2206
|
-
)
|
|
2207
|
-
return None
|
|
2347
|
+
return self.do_request(
|
|
2348
|
+
url=request_url,
|
|
2349
|
+
method="PUT",
|
|
2350
|
+
headers=request_header,
|
|
2351
|
+
data=json.dumps(payload),
|
|
2352
|
+
timeout=REQUEST_TIMEOUT,
|
|
2353
|
+
failure_message="Failed to delete Core Share folder -> {}".format(
|
|
2354
|
+
resource_id,
|
|
2355
|
+
),
|
|
2356
|
+
user_credentials=True,
|
|
2357
|
+
)
|
|
2208
2358
|
|
|
2209
2359
|
# end method definition
|
|
2210
2360
|
|
|
@@ -2212,12 +2362,13 @@ class CoreShare(object):
|
|
|
2212
2362
|
"""Delete Core Share document with a given resource ID.
|
|
2213
2363
|
|
|
2214
2364
|
Args:
|
|
2215
|
-
resource_id (str):
|
|
2365
|
+
resource_id (str):
|
|
2366
|
+
The ID of the document (resource) to delete.
|
|
2216
2367
|
|
|
2217
2368
|
Returns:
|
|
2218
|
-
dict | None:
|
|
2369
|
+
dict | None:
|
|
2370
|
+
Dictionary with the Core Share request data or None if the request fails.
|
|
2219
2371
|
|
|
2220
|
-
Example response (it is a list!):
|
|
2221
2372
|
"""
|
|
2222
2373
|
|
|
2223
2374
|
if not self._access_token_user:
|
|
@@ -2228,47 +2379,39 @@ class CoreShare(object):
|
|
|
2228
2379
|
|
|
2229
2380
|
payload = {"state": "deleted"}
|
|
2230
2381
|
|
|
2231
|
-
logger.debug(
|
|
2382
|
+
self.logger.debug(
|
|
2232
2383
|
"Delete Core Share document -> %s; calling -> %s",
|
|
2233
2384
|
resource_id,
|
|
2234
2385
|
request_url,
|
|
2235
2386
|
)
|
|
2236
2387
|
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
2249
|
-
self.authenticate_user(revalidate=True)
|
|
2250
|
-
request_header = self.request_header_user()
|
|
2251
|
-
retries += 1
|
|
2252
|
-
else:
|
|
2253
|
-
logger.error(
|
|
2254
|
-
"Failed to delete Core Share document -> %s; status -> %s; error -> %s",
|
|
2255
|
-
resource_id,
|
|
2256
|
-
response.status_code,
|
|
2257
|
-
response.text,
|
|
2258
|
-
)
|
|
2259
|
-
return None
|
|
2388
|
+
return self.do_request(
|
|
2389
|
+
url=request_url,
|
|
2390
|
+
method="PUT",
|
|
2391
|
+
headers=request_header,
|
|
2392
|
+
data=json.dumps(payload),
|
|
2393
|
+
timeout=REQUEST_TIMEOUT,
|
|
2394
|
+
failure_message="Failed to delete Core Share document -> {}".format(
|
|
2395
|
+
resource_id,
|
|
2396
|
+
),
|
|
2397
|
+
user_credentials=True,
|
|
2398
|
+
)
|
|
2260
2399
|
|
|
2261
2400
|
# end method definition
|
|
2262
2401
|
|
|
2263
2402
|
def leave_share(self, user_id: str, resource_id: str) -> dict | None:
|
|
2264
|
-
"""Remove a Core Share user from a share (i.e. the user leaves the share)
|
|
2403
|
+
"""Remove a Core Share user from a share (i.e. the user leaves the share).
|
|
2265
2404
|
|
|
2266
2405
|
Args:
|
|
2267
|
-
user_id (str):
|
|
2268
|
-
|
|
2406
|
+
user_id (str):
|
|
2407
|
+
The Core Share user ID.
|
|
2408
|
+
resource_id (str):
|
|
2409
|
+
The Core Share ID of the shared folder.
|
|
2269
2410
|
|
|
2270
2411
|
Returns:
|
|
2271
|
-
dict | None:
|
|
2412
|
+
dict | None:
|
|
2413
|
+
Reponse of the REST call or None in case of an error.
|
|
2414
|
+
|
|
2272
2415
|
"""
|
|
2273
2416
|
|
|
2274
2417
|
if not self._access_token_user:
|
|
@@ -2276,45 +2419,29 @@ class CoreShare(object):
|
|
|
2276
2419
|
|
|
2277
2420
|
request_header = self.request_header_user()
|
|
2278
2421
|
|
|
2279
|
-
request_url = (
|
|
2280
|
-
self.config()["foldersUrlv1"]
|
|
2281
|
-
+ "/{}".format(resource_id)
|
|
2282
|
-
+ "/collaborators/"
|
|
2283
|
-
+ str(user_id)
|
|
2284
|
-
)
|
|
2422
|
+
request_url = self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators/" + str(user_id)
|
|
2285
2423
|
|
|
2286
2424
|
payload = {"action": "LEAVE_SHARE"}
|
|
2287
2425
|
|
|
2288
|
-
logger.debug(
|
|
2289
|
-
"User -> %s leaves Core Share shared folder -> %s; calling -> %s",
|
|
2426
|
+
self.logger.debug(
|
|
2427
|
+
"User with ID -> %s leaves Core Share shared folder with ID -> %s; calling -> %s",
|
|
2290
2428
|
user_id,
|
|
2291
2429
|
resource_id,
|
|
2292
2430
|
request_url,
|
|
2293
2431
|
)
|
|
2294
2432
|
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
self.authenticate_user(revalidate=True)
|
|
2308
|
-
request_header = self.request_header_user()
|
|
2309
|
-
retries += 1
|
|
2310
|
-
else:
|
|
2311
|
-
logger.error(
|
|
2312
|
-
"Failed to leave Core Share folder -> %s; status -> %s; error -> %s",
|
|
2313
|
-
resource_id,
|
|
2314
|
-
response.status_code,
|
|
2315
|
-
response.text,
|
|
2316
|
-
)
|
|
2317
|
-
return None
|
|
2433
|
+
return self.do_request(
|
|
2434
|
+
url=request_url,
|
|
2435
|
+
method="DELETE",
|
|
2436
|
+
headers=request_header,
|
|
2437
|
+
data=json.dumps(payload),
|
|
2438
|
+
timeout=REQUEST_TIMEOUT,
|
|
2439
|
+
failure_message="User with ID -> {} failed to leave Core Share folder with ID -> {}".format(
|
|
2440
|
+
user_id,
|
|
2441
|
+
resource_id,
|
|
2442
|
+
),
|
|
2443
|
+
user_credentials=True,
|
|
2444
|
+
)
|
|
2318
2445
|
|
|
2319
2446
|
# end method definition
|
|
2320
2447
|
|
|
@@ -2322,11 +2449,15 @@ class CoreShare(object):
|
|
|
2322
2449
|
"""Stop of share of a user.
|
|
2323
2450
|
|
|
2324
2451
|
Args:
|
|
2325
|
-
user_id (str):
|
|
2326
|
-
|
|
2452
|
+
user_id (str):
|
|
2453
|
+
The Core Share user ID.
|
|
2454
|
+
resource_id (str):
|
|
2455
|
+
The Core Share ID of the shared folder.
|
|
2327
2456
|
|
|
2328
2457
|
Returns:
|
|
2329
|
-
dict | None:
|
|
2458
|
+
dict | None:
|
|
2459
|
+
Response of the REST call or None in case of an error.
|
|
2460
|
+
|
|
2330
2461
|
"""
|
|
2331
2462
|
|
|
2332
2463
|
if not self._access_token_user:
|
|
@@ -2334,46 +2465,38 @@ class CoreShare(object):
|
|
|
2334
2465
|
|
|
2335
2466
|
request_header = self.request_header_user()
|
|
2336
2467
|
|
|
2337
|
-
request_url = (
|
|
2338
|
-
self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2339
|
-
)
|
|
2468
|
+
request_url = self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2340
2469
|
|
|
2341
|
-
logger.debug(
|
|
2470
|
+
self.logger.debug(
|
|
2342
2471
|
"User -> %s stops sharing Core Share shared folder -> %s; calling -> %s",
|
|
2343
2472
|
user_id,
|
|
2344
2473
|
resource_id,
|
|
2345
2474
|
request_url,
|
|
2346
2475
|
)
|
|
2347
2476
|
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
self.authenticate_user(revalidate=True)
|
|
2360
|
-
request_header = self.request_header_user()
|
|
2361
|
-
retries += 1
|
|
2362
|
-
else:
|
|
2363
|
-
logger.error(
|
|
2364
|
-
"Failed to stop sharing Core Share folder -> %s; status -> %s; error -> %s",
|
|
2365
|
-
resource_id,
|
|
2366
|
-
response.status_code,
|
|
2367
|
-
response.text,
|
|
2368
|
-
)
|
|
2369
|
-
return None
|
|
2477
|
+
return self.do_request(
|
|
2478
|
+
url=request_url,
|
|
2479
|
+
method="DELETE",
|
|
2480
|
+
headers=request_header,
|
|
2481
|
+
timeout=REQUEST_TIMEOUT,
|
|
2482
|
+
failure_message="User with ID -> {} failed to stop sharing Core Share folder with ID -> {}".format(
|
|
2483
|
+
user_id,
|
|
2484
|
+
resource_id,
|
|
2485
|
+
),
|
|
2486
|
+
user_credentials=True,
|
|
2487
|
+
)
|
|
2370
2488
|
|
|
2371
2489
|
# end method definition
|
|
2372
2490
|
|
|
2373
2491
|
def cleanup_user_files(
|
|
2374
|
-
self,
|
|
2492
|
+
self,
|
|
2493
|
+
user_id: str,
|
|
2494
|
+
user_login: str,
|
|
2495
|
+
user_password: str,
|
|
2375
2496
|
) -> bool:
|
|
2376
|
-
"""Cleanup files of a user.
|
|
2497
|
+
"""Cleanup files of a user.
|
|
2498
|
+
|
|
2499
|
+
This handles different types of resources.
|
|
2377
2500
|
* Local resources - not shared
|
|
2378
2501
|
* Resources shared by the user
|
|
2379
2502
|
* Resources shared by other users or groups
|
|
@@ -2381,12 +2504,17 @@ class CoreShare(object):
|
|
|
2381
2504
|
The Core Share admin is not entitled to do this.
|
|
2382
2505
|
|
|
2383
2506
|
Args:
|
|
2384
|
-
user_id (str):
|
|
2385
|
-
|
|
2386
|
-
|
|
2507
|
+
user_id (str):
|
|
2508
|
+
The Core Share user ID.
|
|
2509
|
+
user_login (str):
|
|
2510
|
+
The Core Share email (= login) of the user.
|
|
2511
|
+
user_password (str):
|
|
2512
|
+
The Core Share password of the user.
|
|
2387
2513
|
|
|
2388
2514
|
Returns:
|
|
2389
|
-
bool:
|
|
2515
|
+
bool:
|
|
2516
|
+
True = success, False in case of an error.
|
|
2517
|
+
|
|
2390
2518
|
"""
|
|
2391
2519
|
|
|
2392
2520
|
user = self.get_user_by_id(user_id=user_id)
|
|
@@ -2395,13 +2523,13 @@ class CoreShare(object):
|
|
|
2395
2523
|
|
|
2396
2524
|
is_confirmed = self.get_result_value(response=user, key="isConfirmed")
|
|
2397
2525
|
if not is_confirmed:
|
|
2398
|
-
logger.info(
|
|
2526
|
+
self.logger.info(
|
|
2399
2527
|
"User -> %s is not yet confirmed - so it cannot have files to cleanup.",
|
|
2400
2528
|
user_id,
|
|
2401
2529
|
)
|
|
2402
2530
|
return True
|
|
2403
2531
|
|
|
2404
|
-
logger.info("Inpersonate as user -> %s to cleanup files...", user_login)
|
|
2532
|
+
self.logger.info("Inpersonate as user -> %s to cleanup files...", user_login)
|
|
2405
2533
|
|
|
2406
2534
|
# Save admin credentials the class has been initialized with:
|
|
2407
2535
|
admin_credentials = self.credentials()
|
|
@@ -2418,24 +2546,25 @@ class CoreShare(object):
|
|
|
2418
2546
|
# Get all folders of the user:
|
|
2419
2547
|
response = self.get_folders(parent_id=user_root_folder_id)
|
|
2420
2548
|
if not response or not response["results"]:
|
|
2421
|
-
logger.info("User -> %s has no items to cleanup!", user_id)
|
|
2549
|
+
self.logger.info("User -> %s has no items to cleanup!", user_id)
|
|
2422
2550
|
else:
|
|
2423
2551
|
items = response["results"]
|
|
2424
2552
|
for item in items:
|
|
2425
2553
|
if item["isShared"]:
|
|
2426
2554
|
if item["owner"]["id"] == user_id:
|
|
2427
|
-
logger.info(
|
|
2555
|
+
self.logger.info(
|
|
2428
2556
|
"User -> %s stops sharing item -> %s (%s)...",
|
|
2429
2557
|
user_id,
|
|
2430
2558
|
item["name"],
|
|
2431
2559
|
item["id"],
|
|
2432
2560
|
)
|
|
2433
2561
|
response = self.stop_share(
|
|
2434
|
-
user_id=user_id,
|
|
2562
|
+
user_id=user_id,
|
|
2563
|
+
resource_id=item["id"],
|
|
2435
2564
|
)
|
|
2436
2565
|
if not response:
|
|
2437
2566
|
success = False
|
|
2438
|
-
logger.info(
|
|
2567
|
+
self.logger.info(
|
|
2439
2568
|
"User -> %s deletes unshared item -> %s (%s)...",
|
|
2440
2569
|
user_id,
|
|
2441
2570
|
item["name"],
|
|
@@ -2445,19 +2574,20 @@ class CoreShare(object):
|
|
|
2445
2574
|
if not response:
|
|
2446
2575
|
success = False
|
|
2447
2576
|
else:
|
|
2448
|
-
logger.info(
|
|
2577
|
+
self.logger.info(
|
|
2449
2578
|
"User -> %s leaves shared folder -> '%s' (%s)...",
|
|
2450
2579
|
user_id,
|
|
2451
2580
|
item["name"],
|
|
2452
2581
|
item["id"],
|
|
2453
2582
|
)
|
|
2454
2583
|
response = self.leave_share(
|
|
2455
|
-
user_id=user_id,
|
|
2584
|
+
user_id=user_id,
|
|
2585
|
+
resource_id=item["id"],
|
|
2456
2586
|
)
|
|
2457
2587
|
if not response:
|
|
2458
2588
|
success = False
|
|
2459
2589
|
else:
|
|
2460
|
-
logger.info(
|
|
2590
|
+
self.logger.info(
|
|
2461
2591
|
"User -> %s deletes local item -> '%s' (%s) of type -> '%s'...",
|
|
2462
2592
|
user_id,
|
|
2463
2593
|
item["name"],
|
|
@@ -2469,21 +2599,23 @@ class CoreShare(object):
|
|
|
2469
2599
|
elif item["resourceType"] == "document":
|
|
2470
2600
|
response = self.delete_document(item["id"])
|
|
2471
2601
|
else:
|
|
2472
|
-
logger.error(
|
|
2473
|
-
"Unsupport resource type -> '%s'",
|
|
2602
|
+
self.logger.error(
|
|
2603
|
+
"Unsupport resource type -> '%s'",
|
|
2604
|
+
item["resourceType"],
|
|
2474
2605
|
)
|
|
2475
2606
|
response = None
|
|
2476
2607
|
if not response:
|
|
2477
2608
|
success = False
|
|
2478
2609
|
|
|
2479
|
-
logger.info(
|
|
2610
|
+
self.logger.info(
|
|
2480
2611
|
"End inpersonation and switch back to admin account -> %s...",
|
|
2481
2612
|
admin_credentials["username"],
|
|
2482
2613
|
)
|
|
2483
2614
|
|
|
2484
2615
|
# Reset credentials to admin:
|
|
2485
2616
|
self.set_credentials(
|
|
2486
|
-
admin_credentials["username"],
|
|
2617
|
+
admin_credentials["username"],
|
|
2618
|
+
admin_credentials["password"],
|
|
2487
2619
|
)
|
|
2488
2620
|
# Authenticate as administrator the class has been initialized with:
|
|
2489
2621
|
self.authenticate_user(revalidate=True)
|
|
@@ -2496,10 +2628,13 @@ class CoreShare(object):
|
|
|
2496
2628
|
"""Get (incoming) shares of a Core Share group.
|
|
2497
2629
|
|
|
2498
2630
|
Args:
|
|
2499
|
-
group_id (str):
|
|
2631
|
+
group_id (str):
|
|
2632
|
+
The Core Share group ID.
|
|
2500
2633
|
|
|
2501
2634
|
Returns:
|
|
2502
|
-
dict | None:
|
|
2635
|
+
dict | None:
|
|
2636
|
+
Incoming shares or None if the request fails.
|
|
2637
|
+
|
|
2503
2638
|
"""
|
|
2504
2639
|
|
|
2505
2640
|
if not self._access_token_admin:
|
|
@@ -2507,38 +2642,24 @@ class CoreShare(object):
|
|
|
2507
2642
|
|
|
2508
2643
|
request_header = self.request_header_admin()
|
|
2509
2644
|
|
|
2510
|
-
request_url = (
|
|
2511
|
-
self.config()["groupsUrl"] + "/{}".format(group_id) + "/shares/incoming"
|
|
2512
|
-
)
|
|
2645
|
+
request_url = self.config()["groupsUrl"] + "/{}".format(group_id) + "/shares/incoming"
|
|
2513
2646
|
|
|
2514
|
-
logger.debug(
|
|
2647
|
+
self.logger.debug(
|
|
2515
2648
|
"Get shares of Core Share group -> %s; calling -> %s",
|
|
2516
2649
|
group_id,
|
|
2517
2650
|
request_url,
|
|
2518
2651
|
)
|
|
2519
2652
|
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
logger.debug("Session has expired - try to re-authenticate...")
|
|
2531
|
-
self.authenticate_admin(revalidate=True)
|
|
2532
|
-
request_header = self.request_header_admin()
|
|
2533
|
-
retries += 1
|
|
2534
|
-
else:
|
|
2535
|
-
logger.error(
|
|
2536
|
-
"Failed to get shares of Core Share group -> %s; status -> %s; error -> %s",
|
|
2537
|
-
group_id,
|
|
2538
|
-
response.status_code,
|
|
2539
|
-
response.text,
|
|
2540
|
-
)
|
|
2541
|
-
return None
|
|
2653
|
+
return self.do_request(
|
|
2654
|
+
url=request_url,
|
|
2655
|
+
method="GET",
|
|
2656
|
+
headers=request_header,
|
|
2657
|
+
timeout=REQUEST_TIMEOUT,
|
|
2658
|
+
failure_message="Failed to get shares of Core Share group -> {}".format(
|
|
2659
|
+
group_id,
|
|
2660
|
+
),
|
|
2661
|
+
user_credentials=False,
|
|
2662
|
+
)
|
|
2542
2663
|
|
|
2543
2664
|
# end method definition
|
|
2544
2665
|
|
|
@@ -2546,11 +2667,15 @@ class CoreShare(object):
|
|
|
2546
2667
|
"""Revoke sharing of a folder with a group.
|
|
2547
2668
|
|
|
2548
2669
|
Args:
|
|
2549
|
-
group_id (str):
|
|
2550
|
-
|
|
2670
|
+
group_id (str):
|
|
2671
|
+
The Core Share group ID.
|
|
2672
|
+
resource_id (str):
|
|
2673
|
+
The ID of the Core share folder.
|
|
2551
2674
|
|
|
2552
2675
|
Returns:
|
|
2553
|
-
dict | None:
|
|
2676
|
+
dict | None:
|
|
2677
|
+
Response or None if the request fails.
|
|
2678
|
+
|
|
2554
2679
|
"""
|
|
2555
2680
|
|
|
2556
2681
|
if not self._access_token_admin:
|
|
@@ -2559,74 +2684,64 @@ class CoreShare(object):
|
|
|
2559
2684
|
request_header = self.request_header_admin()
|
|
2560
2685
|
|
|
2561
2686
|
request_url = (
|
|
2562
|
-
self.config()["foldersUrlv1"]
|
|
2563
|
-
+ "/{}".format(resource_id)
|
|
2564
|
-
+ "/collaboratorsAsAdmin/"
|
|
2565
|
-
+ str(group_id)
|
|
2687
|
+
self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaboratorsAsAdmin/" + str(group_id)
|
|
2566
2688
|
)
|
|
2567
2689
|
|
|
2568
|
-
logger.debug(
|
|
2690
|
+
self.logger.debug(
|
|
2569
2691
|
"Revoke sharing of folder -> %s with group -> %s; calling -> %s",
|
|
2570
2692
|
resource_id,
|
|
2571
2693
|
group_id,
|
|
2572
2694
|
request_url,
|
|
2573
2695
|
)
|
|
2574
2696
|
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
self.authenticate_admin(revalidate=True)
|
|
2587
|
-
request_header = self.request_header_admin()
|
|
2588
|
-
retries += 1
|
|
2589
|
-
else:
|
|
2590
|
-
logger.error(
|
|
2591
|
-
"Failed to revoke sharing Core Share folder -> %s with group -> %s; status -> %s; error -> %s",
|
|
2592
|
-
resource_id,
|
|
2593
|
-
group_id,
|
|
2594
|
-
response.status_code,
|
|
2595
|
-
response.text,
|
|
2596
|
-
)
|
|
2597
|
-
return None
|
|
2697
|
+
return self.do_request(
|
|
2698
|
+
url=request_url,
|
|
2699
|
+
method="DELETE",
|
|
2700
|
+
headers=request_header,
|
|
2701
|
+
timeout=REQUEST_TIMEOUT,
|
|
2702
|
+
failure_message="Failed to revoke sharing Core Share folder with ID -> {} with group with ID -> {}".format(
|
|
2703
|
+
resource_id,
|
|
2704
|
+
group_id,
|
|
2705
|
+
),
|
|
2706
|
+
user_credentials=False,
|
|
2707
|
+
)
|
|
2598
2708
|
|
|
2599
2709
|
# end method definition
|
|
2600
2710
|
|
|
2601
2711
|
def cleanup_group_shares(self, group_id: str) -> bool:
|
|
2602
2712
|
"""Cleanup all incoming shares of a group.
|
|
2603
|
-
|
|
2713
|
+
|
|
2714
|
+
The Core Share admin is required to do this.
|
|
2604
2715
|
|
|
2605
2716
|
Args:
|
|
2606
|
-
group_id (str):
|
|
2717
|
+
group_id (str):
|
|
2718
|
+
The Core Share group ID.
|
|
2607
2719
|
|
|
2608
2720
|
Returns:
|
|
2609
|
-
bool:
|
|
2721
|
+
bool:
|
|
2722
|
+
True = success, False in case of an error.
|
|
2723
|
+
|
|
2610
2724
|
"""
|
|
2611
2725
|
|
|
2612
2726
|
response = self.get_group_shares(group_id=group_id)
|
|
2613
2727
|
|
|
2614
2728
|
if not response or not response["shares"]:
|
|
2615
|
-
logger.info("Group -> %s has no shares to revoke!", group_id)
|
|
2729
|
+
self.logger.info("Group -> %s has no shares to revoke!", group_id)
|
|
2616
2730
|
return True
|
|
2617
2731
|
|
|
2618
2732
|
success = True
|
|
2619
2733
|
|
|
2620
2734
|
items = response["shares"]
|
|
2621
2735
|
for item in items:
|
|
2622
|
-
logger.info(
|
|
2736
|
+
self.logger.info(
|
|
2623
2737
|
"Revoke sharing of folder -> %s (%s) with group -> %s...",
|
|
2624
2738
|
item["name"],
|
|
2625
2739
|
item["id"],
|
|
2626
2740
|
group_id,
|
|
2627
2741
|
)
|
|
2628
2742
|
response = self.revoke_group_share(
|
|
2629
|
-
group_id=group_id,
|
|
2743
|
+
group_id=group_id,
|
|
2744
|
+
resource_id=item["id"],
|
|
2630
2745
|
)
|
|
2631
2746
|
if not response:
|
|
2632
2747
|
success = False
|