pyxecm 1.6__py3-none-any.whl → 2.0.1__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 +7 -4
- pyxecm/avts.py +727 -254
- pyxecm/coreshare.py +686 -467
- 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 +163 -0
- pyxecm/customizer/api/auth/__init__.py +1 -0
- pyxecm/customizer/api/auth/functions.py +92 -0
- pyxecm/customizer/api/auth/models.py +13 -0
- pyxecm/customizer/api/auth/router.py +78 -0
- pyxecm/customizer/api/common/__init__.py +1 -0
- pyxecm/customizer/api/common/functions.py +47 -0
- pyxecm/customizer/api/common/metrics.py +92 -0
- pyxecm/customizer/api/common/models.py +21 -0
- pyxecm/customizer/api/common/payload_list.py +870 -0
- pyxecm/customizer/api/common/router.py +72 -0
- pyxecm/customizer/api/settings.py +128 -0
- pyxecm/customizer/api/terminal/__init__.py +1 -0
- pyxecm/customizer/api/terminal/router.py +87 -0
- pyxecm/customizer/api/v1_csai/__init__.py +1 -0
- pyxecm/customizer/api/v1_csai/router.py +87 -0
- pyxecm/customizer/api/v1_maintenance/__init__.py +1 -0
- pyxecm/customizer/api/v1_maintenance/functions.py +100 -0
- pyxecm/customizer/api/v1_maintenance/models.py +12 -0
- pyxecm/customizer/api/v1_maintenance/router.py +76 -0
- pyxecm/customizer/api/v1_otcs/__init__.py +1 -0
- pyxecm/customizer/api/v1_otcs/functions.py +61 -0
- pyxecm/customizer/api/v1_otcs/router.py +179 -0
- pyxecm/customizer/api/v1_payload/__init__.py +1 -0
- pyxecm/customizer/api/v1_payload/functions.py +179 -0
- pyxecm/customizer/api/v1_payload/models.py +51 -0
- pyxecm/customizer/api/v1_payload/router.py +499 -0
- pyxecm/customizer/browser_automation.py +721 -286
- pyxecm/customizer/customizer.py +1076 -1425
- pyxecm/customizer/exceptions.py +35 -0
- pyxecm/customizer/guidewire.py +1186 -0
- pyxecm/customizer/k8s.py +901 -379
- pyxecm/customizer/log.py +107 -0
- pyxecm/customizer/m365.py +2967 -920
- pyxecm/customizer/nhc.py +1169 -0
- pyxecm/customizer/openapi.py +258 -0
- pyxecm/customizer/payload.py +18228 -7820
- pyxecm/customizer/pht.py +717 -286
- pyxecm/customizer/salesforce.py +516 -342
- pyxecm/customizer/sap.py +58 -41
- pyxecm/customizer/servicenow.py +611 -372
- pyxecm/customizer/settings.py +445 -0
- pyxecm/customizer/successfactors.py +408 -346
- pyxecm/customizer/translate.py +83 -48
- pyxecm/helper/__init__.py +5 -2
- pyxecm/helper/assoc.py +83 -43
- pyxecm/helper/data.py +2406 -870
- pyxecm/helper/logadapter.py +27 -0
- pyxecm/helper/web.py +229 -101
- pyxecm/helper/xml.py +596 -171
- 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 +235 -141
- pyxecm/otawp.py +2668 -1220
- pyxecm/otca.py +569 -0
- pyxecm/otcs.py +7956 -3237
- pyxecm/otds.py +2178 -925
- pyxecm/otiv.py +36 -21
- pyxecm/otmm.py +1272 -325
- pyxecm/otpd.py +231 -127
- pyxecm-2.0.1.dist-info/METADATA +122 -0
- pyxecm-2.0.1.dist-info/RECORD +76 -0
- {pyxecm-1.6.dist-info → pyxecm-2.0.1.dist-info}/WHEEL +1 -1
- pyxecm-1.6.dist-info/METADATA +0 -53
- pyxecm-1.6.dist-info/RECORD +0 -32
- {pyxecm-1.6.dist-info → pyxecm-2.0.1.dist-info/licenses}/LICENSE +0 -0
- {pyxecm-1.6.dist-info → pyxecm-2.0.1.dist-info}/top_level.txt +0 -0
pyxecm/coreshare.py
CHANGED
|
@@ -1,91 +1,53 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
See:
|
|
4
|
-
|
|
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)
|
|
5
6
|
|
|
6
7
|
Authentication - get Client Secrets:
|
|
7
|
-
1. Login to Core Share as a Tenant Admin User
|
|
8
|
-
2. Navigate to Security
|
|
9
|
-
3. On OAuth Confidential Clients section provide Description and Redirect URLs. It will populate a
|
|
10
|
-
dialog with Client Secret.
|
|
11
|
-
4. Copy Client Secret as it will not be available anywhere once the dialog is closed.
|
|
12
|
-
|
|
13
|
-
Class: CoreShare
|
|
14
|
-
Methods:
|
|
15
|
-
|
|
16
|
-
__init__ : class initializer
|
|
17
|
-
config : Returns config data set
|
|
18
|
-
credentials: Get credentials (username + password)
|
|
19
|
-
set_credentials: Set the credentials for Core Share based on username and password.
|
|
20
|
-
|
|
21
|
-
request_header_admin: Returns the request header used for Application calls
|
|
22
|
-
that require administrator credentials
|
|
23
|
-
request_header_user: Returns the request header used for Application calls
|
|
24
|
-
that require user (non-admin) credentials.
|
|
25
|
-
do_request: call an Core Share REST API in a safe way.
|
|
26
|
-
parse_request_response: Parse the REST API responses and convert
|
|
27
|
-
them to Python dict in a safe way
|
|
28
|
-
lookup_result_value: Lookup a property value based on a provided key / value pair in the response
|
|
29
|
-
properties of a Core Share REST API call
|
|
30
|
-
exist_result_item: Check if an dict item is in the response
|
|
31
|
-
of the Core Share API call
|
|
32
|
-
get_result_value: Check if a defined value (based on a key) is in the Core Share API response
|
|
33
|
-
|
|
34
|
-
authenticate_admin : Authenticates as Admin at Core Share API
|
|
35
|
-
authenticate_user : Authenticates as Service user at Core Share API
|
|
36
|
-
|
|
37
|
-
get_groups: Get Core Share groups.
|
|
38
|
-
add_group: Add a new Core Share group.
|
|
39
|
-
get_group_members: Get Core Share group members.
|
|
40
|
-
add_group_member: Add a Core Share user to a Cire Share group.
|
|
41
|
-
remove_group_member: Remove a Core Share user from a Core Share group.
|
|
42
|
-
get_group_by_id: Get a Core Share group by its ID.
|
|
43
|
-
get_group_by_name: Get Core Share group by its name.
|
|
44
|
-
search_groups: Search Core Share group(s) by name.
|
|
45
|
-
|
|
46
|
-
get_users: Get Core Share users.
|
|
47
|
-
get_user_by_id: Get a Core Share user by its ID.
|
|
48
|
-
get_user_by_name: Get Core Share user by its first and last name.
|
|
49
|
-
search_users: Search Core Share user(s) by name / property.
|
|
50
|
-
add_user: Add a new Core Share user. This requires a Tenent Admin authorization.
|
|
51
|
-
resend_user_invite: Resend the invite for a Core Share user.
|
|
52
|
-
update_user: Update a Core Share user.
|
|
53
|
-
add_user_access_role: Add an access role to a Core Share user.
|
|
54
|
-
remove_user_access_role: Remove an access role from a Core Share user.
|
|
55
|
-
update_user_access_roles: Define the access roles of a Core Share user.
|
|
56
|
-
update_user_password: Update the password of a Core Share user.
|
|
57
|
-
update_user_photo: Update the Core Share user photo.
|
|
58
|
-
|
|
59
|
-
get_folders: Get Core Share folders under a given parent ID.
|
|
60
|
-
unshare_folder: Unshare Core Share folder with a given resource ID.
|
|
61
|
-
delete_folder: Delete Core Share folder with a given resource ID.
|
|
62
|
-
delete_document: Delete Core Share document with a given resource ID.
|
|
63
|
-
leave_share: Remove a Core Share user from a share (i.e. the user leaves the share)
|
|
64
|
-
stop_share: Stop of share of a user.
|
|
65
|
-
cleanup_user_files: Cleanup all files of a user. This handles different types of resources.
|
|
66
|
-
get_group_shares: Get (incoming) shares of a Core Share group.
|
|
67
|
-
revoke_group_share: Revoke sharing of a folder with a group.
|
|
68
|
-
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.
|
|
69
13
|
"""
|
|
70
14
|
|
|
71
15
|
__author__ = "Dr. Marc Diefenbruch"
|
|
72
|
-
__copyright__ = "Copyright 2024, OpenText"
|
|
16
|
+
__copyright__ = "Copyright (C) 2024-2025, OpenText"
|
|
73
17
|
__credits__ = ["Kai-Philip Gatzweiler"]
|
|
74
18
|
__maintainer__ = "Dr. Marc Diefenbruch"
|
|
75
19
|
__email__ = "mdiefenb@opentext.com"
|
|
76
20
|
|
|
77
|
-
import os
|
|
78
21
|
import json
|
|
79
22
|
import logging
|
|
23
|
+
import os
|
|
24
|
+
import platform
|
|
25
|
+
import sys
|
|
80
26
|
import time
|
|
81
|
-
|
|
82
27
|
import urllib.parse
|
|
83
28
|
from http import HTTPStatus
|
|
29
|
+
from importlib.metadata import version
|
|
30
|
+
|
|
84
31
|
import requests
|
|
85
32
|
|
|
86
|
-
|
|
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)
|
|
87
48
|
|
|
88
49
|
REQUEST_LOGIN_HEADERS = {
|
|
50
|
+
"User-Agent": USER_AGENT,
|
|
89
51
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
90
52
|
"Accept": "application/json",
|
|
91
53
|
}
|
|
@@ -94,9 +56,14 @@ REQUEST_TIMEOUT = 60
|
|
|
94
56
|
REQUEST_RETRY_DELAY = 20
|
|
95
57
|
REQUEST_MAX_RETRIES = 2
|
|
96
58
|
|
|
59
|
+
CONTENT_MANAGER_ROLE_ID = 5
|
|
60
|
+
GROUP_ADMIN_ROLE_ID = 3
|
|
61
|
+
|
|
97
62
|
|
|
98
|
-
class CoreShare
|
|
99
|
-
"""
|
|
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
|
|
100
67
|
|
|
101
68
|
_config: dict
|
|
102
69
|
_access_token_user = None
|
|
@@ -110,17 +77,31 @@ class CoreShare(object):
|
|
|
110
77
|
client_secret: str,
|
|
111
78
|
username: str,
|
|
112
79
|
password: str,
|
|
113
|
-
|
|
114
|
-
|
|
80
|
+
logger: logging.Logger = default_logger,
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Initialize the CoreShare object.
|
|
115
83
|
|
|
116
84
|
Args:
|
|
117
|
-
base_url (str):
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
+
|
|
123
100
|
"""
|
|
101
|
+
if logger != default_logger:
|
|
102
|
+
self.logger = logger.getChild("coreshare")
|
|
103
|
+
for logfilter in logger.filters:
|
|
104
|
+
self.logger.addFilter(logfilter)
|
|
124
105
|
|
|
125
106
|
core_share_config = {}
|
|
126
107
|
|
|
@@ -141,22 +122,14 @@ class CoreShare(object):
|
|
|
141
122
|
core_share_config["invitesUrl"] = core_share_config["restUrlv1"] + "/invites"
|
|
142
123
|
core_share_config["foldersUrlv1"] = core_share_config["restUrlv1"] + "/folders"
|
|
143
124
|
core_share_config["foldersUrlv3"] = core_share_config["restUrlv3"] + "/folders"
|
|
144
|
-
core_share_config["documentsUrlv1"] =
|
|
145
|
-
|
|
146
|
-
)
|
|
147
|
-
core_share_config["documentsUrlv3"] = (
|
|
148
|
-
core_share_config["restUrlv3"] + "/documents"
|
|
149
|
-
)
|
|
125
|
+
core_share_config["documentsUrlv1"] = core_share_config["restUrlv1"] + "/documents"
|
|
126
|
+
core_share_config["documentsUrlv3"] = core_share_config["restUrlv3"] + "/documents"
|
|
150
127
|
core_share_config["searchUrl"] = core_share_config["baseUrl"] + "/search/v1"
|
|
151
128
|
core_share_config["searchUserUrl"] = core_share_config["searchUrl"] + "/user"
|
|
152
|
-
core_share_config["searchGroupUrl"] =
|
|
153
|
-
core_share_config["searchUrl"] + "/user/group-all"
|
|
154
|
-
)
|
|
129
|
+
core_share_config["searchGroupUrl"] = core_share_config["searchUrl"] + "/user/group-all"
|
|
155
130
|
|
|
156
131
|
core_share_config["sessionsUrl"] = core_share_config["restUrlv1"] + "/sessions"
|
|
157
|
-
core_share_config["tokenUrl"] =
|
|
158
|
-
core_share_config["ssoUrl"] + "/otdsws/oauth2/token"
|
|
159
|
-
)
|
|
132
|
+
core_share_config["tokenUrl"] = core_share_config["ssoUrl"] + "/otdsws/oauth2/token"
|
|
160
133
|
core_share_config["sessionsUrl"] = core_share_config["restUrlv1"] + "/sessions"
|
|
161
134
|
|
|
162
135
|
# Tenant Admin User Authentication information (Session URL):
|
|
@@ -196,21 +169,27 @@ class CoreShare(object):
|
|
|
196
169
|
# end method definition
|
|
197
170
|
|
|
198
171
|
def config(self) -> dict:
|
|
199
|
-
"""
|
|
172
|
+
"""Return the configuration dictionary.
|
|
200
173
|
|
|
201
174
|
Returns:
|
|
202
|
-
dict:
|
|
175
|
+
dict:
|
|
176
|
+
The configuration dictionary.
|
|
177
|
+
|
|
203
178
|
"""
|
|
179
|
+
|
|
204
180
|
return self._config
|
|
205
181
|
|
|
206
182
|
# end method definition
|
|
207
183
|
|
|
208
184
|
def credentials(self) -> dict:
|
|
209
|
-
"""Get credentials (username + password)
|
|
185
|
+
"""Get credentials (username + password).
|
|
210
186
|
|
|
211
187
|
Returns:
|
|
212
|
-
dict:
|
|
188
|
+
dict:
|
|
189
|
+
A dictionary with username and password.
|
|
190
|
+
|
|
213
191
|
"""
|
|
192
|
+
|
|
214
193
|
return {
|
|
215
194
|
"username": self.config()["username"],
|
|
216
195
|
"password": self.config()["password"],
|
|
@@ -218,15 +197,16 @@ class CoreShare(object):
|
|
|
218
197
|
|
|
219
198
|
# end method definition
|
|
220
199
|
|
|
221
|
-
def set_credentials(self, username: str = "admin", password: str = ""):
|
|
200
|
+
def set_credentials(self, username: str = "admin", password: str = "") -> None:
|
|
222
201
|
"""Set the credentials for Core Share based on username and password.
|
|
223
202
|
|
|
224
203
|
Args:
|
|
225
204
|
username (str, optional): Username. Defaults to "admin".
|
|
226
205
|
password (str, optional): Password of the user. Defaults to "".
|
|
206
|
+
|
|
227
207
|
"""
|
|
228
208
|
|
|
229
|
-
logger.info("Change Core Share credentials to user -> %s...", username)
|
|
209
|
+
self.logger.info("Change Core Share credentials to user -> %s...", username)
|
|
230
210
|
|
|
231
211
|
self.config()["username"] = username
|
|
232
212
|
self.config()["password"] = password
|
|
@@ -258,17 +238,27 @@ class CoreShare(object):
|
|
|
258
238
|
# end method definition
|
|
259
239
|
|
|
260
240
|
def request_header_admin(self, content_type: str = "application/json") -> dict:
|
|
261
|
-
"""
|
|
262
|
-
|
|
263
|
-
|
|
241
|
+
"""Return the request header used for application calls that require administrator credentials.
|
|
242
|
+
|
|
243
|
+
Consists of Bearer access token and Content Type
|
|
264
244
|
|
|
265
245
|
Args:
|
|
266
|
-
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
|
+
|
|
267
254
|
Return:
|
|
268
|
-
dict:
|
|
255
|
+
dict:
|
|
256
|
+
The request header values.
|
|
257
|
+
|
|
269
258
|
"""
|
|
270
259
|
|
|
271
260
|
request_header = {
|
|
261
|
+
"User-Agent": USER_AGENT,
|
|
272
262
|
"Authorization": "Bearer {}".format(self._access_token_admin),
|
|
273
263
|
}
|
|
274
264
|
if content_type:
|
|
@@ -279,17 +269,22 @@ class CoreShare(object):
|
|
|
279
269
|
# end method definition
|
|
280
270
|
|
|
281
271
|
def request_header_user(self, content_type: str = "application/json") -> dict:
|
|
282
|
-
"""
|
|
283
|
-
|
|
284
|
-
|
|
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
|
|
285
275
|
|
|
286
276
|
Args:
|
|
287
|
-
content_type (str, optional):
|
|
277
|
+
content_type (str, optional):
|
|
278
|
+
The content type for the request.
|
|
279
|
+
|
|
288
280
|
Return:
|
|
289
|
-
dict:
|
|
281
|
+
dict:
|
|
282
|
+
The request header values.
|
|
283
|
+
|
|
290
284
|
"""
|
|
291
285
|
|
|
292
286
|
request_header = {
|
|
287
|
+
"User-Agent": USER_AGENT,
|
|
293
288
|
"Authorization": "Bearer {}".format(self._access_token_user),
|
|
294
289
|
}
|
|
295
290
|
if content_type:
|
|
@@ -319,33 +314,61 @@ class CoreShare(object):
|
|
|
319
314
|
user_credentials: bool = False,
|
|
320
315
|
verify: bool = True,
|
|
321
316
|
) -> dict | None:
|
|
322
|
-
"""Call an OTDS REST API in a safe way
|
|
317
|
+
"""Call an OTDS REST API in a safe way.
|
|
323
318
|
|
|
324
319
|
Args:
|
|
325
|
-
url (str):
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
|
342
361
|
|
|
343
362
|
Returns:
|
|
344
|
-
dict | None:
|
|
363
|
+
dict | None:
|
|
364
|
+
Response of OTDS REST API or None in case of an error.
|
|
365
|
+
|
|
345
366
|
"""
|
|
346
367
|
|
|
347
368
|
if headers is None:
|
|
348
|
-
logger.error(
|
|
369
|
+
self.logger.error(
|
|
370
|
+
"Missing request header. Cannot send request to Core Share!",
|
|
371
|
+
)
|
|
349
372
|
return None
|
|
350
373
|
|
|
351
374
|
# In case of an expired session we reauthenticate and
|
|
@@ -368,7 +391,7 @@ class CoreShare(object):
|
|
|
368
391
|
|
|
369
392
|
if response.ok:
|
|
370
393
|
if success_message:
|
|
371
|
-
logger.info(success_message)
|
|
394
|
+
self.logger.info(success_message)
|
|
372
395
|
if parse_request_response:
|
|
373
396
|
return self.parse_request_response(response)
|
|
374
397
|
else:
|
|
@@ -376,22 +399,22 @@ class CoreShare(object):
|
|
|
376
399
|
# Check if Session has expired - then re-authenticate and try once more
|
|
377
400
|
elif response.status_code == 401 and retries == 0:
|
|
378
401
|
if user_credentials:
|
|
379
|
-
logger.debug(
|
|
380
|
-
"User session has expired - try to re-authenticate..."
|
|
402
|
+
self.logger.debug(
|
|
403
|
+
"User session has expired - try to re-authenticate...",
|
|
381
404
|
)
|
|
382
405
|
self.authenticate_user(revalidate=True)
|
|
383
406
|
# Make sure to not change the content type:
|
|
384
407
|
headers = self.request_header_user(
|
|
385
|
-
content_type=headers.get("Content-Type", None)
|
|
408
|
+
content_type=headers.get("Content-Type", None),
|
|
386
409
|
)
|
|
387
410
|
else:
|
|
388
|
-
logger.warning(
|
|
389
|
-
"Admin session has expired - try to re-authenticate..."
|
|
411
|
+
self.logger.warning(
|
|
412
|
+
"Admin session has expired - try to re-authenticate...",
|
|
390
413
|
)
|
|
391
414
|
self.authenticate_admin(revalidate=True)
|
|
392
415
|
# Make sure to not change the content type:
|
|
393
416
|
headers = self.request_header_admin(
|
|
394
|
-
content_type=headers.get("Content-Type", None)
|
|
417
|
+
content_type=headers.get("Content-Type", None),
|
|
395
418
|
)
|
|
396
419
|
retries += 1
|
|
397
420
|
else:
|
|
@@ -405,7 +428,7 @@ class CoreShare(object):
|
|
|
405
428
|
response_text = response.text
|
|
406
429
|
|
|
407
430
|
if show_error:
|
|
408
|
-
logger.error(
|
|
431
|
+
self.logger.error(
|
|
409
432
|
"%s; status -> %s/%s; error -> %s",
|
|
410
433
|
failure_message,
|
|
411
434
|
response.status_code,
|
|
@@ -413,7 +436,7 @@ class CoreShare(object):
|
|
|
413
436
|
response_text,
|
|
414
437
|
)
|
|
415
438
|
elif show_warning:
|
|
416
|
-
logger.warning(
|
|
439
|
+
self.logger.warning(
|
|
417
440
|
"%s; status -> %s/%s; warning -> %s",
|
|
418
441
|
warning_message if warning_message else failure_message,
|
|
419
442
|
response.status_code,
|
|
@@ -421,7 +444,7 @@ class CoreShare(object):
|
|
|
421
444
|
response_text,
|
|
422
445
|
)
|
|
423
446
|
if content_type == "text/html":
|
|
424
|
-
logger.debug(
|
|
447
|
+
self.logger.debug(
|
|
425
448
|
"%s; status -> %s/%s; warning -> %s",
|
|
426
449
|
failure_message,
|
|
427
450
|
response.status_code,
|
|
@@ -431,45 +454,45 @@ class CoreShare(object):
|
|
|
431
454
|
return None
|
|
432
455
|
except requests.exceptions.Timeout:
|
|
433
456
|
if retries <= max_retries:
|
|
434
|
-
logger.warning(
|
|
457
|
+
self.logger.warning(
|
|
435
458
|
"Request timed out. Retrying in %s seconds...",
|
|
436
459
|
str(REQUEST_RETRY_DELAY),
|
|
437
460
|
)
|
|
438
461
|
retries += 1
|
|
439
462
|
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
440
463
|
else:
|
|
441
|
-
logger.error(
|
|
442
|
-
"%s; timeout error",
|
|
464
|
+
self.logger.error(
|
|
465
|
+
"%s; timeout error.",
|
|
443
466
|
failure_message,
|
|
444
467
|
)
|
|
445
468
|
if retry_forever:
|
|
446
469
|
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
447
|
-
logger.warning("Turn timeouts off and wait forever...")
|
|
470
|
+
self.logger.warning("Turn timeouts off and wait forever...")
|
|
448
471
|
timeout = None
|
|
449
472
|
else:
|
|
450
473
|
return None
|
|
451
474
|
except requests.exceptions.ConnectionError:
|
|
452
475
|
if retries <= max_retries:
|
|
453
|
-
logger.warning(
|
|
476
|
+
self.logger.warning(
|
|
454
477
|
"Connection error. Retrying in %s seconds...",
|
|
455
478
|
str(REQUEST_RETRY_DELAY),
|
|
456
479
|
)
|
|
457
480
|
retries += 1
|
|
458
481
|
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
459
482
|
else:
|
|
460
|
-
logger.error(
|
|
461
|
-
"%s; connection error",
|
|
483
|
+
self.logger.error(
|
|
484
|
+
"%s; connection error.",
|
|
462
485
|
failure_message,
|
|
463
486
|
)
|
|
464
487
|
if retry_forever:
|
|
465
488
|
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
466
|
-
logger.warning("Turn timeouts off and wait forever...")
|
|
489
|
+
self.logger.warning("Turn timeouts off and wait forever...")
|
|
467
490
|
timeout = None
|
|
468
491
|
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
469
492
|
else:
|
|
470
493
|
return None
|
|
471
494
|
# end try
|
|
472
|
-
logger.debug(
|
|
495
|
+
self.logger.debug(
|
|
473
496
|
"Retrying REST API %s call -> %s... (retry = %s)",
|
|
474
497
|
method,
|
|
475
498
|
url,
|
|
@@ -485,43 +508,47 @@ class CoreShare(object):
|
|
|
485
508
|
additional_error_message: str = "",
|
|
486
509
|
show_error: bool = True,
|
|
487
510
|
) -> dict | None:
|
|
488
|
-
"""
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
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.
|
|
493
517
|
|
|
494
518
|
Args:
|
|
495
|
-
response_object (object):
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
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
|
+
|
|
500
528
|
Returns:
|
|
501
529
|
dict: response information or None in case of an error
|
|
530
|
+
|
|
502
531
|
"""
|
|
503
532
|
|
|
504
533
|
if not response_object:
|
|
505
534
|
return None
|
|
506
535
|
|
|
507
536
|
try:
|
|
508
|
-
if response_object.text
|
|
509
|
-
dict_object = json.loads(response_object.text)
|
|
510
|
-
else:
|
|
511
|
-
dict_object = vars(response_object)
|
|
537
|
+
dict_object = json.loads(response_object.text) if response_object.text else vars(response_object)
|
|
512
538
|
except json.JSONDecodeError as exception:
|
|
513
539
|
if additional_error_message:
|
|
514
540
|
message = "Cannot decode response as JSon. {}; error -> {}".format(
|
|
515
|
-
additional_error_message,
|
|
541
|
+
additional_error_message,
|
|
542
|
+
exception,
|
|
516
543
|
)
|
|
517
544
|
else:
|
|
518
545
|
message = "Cannot decode response as JSon; error -> {}".format(
|
|
519
|
-
exception
|
|
546
|
+
exception,
|
|
520
547
|
)
|
|
521
548
|
if show_error:
|
|
522
|
-
logger.error(message)
|
|
549
|
+
self.logger.error(message)
|
|
523
550
|
else:
|
|
524
|
-
logger.warning(message)
|
|
551
|
+
self.logger.warning(message)
|
|
525
552
|
return None
|
|
526
553
|
else:
|
|
527
554
|
return dict_object
|
|
@@ -529,24 +556,34 @@ class CoreShare(object):
|
|
|
529
556
|
# end method definition
|
|
530
557
|
|
|
531
558
|
def lookup_result_value(
|
|
532
|
-
self,
|
|
559
|
+
self,
|
|
560
|
+
response: dict,
|
|
561
|
+
key: str,
|
|
562
|
+
value: str,
|
|
563
|
+
return_key: str,
|
|
533
564
|
) -> str | None:
|
|
534
|
-
"""Lookup a property value based on a provided key / value pair in the
|
|
535
|
-
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.
|
|
536
566
|
|
|
537
567
|
Args:
|
|
538
|
-
response (dict):
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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
|
+
|
|
542
577
|
Returns:
|
|
543
|
-
str
|
|
544
|
-
|
|
578
|
+
str | None:
|
|
579
|
+
The value of the property with the key defined in "return_key"
|
|
580
|
+
or None if the lookup fails.
|
|
581
|
+
|
|
545
582
|
"""
|
|
546
583
|
|
|
547
584
|
if not response:
|
|
548
585
|
return None
|
|
549
|
-
if
|
|
586
|
+
if "results" not in response:
|
|
550
587
|
return None
|
|
551
588
|
|
|
552
589
|
results = response["results"]
|
|
@@ -562,16 +599,28 @@ class CoreShare(object):
|
|
|
562
599
|
# end method definition
|
|
563
600
|
|
|
564
601
|
def exist_result_item(
|
|
565
|
-
self,
|
|
602
|
+
self,
|
|
603
|
+
response: dict,
|
|
604
|
+
key: str,
|
|
605
|
+
value: str,
|
|
606
|
+
results_marker: str = "results",
|
|
566
607
|
) -> bool:
|
|
567
608
|
"""Check existence of key / value pair in the response properties of a Core Share API call.
|
|
568
609
|
|
|
569
610
|
Args:
|
|
570
|
-
response (dict):
|
|
571
|
-
|
|
572
|
-
|
|
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
|
+
|
|
573
620
|
Returns:
|
|
574
|
-
bool:
|
|
621
|
+
bool:
|
|
622
|
+
True, if the value was found, False otherwise.
|
|
623
|
+
|
|
575
624
|
"""
|
|
576
625
|
|
|
577
626
|
if not response:
|
|
@@ -586,7 +635,7 @@ class CoreShare(object):
|
|
|
586
635
|
if value == result[key]:
|
|
587
636
|
return True
|
|
588
637
|
else:
|
|
589
|
-
if not
|
|
638
|
+
if key not in response:
|
|
590
639
|
return False
|
|
591
640
|
if value == response[key]:
|
|
592
641
|
return True
|
|
@@ -604,12 +653,18 @@ class CoreShare(object):
|
|
|
604
653
|
"""Get value of a result property with a given key of a Core Share API call.
|
|
605
654
|
|
|
606
655
|
Args:
|
|
607
|
-
response (dict or list):
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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
|
+
|
|
611
664
|
Returns:
|
|
612
|
-
str:
|
|
665
|
+
str:
|
|
666
|
+
The value for the key, None in case of an error.
|
|
667
|
+
|
|
613
668
|
"""
|
|
614
669
|
|
|
615
670
|
if not response:
|
|
@@ -619,7 +674,7 @@ class CoreShare(object):
|
|
|
619
674
|
if isinstance(response, list):
|
|
620
675
|
if len(response) - 1 < index:
|
|
621
676
|
return None
|
|
622
|
-
if not
|
|
677
|
+
if key not in response[index]:
|
|
623
678
|
return None
|
|
624
679
|
value = response[index][key]
|
|
625
680
|
return value
|
|
@@ -629,17 +684,13 @@ class CoreShare(object):
|
|
|
629
684
|
if "results" in response:
|
|
630
685
|
# we expect results to be a list!
|
|
631
686
|
values = response["results"]
|
|
632
|
-
if (
|
|
633
|
-
not values
|
|
634
|
-
or not isinstance(values, list)
|
|
635
|
-
or len(values) - 1 < index
|
|
636
|
-
):
|
|
687
|
+
if not values or not isinstance(values, list) or len(values) - 1 < index:
|
|
637
688
|
return None
|
|
638
|
-
if not
|
|
689
|
+
if key not in values[index]:
|
|
639
690
|
return None
|
|
640
691
|
value = values[index][key]
|
|
641
692
|
else: # simple response as dictionary - try to find key in response directly:
|
|
642
|
-
if not
|
|
693
|
+
if key not in response:
|
|
643
694
|
return None
|
|
644
695
|
value = response[key]
|
|
645
696
|
|
|
@@ -656,15 +707,20 @@ class CoreShare(object):
|
|
|
656
707
|
"""Authenticate at Core Share as Tenant Admin.
|
|
657
708
|
|
|
658
709
|
Args:
|
|
659
|
-
revalidate (bool, optional):
|
|
660
|
-
|
|
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
|
+
|
|
661
714
|
Returns:
|
|
662
|
-
str:
|
|
715
|
+
str:
|
|
716
|
+
The access token. Also stores access token in self._access_token.
|
|
717
|
+
None in case of error.
|
|
718
|
+
|
|
663
719
|
"""
|
|
664
720
|
|
|
665
721
|
# Already authenticated and session still valid?
|
|
666
722
|
if self._access_token_admin and not revalidate:
|
|
667
|
-
logger.debug(
|
|
723
|
+
self.logger.debug(
|
|
668
724
|
"Session still valid - return existing access token -> %s",
|
|
669
725
|
str(self._access_token_admin),
|
|
670
726
|
)
|
|
@@ -674,7 +730,10 @@ class CoreShare(object):
|
|
|
674
730
|
|
|
675
731
|
request_header = REQUEST_LOGIN_HEADERS
|
|
676
732
|
|
|
677
|
-
logger.debug(
|
|
733
|
+
self.logger.debug(
|
|
734
|
+
"Requesting Core Share Admin Access Token from -> %s",
|
|
735
|
+
request_url,
|
|
736
|
+
)
|
|
678
737
|
|
|
679
738
|
response = None
|
|
680
739
|
self._access_token_admin = None
|
|
@@ -686,7 +745,7 @@ class CoreShare(object):
|
|
|
686
745
|
timeout=REQUEST_TIMEOUT,
|
|
687
746
|
)
|
|
688
747
|
except requests.exceptions.ConnectionError as exception:
|
|
689
|
-
logger.warning(
|
|
748
|
+
self.logger.warning(
|
|
690
749
|
"Unable to connect to -> %s : %s",
|
|
691
750
|
request_url,
|
|
692
751
|
exception,
|
|
@@ -709,13 +768,14 @@ class CoreShare(object):
|
|
|
709
768
|
|
|
710
769
|
# Store authentication access_token:
|
|
711
770
|
self._access_token_admin = access_token
|
|
712
|
-
logger.debug(
|
|
713
|
-
"Tenant Admin Access Token -> %s",
|
|
771
|
+
self.logger.debug(
|
|
772
|
+
"Tenant Admin Access Token -> %s",
|
|
773
|
+
self._access_token_admin,
|
|
714
774
|
)
|
|
715
775
|
else:
|
|
716
776
|
return None
|
|
717
777
|
else:
|
|
718
|
-
logger.error(
|
|
778
|
+
self.logger.error(
|
|
719
779
|
"Failed to request a Core Share Tenant Admin Access Token; error -> %s",
|
|
720
780
|
response.text,
|
|
721
781
|
)
|
|
@@ -726,37 +786,38 @@ class CoreShare(object):
|
|
|
726
786
|
# end method definition
|
|
727
787
|
|
|
728
788
|
def authenticate_user(
|
|
729
|
-
self,
|
|
789
|
+
self,
|
|
790
|
+
revalidate: bool = False,
|
|
791
|
+
grant_type: str = "password",
|
|
730
792
|
) -> str | None:
|
|
731
793
|
"""Authenticate at Core Share as Tenant Service User (TSU) with client ID and client secret.
|
|
732
794
|
|
|
733
795
|
Args:
|
|
734
|
-
revalidate (bool, optional):
|
|
735
|
-
|
|
736
|
-
|
|
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
|
+
|
|
737
802
|
Returns:
|
|
738
|
-
str:
|
|
803
|
+
str:
|
|
804
|
+
The access token. Also stores access token in self._access_token.
|
|
805
|
+
None in case of error.
|
|
806
|
+
|
|
739
807
|
"""
|
|
740
808
|
|
|
741
809
|
# Already authenticated and session still valid?
|
|
742
810
|
if self._access_token_user and not revalidate:
|
|
743
|
-
logger.debug(
|
|
811
|
+
self.logger.debug(
|
|
744
812
|
"Session still valid - return existing access token -> %s",
|
|
745
813
|
str(self._access_token_user),
|
|
746
814
|
)
|
|
747
815
|
return self._access_token_user
|
|
748
816
|
|
|
749
|
-
if grant_type == "client_credentials":
|
|
750
|
-
request_url = self.config()["authorizationUrlCredentials"]
|
|
751
|
-
elif grant_type == "password":
|
|
752
|
-
request_url = self.config()["authorizationUrlPassword"]
|
|
753
|
-
else:
|
|
754
|
-
logger.error("Illegal grant type - authorization not possible!")
|
|
755
|
-
return None
|
|
756
|
-
|
|
757
817
|
request_header = REQUEST_LOGIN_HEADERS
|
|
818
|
+
request_url = self.config()["tokenUrl"]
|
|
758
819
|
|
|
759
|
-
logger.debug(
|
|
820
|
+
self.logger.debug(
|
|
760
821
|
"Requesting Core Share Tenant Service User Access Token from -> %s",
|
|
761
822
|
request_url,
|
|
762
823
|
)
|
|
@@ -764,14 +825,25 @@ class CoreShare(object):
|
|
|
764
825
|
response = None
|
|
765
826
|
self._access_token_user = None
|
|
766
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
|
+
|
|
767
838
|
try:
|
|
768
839
|
response = requests.post(
|
|
769
840
|
request_url,
|
|
770
841
|
headers=request_header,
|
|
842
|
+
data=authentication_body_post,
|
|
771
843
|
timeout=REQUEST_TIMEOUT,
|
|
772
844
|
)
|
|
773
845
|
except requests.exceptions.ConnectionError as exception:
|
|
774
|
-
logger.warning(
|
|
846
|
+
self.logger.warning(
|
|
775
847
|
"Unable to connect to -> %s : %s",
|
|
776
848
|
request_url,
|
|
777
849
|
exception,
|
|
@@ -785,11 +857,12 @@ class CoreShare(object):
|
|
|
785
857
|
else:
|
|
786
858
|
# Store authentication access_token:
|
|
787
859
|
self._access_token_user = authenticate_dict["access_token"]
|
|
788
|
-
logger.debug(
|
|
789
|
-
"Tenant Service User Access Token -> %s",
|
|
860
|
+
self.logger.debug(
|
|
861
|
+
"Tenant Service User Access Token -> %s",
|
|
862
|
+
self._access_token_user,
|
|
790
863
|
)
|
|
791
864
|
else:
|
|
792
|
-
logger.error(
|
|
865
|
+
self.logger.error(
|
|
793
866
|
"Failed to request a Core Share Tenant Service User Access Token; error -> %s",
|
|
794
867
|
response.text,
|
|
795
868
|
)
|
|
@@ -803,11 +876,14 @@ class CoreShare(object):
|
|
|
803
876
|
"""Get Core Share groups.
|
|
804
877
|
|
|
805
878
|
Args:
|
|
806
|
-
offset (int, optional):
|
|
807
|
-
|
|
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.
|
|
808
883
|
|
|
809
884
|
Returns:
|
|
810
|
-
dict | None:
|
|
885
|
+
dict | None:
|
|
886
|
+
Dictionary with the Core Share group data or None if the request fails.
|
|
811
887
|
|
|
812
888
|
Example response:
|
|
813
889
|
{
|
|
@@ -832,6 +908,7 @@ class CoreShare(object):
|
|
|
832
908
|
}
|
|
833
909
|
]
|
|
834
910
|
}
|
|
911
|
+
|
|
835
912
|
"""
|
|
836
913
|
|
|
837
914
|
if not self._access_token_user:
|
|
@@ -839,10 +916,11 @@ class CoreShare(object):
|
|
|
839
916
|
|
|
840
917
|
request_header = self.request_header_user()
|
|
841
918
|
request_url = self.config()["groupsUrl"] + "?offset={}&count={}".format(
|
|
842
|
-
offset,
|
|
919
|
+
offset,
|
|
920
|
+
count,
|
|
843
921
|
)
|
|
844
922
|
|
|
845
|
-
logger.debug("Get Core Share groups; calling -> %s", request_url)
|
|
923
|
+
self.logger.debug("Get Core Share groups; calling -> %s", request_url)
|
|
846
924
|
|
|
847
925
|
return self.do_request(
|
|
848
926
|
url=request_url,
|
|
@@ -863,11 +941,14 @@ class CoreShare(object):
|
|
|
863
941
|
"""Add a new Core Share group. This requires a Tenent Admin authorization.
|
|
864
942
|
|
|
865
943
|
Args:
|
|
866
|
-
group_name (str):
|
|
867
|
-
|
|
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.
|
|
868
948
|
|
|
869
949
|
Returns:
|
|
870
|
-
dict | None:
|
|
950
|
+
dict | None:
|
|
951
|
+
Dictionary with the Core Share Group data or None if the request fails.
|
|
871
952
|
|
|
872
953
|
Example response:
|
|
873
954
|
{
|
|
@@ -887,6 +968,7 @@ class CoreShare(object):
|
|
|
887
968
|
"isSync": false,
|
|
888
969
|
"tenantId": "2157293035593927996"
|
|
889
970
|
}
|
|
971
|
+
|
|
890
972
|
"""
|
|
891
973
|
|
|
892
974
|
if not self._access_token_admin:
|
|
@@ -897,8 +979,10 @@ class CoreShare(object):
|
|
|
897
979
|
|
|
898
980
|
payload = {"name": group_name, "description": description}
|
|
899
981
|
|
|
900
|
-
logger.debug(
|
|
901
|
-
"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,
|
|
902
986
|
)
|
|
903
987
|
|
|
904
988
|
return self.do_request(
|
|
@@ -917,10 +1001,12 @@ class CoreShare(object):
|
|
|
917
1001
|
"""Get Core Share group members.
|
|
918
1002
|
|
|
919
1003
|
Args:
|
|
920
|
-
group_id (str):
|
|
1004
|
+
group_id (str):
|
|
1005
|
+
The ID of the group to deliver the members for.
|
|
921
1006
|
|
|
922
1007
|
Returns:
|
|
923
|
-
dict | None:
|
|
1008
|
+
dict | None:
|
|
1009
|
+
Dictionary with the Core Share group membership data or None if the request fails.
|
|
924
1010
|
|
|
925
1011
|
Example response:
|
|
926
1012
|
{
|
|
@@ -949,6 +1035,7 @@ class CoreShare(object):
|
|
|
949
1035
|
],
|
|
950
1036
|
'count': 0
|
|
951
1037
|
}
|
|
1038
|
+
|
|
952
1039
|
"""
|
|
953
1040
|
|
|
954
1041
|
if not self._access_token_admin:
|
|
@@ -957,7 +1044,7 @@ class CoreShare(object):
|
|
|
957
1044
|
request_header = self.request_header_admin()
|
|
958
1045
|
request_url = self.config()["groupsUrl"] + "/{}".format(group_id) + "/members"
|
|
959
1046
|
|
|
960
|
-
logger.debug(
|
|
1047
|
+
self.logger.debug(
|
|
961
1048
|
"Get members for Core Share group with ID -> %s; calling -> %s",
|
|
962
1049
|
group_id,
|
|
963
1050
|
request_url,
|
|
@@ -969,7 +1056,7 @@ class CoreShare(object):
|
|
|
969
1056
|
headers=request_header,
|
|
970
1057
|
timeout=REQUEST_TIMEOUT,
|
|
971
1058
|
failure_message="Failed to get members of Core Share group -> '{}'".format(
|
|
972
|
-
group_id
|
|
1059
|
+
group_id,
|
|
973
1060
|
),
|
|
974
1061
|
user_credentials=False,
|
|
975
1062
|
)
|
|
@@ -977,16 +1064,25 @@ class CoreShare(object):
|
|
|
977
1064
|
# end method definition
|
|
978
1065
|
|
|
979
1066
|
def add_group_member(
|
|
980
|
-
self,
|
|
1067
|
+
self,
|
|
1068
|
+
group_id: str,
|
|
1069
|
+
user_id: str,
|
|
1070
|
+
is_group_admin: bool = False,
|
|
981
1071
|
) -> list | None:
|
|
982
1072
|
"""Add a Core Share user to a Core Share group.
|
|
983
1073
|
|
|
984
1074
|
Args:
|
|
985
|
-
group_id (str):
|
|
986
|
-
|
|
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.
|
|
987
1082
|
|
|
988
1083
|
Returns:
|
|
989
|
-
list | None:
|
|
1084
|
+
list | None:
|
|
1085
|
+
Dictionary with the Core Share group membership or None if the request fails.
|
|
990
1086
|
|
|
991
1087
|
Example Response ('errors' is only output if success = False):
|
|
992
1088
|
[
|
|
@@ -1020,6 +1116,7 @@ class CoreShare(object):
|
|
|
1020
1116
|
]
|
|
1021
1117
|
}
|
|
1022
1118
|
]
|
|
1119
|
+
|
|
1023
1120
|
"""
|
|
1024
1121
|
|
|
1025
1122
|
if not self._access_token_admin:
|
|
@@ -1033,7 +1130,7 @@ class CoreShare(object):
|
|
|
1033
1130
|
|
|
1034
1131
|
payload = {"members": [user_email], "specificGroupRole": is_group_admin}
|
|
1035
1132
|
|
|
1036
|
-
logger.debug(
|
|
1133
|
+
self.logger.debug(
|
|
1037
1134
|
"Add Core Share user -> '%s' (%s) as %s to Core Share group with ID -> %s; calling -> %s",
|
|
1038
1135
|
user_email,
|
|
1039
1136
|
user_id,
|
|
@@ -1049,7 +1146,8 @@ class CoreShare(object):
|
|
|
1049
1146
|
json_data=payload,
|
|
1050
1147
|
timeout=REQUEST_TIMEOUT,
|
|
1051
1148
|
failure_message="Failed to add Core Share user -> '{}' to Core Share group with ID -> {}".format(
|
|
1052
|
-
user_email,
|
|
1149
|
+
user_email,
|
|
1150
|
+
group_id,
|
|
1053
1151
|
),
|
|
1054
1152
|
user_credentials=False,
|
|
1055
1153
|
)
|
|
@@ -1057,16 +1155,25 @@ class CoreShare(object):
|
|
|
1057
1155
|
# end method definition
|
|
1058
1156
|
|
|
1059
1157
|
def remove_group_member(
|
|
1060
|
-
self,
|
|
1158
|
+
self,
|
|
1159
|
+
group_id: str,
|
|
1160
|
+
user_id: str,
|
|
1161
|
+
is_group_admin: bool = False,
|
|
1061
1162
|
) -> list | None:
|
|
1062
1163
|
"""Remove a Core Share user from a Core Share group.
|
|
1063
1164
|
|
|
1064
1165
|
Args:
|
|
1065
|
-
group_id (str):
|
|
1066
|
-
|
|
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.
|
|
1067
1173
|
|
|
1068
1174
|
Returns:
|
|
1069
|
-
list | None:
|
|
1175
|
+
list | None:
|
|
1176
|
+
Dictionary with the Core Share group membership or None if the request fails.
|
|
1070
1177
|
|
|
1071
1178
|
Example Response ('errors' is only output if success = False):
|
|
1072
1179
|
[
|
|
@@ -1081,6 +1188,7 @@ class CoreShare(object):
|
|
|
1081
1188
|
]
|
|
1082
1189
|
}
|
|
1083
1190
|
]
|
|
1191
|
+
|
|
1084
1192
|
"""
|
|
1085
1193
|
|
|
1086
1194
|
if not self._access_token_admin:
|
|
@@ -1094,7 +1202,7 @@ class CoreShare(object):
|
|
|
1094
1202
|
|
|
1095
1203
|
payload = {"members": [user_email], "specificGroupRole": is_group_admin}
|
|
1096
1204
|
|
|
1097
|
-
logger.debug(
|
|
1205
|
+
self.logger.debug(
|
|
1098
1206
|
"Remove Core Share user -> '%s' (%s) as %s from Core Share group with ID -> %s; calling -> %s",
|
|
1099
1207
|
user_email,
|
|
1100
1208
|
user_id,
|
|
@@ -1110,7 +1218,9 @@ class CoreShare(object):
|
|
|
1110
1218
|
json_data=payload,
|
|
1111
1219
|
timeout=REQUEST_TIMEOUT,
|
|
1112
1220
|
failure_message="Failed to remove Core Share user -> '{}' ({}) from Core Share group with ID -> {}".format(
|
|
1113
|
-
user_email,
|
|
1221
|
+
user_email,
|
|
1222
|
+
user_id,
|
|
1223
|
+
group_id,
|
|
1114
1224
|
),
|
|
1115
1225
|
user_credentials=False,
|
|
1116
1226
|
)
|
|
@@ -1121,12 +1231,13 @@ class CoreShare(object):
|
|
|
1121
1231
|
"""Get a Core Share group by its ID.
|
|
1122
1232
|
|
|
1123
1233
|
Args:
|
|
1124
|
-
|
|
1234
|
+
group_id (str):
|
|
1235
|
+
The ID of the Core Share group.
|
|
1125
1236
|
|
|
1126
1237
|
Returns:
|
|
1127
|
-
dict | None:
|
|
1238
|
+
dict | None:
|
|
1239
|
+
Dictionary with the Core Share group data or None if the request fails.
|
|
1128
1240
|
|
|
1129
|
-
Response example:
|
|
1130
1241
|
"""
|
|
1131
1242
|
|
|
1132
1243
|
if not self._access_token_admin:
|
|
@@ -1135,8 +1246,10 @@ class CoreShare(object):
|
|
|
1135
1246
|
request_header = self.request_header_admin()
|
|
1136
1247
|
request_url = self.config()["groupsUrl"] + "/" + group_id
|
|
1137
1248
|
|
|
1138
|
-
logger.debug(
|
|
1139
|
-
"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,
|
|
1140
1253
|
)
|
|
1141
1254
|
|
|
1142
1255
|
return self.do_request(
|
|
@@ -1145,7 +1258,7 @@ class CoreShare(object):
|
|
|
1145
1258
|
headers=request_header,
|
|
1146
1259
|
timeout=REQUEST_TIMEOUT,
|
|
1147
1260
|
failure_message="Failed to get Core Share group with ID -> {}".format(
|
|
1148
|
-
group_id
|
|
1261
|
+
group_id,
|
|
1149
1262
|
),
|
|
1150
1263
|
user_credentials=False,
|
|
1151
1264
|
)
|
|
@@ -1156,10 +1269,12 @@ class CoreShare(object):
|
|
|
1156
1269
|
"""Get Core Share group by its name.
|
|
1157
1270
|
|
|
1158
1271
|
Args:
|
|
1159
|
-
name (str):
|
|
1272
|
+
name (str):
|
|
1273
|
+
The name of the group to search.
|
|
1160
1274
|
|
|
1161
1275
|
Returns:
|
|
1162
|
-
dict | None:
|
|
1276
|
+
dict | None:
|
|
1277
|
+
Dictionary with the Core Share group data or None if the request fails.
|
|
1163
1278
|
|
|
1164
1279
|
Example result:
|
|
1165
1280
|
{
|
|
@@ -1181,6 +1296,7 @@ class CoreShare(object):
|
|
|
1181
1296
|
],
|
|
1182
1297
|
'total': 1
|
|
1183
1298
|
}
|
|
1299
|
+
|
|
1184
1300
|
"""
|
|
1185
1301
|
|
|
1186
1302
|
groups = self.search_groups(
|
|
@@ -1192,7 +1308,7 @@ class CoreShare(object):
|
|
|
1192
1308
|
# end method definition
|
|
1193
1309
|
|
|
1194
1310
|
def search_groups(self, query_string: str) -> dict | None:
|
|
1195
|
-
"""Search Core Share group(s)
|
|
1311
|
+
"""Search Core Share group(s) using a query string.
|
|
1196
1312
|
|
|
1197
1313
|
Args:
|
|
1198
1314
|
query_string(str): Query for the group name / property
|
|
@@ -1200,7 +1316,6 @@ class CoreShare(object):
|
|
|
1200
1316
|
Returns:
|
|
1201
1317
|
dict | None: Dictionary with the Core Share user data or None if the request fails.
|
|
1202
1318
|
|
|
1203
|
-
Example response:
|
|
1204
1319
|
"""
|
|
1205
1320
|
|
|
1206
1321
|
if not self._access_token_admin:
|
|
@@ -1209,8 +1324,10 @@ class CoreShare(object):
|
|
|
1209
1324
|
request_header = self.request_header_admin()
|
|
1210
1325
|
request_url = self.config()["searchGroupUrl"] + "?q=" + query_string
|
|
1211
1326
|
|
|
1212
|
-
logger.debug(
|
|
1213
|
-
"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,
|
|
1214
1331
|
)
|
|
1215
1332
|
|
|
1216
1333
|
return self.do_request(
|
|
@@ -1219,7 +1336,7 @@ class CoreShare(object):
|
|
|
1219
1336
|
headers=request_header,
|
|
1220
1337
|
timeout=REQUEST_TIMEOUT,
|
|
1221
1338
|
failure_message="Cannot find Core Share group with name / property -> {}".format(
|
|
1222
|
-
query_string
|
|
1339
|
+
query_string,
|
|
1223
1340
|
),
|
|
1224
1341
|
user_credentials=False,
|
|
1225
1342
|
)
|
|
@@ -1233,7 +1350,8 @@ class CoreShare(object):
|
|
|
1233
1350
|
None
|
|
1234
1351
|
|
|
1235
1352
|
Returns:
|
|
1236
|
-
dict | None:
|
|
1353
|
+
dict | None:
|
|
1354
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1237
1355
|
|
|
1238
1356
|
Example response (it is a list!):
|
|
1239
1357
|
[
|
|
@@ -1298,6 +1416,7 @@ class CoreShare(object):
|
|
|
1298
1416
|
},
|
|
1299
1417
|
...
|
|
1300
1418
|
]
|
|
1419
|
+
|
|
1301
1420
|
"""
|
|
1302
1421
|
|
|
1303
1422
|
if not self._access_token_admin:
|
|
@@ -1306,7 +1425,7 @@ class CoreShare(object):
|
|
|
1306
1425
|
request_header = self.request_header_admin()
|
|
1307
1426
|
request_url = self.config()["usersUrlv1"]
|
|
1308
1427
|
|
|
1309
|
-
logger.debug("Get Core Share users; calling -> %s", request_url)
|
|
1428
|
+
self.logger.debug("Get Core Share users; calling -> %s", request_url)
|
|
1310
1429
|
|
|
1311
1430
|
return self.do_request(
|
|
1312
1431
|
url=request_url,
|
|
@@ -1323,10 +1442,12 @@ class CoreShare(object):
|
|
|
1323
1442
|
"""Get a Core Share user by its ID.
|
|
1324
1443
|
|
|
1325
1444
|
Args:
|
|
1326
|
-
|
|
1445
|
+
user_id (str):
|
|
1446
|
+
The ID of the user.
|
|
1327
1447
|
|
|
1328
1448
|
Returns:
|
|
1329
|
-
dict | None:
|
|
1449
|
+
dict | None:
|
|
1450
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1330
1451
|
|
|
1331
1452
|
Response example:
|
|
1332
1453
|
{
|
|
@@ -1387,6 +1508,7 @@ class CoreShare(object):
|
|
|
1387
1508
|
'quota': 10737418240,
|
|
1388
1509
|
'usage': 0
|
|
1389
1510
|
}
|
|
1511
|
+
|
|
1390
1512
|
"""
|
|
1391
1513
|
|
|
1392
1514
|
if not self._access_token_user:
|
|
@@ -1395,8 +1517,10 @@ class CoreShare(object):
|
|
|
1395
1517
|
request_header = self.request_header_user()
|
|
1396
1518
|
request_url = self.config()["usersUrlv1"] + "/" + user_id
|
|
1397
1519
|
|
|
1398
|
-
logger.debug(
|
|
1399
|
-
"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,
|
|
1400
1524
|
)
|
|
1401
1525
|
|
|
1402
1526
|
return self.do_request(
|
|
@@ -1405,7 +1529,7 @@ class CoreShare(object):
|
|
|
1405
1529
|
headers=request_header,
|
|
1406
1530
|
timeout=REQUEST_TIMEOUT,
|
|
1407
1531
|
failure_message="Failed to get Core Share user with ID -> {}".format(
|
|
1408
|
-
user_id
|
|
1532
|
+
user_id,
|
|
1409
1533
|
),
|
|
1410
1534
|
user_credentials=True,
|
|
1411
1535
|
)
|
|
@@ -1413,22 +1537,30 @@ class CoreShare(object):
|
|
|
1413
1537
|
# end method definition
|
|
1414
1538
|
|
|
1415
1539
|
def get_user_by_name(
|
|
1416
|
-
self,
|
|
1540
|
+
self,
|
|
1541
|
+
first_name: str,
|
|
1542
|
+
last_name: str,
|
|
1543
|
+
user_status: str = "internal-native",
|
|
1417
1544
|
) -> dict | None:
|
|
1418
1545
|
"""Get Core Share user by its first and last name.
|
|
1419
1546
|
|
|
1420
1547
|
Args:
|
|
1421
|
-
first_name (str):
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
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
|
|
1429
1559
|
|
|
1430
1560
|
Returns:
|
|
1431
|
-
dict | None:
|
|
1561
|
+
dict | None:
|
|
1562
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1563
|
+
|
|
1432
1564
|
"""
|
|
1433
1565
|
|
|
1434
1566
|
# Search the users with this first and last name (and hope this is unique ;-).
|
|
@@ -1442,21 +1574,27 @@ class CoreShare(object):
|
|
|
1442
1574
|
# end method definition
|
|
1443
1575
|
|
|
1444
1576
|
def get_user_by_email(
|
|
1445
|
-
self,
|
|
1577
|
+
self,
|
|
1578
|
+
email: str,
|
|
1579
|
+
user_status: str = "internal-native",
|
|
1446
1580
|
) -> dict | None:
|
|
1447
1581
|
"""Get Core Share user by its email address.
|
|
1448
1582
|
|
|
1449
1583
|
Args:
|
|
1450
|
-
email (str):
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
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
|
|
1457
1593
|
|
|
1458
1594
|
Returns:
|
|
1459
|
-
dict | None:
|
|
1595
|
+
dict | None:
|
|
1596
|
+
Dictionary with the Core Share user data or None if the request fails.
|
|
1597
|
+
|
|
1460
1598
|
"""
|
|
1461
1599
|
|
|
1462
1600
|
# Search the users with this first and last name (and hope this is unique ;-).
|
|
@@ -1478,14 +1616,17 @@ class CoreShare(object):
|
|
|
1478
1616
|
"""Search Core Share user(s) by name / property. Needs to be a Tenant Administrator to do so.
|
|
1479
1617
|
|
|
1480
1618
|
Args:
|
|
1481
|
-
query_string (str):
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
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)
|
|
1489
1630
|
|
|
1490
1631
|
Returns:
|
|
1491
1632
|
dict | None: Dictionary with the Core Share user data or None if the request fails.
|
|
@@ -1524,6 +1665,7 @@ class CoreShare(object):
|
|
|
1524
1665
|
...
|
|
1525
1666
|
]
|
|
1526
1667
|
}
|
|
1668
|
+
|
|
1527
1669
|
"""
|
|
1528
1670
|
|
|
1529
1671
|
if not self._access_token_admin:
|
|
@@ -1539,8 +1681,10 @@ class CoreShare(object):
|
|
|
1539
1681
|
+ str(page_size)
|
|
1540
1682
|
)
|
|
1541
1683
|
|
|
1542
|
-
logger.debug(
|
|
1543
|
-
"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,
|
|
1544
1688
|
)
|
|
1545
1689
|
|
|
1546
1690
|
return self.do_request(
|
|
@@ -1549,7 +1693,7 @@ class CoreShare(object):
|
|
|
1549
1693
|
headers=request_header,
|
|
1550
1694
|
timeout=REQUEST_TIMEOUT,
|
|
1551
1695
|
failure_message="Failed to search Core Share user with name / property -> {}".format(
|
|
1552
|
-
query_string
|
|
1696
|
+
query_string,
|
|
1553
1697
|
),
|
|
1554
1698
|
user_credentials=False,
|
|
1555
1699
|
)
|
|
@@ -1568,15 +1712,22 @@ class CoreShare(object):
|
|
|
1568
1712
|
"""Add a new Core Share user. This requires a Tenent Admin authorization.
|
|
1569
1713
|
|
|
1570
1714
|
Args:
|
|
1571
|
-
first_name (str):
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
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
|
|
1577
1727
|
|
|
1578
1728
|
Returns:
|
|
1579
|
-
dict | None:
|
|
1729
|
+
dict | None:
|
|
1730
|
+
Dictionary with the Core Share User data or None if the request fails.
|
|
1580
1731
|
|
|
1581
1732
|
Example response:
|
|
1582
1733
|
{
|
|
@@ -1615,6 +1766,7 @@ class CoreShare(object):
|
|
|
1615
1766
|
"quota": 10737418240,
|
|
1616
1767
|
"usage": 0
|
|
1617
1768
|
}
|
|
1769
|
+
|
|
1618
1770
|
"""
|
|
1619
1771
|
|
|
1620
1772
|
if not self._access_token_admin:
|
|
@@ -1637,7 +1789,7 @@ class CoreShare(object):
|
|
|
1637
1789
|
if company:
|
|
1638
1790
|
payload["company"] = company
|
|
1639
1791
|
|
|
1640
|
-
logger.debug(
|
|
1792
|
+
self.logger.debug(
|
|
1641
1793
|
"Adding Core Share user -> %s %s; calling -> %s",
|
|
1642
1794
|
first_name,
|
|
1643
1795
|
last_name,
|
|
@@ -1651,7 +1803,9 @@ class CoreShare(object):
|
|
|
1651
1803
|
json_data=payload,
|
|
1652
1804
|
timeout=REQUEST_TIMEOUT,
|
|
1653
1805
|
failure_message="Failed to add Core Share user -> '{} {}' ({})".format(
|
|
1654
|
-
first_name,
|
|
1806
|
+
first_name,
|
|
1807
|
+
last_name,
|
|
1808
|
+
email,
|
|
1655
1809
|
),
|
|
1656
1810
|
user_credentials=False,
|
|
1657
1811
|
)
|
|
@@ -1662,10 +1816,13 @@ class CoreShare(object):
|
|
|
1662
1816
|
"""Resend the invite for a Core Share user.
|
|
1663
1817
|
|
|
1664
1818
|
Args:
|
|
1665
|
-
user_id (str):
|
|
1819
|
+
user_id (str):
|
|
1820
|
+
The Core Share user ID.
|
|
1666
1821
|
|
|
1667
1822
|
Returns:
|
|
1668
|
-
dict:
|
|
1823
|
+
dict:
|
|
1824
|
+
Response from the Core Share API.
|
|
1825
|
+
|
|
1669
1826
|
"""
|
|
1670
1827
|
|
|
1671
1828
|
if not self._access_token_admin:
|
|
@@ -1675,7 +1832,7 @@ class CoreShare(object):
|
|
|
1675
1832
|
|
|
1676
1833
|
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id)
|
|
1677
1834
|
|
|
1678
|
-
logger.debug(
|
|
1835
|
+
self.logger.debug(
|
|
1679
1836
|
"Resend invite for Core Share user with ID -> %s; calling -> %s",
|
|
1680
1837
|
user_id,
|
|
1681
1838
|
request_url,
|
|
@@ -1690,7 +1847,7 @@ class CoreShare(object):
|
|
|
1690
1847
|
json_data=update_data,
|
|
1691
1848
|
timeout=REQUEST_TIMEOUT,
|
|
1692
1849
|
failure_message="Failed to resend invite for Core Share user with ID -> {}".format(
|
|
1693
|
-
user_id
|
|
1850
|
+
user_id,
|
|
1694
1851
|
),
|
|
1695
1852
|
user_credentials=False,
|
|
1696
1853
|
)
|
|
@@ -1701,10 +1858,15 @@ class CoreShare(object):
|
|
|
1701
1858
|
"""Update a Core Share user.
|
|
1702
1859
|
|
|
1703
1860
|
Args:
|
|
1704
|
-
user_id (str):
|
|
1861
|
+
user_id (str):
|
|
1862
|
+
The ID of the Core Share user.
|
|
1863
|
+
update_data (dict):
|
|
1864
|
+
The updated user data.
|
|
1705
1865
|
|
|
1706
1866
|
Returns:
|
|
1707
|
-
dict:
|
|
1867
|
+
dict:
|
|
1868
|
+
REST response or None if the REST call has failed.
|
|
1869
|
+
|
|
1708
1870
|
"""
|
|
1709
1871
|
|
|
1710
1872
|
if not self._access_token_admin:
|
|
@@ -1714,15 +1876,15 @@ class CoreShare(object):
|
|
|
1714
1876
|
|
|
1715
1877
|
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id)
|
|
1716
1878
|
|
|
1717
|
-
logger.debug(
|
|
1879
|
+
self.logger.debug(
|
|
1718
1880
|
"Update data of Core Share user with ID -> %s; calling -> %s",
|
|
1719
1881
|
user_id,
|
|
1720
1882
|
request_url,
|
|
1721
1883
|
)
|
|
1722
1884
|
|
|
1723
|
-
if "email" in update_data and
|
|
1724
|
-
logger.warning(
|
|
1725
|
-
"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...",
|
|
1726
1888
|
)
|
|
1727
1889
|
|
|
1728
1890
|
return self.do_request(
|
|
@@ -1732,7 +1894,7 @@ class CoreShare(object):
|
|
|
1732
1894
|
json_data=update_data,
|
|
1733
1895
|
timeout=REQUEST_TIMEOUT,
|
|
1734
1896
|
failure_message="Failed to update Core Share user with ID -> {}".format(
|
|
1735
|
-
user_id
|
|
1897
|
+
user_id,
|
|
1736
1898
|
),
|
|
1737
1899
|
user_credentials=False,
|
|
1738
1900
|
)
|
|
@@ -1743,13 +1905,17 @@ class CoreShare(object):
|
|
|
1743
1905
|
"""Add an access role to a Core Share user.
|
|
1744
1906
|
|
|
1745
1907
|
Args:
|
|
1746
|
-
user_id (str):
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
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
|
|
1750
1914
|
|
|
1751
1915
|
Returns:
|
|
1752
|
-
dict:
|
|
1916
|
+
dict:
|
|
1917
|
+
Response from the Core Share API.
|
|
1918
|
+
|
|
1753
1919
|
"""
|
|
1754
1920
|
|
|
1755
1921
|
if not self._access_token_admin:
|
|
@@ -1757,14 +1923,9 @@ class CoreShare(object):
|
|
|
1757
1923
|
|
|
1758
1924
|
request_header = self.request_header_admin()
|
|
1759
1925
|
|
|
1760
|
-
request_url = (
|
|
1761
|
-
self.config()["usersUrlv1"]
|
|
1762
|
-
+ "/{}".format(user_id)
|
|
1763
|
-
+ "/roles/"
|
|
1764
|
-
+ str(role_id)
|
|
1765
|
-
)
|
|
1926
|
+
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id) + "/roles/" + str(role_id)
|
|
1766
1927
|
|
|
1767
|
-
logger.debug(
|
|
1928
|
+
self.logger.debug(
|
|
1768
1929
|
"Add access role -> %s to Core Share user with ID -> %s; calling -> %s",
|
|
1769
1930
|
str(role_id),
|
|
1770
1931
|
user_id,
|
|
@@ -1777,7 +1938,8 @@ class CoreShare(object):
|
|
|
1777
1938
|
headers=request_header,
|
|
1778
1939
|
timeout=REQUEST_TIMEOUT,
|
|
1779
1940
|
failure_message="Failed to add access role with ID -> {} to Core Share user with ID -> {}".format(
|
|
1780
|
-
role_id,
|
|
1941
|
+
role_id,
|
|
1942
|
+
user_id,
|
|
1781
1943
|
),
|
|
1782
1944
|
user_credentials=False,
|
|
1783
1945
|
)
|
|
@@ -1788,13 +1950,17 @@ class CoreShare(object):
|
|
|
1788
1950
|
"""Remove an access role from a Core Share user.
|
|
1789
1951
|
|
|
1790
1952
|
Args:
|
|
1791
|
-
user_id (str):
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
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
|
|
1795
1959
|
|
|
1796
1960
|
Returns:
|
|
1797
|
-
dict:
|
|
1961
|
+
dict:
|
|
1962
|
+
Response from the Core Share API.
|
|
1963
|
+
|
|
1798
1964
|
"""
|
|
1799
1965
|
|
|
1800
1966
|
if not self._access_token_admin:
|
|
@@ -1802,14 +1968,9 @@ class CoreShare(object):
|
|
|
1802
1968
|
|
|
1803
1969
|
request_header = self.request_header_admin()
|
|
1804
1970
|
|
|
1805
|
-
request_url = (
|
|
1806
|
-
self.config()["usersUrlv1"]
|
|
1807
|
-
+ "/{}".format(user_id)
|
|
1808
|
-
+ "/roles/"
|
|
1809
|
-
+ str(role_id)
|
|
1810
|
-
)
|
|
1971
|
+
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id) + "/roles/" + str(role_id)
|
|
1811
1972
|
|
|
1812
|
-
logger.debug(
|
|
1973
|
+
self.logger.debug(
|
|
1813
1974
|
"Remove access role with ID -> %s from Core Share user with ID -> %s; calling -> %s",
|
|
1814
1975
|
str(role_id),
|
|
1815
1976
|
user_id,
|
|
@@ -1822,7 +1983,8 @@ class CoreShare(object):
|
|
|
1822
1983
|
headers=request_header,
|
|
1823
1984
|
timeout=REQUEST_TIMEOUT,
|
|
1824
1985
|
failure_message="Failed to remove access role with ID -> {} from Core Share user with ID -> {}".format(
|
|
1825
|
-
role_id,
|
|
1986
|
+
role_id,
|
|
1987
|
+
user_id,
|
|
1826
1988
|
),
|
|
1827
1989
|
user_credentials=False,
|
|
1828
1990
|
)
|
|
@@ -1839,26 +2001,29 @@ class CoreShare(object):
|
|
|
1839
2001
|
"""Define the access roles of a Core Share user.
|
|
1840
2002
|
|
|
1841
2003
|
Args:
|
|
1842
|
-
user_id (str):
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
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.
|
|
1855
2021
|
|
|
1856
2022
|
Returns:
|
|
1857
|
-
dict:
|
|
1858
|
-
|
|
2023
|
+
dict:
|
|
2024
|
+
Response from the Core Share API.
|
|
1859
2025
|
|
|
1860
|
-
|
|
1861
|
-
GROUP_ADMIN_ROLE_ID = 3
|
|
2026
|
+
"""
|
|
1862
2027
|
|
|
1863
2028
|
response = None
|
|
1864
2029
|
|
|
@@ -1872,21 +2037,25 @@ class CoreShare(object):
|
|
|
1872
2037
|
if is_content_manager is not None:
|
|
1873
2038
|
if is_content_manager:
|
|
1874
2039
|
response = self.add_user_access_role(
|
|
1875
|
-
user_id=user_id,
|
|
2040
|
+
user_id=user_id,
|
|
2041
|
+
role_id=CONTENT_MANAGER_ROLE_ID,
|
|
1876
2042
|
)
|
|
1877
2043
|
else:
|
|
1878
2044
|
response = self.remove_user_access_role(
|
|
1879
|
-
user_id=user_id,
|
|
2045
|
+
user_id=user_id,
|
|
2046
|
+
role_id=CONTENT_MANAGER_ROLE_ID,
|
|
1880
2047
|
)
|
|
1881
2048
|
|
|
1882
2049
|
if is_group_admin is not None:
|
|
1883
2050
|
if is_group_admin:
|
|
1884
2051
|
response = self.add_user_access_role(
|
|
1885
|
-
user_id=user_id,
|
|
2052
|
+
user_id=user_id,
|
|
2053
|
+
role_id=GROUP_ADMIN_ROLE_ID,
|
|
1886
2054
|
)
|
|
1887
2055
|
else:
|
|
1888
2056
|
response = self.remove_user_access_role(
|
|
1889
|
-
user_id=user_id,
|
|
2057
|
+
user_id=user_id,
|
|
2058
|
+
role_id=GROUP_ADMIN_ROLE_ID,
|
|
1890
2059
|
)
|
|
1891
2060
|
|
|
1892
2061
|
return response
|
|
@@ -1894,17 +2063,25 @@ class CoreShare(object):
|
|
|
1894
2063
|
# end method definition
|
|
1895
2064
|
|
|
1896
2065
|
def update_user_password(
|
|
1897
|
-
self,
|
|
2066
|
+
self,
|
|
2067
|
+
user_id: str,
|
|
2068
|
+
password: str,
|
|
2069
|
+
new_password: str,
|
|
1898
2070
|
) -> dict:
|
|
1899
2071
|
"""Update the password of a Core Share user.
|
|
1900
2072
|
|
|
1901
2073
|
Args:
|
|
1902
|
-
user_id (str):
|
|
1903
|
-
|
|
1904
|
-
|
|
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.
|
|
1905
2080
|
|
|
1906
2081
|
Returns:
|
|
1907
|
-
dict:
|
|
2082
|
+
dict:
|
|
2083
|
+
Response from the Core Share API.
|
|
2084
|
+
|
|
1908
2085
|
"""
|
|
1909
2086
|
|
|
1910
2087
|
if not self._access_token_admin:
|
|
@@ -1914,7 +2091,7 @@ class CoreShare(object):
|
|
|
1914
2091
|
|
|
1915
2092
|
request_url = self.config()["usersUrlv1"] + "/{}".format(user_id)
|
|
1916
2093
|
|
|
1917
|
-
logger.debug(
|
|
2094
|
+
self.logger.debug(
|
|
1918
2095
|
"Update password of Core Share user with ID -> %s; calling -> %s",
|
|
1919
2096
|
user_id,
|
|
1920
2097
|
request_url,
|
|
@@ -1929,7 +2106,7 @@ class CoreShare(object):
|
|
|
1929
2106
|
json_data=update_data,
|
|
1930
2107
|
timeout=REQUEST_TIMEOUT,
|
|
1931
2108
|
failure_message="Failed to update password of Core Share user with ID -> {}".format(
|
|
1932
|
-
user_id
|
|
2109
|
+
user_id,
|
|
1933
2110
|
),
|
|
1934
2111
|
user_credentials=False,
|
|
1935
2112
|
)
|
|
@@ -1937,15 +2114,25 @@ class CoreShare(object):
|
|
|
1937
2114
|
# end method definition
|
|
1938
2115
|
|
|
1939
2116
|
def update_user_photo(
|
|
1940
|
-
self,
|
|
2117
|
+
self,
|
|
2118
|
+
user_id: str,
|
|
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,17 +2140,18 @@ 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
|
|
|
@@ -1972,7 +2160,7 @@ class CoreShare(object):
|
|
|
1972
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,
|
|
@@ -1985,7 +2173,7 @@ class CoreShare(object):
|
|
|
1985
2173
|
files=files,
|
|
1986
2174
|
timeout=REQUEST_TIMEOUT,
|
|
1987
2175
|
failure_message="Failed to update profile photo of Core Share user with ID -> {}".format(
|
|
1988
|
-
user_id
|
|
2176
|
+
user_id,
|
|
1989
2177
|
),
|
|
1990
2178
|
user_credentials=True,
|
|
1991
2179
|
verify=False,
|
|
@@ -1994,13 +2182,17 @@ class CoreShare(object):
|
|
|
1994
2182
|
# end method definition
|
|
1995
2183
|
|
|
1996
2184
|
def get_folders(self, parent_id: str) -> list | None:
|
|
1997
|
-
"""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!)
|
|
1998
2188
|
|
|
1999
2189
|
Args:
|
|
2000
|
-
parent_id (str):
|
|
2190
|
+
parent_id (str):
|
|
2191
|
+
ID of the parent folder or the root ID of a user
|
|
2001
2192
|
|
|
2002
2193
|
Returns:
|
|
2003
|
-
list | None:
|
|
2194
|
+
list | None:
|
|
2195
|
+
List with the Core Share folders data or None if the request fails.
|
|
2004
2196
|
|
|
2005
2197
|
Example response (it is a list!):
|
|
2006
2198
|
[
|
|
@@ -2050,10 +2242,11 @@ class CoreShare(object):
|
|
|
2050
2242
|
'contentOriginator': {
|
|
2051
2243
|
'id': '0D949C67-473D-448C-8F4B-B2CCA769F586',
|
|
2052
2244
|
'name': 'IDEA-TE-QA',
|
|
2053
|
-
'imageUri': '/api/v1/tenants/2595192600759637225/contentOriginator/images/0D949C67
|
|
2245
|
+
'imageUri': '/api/v1/tenants/2595192600759637225/contentOriginator/images/0D949C67'
|
|
2054
2246
|
}
|
|
2055
2247
|
}
|
|
2056
2248
|
]
|
|
2249
|
+
|
|
2057
2250
|
"""
|
|
2058
2251
|
|
|
2059
2252
|
if not self._access_token_user:
|
|
@@ -2067,7 +2260,7 @@ class CoreShare(object):
|
|
|
2067
2260
|
+ "?limit=25&order=lastModified:desc&filter=any"
|
|
2068
2261
|
)
|
|
2069
2262
|
|
|
2070
|
-
logger.debug(
|
|
2263
|
+
self.logger.debug(
|
|
2071
2264
|
"Get Core Share folders under parent -> %s; calling -> %s",
|
|
2072
2265
|
parent_id,
|
|
2073
2266
|
request_url,
|
|
@@ -2079,7 +2272,7 @@ class CoreShare(object):
|
|
|
2079
2272
|
headers=request_header,
|
|
2080
2273
|
timeout=REQUEST_TIMEOUT,
|
|
2081
2274
|
failure_message="Failed to get Core Share folders under parent -> {}".format(
|
|
2082
|
-
parent_id
|
|
2275
|
+
parent_id,
|
|
2083
2276
|
),
|
|
2084
2277
|
user_credentials=True,
|
|
2085
2278
|
)
|
|
@@ -2090,23 +2283,22 @@ class CoreShare(object):
|
|
|
2090
2283
|
"""Unshare Core Share folder with a given resource ID.
|
|
2091
2284
|
|
|
2092
2285
|
Args:
|
|
2093
|
-
resource_id (str):
|
|
2286
|
+
resource_id (str):
|
|
2287
|
+
The ID of the folder (resource) to unshare with all collaborators.
|
|
2094
2288
|
|
|
2095
2289
|
Returns:
|
|
2096
|
-
dict | None:
|
|
2290
|
+
dict | None:
|
|
2291
|
+
Dictionary with the Core Share folders data or None if the request fails.
|
|
2097
2292
|
|
|
2098
|
-
Example response (it is a list!):
|
|
2099
2293
|
"""
|
|
2100
2294
|
|
|
2101
2295
|
if not self._access_token_user:
|
|
2102
2296
|
self.authenticate_user()
|
|
2103
2297
|
|
|
2104
2298
|
request_header = self.request_header_user()
|
|
2105
|
-
request_url = (
|
|
2106
|
-
self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2107
|
-
)
|
|
2299
|
+
request_url = self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2108
2300
|
|
|
2109
|
-
logger.debug(
|
|
2301
|
+
self.logger.debug(
|
|
2110
2302
|
"Unshare Core Share folder -> %s; calling -> %s",
|
|
2111
2303
|
resource_id,
|
|
2112
2304
|
request_url,
|
|
@@ -2118,7 +2310,7 @@ class CoreShare(object):
|
|
|
2118
2310
|
headers=request_header,
|
|
2119
2311
|
timeout=REQUEST_TIMEOUT,
|
|
2120
2312
|
failure_message="Failed to unshare Core Share folder with ID -> {}".format(
|
|
2121
|
-
resource_id
|
|
2313
|
+
resource_id,
|
|
2122
2314
|
),
|
|
2123
2315
|
user_credentials=True,
|
|
2124
2316
|
)
|
|
@@ -2129,12 +2321,13 @@ class CoreShare(object):
|
|
|
2129
2321
|
"""Delete Core Share folder with a given resource ID.
|
|
2130
2322
|
|
|
2131
2323
|
Args:
|
|
2132
|
-
resource_id (str):
|
|
2324
|
+
resource_id (str):
|
|
2325
|
+
The ID of the folder (resource) to delete.
|
|
2133
2326
|
|
|
2134
2327
|
Returns:
|
|
2135
|
-
dict | None:
|
|
2328
|
+
dict | None:
|
|
2329
|
+
Dictionary with the Core Share request data or None if the request fails.
|
|
2136
2330
|
|
|
2137
|
-
Example response (it is a list!):
|
|
2138
2331
|
"""
|
|
2139
2332
|
|
|
2140
2333
|
if not self._access_token_user:
|
|
@@ -2145,7 +2338,7 @@ class CoreShare(object):
|
|
|
2145
2338
|
|
|
2146
2339
|
payload = {"state": "deleted"}
|
|
2147
2340
|
|
|
2148
|
-
logger.debug(
|
|
2341
|
+
self.logger.debug(
|
|
2149
2342
|
"Delete Core Share folder -> %s; calling -> %s",
|
|
2150
2343
|
resource_id,
|
|
2151
2344
|
request_url,
|
|
@@ -2158,7 +2351,7 @@ class CoreShare(object):
|
|
|
2158
2351
|
data=json.dumps(payload),
|
|
2159
2352
|
timeout=REQUEST_TIMEOUT,
|
|
2160
2353
|
failure_message="Failed to delete Core Share folder -> {}".format(
|
|
2161
|
-
resource_id
|
|
2354
|
+
resource_id,
|
|
2162
2355
|
),
|
|
2163
2356
|
user_credentials=True,
|
|
2164
2357
|
)
|
|
@@ -2169,12 +2362,13 @@ class CoreShare(object):
|
|
|
2169
2362
|
"""Delete Core Share document with a given resource ID.
|
|
2170
2363
|
|
|
2171
2364
|
Args:
|
|
2172
|
-
resource_id (str):
|
|
2365
|
+
resource_id (str):
|
|
2366
|
+
The ID of the document (resource) to delete.
|
|
2173
2367
|
|
|
2174
2368
|
Returns:
|
|
2175
|
-
dict | None:
|
|
2369
|
+
dict | None:
|
|
2370
|
+
Dictionary with the Core Share request data or None if the request fails.
|
|
2176
2371
|
|
|
2177
|
-
Example response (it is a list!):
|
|
2178
2372
|
"""
|
|
2179
2373
|
|
|
2180
2374
|
if not self._access_token_user:
|
|
@@ -2185,7 +2379,7 @@ class CoreShare(object):
|
|
|
2185
2379
|
|
|
2186
2380
|
payload = {"state": "deleted"}
|
|
2187
2381
|
|
|
2188
|
-
logger.debug(
|
|
2382
|
+
self.logger.debug(
|
|
2189
2383
|
"Delete Core Share document -> %s; calling -> %s",
|
|
2190
2384
|
resource_id,
|
|
2191
2385
|
request_url,
|
|
@@ -2198,7 +2392,7 @@ class CoreShare(object):
|
|
|
2198
2392
|
data=json.dumps(payload),
|
|
2199
2393
|
timeout=REQUEST_TIMEOUT,
|
|
2200
2394
|
failure_message="Failed to delete Core Share document -> {}".format(
|
|
2201
|
-
resource_id
|
|
2395
|
+
resource_id,
|
|
2202
2396
|
),
|
|
2203
2397
|
user_credentials=True,
|
|
2204
2398
|
)
|
|
@@ -2206,14 +2400,18 @@ class CoreShare(object):
|
|
|
2206
2400
|
# end method definition
|
|
2207
2401
|
|
|
2208
2402
|
def leave_share(self, user_id: str, resource_id: str) -> dict | None:
|
|
2209
|
-
"""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).
|
|
2210
2404
|
|
|
2211
2405
|
Args:
|
|
2212
|
-
user_id (str):
|
|
2213
|
-
|
|
2406
|
+
user_id (str):
|
|
2407
|
+
The Core Share user ID.
|
|
2408
|
+
resource_id (str):
|
|
2409
|
+
The Core Share ID of the shared folder.
|
|
2214
2410
|
|
|
2215
2411
|
Returns:
|
|
2216
|
-
dict | None:
|
|
2412
|
+
dict | None:
|
|
2413
|
+
Reponse of the REST call or None in case of an error.
|
|
2414
|
+
|
|
2217
2415
|
"""
|
|
2218
2416
|
|
|
2219
2417
|
if not self._access_token_user:
|
|
@@ -2221,16 +2419,11 @@ class CoreShare(object):
|
|
|
2221
2419
|
|
|
2222
2420
|
request_header = self.request_header_user()
|
|
2223
2421
|
|
|
2224
|
-
request_url = (
|
|
2225
|
-
self.config()["foldersUrlv1"]
|
|
2226
|
-
+ "/{}".format(resource_id)
|
|
2227
|
-
+ "/collaborators/"
|
|
2228
|
-
+ str(user_id)
|
|
2229
|
-
)
|
|
2422
|
+
request_url = self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators/" + str(user_id)
|
|
2230
2423
|
|
|
2231
2424
|
payload = {"action": "LEAVE_SHARE"}
|
|
2232
2425
|
|
|
2233
|
-
logger.debug(
|
|
2426
|
+
self.logger.debug(
|
|
2234
2427
|
"User with ID -> %s leaves Core Share shared folder with ID -> %s; calling -> %s",
|
|
2235
2428
|
user_id,
|
|
2236
2429
|
resource_id,
|
|
@@ -2244,7 +2437,8 @@ class CoreShare(object):
|
|
|
2244
2437
|
data=json.dumps(payload),
|
|
2245
2438
|
timeout=REQUEST_TIMEOUT,
|
|
2246
2439
|
failure_message="User with ID -> {} failed to leave Core Share folder with ID -> {}".format(
|
|
2247
|
-
user_id,
|
|
2440
|
+
user_id,
|
|
2441
|
+
resource_id,
|
|
2248
2442
|
),
|
|
2249
2443
|
user_credentials=True,
|
|
2250
2444
|
)
|
|
@@ -2255,11 +2449,15 @@ class CoreShare(object):
|
|
|
2255
2449
|
"""Stop of share of a user.
|
|
2256
2450
|
|
|
2257
2451
|
Args:
|
|
2258
|
-
user_id (str):
|
|
2259
|
-
|
|
2452
|
+
user_id (str):
|
|
2453
|
+
The Core Share user ID.
|
|
2454
|
+
resource_id (str):
|
|
2455
|
+
The Core Share ID of the shared folder.
|
|
2260
2456
|
|
|
2261
2457
|
Returns:
|
|
2262
|
-
dict | None:
|
|
2458
|
+
dict | None:
|
|
2459
|
+
Response of the REST call or None in case of an error.
|
|
2460
|
+
|
|
2263
2461
|
"""
|
|
2264
2462
|
|
|
2265
2463
|
if not self._access_token_user:
|
|
@@ -2267,11 +2465,9 @@ class CoreShare(object):
|
|
|
2267
2465
|
|
|
2268
2466
|
request_header = self.request_header_user()
|
|
2269
2467
|
|
|
2270
|
-
request_url = (
|
|
2271
|
-
self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2272
|
-
)
|
|
2468
|
+
request_url = self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaborators"
|
|
2273
2469
|
|
|
2274
|
-
logger.debug(
|
|
2470
|
+
self.logger.debug(
|
|
2275
2471
|
"User -> %s stops sharing Core Share shared folder -> %s; calling -> %s",
|
|
2276
2472
|
user_id,
|
|
2277
2473
|
resource_id,
|
|
@@ -2284,7 +2480,8 @@ class CoreShare(object):
|
|
|
2284
2480
|
headers=request_header,
|
|
2285
2481
|
timeout=REQUEST_TIMEOUT,
|
|
2286
2482
|
failure_message="User with ID -> {} failed to stop sharing Core Share folder with ID -> {}".format(
|
|
2287
|
-
user_id,
|
|
2483
|
+
user_id,
|
|
2484
|
+
resource_id,
|
|
2288
2485
|
),
|
|
2289
2486
|
user_credentials=True,
|
|
2290
2487
|
)
|
|
@@ -2292,9 +2489,14 @@ class CoreShare(object):
|
|
|
2292
2489
|
# end method definition
|
|
2293
2490
|
|
|
2294
2491
|
def cleanup_user_files(
|
|
2295
|
-
self,
|
|
2492
|
+
self,
|
|
2493
|
+
user_id: str,
|
|
2494
|
+
user_login: str,
|
|
2495
|
+
user_password: str,
|
|
2296
2496
|
) -> bool:
|
|
2297
|
-
"""Cleanup files of a user.
|
|
2497
|
+
"""Cleanup files of a user.
|
|
2498
|
+
|
|
2499
|
+
This handles different types of resources.
|
|
2298
2500
|
* Local resources - not shared
|
|
2299
2501
|
* Resources shared by the user
|
|
2300
2502
|
* Resources shared by other users or groups
|
|
@@ -2302,12 +2504,17 @@ class CoreShare(object):
|
|
|
2302
2504
|
The Core Share admin is not entitled to do this.
|
|
2303
2505
|
|
|
2304
2506
|
Args:
|
|
2305
|
-
user_id (str):
|
|
2306
|
-
|
|
2307
|
-
|
|
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.
|
|
2308
2513
|
|
|
2309
2514
|
Returns:
|
|
2310
|
-
bool:
|
|
2515
|
+
bool:
|
|
2516
|
+
True = success, False in case of an error.
|
|
2517
|
+
|
|
2311
2518
|
"""
|
|
2312
2519
|
|
|
2313
2520
|
user = self.get_user_by_id(user_id=user_id)
|
|
@@ -2316,13 +2523,13 @@ class CoreShare(object):
|
|
|
2316
2523
|
|
|
2317
2524
|
is_confirmed = self.get_result_value(response=user, key="isConfirmed")
|
|
2318
2525
|
if not is_confirmed:
|
|
2319
|
-
logger.info(
|
|
2526
|
+
self.logger.info(
|
|
2320
2527
|
"User -> %s is not yet confirmed - so it cannot have files to cleanup.",
|
|
2321
2528
|
user_id,
|
|
2322
2529
|
)
|
|
2323
2530
|
return True
|
|
2324
2531
|
|
|
2325
|
-
logger.info("Inpersonate as user -> %s to cleanup files...", user_login)
|
|
2532
|
+
self.logger.info("Inpersonate as user -> %s to cleanup files...", user_login)
|
|
2326
2533
|
|
|
2327
2534
|
# Save admin credentials the class has been initialized with:
|
|
2328
2535
|
admin_credentials = self.credentials()
|
|
@@ -2339,24 +2546,25 @@ class CoreShare(object):
|
|
|
2339
2546
|
# Get all folders of the user:
|
|
2340
2547
|
response = self.get_folders(parent_id=user_root_folder_id)
|
|
2341
2548
|
if not response or not response["results"]:
|
|
2342
|
-
logger.info("User -> %s has no items to cleanup!", user_id)
|
|
2549
|
+
self.logger.info("User -> %s has no items to cleanup!", user_id)
|
|
2343
2550
|
else:
|
|
2344
2551
|
items = response["results"]
|
|
2345
2552
|
for item in items:
|
|
2346
2553
|
if item["isShared"]:
|
|
2347
2554
|
if item["owner"]["id"] == user_id:
|
|
2348
|
-
logger.info(
|
|
2555
|
+
self.logger.info(
|
|
2349
2556
|
"User -> %s stops sharing item -> %s (%s)...",
|
|
2350
2557
|
user_id,
|
|
2351
2558
|
item["name"],
|
|
2352
2559
|
item["id"],
|
|
2353
2560
|
)
|
|
2354
2561
|
response = self.stop_share(
|
|
2355
|
-
user_id=user_id,
|
|
2562
|
+
user_id=user_id,
|
|
2563
|
+
resource_id=item["id"],
|
|
2356
2564
|
)
|
|
2357
2565
|
if not response:
|
|
2358
2566
|
success = False
|
|
2359
|
-
logger.info(
|
|
2567
|
+
self.logger.info(
|
|
2360
2568
|
"User -> %s deletes unshared item -> %s (%s)...",
|
|
2361
2569
|
user_id,
|
|
2362
2570
|
item["name"],
|
|
@@ -2366,19 +2574,20 @@ class CoreShare(object):
|
|
|
2366
2574
|
if not response:
|
|
2367
2575
|
success = False
|
|
2368
2576
|
else:
|
|
2369
|
-
logger.info(
|
|
2577
|
+
self.logger.info(
|
|
2370
2578
|
"User -> %s leaves shared folder -> '%s' (%s)...",
|
|
2371
2579
|
user_id,
|
|
2372
2580
|
item["name"],
|
|
2373
2581
|
item["id"],
|
|
2374
2582
|
)
|
|
2375
2583
|
response = self.leave_share(
|
|
2376
|
-
user_id=user_id,
|
|
2584
|
+
user_id=user_id,
|
|
2585
|
+
resource_id=item["id"],
|
|
2377
2586
|
)
|
|
2378
2587
|
if not response:
|
|
2379
2588
|
success = False
|
|
2380
2589
|
else:
|
|
2381
|
-
logger.info(
|
|
2590
|
+
self.logger.info(
|
|
2382
2591
|
"User -> %s deletes local item -> '%s' (%s) of type -> '%s'...",
|
|
2383
2592
|
user_id,
|
|
2384
2593
|
item["name"],
|
|
@@ -2390,21 +2599,23 @@ class CoreShare(object):
|
|
|
2390
2599
|
elif item["resourceType"] == "document":
|
|
2391
2600
|
response = self.delete_document(item["id"])
|
|
2392
2601
|
else:
|
|
2393
|
-
logger.error(
|
|
2394
|
-
"Unsupport resource type -> '%s'",
|
|
2602
|
+
self.logger.error(
|
|
2603
|
+
"Unsupport resource type -> '%s'",
|
|
2604
|
+
item["resourceType"],
|
|
2395
2605
|
)
|
|
2396
2606
|
response = None
|
|
2397
2607
|
if not response:
|
|
2398
2608
|
success = False
|
|
2399
2609
|
|
|
2400
|
-
logger.info(
|
|
2610
|
+
self.logger.info(
|
|
2401
2611
|
"End inpersonation and switch back to admin account -> %s...",
|
|
2402
2612
|
admin_credentials["username"],
|
|
2403
2613
|
)
|
|
2404
2614
|
|
|
2405
2615
|
# Reset credentials to admin:
|
|
2406
2616
|
self.set_credentials(
|
|
2407
|
-
admin_credentials["username"],
|
|
2617
|
+
admin_credentials["username"],
|
|
2618
|
+
admin_credentials["password"],
|
|
2408
2619
|
)
|
|
2409
2620
|
# Authenticate as administrator the class has been initialized with:
|
|
2410
2621
|
self.authenticate_user(revalidate=True)
|
|
@@ -2417,10 +2628,13 @@ class CoreShare(object):
|
|
|
2417
2628
|
"""Get (incoming) shares of a Core Share group.
|
|
2418
2629
|
|
|
2419
2630
|
Args:
|
|
2420
|
-
group_id (str):
|
|
2631
|
+
group_id (str):
|
|
2632
|
+
The Core Share group ID.
|
|
2421
2633
|
|
|
2422
2634
|
Returns:
|
|
2423
|
-
dict | None:
|
|
2635
|
+
dict | None:
|
|
2636
|
+
Incoming shares or None if the request fails.
|
|
2637
|
+
|
|
2424
2638
|
"""
|
|
2425
2639
|
|
|
2426
2640
|
if not self._access_token_admin:
|
|
@@ -2428,11 +2642,9 @@ class CoreShare(object):
|
|
|
2428
2642
|
|
|
2429
2643
|
request_header = self.request_header_admin()
|
|
2430
2644
|
|
|
2431
|
-
request_url = (
|
|
2432
|
-
self.config()["groupsUrl"] + "/{}".format(group_id) + "/shares/incoming"
|
|
2433
|
-
)
|
|
2645
|
+
request_url = self.config()["groupsUrl"] + "/{}".format(group_id) + "/shares/incoming"
|
|
2434
2646
|
|
|
2435
|
-
logger.debug(
|
|
2647
|
+
self.logger.debug(
|
|
2436
2648
|
"Get shares of Core Share group -> %s; calling -> %s",
|
|
2437
2649
|
group_id,
|
|
2438
2650
|
request_url,
|
|
@@ -2444,7 +2656,7 @@ class CoreShare(object):
|
|
|
2444
2656
|
headers=request_header,
|
|
2445
2657
|
timeout=REQUEST_TIMEOUT,
|
|
2446
2658
|
failure_message="Failed to get shares of Core Share group -> {}".format(
|
|
2447
|
-
group_id
|
|
2659
|
+
group_id,
|
|
2448
2660
|
),
|
|
2449
2661
|
user_credentials=False,
|
|
2450
2662
|
)
|
|
@@ -2455,11 +2667,15 @@ class CoreShare(object):
|
|
|
2455
2667
|
"""Revoke sharing of a folder with a group.
|
|
2456
2668
|
|
|
2457
2669
|
Args:
|
|
2458
|
-
group_id (str):
|
|
2459
|
-
|
|
2670
|
+
group_id (str):
|
|
2671
|
+
The Core Share group ID.
|
|
2672
|
+
resource_id (str):
|
|
2673
|
+
The ID of the Core share folder.
|
|
2460
2674
|
|
|
2461
2675
|
Returns:
|
|
2462
|
-
dict | None:
|
|
2676
|
+
dict | None:
|
|
2677
|
+
Response or None if the request fails.
|
|
2678
|
+
|
|
2463
2679
|
"""
|
|
2464
2680
|
|
|
2465
2681
|
if not self._access_token_admin:
|
|
@@ -2468,13 +2684,10 @@ class CoreShare(object):
|
|
|
2468
2684
|
request_header = self.request_header_admin()
|
|
2469
2685
|
|
|
2470
2686
|
request_url = (
|
|
2471
|
-
self.config()["foldersUrlv1"]
|
|
2472
|
-
+ "/{}".format(resource_id)
|
|
2473
|
-
+ "/collaboratorsAsAdmin/"
|
|
2474
|
-
+ str(group_id)
|
|
2687
|
+
self.config()["foldersUrlv1"] + "/{}".format(resource_id) + "/collaboratorsAsAdmin/" + str(group_id)
|
|
2475
2688
|
)
|
|
2476
2689
|
|
|
2477
|
-
logger.debug(
|
|
2690
|
+
self.logger.debug(
|
|
2478
2691
|
"Revoke sharing of folder -> %s with group -> %s; calling -> %s",
|
|
2479
2692
|
resource_id,
|
|
2480
2693
|
group_id,
|
|
@@ -2487,7 +2700,8 @@ class CoreShare(object):
|
|
|
2487
2700
|
headers=request_header,
|
|
2488
2701
|
timeout=REQUEST_TIMEOUT,
|
|
2489
2702
|
failure_message="Failed to revoke sharing Core Share folder with ID -> {} with group with ID -> {}".format(
|
|
2490
|
-
resource_id,
|
|
2703
|
+
resource_id,
|
|
2704
|
+
group_id,
|
|
2491
2705
|
),
|
|
2492
2706
|
user_credentials=False,
|
|
2493
2707
|
)
|
|
@@ -2496,33 +2710,38 @@ class CoreShare(object):
|
|
|
2496
2710
|
|
|
2497
2711
|
def cleanup_group_shares(self, group_id: str) -> bool:
|
|
2498
2712
|
"""Cleanup all incoming shares of a group.
|
|
2499
|
-
|
|
2713
|
+
|
|
2714
|
+
The Core Share admin is required to do this.
|
|
2500
2715
|
|
|
2501
2716
|
Args:
|
|
2502
|
-
group_id (str):
|
|
2717
|
+
group_id (str):
|
|
2718
|
+
The Core Share group ID.
|
|
2503
2719
|
|
|
2504
2720
|
Returns:
|
|
2505
|
-
bool:
|
|
2721
|
+
bool:
|
|
2722
|
+
True = success, False in case of an error.
|
|
2723
|
+
|
|
2506
2724
|
"""
|
|
2507
2725
|
|
|
2508
2726
|
response = self.get_group_shares(group_id=group_id)
|
|
2509
2727
|
|
|
2510
2728
|
if not response or not response["shares"]:
|
|
2511
|
-
logger.info("Group -> %s has no shares to revoke!", group_id)
|
|
2729
|
+
self.logger.info("Group -> %s has no shares to revoke!", group_id)
|
|
2512
2730
|
return True
|
|
2513
2731
|
|
|
2514
2732
|
success = True
|
|
2515
2733
|
|
|
2516
2734
|
items = response["shares"]
|
|
2517
2735
|
for item in items:
|
|
2518
|
-
logger.info(
|
|
2736
|
+
self.logger.info(
|
|
2519
2737
|
"Revoke sharing of folder -> %s (%s) with group -> %s...",
|
|
2520
2738
|
item["name"],
|
|
2521
2739
|
item["id"],
|
|
2522
2740
|
group_id,
|
|
2523
2741
|
)
|
|
2524
2742
|
response = self.revoke_group_share(
|
|
2525
|
-
group_id=group_id,
|
|
2743
|
+
group_id=group_id,
|
|
2744
|
+
resource_id=item["id"],
|
|
2526
2745
|
)
|
|
2527
2746
|
if not response:
|
|
2528
2747
|
success = False
|