11import { Expose } from 'class-transformer' ;
22import { nanoid } from 'nanoid' ;
33import {
4- AfterLoad ,
54 BeforeInsert ,
65 BeforeUpdate ,
76 Column ,
@@ -14,7 +13,6 @@ import {
1413 Relation ,
1514} from 'typeorm' ;
1615import { ConnectionTypesEnum } from '@rocketadmin/shared-code/dist/src/shared/enums/connection-types-enum.js' ;
17- import { Constants } from '../../helpers/constants/constants.js' ;
1816import { Encryptor } from '../../helpers/encryption/encryptor.js' ;
1917import { isConnectionTypeAgent } from '../../helpers/index.js' ;
2018import { AgentEntity } from '../agent/agent.entity.js' ;
@@ -118,9 +116,18 @@ export class ConnectionEntity {
118116 @Column ( { default : null } )
119117 master_hash ?: string | null ;
120118
119+ /**
120+ * Non-persisted flag indicating whether credentials are currently in decrypted state.
121+ * Used by @BeforeUpdate to decide whether encryption is needed.
122+ */
123+ credentialsDecrypted = false ;
124+
121125 @BeforeUpdate ( )
122126 updateTimestampEncryptCredentials ( ) : void {
123127 this . updatedAt = new Date ( ) ;
128+ if ( ! this . credentialsDecrypted ) {
129+ return ;
130+ }
124131 if ( ! isConnectionTypeAgent ( this . type ) ) {
125132 this . host = Encryptor . encryptData ( this . host ) ;
126133 this . database = Encryptor . encryptData ( this . database ) ;
@@ -138,6 +145,7 @@ export class ConnectionEntity {
138145 this . cert = Encryptor . encryptData ( this . cert ) ;
139146 }
140147 }
148+ this . credentialsDecrypted = false ;
141149 }
142150
143151 @BeforeInsert ( )
@@ -168,51 +176,8 @@ export class ConnectionEntity {
168176 }
169177 }
170178
171- @AfterLoad ( )
172- decryptCredentials ( ) : void {
173- if ( this . isTestConnection ) {
174- const testConnectionsArray = Constants . getTestConnectionsArr ( ) ;
175- const foundTestConnectionByType = testConnectionsArray . find (
176- ( testConnection ) => testConnection . type === this . type ,
177- ) ;
178- if ( foundTestConnectionByType ) {
179- this . host = foundTestConnectionByType . host ;
180- this . database = foundTestConnectionByType . database ;
181- this . username = foundTestConnectionByType . username ;
182- this . password = foundTestConnectionByType . password ;
183- this . port = foundTestConnectionByType . port ;
184- this . ssh = foundTestConnectionByType . ssh ;
185- this . privateSSHKey = foundTestConnectionByType . privateSSHKey ;
186- this . sshHost = foundTestConnectionByType . sshHost ;
187- this . sshPort = foundTestConnectionByType . sshPort ;
188- this . sshUsername = foundTestConnectionByType . sshUsername ;
189- this . ssl = foundTestConnectionByType . ssl ;
190- this . cert = foundTestConnectionByType . cert ;
191- this . authSource = foundTestConnectionByType . authSource ;
192- this . sid = foundTestConnectionByType . sid ;
193- this . schema = foundTestConnectionByType . schema ;
194- this . azure_encryption = foundTestConnectionByType . azure_encryption ;
195- }
196- } else {
197- if ( ! isConnectionTypeAgent ( this . type ) ) {
198- this . host = Encryptor . decryptData ( this . host ) ;
199- this . database = Encryptor . decryptData ( this . database ) ;
200- this . password = Encryptor . decryptData ( this . password ) ;
201- this . username = Encryptor . decryptData ( this . username ) ;
202- if ( this . authSource ) {
203- this . authSource = Encryptor . decryptData ( this . authSource ) ;
204- }
205- if ( this . ssh ) {
206- this . privateSSHKey = Encryptor . decryptData ( this . privateSSHKey ) ;
207- this . sshHost = Encryptor . decryptData ( this . sshHost ) ;
208- this . sshUsername = Encryptor . decryptData ( this . sshUsername ) ;
209- }
210- if ( this . ssl && this . cert ) {
211- this . cert = Encryptor . decryptData ( this . cert ) ;
212- }
213- }
214- }
215- }
179+ // Decryption moved to async utility: decrypt-connection-credentials-async.ts
180+ // All repository methods must call decryptConnectionCredentialsAsync() after loading.
216181
217182 @ManyToOne (
218183 ( _ ) => UserEntity ,
0 commit comments