iobroker.eos-admin 7.10.1 → 7.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL_TEST_V7.10.2.md +22 -0
- package/MERGE_UPDATE_README_V7.10.2.md +11 -0
- package/NEXOWATT_EOS_BUILD_INFO.json +15 -16
- package/NEXOWATT_EOS_PREBUILT_MANIFEST.json +1410 -0
- package/PUBLISH_STABLE_V7.10.2.md +21 -0
- package/README.md +4 -4
- package/README_STABILITY_V7.10.2.md +20 -0
- package/RELEASE_ACCEPTANCE_V7.10.2.md +13 -0
- package/RELEASE_NOTES_V7.10.2.md +11 -0
- package/build/lib/eosAutoUpdate.js +418 -20
- package/build/lib/eosAutoUpdate.js.map +1 -0
- package/build/lib/eosRequestSecurity.js +4 -1
- package/build/lib/eosRequestSecurity.js.map +1 -0
- package/build/lib/web.js +40 -9
- package/build/lib/web.js.map +1 -1
- package/io-package.json +60 -5
- package/package.json +22 -16
- package/tools/nexowatt-auto-update-selftest.cjs +144 -32
- package/tools/nexowatt-backend-runtime-selftest.cjs +147 -0
- package/tools/nexowatt-merge-update-selftest.cjs +7 -1
- package/tools/nexowatt-prebuilt-release-selftest.cjs +292 -0
- package/tools/nexowatt-stable-v7102-selftest.cjs +51 -0
- package/tools/nexowatt-validate-package.cjs +35 -11
- package/INSTALL_TEST_V7.10.1.md +0 -10
- package/MERGE_UPDATE_README_V7.10.1.md +0 -10
- package/PUBLISH_STABLE_V7.10.1.md +0 -10
- package/README_STABILITY_V7.10.1.md +0 -10
- package/RELEASE_ACCEPTANCE_V7.10.1.md +0 -10
- package/RELEASE_NOTES_V7.10.1.md +0 -10
- package/adminWww/js/eos-release-watch.js +0 -77
- package/build/lib/eosPassword.js +0 -72
- package/build/lib/nexowattStableAuth.js +0 -74
- package/tools/nexowatt-stable-v7101-selftest.cjs +0 -15
package/build/lib/eosPassword.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.normalizeEosPasswordTarget = normalizeEosPasswordTarget;
|
|
4
|
-
exports.setEosUserPasswordWithVerification = setEosUserPasswordWithVerification;
|
|
5
|
-
exports.verifyEosUserPasswordCredential = verifyEosUserPasswordCredential;
|
|
6
|
-
function normalizeEosPasswordTarget(value) {
|
|
7
|
-
const raw = String(value || '').trim();
|
|
8
|
-
const userId = raw.startsWith('system.user.') ? raw : `system.user.${raw}`;
|
|
9
|
-
const userName = userId.replace(/^system\.user\./, '').trim();
|
|
10
|
-
if (!userName || userName.includes('.') || !/^system\.user\.[^.]+$/.test(userId)) throw new Error('invalidPasswordTarget');
|
|
11
|
-
return { userId, userName };
|
|
12
|
-
}
|
|
13
|
-
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
14
|
-
const accepted = result => result === true || (Array.isArray(result) && result[0] === true);
|
|
15
|
-
async function readPasswordHash(adapter, userId) {
|
|
16
|
-
if (typeof adapter.getForeignObjectAsync !== 'function') return '';
|
|
17
|
-
try {
|
|
18
|
-
const object = await adapter.getForeignObjectAsync(userId);
|
|
19
|
-
return typeof object?.common?.password === 'string' ? object.common.password : '';
|
|
20
|
-
}
|
|
21
|
-
catch { return ''; }
|
|
22
|
-
}
|
|
23
|
-
async function callPasswordApi(adapter, target, password, serviceUser, withOptions) {
|
|
24
|
-
const options = withOptions ? { user: serviceUser } : null;
|
|
25
|
-
if (typeof adapter.setPasswordAsync === 'function') { await adapter.setPasswordAsync(target, password, options); return; }
|
|
26
|
-
if (typeof adapter.setPassword === 'function') {
|
|
27
|
-
await new Promise((resolve, reject) => adapter.setPassword?.(target, password, options, error => error ? reject(error) : resolve()));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
throw new Error('passwordApiUnavailable');
|
|
31
|
-
}
|
|
32
|
-
async function verifyAfterWrite(adapter, normalized, password, serviceUser) {
|
|
33
|
-
const hasCredentialCheck = typeof adapter.checkPasswordAsync === 'function';
|
|
34
|
-
for (let attempt = 0; attempt < 12; attempt++) {
|
|
35
|
-
if (hasCredentialCheck) {
|
|
36
|
-
for (const candidate of [normalized.userId, normalized.userName]) {
|
|
37
|
-
try {
|
|
38
|
-
if (accepted(await adapter.checkPasswordAsync?.(candidate, password, { user: serviceUser }))) return;
|
|
39
|
-
}
|
|
40
|
-
catch { }
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
else if (await readPasswordHash(adapter, normalized.userId)) return;
|
|
44
|
-
if (attempt < 11) await delay(55 + attempt * 35);
|
|
45
|
-
}
|
|
46
|
-
throw new Error(hasCredentialCheck ? 'passwordVerificationFailed' : 'passwordNotPersisted');
|
|
47
|
-
}
|
|
48
|
-
async function verifyEosUserPasswordCredential(adapter, target, password, serviceUser = 'system.user.admin') {
|
|
49
|
-
const normalized = normalizeEosPasswordTarget(target);
|
|
50
|
-
await verifyAfterWrite(adapter, normalized, password, serviceUser);
|
|
51
|
-
return normalized;
|
|
52
|
-
}
|
|
53
|
-
async function setEosUserPasswordWithVerification(adapter, target, password, serviceUser = 'system.user.admin') {
|
|
54
|
-
const normalized = normalizeEosPasswordTarget(target);
|
|
55
|
-
const attempts = [
|
|
56
|
-
{ apiTarget: normalized.userId, withOptions: true },
|
|
57
|
-
{ apiTarget: normalized.userName, withOptions: true },
|
|
58
|
-
{ apiTarget: normalized.userId, withOptions: false },
|
|
59
|
-
{ apiTarget: normalized.userName, withOptions: false },
|
|
60
|
-
];
|
|
61
|
-
let lastError = null;
|
|
62
|
-
for (const attempt of attempts) {
|
|
63
|
-
try {
|
|
64
|
-
await callPasswordApi(adapter, attempt.apiTarget, password, serviceUser, attempt.withOptions);
|
|
65
|
-
await verifyAfterWrite(adapter, normalized, password, serviceUser);
|
|
66
|
-
return { ...normalized, apiTarget: attempt.apiTarget };
|
|
67
|
-
}
|
|
68
|
-
catch (error) { lastError = error; }
|
|
69
|
-
}
|
|
70
|
-
if (lastError instanceof Error) throw lastError;
|
|
71
|
-
throw new Error('passwordNotPersisted');
|
|
72
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.startNexowattStableAuth = startNexowattStableAuth;
|
|
4
|
-
const START_PASSWORD = 'nexowatt';
|
|
5
|
-
const MARKER_KEYS = ["eosFirstLoginPending", "eosMustChangePassword", "eosPasswordSetupRequired", "firstLoginRequired", "mustChangePassword", "nexowattFirstLoginPending", "nexowattMustChangePassword", "nexowattPasswordSetupRequired", "passwordChangeRequired"];
|
|
6
|
-
const timers = new WeakMap();
|
|
7
|
-
function pendingByNative(native) {
|
|
8
|
-
if (!native || typeof native !== 'object') return false;
|
|
9
|
-
return MARKER_KEYS.some(key => native[key] === true || native[key] === 'pending' || native[key] === 'required' || native[key] === 'starter');
|
|
10
|
-
}
|
|
11
|
-
async function setPassword(adapter, user, password) {
|
|
12
|
-
if (typeof adapter.setPasswordAsync === 'function') return adapter.setPasswordAsync(user, password, { user: 'system.user.admin' });
|
|
13
|
-
return new Promise((resolve, reject) => adapter.setPassword(user, password, { user: 'system.user.admin' }, err => err ? reject(err) : resolve()));
|
|
14
|
-
}
|
|
15
|
-
async function ensureGroupMembership(adapter, userId, groupId) {
|
|
16
|
-
const group = await adapter.getForeignObjectAsync(groupId);
|
|
17
|
-
if (!group || group.type !== 'group') return;
|
|
18
|
-
group.common = group.common || { name: groupId.split('.').pop(), members: [] };
|
|
19
|
-
group.common.members = Array.isArray(group.common.members) ? group.common.members : [];
|
|
20
|
-
if (!group.common.members.includes(userId)) {
|
|
21
|
-
group.common.members.push(userId);
|
|
22
|
-
await adapter.setForeignObjectAsync(groupId, group, { user: 'system.user.admin' });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
async function createUser(adapter, name) {
|
|
26
|
-
const id = `system.user.${name}`;
|
|
27
|
-
await adapter.setForeignObjectAsync(id, {
|
|
28
|
-
_id: id, type: 'user',
|
|
29
|
-
common: { name, enabled: true, password: '' },
|
|
30
|
-
native: { nexowattManagedAccount: true, nexowattMustChangePassword: true, nexowattPasswordState: 'starter' }
|
|
31
|
-
}, { user: 'system.user.admin' });
|
|
32
|
-
return adapter.getForeignObjectAsync(id);
|
|
33
|
-
}
|
|
34
|
-
async function prepareOne(adapter, name, group, createMissing) {
|
|
35
|
-
const id = `system.user.${name}`;
|
|
36
|
-
let obj = await adapter.getForeignObjectAsync(id);
|
|
37
|
-
let created = false;
|
|
38
|
-
if (!obj && createMissing) { obj = await createUser(adapter, name); created = true; }
|
|
39
|
-
if (!obj || obj.type !== 'user') return;
|
|
40
|
-
obj.native = obj.native || {};
|
|
41
|
-
const empty = !obj.common || !obj.common.password;
|
|
42
|
-
const pending = created || empty || pendingByNative(obj.native) || obj.native.nexowattPasswordState === 'starter';
|
|
43
|
-
if (pending) {
|
|
44
|
-
await setPassword(adapter, name, START_PASSWORD);
|
|
45
|
-
obj = await adapter.getForeignObjectAsync(id) || obj;
|
|
46
|
-
obj.native = obj.native || {};
|
|
47
|
-
obj.native.nexowattManagedAccount = true;
|
|
48
|
-
obj.native.nexowattStarterPasswordActive = true;
|
|
49
|
-
obj.native.nexowattMustChangePassword = true;
|
|
50
|
-
obj.native.nexowattPasswordState = 'starter';
|
|
51
|
-
obj.native.nexowattStarterPasswordUpdatedAt = new Date().toISOString();
|
|
52
|
-
for (const key of MARKER_KEYS) {
|
|
53
|
-
if (/required|must|pending|first/i.test(key)) obj.native[key] = true;
|
|
54
|
-
}
|
|
55
|
-
await adapter.setForeignObjectAsync(id, obj, { user: 'system.user.admin' });
|
|
56
|
-
}
|
|
57
|
-
await ensureGroupMembership(adapter, id, group);
|
|
58
|
-
}
|
|
59
|
-
async function reconcile(adapter) {
|
|
60
|
-
try {
|
|
61
|
-
await prepareOne(adapter, 'installer', 'system.group.installer', true);
|
|
62
|
-
const guest = await adapter.getForeignObjectAsync('system.user.guest');
|
|
63
|
-
const user = await adapter.getForeignObjectAsync('system.user.user');
|
|
64
|
-
if (guest || !user) await prepareOne(adapter, 'guest', 'system.group.endkunden', true);
|
|
65
|
-
if (user) await prepareOne(adapter, 'user', 'system.group.endkunden', false);
|
|
66
|
-
} catch (e) { adapter.log.warn(`[NexoWatt EOS login] Starter-account reconciliation failed: ${e && e.message || e}`); }
|
|
67
|
-
}
|
|
68
|
-
function startNexowattStableAuth(adapter) {
|
|
69
|
-
if (timers.has(adapter)) return;
|
|
70
|
-
void reconcile(adapter);
|
|
71
|
-
const timer = setInterval(() => void reconcile(adapter), 5000);
|
|
72
|
-
if (timer.unref) timer.unref();
|
|
73
|
-
timers.set(adapter, timer);
|
|
74
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
const fs=require('node:fs'),path=require('node:path');const root=path.resolve(__dirname,'..');const read=r=>fs.readFileSync(path.join(root,r),'utf8');const j=r=>JSON.parse(read(r));const must=(v,m)=>{if(!v){console.error('[NexoWatt EOS stable v7101] '+m);process.exit(1)}};
|
|
4
|
-
const p=j('package.json'),io=j('io-package.json'),info=j('NEXOWATT_EOS_BUILD_INFO.json'),main=read('src/main.ts'),boot=read('adminWww/js/eos-role-bootstrap.js'),role=read('adminWww/js/eos-role-ui.js'),css=read('adminWww/css/nexowatt-native-shell.css'),index=read('adminWww/index.html'),ems=read('adminWww/js/eos-ems-overview.js'),intro=read('src-admin/src/tabs/Intro.tsx'),bundle=read('adminWww/assets/Intro-DkwRiz1n-v84.js'),stable=read('adminWww/static/js/nexowatt-stable-v7101.js'),auto=read('src/lib/eosAutoUpdate.ts');
|
|
5
|
-
must(p.version==='7.10.1'&&io.version==='7.10.1'&&io.common.version==='7.10.1'&&info.version==='7.10.1','version drift');
|
|
6
|
-
must(io.native.eosRequireFirstLoginPassword===false&&io.native.eosRequireFirstLoginPasswordChange===false,'forced first password still enabled');
|
|
7
|
-
must(!index.includes('eos-account-management.js'),'custom reset UI still loaded');
|
|
8
|
-
must(!boot.includes('installIntegratedFirstLogin(base);')&&!boot.includes('showFirstLoginPassword(resolved, base);'),'forced first-login UI still active');
|
|
9
|
-
must(main.includes('standardPasswordMode: true')&&main.includes('nexowattPasswordChangeRequired: false'),'account migration missing');
|
|
10
|
-
must(role.includes("route === 'tab-users'")&&main.includes("command === 'changePassword'"),'role-aware native password editing missing');
|
|
11
|
-
must(css.includes('persistent native overview scrolling')&&stable.includes("overflow-y','scroll"),'persistent scroll missing');
|
|
12
|
-
must(intro.includes('eos-overview-edit-controls')&&bundle.includes('eos-overview-edit-controls'),'edit control not in bottom grid');
|
|
13
|
-
must(!ems.includes('Vollständige EMS-Diagnose öffnen'),'unsupported EMS link remains');
|
|
14
|
-
must(index.includes('eos-auto-update.js?v=7101')&&auto.includes("const POLICY: NexoWattAutoUpdatePolicy = 'major'"),'auto update missing');
|
|
15
|
-
console.log('[NexoWatt EOS stable v7101] OK');
|