Skip to content

Commit 8177f37

Browse files
kpande-kssk-keeper
authored andcommitted
Add support for listing classic and nested records (#481)
1 parent 8d80c1e commit 8177f37

1 file changed

Lines changed: 142 additions & 7 deletions

File tree

PowerCommander/RecordCommands.ps1

Lines changed: 142 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,113 @@
11
#requires -Version 5.1
22

3+
class KeeperRecordListItem {
4+
[string]$RecordUid
5+
[string]$Name
6+
[string]$Type
7+
[string]$Category
8+
[string]$Description
9+
[int]$Version
10+
[long]$Revision
11+
[bool]$Shared
12+
}
13+
14+
function Get-KeeperRecordListItems {
15+
Param(
16+
[Parameter(Mandatory = $true)][KeeperSecurity.Vault.VaultOnline] $Vault,
17+
[Parameter()][switch] $ClassicOnly
18+
)
19+
20+
if (-not $Vault) {
21+
Write-Error -Message "Not connected to Keeper. Please run Connect-Keeper first."
22+
return [System.Collections.Generic.List[KeeperRecordListItem]]::new()
23+
}
24+
25+
$records = [System.Collections.Generic.List[KeeperRecordListItem]]::new()
26+
27+
if (-not $ClassicOnly.IsPresent) {
28+
foreach ($record in $Vault.KeeperNSFRecordEntries) {
29+
$name = if ($record.Title) { $record.Title } else { '' }
30+
$type = if ($record.Type) { $record.Type } else { 'Unknown' }
31+
if (Get-Command Get-KdRecordTypeAndTitle -ErrorAction SilentlyContinue) {
32+
$meta = Get-KdRecordTypeAndTitle $record
33+
$type = $meta.Type
34+
if (-not $name) { $name = $meta.Title }
35+
}
36+
37+
$item = [KeeperRecordListItem]::new()
38+
$item.RecordUid = $record.RecordUid
39+
$item.Name = $name
40+
$item.Type = $type
41+
$item.Category = 'nested'
42+
$item.Description = if ($record.Notes) { $record.Notes.Trim() } else { '' }
43+
$item.Version = $record.Version
44+
$item.Revision = $record.Revision
45+
$item.Shared = $record.Shared
46+
$records.Add($item) | Out-Null
47+
}
48+
}
49+
50+
foreach ($record in $Vault.KeeperRecords) {
51+
if ($record.Version -ne 2 -and $record.Version -ne 3) { continue }
52+
53+
$item = [KeeperRecordListItem]::new()
54+
$item.RecordUid = $record.Uid
55+
$item.Name = if ($record.Title) { $record.Title } else { '' }
56+
$item.Type = [KeeperSecurity.Utils.RecordTypesUtils]::KeeperRecordType($record)
57+
$item.Category = 'classic'
58+
$item.Description = if ($record.Notes) { $record.Notes.Trim() } else { '' }
59+
$item.Version = $record.Version
60+
$item.Revision = $record.Revision
61+
$item.Shared = $record.Shared
62+
$records.Add($item) | Out-Null
63+
}
64+
65+
return $records
66+
}
67+
68+
function Test-KeeperRecordFormattedListOutput {
69+
Param(
70+
[Parameter(Mandatory = $true)][System.Management.Automation.InvocationInfo] $Invocation
71+
)
72+
73+
if ([Console]::IsOutputRedirected) { return $false }
74+
75+
$line = $Invocation.Line
76+
if ([string]::IsNullOrWhiteSpace($line)) { return $true }
77+
78+
if ($line -match '(?<![\w-])(kr|Get-KeeperRecord)\b[^;\r\n]*\|\s*\S') { return $false }
79+
if ($line -match '=\s*(kr\b|Get-KeeperRecord\b)') { return $false }
80+
81+
return $true
82+
}
83+
384
function Get-KeeperRecord {
485
<#
586
.Synopsis
687
Get Keeper Records
788
89+
.Description
90+
Lists classic and nested records with Category and Description.
91+
892
.Parameter Uid
993
Record UID
1094
1195
.Parameter Filter
12-
Return matching records only
96+
Return matching classic records only as KeeperRecord objects
97+
98+
.Parameter AsObject
99+
Return unified list rows (KeeperRecordListItem) for scripting
100+
101+
.Parameter ClassicOnly
102+
Exclude nested shared (NSF) records from the interactive list
13103
#>
14104
[CmdletBinding()]
15105
[OutputType([KeeperSecurity.Vault.KeeperRecord[]])]
16106
Param (
17107
[string] $Uid,
18-
[string] $Filter
108+
[string] $Filter,
109+
[Parameter()][switch] $AsObject,
110+
[Parameter()][switch] $ClassicOnly
19111
)
20112

21113
[KeeperSecurity.Vault.VaultOnline]$vault = getVault
@@ -28,14 +120,57 @@ function Get-KeeperRecord {
28120
Get-KeeperNSFRecord -Uid $Uid
29121
}
30122
}
31-
else {
123+
elseif ($Filter) {
32124
foreach ($record in $vault.KeeperRecords) {
33-
if ($Filter) {
34-
$match = $($record.Uid, $record.TypeName, $record.Title, $record.Notes) | Select-String $Filter | Select-Object -First 1
35-
if (-not $match) {
36-
continue
125+
$match = $($record.Uid, $record.TypeName, $record.Title, $record.Notes) | Select-String $Filter | Select-Object -First 1
126+
if (-not $match) {
127+
continue
128+
}
129+
$record
130+
}
131+
}
132+
else {
133+
$useListOutput = $AsObject.IsPresent -or (Test-KeeperRecordFormattedListOutput -Invocation $MyInvocation)
134+
if ($useListOutput) {
135+
$items = [System.Collections.Generic.List[KeeperRecordListItem]]::new()
136+
foreach ($item in (Get-KeeperRecordListItems -Vault $vault -ClassicOnly:$ClassicOnly.IsPresent | Sort-Object -Property Name)) {
137+
$items.Add($item) | Out-Null
138+
}
139+
140+
if (-not $AsObject.IsPresent) {
141+
if ($items.Count -eq 0) {
142+
Write-Host "No records found."
143+
return
144+
}
145+
146+
Write-Host ""
147+
Write-Host "Found $($items.Count) record(s)" -ForegroundColor Green
148+
Write-Host ""
149+
150+
$rows = foreach ($item in $items) {
151+
$desc = $item.Description
152+
if (-not [string]::IsNullOrEmpty($desc)) {
153+
$desc = ($desc -replace '\s+', ' ').Trim()
154+
if ($desc.Length -gt 36) { $desc = $desc.Substring(0, 33) + '...' }
155+
}
156+
[PSCustomObject]@{
157+
UID = $item.RecordUid
158+
Name = $item.Name
159+
Type = $item.Type
160+
Category = $item.Category
161+
Description = $desc
162+
Version = $item.Version
163+
Revision = $item.Revision
164+
Shared = $item.Shared
165+
}
37166
}
167+
return $rows
38168
}
169+
170+
return $items
171+
}
172+
173+
foreach ($record in $vault.KeeperRecords) {
39174
$record
40175
}
41176
}

0 commit comments

Comments
 (0)