Skip to content

Commit 0b3c6e0

Browse files
authored
Type improvements (#2410)
* started working on auto upgrade feature for adapters * implemented full auto upgrade logic * introduce logging to the auto upgrade manager * make the processExit dummy a one liner * also generate a notification for successful auto upgrades * Filter out values with missing automaticUpgrade config - optimize internal return type for GetObjectView on database level - and fix types due to this - and added some more types like for notifications * fix missing generic arg * updated the getObjectList types * rm outcommented code * group acl have users not user * only auto upgrade if repo changed * incorportate changes from PR #2279 but without the automatic upgrade functionality * remove old methods not used externally and are just aliases internally * improve getObjectView return types on db level * fix some adaptions, because res is always defined on the promise based methods - and rows is always there if we have a return value - and also fix internal promise return type of getObjectList * minor refacotring * added blockedVersions to schema - see #625 * also add blockedVersions to types * filter out all null values instead of only parse errors * clean up found usages of useless guards * some more occurences
1 parent 93e1145 commit 0b3c6e0

File tree

22 files changed

+410
-458
lines changed

22 files changed

+410
-458
lines changed

packages/adapter/src/lib/adapter/adapter.ts

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,37 +1583,40 @@ export class AdapterClass extends EventEmitter {
15831583
}
15841584

15851585
private async _checkPassword(options: InternalCheckPasswordOptions): Promise<void> {
1586-
if (options.user && !options.user.startsWith('system.user.')) {
1586+
let { user } = options;
1587+
const { callback, pw } = options;
1588+
1589+
if (user && !user.startsWith('system.user.')) {
15871590
// it's not yet a `system.user.xy` id, thus we assume it's a username
1588-
if (!this.usernames[options.user]) {
1591+
if (!this.usernames[user]) {
15891592
// we did not find the id of the username in our cache -> update cache
15901593
try {
15911594
await this._updateUsernameCache();
15921595
} catch (e) {
15931596
this._logger.error(`${this.namespaceLog} ${e.message}`);
15941597
}
1595-
if (!this.usernames[options.user]) {
1598+
if (!this.usernames[user]) {
15961599
// user still not there, it's no valid user -> fallback to legacy check
1597-
options.user = `system.user.${options.user
1600+
user = `system.user.${user
15981601
.toString()
15991602
.replace(this.FORBIDDEN_CHARS, '_')
16001603
.replace(/\s/g, '_')
16011604
.replace(/\./g, '_')
16021605
.toLowerCase()}`;
16031606
} else {
1604-
options.user = this.usernames[options.user].id;
1607+
user = this.usernames[user].id;
16051608
}
16061609
} else {
1607-
options.user = this.usernames[options.user].id;
1610+
user = this.usernames[user].id;
16081611
}
16091612
}
16101613

1611-
this.getForeignObject(options.user, options, (err, obj) => {
1612-
if (err || !obj || !obj.common || (!obj.common.enabled && options.user !== SYSTEM_ADMIN_USER)) {
1613-
return tools.maybeCallback(options.callback, false, options.user);
1614+
this.getForeignObject(user, options, (err, obj) => {
1615+
if (err || !obj || !obj.common || (!obj.common.enabled && user !== SYSTEM_ADMIN_USER)) {
1616+
return tools.maybeCallback(callback, false, user);
16141617
} else {
1615-
password(options.pw).check(obj.common.password, (err, res) => {
1616-
return tools.maybeCallback(options.callback, !!res, options.user);
1618+
password(pw).check(obj.common.password, (err, res) => {
1619+
return tools.maybeCallback(callback, !!res, user);
16171620
});
16181621
}
16191622
});
@@ -1995,7 +1998,10 @@ export class AdapterClass extends EventEmitter {
19951998
private async _calculatePermissions(
19961999
options: InternalCalculatePermissionsOptions
19972000
): Promise<void | ioBroker.PermissionSet> {
1998-
if (options.user && !options.user.startsWith('system.user.')) {
2001+
const { user } = options;
2002+
let userId: ioBroker.ObjectIDs.User;
2003+
2004+
if (user && !user.startsWith('system.user.')) {
19992005
// it's not yet a `system.user.xy` id, thus we assume it's a username
20002006
if (!this.usernames[options.user]) {
20012007
// we did not find the id of the username in our cache -> update cache
@@ -2005,24 +2011,26 @@ export class AdapterClass extends EventEmitter {
20052011
this._logger.error(`${this.namespaceLog} ${e.message}`);
20062012
}
20072013
// user still not there, fallback
2008-
if (!this.usernames[options.user]) {
2009-
options.user = `system.user.${options.user
2014+
if (!this.usernames[user]) {
2015+
userId = `system.user.${user
20102016
.toString()
20112017
.replace(this.FORBIDDEN_CHARS, '_')
20122018
.replace(/\s/g, '_')
20132019
.replace(/\./g, '_')
20142020
.toLowerCase()}`;
20152021
} else {
2016-
options.user = this.usernames[options.user].id;
2022+
userId = this.usernames[user].id as ioBroker.ObjectIDs.User;
20172023
}
20182024
} else {
2019-
options.user = this.usernames[options.user].id;
2025+
userId = this.usernames[user].id as ioBroker.ObjectIDs.User;
20202026
}
2027+
} else {
2028+
userId = user as ioBroker.ObjectIDs.User;
20212029
}
20222030

20232031
// read all groups
2024-
let acl: Partial<ioBroker.PermissionSet> = { user: options.user };
2025-
if (options.user === SYSTEM_ADMIN_USER) {
2032+
let acl: Partial<ioBroker.PermissionSet> = { user: userId };
2033+
if (userId === SYSTEM_ADMIN_USER) {
20262034
acl.groups = [SYSTEM_ADMIN_GROUP];
20272035
for (const commandPermission of Object.values(options.commandsPermissions)) {
20282036
if (!commandPermission.type) {
@@ -2041,12 +2049,7 @@ export class AdapterClass extends EventEmitter {
20412049
// aggregate all groups permissions, where this user is
20422050
if (groups) {
20432051
for (const g of Object.keys(groups)) {
2044-
if (
2045-
groups[g] &&
2046-
groups[g].common &&
2047-
groups[g].common.members &&
2048-
groups[g].common.members.includes(options.user)
2049-
) {
2052+
if (groups[g]?.common?.members && groups[g].common.members.includes(userId)) {
20502053
acl.groups.push(groups[g]._id);
20512054
if (groups[g]._id === SYSTEM_ADMIN_GROUP) {
20522055
acl = {
@@ -2071,7 +2074,7 @@ export class AdapterClass extends EventEmitter {
20712074
create: true,
20722075
list: true
20732076
},
2074-
user: options.user,
2077+
user: userId,
20752078
users: {
20762079
read: true,
20772080
write: true,
@@ -3768,11 +3771,14 @@ export class AdapterClass extends EventEmitter {
37683771
}
37693772

37703773
// external signatures
3771-
getObjectList(params: ioBroker.GetObjectListParams | null, callback: ioBroker.GetObjectListCallback): void;
3774+
getObjectList(
3775+
params: ioBroker.GetObjectListParams | null,
3776+
callback: ioBroker.GetObjectListCallback<ioBroker.Object>
3777+
): void;
37723778
getObjectList(
37733779
params: ioBroker.GetObjectListParams | null,
37743780
options: { sorted?: boolean } | Record<string, any>,
3775-
callback: ioBroker.GetObjectListCallback
3781+
callback: ioBroker.GetObjectListCallback<ioBroker.Object>
37763782
): void;
37773783

37783784
/**
@@ -3902,7 +3908,7 @@ export class AdapterClass extends EventEmitter {
39023908
if (err) {
39033909
return tools.maybeCallbackWithError(callback, err);
39043910
}
3905-
if (res && res.rows) {
3911+
if (res?.rows) {
39063912
for (const row of res.rows) {
39073913
result[row.id] = row.value;
39083914
}
@@ -4040,7 +4046,7 @@ export class AdapterClass extends EventEmitter {
40404046
const result: {
40414047
[groupName: string]: Record<string, ioBroker.Enum>;
40424048
} = {};
4043-
if (res && res.rows) {
4049+
if (res?.rows) {
40444050
for (const row of res.rows) {
40454051
const parts: string[] = row.id.split('.', 3);
40464052
if (!parts[2]) {
@@ -4553,9 +4559,8 @@ export class AdapterClass extends EventEmitter {
45534559
// read all underlying states
45544560
adapterObjects!.getObjectList(selector, options, (err, res) => {
45554561
res &&
4556-
res.rows &&
45574562
res.rows.forEach(
4558-
(item: ioBroker.GetObjectListItem) =>
4563+
(item: ioBroker.GetObjectListItem<ioBroker.Object>) =>
45594564
!tasks.find(task => task.id === item.id) &&
45604565
(!item.value || !item.value.common || !item.value.common.dontDelete) && // exclude objects with dontDelete flag
45614566
tasks.push({ id: item.id, state: item.value && item.value.type === 'state' })
@@ -4569,7 +4574,7 @@ export class AdapterClass extends EventEmitter {
45694574
return tools.maybeCallbackWithError(callback, err);
45704575
} else if (obj) {
45714576
// do not allow deletion of objects with dontDelete flag
4572-
if (obj.common && obj.common.dontDelete) {
4577+
if (obj.common?.dontDelete) {
45734578
return tools.maybeCallbackWithError(callback, new Error('not deletable'));
45744579
}
45754580

@@ -5687,7 +5692,7 @@ export class AdapterClass extends EventEmitter {
56875692
return tools.maybeCallbackWithError(callback, err);
56885693
}
56895694

5690-
if (res && res.rows) {
5695+
if (res) {
56915696
for (const row of res.rows) {
56925697
try {
56935698
const obj = (await adapterObjects!.getObject(row.id, options)) as
@@ -6419,7 +6424,7 @@ export class AdapterClass extends EventEmitter {
64196424
},
64206425
options,
64216426
async (err, res) => {
6422-
if (err || !res || !res.rows) {
6427+
if (err || !res) {
64236428
return tools.maybeCallbackWithError(callback, err);
64246429
}
64256430

@@ -7176,7 +7181,7 @@ export class AdapterClass extends EventEmitter {
71767181
endkey: `${instanceName}.\u9999`
71777182
});
71787183

7179-
if (res?.rows) {
7184+
if (res) {
71807185
for (const row of res.rows) {
71817186
try {
71827187
await adapterStates!.pushMessage(row.id, obj);
@@ -7337,7 +7342,7 @@ export class AdapterClass extends EventEmitter {
73377342
// if states is no longer existing, we do not need to unsubscribe
73387343
return;
73397344
}
7340-
if (!err && res?.rows?.length) {
7345+
if (!err && res?.rows.length) {
73417346
for (const row of res.rows) {
73427347
const parts: string[] = row.id.split('.');
73437348
// ignore system.host.name.alive and so on
@@ -8915,7 +8920,7 @@ export class AdapterClass extends EventEmitter {
89158920

89168921
if (_obj?.rows) {
89178922
for (const row of _obj.rows) {
8918-
if (row.value.common && row.value.common.type === 'storage') {
8923+
if (row.value?.common && row.value.common.type === 'storage') {
89198924
this.defaultHistory = row.id.substring('system.adapter.'.length);
89208925
break;
89218926
}
@@ -9406,7 +9411,7 @@ export class AdapterClass extends EventEmitter {
94069411
options.checked = undefined;
94079412
}
94089413

9409-
if (!res || !res.rows) {
9414+
if (!res) {
94109415
return tools.maybeCallbackWithError(callback, null, {});
94119416
}
94129417
const keys = [];
@@ -10415,14 +10420,12 @@ export class AdapterClass extends EventEmitter {
1041510420
endkey: 'system.adapter.\u9999'
1041610421
});
1041710422

10418-
if (res && res.rows) {
10419-
this.autoSubscribe = [];
10420-
for (const row of res.rows) {
10421-
if (row.value.common.subscribable) {
10422-
const _id = row.id.substring(15); // cut system.adapter.
10423-
if (!this.autoSubscribe.includes(_id)) {
10424-
this.autoSubscribe.push(_id);
10425-
}
10423+
this.autoSubscribe = [];
10424+
for (const row of res.rows) {
10425+
if (row.value?.common.subscribable) {
10426+
const _id = row.id.substring(15); // cut system.adapter.
10427+
if (!this.autoSubscribe.includes(_id)) {
10428+
this.autoSubscribe.push(_id);
1042610429
}
1042710430
}
1042810431
}

packages/cli/src/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
export { execute } from './lib/setup';
22
export { dbConnectAsync } from './lib/setup/dbConnection';
3-
// required by main.ts
43
export { Vendor } from './lib/setup/setupVendor';
5-
// required by main.ts
64
export { Upload } from './lib/setup/setupUpload';
7-
// required by testConsole
8-
export { BackupRestore } from './lib/setup/setupBackup';
9-
// used by adapter upgrade manager
105
export { Upgrade } from './lib/setup/setupUpgrade';
6+
export { BackupRestore } from './lib/setup/setupBackup';

packages/cli/src/lib/cli/cliObjects.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,11 @@ export class CLIObjects extends CLICommand {
480480
for (const type of types) {
481481
try {
482482
const res = await objects.getObjectViewAsync('system', type, params);
483-
res?.rows.forEach(item => result.push(item.value));
483+
res.rows.forEach(item => {
484+
if (item.value) {
485+
result.push(item.value);
486+
}
487+
});
484488
} catch {
485489
// ignore
486490
}

packages/cli/src/lib/setup.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ async function processCommand(
633633
endkey: `system.adapter.${instance}\u9999`
634634
});
635635

636-
otherInstanceExists = !!res?.rows?.length;
636+
otherInstanceExists = !!res.rows.length;
637637
} catch {
638638
// ignore - on install we have no object views
639639
}
@@ -916,7 +916,7 @@ async function processCommand(
916916
// @ts-expect-error todo check or handle null return value
917917
const { stoppedList } = await install.downloadPacket(repoUrl, installName);
918918
await install.installAdapter(installName, repoUrl);
919-
await install.enableInstances(stoppedList, true); // even if unlikely make sure to reenable disabled instances
919+
await install.enableInstances(stoppedList, true); // even if unlikely make sure to re-enable disabled instances
920920
if (command !== 'install' && command !== 'i') {
921921
await install.createInstance(name, params);
922922
}
@@ -1182,8 +1182,7 @@ async function processCommand(
11821182
objects,
11831183
states,
11841184
params,
1185-
processExit: callback,
1186-
restartController
1185+
processExit: callback
11871186
});
11881187

11891188
if (adapter) {
@@ -1208,7 +1207,7 @@ async function processCommand(
12081207
} else {
12091208
// upgrade all
12101209
try {
1211-
const links = await getRepository(objects);
1210+
const links = await getRepository({ objects });
12121211
if (!links) {
12131212
return void callback(EXIT_CODES.INVALID_REPO);
12141213
}
@@ -2860,7 +2859,7 @@ async function cleanDatabase(isDeleteDb: boolean): Promise<number> {
28602859

28612860
try {
28622861
const res = await objects.getObjectListAsync({ startkey: '\u0000', endkey: '\u9999' });
2863-
if (res?.rows.length) {
2862+
if (res.rows.length) {
28642863
console.log(`clean ${res.rows.length} objects...`);
28652864
ids = res.rows.map(e => e.id);
28662865
}

packages/cli/src/lib/setup/setupBackup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export interface CLIBackupRestoreOptions {
1919
restartController: RestartController;
2020
}
2121

22-
type BackupObject = Omit<ioBroker.GetObjectListItem, 'doc'>;
22+
type BackupObject = Omit<ioBroker.GetObjectListItem<ioBroker.Object>, 'doc'>;
2323

2424
export interface RestoreBackupReturnValue {
2525
/** Exit code of the process */

0 commit comments

Comments
 (0)