Microsoft Graph Calendar

O365 Outlook Calendar enables you to create and manage different calendars and events according to your requirements.

IT Services · Microsoft Graph Calendar

Details

IDMicrosoft Graph Calendar
ProviderMicrosoft
CategoryIT Services
From Version5.0.0
Docker Imagedemisto/crypto:1.0.0.5490413
Supported ModulesAgentix Cloud Runtime Security XSIAM EDR Cortex Cloud

README

Use the O365 Outlook Calendar integration to create, and manage different calendars and events according to your requirements.

Authentication

For more details about the authentication used in this integration, see Microsoft Integrations - Authentication.

Required Permissions

  • Directory.ReadWrite.All - Delegated
  • Directory.ReadWrite.All - Application
  • Group.ReadWrite.All - Application
  • Calendars.Read - Delegated
  • Calendars.Read - Application
  • Calendars.ReadWrite - Delegated
  • Calendars.ReadWrite - Application

Configure O365 Outlook Calendar on Cortex XSOAR

  1. Navigate to Settings > Integrations  > Servers & Services.
  2. Search for O365 Outlook Calendar.
  3. Click Add instance to create and configure a new integration instance.
    • Name: a textual name for the integration instance.
    • Server URL
    • ID for more details see cortex xsoar platform when configuring the integration instance
    • Token for more details see cortex xsoar platform when configuring the integration instance
    • Key for more details see cortex xsoar platform when configuring the integration instance
    • Certificate Thumbprint
    • Private Key
    • Default user
    • Trust any certificate (not secure)
    • Use system proxy settings
  4. Click Test to validate the new instance.

Commands

You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. After you successfully execute a command, a DBot message appears in the War Room with the command details.

  1. Get all calendars for a user: msgraph-calendar-list-calendars
  2. Get one user's calendar: msgraph-calendar-get-calendar
  3. Get a calendar's list of events: msgraph-calendar-list-events
  4. Get an event by ID: msgraph-calendar-get-event
  5. Create a new event: msgraph-calendar-create-event
  6. Update an existing event: msgraph-calendar-update-event
  7. Delete an existing event: msgraph-calendar-delete-event

1. Get all calendars for a user


Gets all calendars of a user.

Base Command

msgraph-calendar-list-calendars

Input
Argument Name Description Required
user The user ID or userPrincipalName. Optional
order_by Sorts the order of the returned items from Microsoft Graph. Optional
next_link The link for the next page of results, if it exists. Follow this link for more details. Optional
top Specifies the page size of the result set. Optional

 

Context Output
Path Type Description
MSGraphCalendar.Calendar.Name String The name of the calendar.
MSGraphCalendar.Calendar.CanShare Boolean Whether the user has permission to share the calendar. Only the user who created the calendar can share.
MSGraphCalendar.Calendar.CanEdit Boolean Whether the user can write to the calendar (this is true for the user who created the calendar and for a user who has been granted access to a shared calendar).
MSGraphCalendar.Calendar.ChangeKey String Identifies the version of the calendar object. Every time the calendar is changed, the changeKey changes as well. This allows the exchange to apply changes to the correct version of the object. Read-only.
MSGraphCalendar.Calendar.Owner Unknown The user who created or added the calendar.
MSGraphCalendar.Calendar.ID String The unique ID of the calendar. Read-only.
MSGraphCalendar.Calendar.CanViewPrivateItems Boolean Whether the user can read calendar items that have been marked private.

 

Command Example
!msgraph-calendar-list-calendars user=someemail@domain.com
Context Example
{
    "MSGraphCalendar.Calendar": [
        {
            "CanEdit": true,
            "CanShare": true,
            "CanViewPrivateItems": true,
            "ChangeKey": "Some_Change_Key",
            "ID": "Some_ID",
            "Name": "Calendar",
            "Owner": {
                "address": "someemail@domain.com",
                "name": "User Name"
            }
        },
        {
            "CanEdit": false,
            "CanShare": false,
            "CanViewPrivateItems": true,
            "ChangeKey": "Some_Change_Key",
            "ID": "Some_ID",
            "Name": "United States holidays",
            "Owner": {
                "address": "someemail@domain.com",
                "name": "User Name"
            }
        },
        {
            "CanEdit": false,
            "CanShare": false,
            "CanViewPrivateItems": true,
            "ChangeKey": "Some_Change_Key",
            "ID": "Some_ID",
            "Name": "Birthdays",
            "Owner": {
                "address": "someemail@domain.com",
                "name": "User Name"
            }
        }
    ]
}
Human Readable Output

Calendar:

Name Owner Name Owner Address ID
Calendar User Name someemail@domain.com Some_ID
United States holidays User Name someemail@domain.com Some_ID
Birthdays User Name someemail@domain.com Some_ID

2. Get one user's calendar


Returns a specific user's calendar.

Base Command

msgraph-calendar-get-calendar

Input
Argument Name Description Required
user The user's ID or the userPrincipalName. Optional
calendar_id The calendar's ID or name. If not specified, it retrieves the user's default calendar. Optional

 

Context Output
Path Type Description
MSGraphCalendar.Calendar.Name String The calendar's name.
MSGraphCalendar.Calendar.CanShare Boolean Whether the user has permission to share the calendar. Only the user who created the calendar can share it.
MSGraphCalendar.Calendar.CanEdit Boolean Whether the user can write to the calendar (true for the user who created the calendar and for a user who has been shared a calendar and granted write access).
MSGraphCalendar.Calendar.ChangeKey String Identifies the version of the calendar object. Every time the calendar is changed, the changeKey changes as well. This allows the exchange to apply changes to the correct version of the object. Read-only.
MSGraphCalendar.Calendar.Owner Unknown The user who created or added the calendar.
MSGraphCalendar.Calendar.ID String The unique ID of the calendar. Read-only.
MSGraphCalendar.Calendar.CanViewPrivateItems unknown Whether the user can read calendar items that have been marked private.

 

Command Example
!msgraph-calendar-get-calendar
Human Readable Output

3. Get a calendar's list of events


Returns a list of events from a calendar.

Base Command

msgraph-calendar-list-events

Input
Argument Name Description Required
user The user's ID or userPrincipalName. Optional
calendar_id The calendar ID or name. If not provided, the default calendar is used. Optional
order_by Sorts the order of the items returned from Microsoft Graph. Optional
next_link Link for the next page of results, if it exists. Follow this link for more details. Optional
top Specifies the page size of the result set. Optional
filter_by Filter Results. Follow this link for more details. Optional

 

Context Output
Path Type Description
MSGraphCalendar.ID Unknown The user's ID.
MSGraphCalendar.DisplayName Unknown The display name of the user.
MSGraphCalendar.GivenName Unknown The given name of the user.
MSGraphCalendar.BusinessPhones Unknown The business phone numbers of the user.
MSGraphCalendar.JobTitle Unknown The job title of the user.
MSGraphCalendar.Mail Unknown The mail address of the user.
MSGraphCalendar.MobilePhone Unknown The mobile phone number of the user.
MSGraphCalendar.OfficeLocation Unknown The location of the office of the user.
MSGraphCalendar.PreferredLanguage Unknown The user's preferred language.
MSGraphCalendar.Surname Unknown The user's surname.
MSGraphCalendar.UserPrincipalName Unknown The user's principal name.

 

Command Example
!msgraph-calendar-list-events
Human Readable Output

4. Get an event by ID


Returns an event based on its ID.

Base Command

msgraph-calendar-get-event

Input
Argument Name Description Required
user The user's ID or the userPrincipalName. Optional
event_id The ID of the event. Required

 

Context Output
Path Type Description
MSGraphCalendar.Event.OriginalStartTimeZone String The start time zone that was set when the event was created.
MSGraphCalendar.Event.HasAttachments Boolean Whether the event has attachments.
MSGraphCalendar.Event.ResponseRequested Boolean Whether the sender requests a response when the event is accepted or declined.
MSGraphCalendar.Event.WebLink String The URL used to open the event in Outlook on the web.
MSGraphCalendar.Event.Recurrence Unknown The recurrence pattern for the event.
MSGraphCalendar.Event.Start Unknown The starting date, time, and time zone of the event. By default, the start time is in UTC.
MSGraphCalendar.Event.End Unknown The date, time, and time zone that the event ends. By default, the end time is in UTC.
MSGraphCalendar.Event.Location Unknown The location of the event.
MSGraphCalendar.Event.Attendees Unknown The list of attendees for the event.
MSGraphCalendar.Event.Type String The event type. For example, singleInstance, occurrence, exception, seriesMaster. Read-only.
MSGraphCalendar.Event.ResponseStatus.response Unknown Indicates the response type sent in response to an event message.
MSGraphCalendar.Event.Importance String The importance of the event. For example, low, normal, high.
MSGraphCalendar.Event.ICalUId String A unique identifier that is shared by all instances of an event across different calendars.
MSGraphCalendar.Event.IsCancelled Boolean Whether the event has been canceled.
MSGraphCalendar.Event.IsAllDay Boolean Whether the event lasts all day.
MSGraphCalendar.Event.ReminderMinutesBeforeStart Number The number of minutes before the event start time of the reminder alert.
MSGraphCalendar.Event.LastModifiedDateTime String The last time the event was modified, using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.OriginalEndTimeZone String The end time zone that was set when the event was created.
MSGraphCalendar.Event.CreatedDateTime String The date the event was created using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 would be: '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.ChangeKey String Identifies the version of the event object. Every time the event is changed, the ChangeKey changes as well. This allows the Exchange to apply changes to the correct version of the object.
MSGraphCalendar.Event.ID String The ID of the event.
MSGraphCalendar.Event.IsOrganizer Boolean Whether the message sender is also the organizer.
MSGraphCalendar.Event.Sensitivity String The sensitivity of the event. Possible values are: normal, personal, private, confidential.
MSGraphCalendar.Event.IsReminderOn Boolean Whether an alert is set to remind the user of the event.
MSGraphCalendar.Event.Organizer Unknown The organizer of the event.
MSGraphCalendar.Event.Subject String The text of the event's subject line.
MSGraphCalendar.Event.OnlineMeetingUrl Unknown A URL for an online meeting, which is used when an organizer specifies an event as an online meeting, such as a Skype meeting. Read-only.

 

Command Example
!msgraph-calendar-get-event user="someemail@domain.com" event_id=Some_ID
Context Example
{
    "MSGraphCalendar.Event": [
        {
            "@Odata.Context": "https://graph.microsoft.com/v1.0/$metadata#users('oren%40demistodev.onmicrosoft.com')/calendar/events/$entity",
            "Attendees": [
                {
                    "emailAddress": {
                        "address": "someemail@domain.com",
                        "name": "User Name"
                    },
                    "status": {
                        "response": "none",
                        "time": "0001-01-01T00:00:00Z"
                    },
                    "type": "required"
                }
            ],
            "Body": {
                "content": "\r\n\r\n\r\n\r\n
This event was created by MSGraph integration
\r\n\r\n\r\n", "contentType": "html" }, "BodyPreview": "This event was created by MSGraph integration", "Categories": [], "ChangeKey": "Some_Change_Key", "CreatedDateTime": "2019-12-30T14:16:47.4108451Z", "End": { "dateTime": "2022-11-11T15:30:00.0000000", "timeZone": "UTC" }, "HasAttachments": false, "ICalUId": "040000008200E00074C5B7101A82E00800000000373066C51BBFD501000000000000000010000000D3EB65FAAFB082478A64C036CFE6783A", "ID": "Some_ID", "Importance": "normal", "IsAllDay": false, "IsCancelled": false, "IsOrganizer": true, "IsReminderOn": true, "LastModifiedDateTime": "2019-12-30T14:16:48.5891688Z", "Location": { "displayName": "Tel Aviv", "locationType": "default", "uniqueId": "Tel Aviv", "uniqueIdType": "private" }, "Locations": [ { "displayName": "Tel Aviv", "locationType": "default", "uniqueId": "Tel Aviv", "uniqueIdType": "private" } ], "OnlineMeetingUrl": null, "Organizer": { "emailAddress": { "address": "someemail@domain.com", "name": "User Name" } }, "OriginalEndTimeZone": "Asia/Jerusalem", "OriginalStartTimeZone": "Asia/Jerusalem", "Recurrence": null, "ReminderMinutesBeforeStart": 15, "ResponseRequested": true, "ResponseStatus": { "response": "organizer", "time": "0001-01-01T00:00:00Z" }, "Sensitivity": "normal", "SeriesMasterId": null, "ShowAs": "busy", "Start": { "dateTime": "2022-11-11T15:00:00.0000000", "timeZone": "UTC" }, "Subject": "test - delete", "Type": "singleInstance", "WebLink": "https://outlook.office365.com/owa/?itemid=AAMkADMzZWNjMjBkLTE2ZGQtNDE1NS05OTg3LTI5ZTRlY2Q5YjFiMgBGAAAAAACtWsHs6cTlRYm91jJyqUgDBwCPVsAqlO3YRKNF6ZoON8u7AAAAAAENAACPVsAqlO3YRKNF6ZoON8u7AACqxAGGAAA%3D&exvsurl=1&path=/calendar/item" } ] }
Human Readable Output

Event - test - delete

Subject Organizer Attendees Start End ID
test - delete User Name User Name 2022-11-11T15:00:00.0000000 2022-11-11T15:30:00.0000000 Some_ID

5. Create a new event


Creates a new event.

Base Command

msgraph-calendar-create-event

Input
Argument Name Description Required
user The user's ID or userPrincipalName. Optional
calendar_id The unique ID of the calendar or name. If not provided, the default calendar is used. Optional
attendees The collection of attendees for the event. Optional
body The body of the message associated with the event in HTML or text format. Optional
subject The text of the event's subject line. Optional
location The location of the event for an online meeting, such as a Skype meeting. Read-only. Optional
end The date and time the event ends. For example, '2017-05-28T12:00:00'. By default, the start time is in UTC. Optional
original_end_time_zone The end time zone that was set when the event was created. Optional
original_start The original start time of the calendar item using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z' Optional
start The date and time the event starts at, for example '2017-05-28T12:00:00'. By default, the start time is in UTC. Optional
time_zone Represents a time zone. For example, 'Pacific Standard Time'. Follow this link for more information. Optional
original_start_time_zone The start time zone that was set when the event was created. Optional

 

Context Output
Path Type Description
MSGraphCalendar.Event.OriginalStartTimeZone String The start time zone that was set when the event was created.
MSGraphCalendar.Event.HasAttachments Boolean Whether the event has attachments.
MSGraphCalendar.Event.ResponseRequested Boolean Whether the sender would like a response when the event is accepted or declined.
MSGraphCalendar.Event.WebLink String The URL used to open the event in Outlook on the web.
MSGraphCalendar.Event.Recurrence Unknown The recurrence pattern for the event.
MSGraphCalendar.Event.Start Unknown The date, time, and time zone that the event starts. By default, the start time is in UTC.
MSGraphCalendar.Event.End Unknown The starting date, time, and time zone of the event. By default, the start time is in UTC.
MSGraphCalendar.Event.Location Unknown The location of the event.
MSGraphCalendar.Event.Attendees Unknown The collection of attendees for the event.
MSGraphCalendar.Event.Type String The event type. For example, singleInstance, occurrence, exception, seriesMaster. Read-only.
MSGraphCalendar.Event.ResponseStatus.response Unknown Indicates the type of response sent in response to an event message.
MSGraphCalendar.Event.Importance String The importance of the event. For example, low, normal, high.
MSGraphCalendar.Event.ICalUId String A unique identifier that is shared by all instances of an event across different calendars.
MSGraphCalendar.Event.IsCancelled Boolean Whether the event has been canceled.
MSGraphCalendar.Event.IsAllDay Boolean Whether the event lasts all day.
MSGraphCalendar.Event.ReminderMinutesBeforeStart Number The number of minutes before the event start time of the reminder alert.
MSGraphCalendar.Event.LastModifiedDateTime String Last modified time and date of the event using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.OriginalEndTimeZone String The end time zone that was set when the event was created.
MSGraphCalendar.Event.CreatedDateTime String The time and date the event was created using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.ChangeKey String Identifies the version of the event object. Every time the event is changed, the ChangeKey changes as well. This allows the exchange to apply changes to the correct version of the object.
MSGraphCalendar.Event.ID String The event's ID.
MSGraphCalendar.Event.IsOrganizer Boolean Whether the message sender is also the organizer.
MSGraphCalendar.Event.Sensitivity String The sensitivity of the event. Possible values are: normal, personal, private, confidential.
MSGraphCalendar.Event.IsReminderOn Boolean Whether an alert is set to remind the user of the event.
MSGraphCalendar.Event.Organizer Unknown The organizer of the event.
MSGraphCalendar.Event.Subject String The text of the event's subject line.
MSGraphCalendar.Event.OnlineMeetingUrl Unknown A URL for an online meeting, which is used only when an organizer specifies an event as an online meeting, such as a Skype meeting. Read-only.

 

Command Example
!msgraph-calendar-create-event user="someemail@domain.com" calendar_id="Calendar" attendees="someemail@domain.com" body="This event was created by MSGraph integration" subject="test - delete" location="Tel Aviv" end="2022-12-11T17:30:00" start="2022-12-11T17:00:00" time_zone="Asia/Jerusalem"
Context Example
{
    "MSGraphCalendar.Event": [
        {
            "@Odata.Context": "https://graph.microsoft.com/v1.0/$metadata#users('oren%40demistodev.onmicrosoft.com')/calendars('Calendar')/events/$entity",
            "Attendees": [
                {
                    "emailAddress": {
                        "address": "someemail@domain.com",
                        "name": "User Name"
                    },
                    "status": {
                        "response": "none",
                        "time": "0001-01-01T00:00:00Z"
                    },
                    "type": "required"
                }
            ],
            "Body": {
                "content": "This event was created by MSGraph integration",
                "contentType": "text"
            },
            "BodyPreview": "This event was created by MSGraph integration",
            "Categories": [],
            "ChangeKey": "Some_Change_Key",
            "CreatedDateTime": "2019-12-30T14:19:48.7510847Z",
            "End": {
                "dateTime": "2022-12-11T17:30:00.0000000",
                "timeZone": "Asia/Jerusalem"
            },
            "HasAttachments": false,
            "ICalUId": "040000008200E00074C5B7101A82E0080000000055837C311CBFD501000000000000000010000000C8489B38018FA74DA3FD6E7D67B7DC54",
            "ID": "Some_ID",
            "Importance": "normal",
            "IsAllDay": false,
            "IsCancelled": false,
            "IsOrganizer": true,
            "IsReminderOn": true,
            "LastModifiedDateTime": "2019-12-30T14:19:48.7900629Z",
            "Location": {
                "displayName": "Tel Aviv",
                "locationType": "default",
                "uniqueId": "Tel Aviv",
                "uniqueIdType": "private"
            },
            "Locations": [
                {
                    "displayName": "Tel Aviv",
                    "locationType": "default",
                    "uniqueId": "Tel Aviv",
                    "uniqueIdType": "private"
                }
            ],
            "OnlineMeetingUrl": null,
            "Organizer": {
                "emailAddress": {
                    "address": "someemail@domain.com",
                    "name": "User Name"
                }
            },
            "OriginalEndTimeZone": "Asia/Jerusalem",
            "OriginalStartTimeZone": "Asia/Jerusalem",
            "Recurrence": null,
            "ReminderMinutesBeforeStart": 15,
            "ResponseRequested": true,
            "ResponseStatus": {
                "response": "organizer",
                "time": "0001-01-01T00:00:00Z"
            },
            "Sensitivity": "normal",
            "SeriesMasterId": null,
            "ShowAs": "busy",
            "Start": {
                "dateTime": "2022-12-11T17:00:00.0000000",
                "timeZone": "Asia/Jerusalem"
            },
            "Subject": "test - delete",
            "Type": "singleInstance",
            "WebLink": "https://outlook.office365.com/owa/?itemid=AAMkADMzZWNjMjBkLTE2ZGQtNDE1NS05OTg3LTI5ZTRlY2Q5YjFiMgBGAAAAAACtWsHs6cTlRYm91jJyqUgDBwCPVsAqlO3YRKNF6ZoON8u7AAAAAAENAACPVsAqlO3YRKNF6ZoON8u7AACqxAGJAAA%3D&exvsurl=1&path=/calendar/item"
        }
    ]
}
Human Readable Output

Event was created successfully:

Subject Organizer Attendees Start End ID
test - delete User Name User Name 2022-12-11T17:00:00.0000000 2022-12-11T17:30:00.0000000 Some_ID

6. Update an existing event


Updates an existing event.

Base Command

msgraph-calendar-update-event

Input
Argument Name Description Required
user The user's ID or userPrincipalName. Optional
event_id The event's ID. Required
attendees The collection of attendees for the event. Optional
body The body of the message associated with the event. It can be in HTML or text format. Optional
subject The text of the event's subject line. Optional
location The location of the event for an online meeting, such as a Skype meeting. Read-only. Optional
end The date and time the event ends. For example '2017-05-28T12:00:00'. By default, the start time is in UTC. Optional
original_end_time_zone The end time zone when the event was created. Optional
start The date and time the event starts. For example '2017-05-28T12:00:00'. By default, the start time is in UTC. Optional
time_zone Represents a time zone, for example, 'Pacific Standard Time'. For more information, see https://docs.microsoft.com/en-us/graph/api/resources/datetimetimezone?view=graph-rest-1.0 Optional
original_start The original start time of the calendar item, using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z' Optional
original_start_time_zone The start time zone when the event was created. Optional

 

Context Output
Path Type Description
MSGraphCalendar.Event.OriginalStartTimeZone String The start time zone that was set when the event was created.
MSGraphCalendar.Event.HasAttachments Boolean Whether the event has attachments.
MSGraphCalendar.Event.ResponseRequested Boolean Whether the sender requests a response when the event is accepted or declined.
MSGraphCalendar.Event.WebLink String The URL used to open the event in Outlook on the web.
MSGraphCalendar.Event.Recurrence Unknown The recurrence pattern for the event.
MSGraphCalendar.Event.Start Unknown The date, time, and time zone that the event starts. By default, the start time is in UTC.
MSGraphCalendar.Event.End Unknown The date, time, and time zone that the event ends. By default, the end time is in UTC.
MSGraphCalendar.Event.Location Unknown The location of the event.
MSGraphCalendar.Event.Attendees Unknown The collection of attendees for the event.
MSGraphCalendar.Event.Type String The event type. For example, singleInstance, occurrence, exception, seriesMaster. Read-only.
MSGraphCalendar.Event.ResponseStatus.response Unknown Indicates the type of response sent in response to an event message.
MSGraphCalendar.Event.Importance String The importance of the event. For example, low, normal, high.
MSGraphCalendar.Event.ICalUId String A unique identifier that is shared by all instances of an event across different calendars.
MSGraphCalendar.Event.IsCancelled Boolean Whether the event has been canceled.
MSGraphCalendar.Event.IsAllDay Boolean Whether the event lasts all day.
MSGraphCalendar.Event.ReminderMinutesBeforeStart Number The number of minutes before the event start time of the reminder alert.
MSGraphCalendar.Event.LastModifiedDateTime String The last time and date the event was modified using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.OriginalEndTimeZone String The end time zone that was set when the event was created.
MSGraphCalendar.Event.CreatedDateTime String The date and time the event was created using ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.ChangeKey String Identifies the version of the event object. Every time the event is changed, the ChangeKey changes as well. This allows the exchange to apply changes to the correct version of the object.
MSGraphCalendar.Event.ID String The ID of the event.
MSGraphCalendar.Event.IsOrganizer Boolean Whether the message sender is also the organizer.
MSGraphCalendar.Event.Sensitivity String The sensitivity of the event. Possible values are: normal, personal, private, confidential.
MSGraphCalendar.Event.IsReminderOn Boolean Whether an alert is set to remind the user of the event.
MSGraphCalendar.Event.Organizer Unknown The organizer of the event.
MSGraphCalendar.Event.Subject String The text of the event's subject line.
MSGraphCalendar.Event.OnlineMeetingUrl Unknown A URL for an online meeting, used only when an organizer specifies an event as an online meeting, such as a Skype meeting. Read-only.

 

Command Example
!msgraph-calendar-update-event user="someemail@domain.com" event_id=Some_ID subject="updated"
Context Example
{
    "MSGraphCalendar": [
        {
            "@Odata.Context": "https://graph.microsoft.com/v1.0/$metadata#users('oren%40demistodev.onmicrosoft.com')/calendar/events/$entity",
            "Attendees": [
                {
                    "emailAddress": {},
                    "status": {
                        "response": "none",
                        "time": "0001-01-01T00:00:00Z"
                    },
                    "type": "required"
                }
            ],
            "Body": {
                "content": "",
                "contentType": "text"
            },
            "BodyPreview": "",
            "Categories": [],
            "ChangeKey": "Some_Change_Key",
            "CreatedDateTime": "2019-12-30T14:16:47.4108451Z",
            "End": {
                "dateTime": "2022-11-11T15:30:00.0000000",
                "timeZone": "UTC"
            },
            "HasAttachments": false,
            "ICalUId": "040000008200E00074C5B7101A82E00800000000373066C51BBFD501000000000000000010000000D3EB65FAAFB082478A64C036CFE6783A",
            "ID": "Some_ID",
            "Importance": "normal",
            "IsAllDay": false,
            "IsCancelled": false,
            "IsOrganizer": true,
            "IsReminderOn": true,
            "LastModifiedDateTime": "2019-12-30T14:19:50.1373174Z",
            "Location": {
                "address": {},
                "coordinates": {},
                "displayName": "",
                "locationType": "default",
                "uniqueIdType": "unknown"
            },
            "Locations": [],
            "OnlineMeetingUrl": null,
            "Organizer": {
                "emailAddress": {
                    "address": "someemail@domain.com",
                    "name": "User Name"
                }
            },
            "OriginalEndTimeZone": "Asia/Jerusalem",
            "OriginalStartTimeZone": "Asia/Jerusalem",
            "Recurrence": null,
            "ReminderMinutesBeforeStart": 15,
            "ResponseRequested": true,
            "ResponseStatus": {
                "response": "organizer",
                "time": "0001-01-01T00:00:00Z"
            },
            "Sensitivity": "normal",
            "SeriesMasterId": null,
            "ShowAs": "busy",
            "Start": {
                "dateTime": "2022-11-11T15:00:00.0000000",
                "timeZone": "UTC"
            },
            "Subject": "updated",
            "Type": "singleInstance",
            "WebLink": "https://outlook.office365.com/owa/?itemid=AAMkADMzZWNjMjBkLTE2ZGQtNDE1NS05OTg3LTI5ZTRlY2Q5YjFiMgBGAAAAAACtWsHs6cTlRYm91jJyqUgDBwCPVsAqlO3YRKNF6ZoON8u7AAAAAAENAACPVsAqlO3YRKNF6ZoON8u7AACqxAGGAAA%3D&exvsurl=1&path=/calendar/item"
        }
    ]
}
Human Readable Output

Event:

Subject Organizer Attendees Start End ID
updated User Name None 2022-11-11T15:00:00.0000000 2022-11-11T15:30:00.0000000 Some_ID

7. Delete an existing event


Deletes an existing event.

Base Command

msgraph-calendar-delete-event

Input
Argument Name Description Required
user The user ID or userPrincipalName. Optional
event_id The event ID. Required

 

Context Output
Path Type Description
MSGraphCalendar.Event.OriginalStartTimeZone String The start time zone that was set when the event was created..
MSGraphCalendar.Event.HasAttachments Boolean Whether the event has attachments.
MSGraphCalendar.Event.ResponseRequested Boolean Whether the sender receives a response when the event is accepted or declined.
MSGraphCalendar.Event.WebLink String The URL used to open the event in Outlook on the web.
MSGraphCalendar.Event.Recurrence Unknown The recurrence pattern for the event.
MSGraphCalendar.Event.Start Unknown The date, time, and time zone that the event starts. By default, the start time is in UTC.
MSGraphCalendar.Event.End Unknown The date, time, and time zone that the event ends. By default, the end time is in UTC.
MSGraphCalendar.Event.Location Unknown The location of the event.
MSGraphCalendar.Event.Attendees Unknown The collection of attendees for the event.
MSGraphCalendar.Event.Type String The event type. For example, singleInstance, occurrence, exception, seriesMaster. Read-only.
MSGraphCalendar.Event.ResponseStatus.response Unknown Indicates the type of response sent in response to an event message.
MSGraphCalendar.Event.Importance String The importance of the event. For example, low, normal, high.
MSGraphCalendar.Event.ICalUId String A unique identifier that is shared by all instances of an event across different calendars.
MSGraphCalendar.Event.IsCancelled Boolean Whether the event has been canceled.
MSGraphCalendar.Event.IsAllDay Boolean Whether the event lasts all day.
MSGraphCalendar.Event.ReminderMinutesBeforeStart Number The number of minutes before the event start time of the reminder alert.
MSGraphCalendar.Event.LastModifiedDateTime String The time and date the event was last modified using the ISO 8601 format in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'
MSGraphCalendar.Event.OriginalEndTimeZone String The end time zone that was set when the event was created.
MSGraphCalendar.Event.CreatedDateTime String The time and date the event was created using ISO 8601 format and is always in UTC time. For example, midnight UTC on Jan 1, 2014 is '2014-01-01T00:00:00Z'.
MSGraphCalendar.Event.ChangeKey String Identifies the version of the event object. Every time the event is changed, the ChangeKey changes as well. This allows the exchange to apply changes to the correct version of the object.
MSGraphCalendar.Event.ID String The ID of the Event.
MSGraphCalendar.Event.IsOrganizer Boolean Whether the message sender is also the organizer.
MSGraphCalendar.Event.Sensitivity String The sensitivity of the event. Possible values are: normal, personal, private, confidential.
MSGraphCalendar.Event.IsReminderOn Boolean Whether an alert is set to remind the user of the event.
MSGraphCalendar.Event.Organizer Unknown The organizer of the event.
MSGraphCalendar.Event.Subject String The text of the event's subject line.
MSGraphCalendar.Event.OnlineMeetingUrl Unknown A URL for an online meeting, used only when an organizer specifies an event as an online meeting, such as a Skype meeting. Read-only.

 

Command Example
!msgraph-calendar-delete-event user="someemail@domain.com" event_id=Some_ID
Context Example
{
    "MSGraphCalendar.Event": {
        "@Odata.Context": "https://graph.microsoft.com/v1.0/$metadata#users('oren%40demistodev.onmicrosoft.com')/calendars('Calendar')/events/$entity",
        "Attendees": [
            {
                "emailAddress": {
                    "address": "someemail@domain.com",
                    "name": "User Name"
                },
                "status": {
                    "response": "none",
                    "time": "0001-01-01T00:00:00Z"
                },
                "type": "required"
            }
        ],
        "Body": {
            "content": "This event was created by MSGraph integration",
            "contentType": "text"
        },
        "BodyPreview": "This event was created by MSGraph integration",
        "Categories": [],
        "ChangeKey": "Some_Change_Key",
        "CreatedDateTime": "2019-12-30T14:16:47.4108451Z",
        "Deleted": true,
        "End": {
            "dateTime": "2022-11-11T17:30:00.0000000",
            "timeZone": "Asia/Jerusalem"
        },
        "HasAttachments": false,
        "ICalUId": "040000008200E00074C5B7101A82E00800000000373066C51BBFD501000000000000000010000000D3EB65FAAFB082478A64C036CFE6783A",
        "ID": "Some_ID",
        "Importance": "normal",
        "IsAllDay": false,
        "IsCancelled": false,
        "IsOrganizer": true,
        "IsReminderOn": true,
        "LastModifiedDateTime": "2019-12-30T14:16:47.4508223Z",
        "Location": {
            "displayName": "Tel Aviv",
            "locationType": "default",
            "uniqueId": "Tel Aviv",
            "uniqueIdType": "private"
        },
        "Locations": [
            {
                "displayName": "Tel Aviv",
                "locationType": "default",
                "uniqueId": "Tel Aviv",
                "uniqueIdType": "private"
            }
        ],
        "OnlineMeetingUrl": null,
        "Organizer": {
            "emailAddress": {
                "address": "someemail@domain.com",
                "name": "User Name"
            }
        },
        "OriginalEndTimeZone": "Asia/Jerusalem",
        "OriginalStartTimeZone": "Asia/Jerusalem",
        "Recurrence": null,
        "ReminderMinutesBeforeStart": 15,
        "ResponseRequested": true,
        "ResponseStatus": {
            "response": "organizer",
            "time": "0001-01-01T00:00:00Z"
        },
        "Sensitivity": "normal",
        "SeriesMasterId": null,
        "ShowAs": "busy",
        "Start": {
            "dateTime": "2022-11-11T17:00:00.0000000",
            "timeZone": "Asia/Jerusalem"
        },
        "Subject": "test - delete",
        "Type": "singleInstance",
        "WebLink": "https://outlook.office365.com/owa/?itemid=AAMkADMzZWNjMjBkLTE2ZGQtNDE1NS05OTg3LTI5ZTRlY2Q5YjFiMgBGAAAAAACtWsHs6cTlRYm91jJyqUgDBwCPVsAqlO3YRKNF6ZoON8u7AAAAAAENAACPVsAqlO3YRKNF6ZoON8u7AACqxAGGAAA%3D&exvsurl=1&path=/calendar/item"
    }
}
Human Readable Output

Event was deleted successfully.

8. msgraph-calendar-auth-reset


Run this command if for some reason you need to rerun the authentication process.

Base Command

msgraph-calendar-auth-reset

Input

There are no input arguments for this command. 

Context Output

There are no context output for this command.

 

Configuration parameters

  • url — Server URL (required)
  • auth_id — ID (received from the admin consent - see Detailed Instructions (?)
  • credentials_auth_id
  • tenant_id — Token (received from the admin consent - see Detailed Instructions (?) section)
  • credentials_tenant_id
  • enc_key — Key (received from the admin consent - see Detailed Instructions (?)
  • credentials_enc_key
  • certificate_thumbprint — Certificate Thumbprint
  • credentials_certificate_thumbprint
  • private_key — Private Key
  • use_managed_identities — Use Azure Managed Identities
  • managed_identities_client_id
  • default_user — Default user
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • self_deployed — Use a self-deployed Azure Application

Commands (8)

  • msgraph-calendar-auth-reset

    Run this command if for some reason you need to rerun the authentication process.

  • msgraph-calendar-create-event

    Creates a new event.

  • msgraph-calendar-delete-event

    Updates an existing event.

  • msgraph-calendar-get-calendar

    Retrieves one of user's Calendars.

  • msgraph-calendar-get-event

    Retrieves an event by event ID.

  • msgraph-calendar-list-calendars

    Retrieves a list of user Calendar.

  • msgraph-calendar-list-events

    Retrieves a list of Calendar's events.

  • msgraph-calendar-update-event

    Updates an existing event.

import urllib3
from CommonServerPython import *
from MicrosoftApiModule import *  # noqa: E402

# Disable insecure warnings
urllib3.disable_warnings()

INTEGRATION_CONTEXT_NAME = "MSGraphCalendar"
DEFAULT_PAGE_SIZE = 100
NO_OUTPUTS: dict = {}
APP_NAME = "ms-graph-calendar"
EVENT_HEADERS = ["Subject", "Organizer", "Attendees", "Start", "End", "ID"]
CALENDAR_HEADERS = ["Name", "Owner Name", "Owner Address", "ID"]


def camel_case_to_readable(cc: str | dict, fields_to_drop: list[str] = None) -> str | dict:
    """
    'camelCase' -> 'Camel Case' (text or dictionary keys)

    Args:
        cc: either a dictionary or a text to transform
        fields_to_drop: keys to drop from input dictionary

    Returns:
        A Camel Cased string of Dict.
    """
    if fields_to_drop is None:
        fields_to_drop = []
    if isinstance(cc, str):
        if cc == "id":
            return "ID"
        return "".join(" " + char if char.isupper() else char.strip() for char in cc).strip().title()

    elif isinstance(cc, dict):
        return {camel_case_to_readable(field): value for field, value in cc.items() if field not in fields_to_drop}
    return cc


def snakecase_to_camelcase(sc: str | dict, fields_to_drop: list[str] = None) -> str | dict:
    """
    'snake_case' -> 'snakeCase' (text or dictionary keys)

    Args:
        sc: either a dictionary or a text to transform
        fields_to_drop: keys to drop from input dictionary

    Returns:
        A connectedCamelCased string of Dict.
    """
    if fields_to_drop is None:
        fields_to_drop = []
    if isinstance(sc, str):
        return "".join([word.title() for word in sc.split("_")])

    elif isinstance(sc, dict):
        return {snakecase_to_camelcase(field): value for field, value in sc.items() if field not in fields_to_drop}
    return sc


def parse_events(raw_events: dict | list[dict]) -> tuple[list[dict], list[dict]]:
    """
    Parse Calendar Events json data coming from Microsoft Graph into Demisto readable format
    :param raw_events: raw events data
    """
    # Fields to filter, dropping to not bloat the incident context.
    fields_to_drop = ["@odata.etag", "color"]
    if not isinstance(raw_events, list):
        raw_events = [raw_events]

    readable_events, context_output = [], []
    for event in raw_events:
        event_readable: dict = camel_case_to_readable(event, fields_to_drop)  # type: ignore
        if "@removed" in event:
            event_readable["Status"] = "deleted"
        event_context = {field.replace(" ", ""): value for field, value in event_readable.items()}

        event_readable = {
            "Subject": event_readable.get("Subject"),
            "ID": event_readable.get("ID"),
            "Organizer": demisto.get(event_readable, "Organizer.emailAddress.name"),
            "Attendees": [att.get("emailAddress", {}).get("name") for att in event_readable.get("Attendees", [])],
            "Start": event_readable.get("Start", {}).get("dateTime"),
            "End": event_readable.get("End", {}).get("dateTime"),
        }
        readable_events.append(event_readable)
        context_output.append(event_context)

    return readable_events, context_output


def parse_calendar(raw_calendars: dict | list[dict]) -> tuple[list[dict], list[dict]]:
    """
    Parse Calendar json data coming from Microsoft Graph into Demisto readable format
    :param raw_calendars: raw calendars data
    """
    if not isinstance(raw_calendars, list):
        raw_calendars = [raw_calendars]

    readable_calendars, context_output = [], []
    for raw_calendar in raw_calendars:
        readable_calendar: dict = camel_case_to_readable(raw_calendar, ["@odata.context", "color"])  # type: ignore
        if "@removed" in readable_calendar:
            readable_calendar["Status"] = "deleted"
        context_calendar = {field.replace(" ", ""): value for field, value in readable_calendar.items()}

        readable_calendar = {
            "Name": readable_calendar.get("Name"),
            "Owner Name": readable_calendar.get("Owner", {}).get("name"),
            "Owner Address": readable_calendar.get("Owner", {}).get("address"),
            "ID": readable_calendar.get("ID"),
        }
        context_output.append(context_calendar)
        readable_calendars.append(readable_calendar)

    return readable_calendars, context_output


def process_event_params(
    body: str = "", start: str = "", end: str = "", time_zone: str = "", attendees: str = "", location: str = "", **other_params
) -> dict:
    # some parameters don't need any processing
    event_params: dict[str, str | dict | list[dict]] = other_params

    event_params["body"] = {"content": body}
    event_params["location"] = {"displayName": location}
    if start:
        event_params["start"] = {"dateTime": start, "timeZone": time_zone}
    if end:
        event_params["end"] = {"dateTime": end, "timeZone": time_zone}
    event_params["attendees"] = [{"emailAddress": {"address": attendee}} for attendee in attendees.split(",")]
    return event_params


class MsGraphClient:
    def __init__(
        self,
        tenant_id,
        auth_id,
        enc_key,
        app_name,
        base_url,
        verify,
        proxy,
        default_user,
        self_deployed,
        certificate_thumbprint,
        private_key,
        managed_identities_client_id,
    ):
        self.ms_client = MicrosoftClient(
            tenant_id=tenant_id,
            auth_id=auth_id,
            enc_key=enc_key,
            app_name=app_name,
            base_url=base_url,
            verify=verify,
            proxy=proxy,
            self_deployed=self_deployed,
            certificate_thumbprint=certificate_thumbprint,
            private_key=private_key,
            managed_identities_client_id=managed_identities_client_id,
            managed_identities_resource_uri=Resources.graph,
            command_prefix="msgraph-calendar",
        )

        self.default_user = default_user

    def test_function(self):
        """
        Performs basic GET request to check if the API is reachable and authentication is successful.

        Returns ok if successful.
        """
        self.ms_client.http_request(method="GET", url_suffix="users/")
        return "ok", NO_OUTPUTS, NO_OUTPUTS

    def get_calendar(self, user: str, calendar_id: str = None) -> dict:
        """Returns a single calendar by sending a GET request.

        Args:
        :argument user: the user id | userPrincipalName
        :argument calendar_id: calendar id  | name
        """
        if not user and not self.default_user:
            return_error(
                "No user was provided. Please make sure to enter the use either in the instance setting,"
                " or in the command parameter."
            )
        calendar_raw = self.ms_client.http_request(
            method="GET", url_suffix=f"users/{user}/calendar" + f"s/{calendar_id}" if calendar_id else ""
        )

        return calendar_raw

    def list_calendars(
        self, user: str, order_by: str = None, next_link: str = None, top: int = DEFAULT_PAGE_SIZE, filter_by: str = None
    ) -> dict:
        """
        Lists all calendars by sending a GET request.

        Args:
        :argument user: the user id | userPrincipalName
        :argument order_by: specify the sort order of the items returned from Microsoft Graph
        :argument next_link: link for the next page of results, if exists. See Microsoft documentation for more details.
            docs.microsoft.com/en-us/graph/api/event-list?view=graph-rest-1.0
        :argument top: specify the page size of the result set.
        filter_by: filters results.
        """
        params = {"$orderby": order_by} if order_by else {}
        if next_link:  # pagination
            calendars = self.ms_client.http_request(method="GET", full_url=next_link)
        elif filter_by:
            calendars = self.ms_client.http_request(
                method="GET", url_suffix=f"users/{user}/calendars?$filter={filter_by}&$top={top}", params=params
            )
        else:
            calendars = self.ms_client.http_request(method="GET", url_suffix=f"users/{user}/calendars?$top={top}", params=params)

        return calendars

    def list_events(
        self,
        user: str,
        calendar_id: str = "",
        order_by: str = None,
        next_link: str = None,
        top: int = DEFAULT_PAGE_SIZE,
        filter_by: str = None,
    ) -> dict:
        """
        Returns all events by sending a GET request.

        Args:
        :argument user: the user id | userPrincipalName
        :argument calendar_id: calendar id  | name
        :argument order_by: specify the sort order of the items returned from Microsoft Graph
        :argument next_link: the link for the next page of results. see Microsoft documentation for more details.
        :argument top: specify the page size of the result set.
        :argument filter_by: filters results.
        """
        calendar_url = f"{user}/calendars/{calendar_id}" if calendar_id else user
        params = {"$orderby": order_by} if order_by else {}
        if next_link:  # pagination
            events = self.ms_client.http_request(method="GET", full_url=next_link)
        elif filter_by:
            events = self.ms_client.http_request(
                method="GET", url_suffix=f"users/{calendar_url}/events?$filter={filter_by}&$top={top}", params=params
            )
        else:
            events = self.ms_client.http_request(
                method="GET", url_suffix=f"users/{calendar_url}/events?$top={top}", params=params
            )
        return events

    def get_event(self, user: str, event_id: str) -> dict:
        """
        Create a single event in a user calendar, or the default calendar of an Office 365 group.

        Args:
        :argument user: the user id | userPrincipalName
        :argument event_id: the event id
        """
        event = self.ms_client.http_request(method="GET", url_suffix=f"users/{user}/calendar/events/{event_id}")

        return event

    def create_event(self, user: str, calendar_id: str = "", **kwargs) -> dict:
        """
        Create a single event in a user calendar, or the default calendar of an Office 365 group.

        Args:
        :argument user: the user id | userPrincipalName
        :argument calendar_id: calendar id  | name

        Event Properties:
        :keyword attendees: The collection of attendees for the event.
        :keyword body: The body of the message associated with the event. It can be in HTML or text format.
        :keyword subject: The text of the event's subject line.
        :keyword location: The location of the event. an event as an online meeting such as a Zoom meeting. Read-only.
        :keyword end: The date, time, and time zone that the event ends. By default, the end time is in UTC.
        :keyword originalEndTimeZone: The end time zone that was set when the event was created.
        :keyword originalStart: The Timestamp type represents date and time using ISO 8601 format in UTC time.
         For example, midnight UTC on Jan 1, 2014 would look like this: '2014-01-01T00:00:00Z'
        :keyword originalStartTimeZone: The start time zone that was set when the event was created.
        """
        if calendar_id:
            event = self.ms_client.http_request(
                method="POST", url_suffix=f"/users/{user}/calendars/{calendar_id}/events", json_data=kwargs
            )
        else:
            event = self.ms_client.http_request(method="POST", url_suffix=f"users/{user}/calendar/events", json_data=kwargs)
        return event

    def update_event(self, user: str, event_id: str, **kwargs) -> dict:
        """
        Create a single event in a user calendar, or the default calendar of an Office 365 group.

        Args:
        :argument user: the user id | userPrincipalName
        :argument event_id: the event ID

        Event Properties:
        :keyword attendees: The collection of attendees for the event.
        :keyword body: The body of the message associated with the event. It can be in HTML or text format.
        :keyword subject:The text of the event's subject line.
        :keyword location: The location of the event.
         an event as an online meeting such as a Skype meeting. Read-only.
        :keyword end: The date, time, and time zone that the event ends. By default, the end time is in UTC.
        :keyword originalEndTimeZone: The end time zone that was set when the event was created.
        :keyword originalStart: The Timestamp type represents date and time using ISO 8601 format in UTC time.
         For example, midnight UTC on Jan 1, 2014 would look like this: '2014-01-01T00:00:00Z'
        :keyword originalStartTimeZone: The start time zone that was set when the event was created.
        """
        event = self.ms_client.http_request(
            method="PATCH", url_suffix=f"users/{user}/calendar/events/{event_id}", json_data=kwargs
        )
        return event

    def delete_event(self, user: str, event_id: str):
        """
        Delete a single event by sending a DELETE request.

        Args:
        :argument user: the user id | userPrincipalName
        :argument id: the event id
        """
        #  If successful, this method returns 204 No Content response code.
        #  It does not return anything in the response body.
        self.ms_client.http_request(method="DELETE", url_suffix=f"users/{user}/calendar/events/{event_id}", resp_type="text")


def list_events_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Lists all events and return outputs in Demisto's format.

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    events = client.list_events(**args)

    events_readable, events_outputs = parse_events(events.get("value"))  # type: ignore

    next_link_response = ""
    if "@odata.nextLink" in events:
        next_link_response = events["@odata.nextLink"]

    if next_link_response:
        entry_context = {
            f"{INTEGRATION_CONTEXT_NAME}.Event(val.ID === obj.ID).NextLink": next_link_response,
            f"{INTEGRATION_CONTEXT_NAME}.Event(val.ID === obj.ID)": events_outputs,
        }
        title = "Events (Note that there are more results. Please use the next_link argument to see them.):"
    else:
        entry_context = {f"{INTEGRATION_CONTEXT_NAME}.Event(val.ID === obj.ID)": events_outputs}
        title = "Events:"

    human_readable = tableToMarkdown(name=title, t=events_readable, headers=EVENT_HEADERS, removeNull=True)

    return human_readable, entry_context, events


def get_event_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Retrieves an event by event id and return outputs in Demisto's format

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    event = client.get_event(**args)

    # display the event and it's properties
    event_readable, event_outputs = parse_events(event)
    human_readable = tableToMarkdown(
        name=f"Event - {event_outputs[0].get('Subject')}", t=event_readable, headers=EVENT_HEADERS, removeNull=True
    )
    entry_context = {f"{INTEGRATION_CONTEXT_NAME}.Event(val.ID === obj.ID)": event_outputs}
    return human_readable, entry_context, event


def create_event_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Creates an event by event id and return outputs in Demisto's format

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    args = process_event_params(**args)
    params: dict = snakecase_to_camelcase(args, fields_to_drop=["user", "calendar_id"])  # type: ignore

    # create the event
    event = client.create_event(user=args.get("user", ""), calendar_id=args.get("calendar_id", ""), **params)

    # display the new event and it's properties
    event_readable, event_outputs = parse_events(event)
    human_readable = tableToMarkdown(
        name="Event was created successfully:", t=event_readable, headers=EVENT_HEADERS, removeNull=True
    )
    entry_context = {f"{INTEGRATION_CONTEXT_NAME}.Event(val.ID === obj.ID)": event_outputs}
    return human_readable, entry_context, event


def update_event_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Get a event by event id and return outputs in Demisto's format.

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    event_id = args.get("event_id", "")
    args = process_event_params(**args)
    params: dict = snakecase_to_camelcase(args, fields_to_drop=["user", "calendar_id", "event_id"])  # type: ignore

    # update the event
    event = client.update_event(user=args.get("user", ""), event_id=args.get("event_id", ""), **params)

    # display the updated event and it's properties
    event_readable, event_outputs = parse_events(event)
    human_readable = tableToMarkdown(name="Event:", t=event_readable, headers=EVENT_HEADERS, removeNull=True)
    entry_context = {f"{INTEGRATION_CONTEXT_NAME}(obj.ID === {event_id})": event_outputs}
    return human_readable, entry_context, event


def delete_event_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Delete an event by event id and return outputs in Demisto's format

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    event_id = str(args.get("event_id"))
    client.delete_event(**args)

    # get the event data from the context
    event_data = demisto.dt(demisto.context(), f'{INTEGRATION_CONTEXT_NAME}.Event(val.ID === "{event_id}")')
    if isinstance(event_data, list):
        event_data = event_data[0]

    # add a field that indicates that the event was deleted
    event_data["Deleted"] = True  # add a field with the members to the event
    entry_context = {f"{INTEGRATION_CONTEXT_NAME}.Event(val.ID === obj.ID)": event_data}

    human_readable = "Event was deleted successfully."
    return human_readable, entry_context, NO_OUTPUTS


def list_calendars_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Get all the user's calendars (/calendars navigation property)

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    calendar = client.list_calendars(**args)

    calendar_readable, calendar_outputs = parse_calendar(calendar.get("value"))  # type: ignore

    entry_context = {f"{INTEGRATION_CONTEXT_NAME}.Calendar(val.ID === obj.ID)": calendar_outputs}
    title = "Calendar:"

    human_readable = tableToMarkdown(name=title, t=calendar_readable, headers=CALENDAR_HEADERS, removeNull=True)

    return human_readable, entry_context, calendar


def get_calendar_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Get the properties and relationships of a calendar object.
    The calendar can be one for a user, or the default calendar of an Office 365 group.

    Args:
        client: Client object with request
        args: Usually demisto.args()
    """
    calendar = client.get_calendar(**args)

    calendar_readable, calendar_outputs = parse_calendar(calendar)

    entry_context = {f"{INTEGRATION_CONTEXT_NAME}.Calendar(val.ID === obj.ID)": calendar_outputs}
    title = "Calendar:"

    human_readable = tableToMarkdown(name=title, t=calendar_readable, headers=CALENDAR_HEADERS, removeNull=True)

    return human_readable, entry_context, calendar


def module_test_function_command(client: MsGraphClient, args: dict) -> tuple[str, dict, dict]:
    """
    Performs a basic GET request to check if the API is reachable and authentication is successful.

    Args:
        client: Client object with request
    """
    return client.test_function()


def main():
    params: dict = demisto.params()
    url = params.get("url", "").rstrip("/") + "/v1.0/"
    tenant = params.get("credentials_tenant_id", {}).get("password") or params.get("tenant_id")
    auth_and_token_url = params.get("credentials_auth_id", {}).get("password") or params.get("auth_id", "")
    enc_key = params.get("credentials_enc_key", {}).get("password") or params.get("enc_key")
    verify = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    default_user = params.get("default_user")
    certificate_thumbprint = params.get("credentials_certificate_thumbprint", {}).get("password") or params.get(
        "certificate_thumbprint"
    )
    private_key = params.get("private_key")
    managed_identities_client_id = get_azure_managed_identities_client_id(params)
    self_deployed: bool = params.get("self_deployed", False) or managed_identities_client_id is not None

    if not managed_identities_client_id:
        if not self_deployed and not enc_key:
            raise DemistoException(
                "Key must be provided. For further information see "
                "https://xsoar.pan.dev/docs/reference/articles/microsoft-integrations---authentication"
            )
        elif not enc_key and not (certificate_thumbprint and private_key):
            raise DemistoException("Key or Certificate Thumbprint and Private Key must be provided.")

    commands = {
        "test-module": module_test_function_command,
        "msgraph-calendar-list-calendars": list_calendars_command,
        "msgraph-calendar-get-calendar": get_calendar_command,
        "msgraph-calendar-list-events": list_events_command,
        "msgraph-calendar-get-event": get_event_command,
        "msgraph-calendar-create-event": create_event_command,
        "msgraph-calendar-update-event": update_event_command,
        "msgraph-calendar-delete-event": delete_event_command,
    }
    command = demisto.command()
    LOG(f"Command being called is {command}")

    try:
        client: MsGraphClient = MsGraphClient(
            tenant_id=tenant,
            auth_id=auth_and_token_url,
            enc_key=enc_key,
            app_name=APP_NAME,
            base_url=url,
            verify=verify,
            proxy=proxy,
            default_user=default_user,
            self_deployed=self_deployed,
            certificate_thumbprint=certificate_thumbprint,
            private_key=private_key,
            managed_identities_client_id=managed_identities_client_id,
        )
        if "user" not in demisto.args():
            demisto.args()["user"] = client.default_user
        if command == "msgraph-calendar-auth-reset":
            return_results(reset_auth())
        else:
            # Run the command
            human_readable, entry_context, raw_response = commands[command](client, demisto.args())  # type: ignore
            # create a war room entry
            return_outputs(readable_output=human_readable, outputs=entry_context, raw_response=raw_response)

    except Exception as err:
        return_error(str(err))


if __name__ in ["__main__", "builtin", "builtins"]:
    main()