iobroker.eos-admin 7.10.3 → 7.10.5
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.5.md +8 -0
- package/MERGE_UPDATE_README_V7.10.5.md +7 -0
- package/NEXOWATT_EOS_BUILD_INFO.json +22 -18
- package/NEXOWATT_EOS_PREBUILT_MANIFEST.json +37 -36
- package/PUBLISH_STABLE_V7.10.5.md +8 -0
- package/README.md +4 -4
- package/README_STABILITY_V7.10.5.md +5 -0
- package/RELEASE_ACCEPTANCE_V7.10.5.md +11 -0
- package/RELEASE_NOTES_V7.10.5.md +11 -0
- package/SECURITY_ROLE_MATRIX_V7.10.5.md +12 -0
- package/adminWww/assets/Intro-DkwRiz1n-v84.js +2 -2
- package/adminWww/assets/Objects-DPan0bzw-v84.js +1 -1
- package/adminWww/assets/bootstrap-COulQZax-v84.js +2 -2
- package/adminWww/css/nexowatt-native-shell.css +12 -1
- package/adminWww/index.html +14 -14
- package/adminWww/js/eos-role-bootstrap.js +5 -5
- package/adminWww/js/eos-role-ui.js +130 -17
- package/adminWww/js/nexowatt-native-shell.js +1 -1
- package/adminWww/static/js/{nexowatt-stable-v7101.js → nexowatt-stable-v7105.js} +1 -1
- package/build/main.js +14 -11
- package/io-package.json +31 -9
- package/package.json +14 -11
- package/tools/nexowatt-account-password-flow-selftest.cjs +3 -3
- package/tools/nexowatt-clean-legacy-runtime.cjs +6 -0
- package/tools/nexowatt-internal-reserve-selftest.cjs +1 -1
- package/tools/nexowatt-login-layout-selftest.cjs +3 -3
- package/tools/nexowatt-merge-update-selftest.cjs +1 -1
- package/tools/nexowatt-modern-ui-selftest.cjs +2 -2
- package/tools/nexowatt-role-security-selftest.cjs +131 -0
- package/tools/nexowatt-runtime-cleanup-selftest.cjs +4 -0
- package/tools/nexowatt-stable-v7103-selftest.cjs +4 -4
- package/tools/nexowatt-ui-overview-runtime-selftest.cjs +2 -2
- package/tools/nexowatt-validate-package.cjs +9 -8
- package/INSTALL_TEST_V7.10.3.md +0 -7
- package/MERGE_UPDATE_README_V7.10.3.md +0 -3
- package/PUBLISH_STABLE_V7.10.3.md +0 -10
- package/README_STABILITY_V7.10.3.md +0 -5
- package/RELEASE_ACCEPTANCE_V7.10.3.md +0 -3
- package/RELEASE_NOTES_V7.10.3.md +0 -7
|
@@ -1184,12 +1184,23 @@ html.eos-login .eos-login-card-modern {
|
|
|
1184
1184
|
/* Internal fallback services are never exposed outside Admin / Service. */
|
|
1185
1185
|
html.eos-role-installer [data-instance^="admin."],
|
|
1186
1186
|
html.eos-role-installer [data-instance^="backitup."],
|
|
1187
|
+
html.eos-role-installer [data-instance^="xterm."],
|
|
1187
1188
|
html.eos-role-enduser [data-instance^="admin."],
|
|
1188
1189
|
html.eos-role-enduser [data-instance^="backitup."],
|
|
1190
|
+
html.eos-role-enduser [data-instance^="xterm."],
|
|
1189
1191
|
html.eos-role-installer [data-instance-id^="admin."],
|
|
1190
1192
|
html.eos-role-installer [data-instance-id^="backitup."],
|
|
1193
|
+
html.eos-role-installer [data-instance-id^="xterm."],
|
|
1191
1194
|
html.eos-role-enduser [data-instance-id^="admin."],
|
|
1192
|
-
html.eos-role-enduser [data-instance-id^="backitup."]
|
|
1195
|
+
html.eos-role-enduser [data-instance-id^="backitup."],
|
|
1196
|
+
html.eos-role-enduser [data-instance-id^="xterm."] { display: none !important; }
|
|
1197
|
+
|
|
1198
|
+
html.eos-role-enduser #app-paper[data-eos-datapoints-readonly] [data-eos-object-writable="1"],
|
|
1199
|
+
html.eos-role-enduser #app-paper[data-eos-datapoints-readonly] [data-eos-enduser-write-blocked="1"] {
|
|
1200
|
+
pointer-events: none !important;
|
|
1201
|
+
cursor: default !important;
|
|
1202
|
+
opacity: 0.62 !important;
|
|
1203
|
+
}
|
|
1193
1204
|
|
|
1194
1205
|
|
|
1195
1206
|
|
package/adminWww/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate" />
|
|
9
9
|
<meta http-equiv="Pragma" content="no-cache" />
|
|
10
10
|
<meta http-equiv="Expires" content="0" />
|
|
11
|
-
<script src="./js/eos-manual-write-policy.js?v=
|
|
11
|
+
<script src="./js/eos-manual-write-policy.js?v=7105"></script>
|
|
12
12
|
<script type="module" src="./assets/hostInit-v84.js?v=84"></script>
|
|
13
13
|
|
|
14
14
|
<meta charset="utf-8" />
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
rel="stylesheet"
|
|
37
37
|
href="css/leaflet.css"
|
|
38
38
|
/>
|
|
39
|
-
<link rel="stylesheet" href="./css/nexowatt-native-shell.css?v=
|
|
40
|
-
<link rel="stylesheet" href="./css/eos-ems-overview.css?v=
|
|
39
|
+
<link rel="stylesheet" href="./css/nexowatt-native-shell.css?v=7105" />
|
|
40
|
+
<link rel="stylesheet" href="./css/eos-ems-overview.css?v=7105" />
|
|
41
41
|
<link rel="stylesheet" href="./css/eos-auto-update.css?v=7103" />
|
|
42
42
|
<link
|
|
43
43
|
rel="manifest"
|
|
@@ -160,22 +160,22 @@
|
|
|
160
160
|
</script>
|
|
161
161
|
<link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
|
|
162
162
|
<link rel="modulepreload" crossorigin href="./assets/iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js">
|
|
163
|
-
<script defer src="./js/eos-role-bootstrap.js?v=
|
|
164
|
-
<script defer src="./js/eos-policy-client.js?v=
|
|
165
|
-
<script defer src="./js/eos-branding-sanitizer.js?v=
|
|
166
|
-
<script defer src="./js/nexowatt-native-shell.js?v=
|
|
167
|
-
<script defer src="./js/eos-native-security.js?v=
|
|
168
|
-
<script defer src="./js/eos-basic-settings.js?v=
|
|
169
|
-
<script defer src="./js/eos-role-ui.js?v=
|
|
170
|
-
<script defer src="./js/eos-ems-overview.js?v=
|
|
163
|
+
<script defer src="./js/eos-role-bootstrap.js?v=7105" data-eos-entry="./assets/index-CQZugZ1z-v84.js?v=84"></script>
|
|
164
|
+
<script defer src="./js/eos-policy-client.js?v=7105"></script>
|
|
165
|
+
<script defer src="./js/eos-branding-sanitizer.js?v=7105"></script>
|
|
166
|
+
<script defer src="./js/nexowatt-native-shell.js?v=7105"></script>
|
|
167
|
+
<script defer src="./js/eos-native-security.js?v=7105"></script>
|
|
168
|
+
<script defer src="./js/eos-basic-settings.js?v=7105"></script>
|
|
169
|
+
<script defer src="./js/eos-role-ui.js?v=7105"></script>
|
|
170
|
+
<script defer src="./js/eos-ems-overview.js?v=7105"></script>
|
|
171
171
|
|
|
172
172
|
<script defer src="./js/eos-auto-update.js?v=7103"></script>
|
|
173
|
-
<script defer src="./js/eos-assistant.js?v=
|
|
173
|
+
<script defer src="./js/eos-assistant.js?v=7105"></script>
|
|
174
174
|
</head>
|
|
175
175
|
<body>
|
|
176
176
|
<noscript>Für NexoWatt EOS muss JavaScript aktiviert sein.</noscript>
|
|
177
177
|
<div id="root"></div>
|
|
178
|
-
<script defer src="static/js/nexowatt-stable-login.js?v=
|
|
179
|
-
<script defer src="static/js/nexowatt-stable-
|
|
178
|
+
<script defer src="static/js/nexowatt-stable-login.js?v=7105"></script>
|
|
179
|
+
<script defer src="static/js/nexowatt-stable-v7105.js?v=7105"></script>
|
|
180
180
|
</body>
|
|
181
181
|
</html>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const VERSION = '
|
|
4
|
+
const VERSION = 'v7105-admin-authoritative-rbac';
|
|
5
5
|
const script = document.currentScript || document.querySelector('script[src*="eos-role-bootstrap.js"]');
|
|
6
6
|
const entry = script?.dataset?.eosEntry || '';
|
|
7
7
|
let launched = false;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
const roleFromPolicy = policy => {
|
|
18
18
|
const raw = normalize(policy?.role || policy?.eosRole || policy?.accessRole || '');
|
|
19
|
-
if (policy?.isAdmin || policy?.isEosAdminGroup || policy?.isAdministrator || /^(?:admin|administrator)$/.test(raw)) return 'admin';
|
|
19
|
+
if (policy?.user === 'system.user.admin' || policy?.userId === 'system.user.admin' || policy?.isAdmin || policy?.isEosAdminGroup || policy?.isAdministrator || /^(?:admin|administrator)$/.test(raw)) return 'admin';
|
|
20
20
|
if (/nexowatt service|eos service|service admin|service administrator/.test(raw)) return 'admin';
|
|
21
21
|
if (policy?.isInstaller || /installateur|installer|installation|inbetriebnahme|techniker|technician|integrator|partner/.test(raw)) return 'installer';
|
|
22
22
|
return 'enduser';
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
const isCustomerBackupTab = tab => /^(?:tab-)?(?:nexowatt-backup|eos-backup|nexowatt-sicherung)(?:-|$)/.test(normalize(tab));
|
|
26
26
|
const isReleasedEndUserTab = tab => /^(?:tab-)?(?:nexowatt-ui|nexowatt-cockpit|eos-cockpit|eos-dashboard|kunden-cockpit|endkunden-cockpit|lovelace|jarvis|vis|iqontrol|material)(?:-|$)/.test(normalize(tab));
|
|
27
27
|
const isOfficialReserveTab = tab => /^(?:tab-)?(?:admin|backitup)(?:-\d+)?$/.test(normalize(tab));
|
|
28
|
-
const isInstallerDenied = tab => /(?:tab-hosts|tab-files|tab-xterm|tab-xtrem|tab-system|hosts|files|console|terminal|security)/.test(normalize(tab)) || isOfficialReserveTab(tab);
|
|
28
|
+
const isInstallerDenied = tab => /(?:tab-users|tab-hosts|tab-files|tab-xterm|tab-xtrem|tab-system|users|hosts|files|console|terminal|security)/.test(normalize(tab)) || isOfficialReserveTab(tab);
|
|
29
29
|
const isAllowed = (role, route) => route !== 'easy' && (role === 'admin'
|
|
30
30
|
|| (role === 'installer'
|
|
31
|
-
? route === 'tab-intro' ||
|
|
32
|
-
: route === 'tab-intro' || route === 'tab-enums' || isCustomerBackupTab(route) || isReleasedEndUserTab(route)));
|
|
31
|
+
? route === 'tab-intro' || isCustomerBackupTab(route) || !isInstallerDenied(route)
|
|
32
|
+
: route === 'tab-intro' || route === 'tab-enums' || route === 'tab-objects' || isCustomerBackupTab(route) || isReleasedEndUserTab(route)));
|
|
33
33
|
const defaultTab = () => 'tab-intro';
|
|
34
34
|
const currentRoute = () => {
|
|
35
35
|
const hash = decodeURIComponent(window.location.hash || '').toLowerCase();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const VERSION = '
|
|
4
|
+
const VERSION = 'v7105-admin-authoritative-rbac';
|
|
5
5
|
window.NEXOWATT_EOS_ROLE_UI_VERSION = VERSION;
|
|
6
6
|
|
|
7
7
|
const state = {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
const roleFromPolicy = policy => {
|
|
39
39
|
const raw = normalize(policy?.role || policy?.eosRole || policy?.accessRole || '');
|
|
40
|
-
if (policy?.isAdmin || policy?.isEosAdminGroup || policy?.isAdministrator || /^(?:admin|administrator)$/.test(raw)) return 'admin';
|
|
40
|
+
if (policy?.user === 'system.user.admin' || policy?.userId === 'system.user.admin' || policy?.isAdmin || policy?.isEosAdminGroup || policy?.isAdministrator || /^(?:admin|administrator)$/.test(raw)) return 'admin';
|
|
41
41
|
if (/nexowatt service|eos service|service admin|service administrator/.test(raw)) return 'admin';
|
|
42
42
|
if (policy?.isInstaller || /installateur|installer|installation|inbetriebnahme|techniker|technician|integrator|partner/.test(raw)) return 'installer';
|
|
43
43
|
return 'enduser';
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
const isOfficialReserveTab = tab => isOfficialAdminTab(tab) || isOfficialBackupTab(tab);
|
|
48
48
|
const isCustomerBackupTab = tab => /^tab-(?:nexowatt-backup|eos-backup|nexowatt-sicherung)(?:-\d+)?$/.test(normalize(tab));
|
|
49
49
|
const endUserAllowedByText = value => /(eos cockpit|nexowatt ui|nexowatt cockpit|kunden cockpit|kundenbereich|endkundenbereich|visualisierung|visualisation|visu|dashboard|energie cockpit|energy cockpit|bedienung|smart home|smart-home|lovelace|jarvis|iqontrol|material)/.test(normalize(value));
|
|
50
|
-
const endUserDeniedByText = value => /(module|dienste|
|
|
50
|
+
const endUserDeniedByText = value => /(module|dienste|systemlogs|logs|zugange|rechte|benutzer|users|gruppen|groups|system hosts|system-hosts|hosts|dateien|files|konsole|console|terminal|xterm|adapter|instances?|instanzen|geraetesuche|discovery|systemschutz|security)/.test(normalize(value));
|
|
51
51
|
const isEndUserTab = (tab, label = '') => {
|
|
52
52
|
const clean = normalize(tab); const text = `${clean} ${normalize(label)}`;
|
|
53
|
-
if (clean === 'tab-intro' || clean === 'tab-enums' || isCustomerBackupTab(clean)) return true;
|
|
53
|
+
if (clean === 'tab-intro' || clean === 'tab-enums' || clean === 'tab-objects' || isCustomerBackupTab(clean)) return true;
|
|
54
54
|
if (/^tab-(nexowatt-ui|nexowatt-cockpit|eos-cockpit|eos-dashboard|kunden-cockpit|endkunden-cockpit|lovelace|jarvis|vis|iqontrol|material)(?:-|$)/.test(clean)) return true;
|
|
55
55
|
return !!clean && !endUserDeniedByText(text) && endUserAllowedByText(text);
|
|
56
56
|
};
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
const clean = normalize(tab); const text = `${clean} ${normalize(label)}`;
|
|
59
59
|
if (isOfficialReserveTab(clean)) return true;
|
|
60
60
|
if (isCustomerBackupTab(clean)) return false;
|
|
61
|
-
return /(?:tab-hosts|tab-files|tab-xterm|tab-xtrem|tab-system|system-hosts|system hosts|hosts|dateien|files|konsole|console|terminal|xterm|systemschutz|security)/.test(text);
|
|
61
|
+
return /(?:tab-users|tab-hosts|tab-files|tab-xterm|tab-xtrem|tab-system|users|benutzer|gruppen|groups|system-hosts|system hosts|hosts|dateien|files|konsole|console|terminal|xterm|systemschutz|security)/.test(text);
|
|
62
62
|
};
|
|
63
63
|
const isRouteAllowed = (role, route, label = '') => {
|
|
64
64
|
if (route === 'easy') return false;
|
|
65
65
|
if (role === 'admin') return true;
|
|
66
66
|
if (isOfficialReserveTab(route)) return false;
|
|
67
|
-
if (role === 'installer') return route === 'tab-intro' || route
|
|
68
|
-
if (role === 'enduser') return
|
|
67
|
+
if (role === 'installer') return route === 'tab-intro' || (route !== 'tab-users' && !isInstallerDenied(route, label));
|
|
68
|
+
if (role === 'enduser') return isEndUserTab(route, label);
|
|
69
69
|
return false;
|
|
70
70
|
};
|
|
71
71
|
const defaultTab = () => 'tab-intro';
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
return normalize(`${button?.getAttribute?.('aria-label') || ''} ${button?.getAttribute?.('title') || ''} ${testIds}`);
|
|
134
134
|
};
|
|
135
135
|
const isSystemSettingsButton = button => /buildicon|system settings|systemeinstellungen|systeeminstellingen/.test(toolbarButtonSignature(button));
|
|
136
|
-
const isExpertModeButton = button => /expert|experten/.test(toolbarButtonSignature(button));
|
|
136
|
+
const isExpertModeButton = button => button?.dataset?.eosExpertControl === '1' || /expert|experten/.test(toolbarButtonSignature(button));
|
|
137
137
|
const markAdminOnlyToolbarControls = () => safe(() => {
|
|
138
138
|
const toolbar = document.querySelector('.eos-top-toolbar,.MuiAppBar-root .MuiToolbar-root');
|
|
139
139
|
if (!toolbar) return;
|
|
@@ -226,7 +226,6 @@
|
|
|
226
226
|
['Datenpunkte', 'Messwerte prüfen und freigegebene Werte schreiben', 'tab-objects', 'datapoints'],
|
|
227
227
|
['Struktur', 'Räume und Funktionen für Smart Home zuordnen', 'tab-enums', 'structure'],
|
|
228
228
|
['Geräte', 'Geräteintegration und Inbetriebnahme öffnen', 'tab-devicemanager', 'devices'],
|
|
229
|
-
['Zugänge & Rechte', 'Passwörter im nativen Benutzereditor verwalten', 'tab-users', 'rights'],
|
|
230
229
|
['Basis-Einstellungen', 'Standort, Sprache und Anlagenparameter', 'basic-settings', 'settings'],
|
|
231
230
|
...(backupTab ? [['NexoWatt Sicherung', 'Sicherung und Wiederherstellung des EOS-Systems', backupTab, 'backup']] : []),
|
|
232
231
|
['EOS Cockpit', 'Energie-, Lade- und Gebäudesteuerung öffnen', uiTab, 'eos'],
|
|
@@ -234,6 +233,7 @@
|
|
|
234
233
|
}
|
|
235
234
|
return [
|
|
236
235
|
['EOS Cockpit', 'Energie, Laden und Gebäude bedienen', uiTab, 'eos'],
|
|
236
|
+
['Datenpunkte', 'Messwerte und Zustände ausschließlich lesen', 'tab-objects', 'datapoints'],
|
|
237
237
|
['Smart Home', 'Räume, Funktionen und freigegebene Geräte zuordnen', 'tab-enums', 'structure'],
|
|
238
238
|
...(backupTab ? [['NexoWatt Sicherung', 'Eigene Sicherungen ausführen und wiederherstellen', backupTab, 'backup']] : []),
|
|
239
239
|
];
|
|
@@ -320,7 +320,7 @@
|
|
|
320
320
|
'tr', '.MuiTableRow-root', '.MuiAccordion-root', '.MuiCard-root', '.MuiListItem-root',
|
|
321
321
|
'[role="row"]', '[data-instance-row]', '[data-testid="adapter-card"]', '[data-testid="instance-card"]',
|
|
322
322
|
].join(',');
|
|
323
|
-
const reserveId = /^(?:system\.adapter\.)?(?:admin|backitup)\.\d+$/i;
|
|
323
|
+
const reserveId = /^(?:system\.adapter\.)?(?:admin|backitup|xterm)\.\d+$/i;
|
|
324
324
|
const normalizeInstance = value => String(value || '').trim().replace(/^system\.adapter\./i, '');
|
|
325
325
|
const identityValues = node => {
|
|
326
326
|
if (!node) return [];
|
|
@@ -337,7 +337,7 @@
|
|
|
337
337
|
.replace(/nexowatt-backup\.\d+/gi, '')
|
|
338
338
|
.replace(/eos-backup\.\d+/gi, '')
|
|
339
339
|
.replace(/system\.adapter\.(?:eos-admin|nexowatt-backup|eos-backup)\.\d+/gi, '');
|
|
340
|
-
return /(?:^|[\s|,;])(?:system\.adapter\.)?(?:admin|backitup)\.\d+(?=$|[\s|,;])/i.test(text.trim());
|
|
340
|
+
return /(?:^|[\s|,;])(?:system\.adapter\.)?(?:admin|backitup|xterm)\.\d+(?=$|[\s|,;])/i.test(text.trim());
|
|
341
341
|
};
|
|
342
342
|
const rowIsReserve = row => identityValues(row).some(value => reserveId.test(value)) || rowTextContainsReserve(row);
|
|
343
343
|
const setHidden = (row, hidden) => {
|
|
@@ -363,12 +363,12 @@
|
|
|
363
363
|
|
|
364
364
|
paper.querySelectorAll(rowSelector).forEach(row => setHidden(row, rowIsReserve(row)));
|
|
365
365
|
paper.querySelectorAll([
|
|
366
|
-
'[data-id^="system.adapter.admin"]','[data-id^="system.adapter.backitup"]',
|
|
367
|
-
'[data-instance^="admin."]','[data-instance^="backitup."]',
|
|
368
|
-
'[data-instance-id^="admin."]','[data-instance-id^="backitup."]',
|
|
369
|
-
'[data-name="admin"]','[data-name="backitup"]',
|
|
370
|
-
'a[href*="#tab-admin"]','a[href*="#tab-backitup"]',
|
|
371
|
-
'a[href*="system.adapter.admin"]','a[href*="system.adapter.backitup"]',
|
|
366
|
+
'[data-id^="system.adapter.admin"]','[data-id^="system.adapter.backitup"]','[data-id^="system.adapter.xterm"]',
|
|
367
|
+
'[data-instance^="admin."]','[data-instance^="backitup."]','[data-instance^="xterm."]',
|
|
368
|
+
'[data-instance-id^="admin."]','[data-instance-id^="backitup."]','[data-instance-id^="xterm."]',
|
|
369
|
+
'[data-name="admin"]','[data-name="backitup"]','[data-name="xterm"]',
|
|
370
|
+
'a[href*="#tab-admin"]','a[href*="#tab-backitup"]','a[href*="#tab-xterm"]',
|
|
371
|
+
'a[href*="system.adapter.admin"]','a[href*="system.adapter.backitup"]','a[href*="system.adapter.xterm"]',
|
|
372
372
|
].join(',')).forEach(node => setHidden(rowFor(node) || node, true));
|
|
373
373
|
|
|
374
374
|
// Admin 7 table cells may have no metadata. Match only an exact visible instance ID and
|
|
@@ -429,6 +429,111 @@
|
|
|
429
429
|
}
|
|
430
430
|
});
|
|
431
431
|
|
|
432
|
+
|
|
433
|
+
const privilegedFrameObservers = new WeakMap();
|
|
434
|
+
const privilegedActionPattern = /^(?:ems apps?(?: offnen| öffnen)?|app center|app-center|appcenter|simulation|simulator|lizenz|license)$/;
|
|
435
|
+
const isPrivilegedAction = element => {
|
|
436
|
+
const signature = normalize(textOf(element));
|
|
437
|
+
const href = normalize(element?.getAttribute?.('href') || element?.href || element?.getAttribute?.('data-href') || '');
|
|
438
|
+
return privilegedActionPattern.test(signature)
|
|
439
|
+
|| /(?:^|[\/#?&_.-])(?:appcenter|app-center|simulation|simulator|license|lizenz)(?:$|[\/#?&=_.-])/.test(href);
|
|
440
|
+
};
|
|
441
|
+
const setPrivilegedActionHidden = (element, hidden) => {
|
|
442
|
+
if (!element) return;
|
|
443
|
+
const target = element.closest?.('a,button,[role="button"],[role="tab"],.MuiButtonBase-root') || element;
|
|
444
|
+
if (hidden) {
|
|
445
|
+
target.dataset.eosPrivilegedActionHidden = '1';
|
|
446
|
+
target.classList.add('eos-role-hidden');
|
|
447
|
+
target.setAttribute('aria-hidden', 'true');
|
|
448
|
+
if ('disabled' in target) target.disabled = true;
|
|
449
|
+
} else if (target.dataset.eosPrivilegedActionHidden === '1') {
|
|
450
|
+
delete target.dataset.eosPrivilegedActionHidden;
|
|
451
|
+
target.classList.remove('eos-role-hidden');
|
|
452
|
+
target.removeAttribute('aria-hidden');
|
|
453
|
+
if ('disabled' in target) target.disabled = false;
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
const applyPrivilegedActionsInDocument = doc => safe(() => {
|
|
457
|
+
if (!doc?.documentElement) return;
|
|
458
|
+
const admin = state.role === 'admin';
|
|
459
|
+
doc.querySelectorAll('[data-eos-privileged-action-hidden="1"]').forEach(element => {
|
|
460
|
+
if (admin || !isPrivilegedAction(element)) setPrivilegedActionHidden(element, false);
|
|
461
|
+
});
|
|
462
|
+
for (const element of doc.querySelectorAll('a,button,[role="button"],[role="tab"],.MuiButtonBase-root')) {
|
|
463
|
+
if (isPrivilegedAction(element)) setPrivilegedActionHidden(element, !admin);
|
|
464
|
+
}
|
|
465
|
+
if (!doc.documentElement.dataset.eosPrivilegedClickGuard) {
|
|
466
|
+
doc.documentElement.dataset.eosPrivilegedClickGuard = '1';
|
|
467
|
+
doc.addEventListener('click', event => {
|
|
468
|
+
if (state.role === 'admin' || state.role === 'unknown') return;
|
|
469
|
+
const target = event.target?.closest?.('a,button,[role="button"],[role="tab"],.MuiButtonBase-root');
|
|
470
|
+
if (!target || !isPrivilegedAction(target)) return;
|
|
471
|
+
event.preventDefault();
|
|
472
|
+
event.stopImmediatePropagation();
|
|
473
|
+
}, true);
|
|
474
|
+
}
|
|
475
|
+
if (!privilegedFrameObservers.has(doc)) {
|
|
476
|
+
const observer = new MutationObserver(() => {
|
|
477
|
+
window.setTimeout(() => applyPrivilegedActionsInDocument(doc), 0);
|
|
478
|
+
});
|
|
479
|
+
observer.observe(doc.documentElement, { childList: true, subtree: true });
|
|
480
|
+
privilegedFrameObservers.set(doc, observer);
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
const applyPrivilegedIframePolicy = () => safe(() => {
|
|
484
|
+
applyPrivilegedActionsInDocument(document);
|
|
485
|
+
document.querySelectorAll('iframe').forEach(frame => {
|
|
486
|
+
const applyFrame = () => safe(() => applyPrivilegedActionsInDocument(frame.contentDocument));
|
|
487
|
+
if (frame.dataset.eosRoleFrameGuard !== '1') {
|
|
488
|
+
frame.dataset.eosRoleFrameGuard = '1';
|
|
489
|
+
frame.addEventListener('load', applyFrame);
|
|
490
|
+
}
|
|
491
|
+
applyFrame();
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
const scrubInheritedUiAdminSession = () => safe(() => {
|
|
495
|
+
if (state.role === 'admin' || state.role === 'unknown') return;
|
|
496
|
+
const user = String(state.policy?.user || state.policy?.userId || '').replace(/^system\.user\./, '') || state.role;
|
|
497
|
+
const key = `eosUiAdminSessionScrubbed:v7105:${user}:${state.role}`;
|
|
498
|
+
if (sessionStorage.getItem(key) === '1') return;
|
|
499
|
+
sessionStorage.setItem(key, '1');
|
|
500
|
+
const frame = document.createElement('iframe');
|
|
501
|
+
frame.hidden = true;
|
|
502
|
+
frame.tabIndex = -1;
|
|
503
|
+
frame.setAttribute('aria-hidden', 'true');
|
|
504
|
+
frame.src = `${window.location.protocol}//${window.location.hostname}:8188/logout?source=eos-admin&role=${encodeURIComponent(state.role)}&t=${Date.now()}`;
|
|
505
|
+
frame.addEventListener('load', () => window.setTimeout(() => frame.remove(), 1200), { once: true });
|
|
506
|
+
document.body?.appendChild(frame);
|
|
507
|
+
window.setTimeout(() => frame.remove(), 7000);
|
|
508
|
+
});
|
|
509
|
+
const applyEndUserDatapointPolicy = () => safe(() => {
|
|
510
|
+
const paper = appPaper();
|
|
511
|
+
if (!paper) return;
|
|
512
|
+
const readonly = state.role === 'enduser' && currentRoute() === 'tab-objects';
|
|
513
|
+
paper.toggleAttribute('data-eos-datapoints-readonly', readonly);
|
|
514
|
+
if (!readonly) return;
|
|
515
|
+
paper.querySelectorAll('[data-eos-object-writable="1"],button[title*="edit" i],button[title*="delete" i],button[aria-label*="edit" i],button[aria-label*="delete" i]').forEach(control => {
|
|
516
|
+
control.setAttribute('aria-disabled', 'true');
|
|
517
|
+
control.setAttribute('data-eos-enduser-write-blocked', '1');
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
const clearLegacyHeuristicRestrictionsForAdmin = () => safe(() => {
|
|
521
|
+
if (state.role !== 'admin') return;
|
|
522
|
+
document.querySelectorAll('[data-eos-role-hidden]').forEach(element => {
|
|
523
|
+
element.removeAttribute('data-eos-role-hidden');
|
|
524
|
+
element.removeAttribute('aria-hidden');
|
|
525
|
+
element.style.removeProperty('display');
|
|
526
|
+
});
|
|
527
|
+
document.querySelectorAll('[data-eos-readonly],[data-eos-enduser-write-blocked]').forEach(element => {
|
|
528
|
+
element.removeAttribute('data-eos-readonly');
|
|
529
|
+
element.removeAttribute('data-eos-enduser-write-blocked');
|
|
530
|
+
element.removeAttribute('aria-disabled');
|
|
531
|
+
element.style.removeProperty('pointer-events');
|
|
532
|
+
element.style.removeProperty('opacity');
|
|
533
|
+
if ('disabled' in element) element.disabled = false;
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
|
|
432
537
|
const apply = () => {
|
|
433
538
|
if (!state.policy || state.role === 'unknown') return;
|
|
434
539
|
setRoleClasses(state.role);
|
|
@@ -436,10 +541,14 @@
|
|
|
436
541
|
applyMenuPolicy();
|
|
437
542
|
markAdminOnlyToolbarControls();
|
|
438
543
|
applySensitiveDialogPolicy();
|
|
544
|
+
clearLegacyHeuristicRestrictionsForAdmin();
|
|
439
545
|
redirectIfNeeded();
|
|
440
546
|
ensureSafeOverview();
|
|
441
547
|
filterNativeUsersPage();
|
|
442
548
|
hideOfficialReserveSurfaces();
|
|
549
|
+
applyEndUserDatapointPolicy();
|
|
550
|
+
applyPrivilegedIframePolicy();
|
|
551
|
+
scrubInheritedUiAdminSession();
|
|
443
552
|
ensureReserveObserver();
|
|
444
553
|
suppressPermissionErrors();
|
|
445
554
|
window.NEXOWATT_EOS_ACCOUNT_MANAGEMENT?.refreshEntry?.();
|
|
@@ -491,6 +600,10 @@
|
|
|
491
600
|
if (state.role === 'installer') window.NEXOWATT_EOS_BASIC_SETTINGS?.open?.();
|
|
492
601
|
return;
|
|
493
602
|
}
|
|
603
|
+
if (state.role === 'enduser' && currentRoute() === 'tab-objects') {
|
|
604
|
+
const writeTarget = event.target?.closest?.('[data-eos-object-writable="1"],[data-eos-enduser-write-blocked="1"],button[title*="edit" i],button[title*="delete" i],button[aria-label*="edit" i],button[aria-label*="delete" i]');
|
|
605
|
+
if (writeTarget) { event.preventDefault(); event.stopImmediatePropagation(); return; }
|
|
606
|
+
}
|
|
494
607
|
const target = event.target?.closest?.('[data-eos-admin-only-control="1"],[data-eos-system-settings-control="1"],[data-eos-role-tab],a[href*="#tab-"],a[href*="#/tab-"]');
|
|
495
608
|
if (!target) return;
|
|
496
609
|
if (target.matches('[data-eos-admin-only-control="1"]')) { event.preventDefault(); event.stopImmediatePropagation(); return; }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const VERSION = '
|
|
4
|
+
const VERSION = 'v7105-nexowatt-native-shell-native-overview';
|
|
5
5
|
const previous = window.NEXOWATT_NATIVE_SHELL;
|
|
6
6
|
if (previous?.version === VERSION) return;
|
|
7
7
|
previous?.destroy?.();
|
package/build/main.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* Admin backend
|
|
4
5
|
*
|
|
@@ -1267,14 +1268,9 @@ class Admin extends adapter_core_1.Adapter {
|
|
|
1267
1268
|
return deny(socketClient, command, callback, 'technical diagnostics are installer/service-only');
|
|
1268
1269
|
}
|
|
1269
1270
|
if (command === 'changePassword') {
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
const allowed = role === 'installer'
|
|
1274
|
-
? new Set([selfUser, 'system.user.installer', 'system.user.user', 'system.user.guest']).has(targetUser)
|
|
1275
|
-
: targetUser === selfUser;
|
|
1276
|
-
if (!allowed) return deny(socketClient, command, callback, 'password target outside EOS role scope');
|
|
1277
|
-
return true;
|
|
1271
|
+
// Initial password activation has a separate, tightly scoped backend endpoint.
|
|
1272
|
+
// The normal Admin socket password editor remains Service/Admin-only.
|
|
1273
|
+
return deny(socketClient, command, callback, 'password administration is Service-only');
|
|
1278
1274
|
}
|
|
1279
1275
|
if (['addUser', 'delUser', 'addGroup', 'delGroup'].includes(command)) {
|
|
1280
1276
|
return deny(socketClient, command, callback, 'account administration is Service-only');
|
|
@@ -1295,9 +1291,16 @@ class Admin extends adapter_core_1.Adapter {
|
|
|
1295
1291
|
return deny(socketClient, command, callback, 'end users may only maintain Smart Home assignments');
|
|
1296
1292
|
}
|
|
1297
1293
|
}
|
|
1298
|
-
if (['setState', 'delState', 'createState'].includes(command)
|
|
1299
|
-
|
|
1300
|
-
|
|
1294
|
+
if (['setState', 'delState', 'createState'].includes(command)) {
|
|
1295
|
+
if (role === 'enduser') {
|
|
1296
|
+
return deny(socketClient, command, callback, 'end-user datapoints are read-only in EOS Admin');
|
|
1297
|
+
}
|
|
1298
|
+
if (objectId === `${this.namespace}.info.uiTabsVisible`) {
|
|
1299
|
+
return deny(socketClient, command, callback, 'navigation layout is Service-only');
|
|
1300
|
+
}
|
|
1301
|
+
if (/^(?:admin|backitup|xterm)\.\d+(?:\.|$)/.test(objectId)) {
|
|
1302
|
+
return deny(socketClient, command, callback, 'internal Service reserve is Admin/Service-only');
|
|
1303
|
+
}
|
|
1301
1304
|
}
|
|
1302
1305
|
return original(socketClient, command, callback, ...args);
|
|
1303
1306
|
};
|
package/io-package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "eos-admin",
|
|
4
|
-
"version": "7.10.
|
|
4
|
+
"version": "7.10.5",
|
|
5
5
|
"titleLang": {
|
|
6
6
|
"en": "NexoWatt EOS Admin",
|
|
7
7
|
"de": "NexoWatt EOS Admin",
|
|
@@ -18,10 +18,15 @@
|
|
|
18
18
|
"connectionType": "local",
|
|
19
19
|
"dataSource": "push",
|
|
20
20
|
"news": {
|
|
21
|
-
"7.10.
|
|
22
|
-
"de": "Stable 7.10.
|
|
23
|
-
"en": "Stable 7.10.
|
|
24
|
-
"nl": "Stable 7.10.
|
|
21
|
+
"7.10.5": {
|
|
22
|
+
"de": "Stable 7.10.5 stellt die vollständigen Administratorrechte wieder her und trennt die Rollen verbindlich über den authentifizierten Backend-Kontext. Admin darf Datenpunkte schreiben, den Expertenmodus in beide Richtungen schalten und sieht Admin-/XTerm-Kacheln. Endkunden sehen Datenpunkte ausschließlich lesend; App-Center, Lizenz, Simulation, Benutzerverwaltung, ioBroker Admin, XTerm und Expertenmodus bleiben für Installateur und Endkunde gesperrt. Navigationsänderungen werden neustartsicher im Adapter-State gespeichert; Sicherung erscheint nur bei aktiver Backup-Instanz.",
|
|
23
|
+
"en": "Stable 7.10.5 restores full administrator authority and binds roles exclusively to the authenticated backend context. Admin can write datapoints, toggle expert mode in both directions and sees the Admin/XTerm cards. End users can view datapoints read-only; App Center, License, Simulation, account management, ioBroker Admin, XTerm and expert mode remain blocked for Installer and End User. Navigation changes are stored restart-safely in an adapter state, and Backup is shown only for an enabled backup instance.",
|
|
24
|
+
"nl": "Stable 7.10.5 herstelt de volledige beheerdersrechten en bepaalt rollen uitsluitend via de geauthenticeerde backendcontext. Admin kan datapunten schrijven, de expertmodus in beide richtingen schakelen en ziet de Admin-/XTerm-kaarten. Eindgebruikers kunnen datapunten alleen lezen; App Center, Licentie, Simulatie, accountbeheer, ioBroker Admin, XTerm en expertmodus blijven geblokkeerd voor Installateur en Eindgebruiker. Navigatiewijzigingen worden herstartveilig in een adapterstatus opgeslagen en Back-up verschijnt alleen bij een ingeschakelde back-upinstantie."
|
|
25
|
+
},
|
|
26
|
+
"7.10.4": {
|
|
27
|
+
"de": "Stable 7.10.4 verschiebt die Einstellung für automatische NexoWatt-Adapter-Updates vollständig in die Systemeinstellungen hinter dem Schraubenschlüssel. Auf Übersicht, Module und allen anderen Hauptseiten wird die Update-Karte nicht mehr eingeblendet. Die stabile Update-Logik und die Absturzkorrekturen aus 7.10.2 bleiben unverändert.",
|
|
28
|
+
"en": "Stable 7.10.4 moves the automatic NexoWatt adapter update control entirely into System Settings behind the wrench button. The update card is no longer shown on Overview, Modules or any other main page. Stable update behavior and the 7.10.2 crash fixes remain unchanged.",
|
|
29
|
+
"nl": "Stable 7.10.4 verplaatst de instelling voor automatische NexoWatt-adapterupdates volledig naar de systeeminstellingen achter de moersleutelknop. De updatekaart wordt niet meer weergegeven op Overzicht, Modules of andere hoofdpagina’s. De stabiele updatelogica en crashfixes uit 7.10.2 blijven ongewijzigd."
|
|
25
30
|
},
|
|
26
31
|
"7.10.2": {
|
|
27
32
|
"de": "Stable-Hotfix 7.10.2 beseitigt die EOS-Admin-Startschleife: Stable-Update-Status wird nicht mehr in die laufende Instanzkonfiguration geschrieben, der erste Abgleich startet verzögert und das Release prüft die vollständige Backend-Modulkette einschließlich eosRequestSecurity.",
|
|
@@ -349,7 +354,7 @@
|
|
|
349
354
|
"icon": "admin.svg",
|
|
350
355
|
"messagebox": true,
|
|
351
356
|
"enabled": true,
|
|
352
|
-
"extIcon": "https://unpkg.com/iobroker.eos-admin@7.10.
|
|
357
|
+
"extIcon": "https://unpkg.com/iobroker.eos-admin@7.10.5/admin/admin.svg",
|
|
353
358
|
"keywords": [
|
|
354
359
|
"NexoWatt",
|
|
355
360
|
"EOS",
|
|
@@ -360,7 +365,7 @@
|
|
|
360
365
|
"licensed"
|
|
361
366
|
],
|
|
362
367
|
"compact": true,
|
|
363
|
-
"readme": "https://unpkg.com/iobroker.eos-admin@7.10.
|
|
368
|
+
"readme": "https://unpkg.com/iobroker.eos-admin@7.10.5/README.md",
|
|
364
369
|
"authors": [
|
|
365
370
|
"NexoWatt"
|
|
366
371
|
],
|
|
@@ -428,7 +433,7 @@
|
|
|
428
433
|
"nondeletable": false,
|
|
429
434
|
"allowAdapterUpdate": true,
|
|
430
435
|
"allowAdapterDelete": false,
|
|
431
|
-
"meta": "https://unpkg.com/iobroker.eos-admin@7.10.
|
|
436
|
+
"meta": "https://unpkg.com/iobroker.eos-admin@7.10.5/io-package.json",
|
|
432
437
|
"npmPackage": "iobroker.eos-admin",
|
|
433
438
|
"packetName": "iobroker.eos-admin",
|
|
434
439
|
"publisher": "NexoWatt"
|
|
@@ -1001,6 +1006,23 @@
|
|
|
1001
1006
|
"def": ""
|
|
1002
1007
|
},
|
|
1003
1008
|
"native": {}
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
"_id": "info.uiTabsVisible",
|
|
1012
|
+
"type": "state",
|
|
1013
|
+
"common": {
|
|
1014
|
+
"name": {
|
|
1015
|
+
"en": "EOS navigation layout",
|
|
1016
|
+
"de": "EOS-Navigationslayout",
|
|
1017
|
+
"nl": "EOS-navigatielay-out"
|
|
1018
|
+
},
|
|
1019
|
+
"role": "json",
|
|
1020
|
+
"type": "string",
|
|
1021
|
+
"read": true,
|
|
1022
|
+
"write": true,
|
|
1023
|
+
"def": "[]"
|
|
1024
|
+
},
|
|
1025
|
+
"native": {}
|
|
1004
1026
|
}
|
|
1005
1027
|
],
|
|
1006
1028
|
"schemas": {
|
|
@@ -1188,5 +1210,5 @@
|
|
|
1188
1210
|
}
|
|
1189
1211
|
}
|
|
1190
1212
|
},
|
|
1191
|
-
"version": "7.10.
|
|
1213
|
+
"version": "7.10.5"
|
|
1192
1214
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.eos-admin",
|
|
3
3
|
"description": "NexoWatt EOS Admin – repaired stable baseline with restart-safe automatic updates, native account passwords and persistent cockpit scrolling.",
|
|
4
|
-
"version": "7.10.
|
|
4
|
+
"version": "7.10.5",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"bluefox <dogafox@gmail.com>",
|
|
7
7
|
"apollon77",
|
|
@@ -133,13 +133,15 @@
|
|
|
133
133
|
"NEXOWATT_EOS_PREBUILT_MANIFEST.json",
|
|
134
134
|
"tools/nexowatt-prebuilt-release-selftest.cjs",
|
|
135
135
|
"tools/nexowatt-stable-v7103-selftest.cjs",
|
|
136
|
-
"README_STABILITY_V7.10.
|
|
137
|
-
"RELEASE_NOTES_V7.10.
|
|
138
|
-
"PUBLISH_STABLE_V7.10.
|
|
139
|
-
"INSTALL_TEST_V7.10.
|
|
140
|
-
"RELEASE_ACCEPTANCE_V7.10.
|
|
141
|
-
"MERGE_UPDATE_README_V7.10.
|
|
142
|
-
"tools/nexowatt-auto-update-placement-selftest.cjs"
|
|
136
|
+
"README_STABILITY_V7.10.5.md",
|
|
137
|
+
"RELEASE_NOTES_V7.10.5.md",
|
|
138
|
+
"PUBLISH_STABLE_V7.10.5.md",
|
|
139
|
+
"INSTALL_TEST_V7.10.5.md",
|
|
140
|
+
"RELEASE_ACCEPTANCE_V7.10.5.md",
|
|
141
|
+
"MERGE_UPDATE_README_V7.10.5.md",
|
|
142
|
+
"tools/nexowatt-auto-update-placement-selftest.cjs",
|
|
143
|
+
"tools/nexowatt-role-security-selftest.cjs",
|
|
144
|
+
"SECURITY_ROLE_MATRIX_V7.10.5.md"
|
|
143
145
|
],
|
|
144
146
|
"scripts": {
|
|
145
147
|
"npm": "npm i -f && cd src-admin && npm i -f",
|
|
@@ -174,7 +176,7 @@
|
|
|
174
176
|
"nexowatt:repo-entry": "node tools/nexowatt-generate-repo-entry.cjs",
|
|
175
177
|
"nexowatt:patch-repo": "node tools/nexowatt-patch-repo.cjs",
|
|
176
178
|
"nexowatt:repair-update": "node tools/nexowatt-repair-eos-admin-update.cjs",
|
|
177
|
-
"check:eos-stability": "node tools/nexowatt-stability-check.cjs && node tools/nexowatt-esm-syntax-selftest.cjs && node tools/nexowatt-backend-runtime-selftest.cjs && node tools/nexowatt-prebuilt-release-selftest.cjs && node tools/nexowatt-import-integrity-selftest.cjs && node tools/nexowatt-entrypoint-smoke-selftest.cjs && node tools/nexowatt-frontend-graph-check.cjs && node tools/nexowatt-policy-selftest.cjs && node tools/nexowatt-publish-channel-selftest.cjs && node tools/nexowatt-release-defaults-selftest.cjs && node tools/nexowatt-role-access-selftest.cjs && node tools/nexowatt-internal-reserve-selftest.cjs && node tools/nexowatt-modern-ui-selftest.cjs && node tools/nexowatt-login-layout-selftest.cjs && node tools/nexowatt-branding-selftest.cjs && node tools/nexowatt-default-port-selftest.cjs && node tools/nexowatt-module-popup-selftest.cjs && node tools/nexowatt-datapoint-selftest.cjs && node tools/nexowatt-update-selftest.cjs && node tools/nexowatt-datapoint-interaction-selftest.cjs && node tools/nexowatt-manual-write-policy-selftest.cjs && node tools/nexowatt-value-column-selftest.cjs && node tools/nexowatt-native-shell-selftest.cjs && node tools/nexowatt-assistant-separation-selftest.cjs && node tools/nexowatt-runtime-cleanup-selftest.cjs && node tools/nexowatt-version-sync-selftest.cjs && node tools/nexowatt-merge-update-selftest.cjs && node tools/nexowatt-password-write-selftest.cjs && node tools/nexowatt-account-password-flow-selftest.cjs && npm run check:eos-stable-v7103 && node tools/nexowatt-ems-overview-selftest.cjs && node tools/nexowatt-ui-overview-runtime-selftest.cjs && node tools/nexowatt-auto-update-selftest.cjs && node tools/nexowatt-auto-update-placement-selftest.cjs",
|
|
179
|
+
"check:eos-stability": "node tools/nexowatt-stability-check.cjs && node tools/nexowatt-esm-syntax-selftest.cjs && node tools/nexowatt-backend-runtime-selftest.cjs && node tools/nexowatt-prebuilt-release-selftest.cjs && node tools/nexowatt-import-integrity-selftest.cjs && node tools/nexowatt-entrypoint-smoke-selftest.cjs && node tools/nexowatt-frontend-graph-check.cjs && node tools/nexowatt-policy-selftest.cjs && node tools/nexowatt-publish-channel-selftest.cjs && node tools/nexowatt-release-defaults-selftest.cjs && node tools/nexowatt-role-access-selftest.cjs && node tools/nexowatt-internal-reserve-selftest.cjs && node tools/nexowatt-modern-ui-selftest.cjs && node tools/nexowatt-login-layout-selftest.cjs && node tools/nexowatt-branding-selftest.cjs && node tools/nexowatt-default-port-selftest.cjs && node tools/nexowatt-module-popup-selftest.cjs && node tools/nexowatt-datapoint-selftest.cjs && node tools/nexowatt-update-selftest.cjs && node tools/nexowatt-datapoint-interaction-selftest.cjs && node tools/nexowatt-manual-write-policy-selftest.cjs && node tools/nexowatt-value-column-selftest.cjs && node tools/nexowatt-native-shell-selftest.cjs && node tools/nexowatt-assistant-separation-selftest.cjs && node tools/nexowatt-runtime-cleanup-selftest.cjs && node tools/nexowatt-version-sync-selftest.cjs && node tools/nexowatt-merge-update-selftest.cjs && node tools/nexowatt-password-write-selftest.cjs && node tools/nexowatt-account-password-flow-selftest.cjs && npm run check:eos-stable-v7103 && node tools/nexowatt-ems-overview-selftest.cjs && node tools/nexowatt-ui-overview-runtime-selftest.cjs && node tools/nexowatt-auto-update-selftest.cjs && node tools/nexowatt-auto-update-placement-selftest.cjs && node tools/nexowatt-role-security-selftest.cjs",
|
|
178
180
|
"nexowatt:patch-built-frontend": "node tools/nexowatt-patch-built-frontend.cjs",
|
|
179
181
|
"clean:eos-runtime": "node tools/nexowatt-clean-legacy-runtime.cjs",
|
|
180
182
|
"precheck:eos-package": "npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run clean:eos-runtime",
|
|
@@ -202,7 +204,8 @@
|
|
|
202
204
|
"check:eos-prebuilt-release": "node tools/nexowatt-prebuilt-release-selftest.cjs",
|
|
203
205
|
"seal:eos-prebuilt-release": "node tools/nexowatt-prebuilt-release-selftest.cjs --write",
|
|
204
206
|
"check:eos-stable-v7103": "node tools/nexowatt-stable-v7103-selftest.cjs",
|
|
205
|
-
"test:eos-auto-update-placement": "node tools/nexowatt-auto-update-placement-selftest.cjs"
|
|
207
|
+
"test:eos-auto-update-placement": "node tools/nexowatt-auto-update-placement-selftest.cjs",
|
|
208
|
+
"check:eos-role-security": "node tools/nexowatt-role-security-selftest.cjs"
|
|
206
209
|
},
|
|
207
210
|
"author": "NexoWatt",
|
|
208
211
|
"private": false,
|
|
@@ -213,7 +216,7 @@
|
|
|
213
216
|
},
|
|
214
217
|
"nexowattReleasePolicy": {
|
|
215
218
|
"distTag": "latest",
|
|
216
|
-
"purpose": "accepted stable NexoWatt EOS
|
|
219
|
+
"purpose": "accepted stable NexoWatt EOS admin-rights and RBAC correction 7.10.5"
|
|
217
220
|
},
|
|
218
221
|
"publisher": "NexoWatt"
|
|
219
222
|
}
|
|
@@ -6,10 +6,10 @@ for(const code of [source,built]){
|
|
|
6
6
|
must(code.includes("EOS_STABLE_INITIAL_PASSWORD = 'nexowatt'"),'initial password constant missing');
|
|
7
7
|
must(code.includes("if (created || !String(object.common?.password || '').trim())")||code.includes("if (created || !String(object.common?.password || '').trim())"),'password is not limited to new/passwordless accounts');
|
|
8
8
|
for(const marker of ['nexowattPasswordChangeRequired: false','eosPasswordChangeRequired: false','nexowattFirstLoginPending: false','eosFirstLoginRequired: false','forcePasswordChange: false','standardPasswordMode: true']) must(code.includes(marker),`legacy first-login flag is not cleared: ${marker}`);
|
|
9
|
-
must(code.includes("command === 'changePassword'")&&code.includes('password
|
|
9
|
+
must(code.includes("command === 'changePassword'")&&code.includes('password administration is Service-only'),'native password command role guard missing');
|
|
10
10
|
}
|
|
11
11
|
must(io.native.eosRequireFirstLoginPassword===false&&io.native.eosRequireFirstLoginPasswordChange===false,'forced first-password defaults remain');
|
|
12
12
|
must(!boot.includes('installIntegratedFirstLogin(base);')&&!boot.includes('showFirstLoginPassword(resolved, base);'),'forced password surface remains active');
|
|
13
13
|
must(!index.includes('eos-account-management.js'),'custom reset runtime remains active');
|
|
14
|
-
must(role.includes(
|
|
15
|
-
console.log('[NexoWatt EOS standard password flow] OK (
|
|
14
|
+
must(role.includes("route !== 'tab-users'")&&role.includes('filterNativeUsersPage'),'native Users page is not blocked for Installer/End User');
|
|
15
|
+
console.log('[NexoWatt EOS standard password flow] OK (initial password on creation, Admin-only native password editor, no forced reset flow)');
|
|
@@ -23,6 +23,12 @@ const LEGACY_OVERLAYS = [
|
|
|
23
23
|
'src-admin/public/js/eos-runtime-fixes.js',
|
|
24
24
|
'src-admin/public/js/eos-hard-logout.js',
|
|
25
25
|
'src-admin/public/css/eos-branding.css',
|
|
26
|
+
// Removed 7.10.4 role-security overlays. These files must be deleted when
|
|
27
|
+
// a complete repository ZIP is accidentally extracted over an older tree;
|
|
28
|
+
// otherwise the sealed-release check correctly rejects them as stale input.
|
|
29
|
+
'adminWww/nexowatt-role-security.js',
|
|
30
|
+
'src-admin/nexowatt-role-security.js',
|
|
31
|
+
'build/lib/eosRoleSecurity.js',
|
|
26
32
|
];
|
|
27
33
|
|
|
28
34
|
const readJson = file => JSON.parse(fs.readFileSync(file, 'utf8'));
|