@@ -7,10 +7,18 @@ import { getRecordTitle, getRecordType } from '../../records/RecordUtils'
77import { updateRecord } from '../../records/RecordOperations'
88import { KeeperSdkError , ResultCodes } from '../../utils'
99import { SCRIPT_FIELD_TYPE } from './rotationConstants'
10- import type { PamRecordData , RotationScriptValue , ScriptFieldLocation , ScriptSearchResult } from './rotationScriptTypes'
11-
12- export function findPamRecordsByName ( storage : InMemoryStorage , searchText : string ) : DRecord [ ] {
13- const results : DRecord [ ] = [ ]
10+ import type {
11+ PamRecord ,
12+ PamRecordData ,
13+ RecordField ,
14+ RotationScriptValue ,
15+ ScriptField ,
16+ ScriptFieldLocation ,
17+ ScriptSearchResult ,
18+ } from './rotationScriptTypes'
19+
20+ export function findPamRecordsByName ( storage : InMemoryStorage , searchText : string ) : PamRecord [ ] {
21+ const results : PamRecord [ ] = [ ]
1422 const searchLower = searchText . toLowerCase ( )
1523
1624 const allRecords = storage . getRecords ( )
@@ -21,6 +29,7 @@ export function findPamRecordsByName(storage: InMemoryStorage, searchText: strin
2129 if ( recordType !== 'pamUser' && recordType !== 'pamDirectory' ) {
2230 continue
2331 }
32+ if ( ! isPamRecord ( record ) ) continue
2433
2534 const title = getRecordTitle ( record ) || ''
2635 if (
@@ -39,7 +48,15 @@ export function getRecordTitleSafe(record: DRecord): string {
3948 return getRecordTitle ( record ) || record . uid
4049}
4150
42- export function getSinglePamRecord ( storage : InMemoryStorage , recordName : string ) : DRecord {
51+ function isPamRecordData ( data : unknown ) : data is PamRecordData {
52+ return typeof data === 'object' && data !== null && Array . isArray ( ( data as { fields ?: unknown } ) . fields )
53+ }
54+
55+ export function isPamRecord ( record : DRecord ) : record is PamRecord {
56+ return isPamRecordData ( record . data )
57+ }
58+
59+ export function getSinglePamRecord ( storage : InMemoryStorage , recordName : string ) : PamRecord {
4360 const recordNameTrimmed = recordName ?. trim ( )
4461 if ( ! recordNameTrimmed ) {
4562 throw new KeeperSdkError ( 'Record UID or title is required' , ResultCodes . INVALID_PATTERN )
@@ -66,34 +83,45 @@ export function getSinglePamRecord(storage: InMemoryStorage, recordName: string)
6683 )
6784 }
6885
86+ if ( ! isPamRecord ( record ) ) {
87+ throw new KeeperSdkError (
88+ `PAM record "${ recordNameTrimmed } " has invalid record data` ,
89+ ResultCodes . PAM_CONFIG_INVALID
90+ )
91+ }
92+
6993 return record
7094}
7195
96+ function isRotationScriptValue ( value : unknown ) : value is RotationScriptValue {
97+ if ( typeof value !== 'object' || value === null ) return false
98+ const candidate = value as Partial < RotationScriptValue >
99+ return (
100+ typeof candidate . fileRef === 'string' &&
101+ Array . isArray ( candidate . recordRef ) &&
102+ candidate . recordRef . every ( ( uid ) : uid is string => typeof uid === 'string' ) &&
103+ typeof candidate . command === 'string'
104+ )
105+ }
106+
107+ function isScriptField ( field : RecordField ) : field is ScriptField {
108+ return field . type === SCRIPT_FIELD_TYPE && Array . isArray ( field . value ) && field . value . every ( isRotationScriptValue )
109+ }
110+
72111export function findScriptFieldsInRecord ( recordData : PamRecordData ) : ScriptFieldLocation [ ] {
73112 const results : ScriptFieldLocation [ ] = [ ]
74113
75114 const dataFields = recordData . fields || [ ]
76115 for ( let i = 0 ; i < dataFields . length ; i ++ ) {
77116 const field = dataFields [ i ]
78- if ( field . type !== SCRIPT_FIELD_TYPE ) continue
79-
80- const value = field . value as unknown
81- if ( ! Array . isArray ( value ) ) continue
82-
83- for ( let j = 0 ; j < value . length ; j ++ ) {
84- const script = value [ j ]
85- if (
86- script &&
87- typeof script === 'object' &&
88- 'fileRef' in script &&
89- typeof ( script as any ) . fileRef === 'string'
90- ) {
91- results . push ( {
92- fieldIndex : i ,
93- scriptIndex : j ,
94- script : script as RotationScriptValue ,
95- } )
96- }
117+ if ( ! isScriptField ( field ) ) continue
118+
119+ for ( let j = 0 ; j < field . value . length ; j ++ ) {
120+ results . push ( {
121+ fieldIndex : i ,
122+ scriptIndex : j ,
123+ script : field . value [ j ] ,
124+ } )
97125 }
98126 }
99127
@@ -128,22 +156,23 @@ export function findScriptByUidOrName(
128156}
129157
130158export function expandFilePath ( filePath : string ) : string {
131- return filePath . startsWith ( '~' ) ? path . join ( process . env . HOME || '' , filePath . slice ( 1 ) ) : filePath
159+ const expandedPath = filePath . startsWith ( '~' ) ? path . join ( process . env . HOME || '' , filePath . slice ( 1 ) ) : filePath
160+ return path . resolve ( expandedPath )
132161}
133162
134163export function validateScriptFileExists ( filePath : string ) : string {
135164 const expandedPath = expandFilePath ( filePath )
136- if ( ! fs . existsSync ( expandedPath ) ) {
165+ if ( ! fs . existsSync ( expandedPath ) || ! fs . statSync ( expandedPath ) . isFile ( ) ) {
137166 throw new KeeperSdkError ( `Script file not found: ${ filePath } ` , ResultCodes . PAM_CONFIG_CREATE_FAILED )
138167 }
139168 return expandedPath
140169}
141170
142171export async function updatePamRecordFields (
143172 auth : Auth ,
144- record : DRecord ,
173+ record : PamRecord ,
145174 recordType : string ,
146- fields : unknown [ ] ,
175+ fields : RecordField [ ] ,
147176 currentRevision : number ,
148177 storage : InMemoryStorage
149178) : Promise < void > {
@@ -155,14 +184,14 @@ export async function updatePamRecordFields(
155184 )
156185 }
157186
158- const recordData = ( record . data as PamRecordData ) || { fields : [ ] }
187+ const recordData = record . data
159188 const updateResult = await updateRecord (
160189 auth ,
161190 record . uid ,
162191 {
163192 type : recordType ,
164193 title : getRecordTitle ( record ) || '' ,
165- fields : fields as any ,
194+ fields,
166195 notes : recordData . notes || '' ,
167196 } ,
168197 currentRevision ,
0 commit comments