Zoom
Use the Zoom integration to manage your Zoom users and meetings.
Messaging and Conferencing · Zoom
Details
| ID | Zoom |
|---|---|
| Provider | Zoom |
| Category | Messaging and Conferencing |
| From Version | 5.0.0 |
| Docker Image | demisto/fastapi:0.125.0.10158186 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Use the Zoom integration manage your Zoom users and meetings
This integration was integrated and tested with version 2.0.0 of Zoom
Configure Zoom in Cortex
| Parameter | Description | Required |
|---|---|---|
Server URL (e.g., ‘https://api.zoom.us/v2/’) |
True | |
Account ID (OAuth) |
True | |
Client ID (OAuth) |
True | |
Client Secret (OAuth) |
True | |
Use system proxy settings |
False | |
Trust any certificate (not secure) |
False | |
Long running instance |
Enable in order to use zoom-ask and for mirroring. | False |
Listen Port |
Listener port number. Required when choosing long running instance with an external engine for using the Zoom Bot. | False |
Bot JID |
Zoom Bot app JID. | False |
Bot Client ID (OAuth) |
Zoom Bot app client ID. | False |
Bot Client Secret (OAuth) |
Zoom Bot app secret ID. | False |
Secret Token |
For mirroring, see Configuring Secret Token. | False |
Verification Token |
For verify the mirror in. | False |
Mirroring |
Enable Incident Mirroring. See how to configure the app. | False |
Certificate (Required for HTTPS) |
(For Cortex XSOAR 6.x) For use with HTTPS - the certificate that the service should use. (For Cortex XSOAR 8 and Cortex XSIAM) Custom certificates are supported only using engine. | False |
Private Key (Required for HTTPS) |
(For Cortex XSOAR 6.x) For use with HTTPS - the private key that the service should use. (For Cortex XSOAR 8 and Cortex XSIAM) When using an engine, configure a private API key | False |
Server configuration (XSOAR 6.x)
In the Server Configuration section, verify that the value for the instance.execute.external.INTEGRATION-INSTANCE-NAME key is set to true. If this key does not exist:
- Click + Add Server Configuration.
- Add instance.execute.external.
INTEGRATION-INSTANCE-NAMEand set the value to true.
XSOAR endpoint URL-
- For Cortex XSOAR 6.x:
<CORTEX-XSOAR-URL>/instance/execute/<INTEGRATION-INSTANCE-NAME>. For example,https://my.demisto.live/instance/execute/zoom. Note that the stringinstancedoes not refer to the name of your XSOAR instance, but rather is part of the URL. - For Cortex XSOAR 8.x / XSIAM: you need to run using external engine:
https://<Engine URL>:<port>. For example, https://my-engine-url:7001.
Create Zoom ChatBOT app
- Log onto the Zoom App Marketplace: https://marketplace.zoom.us/.
- Click Develop > Build App.
- Choose General App.
- Click Create.

Configure App Settings
- Update your app’s name. By default, the build flow generates a generic name for your app. To change your app’s name, select the edit icon (pencil) and update the name. To save your changes, click anywhere outside of the app name field.
- Under the section “Select how the app is managed”, select “Admin-managed”, and click “Save”.
- Enter your Cortex XSOAR endpoint URL in the OAuth Redirect URL.
- Click Features > Surface > Team Chat.
Toggle on the “Team Chat Subscription” section. Under “Bot Endpoint URL”, add:- For Cortex XSOAR 6.x:
<CORTEX-XSOAR-URL>/instance/execute/<INTEGRATION-INSTANCE-NAME>. For example,https://my.demisto.live/instance/execute/zoom. Note that the stringinstancedoes not refer to the name of your Cortex XSOAR instance, but rather is part of the URL. - For Cortex XSOAR 8.x / XSIAM you need to run using external engine:
https://<Engine Url>:<port>. For example, https://my-engine-url:7001.
- For Cortex XSOAR 6.x:

-
Click Scopes > + Add Scopes to add the following scope permissions.
Scope Type Scope Name Team Chat /imchat:bot Team Chat /team_chat:read:user_message:admin Team Chat /team_chat:read:list_user_sessions:admin Team Chat /team_chat:read:list_user_messages:admin Team Chat /team_chat:write:user_channel:admin Team Chat /team_chat:write:members:admin Team Chat /team_chat:update:user_channel:admin User /user:read:user:admin

-
Click Local Test > Add App Now to test your app and authorize your Cortex XSOAR app.
-
If mirroring is enabled in the integration configuration or using
ZoomAsk:- Endpoint URL Requirements:
According to the Zoom requirements in order to receive webhooks, the Event notification endpoint URL that you specify for each event subscription must:- Be a publicly accessible https endpoint url that supports TLSv1.2+ with a valid certificate chain issued by a Certificate Authority (CA).
- Employ the
https://scheme. - Be able to accept HTTP POST requests containing JSON payloads.
- Be a fully qualified domain name (FQDN).
- be able to respond with an HTTP Status Code.
-
Zoom Configurations:
- Copy the Secret Token from the “Features” > “Access” page under the “Token” section and add it to the instance configuration.

- Configure Event Subscriptions.
- In the “Features” section, under “Access”, in the “General Features” section, enable “Event Subscription”.
- Click +Add New Event Subscription.
- Enter the following information:
- Subscription name: Enter a name for this Event Subscription (e.g., “Send Message Sent”)
- Add Events: Click +Add Events. Under Event Types, select Chat Message, and then select Chat Message Sent.
- Event notification endpoint URL: Enter the Cortex XSOAR URL of your server (
CORTEX-XSOAR-URL/instance/execute/INTEGRATION-INSTANCE-NAME) where you want to receive event notifications. This URL should handle incoming event data from Zoom. Make sure it’s publicly accessible. - Authentication Header Option -
-
Default Header Provided by Zoom option - This option allows you to use a verification token provided by Zoom. Copy the Verification Token under the “Token” section and add it to the instance configuration.

-
Basic Authentication option - You can use Basic Authentication by providing your Zoom Client ID (OAuth) and Secret ID (OAuth) as configured in the instance configuration.

-

- Copy the Secret Token from the “Features” > “Access” page under the “Token” section and add it to the instance configuration.
- Endpoint URL Requirements:
Commands
You can execute these commands from the 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.
zoom-create-user
Create a new user in zoom account
Base Command
zoom-create-user
Input
| Argument Name | Description | Required |
|---|---|---|
| first_name | First name of the new user. | Required |
| last_name | Last name of the new user. | Required |
| The email of the new user. | Required | |
| user_type | The type of the newly created user. Note: the old type “pro” in now called “Licensed”, and the type “Corporate” is not sopprted in Zoom v2 and above.. Possible values are: Basic, Licensed, pro, Corporate. Default is Basic. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.User.id | string | The ID of the created user |
| Zoom.User.first_name | string | First name of the created user |
| Zoom.User.last_name | string | Last name for the created user |
| Zoom.User.email | string | Email of the created user |
| Zoom.User.created_at | date | Created date of the user. Note that this field does not appear in zoom v2 and above. |
| Zoom.User.type | number | The type of the user |
Command example
!zoom-create-user email=example@example.com first_name=john last_name=smith user_type=Basic
Context Example
{
"Zoom": {
"User": {
"email": "example@example.com",
"first_name": "john",
"id": "wSQafNLNSJWq_oBzmT7XOw",
"last_name": "smith",
"type": 1
}
}
}
Human Readable Output
User created successfully with ID: wSQafNLNSJWq_oBzmT7XOw
zoom-create-meeting
Create a new zoom meeting (scheduled ,instant, or recurring)
Base Command
zoom-create-meeting
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The type of the meeting. Possible values are: Instant, Scheduled, Recurring meeting with fixed time. Default is Instant. | Required |
| end_date_time | For recurring meetings only. Select the final date on which the meeting will recur before it is canceled. For example: 2017-11-25T12:00:00Z. | Optional |
| end_times | For recurring meetings only.Select how many times the meeting should recur before it is canceled. max = 365. Default = 1.. | Optional |
| monthly_day | For recurring meetings with Monthly recurrence_type only. State the day in a month the meeting should recur. The value range is from 1 to 31. Default = 1.. | Optional |
| monthly_week | For recurring meetings with Monthly recurrence_type only.State the week of the month when the meeting should recur. If you use this field, you must also use the monthly_week_day field to state the day of the week when the meeting should recur. Allowed: -1 (for last week of the month) ┃1┃2┃3┃4. | Optional |
| monthly_week_day | For recurring meetings with Monthly recurrence_type only. State a specific day in a week when the monthly meeting should recur. Allowed: 1┃2┃3┃4┃5┃6┃7To use this field, you must also use the monthly_week field.. | Optional |
| repeat_interval | For recurring meeting with fixed time only. Define the interval at which the meeting should recur. For instance, if you would like to schedule a meeting that recurs every two months, you must set the value of this field as 2 and the value of the type parameter as Monthly. For a daily meeting, the maximum is 90 days. For a weekly meeting the maximum is of 12 weeks. For a monthly meeting, there is a maximum of 3 months. | Optional |
| recurrence_type | For recurring meetings only. Set the recurrence meeting types.. Possible values are: Daily, Weekly, Monthly. | Optional |
| weekly_days | For recurring meetings with a Weekly recurrence_type only. State a specific day in a week when the weekly meeting should recur. Allowed: 1┃2┃3┃4┃5┃6┃7 Default = 1.. | Optional |
| auto-record-meeting | The automatic recording settings. Note that the Cloud option is available for Zoom paid customers only. Possible values are: local, cloud, none. Default is none. | Optional |
| encryption_type | The type of end-to-end (E2EE) encryption, enhanced_encryption or e2ee. Possible values are: enhanced_encryption, e2ee. Default is enhanced_encryption. | Optional |
| host_video | start meetings with the host video on. Possible values are: true, false. Default is True. | Optional |
| join_before_host_time | If the value of the join_before_host field is true, this field sets the time that a participant can join before the meeting’s host. You can choose: 5 or 10 (minutes), or 0 for any time. Possible values are: 0, 5, 10. | Optional |
| join_before_host | Whether participants can join the meeting before its host. For scheduled or recurring meetings only. The default value is False. Possible values are: false, true. | Optional |
| meeting_authentication | If true, only authenticated users can join the meeting. Possible values are: false, true. Default is false. | Optional |
| user | email address or id of user for meeting. | Required |
| topic | The topic of the meeting. | Required |
| waiting_room | This allows the host to control when a participant joins the meeting. The default is False. Possible values are: false, true. | Optional |
| start-time | Meeting start time. When using a format like “yyyy-MM-ddTHH:mm:ssZ”, always use GMT time. When using a format like “yyyy-MM-ddTHH:mm:ss”, you should use local time and you will need to specify the time zone. Only used for scheduled meetings and recurring meetings with fixed time. | Optional |
| timezone | Timezone to format start_time. For example, “America/Los_Angeles”. For scheduled meetings only. . | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Meeting.join_url | string | Join url for the meeting |
| Zoom.Meeting.id | string | Meeting id of the new meeting that is created |
| Zoom.Meeting.start_url | string | The URL to start the meeting |
| Zoom.Meeting.uuid | string | Unique meeting ID of the new meeting that is created |
| Zoom.Meeting.status | string | The status of the meeting |
| Zoom.Meeting.start_time | Date | The time that the meeting will start at |
| Zoom.Meeting.host email | string | The email of the host of this meeting |
| Zoom.Meeting.topic | string | The topic of the meeting |
| Zoom.Meeting.duration | number | The duratian of the meeting |
| Zoom.Meeting.created_at | Date | The time that this meeting was created |
| Zoom.Meeting.type | number | The type of the new meeting, Instant = 1, Scheduled =2,Recurring with fixed time = 8 |
Command example
!zoom-create-meeting topic=test type=scheduled user=example@example.com start-time=2023-01-29T12:12:12Z
Context Example
{
"Zoom": {
"Meeting": {
"created_at": "2023-01-15T12:44:30Z",
"duration": 60,
"host_email": "example@example.com",
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 88454393857,
"join_url": "https://us06web.zoom.us/j/8845?pwd=WkI1WUdvbHhnMlJuaXU1WDNPdz09",
"pre_schedule": false,
"settings": {
"allow_multiple_devices": false,
"alternative_host_update_polls": false,
"alternative_hosts": "",
"alternative_hosts_email_notification": true,
"approval_type": 2,
"approved_or_denied_countries_or_regions": {
"enable": false
},
"audio": "both",
"auto_recording": "none",
"breakout_room": {
"enable": false
},
"close_registration": false,
"cn_meeting": false,
"device_testing": false,
"email_notification": true,
"enable_dedicated_group_chat": false,
"encryption_type": "enhanced_encryption",
"enforce_login": false,
"enforce_login_domains": "",
"focus_mode": false,
"global_dial_in_countries": [
"US"
],
"global_dial_in_numbers": [
{
"city": "Houston",
"country": "US",
"country_name": "US",
"number": "+1 3462487799",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3602095623",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3863475053",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 5074734847",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 5642172000",
"type": "toll"
},
{
"city": "New York",
"country": "US",
"country_name": "US",
"number": "+1 6465588656",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 6469313860",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 6694449171",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 6892781000",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 7193594580",
"type": "toll"
},
{
"city": "Denver",
"country": "US",
"country_name": "US",
"number": "+1 7207072699",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 2532050468",
"type": "toll"
},
{
"city": "Tacoma",
"country": "US",
"country_name": "US",
"number": "+1 2532158782",
"type": "toll"
},
{
"city": "Washington DC",
"country": "US",
"country_name": "US",
"number": "+1 3017158592",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3052241968",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3092053325",
"type": "toll"
},
{
"city": "US",
"country": "US",
"country_name": "US",
"number": "+1 3126266799",
"type": "toll"
}
],
"host_save_video_order": false,
"host_video": true,
"in_meeting": false,
"jbh_time": 0,
"join_before_host": false,
"meeting_authentication": false,
"mute_upon_entry": false,
"participant_video": false,
"private_meeting": false,
"registrants_confirmation_email": true,
"registrants_email_notification": true,
"request_permission_to_unmute_participants": false,
"show_share_button": false,
"use_pmi": false,
"waiting_room": false,
"watermark": false
},
"start_time": "2023-01-29T12:12:12Z",
"start_url": "https://us06web.zoom.us/s/883857?zIjAwMDAwMSIsInptX3NrbSI6InptX28ybSIsImFsZyI6IkhTMjU2In0.eyJhdWQiOiJjbGllbnRzbSIsInVpZCI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4NDU0MzkzODU3IiwiZXhwIjoxNjczNzkzODcwLCJpYXQiOjE2NzM3ODY2NzAsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.5vRJBkMbmODUD_7H3bkS7OjR-MuuLUzNMJ_KeCzWc_U",
"status": "waiting",
"timezone": "Asia/Jerusalem",
"topic": "test",
"type": 2,
"uuid": "4gbib+fjTFmz1wH1LoE7EQ=="
}
}
}
Human Readable Output
Meeting details
uuid id host_id host_email topic type status start_time duration timezone created_at start_url join_url 4gbib+fjTFmz1wH1LoE7EQ== 88454393857 uJiZN-O7Rp6Jp_995FpZGg example@example.com test 2 waiting 2023-01-29T12:12:12Z 60 Asia/Jerusalem 2023-01-15T12:44:30Z https://us06web.zoom.us/s/88454393857?zak=eyJ0eXAiOiJKV1QiLCJzdiI6IjAwMDAwMSIsInptX3NrbSI6InptX28ybSIsImFsZyI6IkhTMjU2In0.eyJhdWQiOiJjbGllbnRzbSIsInVpZCI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4NDU0MzkzODU3IiwiZXhwIjoxNjczNzkzODcwLCJpYXQiOjE2NzM3ODY2NzAsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.5vRJBkMbmODUD_7H3bkS7OjR-MuuLUzNMJ_KeCzWc_U https://us06web.zoom.us/j/88454393857?pwd=WkI1WnVEWUdvbHhnMlJuaXU1WDNPdz09
zoom-fetch-recording
Get meeting record and save as file in the warroom
Base Command
zoom-fetch-recording
Input
| Argument Name | Description | Required |
|---|---|---|
| meeting_id | Meeting ID of the recorded meeting. | Required |
| delete_after | Whether to delete the recording from the cloud after downloading. Possible values are: false, true. Default is true. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.SHA256 | Unknown | Attachment’s SHA256 |
| File.SHA1 | Unknown | Attachment’s SHA1 |
| File.MD5 | Unknown | Attachment’s MD5 |
| File.Name | Unknown | Attachment’s Name |
| File.Info | Unknown | Attachment’s Info |
| File.Size | Unknown | Attachment’s Size (In Bytes) |
| File.Extension | Unknown | Attachment’s Extension |
| File.Type | Unknown | Attachment’s Type |
| File.EntryID | Unknown | Attachment’s EntryID |
| File.SSDeep | Unknown | Attachment’s SSDeep hash |
Command example
!zoom-fetch-recording meeting_id=83622325727 delete_after=false
Context Example
{
"File": [
{
"EntryID": "446@37e93103-1bd6-4776-8021-0f7023b1bb79",
"Extension": "MP4",
"Info": "video/mp4",
"MD5": "0de01f8f6d037e9ebecde2f91ad9b7a3",
"Name": "recording_83622325727_d831fbd5-3938-44d0-b30b-962bf76e2916.MP4",
"SHA1": "c81f9abb6dcf9be42dae99bc5e1501c43496d66e",
"SHA256": "8b252b01c8e6af62b88de64abf80d360467da1598dcd6b50ac9a252ffafb2eb5",
"SHA512": "b273e90a9cd0589eaba1c5e647fedab7b46e198193a54bec70a18def9ada57575833ea89b6eabf7f5852c3dc98b862780793d3e87e32a238ec2a7acffdba2495",
"SSDeep": "1536:TDWnSNbM8oEWzjSn7anYBcoGdee32hfUunvSHx8:T6t8JWzjSWnYBcoG9325UunvSHq",
"Size": 320333,
"Type": "ISO Media, MP4 v2 [ISO 14496-14]"
},
{
"EntryID": "447@37e93103-1bd6-4776-8021-0f7023b1bb79",
"Extension": "M4A",
"Info": "video/mp4",
"MD5": "e826111564499ca8021d0ddfcfde064b",
"Name": "recording_83622325727_19bf5f8a-e77c-4b75-b09e-13983521703c.M4A",
"SHA1": "50d3386dc5b74935b8f8d541f319df34a49f90a0",
"SHA256": "2719528cf61358ccbee861fb8e42d9d5fb37390baa22d0dc7dad1aa7e3935146",
"SHA512": "74bfb40ade824e6e36329b3e2335b2028fac648d3ecef1a02e9be93d4a455e3acf4c1f9c844d1c2ebcc661d4c84d66c1da4f0ca0462eabc12bf2dff84006d460",
"SSDeep": "24:fctSXvr4S+08n11/TlllZltk2B0tDilduxEJvCXyxrApd4dEcpXuFxnZQ4r:uYr41Xnf/T/vX/8OvqyrjiCuFhZQK",
"Size": 243652,
"Type": "ISO Media, MP4 v2 [ISO 14496-14]"
}
]
}
Human Readable Output
The Audio file recording_83622325727_19bf5f8a-e77c-4b75-b09e-13983521703c.M4A was downloaded successfully
zoom-list-users
List the existing users
Base Command
zoom-list-users
Input
| Argument Name | Description | Required |
|---|---|---|
| status | Which status of users to list. Possible values are: active, inactive, pending. Default is active. | Optional |
| page-size | Number of users to return. Max 300. The default is 30. | Optional |
| next_page_token | The next page token is used to get the next page. IMPORTANT: You must pass the same page size that you passed in the first call. | Optional |
| page-number | Which page of results to return. The default = 1. Note: This argument is in a deprecate process by the API. As an alternative use “next_page_token” or “limit”.. | Optional |
| limit | The total amunt of results to show. | Optional |
| user_id | A user ID. this is for a singel user. | Optional |
| role_id | Filter the response by a specific role. For example: role_id=0 (Owner), role_id=2 (Member). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Metadata.Count | number | Total page count available |
| Zoom.Metadata.Number | number | Current page number |
| Zoom.Metadata.Size | number | Number of results in current page |
| Zoom.Metadata.Total | number | Total number of records |
| Zoom.User.id | string | ID of the user |
| Zoom.User.first_name | string | First name of user |
| Zoom.User.last_name | string | Last name of user |
| Zoom.User.email | string | Email of user |
| Zoom.User.type | number | Type of user |
| Zoom.User.created_at | date | Date when user was created |
| Zoom.User.dept | string | Department for user |
| Zoom.User.verified | number | Is the user verified |
| Zoom.User.last_login_time | date | Last login time of the user |
| Zoom.User.timezone | string | Default timezone for the user |
| Zoom.User.pmi | string | PMI of user |
| Zoom.User.group_ids | string | Groups user belongs to |
Command example
!zoom-list-users status=pending limit=10
Context Example
{
"Zoom": {
"Metadata": {
"Count": 6,
"Number": 1,
"Size": 10,
"Total": 59
},
"User": [
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T12:55:33Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T13:09:28Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2022-12-22T10:19:47Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T13:12:46Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T12:04:08Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T12:56:08Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T12:58:16Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T13:15:04Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T11:58:04Z",
"verified": 0
},
{
"created_at": "2023-01-15T12:44:34Z",
"email": "example@example.com",
"id": "",
"pmi": 0,
"role_id": "0",
"status": "pending",
"type": 1,
"user_created_at": "2023-01-02T13:09:52Z",
"verified": 0
}
]
}
}
Human Readable Output
Users
id type pmi verified created_at status role_id example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0 Metadata
total_records 59
zoom-delete-user
Delete a user from Zoom
Base Command
zoom-delete-user
Input
| Argument Name | Description | Required |
|---|---|---|
| user | The user ID or email to delete. | Required |
| action | The action to take. Possible values are: disassociate, delete. Default is disassociate. | Optional |
Context Output
There is no context output for this command.
zoom-meeting-get
Get the information of an existing zoom meeting
Base Command
zoom-meeting-get
Input
| Argument Name | Description | Required |
|---|---|---|
| meeting_id | The id of the existing meeting. | Required |
| occurrence_id | Provide this field to view meeting details of a particular occurrence of the recurring meeting. | Optional |
| show_previous_occurrences | Set the value of this field to true if you would like to view meeting details of all previous occurrences of a recurring meeting. Possible values are: false, true. Default is True. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Meeting.join_url | string | Join url for the meeting |
| Zoom.Meeting.id | string | Meeting id of the new meeting that is created |
| Zoom.Meeting.start_url | string | The URL to start the meeting |
| Zoom.Meeting.uuid | string | Unique meeting ID of the new meeting that is created |
| Zoom.Meeting.status | string | The status of the meeting |
| Zoom.Meeting.start_time | Date | The time that the meeting will start at |
| Zoom.Meeting.host email | string | The email of the host of this meeting |
| Zoom.Meeting.topic | string | The topic of the meeting |
| Zoom.Meeting.duration | number | The duratian of the meeting |
| Zoom.Meeting.created_at | Date | The time that this meeting was created |
| Zoom.Meeting.type | number | The type of the new meeting, Instant = 1, Scheduled =2,Recurring with fixed time = 8 |
Command example
!zoom-meeting-get meeting_id=88949894296
Context Example
{
"Zoom": {
"Meeting": {
"agenda": "",
"assistant_id": "",
"created_at": "2022-12-29T08:10:13Z",
"duration": 60,
"host_email": "example@example.com",
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 88949894296,
"join_url": "https://us06web.zoom.us/94296?pwd=b3GdrSDBBNU1FYTVRVmdadz09",
"pre_schedule": false,
"settings": {
"allow_multiple_devices": false,
"alternative_host_update_polls": false,
"alternative_hosts": "",
"alternative_hosts_email_notification": true,
"approval_type": 2,
"approved_or_denied_countries_or_regions": {
"enable": false
},
"audio": "both",
"auto_recording": "none",
"breakout_room": {
"enable": false
},
"close_registration": false,
"cn_meeting": false,
"device_testing": false,
"email_notification": true,
"enable_dedicated_group_chat": false,
"encryption_type": "enhanced_encryption",
"enforce_login": false,
"enforce_login_domains": "",
"focus_mode": false,
"global_dial_in_countries": [
"US"
],
"global_dial_in_numbers": [
{
"country": "US",
"country_name": "US",
"number": "+1 6469313860",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 6694449171",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 6892781000",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 7193594580",
"type": "toll"
},
{
"city": "Denver",
"country": "US",
"country_name": "US",
"number": "+1 7207072699",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 2532050468",
"type": "toll"
},
{
"city": "Tacoma",
"country": "US",
"country_name": "US",
"number": "+1 2532158782",
"type": "toll"
},
{
"city": "Washington DC",
"country": "US",
"country_name": "US",
"number": "+1 3017158592",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3052241968",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3092053325",
"type": "toll"
},
{
"city": "US",
"country": "US",
"country_name": "US",
"number": "+1 3126266799",
"type": "toll"
},
{
"city": "Houston",
"country": "US",
"country_name": "US",
"number": "+1 3462487799",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3602095623",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 3863475053",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 5074734847",
"type": "toll"
},
{
"country": "US",
"country_name": "US",
"number": "+1 5642172000",
"type": "toll"
},
{
"city": "New York",
"country": "US",
"country_name": "US",
"number": "+1 6465588656",
"type": "toll"
}
],
"host_save_video_order": false,
"host_video": true,
"in_meeting": false,
"jbh_time": 0,
"join_before_host": false,
"meeting_authentication": false,
"mute_upon_entry": false,
"participant_video": false,
"private_meeting": false,
"registrants_confirmation_email": true,
"registrants_email_notification": true,
"request_permission_to_unmute_participants": false,
"show_share_button": false,
"use_pmi": false,
"waiting_room": false,
"watermark": false
},
"start_time": "2022-12-29T12:12:12Z",
"start_url": "https://us06web.zoom.us/s/88949?zak=eyJ0eXAiOiJKV1QiLCJzdiI6IjAwMDAwMSIsInptX3NrbSI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4OTQ5ODk0Mjk2IiwiZXhwIjoxNjczNzkzODc2LCJpYXQiOjE2NzM3ODY2NzYsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.BTOeH_-MZRm7A5sACnDJrP_zKbzaDCWZ5orvtH4rVb0",
"status": "waiting",
"timezone": "Asia/Jerusalem",
"topic": "test",
"type": 2,
"uuid": "anhEx2x6QWG7TREn71MmoA=="
}
}
}
Human Readable Output
Meeting details
uuid id host_id host_email topic type status start_time duration timezone agenda created_at start_url join_url anhEx2x6QWG7TREn71MmoA== 88949894296 uJiZN-O7Rp6Jp_995FpZGg example@example.com test 2 waiting 2022-12-29T12:12:12Z 60 Asia/Jerusalem 2022-12-29T08:10:13Z https://us06web.zoom.us/s/88949894296?zak=eyJ0eXAiOiJKV1QiLCJzdiI6IjAwMDAwMSIsInptX3NrbSI6InptX28ybSIsImFsZyI6IkhTMjU2In0.eyJhdWQiOiJjbGllbnRzbSIsInVpZCI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4OTQ5ODk0Mjk2IiwiZXhwIjoxNjczNzkzODc2LCJpYXQiOjE2NzM3ODY2NzYsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.BTOeH_-MZRm7A5sACnDJrP_zKbzaDCWZ5orvtH4rVb0 https://us06web.zoom.us/j/88949894296?pwd=b3dzT1pzWGdrSDBBNU1FYTVRVmdadz09
zoom-meeting-list
Show all the meetings of a given user. Note: only scheduled and unexpired meetings will appear.
Base Command
zoom-meeting-list
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | The user ID of the meetings owner. | Required |
| page_size | Number of users to return. Default = 30. Max = 300. | Optional |
| page_number | Which page of results to return. The default = 1. Note: This argument is in a deprecate process by the API. As an alternative use “next_page_token” or “limit”. | Optional |
| next_page_token | The next page token is used to paginate te the next page. IMPORTENT: You must pass the same page size that you pased at the first call.. | Optional |
| limit | The total amunt of results to show. | Optional |
| type | Filter the results by searching specific types. Possible values are: all, scheduled, live, upcoming, upcoming_meetings, previous_meetings. Default is “scheduled”. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Metadata.Total | number | Total number of records |
| Zoom.Meeting.page_size | number | The size of the page returned from the API |
| Zoom.Meeting.total_records | number | The total records in the API for this request. |
| Zoom.Meeting.join_url | string | Join url for the meeting |
| Zoom.Meeting.id | string | Meeting id of the new meeting that is created |
| Zoom.Meeting.start_url | string | The URL to start the meeting |
| Zoom.Meeting.uuid | string | Unique meeting ID of the new meeting that is created |
| Zoom.Meeting.status | string | The status of the meeting |
| Zoom.Meeting.start_time | Date | The time that the meeting will start at |
| Zoom.Meeting.host email | string | The email of the host of this meeting |
| Zoom.Meeting.topic | string | The topic of the meeting |
| Zoom.Meeting.duration | number | The duratian of the meeting |
| Zoom.Meeting.created_at | Date | The time that this meeting was created |
| Zoom.Meeting.type | unknown | The ty pe of this meeting |
Command example
!zoom-meeting-list user_id=example@example.com type=scheduled limit=7
Context Example
{
"Zoom": {
"Meeting": {
"meetings": [
{
"created_at": "2022-12-04T10:41:27Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 83810397585,
"join_url": "https://us06web.zoom.us/j/83810397585?pwd=OGFiZjVvMWZzdDBoaXlLdz09",
"start_time": "2022-12-10T11:00:00Z",
"timezone": "Asia/Jerusalem",
"topic": "2",
"type": 8,
"uuid": "z93Dc6Kj3jx+zaYg=="
},
{
"created_at": "2022-12-06T07:59:02Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 84540166459,
"join_url": "https://us06web.zoom.us/j/84540166459?pwd=ZzZaaVpFYlBVYnFoUT09",
"start_time": "2022-12-12T08:00:00Z",
"timezone": "Asia/Jerusalem",
"topic": "My recurring Meeting -Dima",
"type": 8,
"uuid": "4kZQ+HlFOAz0VBPHoCYg=="
},
{
"created_at": "2022-12-27T21:05:41Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 89824497327,
"join_url": "https://us06web.zoom.us/j/89824497327?pwd=SWp3b3VDRVhmQT09",
"start_time": "2022-12-27T21:05:00Z",
"timezone": "Asia/Jerusalem",
"topic": "efe",
"type": 8,
"uuid": "RABXy2D4hA1rgpDgQ=="
},
{
"created_at": "2022-12-27T21:11:01Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 83245658341,
"join_url": "https://us06web.zoom.us/j/83245658341?pwd=SmNGMHI0RDNkZ2Yms3Zz09",
"start_time": "2022-12-27T21:11:00Z",
"timezone": "Asia/Jerusalem",
"topic": "efe",
"type": 8,
"uuid": "qOXvloSamJjjFaFgniTA=="
},
{
"created_at": "2022-12-27T21:25:54Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 88468901206,
"join_url": "https://us06web.zoom.us/j/88468901206?pwd=RXZYQlWCtpS3l1MHUxZz09",
"start_time": "2022-12-27T21:25:00Z",
"timezone": "Asia/Jerusalem",
"topic": "efe",
"type": 8,
"uuid": "yHzCvl4Sry+C9LnCwdnwQ=="
},
{
"created_at": "2022-12-28T06:39:48Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 87525048161,
"join_url": "https://us06web.zoom.us/j/87525048161?pwd=ZXlV3U0OUxxSlBkdz09",
"start_time": "2022-12-28T06:39:00Z",
"timezone": "Asia/Jerusalem",
"topic": "efe",
"type": 8,
"uuid": "Sblh/S1W+rTKUcojJjw=="
},
{
"created_at": "2022-12-28T06:42:25Z",
"duration": 60,
"host_id": "uJiZN-O7Rp6Jp_995FpZGg",
"id": 83877839723,
"join_url": "https://us06web.zoom.us/j/83877839723?pwd=WySkY4Zkc4Zz09",
"start_time": "2022-12-28T06:42:00Z",
"timezone": "Asia/Jerusalem",
"topic": "efe",
"type": 8,
"uuid": "iLXDe4HsR6uMb+x8GyybTA=="
}
],
"next_page_token": "N58N4bhqiBFapzndJocx6cc8NKr2",
"page_size": 7,
"total_records": 60
},
"Metadata": {
"Size": 7,
"Total": 60
}
}
}
Human Readable Output
Meeting list
uuid id host_id topic type start time duration timezone created_at join_url z93Dc6KjSo20Wr3jx+zaYg== 83810397585 uJiZN-O7Rp6Jp_995FpZGg 2 8 60 Asia/Jerusalem 2022-12-04T10:41:27Z https://us06web.zoom.us/j/83810397585?pwd=OGFiZjRYNGhwWkVvMWZzdDBoaXlLdz09 4kZQ+Hl2RFOAz0VBPHoCYg== 84540166459 uJiZN-O7Rp6Jp_995FpZGg My recurring Meeting -Dima 8 60 Asia/Jerusalem 2022-12-06T07:59:02Z https://us06web.zoom.us/j/84540166459?pwd=ZzdmUEJ5QkZaaUZaaVpFYlBVYnFoUT09 RABXyk81T02D4hA1rgpDgQ== 89824497327 uJiZN-O7Rp6Jp_995FpZGg efe 8 60 Asia/Jerusalem 2022-12-27T21:05:41Z https://us06web.zoom.us/j/89824497327?pwd=SWpvK0I0L3pQcTNnWlF3b3VDRVhmQT09 qOXvlLOoSamJjjFaFgniTA== 83245658341 uJiZN-O7Rp6Jp_995FpZGg efe 8 60 Asia/Jerusalem 2022-12-27T21:11:01Z https://us06web.zoom.us/j/83245658341?pwd=SmNGMHI0R1hndnNlRXRDNkZ2Yms3Zz09 yHzCvl4USry+C9LnCwdnwQ== 88468901206 uJiZN-O7Rp6Jp_995FpZGg efe 8 60 Asia/Jerusalem 2022-12-27T21:25:54Z https://us06web.zoom.us/j/88468901206?pwd=RXZYQlhVbWJKZ1pLWCtpS3l1MHUxZz09 Sblh/I34S1W+rTKUcojJjw== 87525048161 uJiZN-O7Rp6Jp_995FpZGg efe 8 60 Asia/Jerusalem 2022-12-28T06:39:48Z https://us06web.zoom.us/j/87525048161?pwd=ZXlXdXl0QWlLOFVyV3U0OUxxSlBkdz09 iLXDe4HsR6uMb+x8GyybTA== 83877839723 uJiZN-O7Rp6Jp_995FpZGg efe 8 60 Asia/Jerusalem 2022-12-28T06:42:25Z https://us06web.zoom.us/j/83877839723?pwd=WU9xNmp5RW5KRDhsZ1RySkY4Zkc4Zz09 Metadata
total_records 60
Command example
#### Context Example
```json
{
"Zoom": {
"Channel": {
"channels": [
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"id": "f7ce414a24634240ae0a7894823d8707",
"jid": "f7ce414a24634240ae0a7894823d8707@conference.xmpp.zoom.us",
"name": "Channel1",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"id": "e82e99ac9b0c40b08449c76766cf398d",
"jid": "e82e99ac9b0c40b08449c76766cf398d@conference.xmpp.zoom.us",
"name": "Channel2",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": false,
"posting_permissions": 1
},
"id": "e7e2c5e1ba854056906af1c9dc36148f",
"jid": "e7e2c5e1ba854056906af1c9dc36148f@conference.xmpp.zoom.us",
"name": "Channel3",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 2,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"id": "e6388c9667c245c3844009ae995664d5",
"jid": "e6388c9667c245c3844009ae995664d5@conference.xmpp.zoom.us",
"name": "Channel4",
"type": 3
}
],
"next_page_token": "",
"page_size": 20,
"total_records": 4
},
"ChannelsNextToken": ""
}
}
Human Readable Output
Channels
Channel ID Channel JID Channel name Channel type f7ce414a24634240ae0a7894823d8707 f7ce414a24634240ae0a7894823d8707@conference.xmpp.zoom.us Channel1 3 e82e99ac9b0c40b08449c76766cf398d e82e99ac9b0c40b08449c76766cf398d@conference.xmpp.zoom.us Channel2 3 e7e2c5e1ba854056906af1c9dc36148f e7e2c5e1ba854056906af1c9dc36148f@conference.xmpp.zoom.us channel3 3 e6388c9667c245c3844009ae995664d5 e6388c9667c245c3844009ae995664d5@conference.xmpp.zoom.us Channel4 3
zoom-list-user-channels
List the existing channels
Base Command
zoom-list-user-channels
Input
| Argument Name | Description | Required |
|---|---|---|
| page-size | Number of channels to return. Max 300. The default is 50. | Optional |
| next_page_token | The next page token is used to get the next page. IMPORTANT: You must pass the same page size that you passed in the first call. | Optional |
| page-number | Which page of results to return. The default = 1. Note: This argument is in a deprecate process by the API. As an alternative use “next_page_token” or “limit”. | Optional |
| limit | The total amunt of results to show. | Optional |
| channel_id | A channel ID. This is for a single channel. | Optional |
| user_id | A user ID. This is for a single user. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Channel.id | string | The ID of the created channel. |
| Zoom.Channel.name | string | The name of the created channel. |
| Zoom.Channel.type | string | The created channel type. |
| Zoom.Channel.url | string | The created channel URL. |
Command example
!zoom-list-user-channels user_id=uJiZN-O7Rp6Jp_995FpZGg channel_id=88f2f20f4abd415cba2429538be58025
Context Example
{
"Zoom": {
"Channel": {
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI4OGYyZjIwZjRhYmQ0MTVjYmEyNDI5NTM4YmU1ODAyNUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "88f2f20f4abd415cba2429538be58025",
"jid": "88f2f20f4abd415cba2429538be58025@conference.xmpp.zoom.us",
"name": "Channel-Updated5",
"type": 3
},
"UserChannelsNextToken": null
}
}
Human Readable Output
Channels
Channel ID Channel name Channel type Channel url User id channel JID 88f2f20f4abd415cba2429538be58025 Channel-Updated5 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI4OGYyZjIwZjRhYmQ0MTVjYmEyNDI5NTM4YmU1ODAyNUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 88f2f20f4abd415cba2429538be58025@conference.xmpp.zoom.us
Command example
!zoom-list-user-channels user_id=uJiZN-O7Rp6Jp_995FpZGg
Context Example
{
"Zoom": {
"Channel": {
"channels": [
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": false,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJlN2UyYzVlMWJhODU0MDU2OTA2YWYxYzlkYzM2MTQ4ZkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "e7e2c5e1ba854056906af1c9dc36148f",
"jid": "e7e2c5e1ba854056906af1c9dc36148f@conference.xmpp.zoom.us",
"name": "TestChannel1",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI3ODI4YTFiMjgzYmQ0MjYxOTkwOTRlNWVhMGFhOTM1M0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "7828a1b283bd426199094e5ea0aa9353",
"jid": "7828a1b283bd426199094e5ea0aa9353@conference.xmpp.zoom.us",
"name": "Channel",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIwOGE0OWVmY2I5YTA0N2MzYmU5NWMwNDc4NzI1NjJjZkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "08a49efcb9a047c3be95c047872562cf",
"jid": "08a49efcb9a047c3be95c047872562cf@conference.xmpp.zoom.us",
"name": "DemoChannel-Updated",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": false,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI5MmIwMjY4YWFmOGQ0MDM5OTQ4YjE3ZDc4M2IwODE5OEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "92b0268aaf8d4039948b17d783b08198",
"jid": "92b0268aaf8d4039948b17d783b08198@conference.xmpp.zoom.us",
"name": "TestGroupChannel1",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIzZDRjZjFiNDkzNDk0NGFkODM5YzEwOWJhYWM5MzEyNkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "3d4cf1b4934944ad839c109baac93126",
"jid": "3d4cf1b4934944ad839c109baac93126@conference.xmpp.zoom.us",
"name": "Admins1",
"type": 2
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJlODJlOTlhYzliMGM0MGIwODQ0OWM3Njc2NmNmMzk4ZEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "e82e99ac9b0c40b08449c76766cf398d",
"jid": "e82e99ac9b0c40b08449c76766cf398d@conference.xmpp.zoom.us",
"name": "Admins_to_delete_2",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIwZWJlNzEwMDNlYjI0ZjVmODU3N2U1YTEyNGYwNjQyOEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "0ebe71003eb24f5f8577e5a124f06428",
"jid": "0ebe71003eb24f5f8577e5a124f06428@conference.xmpp.zoom.us",
"name": "Admins_to_delete_2_updated",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 1,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIyZTk5YTdlMDdkZTA0ZjUyYmYyYzQ0OGNkMmIxNTFmY0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "2e99a7e07de04f52bf2c448cd2b151fc",
"jid": "2e99a7e07de04f52bf2c448cd2b151fc@conference.xmpp.zoom.us",
"name": "BotChannel",
"type": 5
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "b18d15140c254549a80af6572b3b552e",
"jid": "b18d15140c254549a80af6572b3b552e@conference.xmpp.zoom.us",
"name": "ChannelName",
"type": 3
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIzNjQxYzNmZGMxZGM0Zjc4OGU4ZWIzNDA3YTQwYzQ3MkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "3641c3fdc1dc4f788e8eb3407a40c472",
"jid": "3641c3fdc1dc4f788e8eb3407a40c472@conference.xmpp.zoom.us",
"name": "Admins",
"type": 2
},
{
"channel_settings": {
"add_member_permissions": 1,
"allow_to_add_external_users": 0,
"mention_all_permissions": 1,
"new_members_can_see_previous_messages_files": true,
"posting_permissions": 1
},
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJmN2NlNDE0YTI0NjM0MjQwYWUwYTc4OTQ4MjNkODcwN0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "f7ce414a24634240ae0a7894823d8707",
"jid": "f7ce414a24634240ae0a7894823d8707@conference.xmpp.zoom.us",
"name": "TestChannel3",
"type": 3
}
],
"next_page_token": "",
"page_size": 50,
"total_records": 11
},
"UserChannelsNextToken": ""
}
}
Human Readable Output
Channels
zoom-create-channel
Creates a channel for a user
Base Command
zoom-create-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | The user’s unique identifier. | Required |
| member_emails | The member(s) to include in the channel. A maximum of 20 members can be added to the channel at once with this API. | Required |
| add_member_permissions | Who can add new channel members: 1 - All channel members can add new members. 2 - Only channel owner and administrators can add new members. Note: This setting can only be modified by the channel owner. Default: 1. | |
| posting_permissions | The channel members’ posting permissions: 1 — All chat channel members can post to the channel. 2 — Only the channel owner and administrators can post to the channel. * 3 — Only the channel owner, administrators and certain members can post to the channel. Default: 1. | Optional |
| new_members_can_see_prev_msgs | Whether new channel members can view messages and files previously posted in the channel. Possible values are: true, false. Default is True. | Optional |
| channel_name | The name of the channel. Maximum of 128 characters. | Required |
| channel_type | The type of the channel. The value can be one of the following: 1: Private channel. In this type of channel, members must be invited to join a channel. 2: Private channel with members that belong to one Zoom account. Members in this channel should be invited and the members should be from the same organization. 3: Public channel. Anyone can search for this channel and join the channel. 4: New chat. This is an instant channel which can be created by adding members to a new chat. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Channel.id | string | the channel’s unique identifier. |
| Zoom.Channel.jid | string | The channel JID. |
| Zoom.Channel.name | string | The channel name. |
| Zoom.Channel.type | string | The type of the channel. The value can be one of the following: 1: Private channel. In this type of channel, members must be invited to join a channel. 2: Private channel with members that belong to one Zoom account. Members in this channel should be invited and the members should be from the same organization. 3: Public channel. Anyone can search for this channel and join the channel. 4: Group chat. This is an instant channel which can be created by adding members to a new chat. |
| Zoom.Channel.url | string | The URL of the Zoom chat channel. |
Command example
!zoom-create-channel user_id=uJiZN-O7Rp6Jp_995FpZGg member_emails=example@example.com channel_name=ChannelName channel_type="Public channel"
Context Example
{
"Zoom": {
"Channel": {
"channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
"id": "b18d15140c254549a80af6572b3b552e",
"jid": "b18d15140c254549a80af6572b3b552e@conference.xmpp.zoom.us",
"name": "ChannelName",
"type": 3
}
}
}
Human Readable Output
Channel details
Channel ID Channel name Channel type Channel url User id b18d15140c254549a80af6572b3b552e ChannelName 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg
zoom-delete-channel
Deletes a specific Zoom channel
Base Command
zoom-delete-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| channel_id | Unique identifier of a channel. | Required |
| user_id | User unique identifier. | Required |
Context Output
There is no context output for this command.
Command example
!zoom-delete-channel user_id=uJiZN-O7Rp6Jp_995FpZGg channel_id=88f2f20f4abd415cba2429538be58025
Human Readable Output
Channel 88f2f20f4abd415cba2429538be58025 was deleted successfully
zoom-update-channel
Update an existing channel in a Zoom account.
Base Command
zoom-update-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| channel_id | The channel ID. | Required |
| user_id | User unique identifier. | Required |
| add_member_permissions | Who can add new channel members: 1 - All channel members can add new members. 2 - Only channel owner and administrators can add new members. Note: This setting can only be modified by the channel owner. | Optional |
| posting_permissions | The channel members’ posting permissions: 1 — All chat channel members can post to the channel. 2 — Only the channel owner and administrators can post to the channel. * 3 — Only the channel owner, administrators and certain members can post to the channel. | Optional |
| new_members_can_see_prev_msgs | Whether new channel members can view messages and files previously posted in the channel. Possible values are: true, false. Default is True. | Optional |
| channel_name | A new name for the channel. | Optional |
Context Output
There is no context output for this command.
Command example
!zoom-update-channel user_id=uJiZN-O7Rp6Jp_995FpZGg channel_name=Channel-Updated5 channel_id=88f2f20f4abd415cba2429538be58025
Human Readable Output
Channel 88f2f20f4abd415cba2429538be58025 was updated successfully
zoom-invite-to-channel
Invites members that are in a user’s contact list to a channel. A channel can have one or multiple members. The maximum number of members that can be added at once with this API is 5.
Base Command
zoom-invite-to-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| channel_id | The channel’s unique identifier. | Required |
| user_id | User unique identifier. | Required |
| members | The member’s email address. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.Channel.ids | string | A comma-separated list of user IDs of the members added to the channel. User IDs of those who are not from the same account will be omitted from the list. |
| Zoom.Channel.added_at | string | The date and time when the members are added to the channel. |
| Zoom.Channel.member_ids | string | A comma-separated list of member IDs of the members added to the channel. |
Command example
!zoom-invite-to-channel user_id=uJiZN-O7Rp6Jp_995FpZGg members=example@example.com channel_id=88f2f20f4abd415cba2429538be58025
Context Example
{
"Zoom": {
"Channel": {
"added_at": "2023-05-22T08:36:57Z",
"ids": "pq0t1uvlrqmi_p_-cg2ugq",
"member_ids": "1vqMC-BQdfok1tpAnSw8OT6FtcMiXBaUPNoRhTIzcvJjtbxgPXQRLmDm-10C2Ggg"
}
}
}
Human Readable Output
Channel details
Added at date and time Channel ID User id 2023-05-22T08:36:57Z 88f2f20f4abd415cba2429538be58025 pq0t1uvlrqmi_p_-cg2ugq
zoom-remove-from-channel
Removes a member from a chat channel. A channel can have one or more members.
Base Command
zoom-remove-from-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| channel_id | The unique identifier of the channel from where you would like to remove a member. | Required |
| user_id | User unique identifier. | Required |
| member_id | The email address or user ID or member ID of the member to remove from the channel. | Required |
Context Output
There is no context output for this command.
Command example
!zoom-remove-from-channel user_id=uJiZN-O7Rp6Jp_995FpZGg member_id=example@example.com channel_id=88f2f20f4abd415cba2429538be58025
Human Readable Output
Member example@example.com was successfully removed from channel 88f2f20f4abd415cba2429538be58025
zoom-send-file
Sends a file on Zoom to either an individual user in your contact list or a channel of which you are a member.
Base Command
zoom-send-file
Input
| Argument Name | Description | Required |
|---|---|---|
| to_channel | The channel ID of the channel to which to send the chat file. | Optional |
| user_id | The user’s ID. | Required |
| to_contact | The user ID or member ID of the contact to send the chat file. | Optional |
| entry_id | Cortex XSOAR internal file ID. | Required |
Context Output
There is no context output for this command.
zoom-send-message
Sends chat messages on Zoom to either an individual user who is in your contact list or to a channel of which you are a member.
Base Command
zoom-send-message
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | Unique identifier of the user. | Required |
| at_contact | Email address of the mention contact. | Optional |
| is_markdown | if a markdown message provide in the message argument | Optional |
| message | The message to be sent. Maximum of 1024 characters. | Required |
| entry_ids | A list of the file IDs to send. This field only accepts a maximum of six file IDs. | Optional |
| reply_main_message_id | The reply message’s ID. This field only returns if the message is a reply message. | Optional |
| to_channel | The channel ID of the channel to send a message. | Optional |
| to_contact | The email address or user ID or member ID of the person to send a message. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.ChatMessage.id | number | Unique identifier of the message. |
Command example
!zoom-send-message user_id=uJiZN-O7Rp6Jp_995FpZGg message="message" to_contact=example@example.com
Context Example
{
"Zoom": {
"ChatMessage": {
"id": "7df8cc5b-efc4-4e08-9083-9823b8871c82"
}
}
}
Human Readable Output
Message
Contact Message ID example@example.com 7df8cc5b-efc4-4e08-9083-9823b8871c82
zoom-delete-message
Deletes a chat message previously sent to a contact or a channel.
Base Command
zoom-delete-message
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | Unique identifier of the user. | Required |
| message_id | Unique identifier of the message. | Required |
| to_channel | The channel ID where the message was sent. You must provide this parameter or the to_contact parameter. | Optional |
| to_contact | The member ID or user ID or email address of a chat contact to whom the message was sent. You must provide this parameter or the to_channel parameter. | Optional |
Context Output
There is no context output for this command.
Command example
!zoom-delete-message user_id=uJiZN-O7Rp6Jp_995FpZGg to_contact=example@example.com message_id=4a59df4a-9668-46bd-bff2-3e1f3462ecc3
Human Readable Output
Message 4a59df4a-9668-46bd-bff2-3e1f3462ecc3 was deleted successfully
zoom-update-message
Edits a chat message that you previously sent to either a contact or a channel in Zoom by providing the ID of the message as the value of the messageId parameter. As a query parameter, you must provide either the contact’s email address or the Channel ID of the channel where the message was sent.
Base Command
zoom-update-message
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | Unique identifier of the user. | Required |
| message_id | Unique identifier of the message. | Required |
| message | The edited message. | Required |
| to_channel | The channel ID of the channel where you sent the message. You must provide either to_contact or to_channel parameter in the API request. Channel ID can be retrieved from List User’s Channels API. | Optional |
| to_contact | The email address or user ID or member ID of the contact to whom the message was sent. You must provide either this parameter or the to_channel parameter in the API request. | Optional |
| entry_ids | A list of Cortex XSOAR file entry IDs to send. | Optional |
Context Output
There is no context output for this command.
Command example
!zoom-update-message user_id=uJiZN-O7Rp6Jp_995FpZGg message="message2" to_contact=example@example.com message_id=4a59df4a-9668-46bd-bff2-3e1f3462ecc3
Human Readable Output
Message 4a59df4a-9668-46bd-bff2-3e1f3462ecc3 was successfully updated
zoom-list-messages
Searches chat messages or shared files between a user and an individual contact or a chat channel.
Base Command
zoom-list-messages
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | Unique identifier of the user. | Required |
| to_contact | This field allows you to query by the email address or user ID or member ID of a chat contact with whom the user communicated. The API only returns messages sent and/or received between the user and the queried contact. | Optional |
| to_channel | This field queries by the channel ID of a channel in which the user had chat conversations. The API only returns messages sent and/or received by the user in the queried channel. | Optional |
| date | The query date from which to retrieve the chat messages. This value defaults to the current date. Format %Y-%m-%dT%H:%M:%S.. | Optional |
| from | Start date. Format %Y-%m-%dT%H:%M:%S. | Optional |
| to | End date. Format %Y-%m-%dT%H:%M:%S. | Optional |
| include_deleted_and_edited_message | Whether to include deleted and edited messages. Default false. | Optional |
| search_type | The type of search: message — Search messages. file — Search files.. Possible values are: message, file. | Optional |
| search_key | Key for search in messages. | Optional |
| exclude_child_message | Whether to exclude returning all child messages in a chat, leaving only the parent messages. Default: false. | Optional |
| next_page_token | The next page token paginates through a large set of results. A next page token is returned whenever the set of available results exceeds the current page size. This token’s expiration period is 15 minutes. | Optional |
| page_size | Number of records returned from a single API call. Default 50. | Optional |
| page_number | The page of results to return. Default 1. | Optional |
| limit | Total amount of results to show. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Zoom.ChatMessage.date | date | The queried date value. |
| Zoom.ChatMessage.id | string | The channel’s unique identifier. |
| Zoom.Channel.jid | string | The channel JID. |
| Zoom.Channel.name | string | The channel name. |
| Zoom.Channel.type | string | The type of the channel. The value can be one of the following: 1: Private channel. In this type of channel, members must be invited to join a channel. 2: Private channel with members that belong to one Zoom account. Members in this channel should be invited and the members should be from the same organization. 3: Public channel. Anyone can search for this channel and join the channel. 4: Group chat. This is an instant channel which can be created by adding members to a new chat. |
| Zoom.ChatMessage.date | date | The queried date value. |
| Zoom.ChatMessage.from | date-time | The queried from value. (Returned only if the from query parameter is used) |
| Zoom.ChatMessage.messages | array of object | Information about received messages and files. |
| Zoom.ChatMessage.messages.bot_message | object | The chatbot’s message in JSON format. |
| Zoom.ChatMessage.messages.bot_message.date_time | date-time | The date and time when the message was sent. |
| Zoom.ChatMessage.messages.files | array of object | Information about chat files (if multiple files exist). |
| Zoom.ChatMessage.messages.files.download_url | string | The download URL of the chat file. |
| Zoom.ChatMessage.messages.files.file_id | string | The unique ID of the chat file. |
| Zoom.ChatMessage.messages.files.file_name | string | The name and file extension of the chat file. |
| Zoom.ChatMessage.messages.files.file_size | integer | The size of the chat file in bytes. |
| Zoom.ChatMessage.messages.rich_text | array of object | Rich text formatting information. |
| Zoom.ChatMessage.messages.rich_text.start_position | integer | The start position of the rich text in the message string. |
| Zoom.ChatMessage.messages.rich_text.end_position | integer | The end position of the rich text. |
| Zoom.ChatMessage.messages.rich_text.format_type | enum | The type of rich text format. |
| Zoom.ChatMessage.messages.rich_text.format_attr | string | The attribute values of a specific format_type. |
| Zoom.ChatMessage.messages.rich_text.download_url | string | The download URL of the first file. |
| Zoom.ChatMessage.messages.rich_text.file_id | string | The unique ID of the first file. |
| Zoom.ChatMessage.messages.rich_text.file_name | string | The name of the first file. |
| Zoom.ChatMessage.messages.rich_text.file_size | integer | The size of the first file in bytes. |
| Zoom.ChatMessage.messages.id | string | Unique identifier of the message. |
| Zoom.ChatMessage.messages.message | string | The message content. |
| Zoom.ChatMessage.messages.reply_main_message_id | string | The unique identifier of a reply message. (Returned only for reply messages) |
| Zoom.ChatMessage.messages.reply_main_message_timestamp | integer | The timestamp of when the reply message was sent. (Returned only for reply messages) |
| Zoom.ChatMessage.messages.sender | string | The email address of the message sender. Empty if the sender does not belong to the same account as the current user or is not a contact. |
| Zoom.ChatMessage.messages.sender_member_id | string | The member ID of the message sender. |
| Zoom.ChatMessage.messages.sender_display_name | string | The display name of the message sender. |
| Zoom.ChatMessage.messages.status | enum | Indicates the status of the message. Allowed values Deleted, Edited, Normal. (Returned only when include_deleted_and_edited_message query parameter is set to true) |
| Zoom.ChatMessage.messages.timestamp | integer | The timestamp of the message in microseconds. |
| Zoom.ChatMessage.at_items | array of object | Information about mentions. |
| Zoom.ChatMessage.at_items.at_contact | string | The user ID of the mentioned contact. Empty if the contact does not belong to the same account as the current user. |
| Zoom.ChatMessage.at_items.at_contact_member_id | string | The member ID of the mentioned contact. |
| Zoom.ChatMessage.at_items.at_type | integer | The type of mention. Allowed values 1 (Contact), 2 (Channel). |
| Zoom.ChatMessage.at_items.end_position | integer | The end position of the mention. |
| Zoom.ChatMessage.at_items.start_position | integer | The start position of the mention. |
| Zoom.ChatMessageNextToken.user_id | string | The user ID associated with the next page token. |
| Zoom.ChatMessageNextToken.to_channel | string | The channel ID associated with the next page token. |
| Zoom.ChatMessageNextToken.include_deleted_and_edited_message | boolean | Indicates whether deleted and edited messages are included in the next page token request. |
| Zoom.ChatMessageNextToken.search_type | string | The search type associated with the next page token. |
| Zoom.ChatMessageNextToken.to | string | The recipient associated with the next page token. |
| Zoom.ChatMessageNextToken.date | string | The date associated with the next page token. |
| Zoom.ChatMessageNextToken.page_size | integer | The page size associated with the next page token. |
| Zoom.ChatMessageNextToken.next_page_token | string | The next page token for pagination. |
| Zoom.ChatMessageNextToken.from | string | The sender associated with the next page token. |
| Zoom.ChatMessageNextToken.search_key | string | The search key associated with the next page token. |
| Zoom.ChatMessageNextToken.exclude_child_message | boolean | Indicates whether child messages are excluded in the next page token request. |
| Zoom.ChatMessageNextToken.to_contact | string | The contact ID associated with the next page token. |
Command example
!zoom-list-messages user_id=uJiZN-O7Rp6Jp_995FpZGg to_contact=example@example.com date=today
Context Example
{
"Zoom": {
"ChatMessage": {
"ChatMessage": [
{
"date_time": "2023-05-22T08:24:14Z",
"id": "a62636c8-b6c1-4135-9352-88ac61eafc31",
"message": "message",
"send_member_id": "1vrdvnC1gHuxZtpVLR7Oz1_A1dcCrBf0PNoRhTIzcvJjtbxgPXQRLmDm-10C2Ggg",
"sender": "example@example.com",
"sender_display_name": "admin zoom",
"timestamp": 1684743854543
},
{
"date_time": "2023-05-22T08:20:22Z",
"id": "4a59df4a-9668-46bd-bff2-3e1f3462ecc3",
"message": "my message",
"send_member_id": "1vrdvnC1gHuxZtpVLR7Oz1_A1dcCrBf0PNoRhTIzcvJjtbxgPXQRLmDm-10C2Ggg",
"sender": "example@example.com",
"sender_display_name": "admin zoom",
"timestamp": 1684743622899
}
],
"ChatMessageNextToken": ""
}
}
}
Human Readable Output
Messages
Date Time From Message Id Message sender Message text Sender display name To User id 2023-05-22T08:24:14Z None a62636c8-b6c1-4135-9352-88ac61eafc31 example@example.com message admin zoom None uJiZN-O7Rp6Jp_995FpZGg 2023-05-22T08:20:22Z None 4a59df4a-9668-46bd-bff2-3e1f3462ecc3 example@example.com my message admin zoom None uJiZN-O7Rp6Jp_995FpZGg
zoom-delete-user-token
Revoke a user’s Zoom SSO session.
To list all available users use the zoom-list-users command.
Base Command
zoom-delete-user-token
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | The user ID or email to be revoked. | Required |
Command example
!zoom-delete-user-token user_id=useremail@myself.com
Context Output
There is no context output for this command.
Human Readable Output
Message
User SSO token for user useremail@myself.com is deleted
send-notification
Sends messages from your Marketplace Chatbot app on Zoom to either an individual user or to a channel.
Base Command
send-notification
Input
| Argument Name | Description | Required |
|---|---|---|
| to | The email address or user ID or member ID of the person to send a message. | Required |
| channel_id | The channel ID of the channel to send a message. | Optional |
| message | The message to be sent. Maximum of 1024 characters. | Required |
| visible_to_user | The UserID that allows a Chatbot to send a message to a group channel when it has only one designated person in that group channel to see the message. | Optional |
Context Output
There is no context output for this command.
Command example
!send-notification message=hi to=example@example.com
Context Output
There is no context output for this command.
Human Readable Output
Message
Message sent to Zoom successfully. Message ID is: 20230815153245201_BPK3S3S_aw1
mirror-investigation
Mirrors the investigation between Zoom and the Cortex XSOAR War Room.
Base Command
mirror-investigation
Input
| Argument Name | Description | Required |
|---|---|---|
| type | The mirroring type. Can be “all”, which mirrors everything, “chat”, which mirrors only chats (not commands), or “none”, which stops all mirroring. Possible values are: all, chat, none. Default is all. | Optional |
| autoclose | Whether the channel is auto-closed when an investigation is closed. Can be “true” or “false”. Default is “true”. | Optional |
| direction | The mirroring direction. Can be “FromDemisto”, “ToDemisto”, or “Both”. Default value is “Both”. | Optional |
| channelName | The name of the channel. The default is “incident-<incidentID>”. | Optional |
Context Output
There is no context output for this command.
Command Example
!mirror-investigation direction="FromDemisto" channelName="example"
Human Readable Output
Investigation mirrored successfully, channel:example
close-channel
Delete a mirrored Zoom channel.
Base Command
close-channel
Input
| Argument Name | Description | Required |
|---|---|---|
| channel | The name of the channel to delete. If not provided, the mirrored investigation channel is deleted (if the channel exists). | Optional |
| channel_id | The ID of the channel to delete. If not provided, the mirrored investigation channel is deleted (if the channel exists). | Optional |
Context Output
There is no context output for this command.
Command Example
!close-channel channel=new-zoom-channel
Human Readable Output
Channel successfully deleted.
Configuration parameters
url— Server URL (e.g. 'https://api.zoom.us/v2/') (required)account_id— Account ID (OAuth) (required)credentials— Client ID (OAuth) (required)botJID— Bot JIDbot_credentials— Bot Client ID ((Team Chat App))secret_token—verification_token—longRunning— Long running instancelongRunningPort— Listen Portmirroring— Enable Incident Mirroringproxy— Use system proxy settingsinsecure— Trust any certificate (not secure)certificate— Certificate (Required for HTTPS)key— Private Key (Required for HTTPS)
Commands (23)
-
close-channelDelete a mirrored Zoom channel.
-
mirror-investigationMirrors the investigation between Zoom and the Cortex XSOAR War Room.
-
send-notificationSend a message using a chatbot app.
-
zoom-create-channelCreates a channel for a user. Use the existing command zoom-list-users to get the user ID by email (only if the user has an email address as part of the user parameters).
-
zoom-create-meetingCreate a new Zoom meeting (scheduled, instant, or recurring).
-
zoom-create-userCreate a new user in zoom account.
-
zoom-delete-channelDeletes a specific Zoom channel. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name.
-
zoom-delete-messageDeletes a chat message previously sent to a contact or a channel. Use the command zoom-list-user-channels to get the channel ID by the channel name (for to_channel). See the existing command zoom-list-users to get the user ID by email (for to_contact). In order to update messages (or a single message using messageId), you need to provide to_contact (contact to send) or to_channel (channel to send to), but not both of them.
-
zoom-delete-userDelete a user from Zoom.
-
zoom-delete-user-tokenRevoke a user's Zoom SSO session. Use the zoom-list-users command to get the user ID or user email.
-
zoom-fetch-recordingGet the meeting record and save it as a file in the War Room.
-
zoom-invite-to-channelInvites members that are in a user's contact list to a channel. A channel can have one or more members. The maximum number of members that can be added at once with this API is 5. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name.
-
zoom-list-account-public-channelsList the existing channels You can only retrieve the channel information for the authorized user. In order to get a public channel by its name (for example Admins_to_delete_4) you need to run the command zoom-list-account-public-channels without the channel_id param and find which channel_id fits the channel name.
-
zoom-list-messagesSearches chat messages or shared files between a user and an individual contact or a chat channel.
-
zoom-list-user-channelsList the existing channels. In order get the user ID by user email - use the existing command zoom-list-users. In order to get the user channel by its name, run the command zoom-list-user-channels without the channel_id param and find which channel_id fits the channel name.
-
zoom-list-usersList the existing users.
-
zoom-meeting-getGet the information of an existing Zoom meeting.
-
zoom-meeting-listShow all the meetings of a given user. Note: only scheduled and unexpired meetings will appear.
-
zoom-remove-from-channelRemoves a member from a chat channel. A channel can have one or more members. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name. In order get the user ID by the user email - use the existing command zoom-list-users.
-
zoom-send-fileSends a file on Zoom to either an individual user in your contact list or a channel of which you are a member. Use existing command zoom-list-users to get the user ID by the user email (for to_contact). Use the command zoom-list-user-channels in order to fetch the channel ID by the channel name (for to_channel).
-
zoom-send-messageSends chat messages on Zoom to either an individual user who is in your contact list or to a channel of which you are a member. Use the command zoom-list-users to get the user id by the user email (for to_contact). Use the command zoom-list-user-channels in order to fetch the channel ID by the channel name (for to_channel). In order to send a message, you need to provide at least a message (message text) and to_contact (contact to send) or to_channel (channel to send to), but not both of them. In order to send a style message you need to provide is-markdown=true and the message can contain a markdown format. If you are using mention markdown in a message, provide the email address in the at_contact argument.
-
zoom-update-channelUpdate an existing channel in a Zoom account. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name. "Need to provide at least one of the following arguments: posting_permissions or channnel_name.".
-
zoom-update-messageEdits a chat message that you previously sent to either a contact or a channel in Zoom by providing the ID of the message as the value of the messageId parameter. As a query parameter, you must provide either the contact's email address of the contact or the Channel ID of the channel where the message was sent. Use the command zoom-list-user-channels to get the channel ID by the channel name (for to_channel). Use the existing command zoom-list-users to get the user ID by email (for to_contact). In order to update messages (or a single message using messageId), you need to provide to_contact (contact to send) or to_channel (channel to send to), but not both of them.
import json from unittest.mock import patch import demistomock as demisto import pytest import Zoom from CommonServerPython import CommandResults, DemistoException from fastapi import Request, status from fastapi.security import HTTPBasicCredentials from freezegun import freeze_time from Zoom import Client def test_zoom_list_users_command__limit(mocker): """ Given - client When - asking for a limit of results Then - Validate that a func that runs a pagination has been called """ manual_list_user_pagination_mock = mocker.patch.object(Zoom, "manual_list_user_pagination") mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_users_command zoom_list_users_command(client=client, limit=50) assert manual_list_user_pagination_mock.called def test_zoom_list_users_command__no_limit(mocker): """ Given - client When - asking for one page results (the default) Then - Validate that a func that runs a pagination has not been called Validate that a func that returns the first page is called """ manual_list_user_pagination_mock = mocker.patch.object(Zoom, "manual_list_user_pagination", return_value=[{"None": None}]) returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_list_users_mock = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_users_command zoom_list_users_command( client=client, page_size=30, user_id=None, status="active", next_page_token=None, role_id=None, limit=None ) assert not manual_list_user_pagination_mock.called assert zoom_list_users_mock.called def test_zoom_list_users_command__limit_and_page_size(mocker): """ When - asking for a limit of results and for a user_id Then - Validate that an error message will be returned """ returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_users_command with pytest.raises(DemistoException) as e: zoom_list_users_command( client=client, page_size=30, user_id="fdghdf", status="active", next_page_token=None, role_id=None, limit=50 ) assert ( e.value.message == """Too many arguments. If you choose a limit, don't enter a user_id or page_size or next_page_token or page_number.""" ) def test_zoom_list_users_command__user_id(mocker): """ Given - client When - asking for a specific user Then - Validate that the API call will be for a specific user and the url_suffix has changed to the right value """ returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_users_command zoom_list_users_command( client=client, page_size=30, user_id="bla@bla.com", status="active", next_page_token=None, role_id=None, limit=None ) assert zoom_list_users_mocker.call_args[1].get("url_suffix") == "users/bla@bla.com" def test_manual_list_user_pagination__small_limit(mocker): """ Given - client When - limit > 0 < MAX_RECORDS_PER_PAGE Then - Validate that the page_size == limit """ mocker.patch.object(Client, "generate_oauth_token") returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") limit = 5 from Zoom import manual_list_user_pagination manual_list_user_pagination(client=client, next_page_token="None", limit=limit, status="None", role_id="None") assert zoom_list_users_mocker.call_args[1].get("page_size") == limit def test_manual_list_user_pagination__large_limit(mocker): """ Given - client When - limit > MAX_RECORDS_PER_PAGE Then - Validate that the page_size at the last call == MAX_RECORDS_PER_PAGE (currently 300) """ mocker.patch.object(Client, "generate_oauth_token") returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") limit = 2000 from Zoom import manual_list_user_pagination manual_list_user_pagination(client=client, next_page_token="None", limit=limit, status="None", role_id="None") assert zoom_list_users_mocker.call_args[1].get("page_size") == 300 def test_zoom_create_user_command(mocker): client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") user_type = ("Basic",) email = ("mock@moker.com",) first_name = ("John",) last_name = "Smith" zoom_create_user_mock = mocker.patch.object(client, "zoom_create_user") from Zoom import zoom_create_user_command zoom_create_user_command(client, email=email, user_type=user_type, first_name=first_name, last_name=last_name) zoom_create_user_mock.assert_called() def test_zoom_create_user__basic_user_type(mocker): """ Given - client When - asking for a basic user type Then - Validate that the right type is sent to the API """ mocker.patch.object(Client, "generate_oauth_token") http_request_mocker = mocker.patch.object(Client, "error_handled_http_request", return_value=None) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") client.zoom_create_user(user_type_num=1, email="mock@moker.com", first_name="John", last_name="Smith") assert http_request_mocker.call_args[1].get("json_data").get("user_info").get("type") == 1 def test_zoom_user_create__pro_user_type(mocker): """ Given - client When - asking for a pro user type Then - Validate that the right type is sent in the error_handled_http_request """ mocker.patch.object(Client, "generate_oauth_token") http_request_mocker = mocker.patch.object(Client, "error_handled_http_request", return_value=None) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") client.zoom_create_user(user_type_num=2, email="mock@moker.com", first_name="John", last_name="Smith") assert http_request_mocker.call_args[1].get("json_data").get("user_info").get("type") == 2 def test_zoom_user_create__Corporate_user_type(mocker): """ Given - client When - asking for a Corporate user type Then - Validate that the right type is sent in the http_request """ mocker.patch.object(Client, "generate_oauth_token") http_request_mocker = mocker.patch.object(Client, "error_handled_http_request", return_value=None) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") client.zoom_create_user(user_type_num=3, email="mock@moker.com", first_name="John", last_name="Smith") assert http_request_mocker.call_args[1].get("json_data").get("user_info").get("type") == 3 def test_zoom_delete_user_command(mocker): client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") user_id = "user_id" zoom_delete_user_mock = mocker.patch.object(client, "zoom_delete_user") from Zoom import zoom_delete_user_command zoom_delete_user_command(client, user_id=user_id) zoom_delete_user_mock.assert_called() def test_zoom__create_meeting_command__instant_meeting(mocker): """ Given - client When - asking for a instant meeting Then - Validate that the right type is sent in the API """ zoom_create_meeting_mocker = mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command zoom_create_meeting_command( client=client, user_id="mock@moker.com", topic="nonsense", type="Instant", ) assert zoom_create_meeting_mocker.call_args[1]["json_data"].get("type") == 1 def test_zoom_meeting_create_command__scheduled_meeting(mocker): """ Given - client When - asking for a scheduled meeting Then - Validate that the right type is sent in the API """ zoom_create_meeting_mocker = mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command zoom_create_meeting_command(client=client, user_id="mock@moker.com", topic="nonsense", type="Scheduled") assert zoom_create_meeting_mocker.call_args[1]["json_data"].get("type") == 2 def test_zoom_create_meeting_command_too_many_arguments(mocker): """ Given - client When - asking for a meeting with join_before_host_and_waiting_room Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command( client=client, user_id="mock@moker.com", topic="nonsense", type="Scheduled", waiting_room=True, join_before_host=True ) assert e.value.message == "Collision arguments. join_before_host argument can be used only if waiting_room is 'False'." def test_zoom_create_meeting__too_meny_arguments(mocker): """ Given - client When - asking for a meeting with join_before_host_time ant not join_before_host Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command( client=client, user_id="mock@moker.com", topic="nonsense", type="Scheduled", join_before_host_time=5, join_before_host=False, ) assert ( e.value.message == """Collision arguments. join_before_host_time argument can be used only if join_before_host is 'True'.""" ) def test_zoom_create_meeting_command__too_meny_arguments1(mocker): """ Given - client When - asking for a meeting with instant type ant start_time Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command( client=client, type="Instant", topic="nonsense", user_id="mock@moker.com", start_time="2022-10-04T15:59:00Z" ) assert e.value.message == "Too many arguments.Use start_time and timezone for scheduled meetings only." def test_zoom_create_meeting_command__too_many_arguments2(mocker): """ Given - client When - asking for a instant meeting with end_times and monthly_week : Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command( client=client, type="Instant", recurrence_type=3, topic="nonsense", user_id="mock@moker.com", end_date_time="2022-10-04T15:59:00Z", monthly_week=2, monthly_week_day=3, end_times=7, ) assert e.value.message == "Collision arguments. Choose only one of these two arguments, end_time or end_date_time." def test_zoom_create_meeting_command__too_meny_arguments3(mocker): """ Given - client When - asking for a recurring meeting with fixed time and recurrence_type = 3, with no monthly_week : Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command( client=client, type="Recurring meeting with fixed time", recurrence_type="Monthly", topic="nonsense", user_id="mock@moker.com", end_date_time="2022-10-04T15:59:00Z", end_times=None, ) assert ( e.value.message == """Missing arguments. A recurring meeting with a fixed time and monthly recurrence_type must have the following arguments: monthly_week and monthly_week_day.""" ) def test_zoom_create_meeting_command__too_meny_arguments4(mocker): """ Given - client When - asking for a recurring meeting with fixed time and recurrence_type = 3, with no monthly_week : Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command( client=client, type="Recurring meeting with fixed time", topic="nonsense", user_id="mock@moker.com" ) assert ( e.value.message == """Missing arguments. A recurring meeting with a fixed time is missing this argument: recurrence_type.""" ) def test_zoom_create_meeting_command__too_many_arguments5(mocker): """ Given - client When - asking for a instant meeting with end_times: Then - Validate that the right error will return """ mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"}) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_meeting_command with pytest.raises(DemistoException) as e: zoom_create_meeting_command(client=client, type="Instant", end_times=7) assert e.value.message == "One or more arguments that were filed\nare used for a recurring meeting with a fixed time only." def test_meeting_get_command__show_previous_occurrences_is_false(mocker): """ Given - client When - asking to get a meeting, and the previous_occurrences Then - Validate that the right argument is sent in the API """ returned_dict = { "uuid": "u=", "id": 847, "host_id": "u", "host_email": "example@example.com", "assistant_id": "", "topic": "My Meeting", "type": 2, "status": "waiting", "start_time": "5Z", "duration": 60, "timezone": "lem", "agenda": "", "created_at": "48Z", "start_url": ".2-dio1Se7o", } zoom_meeting_get_mocker = mocker.patch.object(Client, "zoom_meeting_get", return_value=returned_dict) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_meeting_get_command zoom_meeting_get_command(client=client, meeting_id="1234", show_previous_occurrences=True) assert zoom_meeting_get_mocker.call_args[0][2] is True def test_zoom_meeting_list_command__limit(mocker): """ Given - client When - asking for a limit of results Then - Validate that a func that runs a pagination has been called """ manual_meeting_list_pagination_mock = mocker.patch.object(Zoom, "manual_meeting_list_pagination") mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_meeting_list_command zoom_meeting_list_command(client=client, user_id="blabla", limit=50) assert manual_meeting_list_pagination_mock.called def test_zoom_meeting_list_command__no_limit(mocker): """ Given - client When - asking for one page results (the default) Then - Validate that a func that runs a pagination has not been called Validate that a func that returns the first page is called """ manual_meeting_list_pagination_mock = mocker.patch.object(Zoom, "manual_meeting_list_pagination") mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") returned_dict = { "uuid": "u=", "id": 847, "host_id": "u", "host_email": "example@example.com", "assistant_id": "", "topic": "My Meeting", "type": 2, "status": "waiting", "start_time": "5Z", "duration": 60, "timezone": "lem", "agenda": "", "created_at": "48Z", "start_url": ".2-dio1Se7o", } zoom_meeting_list_mock = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict) from Zoom import zoom_meeting_list_command zoom_meeting_list_command(client=client, user_id="blabla") assert not manual_meeting_list_pagination_mock.called assert zoom_meeting_list_mock.called def test_manual_meeting_list_pagination__small_limit(mocker): """ Given - client When - limit > 0 < MAX_RECORDS_PER_PAGE Then - Validate that the page_size == limit """ mocker.patch.object(Client, "generate_oauth_token") returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_meeting_list_mocker = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") limit = 5 from Zoom import manual_meeting_list_pagination manual_meeting_list_pagination(client=client, user_id="bla", next_page_token=None, limit=limit, type="all") assert zoom_meeting_list_mocker.call_args[1].get("page_size") == limit def test_manual_meeting_list_pagination__large_limit(mocker): """ Given - client When - limit > MAX_RECORDS_PER_PAGE Then - Validate that the page_size at the last call == MAX_RECORDS_PER_PAGE (currently 300) """ mocker.patch.object(Client, "generate_oauth_token") returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": "", "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_meeting_list_mocker = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") limit = 2000 from Zoom import manual_meeting_list_pagination manual_meeting_list_pagination(client=client, user_id="bla", next_page_token=None, limit=limit, type="all") assert zoom_meeting_list_mocker.call_args[1].get("page_size") == 300 def test_check_authentication_type_parameters_with_extra_jwt_member(mocker): """ Given - client When - creating a client with an extra authentication type argument Then - Validate that the error wil raise as excepted """ with pytest.raises(DemistoException) as e: Zoom.check_authentication_type_parameters( account_id="mockaccount", client_id="mockclient", client_secret="mocksecret", api_key="blabla", api_secret="" ) assert ( e.value.message == """Too many fields were filled. You should fill the Account ID, Client ID, and Client Secret fields (OAuth), OR the API Key and API Secret fields (JWT - Deprecated).""" ) def test_check_authentication_type_parameters__with_extra_AOuth_member(): """ Given - When - creating a client with an extra authentication type argument Then - Validate that the error wil raise as excepted """ with pytest.raises(DemistoException) as e: Zoom.check_authentication_type_parameters( account_id="", client_id="", client_secret="mocksecret", api_key="blabla", api_secret="ertert" ) assert ( e.value.message == """Too many fields were filled. You should fill the Account ID, Client ID, and Client Secret fields (OAuth), OR the API Key and API Secret fields (JWT - Deprecated).""" ) def test_zoom_user_list_command__when_user_id(mocker): """ Given - a response from a client When - a user_id argument was passed Then - Validate that the parsing is as expected """ to_md = { "id": "C", "first_name": "Ye", "last_name": "Ro", "email": "y@gmail.com", "type": 1, "role_name": "Member", "pmi": 9, "use_pmi": False, "personal_meeting_url": "hts://us0", "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", "created_at": "2022-12-01T07:40:02Z", "last_login_time": "2022-12-14T08:14:29Z", } mocker.patch.object(Client, "zoom_list_users", return_value=to_md) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_users_command res = zoom_list_users_command(client, user_id="bla") assert len(res.readable_output) == 159 # type: ignore[arg-type] def test_zoom_meeting_list_command__when_user_id(mocker): """ Given - a response from a client When - a user_id argument was passed Then - Validate that the parsing is as expected """ to_md = { "id": "CTJ7hG", "first_name": "Ye", "last_name": "Ro", "email": "y@gmail.com", "type": 1, "role_name": "Member", "pmi": 98, "use_pmi": False, "personal_meeting_url": "https://", "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", "created_at": "2022-12-01T07:40:02Z", "last_login_time": "2022-12-14T08:14:29Z", } mocker.patch.object(Client, "zoom_meeting_list", return_value=to_md) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_meeting_list_command res = zoom_meeting_list_command(client, user_id="bla") assert len(res.readable_output) == 133 # type: ignore[arg-type] def test_remove_None_values_from_dict(): from Zoom import remove_None_values_from_dict """ Given - a nested dict When - some values == None Then - Validate that the keys with value None are removed """ dict_input = { "settings": { "allow_multiple_devices": "tuyytu", "auto_recording": "dyj", "encryption_type": "jy", "focus_mode": False, "host_video": None, "jbh_time": "jdfd", "join_before_host": "join_before_host", "meeting_authentication": "meeting_authentication", "meeting_invitees": "meeting_invitees", "waiting_room": False, }, "start_time": "start_time", "timezone": None, "type": "num_type", "topic": False, } dict_expected_output = { "settings": { "allow_multiple_devices": "tuyytu", "auto_recording": "dyj", "encryption_type": "jy", "focus_mode": False, "jbh_time": "jdfd", "join_before_host": "join_before_host", "meeting_authentication": "meeting_authentication", "meeting_invitees": "meeting_invitees", "waiting_room": False, }, "start_time": "start_time", "type": "num_type", "topic": False, } assert remove_None_values_from_dict(dict_input) == dict_expected_output def test_check_start_time_format__wrong_format(): """Given - a time format When - missing a field Then - veryfy that the right error wil raise """ from Zoom import check_start_time_format with pytest.raises(DemistoException) as e: check_start_time_format("2022-13-26T22:22:Z") assert e.value.message == "Wrong time format. Use this format: 'yyyy-MM-ddTHH:mm:ssZ' or 'yyyy-MM-ddTHH:mm:ss' " def test_test_moudle__reciving_errors(mocker): mocker.patch.object(Client, "get_oauth_token", return_value=("token", None)) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("Invalid access token")) from Zoom import test_module assert test_module(client=client) == "Invalid credentials. Please verify that your credentials are valid." def test_test_moudle__reciving_errors1(mocker): mocker.patch.object(Client, "get_oauth_token", return_value=("token", None)) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("The Token's Signature resulted invalid")) from Zoom import test_module assert test_module(client=client) == "Invalid API Secret. Please verify that your API Secret is valid." def test_test_moudle__reciving_errors2(mocker): mocker.patch.object(Client, "get_oauth_token", return_value=("token", None)) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("Invalid client_id or client_secret")) from Zoom import test_module assert test_module(client=client) == "Invalid Client ID or Client Secret. Please verify that your ID and Secret is valid." def test_test_moudle__reciving_errors3(mocker): mocker.patch.object(Client, "get_oauth_token", return_value=("token", None)) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("mockerror")) from Zoom import test_module assert test_module(client=client) == "Problem reaching Zoom API, check your credentials. Error message: mockerror" def test_manual_list_user_pagination__next_page_token_None(mocker): """ Given - client When - limit > 0 and next_page_token == None Then - # Validate that the pagination process will start """ mocker.patch.object(Client, "generate_oauth_token") returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": None, "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") limit = 5 from Zoom import manual_list_user_pagination manual_list_user_pagination(client=client, next_page_token=None, limit=limit, status="None", role_id="None") assert zoom_list_users_mocker.called def test_manual_meeting_list_pagination__next_page_token_None(mocker): """ Given - client When - limit > 0 and next_page_token == None Then - # Validate that the pagination process will start """ mocker.patch.object(Client, "generate_oauth_token") returned_dict = { "page_count": 1, "page_number": 1, "page_size": 30, "total_records": 2, "next_page_token": None, "users": [ { "id": "1234", "first_name": "as", "last_name": "bla", "email": "example@example.com", "type": 1, "pmi": 1234, "timezone": "Asia/Jerusalem", "verified": 1, "dept": "", } ], } zoom_meeting_list_mocker = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict) client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") limit = 5 from Zoom import manual_meeting_list_pagination manual_meeting_list_pagination(client=client, user_id="bla", next_page_token=None, limit=limit, type="all") assert zoom_meeting_list_mocker.called class MockResponse: def __init__(self, text="", content="", raw="", decode_content: bool = False): self.text = text self.content = content self.raw = raw self.decode_content = decode_content def test_zoom_fetch_recording__download_success(mocker): """ Given - client When - asking for a specific recording Then: Validate that the successfull messege is added to the commandResults and the writing function was called. """ import shutil from Zoom import zoom_fetch_recording_command mocker.patch.object(demisto, "debug") mocker.patch.object(shutil, "copyfileobj") mocker.patch.object( Client, "zoom_fetch_recording", side_effect=[ { "recording_files": [ { "id": "29c7tc", "meeting_id": "Y", "play_url": "hsy", "download_url": "htsy", "status": "completed", "recording_type": "t", } ] }, MockResponse(raw=MockResponse(decode_content=False)), ], ) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") res = zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="false") assert res[1].readable_output == "The None file recording_000000_29c7tc.None was downloaded successfully" def test_zoom_fetch_recording_command__delete_success(mocker): """ Given - client When - asking for a specific recording and deleting that recording from the cloud Then - Validate that the successfull deleting messege is added to the commandResults """ import shutil from Zoom import zoom_fetch_recording_command mocker.patch.object(demisto, "debug") mocker.patch.object(shutil, "copyfileobj") mocker.patch.object( Client, "zoom_fetch_recording", side_effect=[ { "recording_files": [ { "id": "29c7tc", "meeting_id": "Y", "play_url": "hsy", "download_url": "htsy", "status": "completed", "recording_type": "t", } ] }, MockResponse(raw=MockResponse(decode_content=False)), MockResponse(text="sff"), ], ) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") res = zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true") assert res[2].readable_output == "The None file recording_000000_29c7tc.None was successfully removed from the cloud." def test_zoom_fetch_recording_command__recording_dose_not_exist(mocker): """ Given - client When - asking for a specific recording that dose not exist Then - Validate that right error will return """ import shutil from Zoom import zoom_fetch_recording_command mocker.patch.object(demisto, "debug") mocker.patch.object(shutil, "copyfileobj") mocker.patch.object(Client, "zoom_fetch_recording", side_effect=[DemistoException("mockerror")]) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") with pytest.raises(DemistoException) as e: zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true") assert e.value.message == "mockerror" def test_zoom_fetch_recording_command__not_able_to_download(mocker): """ Given - client When - asking for a specific recording that exist, but unable to download Then - Validate that right error will return """ import shutil from Zoom import zoom_fetch_recording_command mocker.patch.object(demisto, "debug") mocker.patch.object(shutil, "copyfileobj") mocker.patch.object( Client, "zoom_fetch_recording", side_effect=[ { "recording_files": [ { "id": "29c7tc", "meeting_id": "Y", "play_url": "hsy", "download_url": "htsy", "status": "completed", "recording_type": "t", } ] }, DemistoException("mockerror"), ], ) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") with pytest.raises(DemistoException) as e: zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true") assert e.value.message == "Unable to download recording for meeting 000000: mockerror" def test_zoom_fetch_recording_command__not_able_to_delete(mocker): """ Given - client When - asking for a specific recording that exist, successfull downloading, but but unable to download Then - Validate that right error will return """ import shutil from Zoom import zoom_fetch_recording_command mocker.patch.object(demisto, "debug") mocker.patch.object(shutil, "copyfileobj") mocker.patch.object( Client, "zoom_fetch_recording", side_effect=[ { "recording_files": [ { "id": "29c7tc", "meeting_id": "Y", "play_url": "hsy", "download_url": "htsy", "status": "completed", "recording_type": "t", } ] }, MockResponse(raw=MockResponse(decode_content=False)), DemistoException("mockerror"), ], ) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") res = zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true") assert res[2].readable_output == "Failed to delete file recording_000000_29c7tc.None. mockerror" def test_zoom_list_user_channels_command(mocker): """ Given - client When - asking for a list public channels Then - Validate that a func has been called """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") channel_id = "channel_id" user_id = "user_id" expected_url_suffix = f"users/{user_id}/channels/{channel_id}" if channel_id else f"users/{user_id}/channels" expected_raw_data = { "channels": [ { "jid": "channel_jid_1_t", "id": "channel_id_1", "name": "Channel 1", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token1", }, { "jid": "channel_jid_2", "id": "channel_id_2", "name": "Channel 2", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token2", }, ] } expected_results = { "UserChannelsNextToken": None, "channels": [ { "jid": "channel_jid_1_t", "id": "channel_id_1", "name": "Channel 1", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token1", }, { "jid": "channel_jid_2", "id": "channel_id_2", "name": "Channel 2", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token2", }, ], } zoom_list_user_channels_mock = mocker.patch.object(client, "zoom_list_user_channels") zoom_list_user_channels_mock.return_value = expected_raw_data from Zoom import zoom_list_user_channels_command result = zoom_list_user_channels_command(client, channel_id=channel_id, user_id=user_id) zoom_list_user_channels_mock.assert_called_with( user_id=user_id, page_size=50, next_page_token=None, url_suffix=expected_url_suffix, page_number=1 ) assert result.outputs == expected_results assert result.outputs["channels"][0]["id"] == expected_results["channels"][0]["id"] assert result.outputs["channels"][0]["jid"] == expected_results["channels"][0]["jid"] def test_zoom_list_user_channels_command__limit(mocker): """ Given - client When - asking for a limit of results Then - Validate that a func that runs a pagination has been called """ manual_list_user_channel_pagination_mock = mocker.patch.object(Zoom, "manual_list_user_channel_pagination") mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_user_channels_command zoom_list_user_channels_command(client=client, user_id="user_id", limit=5) assert manual_list_user_channel_pagination_mock.called def test_zoom_create_channel_command(mocker): """ Given - client When - creating a Zoom channel Then - Validate that the zoom_create_channel function is called with the correct arguments Validate the command results including outputs and readable output """ # Mock the response from zoom_create_channel response = {"id": "channel_id", "name": "TestChannel3", "type": "1", "channel_url": "https://zoom.us/channel/channel_id"} zoom_create_channel_mock = mocker.patch.object(Client, "zoom_create_channel", return_value=response) mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_create_channel_command # Set up the inputs user_id = "u12345" member_emails = ["user2@example.com", "user1@example.com"] add_member_permissions = "All channel members can add" posting_permissions = "All members can post" new_members_can_see_prev_msgs = True channel_name = "TestChannel" channel_type = "Private channel" zoom_create_channel_command( client=client, user_id=user_id, member_emails=member_emails, add_member_permissions=add_member_permissions, posting_permissions=posting_permissions, new_members_can_see_prev_msgs=new_members_can_see_prev_msgs, channel_name=channel_name, channel_type=channel_type, ) # Verify the API call expected_url_suffix = f"/chat/users/{user_id}/channels" expected_json_data = { "channel_settings": { "add_member_permissions": 1, "new_members_can_see_previous_messages_files": True, "posting_permissions": 1, }, "members": [{"email": "user2@example.com"}, {"email": "user1@example.com"}], "name": "TestChannel", "type": 1, } zoom_create_channel_mock.assert_called_with(expected_url_suffix, expected_json_data) def test_zoom_delete_channel_command(mocker): """ Given - client When - deleting a Zoom channel Then - Validate that the zoom_delete_channel function is called with the correct arguments """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") channel_id = "channel_id" user_id = "user_id" expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}" zoom_delete_channel_mock = mocker.patch.object(client, "zoom_delete_channel") from Zoom import zoom_delete_channel_command zoom_delete_channel_command(client, channel_id=channel_id, user_id=user_id) zoom_delete_channel_mock.assert_called_with(expected_url_suffix) def test_zoom_update_channel_command(mocker): """ Given - client When - updating a Zoom channel Then - Validate that the zoom_update_channel function is called with the correct arguments """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") add_member_permissions = "All channel members can add" posting_permissions = "All members can post" new_members_can_see_prev_msgs = True channel_name = "TestChannel" channel_id = "channel_id" user_id = "user_id" expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}" expected_json_data = { "name": channel_name, "channel_settings": { "add_member_permissions": 1, "new_members_can_see_previous_messages_files": new_members_can_see_prev_msgs, "posting_permissions": 1, }, } zoom_update_channel_mock = mocker.patch.object(client, "zoom_update_channel") from Zoom import zoom_update_channel_command zoom_update_channel_command( client, add_member_permissions=add_member_permissions, posting_permissions=posting_permissions, new_members_can_see_prev_msgs=new_members_can_see_prev_msgs, channel_name=channel_name, channel_id=channel_id, user_id=user_id, ) zoom_update_channel_mock.assert_called_with(expected_url_suffix, expected_json_data) def test_zoom_invite_to_channel_command(mocker): """ Given - client When - Invite user to a Zoom channel Then - Validate that the zoom_invite_to_channel function is called with the correct arguments """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") channel_id = "channel_id" user_id = "user_id" members = ["user1@example.com", "user2@example.com"] expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}/members" expected_json_data = {"members": [{"email": "user1@example.com"}, {"email": "user2@example.com"}]} from Zoom import zoom_invite_to_channel_command zoom_invite_to_channel_mock = mocker.patch.object(client, "zoom_invite_to_channel") # Convert MagicMock to dictionary zoom_invite_to_channel_mock.return_value = expected_json_data zoom_invite_to_channel_command(client, channel_id=channel_id, user_id=user_id, members=members) zoom_invite_to_channel_mock.assert_called_with(expected_json_data, expected_url_suffix) def test_zoom_remove_from_channel_command(mocker): """ Given - client When - Remove user from a Zoom channel Then - Validate that the zoom_remove_from_channel function is called with the correct arguments """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") channel_id = "channel_id" member_id = "member_id" user_id = "user_id" expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}/members/{member_id}" zoom_remove_from_channel_mock = mocker.patch.object(client, "zoom_remove_from_channel") from Zoom import zoom_remove_from_channel_command zoom_remove_from_channel_command(client, channel_id=channel_id, member_id=member_id, user_id=user_id) zoom_remove_from_channel_mock.assert_called_with(expected_url_suffix) def test_zoom_send_file_command(mocker): """ Given - client When - Zoom send file to channel Then - Validate that the zoom_send_file function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") user_id = "user_id" to_channel = "channel_id" entry_id = "entry_id" expected_upload_url = f"https://file.zoom.us/v2/chat/users/{user_id}/messages/files" expected_file_info = {"name": "test_file.txt", "path": "/path/to/test_file.txt"} expected_json_data = {"to_channel": to_channel} expected_upload_response = {"id": "file_id"} mocker.patch("Zoom.demisto.getFilePath", return_value=expected_file_info) zoom_send_file_mock = mocker.patch.object(client, "zoom_send_file", return_value=expected_upload_response) from Zoom import zoom_send_file_command results = zoom_send_file_command(client, user_id=user_id, to_channel=to_channel, entry_id=entry_id) # Assert function calls Zoom.demisto.getFilePath.assert_called_with(entry_id) zoom_send_file_mock.assert_called_with(expected_upload_url, expected_file_info, expected_json_data) # Assert results assert results.readable_output == "Message with id file_id was successfully sent" def test_zoom_list_account_public_channels_command(mocker): """ Given - client When - asking for a list public channels Then - Validate that a func has been called """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") page_size = 50 channel_id = "channel_id" next_page_token = "next_page_token" page_number = 2 expected_url_suffix = f"channels/{channel_id}" if channel_id else "channels" expected_raw_data = { "channels": [ { "jid": "channel_jid_1", "id": "channel_id_1", "name": "Channel 1", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token1", }, { "jid": "channel_jid_2", "id": "channel_id_2", "name": "Channel 2", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token2", }, ] } zoom_list_channels_mock = mocker.patch.object(client, "zoom_list_channels") zoom_list_channels_mock.return_value = expected_raw_data from Zoom import zoom_list_account_public_channels_command result = zoom_list_account_public_channels_command( client, page_size=page_size, channel_id=channel_id, next_page_token=next_page_token, page_number=page_number ) zoom_list_channels_mock.assert_called_with( page_size=page_size, next_page_token=next_page_token, url_suffix=expected_url_suffix, page_number=page_number ) expected_results = { "channels": [ { "jid": "channel_jid_1", "id": "channel_id_1", "name": "Channel 1", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token1", }, { "jid": "channel_jid_2", "id": "channel_id_2", "name": "Channel 2", "type": "public", "channel_url": "https://test1.com", "next_page_token": "token2", }, ], "ChannelsNextToken": None, } assert result.outputs == expected_results assert result.outputs["channels"][0]["id"] == expected_results["channels"][0]["id"] assert result.outputs["channels"][0]["jid"] == expected_results["channels"][0]["jid"] def test_zoom_list_account_public_channels_command__limit(mocker): """ Given - client When - zoom list public account with limit of results Then - Validate that a func that runs a pagination has been called """ manual_manual_list_channel_paginatio_mock = mocker.patch.object(Zoom, "manual_list_channel_pagination") mocker.patch.object(Client, "generate_oauth_token") client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_list_account_public_channels_command zoom_list_account_public_channels_command(client=client, user_id="example@example.com", limit=5) assert manual_manual_list_channel_paginatio_mock.called def test_zoom_send_message_command_with_file(mocker): client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") entry_id = "entry_id" user_id = "user1" expected_file_info = {"name": "test_file.txt", "path": "/path/to/test_file.txt"} expected_upload_response = {"id": "file_id"} expected_uplaod_file_url = f"https://file.zoom.us/v2/chat/users/{user_id}/files" expected_response = {"id": "message_id", "contact": "user2@example.com", "channel_name": "channel_name"} mocker.patch("Zoom.demisto.getFilePath", return_value=expected_file_info) zoom_send_file_mock = mocker.patch.object(client, "zoom_upload_file", return_value=expected_upload_response) mock_send_chat_message = mocker.patch.object(client, "zoom_send_message") mock_send_chat_message.return_value = expected_response from Zoom import zoom_send_message_command zoom_send_message_command(client, user_id=user_id, message="Hello from @dima!", to_channel="channel1", entry_ids="entry_id") # Assert function calls Zoom.demisto.getFilePath.assert_called_with(entry_id) zoom_send_file_mock.assert_called_with(expected_uplaod_file_url, expected_file_info) def test_zoom_send_message_command(mocker): """ Given - client When - send message to channel Then - Validate that the zoom_send_message function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") expected_request_payload = {"message": "Hello from @dima!", "to_channel": "channel1", "file_ids": []} expected_response = {"id": "message_id", "contact": "user2@example.com", "channel_name": "channel_name"} mock_send_chat_message = mocker.patch.object(client, "zoom_send_message") mock_send_chat_message.return_value = expected_response from Zoom import zoom_send_message_command result = zoom_send_message_command( client, user_id="user1", message="Hello from @dima!", to_channel="channel1", ) assert result.outputs == expected_response assert mock_send_chat_message.call_args[0][1] == expected_request_payload def test_zoom_send_message_markdown_command(mocker): """ Given - client When - send message to channel with markdown Then - Validate that the zoom_send_message function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") expected_request_payload = { "message": "HI \n@John, please review the following report", "to_channel": "channel1", "at_items": [{"text": "@John", "at_contact": "user2@example.com", "at_type": 1, "start_position": 4, "end_position": 8}], "rich_text": [ { "text": "report", "format_type": "AddLink", "format_attr": "https://example.com", "start_position": 39, "end_position": 44, }, {"text": "HI ", "format_type": "paragraph", "format_attr": "h1", "start_position": 0, "end_position": 2}, { "text": "@John, please review the following report", "format_type": "LeftIndent", "format_attr": 40, "start_position": 4, "end_position": 44, }, ], "file_ids": [], } expected_response = {"id": "message_id", "contact": "user2@example.com", "channel_name": "channel_name"} mock_send_chat_message = mocker.patch.object(client, "zoom_send_message") mock_send_chat_message.return_value = expected_response from Zoom import zoom_send_message_command result = zoom_send_message_command( client, user_id="user1", at_contact="user2@example.com", is_markdown=True, message="# HI \n>> @John, please review the following [report](https://example.com)", to_channel="channel1", ) assert result.outputs == expected_response assert mock_send_chat_message.call_args[0][1] == expected_request_payload def test_zoom_send_message_markdown_command_error_mentions(mocker): """ Given - client When - send message to channel with invalid markdown Then - Validate that an exception is raised """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") from Zoom import zoom_send_message_command with pytest.raises(Exception) as e: zoom_send_message_command( client, user_id="user1", at_contact="user2@example.com", is_markdown=True, message="@user This is an @invalid markdown", to_channel="channel1", ) assert str(e.value) == "Too many mentions in text. you can provide only one mention in each message" def test_zoom_list_messages_command(mocker): """ Given - client When - get all messages in date Then - Validate that the zoom_list_messages_command function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") channel_id = "channel_id" user_id = "user_id" limit = 100 to_contact = "contact@example.com" to_channel = "channel_id" date_arg = "2023-03-07T00:49:01Z" include_deleted_and_edited_message = True search_type = "message" search_key = "keyword" exclude_child_message = False expected_raw_data = { "messages": [ { "id": "message_id_1", "message": "Message 1", "sender": "sender_1", "sender_display_name": "Sender 1", "date_time": "2023-03-07T10:30:00Z", }, { "id": "message_id_2", "message": "Message 2", "sender": "sender_2", "sender_display_name": "Sender 2", "date_time": "2023-03-08T09:15:00Z", }, ] } expacted_result = { "ChatMessage": { "messages": [ { "id": "message_id_1", "message": "Message 1", "sender": "sender_1", "sender_display_name": "Sender 1", "date_time": "2023-03-07T10:30:00Z", }, { "id": "message_id_2", "message": "Message 2", "sender": "sender_2", "sender_display_name": "Sender 2", "date_time": "2023-03-08T09:15:00Z", }, ] }, "ChatMessageNextToken": None, } client.zoom_list_user_messages = mocker.MagicMock(return_value=expected_raw_data) from Zoom import zoom_list_messages_command result = zoom_list_messages_command( client, channel_id=channel_id, user_id=user_id, next_page_token="next_page_token", limit=limit, to_contact=to_contact, to_channel=to_channel, date=date_arg, include_deleted_and_edited_message=include_deleted_and_edited_message, search_type=search_type, search_key=search_key, exclude_child_message=exclude_child_message, ) assert result.outputs == expacted_result assert result.outputs["ChatMessage"]["messages"][0]["id"] == expacted_result["ChatMessage"]["messages"][0]["id"] assert result.outputs["ChatMessage"]["messages"][0]["message"] == expacted_result["ChatMessage"]["messages"][0]["message"] assert result.outputs["ChatMessage"]["messages"][0]["sender"] == expacted_result["ChatMessage"]["messages"][0]["sender"] assert ( result.outputs["ChatMessage"]["messages"][0]["sender_display_name"] == expacted_result["ChatMessage"]["messages"][0]["sender_display_name"] ) # noqa: E501 assert result.outputs["ChatMessage"]["messages"][0]["date_time"] == expacted_result["ChatMessage"]["messages"][0]["date_time"] def test_zoom_list_messages_command_pageination(mocker): """ Given - client When - get all messages in date Then - Validate that the zoom_list_messages_command function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") channel_id = "channel_id" user_id = "user_id" limit = 1 to_contact = "contact@example.com" to_channel = "channel_id" date_arg = "2023-03-07T00:49:01Z" include_deleted_and_edited_message = True search_type = "message" search_key = "keyword" exclude_child_message = False expected_raw_data = { "messages": [ { "id": "message_id_1", "message": "Message 1", "sender": "sender_1", "sender_display_name": "Sender 1", "date_time": "2023-03-07T10:30:00Z", } ], "next_page_token": "xxxxxxxxxxx", } expacted_result = { "ChatMessage": { "messages": [ { "id": "message_id_1", "message": "Message 1", "sender": "sender_1", "sender_display_name": "Sender 1", "date_time": "2023-03-07T10:30:00Z", } ] }, "ChatMessageNextToken": { "user_id": "user_id", "to_contact": "contact@example.com", "to_channel": "channel_id", "date": "2023-03-07T00:49:01Z", "include_deleted_and_edited_message": True, "search_type": "message", "search_key": "keyword", "exclude_child_message": False, "page_size": 1, "next_page_token": "xxxxxxxxxxx", }, } client.zoom_list_user_messages = mocker.MagicMock(return_value=expected_raw_data) from Zoom import zoom_list_messages_command result = zoom_list_messages_command( client, channel_id=channel_id, user_id=user_id, next_page_token="next_page_token", limit=limit, to_contact=to_contact, to_channel=to_channel, date=date_arg, include_deleted_and_edited_message=include_deleted_and_edited_message, search_type=search_type, search_key=search_key, exclude_child_message=exclude_child_message, ) assert result.outputs == expacted_result assert result.outputs["ChatMessageNextToken"]["user_id"] == expacted_result["ChatMessageNextToken"]["user_id"] assert result.outputs["ChatMessageNextToken"]["date"] == expacted_result["ChatMessageNextToken"]["date"] def test_zoom_update_message_command(mocker): """ Given - client When - update a message that was send Then - Validate that the zoom_update_message function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "generate_oauth_token") user_id = "user1" message_id = "2d12042d-1823-4b0c-b26d-3f5ef7a89d68" message = "Hello! this is message for all" to_channel = "channel1" to_contact = "user2@example.com" # entry_ids = ["file_entry_id1", "file_entry_id2"] expected_payload = {"message": message, "file_ids": [], "to_channel": to_channel, "to_contact": to_contact} zoom_update_message_mock = mocker.patch.object(client, "zoom_update_message") from Zoom import zoom_update_message_command result = zoom_update_message_command( client, user_id=user_id, message_id=message_id, message=message, to_channel=to_channel, to_contact=to_contact, # entry_ids=entry_ids ) # Test case: Update message with to_channel zoom_update_message_mock.assert_called_with(f"/chat/users/{user_id}/messages/{message_id}", expected_payload) assert result.readable_output == "Message 2d12042d-1823-4b0c-b26d-3f5ef7a89d68 was successfully updated" def test_zoom_delete_message_command(mocker): """ Given - client When - delete zoom message Then - Validate that the zoom_delete_message function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "generate_oauth_token") user_id = "user1" message_id = "2d12042d-1823-4b0c-b26d-3f5ef7a89d68" to_channel = "channel1" # entry_ids = ["file_entry_id1", "file_entry_id2"] zoom_delete_message_mock = mocker.patch.object(client, "zoom_delete_message") from Zoom import zoom_delete_message_command result_to_channel = zoom_delete_message_command( client, user_id=user_id, message_id=message_id, to_channel=to_channel, # entry_ids=entry_ids ) # Test case: Update message with to_channel zoom_delete_message_mock.assert_called_with(f"/chat/users/{user_id}/messages/{message_id}?to_channel={to_channel}") assert result_to_channel.readable_output == "Message 2d12042d-1823-4b0c-b26d-3f5ef7a89d68 was deleted successfully" def test_zoom_get_user_id_by_email(mocker): """ Given - client When - get userID by his email Then - Validate that the zoom_get_user_id_by_email function is called with the correct arguments Validate the command results """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") email = "user@example.com" expected_user_id = "user_id" expected_response = {"id": expected_user_id} mock_zoom_list_users = mocker.patch.object(client, "zoom_list_users", return_value=expected_response) from Zoom import zoom_get_user_id_by_email result = zoom_get_user_id_by_email(client, email) mock_zoom_list_users.assert_called_with(page_size=50, url_suffix=f"users/{email}") assert result == expected_user_id def test_zoom_get_user_email_by_id(mocker): """ Given - client When - get user email address by their user ID Then - Validate that the get_user_email_by_id function is called with the correct arguments Validate the command results """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") user_id = "user_id" expected_user_email = "user@example.com" expected_response = {"email": expected_user_email} mock_zoom_list_users = mocker.patch.object(client, "zoom_list_users", return_value=expected_response) from Zoom import zoom_get_user_email_by_id result = zoom_get_user_email_by_id(client, user_id) mock_zoom_list_users.assert_called_with(page_size=1, url_suffix=f"users/{user_id}") assert result == expected_user_email def test_zoom_send_notification_command(mocker): """ Given - client When - send message to channel Then - Validate that the zoom_send_message function is called with the correct arguments Validate the command results including outputs and readable output """ client = Client( base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret", bot_client_id="mockclient", bot_client_secret="mocksecret", ) client.bot_jid = "mock_bot" expected_request_payload = { "robot_jid": "mock_bot", "to_jid": "channel1@xmpp.zoom.us", "account_id": "mockaccount", "content": {"head": {"type": "message", "text": "Hello"}}, } expected_response = { "message_id": "message_id", } mock_send_chat_message = mocker.patch.object(client, "zoom_send_notification") mock_send_chat_message.return_value = expected_response from Zoom import send_notification result = send_notification( client, user_id="user1", message="Hello", to="channel1", ) assert result.readable_output == "Message sent to Zoom successfully. Message ID is: message_id" assert mock_send_chat_message.call_args[0][1] == expected_request_payload def test_zoom_delete_user_token_command(mocker): """ Given - Zoom client When - zoom-delete-user-token has called Then - Validate that the zoom_delete_user_token function is called with the correct arguments Validate the command results return the correct readable output """ client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Client, "generate_oauth_token") user_id = "mock_user_id" zoom_delete_user_token_mock = mocker.patch.object(client, "zoom_delete_user_token") from Zoom import zoom_delete_user_token_command result = zoom_delete_user_token_command(client, user_id=user_id) zoom_delete_user_token_mock.assert_called_with(f"/users/{user_id}/token") assert result.readable_output == "User SSO token for user mock_user_id is deleted" @pytest.mark.parametrize( "channel_name, investigation_id, expected_result", [ ("Channel1", None, "JID1"), # Scenario 1: Find by channel_name (None, "Incident123", "JID1"), # Scenario 2: Find by investigation_id ("NonExistentChannel", None, None), # Scenario 3: Channel not found ], ) def test_get_channel_jid_by_channel_name(channel_name, investigation_id, expected_result, mocker): """ Given different scenarios with channel_name and investigation_id parameters, When calling the get_channel_jid_from_context function, Then validate that the function returns the expected result. """ # Mock integration context Zoom.CACHE_EXPIRY = False mock_integration_context = { "mirrors": json.dumps( [ {"channel_name": "Channel1", "channel_jid": "JID1", "investigation_id": "Incident123"}, {"channel_name": "Channel2", "channel_jid": "JID2", "investigation_id": "Incident123"}, ] ) } mocker.patch.object(demisto, "getIntegrationContext", return_value=mock_integration_context) # Call the function from Zoom import get_channel_jid_from_context result = get_channel_jid_from_context(channel_name, investigation_id) # Assert the result assert result == expected_result # Test cases for check_authentication_bot_parameters @pytest.mark.parametrize( "bot_Jid, client_id, client_secret, expected_exception", [ ("bot_Jid", "client_id", "client_secret", None), # Scenario 1: All parameters provided (None, None, None, None), # Scenario 2: All parameters None ("bot_Jid", None, None, DemistoException), # Scenario 3: bot_Jid provided, others None (None, "client_id", None, DemistoException), # Scenario 4: client_id provided, others None (None, None, "client_secret", DemistoException), # Scenario 5: client_secret provided, others None ], ) def test_check_authentication_bot_parameters(bot_Jid, client_id, client_secret, expected_exception): """ Given different scenarios with bot_Jid, client_id, and client_secret parameters, When calling the check_authentication_bot_parameters function, Then validate that the function raises the expected exception or returns without raising an exception. """ from Zoom import check_authentication_bot_parameters if expected_exception: with pytest.raises(expected_exception): check_authentication_bot_parameters(bot_Jid, client_id, client_secret) else: check_authentication_bot_parameters(bot_Jid, client_id, client_secret) def test_get_admin_user_id_from_token(mocker): """ Given a mock client with a zoom_get_admin_user_id_from_token method, When calling the get_admin_user_id_from_token function, Then validate that the function returns the expected user ID. """ # Create a mock client client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(client, "zoom_get_admin_user_id_from_token", return_value={"id": "mock_user_id"}) # Call the function from Zoom import get_admin_user_id_from_token result = get_admin_user_id_from_token(client) # Assert the result assert result == "mock_user_id" def test_mirror_investigation_create_new_channel(mocker): """ Given a mock client and relevant arguments, When calling the mirror_investigation function to create a new channel, Then validate that the function returns the expected CommandResults. """ Zoom.MIRRORING_ENABLED = True Zoom.LONG_RUNNING = True client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") client.bot_jid = "mock_jid" mocker.patch.object(client, "zoom_send_notification") mocker.patch.object(Zoom, "get_admin_user_id_from_token", return_value="mock_user_id") mocker.patch.object( Zoom, "zoom_create_channel_command", return_value=CommandResults(outputs={"jid": "mock_jid", "id": "mock_id"}) ) mocker.patch.object(demisto, "demistoUrls", return_value={"server": "mock_server_url"}) # mocker.patch.object(client, 'botJid', return_value='bot_jid_mock') # Test data args = { "type": "all", "direction": "Both", "channelName": "mirror-channel", "autoclose": True, } # Call the function from Zoom import mirror_investigation result = mirror_investigation(client, **args) # Assert the result assert "Investigation mirrored successfully" in result.readable_output @pytest.mark.asyncio async def test_check_and_handle_entitlement(mocker): """ Test the asynchronous function check_and_handle_entitlement. Given: - Input parameters for the function: text, message_id, user_name. When: - Calling the asynchronous function check_and_handle_entitlement with the given input parameters. Then: - Validate that the function behaves as expected and returns the expected result. """ # Mock integration context mock_integration_context = { "messages": json.dumps( [ { "message_id": "MessageID123", "entitlement": "3dcaae6d-d4d2-45b3-81a7-834bce779009@2b03d219-bbac-4333-84a2-d329d7296baa", "reply": "thanks", "expiry": "2023-08-29 12:32:40", "sent": "2023-08-29 12:27:42", "default_response": "NoResponse", } ] ) } mocker.patch.object(demisto, "getIntegrationContext", return_value=mock_integration_context) Zoom.CACHE_EXPIRY = False # Define the input parameters for the function text = "Entitlement Text" message_id = "MessageID123" user_name = "User123" user_id = "user123@example.com" # Call the async function and await its result from Zoom import check_and_handle_entitlement result = await check_and_handle_entitlement(text, message_id, user_name, user_id) assert result == "thanks" # Adjust the expected reply as needed @pytest.mark.parametrize( "entitlement, expected_result", [ ("guid123@incident456|task789", ("guid123", "incident456", "task789")), # Scenario 1: Full entitlement ("guid123@incident456", ("guid123", "incident456", "")), # Scenario 2: No task ID ("guid123@", ("guid123", "", "")), # Scenario 3: No incident ID or task ID ], ) def test_extract_entitlement(entitlement, expected_result): """ Test the extract_entitlement function. Given: - Input entitlement string. When: - Calling the extract_entitlement function with the given input entitlement. Then: - Validate that the function correctly extracts the entitlement components: guid, incident_id, and task_id. """ from Zoom import extract_entitlement result = extract_entitlement(entitlement) # Assert the result against the expected outcome assert result == expected_result # @pytest.mark.asyncio # async def test_check_for_unanswered_questions(mocker): # mock_integration_context = { # 'messages': json.dumps([ # { # 'message_id': 'MessageID1', # 'expiry': '2023-08-29 12:00:00', # 'default_response': 'DefaultResponse1' # }, # { # 'message_id': 'MessageID2', # 'expiry': '2023-08-29 14:00:00', # 'default_response': 'DefaultResponse2' # }, # ]) # } # mocker.patch.object(demisto, 'getIntegrationContext', return_value=mock_integration_context) @pytest.mark.asyncio async def test_answer_question(mocker): """ Test the answer_question function. Given: - A mocked question dictionary. When: - Calling the answer_question function with the mocked question. Then: - Validate that the function correctly handles the entitlement and returns the incident_id. """ mock_question = {"entitlement": "guid123@incident456|task789", "to_jid": "ToJID123"} Zoom.CLIENT = Client( base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret" ) Zoom.CLIENT.bot_jid = "mock_bot_id" mocker.patch.object(Zoom, "process_entitlement_reply") from Zoom import answer_question result = await answer_question("Answer123", mock_question, "user@example.com") assert result == "incident456" @pytest.mark.asyncio async def test_process_entitlement_reply(mocker): """ Test the process_entitlement_reply function. Given: - Mocked input parameters. When: - Calling the process_entitlement_reply function with the mocked parameters. Then: - Validate that the function correctly prepares and sends a Zoom notification. """ # Mocked input parameters mock_entitlement_reply = "Entitlement Reply" mock_account_id = "mock_account_id" mock_robot_jid = "mock_robot_jid" mock_to_jid = "mock_to_jid" client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") # Mock the CLIENT.zoom_send_notification function Zoom.CLIENT = client mock_zoom_send_notification = mocker.AsyncMock() mock_zoom_send_notification = mocker.patch.object(Zoom, "zoom_send_notification_async") # Call the function with the mocked parameters from Zoom import process_entitlement_reply await process_entitlement_reply(mock_entitlement_reply, mock_account_id, mock_robot_jid, mock_to_jid) # Assert that the CLIENT.zoom_send_notification function was called with the correct arguments mock_zoom_send_notification.assert_called_with( client, "/im/chat/messages", { "content": {"body": [{"type": "message", "text": mock_entitlement_reply}]}, "to_jid": mock_to_jid, "robot_jid": mock_robot_jid, "account_id": mock_account_id, }, ) # Test cases @pytest.mark.asyncio async def test_close_channel(mocker): """ Test the close_channel function Given: - Mocked input parameters. When: - Calling the close_channel function. Then: - Ensure that the function successfully closes the channel. """ mock_integration_context = { "mirrors": json.dumps( [ { "channel_name": "Channel1", "channel_jid": "JID1", "channel_id": "ID1", "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, }, { "channel_name": "Channel2", "channel_jid": "JID2", "channel_id": "ID2", "investigation_id": "Incident123", "mirror_direction": "both", "auto_close": True, }, ] ) } client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret") mocker.patch.object(Zoom, "zoom_delete_channel_command") mocker.patch.object(demisto, "mirrorInvestigation") mocker.patch.object(Zoom, "get_integration_context", return_value=mock_integration_context) mocker.patch.object(Zoom, "set_to_integration_context_with_retries") mocker.patch.object(Zoom, "get_admin_user_id_from_token", return_value="mock_user_id") mocker.patch.object(Zoom, "find_mirror_by_investigation", return_value={"channel_id": "ID1"}) from Zoom import close_channel result = close_channel(client) assert result == "Channel successfully deleted." @pytest.mark.parametrize( "event_type, expected_status", [ ("endpoint.url_validation", status.HTTP_200_OK), ("interactive_message_actions", status.HTTP_200_OK), ("invalid_event_type", status.HTTP_400_BAD_REQUEST), ], ) @pytest.mark.asyncio async def test_handle_zoom_response(event_type, expected_status, mocker): """ Test the handle_zoom_response function with different event types and payload conditions. Given: - Mocked request object. - Mocked event_url_validation, check_and_handle_entitlement, process_entitlement_reply, and handle_mirroring functions. - Parameters for event types and payload conditions. When: - Calling the handle_zoom_response function with different event types and payload conditions. Then: - Ensure that the function returns the expected response status code. """ mock_request = mocker.Mock(spec=Request) json_res = {"plainToken": 123, "encryptedToken": 123} mocker.patch("Zoom.event_url_validation", return_value=json_res) mocker.patch("Zoom.check_and_handle_entitlement") mocker.patch("Zoom.process_entitlement_reply") mocker.patch("Zoom.handle_mirroring") mocker.patch("Zoom.zoom_get_user_email_by_id", return_value="mock_user_email") mocker.patch.object(demisto, "params", return_value={"credentials": {"identifier": "test", "password": "testpass"}}) # Create a mock HTTPBasicCredentials object mock_credentials = HTTPBasicCredentials(username="test", password="testpass") Zoom.SECRET_TOKEN = "token" from Zoom import handle_zoom_response mock_request.json.return_value = { "event": event_type, "payload": { "accountId": "mock_accountid", "actionItem": {"text": "no", "value": "no", "action": "command"}, "messageId": "message_id", "robotJid": "robot_jid", "toJid": "mock_jid", "userName": "admin zoom", "userId": "mock_userId", }, } response = await handle_zoom_response(mock_request, mock_credentials) assert response.status_code == expected_status @pytest.mark.asyncio async def test_event_url_validation(): Zoom.SECRET_TOKEN = "secret_token" # Define the payload for testing payload = {"plainToken": "plain_token"} # Calculate the expected signature import hashlib import hmac hash_object = hmac.new(Zoom.SECRET_TOKEN.encode("utf-8"), msg=payload["plainToken"].encode("utf-8"), digestmod=hashlib.sha256) expected_signature = hash_object.hexdigest() from Zoom import event_url_validation response = await event_url_validation(payload) # Verify that the response matches the expected signature assert response == {"plainToken": payload["plainToken"], "encryptedToken": expected_signature} @pytest.mark.asyncio async def test_handle_text(mocker): # Create mock arguments investigation_id = "123" text = "Hello, this is a test message" operator_email = "test@example.com" operator_name = "Test User" MESSAGE_FOOTER = "\n**From Zoom**" from Zoom import handle_text_received_from_zoom with patch("Zoom.demisto") as mock_demisto: # Call the function await handle_text_received_from_zoom(investigation_id, text, operator_email, operator_name) # Assert that the `demisto.addEntry` method was called with the expected arguments mock_demisto.addEntry.assert_called_once_with( id=investigation_id, entry=text, username=operator_name, email=operator_email, footer=MESSAGE_FOOTER, # Assuming MESSAGE_FOOTER is defined in your module ) def test_save_entitlement(): # Define test inputs entitlement = "Test Entitlement" message_id = "123" reply = "Test Reply" expiry = "2023-09-09" default_response = "Default Response" to_jid = "user@example.com" SYNC_CONTEXT = True OBJECTS_TO_KEYS = { "messages": "entitlement", } # Mock the required functions (get_integration_context, set_to_integration_context_with_retries) and any other dependencies with ( patch("Zoom.get_integration_context") as mock_get_integration_context, patch("Zoom.set_to_integration_context_with_retries") as mock_set_integration_context, ): # Mock the return values of the mocked functions mock_get_integration_context.return_value = {"messages": []} fixed_timestamp = "2023-09-09 20:08:50" with freeze_time(fixed_timestamp): from Zoom import save_entitlement # Call the function to be tested save_entitlement(entitlement, message_id, reply, expiry, default_response, to_jid) # Define the expected data to be added to integration context expected_data = { "messages": [ { "message_id": message_id, "entitlement": entitlement, "reply": reply, "expiry": expiry, "sent": fixed_timestamp, "default_response": default_response, "to_jid": to_jid, } ] } # Assert that the mocked functions were called with the expected arguments mock_get_integration_context.assert_called_once_with(SYNC_CONTEXT) mock_set_integration_context.assert_called_once_with(expected_data, OBJECTS_TO_KEYS, SYNC_CONTEXT)