@@ -10,7 +10,7 @@ import { PluginHandler } from '@iobroker/plugin-base';
1010import semver from 'semver' ;
1111import path from 'path' ;
1212import { getObjectsConstructor , getStatesConstructor } from '@iobroker/js-controller-common-db' ;
13- import { getSupportedFeatures , isMessageboxSupported } from './utils' ;
13+ import { decryptArray , encryptArray , getSupportedFeatures , isMessageboxSupported } from './utils' ;
1414// eslint-disable-next-line @typescript-eslint/no-var-requires
1515const extend = require ( 'node.extend' ) ;
1616import type { Client as StatesInRedisClient } from '@iobroker/db-states-redis' ;
@@ -2434,8 +2434,8 @@ export class AdapterClass extends EventEmitter {
24342434 }
24352435
24362436 private async _updateConfig ( options : InternalUpdateConfigOptions ) : ioBroker . SetObjectPromise {
2437- // merge the old and new configuration
2438- const _config = Object . assign ( { } , this . config , options . newConfig ) ;
2437+ const { newConfig } = options ;
2438+
24392439 // update the adapter config object
24402440 const configObjId = `system.adapter.${ this . namespace } ` ;
24412441 let obj ;
@@ -2449,7 +2449,21 @@ export class AdapterClass extends EventEmitter {
24492449 throw new Error ( tools . ERRORS . ERROR_DB_CLOSED ) ;
24502450 }
24512451
2452- obj . native = _config ;
2452+ const oldConfig = obj . native ;
2453+ let mergedConfig : Record < string , unknown > ;
2454+
2455+ // merge the old and new configuration
2456+ if ( 'encryptedNative' in obj && Array . isArray ( obj . encryptedNative ) ) {
2457+ const secret = await this . getSystemSecret ( ) ;
2458+ decryptArray ( { obj : oldConfig , secret, keys : obj . encryptedNative } ) ;
2459+ mergedConfig = { ...oldConfig , ...newConfig } ;
2460+ encryptArray ( { obj : mergedConfig , secret, keys : obj . encryptedNative } ) ;
2461+ } else {
2462+ mergedConfig = { ...oldConfig , ...newConfig } ;
2463+ }
2464+
2465+ obj . native = mergedConfig ;
2466+
24532467 return this . setForeignObjectAsync ( configObjId , obj ) ;
24542468 }
24552469
@@ -2497,25 +2511,34 @@ export class AdapterClass extends EventEmitter {
24972511 const value = ( this . config as InternalAdapterConfig ) [ attribute ] ;
24982512
24992513 if ( typeof value === 'string' ) {
2500- if ( this . _systemSecret !== undefined ) {
2501- return tools . maybeCallbackWithError ( callback , null , tools . decrypt ( this . _systemSecret , value ) ) ;
2502- } else {
2503- try {
2504- const data = await this . getForeignObjectAsync ( 'system.config' ) ;
2505- if ( data ?. native ) {
2506- this . _systemSecret = data . native . secret ;
2507- }
2508- } catch {
2509- // do nothing - we initialize default secret below
2510- }
2511- this . _systemSecret = this . _systemSecret || DEFAULT_SECRET ;
2512- return tools . maybeCallbackWithError ( callback , null , tools . decrypt ( this . _systemSecret , value ) ) ;
2513- }
2514+ const secret = await this . getSystemSecret ( ) ;
2515+ return tools . maybeCallbackWithError ( callback , null , tools . decrypt ( secret , value ) ) ;
25142516 } else {
25152517 return tools . maybeCallbackWithError ( callback , `Attribute "${ attribute } " not found` ) ;
25162518 }
25172519 }
25182520
2521+ /**
2522+ * Get the system secret, after retrived once it will be read from cache
2523+ */
2524+ private async getSystemSecret ( ) : Promise < string > {
2525+ if ( this . _systemSecret !== undefined ) {
2526+ return this . _systemSecret ;
2527+ }
2528+
2529+ try {
2530+ const data = await this . getForeignObjectAsync ( 'system.config' ) ;
2531+ if ( data ?. native ) {
2532+ this . _systemSecret = data . native . secret ;
2533+ }
2534+ } catch {
2535+ // do nothing - we initialize default secret below
2536+ }
2537+
2538+ this . _systemSecret = this . _systemSecret || DEFAULT_SECRET ;
2539+ return this . _systemSecret ;
2540+ }
2541+
25192542 // external signature
25202543 setTimeout ( cb : TimeoutCallback , timeout : number , ...args : any [ ] ) : ioBroker . Timeout | undefined ;
25212544 /**
@@ -8870,10 +8893,10 @@ export class AdapterClass extends EventEmitter {
88708893 // ignore
88718894 }
88728895
8873- if ( data && data . common ) {
8896+ if ( data ? .common ) {
88748897 this . defaultHistory = data . common . defaultHistory ;
88758898 }
8876- if ( data && data . native ) {
8899+ if ( data ? .native ) {
88778900 this . _systemSecret = data . native . secret ;
88788901 }
88798902
@@ -8890,10 +8913,10 @@ export class AdapterClass extends EventEmitter {
88908913 // ignore
88918914 }
88928915
8893- if ( _obj && _obj . rows ) {
8894- for ( let i = 0 ; i < _obj . rows . length ; i ++ ) {
8895- if ( _obj . rows [ i ] . value . common && _obj . rows [ i ] . value . common . type === 'storage' ) {
8896- this . defaultHistory = _obj . rows [ i ] . id . substring ( 'system.adapter.' . length ) ;
8916+ if ( _obj ? .rows ) {
8917+ for ( const row of _obj . rows ) {
8918+ if ( row . value . common && row . value . common . type === 'storage' ) {
8919+ this . defaultHistory = row . id . substring ( 'system.adapter.' . length ) ;
88978920 break ;
88988921 }
88998922 }
@@ -11210,15 +11233,15 @@ export class AdapterClass extends EventEmitter {
1121011233 // Read dateformat if using of formatDate is announced
1121111234 if ( this . _options . useFormatDate ) {
1121211235 adapterObjects . getObject ( 'system.config' , ( err , data ) => {
11213- if ( data && data . common ) {
11236+ if ( data ? .common ) {
1121411237 this . dateFormat = data . common . dateFormat ;
1121511238 this . isFloatComma = data . common . isFloatComma ;
1121611239 this . language = data . common . language ;
1121711240 this . longitude = data . common . longitude ;
1121811241 this . latitude = data . common . latitude ;
1121911242 this . defaultHistory = data . common . defaultHistory ;
1122011243 }
11221- if ( data && data . native ) {
11244+ if ( data ? .native ) {
1122211245 this . _systemSecret = data . native . secret ;
1122311246 }
1122411247 return tools . maybeCallback ( cb ) ;
@@ -11681,18 +11704,8 @@ export class AdapterClass extends EventEmitter {
1168111704 await this . subscribeObjectsAsync ( '*' ) ;
1168211705 }
1168311706
11684- // read the systemSecret
11685- if ( this . _systemSecret === undefined ) {
11686- try {
11687- const data = await adapterObjects . getObjectAsync ( 'system.config' ) ;
11688- if ( data ?. native ) {
11689- this . _systemSecret = data . native . secret ;
11690- }
11691- } catch {
11692- // ignore
11693- }
11694- this . _systemSecret = this . _systemSecret || DEFAULT_SECRET ;
11695- }
11707+ // initialize the system secret
11708+ await this . getSystemSecret ( ) ;
1169611709
1169711710 // Decrypt all attributes of encryptedNative
1169811711 const promises = [ ] ;
@@ -11740,12 +11753,11 @@ export class AdapterClass extends EventEmitter {
1174011753 } ) ;
1174111754
1174211755 if ( this . _options . instance === undefined ) {
11743- this . version =
11744- this . pack && this . pack . version
11745- ? this . pack . version
11746- : this . ioPack && this . ioPack . common
11747- ? this . ioPack . common . version
11748- : 'unknown' ;
11756+ this . version = this . pack ?. version
11757+ ? this . pack . version
11758+ : this . ioPack ?. common
11759+ ? this . ioPack . common . version
11760+ : 'unknown' ;
1174911761 // display if it's a non-official version - only if installedFrom is explicitly given and differs it's not npm
1175011762 const isNpmVersion =
1175111763 ! this . ioPack ||
@@ -11846,7 +11858,6 @@ export class AdapterClass extends EventEmitter {
1184611858
1184711859 /**
1184811860 * Calls the ready handler, if it is an install run it calls the install handler instead
11849- * @private
1185011861 */
1185111862 private _callReadyHandler ( ) : void {
1185211863 if (
0 commit comments