diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8b6c37..cc6e4725 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,65 +1,82 @@ # Changelog * [Changelog](#changelog) - * [2.19.0](#2190) - * [2.18.1](#2181) - * [2.18.0](#2180) - * [2.17.2](#2172) - * [2.17.1](#2171) - * [2.17.0](#2170) - * [2.16.1](#2161) - * [2.16.0](#2160) - * [2.15.4](#2154) - * [2.15.3](#2153) - * [2.15.2](#2152) - * [2.15.1](#2151) - * [2.15.0](#2150) - * [2.14.1](#2141) - * [2.14.0](#2140) - * [2.13.2](#2132) - * [2.13.1](#2131) - * [2.13.0](#2130) - * [2.12.1](#2121) - * [2.12.0](#2120) - * [2.11.0](#2110) - * [2.10.2](#2102) - * [2.10.1](#2101) - * [2.10.0](#2100) - * [2.9.0](#290) - * [2.8.1](#281) - * [2.8.0](#280) - * [2.7.2](#272) - * [2.7.1](#271) - * [2.7.0](#270) - * [2.6.3](#263) - * [2.6.2](#262) - * [2.6.1](#261) - * [2.6.0](#260) - * [2.5.4](#254) - * [2.5.3](#253) - * [2.5.2](#252) - * [2.5.1](#251) - * [2.5.0](#250) - * [2.4.0](#240) - * [2.3.0](#230) - * [2.2.1](#221) - * [2.2.0](#220) - * [2.1.5](#215) - * [2.1.3 / 2.1.4](#213--214) - * [2.1.2](#212) - * [2.1.1](#211) - * [2.1.0](#210) - * [2.0.3](#203) - * [2.0.2](#202) - * [2.0.1](#201) - * [2.0.0](#200) - * [New Functionality](#new-functionality) - * [Breaking Changes in 2.0.0](#breaking-changes-in-200) - * [Gmail Delegation Management Removed](#gmail-delegation-management-removed) - * [Functions Removed](#functions-removed) - * [Functions Aliased](#functions-aliased) + * [2.20.0](#2200) + * [2.19.0](#2190) + * [2.18.1](#2181) + * [2.18.0](#2180) + * [2.17.2](#2172) + * [2.17.1](#2171) + * [2.17.0](#2170) + * [2.16.1](#2161) + * [2.16.0](#2160) + * [2.15.4](#2154) + * [2.15.3](#2153) + * [2.15.2](#2152) + * [2.15.1](#2151) + * [2.15.0](#2150) + * [2.14.1](#2141) + * [2.14.0](#2140) + * [2.13.2](#2132) + * [2.13.1](#2131) + * [2.13.0](#2130) + * [2.12.1](#2121) + * [2.12.0](#2120) + * [2.11.0](#2110) + * [2.10.2](#2102) + * [2.10.1](#2101) + * [2.10.0](#2100) + * [2.9.0](#290) + * [2.8.1](#281) + * [2.8.0](#280) + * [2.7.2](#272) + * [2.7.1](#271) + * [2.7.0](#270) + * [2.6.3](#263) + * [2.6.2](#262) + * [2.6.1](#261) + * [2.6.0](#260) + * [2.5.4](#254) + * [2.5.3](#253) + * [2.5.2](#252) + * [2.5.1](#251) + * [2.5.0](#250) + * [2.4.0](#240) + * [2.3.0](#230) + * [2.2.1](#221) + * [2.2.0](#220) + * [2.1.5](#215) + * [2.1.3 / 2.1.4](#213--214) + * [2.1.2](#212) + * [2.1.1](#211) + * [2.1.0](#210) + * [2.0.3](#203) + * [2.0.2](#202) + * [2.0.1](#201) + * [2.0.0](#200) + * [New Functionality](#new-functionality) + * [Breaking Changes in 2.0.0](#breaking-changes-in-200) + * [Gmail Delegation Management Removed](#gmail-delegation-management-removed) + * [Functions Removed](#functions-removed) + * [Functions Aliased](#functions-aliased) *** +## 2.20.0 + +* [Issue #115](https://github.com/scrthq/PSGSuite/issues/115) + * Renamed: `Get-GSCalendarEventList` to `Get-GSCalendarEvent` and set the original name as an exported Alias to the new name for backwards compatibility. + * Added: `EventId` parameter to `Get-GSCalendarEvent` to specify individual event ID's to get instead of a filtered list. + * Added: `PrivateExtendedProperty` parameter to `Get-GSCalendarEvent`. + * Added: `SharedExtendedProperty` parameter to `Get-GSCalendarEvent`. + * Added: `PrivateExtendedProperties` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. + * Added: `SharedExtendedProperties` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. + * Added: `ExtendedProperties` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. + * Added: `Id` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. +* [Issue #117](https://github.com/scrthq/PSGSuite/issues/117) + * Fixed: Type error on `States` parameter of `Get-GSStudentGuardianInvitation`. +* Miscellaneous + * Updated Contributing doc with new Build script steps + * Removed `DebugMode.ps1` script since it's no longer needed (use `build.ps1` instead) ## 2.19.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ebef7bc5..1b47710e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,17 +2,17 @@ -- [Contributing to PSGSuite](#contributing-to-psgsuite) - - [Git and Pull requests](#git-and-pull-requests) - - [Overview](#overview) - - [Step by Step](#step-by-step) - - [Contributing Guidelines](#contributing-guidelines) - - [Updating the Wiki](#updating-the-wiki) - - [Getting Started](#getting-started) - - [Enabling Debug Mode](#enabling-debug-mode) - - [Google .NET SDK Documentation](#google-net-sdk-documentation) - - [.NET/API Documentation Links](#netapi-documentation-links) - - [Keeping in Touch](#keeping-in-touch) +* [Contributing to PSGSuite](#contributing-to-psgsuite) + * [Git and Pull requests](#git-and-pull-requests) + * [Overview](#overview) + * [Step by Step (High-Level)](#step-by-step-high-level) + * [Contributing Guidelines](#contributing-guidelines) + * [Updating the Wiki](#updating-the-wiki) + * [Getting Started](#getting-started) + * [Enabling Debug Mode](#enabling-debug-mode) + * [Google .NET SDK Documentation](#google-net-sdk-documentation) + * [.NET/API Documentation Links](#netapi-documentation-links) + * [Keeping in Touch](#keeping-in-touch) @@ -27,9 +27,9 @@ Thank you for your interest in helping PSGSuite grow! Below you'll find some gui ## Overview -### Step by Step +### Step by Step (High-Level) -Here's the overall flow of making contributions: +Here's the overall flow of making contributions: 1. Fork the repo 2. Make your edits / additions on your fork 3. Push your changes back to your fork on GitHub @@ -46,12 +46,12 @@ Please follow these guidelines for any content being added: * work in any OS; * any code that includes paths must build the path using OS-agnostic methods, i.e. by using `Resolve-Path`, `Join-Path` and `Split-Path` * paths also need to use correct casing, as some OS's are case-sensitive in terms of paths -* **Public functions must...** +* **Public functions must...** * include comment-based help (this is used to drive the Wiki updates on deployment) * include Write-Verbose calls to describe what the function is doing (CI tests will fail the build if any don't) * be placed in the correct APU/use-case folder in the Public sub-directory of the module path (if it's a new API/use-case, create the new folder as well) * use `SupportsShouldProcess` if... - * the function's verb is `Remove` or `Set`. + * the function's verb is `Remove` or `Set`. * it can be included on `Update` functions as well, if felt that the actions executed by the function should be guarded * `Get` functions should **never** need `SupportsShouldProcess` * **Every Pull Request must...** @@ -65,7 +65,7 @@ Please follow these guidelines for any content being added: ### Updating the Wiki -* Wiki updates are scripted during deployment builds, so there is no need to manually update the Wiki. +* Wiki updates are scripted during deployment builds, so there is no need to manually update the Wiki. * Any new or updated comment-based help content will be transformed to Markdown using `platyPS` and pushed to the Wiki repo when deployment conditions are met. ## Getting Started @@ -138,4 +138,4 @@ Here are some links to the most commonly used SDK's and API's in PSGSuite: ## Keeping in Touch -For any questions, comments or concerns outside of opening an issue, please join us in the `#psgsuite` channel on the SCRT HQ Slack; Team: `scrthq.slack.com`. [Click here](https://scrthq-slack-invite.herokuapp.com/) to get an invite! \ No newline at end of file +For any questions, comments or concerns outside of opening an issue, please join us in the `#psgsuite` channel on the SCRT HQ Slack; Team: `scrthq.slack.com`. [Click here](https://scrthq-slack-invite.herokuapp.com/) to get an invite! diff --git a/DebugMode.ps1 b/DebugMode.ps1 deleted file mode 100644 index 7da183b7..00000000 --- a/DebugMode.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -<# - This is a quick helper script to get PSGSuite loaded in Debug Mode. - Debug Mode exports the following additional functions with PSGSuite: - - Get-GSToken: Used for legacy functions that require calling Google's REST API directly - - New-GoogleService: Used in all SDK based functions to build out the service client -#> - -# Enable Debug Mode to export the New-GoogleService function during module import -# by setting the environment variable '$env:EnablePSGSuiteDebug' to $true -$env:EnablePSGSuiteDebug = $false - -Get-Module PSGSuite | Remove-Module -Force - -. .\build.ps1 -Task Compile - -# Force import the module in the repo path so that updated functions are reloaded -$modulePath = [System.IO.Path]::Combine("$PSScriptRoot","out","PSGSuite") -Import-Module $modulePath -Force - -Get-Module PSGSuite | Select-Object Name,Version,ModuleBase diff --git a/PSGSuite/Aliases/PSGSuite.Aliases.ps1 b/PSGSuite/Aliases/PSGSuite.Aliases.ps1 index b684cda5..58b580ab 100644 --- a/PSGSuite/Aliases/PSGSuite.Aliases.ps1 +++ b/PSGSuite/Aliases/PSGSuite.Aliases.ps1 @@ -1,37 +1,38 @@ @{ + 'Add-GSDriveFilePermissions' = 'Add-GSDrivePermission' + 'Export-PSGSuiteConfiguration' = 'Set-PSGSuiteConfig' 'Get-GSCalendarResourceList' = 'Get-GSResourceList' - 'Switch-PSGSuiteDomain' = 'Switch-PSGSuiteConfig' - 'Get-GSUserSchemaInfo' = 'Get-GSUserSchema' - 'Get-GSUserLicenseInfo' = 'Get-GSUserLicense' - 'Get-GSGmailMessageInfo' = 'Get-GSGmailMessage' - 'New-GSCalendarResource' = 'New-GSResource' - 'Update-GSCalendarResource' = 'Update-GSResource' - 'Get-GSShortURLInfo' = 'Get-GSShortURL' - 'Move-GSGmailMessageToTrash' = 'Remove-GSGmailMessage' - 'Remove-GSGmailMessageFromTrash' = 'Restore-GSGmailMessage' - 'Get-GSGmailFilterList' = 'Get-GSGmailFilter' - 'Get-GSGmailLabelList' = 'Get-GSGmailLabel' + 'Get-GSCalendarEventList' = 'Get-GSCalendarEvent' + 'Get-GSDataTransferApplicationList' = 'Get-GSDataTransferApplication' 'Get-GSDriveFileInfo' = 'Get-GSDriveFile' - 'Get-GSTeamDrivesList' = 'Get-GSTeamDrive' - 'Add-GSDriveFilePermissions' = 'Add-GSDrivePermission' 'Get-GSDriveFilePermissionsList' = 'Get-GSDrivePermission' + 'Get-GSGmailDelegates' = 'Get-GSGmailDelegate' + 'Get-GSGmailFilterList' = 'Get-GSGmailFilter' + 'Get-GSGmailLabelList' = 'Get-GSGmailLabel' + 'Get-GSGmailMessageInfo' = 'Get-GSGmailMessage' 'Get-GSGroupList' = 'Get-GSGroup' 'Get-GSGroupMemberList' = 'Get-GSGroupMember' - 'Get-GSOrgUnitList' = 'Get-GSOrganizationalUnit' - 'Get-GSOU' = 'Get-GSOrganizationalUnit' + 'Get-GSMobileDeviceList' = 'Get-GSMobileDevice' 'Get-GSOrganizationalUnitList' = 'Get-GSOrganizationalUnit' 'Get-GSOrgUnit' = 'Get-GSOrganizationalUnit' - 'Get-GSMobileDeviceList' = 'Get-GSMobileDevice' - 'Get-GSDataTransferApplicationList' = 'Get-GSDataTransferApplication' + 'Get-GSOrgUnitList' = 'Get-GSOrganizationalUnit' + 'Get-GSOU' = 'Get-GSOrganizationalUnit' 'Get-GSResourceList' = 'Get-GSResource' + 'Get-GSShortURLInfo' = 'Get-GSShortURL' + 'Get-GSTeamDrivesList' = 'Get-GSTeamDrive' 'Get-GSUserASPList' = 'Get-GSUserASP' + 'Get-GSUserLicenseInfo' = 'Get-GSUserLicense' + 'Get-GSUserLicenseList' = 'Get-GSUserLicense' 'Get-GSUserList' = 'Get-GSUser' + 'Get-GSUserSchemaInfo' = 'Get-GSUserSchema' 'Get-GSUserSchemaList' = 'Get-GSUserSchema' 'Get-GSUserTokenList' = 'Get-GSUserToken' - 'Get-GSUserLicenseList' = 'Get-GSUserLicense' - 'Update-GSSheetValue' = 'Export-GSSheet' - 'Export-PSGSuiteConfiguration' = 'Set-PSGSuiteConfig' 'Import-PSGSuiteConfiguration' = 'Get-PSGSuiteConfig' + 'Move-GSGmailMessageToTrash' = 'Remove-GSGmailMessage' + 'New-GSCalendarResource' = 'New-GSResource' + 'Remove-GSGmailMessageFromTrash' = 'Restore-GSGmailMessage' 'Set-PSGSuiteDefaultDomain' = 'Switch-PSGSuiteConfig' - 'Get-GSGmailDelegates' = 'Get-GSGmailDelegate' + 'Switch-PSGSuiteDomain' = 'Switch-PSGSuiteConfig' + 'Update-GSCalendarResource' = 'Update-GSResource' + 'Update-GSSheetValue' = 'Export-GSSheet' } diff --git a/PSGSuite/PSGSuite.psd1 b/PSGSuite/PSGSuite.psd1 index 75f065a6..fcbfe9de 100644 --- a/PSGSuite/PSGSuite.psd1 +++ b/PSGSuite/PSGSuite.psd1 @@ -12,7 +12,7 @@ RootModule = 'PSGSuite.psm1' # Version number of this module. - ModuleVersion = '2.19.0' + ModuleVersion = '2.20.0' # ID used to uniquely identify this module GUID = '9d751152-e83e-40bb-a6db-4c329092aaec' diff --git a/PSGSuite/Public/Calendar/Get-GSCalendarEvent.ps1 b/PSGSuite/Public/Calendar/Get-GSCalendarEvent.ps1 new file mode 100644 index 00000000..7d21cdfd --- /dev/null +++ b/PSGSuite/Public/Calendar/Get-GSCalendarEvent.ps1 @@ -0,0 +1,206 @@ +function Get-GSCalendarEvent { + <# + .SYNOPSIS + Gets the calendar events for a user + + .DESCRIPTION + Gets the calendar events for a user + + .PARAMETER User + The primary email or UserID of the user. You can exclude the '@domain.com' to insert the Domain in the config or use the special 'me' to indicate the AdminEmail in the config. + + Defaults to the AdminEmail in the config + + .PARAMETER CalendarId + The calendar ID of the calendar you would like to list events from. + + Defaults to the user's primary calendar + + .PARAMETER Filter + Free text search terms to find events that match these terms in any field, except for extended properties. + + .PARAMETER OrderBy + The order of the events returned in the result. + + Acceptable values are: + * "startTime": Order by the start date/time (ascending). This is only available when querying single events (i.e. the parameter singleEvents is True) + * "updated": Order by last modification time (ascending). + + .PARAMETER MaxAttendees + The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. + + .PARAMETER PageSize + Maximum number of events returned on one result page. + + .PARAMETER ShowDeleted + Whether to include deleted events (with status equals "cancelled") in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if showDeleted and singleEvents are both False. If showDeleted and singleEvents are both True, only single instances of deleted events (but not the underlying recurring events) are returned. + + .PARAMETER ShowHiddenInvitations + Whether to include hidden invitations in the result. + + .PARAMETER SingleEvents + Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. + + .PARAMETER TimeMin + Lower bound (inclusive) for an event's end time to filter by. If TimeMax is set, TimeMin must be smaller than timeMax. + + .PARAMETER TimeMax + Upper bound (exclusive) for an event's start time to filter by. If TimeMin is set, TimeMax must be greater than timeMin. + + .EXAMPLE + Get-GSCalendarEventList -TimeMin (Get-Date "01-21-2018 00:00:00") -TimeMax (Get-Date "01-28-2018 23:59:59") -SingleEvents + + This gets the single events on the primary calendar of the Admin for the week of Jan 21-28, 2018. + #> + [cmdletbinding(DefaultParameterSetName = "List")] + Param + ( + [parameter(Mandatory = $true,Position = 0,ParameterSetName = "Get")] + [String[]] + $EventId, + [parameter(Mandatory = $false)] + [String] + $CalendarId = "primary", + [parameter(Mandatory = $false,ValueFromPipeline = $true,ValueFromPipelineByPropertyName = $true)] + [Alias("PrimaryEmail","UserKey","Mail")] + [ValidateNotNullOrEmpty()] + [String[]] + $User = $Script:PSGSuite.AdminEmail, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [Alias('Q','Query')] + [String] + $Filter, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [ValidateSet("StartTime","Updated")] + [String] + $OrderBy, + [parameter(Mandatory = $false)] + [Int] + $MaxAttendees, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [ValidateRange(1,2500)] + [Int] + $PageSize = 2500, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [switch] + $ShowDeleted, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [switch] + $ShowHiddenInvitations, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [switch] + $SingleEvents, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [Hashtable] + $PrivateExtendedProperty, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [Hashtable] + $SharedExtendedProperty, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [DateTime] + $TimeMin, + [parameter(Mandatory = $false,ParameterSetName = "List")] + [DateTime] + $TimeMax + ) + Process { + foreach ($U in $User) { + if ($U -ceq 'me') { + $U = $Script:PSGSuite.AdminEmail + } + elseif ($U -notlike "*@*.*") { + $U = "$($U)@$($Script:PSGSuite.Domain)" + } + $serviceParams = @{ + Scope = 'https://www.googleapis.com/auth/calendar' + ServiceType = 'Google.Apis.Calendar.v3.CalendarService' + User = $U + } + $service = New-GoogleService @serviceParams + foreach ($calId in $CalendarId) { + switch ($PSCmdlet.ParameterSetName) { + Get { + foreach ($evId in $EventId) { + try { + $request = $service.Events.Get($calId,$evId) + if ($PSBoundParameters.Keys -contains 'MaxAttendees') { + $request.MaxAttendees = $MaxAttendees + } + Write-Verbose "Getting Event ID '$evId' from Calendar '$calId' for User '$U'" + $request.Execute() | Add-Member -MemberType NoteProperty -Name 'User' -Value $U -PassThru | Add-Member -MemberType NoteProperty -Name 'CalendarId' -Value $calId -PassThru + } + catch { + if ($ErrorActionPreference -eq 'Stop') { + $PSCmdlet.ThrowTerminatingError($_) + } + else { + Write-Error $_ + } + } + } + } + List { + try { + $request = $service.Events.List($calId) + foreach ($key in $PSBoundParameters.Keys | Where-Object {$_ -ne 'CalendarId'}) { + switch ($key) { + Filter { + $request.Q = $Filter + } + PrivateExtendedProperty { + $converted = $PrivateExtendedProperty.Keys | Foreach-Object { + "$($_)=$($PrivateExtendedProperty[$_])" + } + $repeatable = [Google.Apis.Util.Repeatable[String]]::new([String[]]$converted) + $request.PrivateExtendedProperty = $repeatable + } + SharedExtendedProperty { + $converted = $SharedExtendedProperty.Keys | Foreach-Object { + "$($_)=$($SharedExtendedProperty[$_])" + } + $repeatable = [Google.Apis.Util.Repeatable[String]]::new([String[]]$converted) + $request.SharedExtendedProperty = $repeatable + } + Default { + if ($request.PSObject.Properties.Name -contains $key) { + $request.$key = $PSBoundParameters[$key] + } + } + } + } + if ($PageSize) { + $request.MaxResults = $PageSize + } + if ($Filter) { + Write-Verbose "Getting all Calendar Events matching filter '$Filter' on calendar '$calId' for user '$U'" + } + else { + Write-Verbose "Getting all Calendar Events on calendar '$calId' for user '$U'" + } + [int]$i = 1 + do { + $result = $request.Execute() + $result.Items | Add-Member -MemberType NoteProperty -Name 'User' -Value $U -PassThru | Add-Member -MemberType NoteProperty -Name 'CalendarId' -Value $calId -PassThru + if ($result.NextPageToken) { + $request.PageToken = $result.NextPageToken + } + [int]$retrieved = ($i + $result.Items.Count) - 1 + Write-Verbose "Retrieved $retrieved Calendar Events..." + [int]$i = $i + $result.Items.Count + } + until (!$result.NextPageToken) + } + catch { + if ($ErrorActionPreference -eq 'Stop') { + $PSCmdlet.ThrowTerminatingError($_) + } + else { + Write-Error $_ + } + } + } + } + } + } + } +} diff --git a/PSGSuite/Public/Calendar/Get-GSCalendarEventList.ps1 b/PSGSuite/Public/Calendar/Get-GSCalendarEventList.ps1 deleted file mode 100644 index d60cd71f..00000000 --- a/PSGSuite/Public/Calendar/Get-GSCalendarEventList.ps1 +++ /dev/null @@ -1,159 +0,0 @@ -function Get-GSCalendarEventList { - <# - .SYNOPSIS - Gets the calendar events for a user - - .DESCRIPTION - Gets the calendar events for a user - - .PARAMETER User - The primary email or UserID of the user. You can exclude the '@domain.com' to insert the Domain in the config or use the special 'me' to indicate the AdminEmail in the config. - - Defaults to the AdminEmail in the config - - .PARAMETER CalendarId - The calendar ID of the calendar you would like to list events from. - - Defaults to the user's primary calendar - - .PARAMETER Filter - Free text search terms to find events that match these terms in any field, except for extended properties. - - .PARAMETER OrderBy - The order of the events returned in the result. - - Acceptable values are: - * "startTime": Order by the start date/time (ascending). This is only available when querying single events (i.e. the parameter singleEvents is True) - * "updated": Order by last modification time (ascending). - - .PARAMETER MaxAttendees - The maximum number of attendees to include in the response. If there are more than the specified number of attendees, only the participant is returned. - - .PARAMETER PageSize - Maximum number of events returned on one result page. - - .PARAMETER ShowDeleted - Whether to include deleted events (with status equals "cancelled") in the result. Cancelled instances of recurring events (but not the underlying recurring event) will still be included if showDeleted and singleEvents are both False. If showDeleted and singleEvents are both True, only single instances of deleted events (but not the underlying recurring events) are returned. - - .PARAMETER ShowHiddenInvitations - Whether to include hidden invitations in the result. - - .PARAMETER SingleEvents - Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. - - .PARAMETER TimeMin - Lower bound (inclusive) for an event's end time to filter by. If TimeMax is set, TimeMin must be smaller than timeMax. - - .PARAMETER TimeMax - Upper bound (exclusive) for an event's start time to filter by. If TimeMin is set, TimeMax must be greater than timeMin. - - .EXAMPLE - Get-GSCalendarEventList -TimeMin (Get-Date "01-21-2018 00:00:00") -TimeMax (Get-Date "01-28-2018 23:59:59") -SingleEvents - - This gets the single events on the primary calendar of the Admin for the week of Jan 21-28, 2018. - #> - [cmdletbinding()] - Param - ( - [parameter(Mandatory = $false,Position = 0,ValueFromPipeline = $true,ValueFromPipelineByPropertyName = $true)] - [Alias("PrimaryEmail","UserKey","Mail")] - [ValidateNotNullOrEmpty()] - [String[]] - $User = $Script:PSGSuite.AdminEmail, - [parameter(Mandatory = $false)] - [String] - $CalendarId = "primary", - [parameter(Mandatory = $false)] - [Alias('Q','Query')] - [String] - $Filter, - [parameter(Mandatory = $false)] - [ValidateSet("StartTime","Updated")] - [String] - $OrderBy, - [parameter(Mandatory = $false)] - [Int] - $MaxAttendees, - [parameter(Mandatory = $false)] - [ValidateRange(1,2500)] - [Int] - $PageSize = 2500, - [parameter(Mandatory = $false)] - [switch] - $ShowDeleted, - [parameter(Mandatory = $false)] - [switch] - $ShowHiddenInvitations, - [parameter(Mandatory = $false)] - [switch] - $SingleEvents, - [parameter(Mandatory = $false)] - [DateTime] - $TimeMin, - [parameter(Mandatory = $false)] - [DateTime] - $TimeMax - ) - Process { - try { - foreach ($U in $User) { - if ($U -ceq 'me') { - $U = $Script:PSGSuite.AdminEmail - } - elseif ($U -notlike "*@*.*") { - $U = "$($U)@$($Script:PSGSuite.Domain)" - } - $serviceParams = @{ - Scope = 'https://www.googleapis.com/auth/calendar' - ServiceType = 'Google.Apis.Calendar.v3.CalendarService' - User = $U - } - $service = New-GoogleService @serviceParams - foreach ($calId in $CalendarId) { - $request = $service.Events.List($calId) - foreach ($key in $PSBoundParameters.Keys | Where-Object {$_ -ne 'CalendarId'}) { - switch ($key) { - Filter { - $request.Q = $Filter - } - Default { - if ($request.PSObject.Properties.Name -contains $key) { - $request.$key = $PSBoundParameters[$key] - } - } - } - } - if ($PageSize) { - $request.MaxResults = $PageSize - } - if ($Filter) { - Write-Verbose "Getting all Calendar Events matching filter '$Filter' on calendar '$calId' for user '$U'" - } - else { - Write-Verbose "Getting all Calendar Events on calendar '$calId' for user '$U'" - } - [int]$i = 1 - do { - $result = $request.Execute() - $result.Items | Add-Member -MemberType NoteProperty -Name 'User' -Value $U -PassThru | Add-Member -MemberType NoteProperty -Name 'CalendarId' -Value $calId -PassThru - if ($result.NextPageToken) { - $request.PageToken = $result.NextPageToken - } - [int]$retrieved = ($i + $result.Items.Count) - 1 - Write-Verbose "Retrieved $retrieved Calendar Events..." - [int]$i = $i + $result.Items.Count - } - until (!$result.NextPageToken) - } - } - } - catch { - if ($ErrorActionPreference -eq 'Stop') { - $PSCmdlet.ThrowTerminatingError($_) - } - else { - Write-Error $_ - } - } - } -} \ No newline at end of file diff --git a/PSGSuite/Public/Calendar/New-GSCalendarEvent.ps1 b/PSGSuite/Public/Calendar/New-GSCalendarEvent.ps1 index 063e2d42..380a156d 100644 --- a/PSGSuite/Public/Calendar/New-GSCalendarEvent.ps1 +++ b/PSGSuite/Public/Calendar/New-GSCalendarEvent.ps1 @@ -12,6 +12,17 @@ function New-GSCalendarEvent { .PARAMETER Description Event description + .PARAMETER Id + Opaque identifier of the event. When creating new single or recurring events, you can specify their IDs. Provided IDs must follow these rules: + + * characters allowed in the ID are those used in base32hex encoding, i.e. lowercase letters a-v and digits 0-9, see section 3.1.2 in RFC2938 + * the length of the ID must be between 5 and 1024 characters + * the ID must be unique per calendar + + Due to the globally distributed nature of the system, we cannot guarantee that ID collisions will be detected at event creation time. To minimize the risk of collisions we recommend using an established UUID algorithm such as one described in RFC4122. + + If you do not specify an ID, it will be automatically generated by the server. + .PARAMETER User The primary email or UserID of the user. You can exclude the '@domain.com' to insert the Domain in the config or use the special 'me' to indicate the AdminEmail in the config. @@ -61,6 +72,17 @@ function New-GSCalendarEvent { .PARAMETER UTCEndDateTime String representation of the end date in UTC. Highest precendence of the three EndDate parameters. + .PARAMETER PrivateExtendedProperties + A hashtable of properties that are private to the copy of the event that appears on this calendar. + + .PARAMETER SharedExtendedProperties + A hashtable of properties that are shared between copies of the event on other attendees' calendars. + + .PARAMETER ExtendedProperties + Extended properties of the event. This must be of the type 'Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData'. + + This is useful for copying another events ExtendedProperties over when creating a new event. + .EXAMPLE New-GSCalendarEvent "Go to the gym" -StartDate (Get-Date "21:00:00") -EndDate (Get-Date "22:00:00") @@ -75,6 +97,11 @@ function New-GSCalendarEvent { [parameter(Mandatory = $false)] [String] $Description, + [parameter(Mandatory = $false)] + [ValidateScript({if ($_ -match '^[0-9a-v]+$'){$true}else{throw "The characters allowed in the ID are only those used in base32hex encoding, i.e. lowercase letters a-v and digits 0-9"}})] + [ValidateLength(5,1024)] + [String] + $Id, [parameter(Mandatory = $false,ValueFromPipelineByPropertyName = $true)] [Alias("PrimaryEmail","UserKey","Mail")] [ValidateNotNullOrEmpty()] @@ -116,7 +143,16 @@ function New-GSCalendarEvent { $UTCStartDateTime, [parameter(Mandatory = $false)] [String] - $UTCEndDateTime + $UTCEndDateTime, + [parameter(Mandatory = $false)] + [Hashtable] + $PrivateExtendedProperties, + [parameter(Mandatory = $false)] + [Hashtable] + $SharedExtendedProperties, + [parameter(Mandatory = $false)] + [Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData] + $ExtendedProperties ) Begin { $colorHash = @{ @@ -162,6 +198,34 @@ function New-GSCalendarEvent { EventColor { $body.ColorId = $colorHash[$EventColor] } + PrivateExtendedProperties { + if (-not $ExtendedProperties) { + $ExtendedProperties = New-Object 'Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData' -Property @{ + Private__ = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + Shared = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + } + elseif (-not $ExtendedProperties.Private__) { + $ExtendedProperties.Private__ = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + foreach ($prop in $PrivateExtendedProperties.Keys) { + $ExtendedProperties.Private__.Add($prop,$PrivateExtendedProperties[$prop]) + } + } + SharedExtendedProperties { + if (-not $ExtendedProperties) { + $ExtendedProperties = New-Object 'Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData' -Property @{ + Private__ = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + Shared = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + } + elseif (-not $ExtendedProperties.Shared) { + $ExtendedProperties.Shared = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + foreach ($prop in $SharedExtendedProperties.Keys) { + $ExtendedProperties.Shared.Add($prop,$SharedExtendedProperties[$prop]) + } + } DisableReminder { $reminder = New-Object 'Google.Apis.Calendar.v3.Data.Event+RemindersData' -Property @{ UseDefault = (-not $DisableReminder) @@ -175,6 +239,9 @@ function New-GSCalendarEvent { } } } + if ($ExtendedProperties) { + $body.ExtendedProperties = $ExtendedProperties + } $body.Start = if ($UTCStartDateTime) { New-Object 'Google.Apis.Calendar.v3.Data.EventDateTime' -Property @{ DateTime = $UTCStartDateTime diff --git a/PSGSuite/Public/Calendar/Update-GSCalendarEvent.ps1 b/PSGSuite/Public/Calendar/Update-GSCalendarEvent.ps1 index f782739e..de5300ab 100644 --- a/PSGSuite/Public/Calendar/Update-GSCalendarEvent.ps1 +++ b/PSGSuite/Public/Calendar/Update-GSCalendarEvent.ps1 @@ -64,6 +64,17 @@ function Update-GSCalendarEvent { .PARAMETER UTCEndDateTime String representation of the end date in UTC. Highest precendence of the three EndDate parameters. + .PARAMETER PrivateExtendedProperties + A hashtable of properties that are private to the copy of the event that appears on this calendar. + + .PARAMETER SharedExtendedProperties + A hashtable of properties that are shared between copies of the event on other attendees' calendars. + + .PARAMETER ExtendedProperties + Extended properties of the event. This must be of the type 'Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData'. + + This is useful for copying another events ExtendedProperties over when updating an existing event. + .EXAMPLE New-GSCalendarEvent "Go to the gym" -StartDate (Get-Date "21:00:00") -EndDate (Get-Date "22:00:00") @@ -123,7 +134,16 @@ function Update-GSCalendarEvent { $UTCStartDateTime, [parameter(Mandatory = $false)] [String] - $UTCEndDateTime + $UTCEndDateTime, + [parameter(Mandatory = $false)] + [Hashtable] + $PrivateExtendedProperties, + [parameter(Mandatory = $false)] + [Hashtable] + $SharedExtendedProperties, + [parameter(Mandatory = $false)] + [Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData] + $ExtendedProperties ) Begin { $colorHash = @{ @@ -169,6 +189,34 @@ function Update-GSCalendarEvent { EventColor { $body.ColorId = $colorHash[$EventColor] } + PrivateExtendedProperties { + if (-not $ExtendedProperties) { + $ExtendedProperties = New-Object 'Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData' -Property @{ + Private__ = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + Shared = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + } + elseif (-not $ExtendedProperties.Private__) { + $ExtendedProperties.Private__ = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + foreach ($prop in $PrivateExtendedProperties.Keys) { + $ExtendedProperties.Private__.Add($prop,$PrivateExtendedProperties[$prop]) + } + } + SharedExtendedProperties { + if (-not $ExtendedProperties) { + $ExtendedProperties = New-Object 'Google.Apis.Calendar.v3.Data.Event+ExtendedPropertiesData' -Property @{ + Private__ = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + Shared = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + } + elseif (-not $ExtendedProperties.Shared) { + $ExtendedProperties.Shared = (New-Object 'System.Collections.Generic.Dictionary[string,string]') + } + foreach ($prop in $SharedExtendedProperties.Keys) { + $ExtendedProperties.Shared.Add($prop,$SharedExtendedProperties[$prop]) + } + } DisableReminder { $reminder = New-Object 'Google.Apis.Calendar.v3.Data.Event+RemindersData' -Property @{ UseDefault = (-not $DisableReminder) @@ -182,6 +230,9 @@ function Update-GSCalendarEvent { } } } + if ($ExtendedProperties) { + $body.ExtendedProperties = $ExtendedProperties + } $body.Start = if ($UTCStartDateTime) { New-Object 'Google.Apis.Calendar.v3.Data.EventDateTime' -Property @{ DateTime = $UTCStartDateTime diff --git a/PSGSuite/Public/Classroom/Get-GSStudentGuardianInvitation.ps1 b/PSGSuite/Public/Classroom/Get-GSStudentGuardianInvitation.ps1 index 9b8e1fcc..a3a0c923 100644 --- a/PSGSuite/Public/Classroom/Get-GSStudentGuardianInvitation.ps1 +++ b/PSGSuite/Public/Classroom/Get-GSStudentGuardianInvitation.ps1 @@ -53,8 +53,7 @@ function Get-GSStudentGuardianInvitation { [String] $GuardianEmail, [parameter(Mandatory = $false,ParameterSetName = "List")] - [ValidateSet('PENDING','COMPLETE')] - [Google.Apis.Classroom.v1.UserProfilesResource+GuardianInvitationsResource+ListRequest+States[]] + [Google.Apis.Classroom.v1.UserProfilesResource+GuardianInvitationsResource+ListRequest+StatesEnum[]] $States, [parameter(Mandatory = $false)] [String] diff --git a/README.md b/README.md index 84e06457..b138a57a 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,14 @@ Check out the [GitHub wiki for PSGSuite](https://github.com/scrthq/PSGSuite/wiki Interested in helping out with PSGSuite development? Please check out our [Contribution Guidelines](https://github.com/scrthq/PSGSuite/blob/master/CONTRIBUTING.md)! +Building the module locally to test changes is as easy as running the `build.ps1` file in the root of the repo. This will compile the module with your changes and import the newly compiled module at the end by default. + +Want to run the Pester tests locally? Pass `Test` as the value to the `Task` script parameter like so: + +```powershell +.\build.ps1 -Task Test +``` + ## Code of Conduct Please adhere to our [Code of Conduct](https://github.com/scrthq/PSGSuite/blob/master/CODE_OF_CONDUCT.md) when interacting with this repo. @@ -86,6 +94,7 @@ Alias Maps To ----- ------- Add-GSDriveFilePermissions Add-GSDrivePermission Export-PSGSuiteConfiguration Set-PSGSuiteConfig +Get-GSCalendarEventList Get-GSCalendarEvent Get-GSCalendarResourceList Get-GSResourceList Get-GSDataTransferApplicationList Get-GSDataTransferApplication Get-GSDriveFileInfo Get-GSDriveFile @@ -122,6 +131,23 @@ Update-GSSheetValue Export-GSSheet ### Most recent changes +#### 2.20.0 + +* [Issue #115](https://github.com/scrthq/PSGSuite/issues/115) + * Renamed: `Get-GSCalendarEventList` to `Get-GSCalendarEvent` and set the original name as an exported Alias to the new name for backwards compatibility. + * Added: `EventId` parameter to `Get-GSCalendarEvent` to specify individual event ID's to get instead of a filtered list. + * Added: `PrivateExtendedProperty` parameter to `Get-GSCalendarEvent`. + * Added: `SharedExtendedProperty` parameter to `Get-GSCalendarEvent`. + * Added: `PrivateExtendedProperties` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. + * Added: `SharedExtendedProperties` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. + * Added: `ExtendedProperties` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. + * Added: `Id` parameter to `New-GSCalendarEvent` and `Update-GSCalendarEvent`. +* [Issue #117](https://github.com/scrthq/PSGSuite/issues/117) + * Fixed: Type error on `States` parameter of `Get-GSStudentGuardianInvitation`. +* Miscellaneous + * Updated Contributing doc with new Build script steps + * Removed `DebugMode.ps1` script since it's no longer needed (use `build.ps1` instead) + #### 2.19.0 * [PR #113](https://github.com/scrthq/PSGSuite/pull/113) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c1ab462d..29795844 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,7 +19,7 @@ phases: name: Hosted VS2017 steps: - - powershell: . ./build.ps1 -Task Init,Clean,Compile + - powershell: . ./build.ps1 displayName: Compile Module - task: PublishBuildArtifacts@1 @@ -38,7 +38,7 @@ phases: name: Hosted VS2017 steps: - - powershell: . ./build.ps1 + - powershell: . ./build.ps1 -Task Test displayName: Test Module - task: PublishTestResults@2 @@ -58,7 +58,7 @@ phases: name: Hosted Ubuntu 1604 steps: - - powershell: . ./build.ps1 + - powershell: . ./build.ps1 -Task Test displayName: Test Module - task: PublishTestResults@2 @@ -78,7 +78,7 @@ phases: name: Hosted macOS steps: - - powershell: . ./build.ps1 + - powershell: . ./build.ps1 -Task Test displayName: Test Module - task: PublishTestResults@2 @@ -103,7 +103,7 @@ phases: - powershell: | $Env:Path = [Environment]::GetEnvironmentVariable('Path',[EnvironmentVariableTarget]::Machine) - pwsh -command ". ./build.ps1" + pwsh -command ". ./build.ps1 -Task Test" displayName: Test Module - task: PublishTestResults@2 displayName: 'Publish Test Results **/Test*.xml' diff --git a/build.ps1 b/build.ps1 index 06836fe0..faea001c 100644 --- a/build.ps1 +++ b/build.ps1 @@ -2,9 +2,9 @@ [cmdletbinding(DefaultParameterSetName = 'task')] param( [parameter(ParameterSetName = 'task', Position = 0)] - [ValidateSet('Init','Clean','Compile','Test','TestOnly','Deploy','Skip')] + [ValidateSet('Init','Clean','Compile','Import','Test','TestOnly','Deploy','Skip')] [string[]] - $Task = @('Init','Clean','Compile','Test'), + $Task = @('Init','Clean','Compile','Import'), [parameter(ParameterSetName = 'help')] [switch]$Help, @@ -143,6 +143,9 @@ else { $global:ExcludeTag = $null } Invoke-psake @psakeParams @verbose + if ($Task -contains 'Import' -and $psake.build_success) { + Import-Module ([System.IO.Path]::Combine($env:BHBuildOutput,$env:BHProjectName)) -Verbose:$false + } exit ( [int]( -not $psake.build_success ) ) } } diff --git a/psake.ps1 b/psake.ps1 index 2379a02c..70f95b24 100644 --- a/psake.ps1 +++ b/psake.ps1 @@ -206,6 +206,11 @@ catch { Get-ChildItem $outputModVerDir | Format-Table -Autosize } -description 'Compiles module from source' +Task Import -Depends Compile { + ' Testing import of compiled module' + Import-Module (Join-Path $outputModVerDir "$($env:BHProjectName).psd1") +} -description 'Imports the newly compiled module' + $pesterScriptBlock = { Push-Location Set-Location -PassThru $outputModDir