Skip to content

Commit 9288ea1

Browse files
committed
Initial commit
- Set-TeamViewerDevicesPolicy - Remove-TeamViewerOutdatedDevice
0 parents  commit 9288ea1

File tree

8 files changed

+836
-0
lines changed

8 files changed

+836
-0
lines changed

LICENSE.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2019 TeamViewer GmbH
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# TeamViewer API Example Scripts
2+
3+
## Contents
4+
5+
* [Set-TeamViewerDevicesPolicy](Set-TeamViewerDevicesPolicy):
6+
Sets the policy for a list of TeamViewer devices.
7+
* [Remove-TeamViewerOutdatedDevice](Remove-TeamViewerOutdatedDevice):
8+
Removes TeamViewer devices that didn't appear online for a given time.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Remove-TeamViewerOutdatedDevice
2+
3+
Removes TeamViewer devices that didn't appear online for a given time.
4+
5+
The script fetches a list of TeamViewer devices of the TeamViewer company
6+
that corresponds to a given API token. The list will be filtered by
7+
devices being offline for a certain amount of time. These devices will
8+
be removed.
9+
The expiration can either be specified by a specific date or by interval.
10+
11+
## Examples
12+
13+
### List removal candidate devices that have been offline since at least 2018-12-18 00:00:00
14+
15+
```
16+
.\Remove-TeamViewerOutdatedDevice -ExpiryDate 2018-12-18 -WhatIf
17+
```
18+
19+
### List removal candidate devices that have been offline since at least 2018-12-17 17:00:00
20+
21+
```
22+
.\Remove-TeamViewerOutdatedDevice -ExpiryDate '2018-12-17T17:00:00' -WhatIf
23+
```
24+
25+
### List removal candidate devices that have been offline since at least 10 days
26+
27+
```
28+
.\Remove-TeamViewerOutdatedDevice -ExpiryInterval -Days 10 -WhatIf
29+
```
30+
31+
### Remove devices that have been offline since at least 30 days. User needs to confirm
32+
33+
```
34+
.\Remove-TeamViewerOutdatedDevice -ExpiryInterval -Days 30
35+
```
36+
37+
### Remove devices that have been offline since at least 12 hours without further confirmation
38+
39+
```
40+
.\Remove-TeamViewerOutdatedDevice -ExpiryInterval -Hours 12 -Force
41+
```
42+
43+
## More help
44+
45+
To get further help about the script and its parameters, execute the
46+
`Get-Help` PowerShell cmdlet:
47+
48+
```
49+
Get-Help -Detailed .\Remove-TeamViewerOutdatedDevice.ps1
50+
```
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Copyright (c) 2019 TeamViewer GmbH
2+
# See file LICENSE.txt
3+
4+
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
5+
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
6+
. "$here\$sut" -ApiToken "test" -ExpiryDate (Get-Date) -InformationAction 'SilentlyContinue'
7+
8+
Describe '.\Remove-TeamViewerOutdatedDevice' {
9+
Mock Get-TeamViewerDevice {@{
10+
devices = @(
11+
[pscustomobject]@{ device_id = 'device1'; alias = 'device1'; last_seen = '2018-12-16' },
12+
[pscustomobject]@{ device_id = 'device2'; alias = 'device2'; last_seen = '2018-12-17' },
13+
[pscustomobject]@{ device_id = 'device3'; alias = 'device3'; last_seen = '2018-12-18' },
14+
[pscustomobject]@{ device_id = 'device4'; alias = 'device4'; last_seen = '2018-12-19' })
15+
}}
16+
Mock Remove-TeamViewerDevice {}
17+
18+
It 'Should list devices that are offline since the expiration date' {
19+
$result = (Remove-TeamViewerOutdatedDevice 'TestToken' ([DateTime]'2018-12-18') -force:$false -WhatIf)
20+
$result | Should -HaveCount 3
21+
$result[0].DeviceId | Should -Be 'device1'
22+
$result[0].Status | Should -Be 'Unchanged'
23+
$result[1].DeviceId | Should -Be 'device2'
24+
$result[1].Status | Should -Be 'Unchanged'
25+
$result[2].DeviceId | Should -Be 'device3'
26+
$result[2].Status | Should -Be 'Unchanged'
27+
Assert-MockCalled Get-TeamViewerDevice -Times 1 -Scope It
28+
Assert-MockCalled Remove-TeamViewerDevice -Times 0 -Scope It
29+
}
30+
31+
It 'Should remove devices that are offline since the expiration date' {
32+
$result = (Remove-TeamViewerOutdatedDevice 'TestToken' ([DateTime]'2018-12-18') -force:$true)
33+
$result | Should -HaveCount 3
34+
$result[0].DeviceId | Should -Be 'device1'
35+
$result[0].Status | Should -Be 'Removed'
36+
$result[1].DeviceId | Should -Be 'device2'
37+
$result[1].Status | Should -Be 'Removed'
38+
$result[2].DeviceId | Should -Be 'device3'
39+
$result[2].Status | Should -Be 'Removed'
40+
Assert-MockCalled Get-TeamViewerDevice -Times 1 -Scope It
41+
Assert-MockCalled Remove-TeamViewerDevice -Times 3 -Scope It
42+
}
43+
}
44+
45+
Describe 'ConvertTo-TeamViewerRestError' {
46+
It 'Should convert from JSON' {
47+
$result = ('{"foo": "bar"}' | ConvertTo-TeamViewerRestError)
48+
$result.foo | Should -Be 'bar'
49+
}
50+
51+
It 'Should return input object for invalid JSON' {
52+
$result = ('garbage' | ConvertTo-TeamViewerRestError)
53+
$result | Should -Be 'garbage'
54+
}
55+
}
56+
57+
Describe 'Invoke-TeamViewerRestMethod' {
58+
Mock Invoke-WebRequest { @{Content = '{"foo": "bar"}'} }
59+
60+
It 'Should call Invoke-WebRequest and convert the result from JSON' {
61+
$result = Invoke-TeamViewerRestMethod -Uri 'http://example.test'
62+
$result.foo | Should -Be 'bar'
63+
Assert-MockCalled Invoke-WebRequest `
64+
-ParameterFilter { $Uri -eq 'http://example.test' }-Times 1 -Scope It
65+
}
66+
}
67+
68+
Describe 'Get-TeamViewerDevice' {
69+
Mock Invoke-WebRequest { @{Content = '{}'} }
70+
71+
It 'Should call the "devices" TeamViewer Web API endpoint' {
72+
Get-TeamViewerDevice 'TestToken'
73+
Assert-MockCalled Invoke-WebRequest -Times 1 -Scope It -ParameterFilter {
74+
$Uri -And [System.Uri]$Uri.PathAndQuery -eq '/api/v1/devices' -And
75+
$Method -And $Method -eq 'Get'
76+
}
77+
}
78+
79+
It 'Should set specified "online_state" parameter' {
80+
Get-TeamViewerDevice 'TestToken' 'offline'
81+
Assert-MockCalled Invoke-WebRequest -Times 1 -Scope It -ParameterFilter {
82+
$Uri -And [System.Uri]$Uri.PathAndQuery -eq '/api/v1/devices' -And
83+
$Method -And $Method -eq 'Get' -And
84+
$Body -And $Body.online_state -eq 'offline'
85+
}
86+
}
87+
88+
It 'Should set the authorization header' {
89+
Get-TeamViewerDevice 'TestToken'
90+
Assert-MockCalled Invoke-WebRequest -Times 1 -Scope It -ParameterFilter {
91+
$Headers -And $Headers.ContainsKey('authorization') -And `
92+
$Headers.authorization -eq 'Bearer TestToken'
93+
}
94+
}
95+
}
96+
97+
Describe 'Remove-TeamViewerDevice' {
98+
Mock Invoke-WebRequest { @{Content = '{}'} }
99+
100+
It 'Should call the "devices" TeamViewer Web API endpoint' {
101+
Remove-TeamViewerDevice 'TestToken' 'device1'
102+
Assert-MockCalled Invoke-WebRequest -Times 1 -Scope It -ParameterFilter {
103+
$Uri -And [System.Uri]$Uri.PathAndQuery -eq '/api/v1/devices/device1' -And
104+
$Method -And $Method -eq 'Delete'
105+
}
106+
}
107+
108+
It 'Should set the authorization header' {
109+
Remove-TeamViewerDevice 'TestToken' 'device1'
110+
Assert-MockCalled Invoke-WebRequest -Times 1 -Scope It -ParameterFilter {
111+
$Headers -And $Headers.ContainsKey('authorization') -And `
112+
$Headers.authorization -eq 'Bearer TestToken'
113+
}
114+
}
115+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<#
2+
.SYNOPSIS
3+
Removes TeamViewer devices that didn't appear online for a given time.
4+
5+
.DESCRIPTION
6+
The script fetches a list of TeamViewer devices of the TeamViewer company
7+
that corresponds to a given API token. The list will be filtered by
8+
devices being offline for a certain amount of time. These devices will
9+
be removed.
10+
The expiration can either be specified by a specific date or by interval.
11+
12+
.PARAMETER ApiToken
13+
The TeamViewer API token to use.
14+
Must be a user access token.
15+
The token requires the following access permissions:
16+
- `Computer & Contacts > View entries, add entries, edit entries, remove entries`
17+
18+
.PARAMETER ExpiryDate
19+
A specific expiry date. All devices that haven't been online since that
20+
date are considered being removed.
21+
22+
.PARAMETER ExpiryInterval
23+
Switch that enables interval-based calculation of the expiration date.
24+
Should be used in combination with the `Days`, `Hours`, `Minutes` and/or
25+
`Seconds` parameter.
26+
27+
.PARAMETER Days
28+
Days of the expiration interval.
29+
Must be used in combination with the `ExpiryInterval` parameter.
30+
31+
.PARAMETER Hours
32+
Hours of the expiration interval.
33+
Must be used in combination with the `ExpiryInterval` parameter.
34+
35+
.PARAMETER Minutes
36+
Minutes of the expiration interval.
37+
Must be used in combination with the `ExpiryInterval` parameter.
38+
39+
.PARAMETER Seconds
40+
Seconds of the expiration interval.
41+
Must be used in combination with the `ExpiryInterval` parameter.
42+
43+
.PARAMETER Remove
44+
If set, the script actually removes outdated devices.
45+
Otherwise, the script only outputs possible removal candidates.
46+
The default value is `false`.
47+
48+
.PARAMETER Force
49+
If set, the script will NOT ask the user for confirmation of the
50+
removal. This parameter only has effect in combination with the
51+
`Remove` parameter.
52+
The default value is `false`, causing the script to ask the user
53+
one more time before starting to remove devices.
54+
55+
.EXAMPLE
56+
.\Remove-TeamViewerOutdatedDevice -ExpiryDate '2018-12-17T17:00:00'
57+
58+
.EXAMPLE
59+
.\Remove-TeamViewerOutdatedDevice -ExpiryDate 2018-12-31 -WhatIf
60+
61+
.EXAMPLE
62+
.\Remove-TeamViewerOutdatedDevice -ExpiryInterval -Days 10
63+
64+
.EXAMPLE
65+
.\Remove-TeamViewerOutdatedDevice -ExpiryInterval -Hours 12 -Force
66+
67+
.NOTES
68+
Copyright (c) 2019 TeamViewer GmbH
69+
See file LICENSE.txt
70+
Version 1.0.0
71+
#>
72+
73+
[CmdletBinding(DefaultParameterSetName="ExactDate", SupportsShouldProcess=$true)]
74+
param(
75+
[Parameter(Mandatory = $true)]
76+
[string] $ApiToken,
77+
78+
[Parameter(ParameterSetName = "ExactDate", Mandatory = $true)]
79+
[DateTime] $ExpiryDate,
80+
81+
[Parameter(ParameterSetName = "DateInterval", Mandatory = $true)]
82+
[switch] $ExpiryInterval,
83+
84+
[Parameter(ParameterSetName = "DateInterval", Mandatory = $false)]
85+
[int] $Days,
86+
87+
[Parameter(ParameterSetName = "DateInterval", Mandatory = $false)]
88+
[int] $Hours,
89+
90+
[Parameter(ParameterSetName = "DateInterval", Mandatory = $false)]
91+
[int] $Minutes,
92+
93+
[Parameter(ParameterSetName = "DateInterval", Mandatory = $false)]
94+
[int] $Seconds,
95+
96+
[Switch] $Force = $false
97+
)
98+
99+
if (-Not $MyInvocation.BoundParameters.ContainsKey('ErrorAction')) { $script:ErrorActionPreference = 'Stop' }
100+
if (-Not $MyInvocation.BoundParameters.ContainsKey('InformationAction')) { $script:InformationPreference = 'Continue' }
101+
102+
$tvApiVersion = 'v1'
103+
$tvApiBaseUrl = 'https://webapi.teamviewer.com'
104+
105+
function ConvertTo-TeamViewerRestError {
106+
param([parameter(ValueFromPipeline)]$err)
107+
try { return ($err | Out-String | ConvertFrom-Json) }
108+
catch { return $err }
109+
}
110+
111+
function Invoke-TeamViewerRestMethod {
112+
# Using `Invoke-WebRequest` instead of `Invoke-RestMethod`:
113+
# There is a known issue for PUT and DELETE operations to hang on Windows Server 2012.
114+
try { return ((Invoke-WebRequest -UseBasicParsing @args).Content | ConvertFrom-Json) }
115+
catch [System.Net.WebException] {
116+
$stream = $_.Exception.Response.GetResponseStream()
117+
$reader = New-Object System.IO.StreamReader($stream)
118+
$reader.BaseStream.Position = 0
119+
Throw ($reader.ReadToEnd() | ConvertTo-TeamViewerRestError)
120+
}
121+
}
122+
123+
function Get-TeamViewerDevice($accessToken, $onlineState) {
124+
return Invoke-TeamViewerRestMethod -Uri "$tvApiBaseUrl/api/$tvApiVersion/devices" `
125+
-Method Get -Headers @{authorization = "Bearer $accessToken"} `
126+
-Body @{ online_state = $onlineState }
127+
}
128+
129+
function Remove-TeamViewerDevice {
130+
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'None')]
131+
param($accessToken, $deviceId)
132+
if ($PSCmdlet.ShouldProcess($deviceId)) {
133+
return Invoke-TeamViewerRestMethod -Uri "$tvApiBaseUrl/api/$tvApiVersion/devices/$deviceId" `
134+
-Method Delete -Headers @{authorization = "Bearer $accessToken"}
135+
}
136+
}
137+
138+
function Remove-TeamViewerOutdatedDevice {
139+
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
140+
param($accessToken, $expiryDate, [bool]$force)
141+
142+
$devices = @((Get-TeamViewerDevice $accessToken 'offline').devices | `
143+
Where-Object { $_.last_seen -And [DateTime]($_.last_seen) -le $expiryDate })
144+
145+
Write-Information "Found $($devices.Count) devices that have been offline since $expiryDate"
146+
147+
if ($devices.Count -gt 0 -And -Not $WhatIfPreference -And -Not $force -And
148+
-Not $PSCmdlet.ShouldContinue("Do you really want to remove those devices?", $devices)) {
149+
Write-Information "Aborting..."
150+
exit
151+
}
152+
153+
ForEach ($device in $devices) {
154+
$status = 'Unchanged'
155+
if ($force -Or $PSCmdlet.ShouldProcess($device.alias)) {
156+
try {
157+
Remove-TeamViewerDevice $accessToken $device.device_id
158+
$status = 'Removed'
159+
}
160+
catch {
161+
Write-Warning "Failed to remove device '$($device.alias)': $_"
162+
$status = 'Failed'
163+
}
164+
}
165+
Write-Output ([pscustomobject]@{
166+
Alias = $device.alias
167+
DeviceId = $device.device_id
168+
LastSeen = [DateTime]($device.last_seen)
169+
Status = $status
170+
})
171+
}
172+
}
173+
174+
if ($MyInvocation.InvocationName -ne '.') {
175+
$now = (Get-Date)
176+
if ($ExpiryInterval) {
177+
$ExpiryDate = $now.AddDays(-1 * $Days).AddHours(-1 * $Hours).AddMinutes(-1 * $Minutes).AddSeconds(-1 * $Seconds)
178+
}
179+
if ($ExpiryDate -ge $now) {
180+
Throw "Invalid expiry date specified: $ExpiryDate"
181+
}
182+
Remove-TeamViewerOutdatedDevice $ApiToken $ExpiryDate $Force
183+
}

0 commit comments

Comments
 (0)