diff --git a/Packs/GSuiteAdmin/.pack-ignore b/Packs/GSuiteAdmin/.pack-ignore index 0b16963ce1bb..3715a35bc1ad 100644 --- a/Packs/GSuiteAdmin/.pack-ignore +++ b/Packs/GSuiteAdmin/.pack-ignore @@ -6,4 +6,5 @@ g gsuite mobiledevice chromeosdevice +signout diff --git a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.py b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.py index 646b10166f7c..3e6738ea82f7 100644 --- a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.py +++ b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.py @@ -65,6 +65,7 @@ 'MOBILE_DEVICES_LIST_SUCCESS': 'Google Workspace Admin - Mobile Devices List', 'CHROMEOS_DEVICES_LIST_SUCCESS': 'Google Workspace Admin - ChromeOS Devices List', 'CHROMEOS_DEVICE_ACTION_SUCCESS': 'ChromeOS device with resource id - {} updated.', + 'USER_SIGNOUT_SESSIONS': 'Signs a {} out of all web and device sessions and reset their sign-in cookies.', } URL_SUFFIX: Dict[str, str] = { @@ -83,6 +84,7 @@ 'MOBILE_DEVICES_LIST': 'admin/directory/v1/customer/{}/devices/mobile', 'CHROMEOS_DEVICE_ACTION': 'admin/directory/v1/customer/{}/devices/chromeos/{}/action', 'CHROMEOS_DEVICES_LIST': 'admin/directory/v1/customer/{}/devices/chromeos', + 'USER_SIGN_OUT': 'admin/directory/v1/users/{}/signOut', } SCOPES: Dict[str, List[str]] = { @@ -861,6 +863,25 @@ def token_revoke_command(client: Client, args: Dict[str, str]) -> CommandResults return CommandResults(readable_output=HR_MESSAGES['TOKEN_REVOKE_SUCCESS'].format(args.get('client_id', ''))) +@logger +def user_signout_command(client: Client, args: Dict[str, str]) -> CommandResults: + """ + Signs a user out of all web and device sessions and reset their sign-in cookies. + + :param client: Client object. + :param args: Command arguments. + + :return: CommandResults. + """ + + client.set_authorized_http(scopes=SCOPES['USER_SECURITY']) + + user_key = urllib.parse.quote(args.get('user_key', '')) + client.http_request(url_suffix=URL_SUFFIX['USER_SIGN_OUT'].format(user_key), method='POST') + + return CommandResults(readable_output=HR_MESSAGES['USER_SIGNOUT_SESSIONS'].format(args.get('user_key', ''))) + + @logger def datatransfer_list_command(client: Client, args: Dict[str, str]) -> CommandResults: """ @@ -1488,8 +1509,8 @@ def main() -> None: 'gsuite-user-update': user_update_command, 'gsuite-mobiledevice-list': gsuite_mobile_device_list_command, 'gsuite-chromeosdevice-action': gsuite_chromeos_device_action_command, - 'gsuite-chromeosdevice-list': gsuite_chromeos_device_list_command - + 'gsuite-chromeosdevice-list': gsuite_chromeos_device_list_command, + 'gsuite-user-signout': user_signout_command } command = demisto.command() demisto.info(f'Command being called is {command}') diff --git a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.yml b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.yml index 063a6ff34184..5a74cf5af8be 100644 --- a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.yml +++ b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin.yml @@ -1026,6 +1026,13 @@ script: description: |- Delete all access tokens issued by a user for an application. name: gsuite-token-revoke + - arguments: + - description: Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID. + name: user_key + required: true + description: |- + Signs a user out of all web and device sessions and reset their sign-in cookies. + name: gsuite-user-signout - arguments: - description: Immutable ID of the G Suite account. name: customer_id @@ -1035,13 +1042,15 @@ script: name: old_owner_user_id - description: Status of the transfer. name: status - - description: Email ID of the G Suite domain admin who acts on behalf of an end-user. + - description: |- + Email ID of the G Suite domain admin who acts on behalf of an end-user. name: admin_email - - description: Maximum number of results to return. Default is 100. Acceptable values are 1 to 500, inclusive. + - description: |- + Maximum number of results to return. Default is 100. Acceptable values are 1 to 500, inclusive. name: max_results - description: Token to specify the next page in the list. name: page_token - description: Lists the transfers for a customer by source user, destination user, or status. + description: "Lists the transfers for a customer by source user, destination user, or status." name: gsuite-datatransfer-list outputs: - contextPath: GSuite.DataTransfer.kind @@ -1081,7 +1090,7 @@ script: description: Continuation token which will be used to specify next page in list API. type: String - arguments: - - description: Email ID of the G Suite domain admin who acts on behalf of an end-user. + - description: 'Email ID of the G Suite domain admin who acts on behalf of an end-user.' name: admin_email - description: Immutable ID of the G Suite account. name: customer_id @@ -1402,7 +1411,7 @@ script: description: Deletes a user. name: gsuite-user-delete - arguments: - - description: The user's first name. + - description: 'The user''s first name.' name: first_name - description: The user's last name. name: last_name @@ -2220,7 +2229,7 @@ script: - contextPath: GSuite.Group.nonEditableAliases description: List of the group's non-editable alias email addresses that are outside of the account's primary domain or subdomains. type: String - dockerimage: demisto/googleapi-python3:1.0.0.65453 + dockerimage: demisto/googleapi-python3:1.0.0.66918 runonce: false script: '-' subtype: python3 diff --git a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin_test.py b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin_test.py index 7e202d339ad3..1a4d188ec332 100644 --- a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin_test.py +++ b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/GSuiteAdmin_test.py @@ -611,6 +611,28 @@ def test_gsuite_token_revoke_command_success(mocker_http_request, gsuite_client) assert response.readable_output == HR_MESSAGES['TOKEN_REVOKE_SUCCESS'].format('CLIENT_ID') +@patch(MOCKER_HTTP_METHOD) +def test_gsuite_user_signout_command_success(mocker_http_request, gsuite_client): + """ + Scenario: User signout command successful execution. + + Given: + - Working API integration and correct parameters + + When: + - Calling command method gsuite_token_revoke_command. + + Then: + - Ensure expected human readable output is being set. + """ + + mocker_http_request.return_value = {} + + from GSuiteAdmin import user_signout_command + response = user_signout_command(gsuite_client, {'user_key': 'USER_KEY'}) + assert response.readable_output == HR_MESSAGES['USER_SIGNOUT_SESSIONS'].format('USER_KEY') + + @patch(MOCKER_HTTP_METHOD) def test_gsuite_token_revoke_command_failure(mocker_http_request, gsuite_client): """ diff --git a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/README.md b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/README.md index 28d0896bcb5e..75a98a3fa82e 100644 --- a/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/README.md +++ b/Packs/GSuiteAdmin/Integrations/GSuiteAdmin/README.md @@ -614,6 +614,26 @@ There is no context output for this command. >All access tokens deleted for 297408095146-fug707qsjv4ikron0hugpevbrjhkmsk7.apps.googleusercontent.com. +### gsuite-user-signout +*** + Signs a user out of all web and device sessions and reset their sign-in cookies. + +##### Required Permissions +`https://www.googleapis.com/auth/admin.directory.user.security` + +#### Base Command + +`gsuite-user-signout` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| user_key | Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID. | Required | + +#### Context Output + +There is no context output for this command. + ### gsuite-datatransfer-list *** Lists the transfers for a customer by source user, destination user, or status. diff --git a/Packs/GSuiteAdmin/ReleaseNotes/1_1_24.md b/Packs/GSuiteAdmin/ReleaseNotes/1_1_24.md new file mode 100644 index 000000000000..5712dace05df --- /dev/null +++ b/Packs/GSuiteAdmin/ReleaseNotes/1_1_24.md @@ -0,0 +1,6 @@ + +#### Integrations + +##### Google Workspace Admin +- Updated the Docker image to: *demisto/googleapi-python3:1.0.0.66918*. +- Added the command ***gsuite-user-signout***. \ No newline at end of file diff --git a/Packs/GSuiteAdmin/TestPlaybooks/playbook-GSuiteAdmin-Test.yml b/Packs/GSuiteAdmin/TestPlaybooks/playbook-GSuiteAdmin-Test.yml index 73ec3de34c95..423d8d4cc049 100644 --- a/Packs/GSuiteAdmin/TestPlaybooks/playbook-GSuiteAdmin-Test.yml +++ b/Packs/GSuiteAdmin/TestPlaybooks/playbook-GSuiteAdmin-Test.yml @@ -8,14 +8,15 @@ starttaskid: "0" tasks: "0": id: "0" - taskid: 531c820b-c43d-42b4-8651-6221f950b859 + taskid: d7878720-0650-4ee9-8382-a9be1bed4d06 type: start task: - id: 531c820b-c43d-42b4-8651-6221f950b859 + id: d7878720-0650-4ee9-8382-a9be1bed4d06 version: -1 name: "" iscommand: false brand: "" + description: '' nexttasks: '#none#': - "1" @@ -34,12 +35,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "1": id: "1" - taskid: 070c2eba-86bb-4f36-846f-51095cec1b2b + taskid: effae3dd-fcf7-4fc4-8c03-0f506dbc5660 type: regular task: - id: 070c2eba-86bb-4f36-846f-51095cec1b2b + id: effae3dd-fcf7-4fc4-8c03-0f506dbc5660 version: -1 name: DeleteContext script: DeleteContext @@ -67,12 +69,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "20": id: "20" - taskid: eef6dce2-83b1-4c0d-8c81-9350f0050591 + taskid: f05510b8-b41a-401c-812f-497dd505833c type: regular task: - id: eef6dce2-83b1-4c0d-8c81-9350f0050591 + id: f05510b8-b41a-401c-812f-497dd505833c version: -1 name: gsuite-user-create script: '|||gsuite-user-create' @@ -108,12 +111,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "21": id: "21" - taskid: 1f1c69ed-2ecc-4313-81dd-e2169779e308 + taskid: de160fcc-787a-4c6e-894f-e5443e15fbf7 type: condition task: - id: 1f1c69ed-2ecc-4313-81dd-e2169779e308 + id: de160fcc-787a-4c6e-894f-e5443e15fbf7 version: -1 name: Verify Outputs type: condition @@ -170,12 +174,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "25": id: "25" - taskid: 4a1ff324-1b83-4a38-8a3d-b12530f69b3f + taskid: 1500c8c6-2d4b-4ad5-8777-a7aa08ab2003 type: condition task: - id: 4a1ff324-1b83-4a38-8a3d-b12530f69b3f + id: 1500c8c6-2d4b-4ad5-8777-a7aa08ab2003 version: -1 name: Verify Outputs type: condition @@ -212,12 +217,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "26": id: "26" - taskid: ac77ad91-b1b2-4bc9-83a0-238b7d66ff96 + taskid: f9a3af45-e935-4389-8f4b-71cd5df065bd type: regular task: - id: ac77ad91-b1b2-4bc9-83a0-238b7d66ff96 + id: f9a3af45-e935-4389-8f4b-71cd5df065bd version: -1 name: gsuite-role-assignment-list script: '|||gsuite-role-assignment-list' @@ -247,12 +253,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "27": id: "27" - taskid: 2026bb93-9f09-414e-8612-63d2f637ad8d + taskid: 62dce289-f9c8-432d-84a2-d2da417e627a type: condition task: - id: 2026bb93-9f09-414e-8612-63d2f637ad8d + id: 62dce289-f9c8-432d-84a2-d2da417e627a version: -1 name: Verify Outputs type: condition @@ -289,12 +296,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "28": id: "28" - taskid: 7adfdc60-9177-491f-8d80-ddae400ac8dc + taskid: 7c2eb1f6-2719-436c-8402-f4edf7254125 type: regular task: - id: 7adfdc60-9177-491f-8d80-ddae400ac8dc + id: 7c2eb1f6-2719-436c-8402-f4edf7254125 version: -1 name: gsuite-role-assignment-create script: '|||gsuite-role-assignment-create' @@ -334,12 +342,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "29": id: "29" - taskid: 5dee4504-eb18-4a8e-84c3-38500d2cc90c + taskid: 7913421a-5abc-46fb-80bc-ed0ef21c7288 type: condition task: - id: 5dee4504-eb18-4a8e-84c3-38500d2cc90c + id: 7913421a-5abc-46fb-80bc-ed0ef21c7288 version: -1 name: Verify Outputs type: condition @@ -347,7 +356,7 @@ tasks: brand: "" nexttasks: "yes": - - "50" + - "56" separatecontext: false conditions: - label: "yes" @@ -381,23 +390,25 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "47": id: "47" - taskid: d9db92a1-5cbe-4e4d-8f04-8fc87f161828 + taskid: b4f7cc4a-34d0-4623-8a62-9dd0672fb2be type: title task: - id: d9db92a1-5cbe-4e4d-8f04-8fc87f161828 + id: b4f7cc4a-34d0-4623-8a62-9dd0672fb2be version: -1 name: Test Done type: title iscommand: false brand: "" + description: '' separatecontext: false view: |- { "position": { - "x": 50, - "y": 2295 + "x": 40, + "y": 2635 } } note: false @@ -407,12 +418,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "50": id: "50" - taskid: 194a349a-529c-42d5-8ea6-1068a0e6345b + taskid: 678444d7-a27c-4193-8dd1-7c9bc4919a21 type: regular task: - id: 194a349a-529c-42d5-8ea6-1068a0e6345b + id: 678444d7-a27c-4193-8dd1-7c9bc4919a21 version: -1 name: gsuite-user-delete description: Deletes a user. @@ -444,12 +456,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "51": id: "51" - taskid: b8e96b64-e657-454b-8df0-3cf084db672e + taskid: c5157957-a79c-4c2a-843c-0d809daf0ad0 type: regular task: - id: b8e96b64-e657-454b-8df0-3cf084db672e + id: c5157957-a79c-4c2a-843c-0d809daf0ad0 version: -1 name: gsuite-user-update description: Updates a user. @@ -484,12 +497,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "52": id: "52" - taskid: e0b88bb8-d321-4428-887f-48813bf01450 + taskid: 9e65bdf7-5cb7-4a7e-8e41-3d1b6d4da9fe type: regular task: - id: e0b88bb8-d321-4428-887f-48813bf01450 + id: 9e65bdf7-5cb7-4a7e-8e41-3d1b6d4da9fe version: -1 name: sleep 10 description: Sleep for X seconds @@ -508,7 +522,7 @@ tasks: { "position": { "x": 50, - "y": 2120 + "y": 2190 } } note: false @@ -518,12 +532,13 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" "55": id: "55" - taskid: 4150c4ed-a8f5-456d-888f-07d1931c7358 + taskid: c95b3b0d-d28e-4432-8fce-3d53e0f99be8 type: regular task: - id: 4150c4ed-a8f5-456d-888f-07d1931c7358 + id: c95b3b0d-d28e-4432-8fce-3d53e0f99be8 version: -1 name: gsuite-user-delete description: Deletes a user. @@ -555,13 +570,49 @@ tasks: quietmode: 0 isoversize: false isautoswitchedtoquietmode: false + continueonerrortype: "" + "56": + id: "56" + taskid: d526e266-ce59-43ec-888b-d8b4ebb38072 + type: regular + task: + id: d526e266-ce59-43ec-888b-d8b4ebb38072 + version: -1 + name: gsuite-user-signout + description: Signs a user out of all web and device sessions and reset their sign-in cookies. + script: '|||gsuite-user-signout' + type: regular + iscommand: true + brand: "" + nexttasks: + '#none#': + - "50" + scriptarguments: + user_key: + simple: xsoar11@demistodev.com + separatecontext: false + continueonerrortype: "" + view: |- + { + "position": { + "x": 570, + "y": 1840 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false view: |- { "linkLabelsPosition": {}, "paper": { "dimensions": { - "height": 2310, - "width": 390, + "height": 2650, + "width": 910, "x": 40, "y": 50 } diff --git a/Packs/GSuiteAdmin/pack_metadata.json b/Packs/GSuiteAdmin/pack_metadata.json index 394190454655..5d4e194ea37e 100644 --- a/Packs/GSuiteAdmin/pack_metadata.json +++ b/Packs/GSuiteAdmin/pack_metadata.json @@ -2,7 +2,7 @@ "name": "G Suite Admin", "description": "G Suite Admin integration with Cortex XSOAR. G Suite or Google Workspace Admin is an integration to perform an action on IT infrastructure, create users, update settings, and more administrative tasks.", "support": "xsoar", - "currentVersion": "1.1.23", + "currentVersion": "1.1.24", "author": "Cortex XSOAR", "url": "https://www.paloaltonetworks.com/cortex", "email": "", diff --git a/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.py b/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.py index ce20e5cd3b98..0d3f2691e4bd 100644 --- a/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.py +++ b/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.py @@ -1,12 +1,14 @@ import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 + ''' IMPORTS ''' import io import urllib3 import uuid import dateparser -from typing import List, Dict, Any, Tuple, Optional, Union, Callable +from typing import Any +from collections.abc import Callable from apiclient import discovery from googleapiclient.http import MediaFileUpload @@ -15,10 +17,9 @@ # Disable insecure warnings urllib3.disable_warnings() - ''' CONSTANTS ''' -MESSAGES: Dict[str, str] = { +MESSAGES: dict[str, str] = { 'TEST_FAILED_ERROR': 'Test connectivity failed. Check the configuration parameters provided.', 'DRIVE_CHANGES_FIELDS': 'The argument fields must be either basic or advance.', 'INTEGER_ERROR': 'The argument {} must be a positive integer.', @@ -29,7 +30,7 @@ 'USER_ID_REQUIRED': 'The parameter User ID is required.' } -HR_MESSAGES: Dict[str, str] = { +HR_MESSAGES: dict[str, str] = { 'DRIVE_CREATE_SUCCESS': 'A new shared drive created.', 'NOT_FOUND': 'No {} found.', 'LIST_COMMAND_SUCCESS': 'Total Retrieved {}: {}', @@ -40,12 +41,12 @@ 'EXCEPTION_GENERIC': 'Exception handling a {} request: {}', } -SCOPES: Dict[str, List[str]] = { +SCOPES: dict[str, list[str]] = { 'TEST_MODULE': ['https://www.googleapis.com/auth/userinfo.email'], 'DRIVE': ['https://www.googleapis.com/auth/drive'] } -COMMAND_SCOPES: Dict[str, List[str]] = { +COMMAND_SCOPES: dict[str, list[str]] = { 'DRIVE_CHANGES': [ 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file', @@ -101,10 +102,10 @@ } -URLS: Dict[str, str] = { +URLS: dict[str, str] = { 'DRIVE_ACTIVITY': 'https://driveactivity.googleapis.com/v2/activity:query' } -URL_SUFFIX: Dict[str, str] = { +URL_SUFFIX: dict[str, str] = { 'DRIVE_CHANGES': 'drive/v3/changes', 'DRIVE_CREATE': 'drive/v3/drives', 'DRIVE_DRIVES': 'drive/v3/drives', @@ -121,7 +122,7 @@ 'FILE_PERMISSION_DELETE': 'drive/v3/files/{}/permissions/{}', } -OUTPUT_PREFIX: Dict[str, str] = { +OUTPUT_PREFIX: dict[str, str] = { 'GOOGLE_DRIVE_HEADER': 'GoogleDrive.Drive', 'PAGE_TOKEN': 'PageToken', @@ -152,11 +153,11 @@ PRIMARY_ACTION: str = 'Primary Action' NEXT_PAGE_TOKEN: str = '### Next Page Token: {}\n' COLOR_RGB: str = 'Color RGB' -ACTION_MAPPINGS: Dict[str, str] = {'dlpChange': 'DLPChange'} +ACTION_MAPPINGS: dict[str, str] = {'dlpChange': 'DLPChange'} DRIVE_ACTIVITY_DETAIL_ACTION: str = 'detail.action_detail_case: {}' -def prepare_markdown_from_dictionary(data: Dict[str, Any], ignore_fields: List[str] = []) -> str: +def prepare_markdown_from_dictionary(data: dict[str, Any], ignore_fields: list[str] = []) -> str: """ Prepares markdown from dictionary. @@ -165,7 +166,7 @@ def prepare_markdown_from_dictionary(data: Dict[str, Any], ignore_fields: List[s :return: data in markdown format. """ - hr_cell_info: List[str] = [] + hr_cell_info: list[str] = [] for key, value in data.items(): if key not in ignore_fields: hr_cell_info.append( @@ -173,7 +174,7 @@ def prepare_markdown_from_dictionary(data: Dict[str, Any], ignore_fields: List[s return '\n'.join(hr_cell_info) -def prepare_params_for_drive_changes_list(args: Dict[str, str]) -> Dict[str, Any]: +def prepare_params_for_drive_changes_list(args: dict[str, str]) -> dict[str, Any]: """ Prepares arguments for google-drive-changes-list command. @@ -213,8 +214,8 @@ def prepare_params_for_drive_changes_list(args: Dict[str, str]) -> Dict[str, Any return GSuiteClient.remove_empty_entities(params) -def prepare_drive_changes_output(response: Dict[str, Any], drive_id: str, user_id: str) -> \ - Tuple[Dict[str, Any], List[Dict[str, Optional[Any]]], List[Dict[str, Optional[Any]]]]: +def prepare_drive_changes_output(response: dict[str, Any], drive_id: str, user_id: str) -> \ + tuple[dict[str, Any], list[dict[str, Any | None]], list[dict[str, Any | None]]]: """ Prepares context output and human readable for google-drive-changes-list command. @@ -240,8 +241,8 @@ def prepare_drive_changes_output(response: Dict[str, Any], drive_id: str, user_i } outputs = GSuiteClient.remove_empty_entities(outputs) - drive_changes_hr_files: List[Dict[str, Any]] = [{}] - drive_changes_hr_drives: List[Dict[str, Any]] = [{}] + drive_changes_hr_files: list[dict[str, Any]] = [{}] + drive_changes_hr_drives: list[dict[str, Any]] = [{}] for drive_change in drive_changes_context: drive_change_file = drive_change.get('file', {}) drive_changes_hr_files.append({ @@ -266,7 +267,7 @@ def prepare_drive_changes_output(response: Dict[str, Any], drive_id: str, user_i return outputs, drive_changes_hr_files, drive_changes_hr_drives -def prepare_body_for_drive_activity(args: Dict[str, str]) -> Dict[str, Union[str, int]]: +def prepare_body_for_drive_activity(args: dict[str, str]) -> dict[str, str | int]: """ To prepare body for drive_activity_list_command. @@ -280,7 +281,7 @@ def prepare_body_for_drive_activity(args: Dict[str, str]) -> Dict[str, Union[str if time_range: time_range, _ = parse_date_range(time_range, date_format=DATE_FORMAT_TIME_RANGE, utc=True) - filter_activity += 'time >= "{}"'.format(time_range) + filter_activity += f'time >= "{time_range}"' if action_detail_case_include: filter_activity += ' AND ' + DRIVE_ACTIVITY_DETAIL_ACTION.format( @@ -318,10 +319,10 @@ def set_true_for_empty_dict(d): :param d: Input dictionary. :return: Dictionary with all empty dictionary's value set as True. """ - if not isinstance(d, (dict, list)): + if not isinstance(d, dict | list): return d elif isinstance(d, list): - return [value for value in (set_true_for_empty_dict(value) for value in d)] + return ([set_true_for_empty_dict(value) for value in d]) else: if d == {}: return True @@ -329,7 +330,7 @@ def set_true_for_empty_dict(d): for key, value in d.items())} -def prepare_drive_activity_output(activity: Dict[str, Any]) -> Dict[str, Any]: +def prepare_drive_activity_output(activity: dict[str, Any]) -> dict[str, Any]: """ Prepares context output for google-drive-activity-list command. @@ -347,7 +348,7 @@ def prepare_drive_activity_output(activity: Dict[str, Any]) -> Dict[str, Any]: return GSuiteClient.remove_empty_entities(drive_activity_context) -def prepare_hr_setting_changes_entity(context: Dict[str, Any]) -> str: +def prepare_hr_setting_changes_entity(context: dict[str, Any]) -> str: """ Prepare human readable of setting entity of google-drive-activity-list @@ -366,7 +367,7 @@ def prepare_hr_setting_changes_entity(context: Dict[str, Any]) -> str: return restriction_changes -def prepare_target_for_drive_activity(targets_list: List) -> str: +def prepare_target_for_drive_activity(targets_list: list) -> str: """ :param targets_list: Target entity in context data. @@ -375,9 +376,9 @@ def prepare_target_for_drive_activity(targets_list: List) -> str: """ targets_data: str = '' for target in targets_list: - drive: Dict[str, Any] = target.get('drive', {}) - file_comment_parent: Dict[str, Any] = target.get('fileComment', {}).get('parent', {}) - drive_item: Dict[str, Any] = target.get('driveItem', {}) + drive: dict[str, Any] = target.get('drive', {}) + file_comment_parent: dict[str, Any] = target.get('fileComment', {}).get('parent', {}) + drive_item: dict[str, Any] = target.get('driveItem', {}) if drive_item: targets_data += 'Target: \'' + drive_item.get('title', '') + "'\n" @@ -390,7 +391,7 @@ def prepare_target_for_drive_activity(targets_list: List) -> str: return targets_data -def prepare_drive_activity_human_readable(outputs_context: List[Dict[str, Any]]) -> str: +def prepare_drive_activity_human_readable(outputs_context: list[dict[str, Any]]) -> str: """ Prepares human readable for google-drive-activity-list command. @@ -398,7 +399,7 @@ def prepare_drive_activity_human_readable(outputs_context: List[Dict[str, Any]]) :return: Human readable. """ - drive_hr: List[Dict[str, Any]] = [{}] + drive_hr: list[dict[str, Any]] = [{}] for context in outputs_context: primary_action_detail = context.get('primaryActionDetail', {}) @@ -406,58 +407,58 @@ def prepare_drive_activity_human_readable(outputs_context: List[Dict[str, Any]]) object_target: str = prepare_target_for_drive_activity(context.get('targets', [])) time_stamp = context.get('timestamp', '') - if 'edit' == name: + if name == 'edit': drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Edit', OBJECT_HEADER: object_target}) - elif 'delete' == name: + elif name == 'delete': delete_type: str = 'Delete Type: ' + primary_action_detail.get('delete', {}).get('type', '') + '\n' drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Delete', OBJECT_HEADER: delete_type + object_target}) - elif 'restore' == name: + elif name == 'restore': restore_type: str = 'Restore Type: ' + primary_action_detail.get('restore', {}).get('type', '') + '\n' drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Restore', OBJECT_HEADER: restore_type + object_target}) - elif 'dlpChange' == name: + elif name == 'dlpChange': dlp_type: str = 'DataLeakPreventionChange Type: ' + primary_action_detail.get('dlpChange', {}).get('type', '') + '\n' drive_hr.append( {ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'DataLeakPreventionChange', OBJECT_HEADER: dlp_type + object_target}) - elif 'reference' == name: + elif name == 'reference': reference_type: str = 'Reference Type: ' + primary_action_detail.get('reference', {}).get('type', '') + '\n' drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Reference', OBJECT_HEADER: reference_type + object_target}) - elif 'rename' == name: - rename_object: Dict[str, Any] = primary_action_detail.get('rename', {}) + elif name == 'rename': + rename_object: dict[str, Any] = primary_action_detail.get('rename', {}) rename_titles: str = 'Old Title: \'' + rename_object.get('oldTitle', '') + "'\n" + 'New Title: \'' + \ rename_object.get('newTitle', '') + "'\n" drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Rename', OBJECT_HEADER: rename_titles}) - elif 'move' == name: + elif name == 'move': drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Move', OBJECT_HEADER: object_target}) - elif 'permissionChange' == name: + elif name == 'permissionChange': drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'PermissionChange', OBJECT_HEADER: object_target}) - elif 'settingsChange' == name: + elif name == 'settingsChange': settings_changes: str = prepare_hr_setting_changes_entity(context) drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'SettingsChange', OBJECT_HEADER: settings_changes + object_target}) - elif 'comment' == name: + elif name == 'comment': drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Comment', OBJECT_HEADER: object_target}) - elif 'create' == name: - created: List = list(primary_action_detail.get('create', {}).keys()) + elif name == 'create': + created: list = list(primary_action_detail.get('create', {}).keys()) drive_hr.append({ACTIVITY_TIME: time_stamp, PRIMARY_ACTION: 'Create ' + created[0].capitalize(), OBJECT_HEADER: object_target}) @@ -471,7 +472,7 @@ def prepare_drive_activity_human_readable(outputs_context: List[Dict[str, Any]]) return drive_activity_hr -def flatten_user_dict(user: Dict[str, Any]) -> Dict[str, Any]: +def flatten_user_dict(user: dict[str, Any]) -> dict[str, Any]: """ Flatten keys of user to populate the grid field. @@ -487,7 +488,7 @@ def flatten_user_dict(user: Dict[str, Any]) -> Dict[str, Any]: 'isUnknownUser': set_true_for_empty_dict(user.get('unknownUser'))}) -def flatten_targets_keys_for_fetch_incident(activity: Dict[str, Any]) -> None: +def flatten_targets_keys_for_fetch_incident(activity: dict[str, Any]) -> None: """ Flatten keys of targets to populate the grid field. @@ -521,7 +522,7 @@ def update_drive_item(item): activity['targets'] = flatten_targets -def actors_type_keys_for_fetch_incident(activity: Dict[str, Any]) -> None: +def actors_type_keys_for_fetch_incident(activity: dict[str, Any]) -> None: """ Actors to populate on incident. @@ -545,7 +546,7 @@ def actors_type_keys_for_fetch_incident(activity: Dict[str, Any]) -> None: activity['actors'] = flatten_actors -def flatten_permission_change_keys_for_fetch_incident(permission_change: Dict[str, Any]) -> None: +def flatten_permission_change_keys_for_fetch_incident(permission_change: dict[str, Any]) -> None: """ Flatten keys of permission change to populate the grid field. @@ -575,7 +576,7 @@ def update_permission(permission): permission_change['removedPermissions']] -def flatten_move_keys_for_fetch_incident(move: Dict[str, Any]) -> None: +def flatten_move_keys_for_fetch_incident(move: dict[str, Any]) -> None: """ Flatten keys of move to populate the grid field. @@ -604,7 +605,7 @@ def update_move_parents(parents): move['removedParents']] -def flatten_comment_mentioned_user_keys_for_fetch_incident(comment: Dict[str, Any]) -> None: +def flatten_comment_mentioned_user_keys_for_fetch_incident(comment: dict[str, Any]) -> None: """ Flatten keys of mentioned_users to populate the grid field. @@ -617,7 +618,7 @@ def flatten_comment_mentioned_user_keys_for_fetch_incident(comment: Dict[str, An comment['mentionedUsers']] -def prepare_args_for_fetch_incidents(last_fetch: int, args: Dict[str, Any]) -> Dict[str, Any]: +def prepare_args_for_fetch_incidents(last_fetch: int, args: dict[str, Any]) -> dict[str, Any]: """ Prepares arguments for fetch-incidents. @@ -626,8 +627,8 @@ def prepare_args_for_fetch_incidents(last_fetch: int, args: Dict[str, Any]) -> D :return: Prepared request body for fetch-incident. """ - if (args.get('drive_item_search_value') and not args.get('drive_item_search_field')) or ( - not args.get('drive_item_search_value') and args.get('drive_item_search_field')): + if (args.get('drive_item_search_value') and not args.get('drive_item_search_field')) or \ + (not args.get('drive_item_search_value') and args.get('drive_item_search_field')): raise ValueError(MESSAGES['FETCH_INCIDENT_REQUIRED_ARGS']) action_detail_case_include = [action.upper() for action in args.get('action_detail_case_include', [])] @@ -647,7 +648,7 @@ def prepare_args_for_fetch_incidents(last_fetch: int, args: Dict[str, Any]) -> D }) -def validate_params_for_fetch_incidents(params: Dict[str, Any]) -> None: +def validate_params_for_fetch_incidents(params: dict[str, Any]) -> None: """ Validates parameters for fetch-incidents command. @@ -661,8 +662,8 @@ def validate_params_for_fetch_incidents(params: Dict[str, Any]) -> None: params['first_fetch_interval'], _ = parse_date_range(params.get('first_fetch', '10 minutes'), utc=True) # Check for depended required parameters. - if (params.get('drive_item_search_value') and not params.get('drive_item_search_field')) or ( - not params.get('drive_item_search_value') and params.get('drive_item_search_field')): + if (params.get('drive_item_search_value') and not params.get('drive_item_search_field')) or \ + (not params.get('drive_item_search_value') and params.get('drive_item_search_field')): raise ValueError(MESSAGES['FETCH_INCIDENT_REQUIRED_ARGS']) params['max_fetch'] = GSuiteClient.validate_get_int(params.get('max_fetch', 10), limit=100, @@ -673,7 +674,7 @@ def validate_params_for_fetch_incidents(params: Dict[str, Any]) -> None: @logger -def test_module(gsuite_client: 'GSuiteClient', last_run: Dict, params: Dict[str, Any]) -> str: +def test_module(gsuite_client: 'GSuiteClient', last_run: dict, params: dict[str, Any]) -> str: """ Performs test connectivity by valid http response @@ -697,7 +698,7 @@ def test_module(gsuite_client: 'GSuiteClient', last_run: Dict, params: Dict[str, @logger -def drive_create_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def drive_create_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Creates a new Team Drive. The name argument specifies the name of the Team Drive. The specified user will be the first organizer. @@ -735,7 +736,7 @@ def drive_create_command(client: 'GSuiteClient', args: Dict[str, str]) -> Comman @logger -def drive_changes_list_command(client: 'GSuiteClient', args: Dict[str, Any]) -> CommandResults: +def drive_changes_list_command(client: 'GSuiteClient', args: dict[str, Any]) -> CommandResults: """ Lists the changes for a user or shared drive. @@ -775,7 +776,7 @@ def drive_changes_list_command(client: 'GSuiteClient', args: Dict[str, Any]) -> ) -def prepare_drives_request(client: 'GSuiteClient', args: Dict[str, str]) -> Dict[str, Any]: +def prepare_drives_request(client: 'GSuiteClient', args: dict[str, str]) -> dict[str, Any]: """ prepare_drives_request Preparing http_request_params and populating the client @@ -786,7 +787,7 @@ def prepare_drives_request(client: 'GSuiteClient', args: Dict[str, str]) -> Dict :return: Objects ready for requests """ - http_request_params: Dict[str, str] = assign_params( + http_request_params: dict[str, str] = assign_params( q=args.get('query'), pageSize=args.get('page_size'), pageToken=args.get('page_token'), @@ -803,7 +804,7 @@ def prepare_drives_request(client: 'GSuiteClient', args: Dict[str, str]) -> Dict @logger -def drives_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def drives_list_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ google-drive-drives-list Query drives list in Google Drive. @@ -825,7 +826,7 @@ def drives_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> Command @logger -def drive_get_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def drive_get_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ google-drive-drive-get Query a single drive in Google Drive. @@ -845,8 +846,7 @@ def drive_get_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandRe return handle_response_single_drive(response, args) -def handle_response_drive_list(response: Dict[str, Any]) -> CommandResults: - +def handle_response_drive_list(response: dict[str, Any]) -> CommandResults: outputs_context = [] readable_output = '' @@ -855,7 +855,7 @@ def handle_response_drive_list(response: Dict[str, Any]) -> CommandResults: for current_drive in cleaned_drives_context.get('drives', []): outputs_context.append(current_drive) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_DRIVE_HEADER']: { OUTPUT_PREFIX['DRIVE']: outputs_context, }, @@ -877,11 +877,11 @@ def handle_response_drive_list(response: Dict[str, Any]) -> CommandResults: ) -def handle_response_single_drive(response: Dict[str, Any], args: Dict[str, str]): +def handle_response_single_drive(response: dict[str, Any], args: dict[str, str]): drive_context = set_true_for_empty_dict(response) outputs_context = GSuiteClient.remove_empty_entities(drive_context) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_DRIVE_HEADER']: { OUTPUT_PREFIX['DRIVE']: outputs_context, }, @@ -901,7 +901,7 @@ def handle_response_single_drive(response: Dict[str, Any], args: Dict[str, str]) ) -def prepare_drives_human_readable(outputs_context: List[Dict[str, Any]]) -> str: +def prepare_drives_human_readable(outputs_context: list[dict[str, Any]]) -> str: """ Prepares human readable for google-drives-list command. @@ -917,7 +917,7 @@ def prepare_drives_human_readable(outputs_context: List[Dict[str, Any]]) -> str: removeNull=True) -def prepare_single_drive_human_readable(outputs_context: Dict[str, Any], args: Dict[str, str]) -> str: +def prepare_single_drive_human_readable(outputs_context: dict[str, Any], args: dict[str, str]) -> str: """ Prepares human readable for a single drive in google-drives-list command. @@ -934,8 +934,8 @@ def prepare_single_drive_human_readable(outputs_context: Dict[str, Any], args: D removeNull=True) -def prepare_file_read_request(client: 'GSuiteClient', args: Dict[str, str]) -> Dict[str, Any]: - http_request_params: Dict[str, str] = assign_params( +def prepare_file_read_request(client: 'GSuiteClient', args: dict[str, str]) -> dict[str, Any]: + http_request_params: dict[str, str] = assign_params( q=args.get('query'), pageSize=args.get('page_size'), pageToken=args.get('page_token'), @@ -955,7 +955,7 @@ def prepare_file_read_request(client: 'GSuiteClient', args: Dict[str, str]) -> D @logger -def files_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def files_list_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ google-drive-files-list Query files list in Google Drive. @@ -976,7 +976,7 @@ def files_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandR @logger -def file_get_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_get_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ google-drive-file-get Query a single file in Google Drive. @@ -997,8 +997,7 @@ def file_get_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandRes return handle_response_single_file(response, args) -def handle_response_files_list(response: Dict[str, Any]) -> CommandResults: - +def handle_response_files_list(response: dict[str, Any]) -> CommandResults: outputs_context = [] readable_output = '' @@ -1008,7 +1007,7 @@ def handle_response_files_list(response: Dict[str, Any]) -> CommandResults: files_hr = prepare_files_human_readable(outputs_context) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_HEADER']: { OUTPUT_PREFIX['FILE']: outputs_context, }, @@ -1028,12 +1027,12 @@ def handle_response_files_list(response: Dict[str, Any]) -> CommandResults: ) -def handle_response_single_file(response: Dict[str, Any], args: Dict[str, str]): +def handle_response_single_file(response: dict[str, Any], args: dict[str, str]): outputs_context = prepare_single_file_output(response) file_hr = prepare_single_file_human_readable(outputs_context, args) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_HEADER']: { OUTPUT_PREFIX['FILE']: outputs_context } @@ -1050,7 +1049,7 @@ def handle_response_single_file(response: Dict[str, Any], args: Dict[str, str]): ) -def prepare_files_human_readable(outputs_context: List[Dict[str, Any]]) -> str: +def prepare_files_human_readable(outputs_context: list[dict[str, Any]]) -> str: """ Prepares human readable for google-files-list command. @@ -1067,7 +1066,7 @@ def prepare_files_human_readable(outputs_context: List[Dict[str, Any]]) -> str: removeNull=True) -def prepare_single_file_output(response: Dict[str, Any]) -> Dict[str, Any]: +def prepare_single_file_output(response: dict[str, Any]) -> dict[str, Any]: """ Prepares context output for a single file in google-files-list command. @@ -1080,7 +1079,7 @@ def prepare_single_file_output(response: Dict[str, Any]) -> Dict[str, Any]: return GSuiteClient.remove_empty_entities(files_context) -def prepare_single_file_human_readable(outputs_context: Dict[str, Any], args: Dict[str, str]) -> str: +def prepare_single_file_human_readable(outputs_context: dict[str, Any], args: dict[str, str]) -> str: """ Prepares human readable for a single file in google-files-list command. @@ -1097,7 +1096,7 @@ def prepare_single_file_human_readable(outputs_context: Dict[str, Any], args: Di removeNull=False) -def prepare_file_command_request(client: 'GSuiteClient', args: Dict[str, str], scopes: List[str]) -> Dict[str, Any]: +def prepare_file_command_request(client: 'GSuiteClient', args: dict[str, str], scopes: list[str]) -> dict[str, Any]: # Prepare generic HTTP request params http_request_params = assign_params(supportsAllDrives=args.get('supports_all_drives')) @@ -1112,7 +1111,7 @@ def prepare_file_command_request(client: 'GSuiteClient', args: Dict[str, str], s @logger -def file_upload_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_upload_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Upload a file to Google Drive @@ -1130,7 +1129,7 @@ def file_upload_command(client: 'GSuiteClient', args: Dict[str, str]) -> Command user_id = args.get('user_id') or client.user_id client.set_authorized_http(scopes=COMMAND_SCOPES['FILES'], subject=user_id) drive_service = discovery.build(serviceName=service_name, version=version, http=client.authorized_http) - body: Dict[str, str] = assign_params( + body: dict[str, str] = assign_params( parents=[args.get('parent')] if 'parent' in args else None, name=args.get('file_name'), ) @@ -1146,7 +1145,7 @@ def file_upload_command(client: 'GSuiteClient', args: Dict[str, str]) -> Command @logger -def file_download_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_download_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Download a file from Google Drive @@ -1171,7 +1170,7 @@ def file_download_command(client: 'GSuiteClient', args: Dict[str, str]) -> Comma @logger -def file_replace_existing_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_replace_existing_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Replace an existing file in Google Drive google-drive-file-replace-existing @@ -1198,7 +1197,7 @@ def file_replace_existing_command(client: 'GSuiteClient', args: Dict[str, str]) @logger -def file_delete_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_delete_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Delete a file in Google Drive @@ -1216,7 +1215,7 @@ def file_delete_command(client: 'GSuiteClient', args: Dict[str, str]) -> Command outputs_context = { 'id': args.get('file_id'), } - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_HEADER']: { OUTPUT_PREFIX['FILE']: outputs_context, } @@ -1235,15 +1234,14 @@ def file_delete_command(client: 'GSuiteClient', args: Dict[str, str]) -> Command return ret_value -def handle_response_file_single(response: Dict[str, Any], args: Dict[str, str]) -> CommandResults: - +def handle_response_file_single(response: dict[str, Any], args: dict[str, str]) -> CommandResults: readable_output = '' outputs_context = prepare_file_single_output(response) files_hr = prepare_file_single_human_readable(outputs_context, args) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_HEADER']: { OUTPUT_PREFIX['FILE']: outputs_context } @@ -1258,7 +1256,7 @@ def handle_response_file_single(response: Dict[str, Any], args: Dict[str, str]) ) -def prepare_file_single_output(file_single: Dict[str, Any]) -> Dict[str, Any]: +def prepare_file_single_output(file_single: dict[str, Any]) -> dict[str, Any]: """ Prepares context output for google-drive-file commands. @@ -1274,7 +1272,7 @@ def prepare_file_single_output(file_single: Dict[str, Any]) -> Dict[str, Any]: return GSuiteClient.remove_empty_entities(ret_value) -def prepare_file_single_human_readable(outputs_context: Dict[str, Any], args: Dict[str, str]) -> str: +def prepare_file_single_human_readable(outputs_context: dict[str, Any], args: dict[str, str]) -> str: """ Prepares human readable for google-drive-file commands. @@ -1302,16 +1300,16 @@ def prepare_file_single_human_readable(outputs_context: Dict[str, Any], args: Di removeNull=False) -def prepare_file_permission_request(client: 'GSuiteClient', args: Dict[str, str], scopes: List[str]) -> Dict[str, Any]: +def prepare_file_permission_request(client: 'GSuiteClient', args: dict[str, str], scopes: list[str]) -> dict[str, Any]: # user_id can be overridden in the args user_id = args.get('user_id') or client.user_id client.set_authorized_http(scopes=scopes, subject=user_id) - # Prepare generic HTTP request params - http_request_params: Dict[str, str] = assign_params( + http_request_params: dict[str, str] = assign_params( fileId=args.get('file_id'), supportsAllDrives=args.get('supports_all_drives'), fields='*', + useDomainAdminAccess=('true' if argToBoolean(args.get('use_domain_admin_access', 'false')) else 'false') ) return { @@ -1322,7 +1320,7 @@ def prepare_file_permission_request(client: 'GSuiteClient', args: Dict[str, str] @logger -def file_permission_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_permission_list_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ List file permissions @@ -1335,7 +1333,7 @@ def file_permission_list_command(client: 'GSuiteClient', args: Dict[str, str]) - # All permissions prepare_file_permission_request_res = prepare_file_permission_request( client, args, scopes=COMMAND_SCOPES['FILE_PERMISSIONS_LIST']) - http_request_params: Dict[str, str] = prepare_file_permission_request_res['http_request_params'] + http_request_params: dict[str, str] = prepare_file_permission_request_res['http_request_params'] http_request_params.update( assign_params( @@ -1350,7 +1348,7 @@ def file_permission_list_command(client: 'GSuiteClient', args: Dict[str, str]) - @logger -def file_permission_create_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_permission_create_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Create file permissions @@ -1362,28 +1360,26 @@ def file_permission_create_command(client: 'GSuiteClient', args: Dict[str, str]) prepare_file_permission_request_res = prepare_file_permission_request( client, args, scopes=COMMAND_SCOPES['FILE_PERMISSIONS_CRUD']) - http_request_params: Dict[str, str] = prepare_file_permission_request_res['http_request_params'] - + http_request_params: dict[str, str] = prepare_file_permission_request_res['http_request_params'] http_request_params.update( assign_params( sendNotificationEmail=args.get('send_notification_email'), ) ) - body: Dict[str, str] = assign_params( + body: dict[str, str] = assign_params( role=args.get('role'), type=args.get('type'), domain=args.get('domain'), emailAddress=args.get('email_address'), ) - url_suffix = URL_SUFFIX['FILE_PERMISSION_CREATE'].format(args.get('file_id')) response = client.http_request(url_suffix=url_suffix, method='POST', params=http_request_params, body=body) return handle_response_permission_single(response, args) @logger -def file_permission_update_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_permission_update_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Update file permissions @@ -1397,7 +1393,7 @@ def file_permission_update_command(client: 'GSuiteClient', args: Dict[str, str]) client, args, scopes=COMMAND_SCOPES['FILE_PERMISSIONS_CRUD']) http_request_params = prepare_file_permission_request_res['http_request_params'] - body: Dict[str, str] = assign_params( + body: dict[str, str] = assign_params( role=args.get('role'), expirationTime=args.get('expiration_time'), ) @@ -1408,7 +1404,7 @@ def file_permission_update_command(client: 'GSuiteClient', args: Dict[str, str]) @logger -def file_permission_delete_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def file_permission_delete_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Delete file permissions @@ -1425,11 +1421,11 @@ def file_permission_delete_command(client: 'GSuiteClient', args: Dict[str, str]) url_suffix = URL_SUFFIX['FILE_PERMISSION_DELETE'].format(args.get('file_id'), args.get('permission_id')) client.http_request(url_suffix=url_suffix, method='DELETE', params=http_request_params) - outputs_context: Dict = { + outputs_context: dict = { 'fileId': args.get('file_id'), 'id': args.get('permission_id'), } - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_PERMISSION_HEADER']: { OUTPUT_PREFIX['FILE_PERMISSION']: outputs_context, } @@ -1447,8 +1443,7 @@ def file_permission_delete_command(client: 'GSuiteClient', args: Dict[str, str]) ) -def handle_response_permissions_list(response: Dict[str, Any], args: Dict[str, str]) -> CommandResults: - +def handle_response_permissions_list(response: dict[str, Any], args: dict[str, str]) -> CommandResults: outputs_context = [] readable_output = '' @@ -1457,7 +1452,7 @@ def handle_response_permissions_list(response: Dict[str, Any], args: Dict[str, s files_hr = prepare_permissions_human_readable(outputs_context, args) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_PERMISSION_HEADER']: { OUTPUT_PREFIX['FILE_PERMISSION']: outputs_context, }, @@ -1477,7 +1472,7 @@ def handle_response_permissions_list(response: Dict[str, Any], args: Dict[str, s ) -def prepare_permissions_human_readable(outputs_context: List[Dict[str, Any]], args: Dict[str, str]) -> str: +def prepare_permissions_human_readable(outputs_context: list[dict[str, Any]], args: dict[str, str]) -> str: """ Prepares human readable for google-drive-file-permissions-list command. @@ -1493,15 +1488,14 @@ def prepare_permissions_human_readable(outputs_context: List[Dict[str, Any]], ar removeNull=False) -def handle_response_permission_single(response: Dict[str, Any], args: Dict[str, str]) -> CommandResults: - +def handle_response_permission_single(response: dict[str, Any], args: dict[str, str]) -> CommandResults: readable_output = '' outputs_context = prepare_permission_output(response) files_hr = prepare_permission_human_readable(outputs_context, args) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['GOOGLE_DRIVE_FILE_PERMISSION_HEADER']: { OUTPUT_PREFIX['FILE_PERMISSION']: outputs_context } @@ -1516,7 +1510,7 @@ def handle_response_permission_single(response: Dict[str, Any], args: Dict[str, ) -def prepare_permission_output(permission: Dict[str, Any]) -> Dict[str, Any]: +def prepare_permission_output(permission: dict[str, Any]) -> dict[str, Any]: """ Prepares context output for google-drive-file-permissions commands. @@ -1532,7 +1526,7 @@ def prepare_permission_output(permission: Dict[str, Any]) -> Dict[str, Any]: return GSuiteClient.remove_empty_entities(ret_value) -def prepare_permission_human_readable(outputs_context: Dict[str, Any], args: Dict[str, str]) -> str: +def prepare_permission_human_readable(outputs_context: dict[str, Any], args: dict[str, str]) -> str: """ Prepares human readable for google-drive-file-permissions commands. @@ -1549,7 +1543,7 @@ def prepare_permission_human_readable(outputs_context: Dict[str, Any], args: Dic @logger -def drive_activity_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> CommandResults: +def drive_activity_list_command(client: 'GSuiteClient', args: dict[str, str]) -> CommandResults: """ Query past activity in Google Drive. @@ -1572,7 +1566,7 @@ def drive_activity_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> drive_activity_hr = prepare_drive_activity_human_readable(outputs_context) - outputs: Dict = { + outputs: dict = { OUTPUT_PREFIX['DRIVE_ACTIVITY_LIST']: outputs_context } if response.get('nextPageToken', ''): @@ -1589,8 +1583,8 @@ def drive_activity_list_command(client: 'GSuiteClient', args: Dict[str, str]) -> ) -def fetch_incidents(client: 'GSuiteClient', last_run: Dict, params: Dict, is_test: bool = False) -> \ - Tuple[Optional[list], Optional[dict]]: +def fetch_incidents(client: 'GSuiteClient', last_run: dict, params: dict, is_test: bool = False) -> \ + tuple[list | None, dict | None]: """ Prepares incidents from past activity in Google Drive. @@ -1613,7 +1607,7 @@ def fetch_incidents(client: 'GSuiteClient', last_run: Dict, params: Dict, is_tes body = prepare_args_for_fetch_incidents(last_fetch, params) - incidents: List[Dict[str, Any]] = [] + incidents: list[dict[str, Any]] = [] client.set_authorized_http(scopes=COMMAND_SCOPES['DRIVE_ACTIVITY'], subject=params.get('user_id')) response = client.http_request(body=body, full_url=URLS['DRIVE_ACTIVITY'], @@ -1661,7 +1655,7 @@ def main() -> None: """ # Commands dictionary - commands: Dict[str, Callable] = { + commands: dict[str, Callable] = { 'google-drive-create': drive_create_command, 'google-drive-changes-list': drive_changes_list_command, 'google-drive-activity-list': drive_activity_list_command, diff --git a/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.yml b/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.yml index 6d157167595f..e90f8cb3dbda 100644 --- a/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.yml +++ b/Packs/GoogleDrive/Integrations/GoogleDrive/GoogleDrive.yml @@ -1588,9 +1588,13 @@ script: description: Page token for shared drives. - name: query description: Query string for searching shared drives. - - name: use_domain_admin_access - description: "Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned." + - auto: PREDEFINED defaultValue: "false" + name: use_domain_admin_access + description: "Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned." + predefined: + - "true" + - "false" - name: user_id description: The user's primary email address. outputs: @@ -1678,9 +1682,13 @@ script: - name: google-drive-drive-get description: Gets a user shared drives. arguments: - - name: use_domain_admin_access - description: "Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned." + - auto: PREDEFINED defaultValue: "false" + name: use_domain_admin_access + description: "Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned." + predefined: + - "true" + - "false" - name: user_id description: The user's primary email address. - name: drive_id @@ -2544,6 +2552,13 @@ script: predefined: - "true" - "false" + - auto: PREDEFINED + defaultValue: "false" + name: use_domain_admin_access + description: "Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned." + predefined: + - "true" + - "false" outputs: - contextPath: GoogleDrive.FilePermission.FilePermission.deleted description: Whether the account associated with this permission has been deleted. This field only pertains to user and group permissions. @@ -2686,7 +2701,7 @@ script: predefined: - "true" - "false" - dockerimage: demisto/googleapi-python3:1.0.0.65068 + dockerimage: demisto/googleapi-python3:1.0.0.66918 isfetch: true runonce: false script: "-" diff --git a/Packs/GoogleDrive/Integrations/GoogleDrive/README.md b/Packs/GoogleDrive/Integrations/GoogleDrive/README.md index 50c44d988d69..9d32111090cb 100644 --- a/Packs/GoogleDrive/Integrations/GoogleDrive/README.md +++ b/Packs/GoogleDrive/Integrations/GoogleDrive/README.md @@ -1,39 +1,45 @@ Google Drive allows users to store files on their servers, synchronize files across devices, and share files. This integration helps you to create a new drive, query past activity, and view change logs performed by the users. This integration was integrated and tested with version 1.31.0 of GoogleDrive -## Configure GoogleDrive on Cortex XSOAR +## Configure Google Drive on Cortex XSOAR 1. Navigate to **Settings** > **Integrations** > **Servers & Services**. -2. Search for GoogleDrive. +2. Search for Google Drive. 3. Click **Add instance** to create and configure a new integration instance. | **Parameter** | **Description** | **Required** | | --- | --- | --- | - | User's Service Account JSON | | True | - | User ID | The primary email address of the user to fetch the incident\(s\). | False | - | Action Detail Case Include | Action types to include for fetching the incident. | False | - | Drive Item Search Field | itemName - Fetch activities for this drive item. The format is "items/ITEM_ID". folderName - Fetch activities for this drive folder and all children and descendants. The format is "items/ITEM_ID". | False | - | Drive Item Search Value | itemName or folderName for fetching the incident. | False | - | Fetch incidents | | False | - | Incident type | | False | - | Max Incidents | The maximum number of incidents to fetch each time. | False | - | First Fetch Time Interval | The time range to consider for the initial data fetch in the format <number> <unit> e.g., 1 hour, 2 hours, 6 hours, 12 hours, 24 hours, 48 hours. | False | - | Trust any certificate (not secure) | | False | - | Use system proxy settings | | False | + | User's Service Account JSON | | | + | User ID | The primary email address of the user to fetch the incident\(s\). | | + | User ID | | | + | User's Service Account JSON | | | + | Action Detail Case Include | Action types to include for fetching the incident. | | + | Drive Item Search Field | itemName - Fetch activities for this drive item. The format is "items/ITEM_ID". folderName - Fetch activities for this drive folder and all children and descendants. The format is "items/ITEM_ID". | | + | Drive Item Search Value | itemName or folderName for fetching the incident. | | + | Fetch incidents | | | + | Incident type | | | + | Max Incidents | The maximum number of incidents to fetch each time. | | + | First Fetch Time Interval | The time range to consider for the initial data fetch in the format <number> <unit> e.g., 1 hour, 2 hours, 6 hours, 12 hours, 24 hours, 48 hours. | | + | Trust any certificate (not secure) | | | + | Use system proxy settings | | | 4. Click **Test** to validate the URLs, token, and connection. + ## Commands + You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details. + ### google-drive-create + *** Creates a new Team Drive. The name argument specifies the name of the Team Drive. The specified user will be the first organizer. This shared drive/team drive feature is available only with G Suite Enterprise, Enterprise for Education, G Suite Essentials, Business, Education, and Nonprofits edition. - #### Base Command `google-drive-create` + #### Input | **Argument Name** | **Description** | **Required** | @@ -42,7 +48,6 @@ This shared drive/team drive feature is available only with G Suite Enterprise, | name | The name of this shared drive. | Required | | hidden | Whether the shared drive is hidden from the default view. Possible values: "True" and "False". Possible values are: True, False. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -52,22 +57,15 @@ This shared drive/team drive feature is available only with G Suite Enterprise, | GoogleDrive.Drive.name | String | The name of the shared drive. | | GoogleDrive.Drive.hidden | Boolean | Whether the shared drive is hidden from the default view. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-changes-list + *** Lists the changes for a user or shared drive. - #### Base Command `google-drive-changes-list` + #### Input | **Argument Name** | **Description** | **Required** | @@ -85,7 +83,6 @@ Lists the changes for a user or shared drive. | supports_all_drives | Whether the requesting application supports both My Drives and shared drives. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | | fields | The paths of the fields you want to include in the response. Possible values are: "basic" (the response will include a default set of fields specific to this method) and "advance" (you can use the value * to return all the fields). Possible values are: basic, advance. Default is basic. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -287,22 +284,15 @@ Lists the changes for a user or shared drive. | GoogleDrive.DriveChange.drive.restrictions.domainUsersOnly | Boolean | Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. | | GoogleDrive.DriveChange.drive.restrictions.driveMembersOnly | Boolean | Whether access to items inside this shared drive is restricted to its members. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-activity-list + *** Query past activity in Google Drive. - #### Base Command `google-drive-activity-list` + #### Input | **Argument Name** | **Description** | **Required** | @@ -316,7 +306,6 @@ Query past activity in Google Drive. | action_detail_case_remove | A singular value or a list of allowed action types enclosed in parentheses. The filters are based on given actions. For example:
RENAME
(CREATE EDIT)
This argument will override if the filter argument is given. | Optional | | page_token | The token identifying which page of results to return. Set this to the nextPageToken value returned from a previous query to obtain the following page of results. If not set, the first page of results will be returned. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -563,22 +552,15 @@ Query past activity in Google Drive. | GoogleDrive.DriveActivity.timeRange.startTime | String | The start of the time range. | | GoogleDrive.DriveActivity.timeRange.endTime | String | The end of the time range. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-drives-list + *** Lists the user's shared drives. - #### Base Command `google-drive-drives-list` + #### Input | **Argument Name** | **Description** | **Required** | @@ -589,7 +571,6 @@ Lists the user's shared drives. | use_domain_admin_access | Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned. Default is false. | Optional | | user_id | The user's primary email address. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -622,22 +603,15 @@ Lists the user's shared drives. | GoogleDrive.Drive.Drive.restrictions.domainUsersOnly | Boolean | Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. This restriction may be overridden by other sharing policies controlled outside of this shared drive. | | GoogleDrive.Drive.Drive.restrictions.driveMembersOnly | Boolean | Whether access to items inside this shared drive is restricted to its members. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-drive-get + *** Gets a user shared drives. - #### Base Command `google-drive-drive-get` + #### Input | **Argument Name** | **Description** | **Required** | @@ -647,7 +621,6 @@ Gets a user shared drives. | drive_id | ID of the shared drive. Can be retrieved using the `google-drive-drives-list` command. | Optional | | fields | The fields you want included in the response. Default is kind, id, name, themeId, capabilities, createdTime, hidden, restrictions. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -680,22 +653,15 @@ Gets a user shared drives. | GoogleDrive.Drive.Drive.restrictions.domainUsersOnly | Boolean | Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. This restriction may be overridden by other sharing policies controlled outside of this shared drive. | | GoogleDrive.Drive.Drive.restrictions.driveMembersOnly | Boolean | Whether access to items inside this shared drive is restricted to its members. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-files-list + *** Lists the user's shared drives. - #### Base Command `google-drive-files-list` + #### Input | **Argument Name** | **Description** | **Required** | @@ -703,11 +669,10 @@ Lists the user's shared drives. | page_size | Maximum number of shared drives to return. Acceptable values are 1 to 100, inclusive. Default is 100. | Optional | | page_token | Page token for shared drives. | Optional | | query | Query string for searching shared drives. | Optional | +| include_items_from_all_drives | Whether both My Drive and shared drive items should be included in the results. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | | user_id | The user's primary email address. | Optional | | fields | The fields you want included in the response. Default is kind, id, name, mimeType, description, starred, trashed, explicitlyTrashed, trashingUser, trashedTime, parents, properties, appProperties, spaces, version, webContentLink, webViewLink, iconLink, hasThumbnail, thumbnailLink, thumbnailVersion, viewedByMe, viewedByMeTime, createdTime, modifiedTime, modifiedByMeTime, modifiedByMe, sharedWithMeTime, sharingUser, owners, teamDriveId, driveId, lastModifyingUser, shared, ownedByMe, capabilities, viewersCanCopyContent, copyRequiresWriterPermission, writersCanShare, permissions, permissionIds, hasAugmentedPermissions, folderColorRgb, originalFilename, fullFileExtension, fileExtension, md5Checksum, size, quotaBytesUsed, headRevisionId, contentHints, isAppAuthorized, exportLinks, shortcutDetails, contentRestrictions, resourceKey, linkShareMetadata. | Optional | | supports_all_drives | Whether the requesting application supports both My Drives and shared drives. Possible values are: True, False. Default is False. | Optional | -| include_items_from_all_drives | Whether both My Drive and shared drive items should be included in the results. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | - #### Context Output @@ -718,31 +683,23 @@ Lists the user's shared drives. | GoogleDrive.File.File.name | String | The name of the file. This is not necessarily unique within a folder. | | GoogleDrive.File.File.resourceKey | String | A key needed to access the item via a shared link. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-get + *** Get a single file. - #### Base Command `google-drive-file-get` + #### Input | **Argument Name** | **Description** | **Required** | | --- | --- | --- | | file_id | ID of the requested file. Can be retrieved using the `google-drive-files-list` command. | Optional | | user_id | The user's primary email address. | Optional | -| fields | The fields you want included in the response. Default is kind, id, name, mimeType, description, starred, trashed, explicitlyTrashed, trashingUser, trashedTime, parents, properties, appProperties, spaces, version, webContentLink, webViewLink, iconLink, hasThumbnail, thumbnailLink, thumbnailVersion, viewedByMe, viewedByMeTime, createdTime, modifiedTime, modifiedByMeTime, modifiedByMe, sharedWithMeTime, sharingUser, owners, teamDriveId, driveId, lastModifyingUser, shared, ownedByMe, capabilities, viewersCanCopyContent, copyRequiresWriterPermission, writersCanShare, permissions, permissionIds, hasAugmentedPermissions, folderColorRgb, originalFilename, fullFileExtension, fileExtension, md5Checksum, size, quotaBytesUsed, headRevisionId, contentHints, isAppAuthorized, exportLinks, shortcutDetails, contentRestrictions, resourceKey, linkShareMetadata. | Optional | | include_items_from_all_drives | Whether both My Drive and shared drive items should be included in the results. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | - +| fields | The fields you want included in the response. Default is kind, id, name, mimeType, description, starred, trashed, explicitlyTrashed, trashingUser, trashedTime, parents, properties, appProperties, spaces, version, webContentLink, webViewLink, iconLink, hasThumbnail, thumbnailLink, thumbnailVersion, viewedByMe, viewedByMeTime, createdTime, modifiedTime, modifiedByMeTime, modifiedByMe, sharedWithMeTime, sharingUser, owners, teamDriveId, driveId, lastModifyingUser, shared, ownedByMe, capabilities, viewersCanCopyContent, copyRequiresWriterPermission, writersCanShare, permissions, permissionIds, hasAugmentedPermissions, folderColorRgb, originalFilename, fullFileExtension, fileExtension, md5Checksum, size, quotaBytesUsed, headRevisionId, contentHints, isAppAuthorized, exportLinks, shortcutDetails, contentRestrictions, resourceKey, linkShareMetadata. | Optional | #### Context Output @@ -817,22 +774,15 @@ Get a single file. | GoogleDrive.File.File.webViewLink | String | A link for opening the file in a relevant Google editor or viewer in a browser. | | GoogleDrive.File.File.writersCanShare | Boolean | Whether users with only writer permission can modify the file's permissions. Not populated for items in shared drives. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-upload + *** Creates a new file. - #### Base Command `google-drive-file-upload` + #### Input | **Argument Name** | **Description** | **Required** | @@ -841,7 +791,6 @@ Creates a new file. | entry_id | The file's Entry ID. | Optional | | parent | The ID of the parent folder which contains the file. If not specified as part of a create request, the file will be placed directly in the user's My Drive folder. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -916,22 +865,15 @@ Creates a new file. | GoogleDrive.File.File.permissions.type | String | The type of the grantee. | | GoogleDrive.File.File.permissions.photoLink | String | A link to the user's profile photo, if available. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-download + *** Download a single file. - #### Base Command `google-drive-file-download` + #### Input | **Argument Name** | **Description** | **Required** | @@ -940,7 +882,6 @@ Download a single file. | file_name | Name of the downloaded file. Default is untitled. | Optional | | user_id | The user's primary email address. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -956,22 +897,15 @@ Download a single file. | File.MD5 | String | The MD5 hash of the file. | | File.Extension | String | The file extension. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-replace-existing + *** Updates a file's content. - #### Base Command `google-drive-file-replace-existing` + #### Input | **Argument Name** | **Description** | **Required** | @@ -979,7 +913,6 @@ Updates a file's content. | file_id | ID of the file to replace. Can be retrieved using the `google-drive-files-list` command. | Optional | | entry_id | The file's entry ID. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -1054,22 +987,15 @@ Updates a file's content. | GoogleDrive.File.File.permissions.type | String | The type of the grantee. | | GoogleDrive.File.File.permissions.photoLink | String | A link to the user's profile photo, if available. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-delete + *** Permanently deletes a file owned by the user without moving it to the trash. If the file belongs to a shared drive the user must be an organizer on the parent. If the target is a folder, all descendants owned by the user are also deleted. - #### Base Command `google-drive-file-delete` + #### Input | **Argument Name** | **Description** | **Required** | @@ -1078,29 +1004,21 @@ Permanently deletes a file owned by the user without moving it to the trash. If | user_id | The user's primary email address. | Optional | | supports_all_drives | Whether the requesting application supports both My Drives and shared drives. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | - #### Context Output | **Path** | **Type** | **Description** | | --- | --- | --- | | GoogleDrive.File.File.id | String | ID of the deleted file. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-permissions-list + *** Lists a file's or shared drive's permissions. - #### Base Command `google-drive-file-permissions-list` + #### Input | **Argument Name** | **Description** | **Required** | @@ -1110,7 +1028,7 @@ Lists a file's or shared drive's permissions. | page_size | Maximum number of shared drives to return. Acceptable values are 1 to 100, inclusive. Default is 100. | Optional | | page_token | Page token for shared drives. | Optional | | supports_all_drives | Whether the requesting application supports both My Drives and shared drives. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | - +| use_domain_admin_access | Issue the request as a domain administrator. If set to true, all shared drives of the domain in which the requester is an administrator are returned. Default is false. | Optional | #### Context Output @@ -1124,22 +1042,15 @@ Lists a file's or shared drive's permissions. | GoogleDrive.FilePermission.FilePermission.type | String | The type of the grantee. | | GoogleDrive.FilePermission.FilePermission.photoLink | String | A link to the user's profile photo, if available. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-permission-create + *** Creates a permission for a file or shared drive. - #### Base Command `google-drive-file-permission-create` + #### Input | **Argument Name** | **Description** | **Required** | @@ -1152,7 +1063,6 @@ Creates a permission for a file or shared drive. | domain | The domain to which this permission refers. | Optional | | email_address | The email address of the user or group to which this permission refers. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -1165,22 +1075,15 @@ Creates a permission for a file or shared drive. | GoogleDrive.FilePermission.FilePermission.type | String | The type of the grantee. | | GoogleDrive.FilePermission.FilePermission.photoLink | String | A link to the user's profile photo, if available. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-permission-update + *** Updates a permission with patch semantics. - #### Base Command `google-drive-file-permission-update` + #### Input | **Argument Name** | **Description** | **Required** | @@ -1191,7 +1094,6 @@ Updates a permission with patch semantics. | permission_id | The ID of the permission. Can be retrieved using the `google-drive-file-permissions-list` command. | Optional | | role | The role granted by this permission. Possible values: "owner", "organizer", "fileOrganizer", "writer", "commenter", and "reader". Possible values are: owner, organizer, fileOrganizer, writer, commenter, reader. Default is reader. | Optional | - #### Context Output | **Path** | **Type** | **Description** | @@ -1204,22 +1106,15 @@ Updates a permission with patch semantics. | GoogleDrive.FilePermission.FilePermission.type | String | The type of the grantee. | | GoogleDrive.FilePermission.FilePermission.photoLink | String | A link to the user's profile photo, if available. | - -#### Command Example -``` ``` - -#### Human Readable Output - - - ### google-drive-file-permission-delete + *** Delete a permission. - #### Base Command `google-drive-file-permission-delete` + #### Input | **Argument Name** | **Description** | **Required** | @@ -1229,14 +1124,6 @@ Delete a permission. | permission_id | The ID of the permission. Can be retrieved using the `google-drive-file-permissions-list` command. | Optional | | supports_all_drives | Whether the requesting application supports both My Drives and shared drives. Possible values: "true" and "false". Possible values are: true, false. Default is false. | Optional | - #### Context Output There is no context output for this command. - -#### Command Example -``` ``` - -#### Human Readable Output - - diff --git a/Packs/GoogleDrive/ReleaseNotes/1_2_38.md b/Packs/GoogleDrive/ReleaseNotes/1_2_38.md new file mode 100644 index 000000000000..1f56cda38468 --- /dev/null +++ b/Packs/GoogleDrive/ReleaseNotes/1_2_38.md @@ -0,0 +1,4 @@ +#### Integrations +##### Google Drive +- Added the *use_domain_admin_access* param to *google-drive-file-permissions-list*. +- Updated the Docker image to: *demisto/googleapi-python3:1.0.0.66918*. \ No newline at end of file diff --git a/Packs/GoogleDrive/pack_metadata.json b/Packs/GoogleDrive/pack_metadata.json index a39c304050a5..425ac41f7b9b 100644 --- a/Packs/GoogleDrive/pack_metadata.json +++ b/Packs/GoogleDrive/pack_metadata.json @@ -2,7 +2,7 @@ "name": "Google Drive", "description": "Google Drive allows users to store files on their servers, synchronize files across devices, and share files. This integration helps you to create a new drive, query past activity and view change logs performed by the users, as well as list drives and files, and manage their permissions.", "support": "xsoar", - "currentVersion": "1.2.37", + "currentVersion": "1.2.38", "author": "Cortex XSOAR", "url": "https://www.paloaltonetworks.com/cortex", "email": "", diff --git a/Tests/conf.json b/Tests/conf.json index 12ea23dfe6ac..caa7df50e938 100644 --- a/Tests/conf.json +++ b/Tests/conf.json @@ -225,7 +225,8 @@ { "integrations": "GoogleDrive", "playbookID": "GoogleDrive-Test", - "fromversion": "5.0.0" + "fromversion": "5.0.0", + "memory_threshold": 300 }, { "integrations": "FireEye Central Management", @@ -4711,7 +4712,8 @@ "fromversion": "5.0.0", "integrations": [ "GoogleDrive" - ] + ], + "memory_threshold": 300 }, { "playbookID": "RiskIQDigitalFootprint-Test", @@ -6063,7 +6065,7 @@ "memory_threshold": 105 }, "demisto/googleapi-python3": { - "memory_threshold": 200 + "memory_threshold": 300 }, "demisto/python3:3.10.4.29342": { "memory_threshold": 85