Skip to content

Commit 24c11c9

Browse files
authored
fix legal hold/API client bug in devices command (#396)
* fix bug in `devices list --include-legal-hold-membership` when using api client auth * black * skip new bugbear warning * version and changelog
1 parent a43d612 commit 24c11c9

File tree

6 files changed

+133
-17
lines changed

6 files changed

+133
-17
lines changed

Diff for: CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
The intended audience of this file is for py42 consumers -- as such, changes that don't affect
99
how a consumer would use the library (e.g. adding unit tests, updating documentation, etc) are not captured here.
1010

11+
## 1.16.3 - 2022-12-08
12+
13+
### Fixed
14+
15+
- Bug in `devices list` command when using `--include-legal-hold-membership` option with an API client auth profile.
16+
1117
## 1.16.2 - 2022-11-07
1218

1319
### Fixed

Diff for: src/code42cli/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.16.2"
1+
__version__ = "1.16.3"

Diff for: src/code42cli/cmds/devices.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,21 @@ def _add_legal_hold_membership_to_device_dataframe(sdk, df):
432432

433433
def _get_all_active_hold_memberships(sdk):
434434
for page in sdk.legalhold.get_all_matters(active=True):
435-
for matter in page["legalHolds"]:
436-
for _page in sdk.legalhold.get_all_matter_custodians(
437-
legal_hold_uid=matter["legalHoldUid"], active=True
438-
):
439-
yield from _page["legalHoldMemberships"]
435+
if sdk._auth_flag == 1: # noqa: api client endpoint returns a list directly
436+
matters = page.data
437+
else:
438+
matters = page["legalHolds"]
439+
for matter in matters:
440+
if sdk._auth_flag == 1: # noqa: api client endpoint returns a list directly
441+
for _page in sdk.legalhold.get_all_matter_custodians(
442+
legal_hold_matter_uid=matter["legalHoldUid"], active=True
443+
):
444+
yield from _page.data
445+
else:
446+
for _page in sdk.legalhold.get_all_matter_custodians(
447+
legal_hold_uid=matter["legalHoldUid"], active=True
448+
):
449+
yield from _page["legalHoldMemberships"]
440450

441451

442452
def _get_device_dataframe(

Diff for: src/code42cli/output_formats.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def _iter_json(self, dfs, columns=None, **kwargs):
138138
yield f"{json_string}\n"
139139

140140
def _checkpoint_and_iter_formatted_events(self, df, formatted_rows):
141-
for event, row in zip(df.to_dict("records"), formatted_rows):
141+
for event, row in zip(df.to_dict("records"), formatted_rows): # noqa: B905
142142
yield row
143143
self.checkpoint_func(event)
144144

@@ -188,7 +188,7 @@ def iter_rows(self, dfs, columns=None):
188188
filtered = self._select_columns(df, columns)
189189
else:
190190
filtered = df
191-
for full_event, filtered_event in zip(
191+
for full_event, filtered_event in zip( # noqa: B905
192192
df.to_dict("records"), filtered.to_dict("records")
193193
):
194194
yield filtered_event

Diff for: tests/cmds/test_devices.py

+108-8
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,42 @@
279279
},
280280
]
281281
}
282+
API_CLIENT_MATTER_RESPONSE = [
283+
{
284+
"legalHoldUid": "123456789",
285+
"name": "Test legal hold matter",
286+
"description": "",
287+
"notes": None,
288+
"holdExtRef": None,
289+
"active": True,
290+
"creationDate": "2020-08-05T10:49:58.353-05:00",
291+
"lastModified": "2020-08-05T10:49:58.358-05:00",
292+
"creator": {
293+
"userUid": "12345",
294+
"username": "[email protected]",
295+
"email": "[email protected]",
296+
"userExtRef": None,
297+
},
298+
"holdPolicyUid": "966191295667423997",
299+
},
300+
{
301+
"legalHoldUid": "987654321",
302+
"name": "Another Matter",
303+
"description": "",
304+
"notes": None,
305+
"holdExtRef": None,
306+
"active": True,
307+
"creationDate": "2020-05-20T15:58:31.375-05:00",
308+
"lastModified": "2020-05-28T13:49:16.098-05:00",
309+
"creator": {
310+
"userUid": "76543",
311+
"username": "[email protected]",
312+
"email": "[email protected]",
313+
"userExtRef": None,
314+
},
315+
"holdPolicyUid": "946178665645035826",
316+
},
317+
]
282318
ALL_CUSTODIANS_RESPONSE = {
283319
"legalHoldMemberships": [
284320
{
@@ -310,6 +346,35 @@
310346
},
311347
]
312348
}
349+
API_CLIENT_ALL_CUSTODIANS_RESPONSE = [
350+
{
351+
"legalHoldMembershipUid": "99999",
352+
"active": True,
353+
"creationDate": "2020-07-16T08:50:23.405Z",
354+
"legalHold": {
355+
"legalHoldUid": "123456789",
356+
"name": "Test legal hold matter",
357+
},
358+
"user": {
359+
"userUid": "840103986007089121",
360+
"username": "[email protected]",
361+
"email": "[email protected]",
362+
"userExtRef": None,
363+
},
364+
},
365+
{
366+
"legalHoldMembershipUid": "88888",
367+
"active": True,
368+
"creationDate": "2020-07-16T08:50:23.405Z",
369+
"legalHold": {"legalHoldUid": "987654321", "name": "Another Matter"},
370+
"user": {
371+
"userUid": "840103986007089121",
372+
"username": "[email protected]",
373+
"email": "[email protected]",
374+
"userExtRef": None,
375+
},
376+
},
377+
]
313378

314379

315380
@pytest.fixture
@@ -355,12 +420,18 @@ def users_list_generator():
355420
yield TEST_USERS_LIST_PAGE
356421

357422

358-
def matter_list_generator():
359-
yield MATTER_RESPONSE
423+
def matter_list_generator(mocker, api_client=False):
424+
if api_client:
425+
yield create_mock_response(mocker, data=API_CLIENT_MATTER_RESPONSE)
426+
else:
427+
yield create_mock_response(mocker, data=MATTER_RESPONSE)
360428

361429

362-
def custodian_list_generator():
363-
yield ALL_CUSTODIANS_RESPONSE
430+
def custodian_list_generator(mocker, api_client=False):
431+
if api_client:
432+
yield create_mock_response(mocker, data=API_CLIENT_ALL_CUSTODIANS_RESPONSE)
433+
else:
434+
yield create_mock_response(mocker, data=ALL_CUSTODIANS_RESPONSE)
364435

365436

366437
@pytest.fixture
@@ -446,14 +517,28 @@ def get_all_users_success(cli_state):
446517

447518

448519
@pytest.fixture
449-
def get_all_matter_success(cli_state):
450-
cli_state.sdk.legalhold.get_all_matters.return_value = matter_list_generator()
520+
def get_all_matter_success(mocker, cli_state):
521+
cli_state.sdk.legalhold.get_all_matters.return_value = matter_list_generator(mocker)
522+
523+
524+
@pytest.fixture
525+
def get_api_client_all_matter_success(mocker, cli_state):
526+
cli_state.sdk.legalhold.get_all_matters.return_value = matter_list_generator(
527+
mocker, api_client=True
528+
)
451529

452530

453531
@pytest.fixture
454-
def get_all_custodian_success(cli_state):
532+
def get_all_custodian_success(mocker, cli_state):
455533
cli_state.sdk.legalhold.get_all_matter_custodians.return_value = (
456-
custodian_list_generator()
534+
custodian_list_generator(mocker)
535+
)
536+
537+
538+
@pytest.fixture
539+
def get_api_client_all_custodian_success(mocker, cli_state):
540+
cli_state.sdk.legalhold.get_all_matter_custodians.return_value = (
541+
custodian_list_generator(mocker, api_client=True)
457542
)
458543

459544

@@ -740,6 +825,21 @@ def test_add_legal_hold_membership_to_device_dataframe_adds_legal_hold_columns_t
740825
assert "legalHoldName" in result.columns
741826

742827

828+
def test_api_client_add_legal_hold_membership_to_device_dataframe_adds_legal_hold_columns_to_dataframe(
829+
cli_state, get_api_client_all_matter_success, get_api_client_all_custodian_success
830+
):
831+
cli_state.sdk._auth_flag = 1
832+
testdf = DataFrame.from_records(
833+
[
834+
{"userUid": "840103986007089121", "status": "Active"},
835+
{"userUid": "836473273124890369", "status": "Active, Deauthorized"},
836+
]
837+
)
838+
result = _add_legal_hold_membership_to_device_dataframe(cli_state.sdk, testdf)
839+
assert "legalHoldUid" in result.columns
840+
assert "legalHoldName" in result.columns
841+
842+
743843
def test_list_without_page_size_option_defaults_to_100_results_per_page(
744844
cli_state, runner
745845
):

Diff for: tests/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def mock_dataframe_to_string(mocker):
297297

298298

299299
def create_mock_response(mocker, data=None, status=200):
300-
if isinstance(data, dict):
300+
if isinstance(data, (dict, list)):
301301
data = json.dumps(data)
302302
elif not data:
303303
data = ""

0 commit comments

Comments
 (0)