Skip to content

Commit 76a754b

Browse files
author
Nivedithaa Mahendran
committed
update user creation api for version >= 9.1
1 parent cc1c0ce commit 76a754b

2 files changed

Lines changed: 128 additions & 27 deletions

File tree

src/mas/devops/users.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ def get_or_create_user(self, payload):
232232
their existing record is returned without modification. If the user doesn't exist,
233233
they are created with the provided payload.
234234
235+
For MAS version >= 9.1, this method uses the Manage API masapiuser endpoint.
236+
For earlier versions, it uses the Core API v3/users endpoint.
237+
235238
Args:
236239
payload (dict): User definition dictionary containing user details.
237240
Must include "id" field as the unique identifier.
@@ -250,21 +253,46 @@ def get_or_create_user(self, payload):
250253

251254
self.logger.info(f"Creating new user {payload['id']}")
252255

253-
url = f"{self.mas_api_url_internal}/v3/users"
254-
querystring = {}
255-
headers = {
256-
"Content-Type": "application/json",
257-
"x-access-token": self.superuser_auth_token
258-
}
259-
response = requests.post(
260-
url,
261-
json=payload,
262-
headers=headers,
263-
params=querystring,
264-
verify=self.core_internal_ca_pem_file_path
265-
)
266-
if response.status_code == 201:
267-
return response.json()
256+
# For MAS version >= 9.1, use the Manage API masapiuser endpoint
257+
if Version(self.mas_version) >= Version('9.1'):
258+
# Get MAXADMIN API key for authentication
259+
maxadmin_manage_api_key = self.create_or_get_manage_api_key_for_user(MASUserUtils.MAXADMIN, temporary=True)
260+
261+
url = f"{self.manage_api_url_internal}/maximo/api/os/masapiuser"
262+
querystring = {
263+
"lean": 1
264+
}
265+
headers = {
266+
"Content-Type": "application/json",
267+
"apikey": maxadmin_manage_api_key["apikey"]
268+
}
269+
response = requests.post(
270+
url,
271+
json=payload,
272+
headers=headers,
273+
params=querystring,
274+
cert=self.manage_internal_client_pem_file_path,
275+
verify=self.manage_internal_ca_pem_file_path
276+
)
277+
if response.status_code == 201:
278+
return response.json()
279+
else:
280+
# For earlier versions, use the Core API v3/users endpoint
281+
url = f"{self.mas_api_url_internal}/v3/users"
282+
querystring = {}
283+
headers = {
284+
"Content-Type": "application/json",
285+
"x-access-token": self.superuser_auth_token
286+
}
287+
response = requests.post(
288+
url,
289+
json=payload,
290+
headers=headers,
291+
params=querystring,
292+
verify=self.core_internal_ca_pem_file_path
293+
)
294+
if response.status_code == 201:
295+
return response.json()
268296

269297
# if response.status_code == 409:
270298
# json = response.json()

test/src/test_users.py

Lines changed: 85 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,36 @@ def mock_manage_api_key(requests_mock):
138138
Setup mock Manage APIs for setting up an API Key
139139
'''
140140
user_id = "user1"
141-
apikey = {"userid": user_id, "href": f"https://{MANAGE_API_URL}/maximo/api/os/mxapikey/theapikeyid"}
141+
apikey = {"userid": user_id, "apikey": "test-api-key-12345", "href": f"https://{MANAGE_API_URL}/maximo/api/os/mxapikey/theapikeyid"} # pragma: allowlist secret
142+
143+
# Also setup for MAXADMIN user
144+
maxadmin_apikey = {"userid": "MAXADMIN", "apikey": "maxadmin-api-key-67890", "href": f"https://{MANAGE_API_URL}/maximo/api/os/mxapikey/maxadminapikeyid"} # pragma: allowlist secret
145+
146+
def maxadmin_matcher(req):
147+
return req.json().get("userid") == "MAXADMIN" and req.verify == PEM_PATH and req.cert == PEM_PATH
148+
149+
def user1_matcher(req):
150+
return req.json().get("userid") == user_id and req.verify == PEM_PATH and req.cert == PEM_PATH
151+
152+
# Mock for MAXADMIN API key creation (returns 400 - key already exists)
153+
requests_mock.post(
154+
f"{MANAGE_API_URL}/maximo/api/os/mxapiapikey?ccm=1&lean=1",
155+
request_headers={"content-type": "application/json"},
156+
json={"Error": {"reasonCode": "BMXAA10051E", "message": "Only one API key allowed per user"}},
157+
status_code=400,
158+
additional_matcher=maxadmin_matcher
159+
)
142160

161+
# Mock for user1 API key creation
143162
requests_mock.post(
144163
f"{MANAGE_API_URL}/maximo/api/os/mxapiapikey?ccm=1&lean=1",
145164
request_headers={"content-type": "application/json"},
146165
json={"id": user_id},
147166
status_code=201,
148-
additional_matcher=lambda req: additional_matcher(req, json={"expiration": -1, "userid": user_id}, cert=PEM_PATH)
167+
additional_matcher=user1_matcher
149168
)
150169

170+
# Mock for user1 API key retrieval
151171
requests_mock.get(
152172
f"{MANAGE_API_URL}/maximo/api/os/mxapiapikey?ccm=1&lean=1&oslc.select=*&oslc.where=userid=\"{user_id}\"",
153173
request_headers={"accept": "application/json"},
@@ -156,7 +176,16 @@ def mock_manage_api_key(requests_mock):
156176
additional_matcher=lambda req: additional_matcher(req, cert=PEM_PATH)
157177
)
158178

159-
yield apikey
179+
# Mock for MAXADMIN API key retrieval (returns existing key)
180+
requests_mock.get(
181+
f"{MANAGE_API_URL}/maximo/api/os/mxapiapikey?ccm=1&lean=1&oslc.select=*&oslc.where=userid=\"MAXADMIN\"",
182+
request_headers={"accept": "application/json"},
183+
json={"member": [maxadmin_apikey]},
184+
status_code=200,
185+
additional_matcher=lambda req: additional_matcher(req, cert=PEM_PATH)
186+
)
187+
188+
yield maxadmin_apikey
160189

161190

162191
def test_admin_internal_ca_pem_file_path(user_utils, mock_named_temporary_file, mock_atexit):
@@ -319,55 +348,99 @@ def test_get_user_error(user_utils, requests_mock):
319348
assert get.call_count == 1
320349

321350

322-
def test_get_or_create_user_exists(user_utils, requests_mock):
351+
def test_get_or_create_user_exists(user_utils, requests_mock, mock_manage_api_key):
323352
user_id = "user1"
324353
get = mock_get_user_200(requests_mock, user_id)
325354

326-
post = requests_mock.post(
355+
# Mock Core API endpoint for version < 9.1
356+
post_core = requests_mock.post(
327357
f"{MAS_API_URL}/v3/users",
328358
request_headers={"x-access-token": TOKEN},
329359
json={"id": user_id},
330360
status_code=201,
331361
additional_matcher=lambda req: additional_matcher(req, json={"id": user_id})
332362
)
333363

364+
# Mock Manage API endpoint for version >= 9.1
365+
post_manage = requests_mock.post(
366+
f"{MANAGE_API_URL}/maximo/api/os/masapiuser?lean=1",
367+
request_headers={"apikey": mock_manage_api_key["apikey"]},
368+
json={"id": user_id},
369+
status_code=201,
370+
additional_matcher=lambda req: additional_matcher(req, json={"id": user_id}, cert=PEM_PATH)
371+
)
372+
334373
assert user_utils.get_or_create_user({"id": user_id}) == {"id": user_id, "displayName": user_id}
335374
assert get.call_count == 1
336-
assert post.call_count == 0
375+
assert post_core.call_count == 0
376+
assert post_manage.call_count == 0
337377

338378

339-
def test_get_or_create_user_notfound(user_utils, requests_mock):
379+
def test_get_or_create_user_notfound(user_utils, requests_mock, mock_manage_api_key):
340380
user_id = "user1"
341381
get = mock_get_user_404(requests_mock, user_id)
342382

343-
post = requests_mock.post(
383+
# Mock Core API endpoint for version < 9.1
384+
post_core = requests_mock.post(
344385
f"{MAS_API_URL}/v3/users",
345386
request_headers={"x-access-token": TOKEN},
346387
json={"id": user_id, "displayName": user_id},
347388
status_code=201,
348389
additional_matcher=lambda req: additional_matcher(req, json={"id": user_id})
349390
)
350391

392+
# Mock Manage API endpoint for version >= 9.1
393+
post_manage = requests_mock.post(
394+
f"{MANAGE_API_URL}/maximo/api/os/masapiuser?lean=1",
395+
request_headers={"apikey": mock_manage_api_key["apikey"]},
396+
json={"id": user_id, "displayName": user_id},
397+
status_code=201,
398+
additional_matcher=lambda req: additional_matcher(req, json={"id": user_id}, cert=PEM_PATH)
399+
)
400+
351401
assert user_utils.get_or_create_user({"id": user_id}) == {"id": user_id, "displayName": user_id}
352402
assert get.call_count == 1
353-
assert post.call_count == 1
403+
# Check that the correct endpoint was called based on version
404+
if user_utils.mas_version >= '9.1':
405+
assert post_core.call_count == 0
406+
assert post_manage.call_count == 1
407+
else:
408+
assert post_core.call_count == 1
409+
assert post_manage.call_count == 0
354410

355411

356-
def test_get_or_create_user_error(user_utils, requests_mock):
412+
def test_get_or_create_user_error(user_utils, requests_mock, mock_manage_api_key):
357413
user_id = "user1"
358414
get = mock_get_user_404(requests_mock, user_id)
359-
post = requests_mock.post(
415+
416+
# Mock Core API endpoint for version < 9.1
417+
post_core = requests_mock.post(
360418
f"{MAS_API_URL}/v3/users",
361419
request_headers={"x-access-token": TOKEN},
362420
json={"error": "unknown"},
363421
status_code=500,
364422
additional_matcher=lambda req: additional_matcher(req, json={"id": user_id})
365423
)
366424

425+
# Mock Manage API endpoint for version >= 9.1
426+
post_manage = requests_mock.post(
427+
f"{MANAGE_API_URL}/maximo/api/os/masapiuser?lean=1",
428+
request_headers={"apikey": mock_manage_api_key["apikey"]},
429+
json={"error": "unknown"},
430+
status_code=500,
431+
additional_matcher=lambda req: additional_matcher(req, json={"id": user_id}, cert=PEM_PATH)
432+
)
433+
367434
with pytest.raises(Exception):
368435
user_utils.get_or_create_user({"id": user_id})
369436
assert get.call_count == 1
370-
assert post.call_count == 1
437+
# Check that the correct endpoint was called based on version
438+
if user_utils.mas_version >= '9.1':
439+
assert post_core.call_count == 0
440+
assert post_manage.call_count == 1
441+
else:
442+
assert post_core.call_count == 1
443+
assert post_manage.call_count == 0
371444

372445

373446
def test_update_user(user_utils, requests_mock):

0 commit comments

Comments
 (0)