Skip to content

Commit

Permalink
!deploy v2.25.0 to resolve #162 and resolve #163
Browse files Browse the repository at this point in the history
## 2.25.0

* [Issue #162](#162)
  * Updated: `New-GoogleService` now caches Service objects created during the current session. This means that repeated calls will attempt to use an existing Service object from the cache if present, otherwise it will create the Service as usual.
  * Updated: `New-GoogleService` Verbose output. To cut down on verbose noisiness, the following verbose output is set:
    * New Service created = `Building ServiceAccountCredential from....`
    * First use of existing Service = `Using matching cached service for user....`
    * Re-use of existing Service = No verbose output (helps cut down on pipeline verbosity where service re-use is expected)
  * Added: `Get-PSGSuiteServiceCache` to get the current Service Cache for inspection.
* [Issue #163](#163)
  * Added: `Get-GSCalendar` to get the CalendarList of a user.
  * Added: `Remove-GSCalendarAcl` to remove Access Control List rules from Google Calendars.
* Miscellaneous
  * Improved pipeline support for Gmail `*Message` functions and Calendar functions.
  * Added tab completion to `Switch-PSGSuiteConfig` for the ConfigName parameter.
  • Loading branch information
scrthq authored Mar 20, 2019
2 parents ef20a9a + c89c651 commit 0553e1f
Show file tree
Hide file tree
Showing 15 changed files with 600 additions and 191 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

* [Changelog](#changelog)
* [2.25.0](#2250)
* [2.24.0](#2240)
* [2.23.2](#2232)
* [2.23.1](#2231)
Expand Down Expand Up @@ -77,6 +78,22 @@

***

## 2.25.0

* [Issue #162](https://github.com/scrthq/PSGSuite/issues/162)
* Updated: `New-GoogleService` now caches Service objects created during the current session. This means that repeated calls will attempt to use an existing Service object from the cache if present, otherwise it will create the Service as usual.
* Updated: `New-GoogleService` Verbose output. To cut down on verbose noisiness, the following verbose output is set:
* New Service created = `Building ServiceAccountCredential from....`
* First use of existing Service = `Using matching cached service for user....`
* Re-use of existing Service = No verbose output (helps cut down on pipeline verbosity where service re-use is expected)
* Added: `Get-PSGSuiteServiceCache` to get the current Service Cache for inspection.
* [Issue #163](https://github.com/scrthq/PSGSuite/issues/163)
* Added: `Get-GSCalendar` to get the CalendarList of a user.
* Added: `Remove-GSCalendarAcl` to remove Access Control List rules from Google Calendars.
* Miscellaneous
* Improved pipeline support for Gmail `*Message` functions and Calendar functions.
* Added tab completion to `Switch-PSGSuiteConfig` for the ConfigName parameter.

## 2.24.0

* [Issue #159](https://github.com/scrthq/PSGSuite/issues/159)
Expand Down
2 changes: 1 addition & 1 deletion PSGSuite/PSGSuite.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
RootModule = 'PSGSuite.psm1'

# Version number of this module.
ModuleVersion = '2.24.0'
ModuleVersion = '2.25.0'

# ID used to uniquely identify this module
GUID = '9d751152-e83e-40bb-a6db-4c329092aaec'
Expand Down
14 changes: 14 additions & 0 deletions PSGSuite/Private/Get-PSGSuiteConfigNames.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function Get-PSGSuiteConfigNames {
<#
.SYNOPSIS
Gets the current config names for tab completion on Switch-PSGSuiteConfig.
.DESCRIPTION
Gets the current config names for tab completion on Switch-PSGSuiteConfig.
#>
[cmdletbinding()]
Param ()
$script:ConfigScope = $Scope
$fullConf = Import-SpecificConfiguration -CompanyName 'SCRT HQ' -Name 'PSGSuite' -Scope $Script:ConfigScope
$fullConf.Keys | Where-Object {$_ -ne 'DefaultConfig'}
}
31 changes: 31 additions & 0 deletions PSGSuite/Public/Authentication/Get-PSGSuiteServiceCache.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function Get-PSGSuiteServiceCache {
<#
.SYNOPSIS
Returns the dictionary of cached service objects created with New-GoogleService for inspection.
.DESCRIPTION
Returns the dictionary of cached service objects created with New-GoogleService for inspection.
The keys in the session cache dictionary are comprised of the following values which are added to the cache whenever a new session is created:
$SessionKey = @($User,$ServiceType,$(($Scope | Sort-Object) -join ";")) -join ";"
.EXAMPLE
Get-PSGSuiteServiceCache
#>
[CmdletBinding()]
Param (
[parameter(Mandatory = $false,Position = 0)]
[Switch]
$IncludeKeys
)
Begin{
if (-not $script:_PSGSuiteSessions) {
$script:_PSGSuiteSessions = @{}
}
}
Process {
Write-Verbose "Getting cached session list"
$script:_PSGSuiteSessions.Values
}
}
139 changes: 84 additions & 55 deletions PSGSuite/Public/Authentication/New-GoogleService.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,69 +13,98 @@ function New-GoogleService {
[String]
$User = $script:PSGSuite.AdminEmail
)
Begin {
if (-not $script:_PSGSuiteSessions) {
$script:_PSGSuiteSessions = @{}
}
$sessionKey = @($User,$ServiceType,$(($Scope | Sort-Object) -join ";")) -join ";"
}
Process {
if ($script:PSGSuite.P12KeyPath -or $script:PSGSuite.P12Key) {
try {
Write-Verbose "Building ServiceAccountCredential from P12Key as user '$User'"
if (-not $script:PSGSuite.P12Key) {
$script:PSGSuite.P12Key = ([System.IO.File]::ReadAllBytes($script:PSGSuite.P12KeyPath))
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -P12Key $script:PSGSuite.P12Key -Verbose:$false
if ($script:_PSGSuiteSessions.ContainsKey($sessionKey)) {
if (-not $script:_PSGSuiteSessions[$sessionKey].Acknowledged) {
Write-Verbose "Using matching cached service for user '$User'"
$script:_PSGSuiteSessions[$sessionKey].Acknowledged = $true
}
$script:_PSGSuiteSessions[$sessionKey] | Select-Object -ExpandProperty Service
}
else {
if ($script:PSGSuite.P12KeyPath -or $script:PSGSuite.P12Key) {
try {
Write-Verbose "Building ServiceAccountCredential from P12Key as user '$User'"
if (-not $script:PSGSuite.P12Key) {
$script:PSGSuite.P12Key = ([System.IO.File]::ReadAllBytes($script:PSGSuite.P12KeyPath))
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -P12Key $script:PSGSuite.P12Key -Verbose:$false
}
$certificate = New-Object 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList ([System.Byte[]]$script:PSGSuite.P12Key),"notasecret",([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$credential = New-Object 'Google.Apis.Auth.OAuth2.ServiceAccountCredential' (New-Object 'Google.Apis.Auth.OAuth2.ServiceAccountCredential+Initializer' $script:PSGSuite.AppEmail -Property @{
User = $User
Scopes = [string[]]$Scope
}
).FromCertificate($certificate)
}
$certificate = New-Object 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList ([System.Byte[]]$script:PSGSuite.P12Key),"notasecret",([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$credential = New-Object 'Google.Apis.Auth.OAuth2.ServiceAccountCredential' (New-Object 'Google.Apis.Auth.OAuth2.ServiceAccountCredential+Initializer' $script:PSGSuite.AppEmail -Property @{
User = $User
Scopes = [string[]]$Scope
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
).FromCertificate($certificate)
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
}
elseif ($script:PSGSuite.ClientSecretsPath -or $script:PSGSuite.ClientSecrets) {
try {
$ClientSecretsScopes = @(
'https://www.google.com/m8/feeds'
'https://mail.google.com'
'https://www.googleapis.com/auth/gmail.settings.basic'
'https://www.googleapis.com/auth/gmail.settings.sharing'
'https://www.googleapis.com/auth/calendar'
'https://www.googleapis.com/auth/drive'
'https://www.googleapis.com/auth/tasks'
'https://www.googleapis.com/auth/tasks.readonly'
)
if (-not $script:PSGSuite.ClientSecrets) {
$script:PSGSuite.ClientSecrets = ([System.IO.File]::ReadAllText($script:PSGSuite.ClientSecretsPath))
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -ClientSecrets $script:PSGSuite.ClientSecrets -Verbose:$false
elseif ($script:PSGSuite.ClientSecretsPath -or $script:PSGSuite.ClientSecrets) {
try {
$ClientSecretsScopes = @(
'https://www.google.com/m8/feeds'
'https://mail.google.com'
'https://www.googleapis.com/auth/gmail.settings.basic'
'https://www.googleapis.com/auth/gmail.settings.sharing'
'https://www.googleapis.com/auth/calendar'
'https://www.googleapis.com/auth/drive'
'https://www.googleapis.com/auth/tasks'
'https://www.googleapis.com/auth/tasks.readonly'
)
if (-not $script:PSGSuite.ClientSecrets) {
$script:PSGSuite.ClientSecrets = ([System.IO.File]::ReadAllText($script:PSGSuite.ClientSecretsPath))
Set-PSGSuiteConfig -ConfigName $script:PSGSuite.ConfigName -ClientSecrets $script:PSGSuite.ClientSecrets -Verbose:$false
}
$credPath = Join-Path (Resolve-Path (Join-Path "~" ".scrthq")) "PSGSuite"
Write-Verbose "Building UserCredentials from ClientSecrets as user '$User' and prompting for authorization if necessary."
$stream = New-Object System.IO.MemoryStream $([System.Text.Encoding]::ASCII.GetBytes(($script:PSGSuite.ClientSecrets))),$null
$credential = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync(
[Google.Apis.Auth.OAuth2.GoogleClientSecrets]::Load($stream).Secrets,
[string[]]$ClientSecretsScopes,
$User,
[System.Threading.CancellationToken]::None,
[Google.Apis.Util.Store.FileDataStore]::new($credPath,$true),
$(if ($PSVersionTable.PSVersion.Major -gt 5) {
New-Object 'Google.Apis.Auth.OAuth2.PromptCodeReceiver'
}
else {
New-Object 'Google.Apis.Auth.OAuth2.LocalServerCodeReceiver'
})
).Result
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
}
finally {
if ($stream) {
$stream.Close()
}
}
$credPath = Join-Path (Resolve-Path (Join-Path "~" ".scrthq")) "PSGSuite"
Write-Verbose "Building UserCredentials from ClientSecrets as user '$User' and prompting for authorization if necessary."
$stream = New-Object System.IO.MemoryStream $([System.Text.Encoding]::ASCII.GetBytes(($script:PSGSuite.ClientSecrets))),$null
$credential = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync(
[Google.Apis.Auth.OAuth2.GoogleClientSecrets]::Load($stream).Secrets,
[string[]]$ClientSecretsScopes,
$User,
[System.Threading.CancellationToken]::None,
[Google.Apis.Util.Store.FileDataStore]::new($credPath,$true),
$(if($PSVersionTable.PSVersion.Major -gt 5){New-Object 'Google.Apis.Auth.OAuth2.PromptCodeReceiver'}else{New-Object 'Google.Apis.Auth.OAuth2.LocalServerCodeReceiver'})
).Result
}
catch {
$PSCmdlet.ThrowTerminatingError($_)
else {
$PSCmdlet.ThrowTerminatingError((ThrowTerm "The current config '$($script:PSGSuite.ConfigName)' does not contain a P12KeyPath or a ClientSecretsPath! PSGSuite is unable to build a credential object for the service without a path to a credential file! Please update the configuration to include a path at least one of the two credential types."))
}
finally {
if ($stream) {
$stream.Close()
$svc = New-Object "$ServiceType" (New-Object 'Google.Apis.Services.BaseClientService+Initializer' -Property @{
HttpClientInitializer = $credential
ApplicationName = "PSGSuite - $env:USERNAME"
}
}
)
$issued = Get-Date
$script:_PSGSuiteSessions[$sessionKey] = ([PSCustomObject]@{
User = $User
Scope = $Scope
Service = $svc
Issued = $issued
Acknowledged = $false
})
return $svc
}
else {
$PSCmdlet.ThrowTerminatingError((ThrowTerm "The current config '$($script:PSGSuite.ConfigName)' does not contain a P12KeyPath or a ClientSecretsPath! PSGSuite is unable to build a credential object for the service without a path to a credential file! Please update the configuration to include a path at least one of the two credential types."))
}
New-Object "$ServiceType" (New-Object 'Google.Apis.Services.BaseClientService+Initializer' -Property @{
HttpClientInitializer = $credential
ApplicationName = "PSGSuite - $env:USERNAME"
}
)
}
}
139 changes: 139 additions & 0 deletions PSGSuite/Public/Calendar/Get-GSCalendar.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
function Get-GSCalendar {
<#
.SYNOPSIS
Gets the calendars for a user
.DESCRIPTION
Gets the calendars for a user
.PARAMETER CalendarId
The Id of the calendar you would like to get.
If excluded, returns the list of calendars for the 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 MinAccessRole
The minimum access role for the user in the returned entries. Optional. The default is no restriction.
.PARAMETER PageSize
Maximum number of entries returned on one result page. The page size can never be larger than 250 entries.
.PARAMETER ShowDeleted
Whether to include deleted calendar list entries in the result. Optional. The default is False.
.PARAMETER ShowHidden
Whether to show hidden entries. Optional. The default is False.
.PARAMETER SyncToken
Token obtained from the nextSyncToken field returned on the last page of results from the previous list request. It makes the result of this list request contain only entries that have changed since then.
If only read-only fields such as calendar properties or ACLs have changed, the entry won't be returned. All entries deleted and hidden since the previous list request will always be in the result set and it is not allowed to set showDeleted neither showHidden to False.
To ensure client state consistency minAccessRole query parameter cannot be specified together with nextSyncToken. If the syncToken expires, the server will respond with a 410 GONE response code and the client should clear its storage and perform a full synchronization without any syncToken. Learn more about incremental synchronization.
Optional. The default is to return all entries.
#>
[OutputType('Google.Apis.Calendar.v3.Data.CalendarListEntry')]
[cmdletbinding(DefaultParameterSetName = "List")]
Param
(
[parameter(Mandatory = $true,Position = 0,ParameterSetName = "Get")]
[String[]]
$CalendarId,
[parameter(Mandatory = $false,ValueFromPipeline = $true,ValueFromPipelineByPropertyName = $true)]
[Alias("PrimaryEmail","UserKey","Mail")]
[ValidateNotNullOrEmpty()]
[String[]]
$User = $Script:PSGSuite.AdminEmail,
[parameter(Mandatory = $false,ParameterSetName = "List")]
[Google.Apis.Calendar.v3.CalendarListResource+ListRequest+MinAccessRoleEnum]
$MinAccessRole,
[parameter(Mandatory = $false,ParameterSetName = "List")]
[Alias('MaxResults')]
[ValidateRange(1,250)]
[Int]
$PageSize = 250,
[parameter(Mandatory = $false,ParameterSetName = "List")]
[switch]
$ShowDeleted,
[parameter(Mandatory = $false,ParameterSetName = "List")]
[switch]
$ShowHidden,
[parameter(Mandatory = $false,ParameterSetName = "List")]
[String]
$SyncToken
)
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
switch ($PSCmdlet.ParameterSetName) {
Get {
foreach ($calId in $CalendarId) {
try {
$request = $service.CalendarList.Get($calId)
Write-Verbose "Getting Calendar Id '$calId' for User '$U'"
$request.Execute() | Add-Member -MemberType NoteProperty -Name 'User' -Value $U -PassThru
}
catch {
if ($ErrorActionPreference -eq 'Stop') {
$PSCmdlet.ThrowTerminatingError($_)
}
else {
Write-Error $_
}
}
}
}
List {
try {
$request = $service.CalendarList.List()
foreach ($key in $PSBoundParameters.Keys | Where-Object {$_ -ne 'CalendarId'}) {
if ($request.PSObject.Properties.Name -contains $key) {
$request.$key = $PSBoundParameters[$key]
}
}
if ($PageSize) {
$request.MaxResults = $PageSize
}
Write-Verbose "Getting Calendar List for user '$U'"
[int]$i = 1
do {
$result = $request.Execute()
$result.Items | Add-Member -MemberType NoteProperty -Name 'User' -Value $U -PassThru
if ($result.NextPageToken) {
$request.PageToken = $result.NextPageToken
}
[int]$retrieved = ($i + $result.Items.Count) - 1
Write-Verbose "Retrieved $retrieved Calendars..."
[int]$i = $i + $result.Items.Count
}
until (!$result.NextPageToken)
}
catch {
if ($ErrorActionPreference -eq 'Stop') {
$PSCmdlet.ThrowTerminatingError($_)
}
else {
Write-Error $_
}
}
}
}
}
}
}
Loading

0 comments on commit 0553e1f

Please sign in to comment.