iobroker.eos-admin 7.9.29 → 7.9.30

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.
@@ -1,10 +1,18 @@
1
1
  (() => {
2
2
  'use strict';
3
3
 
4
- const VERSION = 'v27-security-visibility-guard';
4
+ const VERSION = 'v30-security-admin-only-polish';
5
5
  const LEGACY_ADMIN = 'admin';
6
6
  const LEGACY_ADMIN_INSTANCE = 'admin.0';
7
- const SECURITY_URL = '/nexowatt/security/session';
7
+ const ASSET_BASE = (() => {
8
+ const script = document.currentScript?.src || document.querySelector('script[src*="eos-security-ui.js"]')?.src || window.location.href;
9
+ return new URL('../', script).href;
10
+ })();
11
+ const SECURITY_URLS = [
12
+ new URL('nexowatt/security/session', ASSET_BASE).href,
13
+ new URL('eos/security/status', ASSET_BASE).href,
14
+ '/nexowatt/security/session',
15
+ ];
8
16
 
9
17
  const state = {
10
18
  loaded: false,
@@ -21,6 +29,7 @@
21
29
  };
22
30
 
23
31
  const normalize = value => String(value || '').replace(/\s+/g, ' ').trim();
32
+ const normalizeFlat = value => normalize(value).toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
24
33
  const normalizeAdapter = value => {
25
34
  let adapter = String(value || '').trim().toLowerCase();
26
35
  adapter = adapter.replace(/^system\.adapter\./, '').replace(/^iobroker\./, '').replace(/^@nexowatt\/iobroker\./, '').replace(/^@nexowatt\//, '');
@@ -31,11 +40,6 @@
31
40
  const isAdminUser = () => !!(state.policy?.isAdmin || state.policy?.isEosAdminGroup || state.policy?.isAdministrator);
32
41
  const protectedAdapters = () => new Set((state.policy?.protectedAdapters || []).map(normalizeAdapter).filter(Boolean));
33
42
 
34
- const isLegacyAdminId = value => {
35
- const text = String(value || '').toLowerCase();
36
- return text === LEGACY_ADMIN || text === LEGACY_ADMIN_INSTANCE || text === 'system.adapter.admin' || text === 'system.adapter.admin.0';
37
- };
38
-
39
43
  const isProtectedAdapter = value => {
40
44
  const adapter = normalizeAdapter(value);
41
45
  return !!adapter && protectedAdapters().has(adapter);
@@ -59,11 +63,7 @@
59
63
  },
60
64
  };
61
65
 
62
- const closestPanel = el => {
63
- if (!el || !el.closest) return null;
64
- return el.closest('.MuiCard-root, .MuiPaper-root, [role="row"], tr, .MuiListItem-root, .MuiBox-root');
65
- };
66
-
66
+ const closestPanel = el => el?.closest?.('.MuiCard-root, .MuiPaper-root, [role="row"], tr, .MuiListItem-root, .MuiBox-root') || null;
67
67
  const markHidden = el => {
68
68
  if (!el || el.classList?.contains('eos-security-keep-visible')) return;
69
69
  el.classList.add('eos-security-hidden');
@@ -80,7 +80,7 @@
80
80
  };
81
81
 
82
82
  const elementTextMatchesLegacyAdmin = el => {
83
- const text = normalize(el?.textContent || '').toLowerCase();
83
+ const text = normalizeFlat(el?.textContent || '');
84
84
  if (!text) return false;
85
85
  if (text.includes('eos-admin') || text.includes('eos admin')) return false;
86
86
  return /\badmin\.0\b/.test(text) || /system\.adapter\.admin(?:\.0)?\b/.test(text) || /\biobroker\.admin\b/.test(text);
@@ -96,7 +96,7 @@
96
96
  if (elementHasLegacyAdminIcon(el) || elementTextMatchesLegacyAdmin(el)) candidates.add(el);
97
97
  });
98
98
  candidates.forEach(el => {
99
- const text = normalize(el.textContent || '').toLowerCase();
99
+ const text = normalizeFlat(el.textContent || '');
100
100
  if (text.includes('eos-admin') || text.includes('eos admin')) return;
101
101
  markHidden(el);
102
102
  });
@@ -106,14 +106,13 @@
106
106
  if (!state.policy?.restrictProtectedAdapterControls || isAdminUser()) return;
107
107
  const protectedSet = protectedAdapters();
108
108
  if (!protectedSet.size) return;
109
-
110
109
  document.querySelectorAll('.MuiCard-root, .MuiPaper-root, [role="row"], tr, .MuiListItem-root').forEach(panel => {
111
110
  let adapter = '';
112
111
  const icon = panel.querySelector('img[src*="/adapter/"], img[src*="adapter/"]');
113
112
  const src = icon ? String(icon.getAttribute('src') || '') : '';
114
113
  const match = src.match(/adapter\/([^\/]+)\//i);
115
114
  if (match) adapter = normalizeAdapter(match[1]);
116
- const text = normalize(panel.textContent || '').toLowerCase();
115
+ const text = normalizeFlat(panel.textContent || '');
117
116
  if (!adapter) {
118
117
  for (const protectedName of protectedSet) {
119
118
  if (new RegExp(`\\b${protectedName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\.\\d+)?\\b`, 'i').test(text)) {
@@ -125,8 +124,8 @@
125
124
  if (!adapter || !protectedSet.has(adapter)) return;
126
125
  panel.classList.add('eos-security-protected-adapter');
127
126
  panel.querySelectorAll('button,[role="button"],a').forEach(button => {
128
- const label = normalize(`${button.textContent || ''} ${button.getAttribute('title') || ''} ${button.getAttribute('aria-label') || ''}`).toLowerCase();
129
- if (/löschen|delete|remove|deinstall|uninstall/.test(label)) {
127
+ const label = normalizeFlat(`${button.textContent || ''} ${button.getAttribute('title') || ''} ${button.getAttribute('aria-label') || ''}`);
128
+ if (/loschen|delete|remove|deinstall|uninstall/.test(label)) {
130
129
  button.classList.add('eos-security-hidden-delete');
131
130
  button.setAttribute('disabled', 'disabled');
132
131
  button.setAttribute('aria-disabled', 'true');
@@ -134,23 +133,84 @@
134
133
  }
135
134
  });
136
135
  });
137
-
138
136
  document.querySelectorAll('[role="menuitem"], .MuiMenuItem-root').forEach(item => {
139
- const text = normalize(item.textContent || '').toLowerCase();
140
- if (/löschen|delete|remove|deinstall|uninstall/.test(text)) {
141
- // Context menus cannot always be mapped back to the originating card. For protected NexoWatt systems,
142
- // deletion through pop-up menus is blocked by the command guard and visually hidden for non-admin users.
137
+ const text = normalizeFlat(item.textContent || '');
138
+ if (/loschen|delete|remove|deinstall|uninstall/.test(text)) {
143
139
  item.classList.add('eos-security-hidden-delete');
144
140
  item.style.display = 'none';
145
141
  }
146
142
  });
147
143
  };
148
144
 
145
+ const replaceTextNodes = () => {
146
+ const map = new Map([
147
+ ['EOS security', 'EOS Sicherheit'],
148
+ ['EOS Security', 'EOS Sicherheit'],
149
+ ['Disable Assistent', 'EOS Assist deaktivieren'],
150
+ ['Disable Assistant', 'EOS Assist deaktivieren'],
151
+ ['NexoWatt security', 'NexoWatt Sicherheit'],
152
+ ['Protected adapters', 'Geschützte Systemadapter'],
153
+ ['Legacy admin', 'Alter Admin-Zugang'],
154
+ ]);
155
+ const walker = document.createTreeWalker(document.body || document.documentElement, NodeFilter.SHOW_TEXT);
156
+ let node;
157
+ while ((node = walker.nextNode())) {
158
+ let value = node.nodeValue || '';
159
+ let changed = false;
160
+ for (const [from, to] of map) {
161
+ if (value.includes(from)) {
162
+ value = value.split(from).join(to);
163
+ changed = true;
164
+ }
165
+ }
166
+ if (changed) node.nodeValue = value;
167
+ }
168
+ };
169
+
170
+ const securityTextPattern = /(eos\s*(security|sicherheit)|nexowatt\s*sicherheit|alter admin-zugang|alten admin|admin\.0 sperren|geschuetzte systemadapter|geschützte systemadapter|eos administratorgruppen|administratorgruppen)/i;
171
+
172
+ const hideEosSecuritySettingsForNonAdmins = () => {
173
+ if (isAdminUser()) return;
174
+ const dialogs = Array.from(document.querySelectorAll('.MuiDialog-paper, [role="dialog"], form'));
175
+ dialogs.forEach(dialog => {
176
+ // Hide the EOS Security tab itself.
177
+ const tabs = Array.from(dialog.querySelectorAll('[role="tab"], .MuiTab-root, button, .MuiButtonBase-root'));
178
+ let activeSecurityTab = false;
179
+ tabs.forEach(tab => {
180
+ const txt = normalize(tab.textContent || tab.getAttribute('aria-label') || tab.getAttribute('title') || '');
181
+ if (/^\s*EOS\s*(Security|Sicherheit)\s*$/i.test(txt)) {
182
+ if (tab.getAttribute('aria-selected') === 'true' || tab.classList.contains('Mui-selected')) activeSecurityTab = true;
183
+ tab.classList.add('eos-security-admin-only-field');
184
+ tab.setAttribute('aria-hidden', 'true');
185
+ tab.style.display = 'none';
186
+ }
187
+ });
188
+ if (activeSecurityTab) {
189
+ const nextTab = tabs.find(tab => tab.style.display !== 'none' && !tab.classList.contains('eos-security-admin-only-field'));
190
+ if (nextTab) setTimeout(() => nextTab.click(), 0);
191
+ }
192
+ // Hide all field groups belonging to the EOS Security panel if the panel is still rendered.
193
+ Array.from(dialog.querySelectorAll('.MuiFormControl-root, .MuiGrid-root, .MuiTableContainer-root, .MuiTable-root, [role="tabpanel"], fieldset, section, .MuiBox-root')).forEach(el => {
194
+ const txt = normalize(el.textContent || '');
195
+ if (!txt || txt.length > 2200) return;
196
+ if (securityTextPattern.test(txt)) {
197
+ el.classList.add('eos-security-admin-only-field');
198
+ el.setAttribute('aria-hidden', 'true');
199
+ el.style.display = 'none';
200
+ }
201
+ });
202
+ });
203
+ };
204
+
149
205
  const applyPolicyToDom = () => {
150
- document.documentElement.classList.toggle('eos-security-admin-user', isAdminUser());
151
- document.documentElement.classList.toggle('eos-security-non-admin-user', !isAdminUser());
206
+ const admin = isAdminUser();
207
+ document.documentElement.classList.toggle('eos-security-admin-user', admin);
208
+ document.documentElement.classList.toggle('eos-security-non-admin-user', !admin);
209
+ document.documentElement.classList.toggle('eos-security-nonadmin', !admin);
210
+ replaceTextNodes();
152
211
  hideLegacyAdminPanels();
153
212
  hideProtectedDeleteControls();
213
+ hideEosSecuritySettingsForNonAdmins();
154
214
  };
155
215
 
156
216
  const scheduleApply = () => {
@@ -165,16 +225,20 @@
165
225
  };
166
226
 
167
227
  const loadPolicy = async () => {
168
- try {
169
- const response = await fetch(SECURITY_URL, { credentials: 'same-origin', cache: 'no-store' });
170
- const policy = await response.json();
171
- state.policy = { ...state.policy, ...policy };
172
- state.loaded = true;
173
- } catch (e) {
174
- state.loaded = false;
175
- state.policy = { ...state.policy, isAdmin: false, isEosAdminGroup: false, isAdministrator: false };
176
- console.warn('[NexoWatt EOS] Cannot read security policy, using safe non-admin UI mode:', e);
228
+ for (const url of SECURITY_URLS) {
229
+ try {
230
+ const response = await fetch(url, { credentials: 'same-origin', cache: 'no-store' });
231
+ if (!response.ok) continue;
232
+ const policy = await response.json();
233
+ state.policy = { ...state.policy, ...policy };
234
+ state.loaded = true;
235
+ scheduleApply();
236
+ return;
237
+ } catch { /* try next */ }
177
238
  }
239
+ state.loaded = false;
240
+ state.policy = { ...state.policy, isAdmin: false, isEosAdminGroup: false, isAdministrator: false };
241
+ console.warn('[NexoWatt EOS] Cannot read security policy, using safe non-admin UI mode');
178
242
  scheduleApply();
179
243
  };
180
244
 
@@ -187,26 +251,19 @@
187
251
  document.addEventListener('click', event => {
188
252
  const target = event.target?.closest?.('button,[role="button"],a,[role="menuitem"],.MuiMenuItem-root');
189
253
  if (!target || isAdminUser()) return;
190
- const label = normalize(`${target.textContent || ''} ${target.getAttribute?.('title') || ''} ${target.getAttribute?.('aria-label') || ''}`).toLowerCase();
191
- if (/löschen|delete|remove|deinstall|uninstall/.test(label)) {
254
+ const label = normalizeFlat(`${target.textContent || ''} ${target.getAttribute?.('title') || ''} ${target.getAttribute?.('aria-label') || ''}`);
255
+ if (/loschen|delete|remove|deinstall|uninstall/.test(label)) {
192
256
  target.classList.add('eos-security-hidden-delete');
193
257
  target.style.display = 'none';
194
258
  }
195
259
  }, true);
196
260
 
197
- if (document.readyState === 'loading') {
198
- document.addEventListener('DOMContentLoaded', () => {
199
- loadPolicy();
200
- installObserver();
201
- [300, 1000, 2500, 5000].forEach(ms => window.setTimeout(scheduleApply, ms));
202
- }, { once: true });
203
- } else {
261
+ const start = () => {
204
262
  loadPolicy();
205
263
  installObserver();
206
264
  [300, 1000, 2500, 5000].forEach(ms => window.setTimeout(scheduleApply, ms));
207
- }
208
- window.addEventListener('hashchange', () => {
209
- loadPolicy();
210
- scheduleApply();
211
- });
265
+ };
266
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start, { once: true });
267
+ else start();
268
+ window.addEventListener('hashchange', () => { loadPolicy(); scheduleApply(); });
212
269
  })();
@@ -1,16 +1,35 @@
1
1
  {
2
+ "Adapter": "Adapter",
3
+ "Administratorgruppen für EOS Sicherheit": "Administratorgruppen für EOS Sicherheit",
4
+ "Aktiv": "Aktiv",
5
+ "Alten Admin für Installateur und Endkunde ausblenden": "Alten Admin für Installateur und Endkunde ausblenden",
6
+ "Alten Admin sperren": "Alten Admin sperren",
2
7
  "Cannot change password for \"%s\": %s": "Kennwort für „%s“ kann nicht geändert werden: %s",
3
8
  "Cannot change password for %s:": "Das Passwort für den Benutzer „%s“ kann nicht geändert werden. Bitte versuchen Sie es manuell.\nÖffnen Sie die CLI, melden Sie sich als Benutzer mit Root-/Sudo-Rechten an und geben Sie ein:",
9
+ "Dieser Bereich ist nur für Administratoren. Hier legst du fest, ob der alte Admin gesperrt wird und welche Systemadapter vor Änderungen durch Installateur- oder Endkundenbenutzer geschützt sind. Updates bleiben möglich.": "Dieser Bereich ist nur für Administratoren. Hier legst du fest, ob der alte Admin gesperrt wird und welche Systemadapter vor Änderungen durch Installateur- oder Endkundenbenutzer geschützt sind. Updates bleiben möglich.",
4
10
  "Empty password isn't allowed": "Leeres Passwort ist nicht zulässig",
5
11
  "Enter your new password by prompt.": "Geben Sie bei der entsprechenden Aufforderung Ihr neues Passwort ein.",
12
+ "Geschützte Adapter nur durch Administratoren ändern lassen": "Geschützte Adapter nur durch Administratoren ändern lassen",
13
+ "Geschützte Systemadapter": "Geschützte Systemadapter",
14
+ "Geschützte Systemadapter aktivieren": "Geschützte Systemadapter aktivieren",
15
+ "Gruppe": "Gruppe",
16
+ "Hinweis": "Hinweis",
17
+ "Hält den alten admin.0 deaktiviert und verschiebt ihn auf den lokalen Fallback-Bind/Port. Nur Administratoren sollten diese Sperre für Wartung deaktivieren.": "Hält den alten admin.0 deaktiviert und verschiebt ihn auf die lokale Sperr-Adresse und den Sperr-Port. Nur Administratoren sollten diese Sperre für Wartung deaktivieren.",
6
18
  "Minimal length is 6 chars": "Die Mindestlänge beträgt 6 Zeichen",
7
19
  "New password": "Neues Passwort",
20
+ "NexoWatt Sicherheit": "NexoWatt Sicherheit",
21
+ "Nur Benutzer der EOS-Administratorgruppen können den alten admin-Adapter und die Instanz admin.0 sehen oder bewusst entsperren.": "Nur Benutzer der EOS-Administratorgruppen können den alten Admin-Adapter und die Instanz admin.0 sehen oder bewusst entsperren.",
22
+ "Nur Mitglieder dieser Gruppen dürfen gesperrte EOS-Systembereiche sehen und warten. Die Gruppe administrator ist immer enthalten.": "Nur Mitglieder dieser Gruppen dürfen gesperrte EOS-Systembereiche sehen und warten. Die Gruppe administrator ist immer enthalten.",
8
23
  "Offline message": "Anleitung zum Ändern des Passworts. Öffnen Sie die CLI, melden Sie sich als Benutzer mit Root-/Sudo-Rechten an und geben Sie ein:\n\n„sudo passwd %s“\nGeben Sie Ihr neues Passwort bei der Eingabeaufforderung ein.",
9
24
  "Password and password repeat are not equal": "Passwort und Passwortwiederholung sind nicht gleich",
10
25
  "Password is too short (min 6 chars)": "Das Passwort ist zu kurz (mindestens 6 Zeichen)",
11
26
  "Password repeat": "Passwort wiederholen",
12
27
  "Password successfully changed for \"%s\"": "Passwort für „%s“ erfolgreich geändert",
28
+ "Schützt ausgewählte Adapter für Installateur-/Endkundenbenutzer über Administrator-ACLs und EOS-UI-Regeln. dontDelete und nondeletable bleiben false, damit Updates weiter funktionieren.": "Schützt ausgewählte Adapter für Installateur- und Endkundenbenutzer über Administratorrechte und EOS-Regeln. dontDelete und nondeletable bleiben false, damit Updates weiter funktionieren.",
13
29
  "Set password": "Passwort festlegen",
30
+ "Setzt Administrator-ACLs auf die geschützte Adapterliste. Installateur-/Endkundenbenutzer können diese Adapter nicht stoppen, aktivieren oder löschen; Administratoren können sie weiterhin updaten und warten.": "Setzt Administratorrechte auf die geschützte Adapterliste. Installateur- und Endkundenbenutzer können diese Adapter nicht stoppen, aktivieren oder löschen. Administratoren können sie weiterhin updaten und warten.",
31
+ "Sperr-Adresse des alten Admins": "Sperr-Adresse des alten Admins",
32
+ "Sperr-Port des alten Admins": "Sperr-Port des alten Admins",
14
33
  "The password for user \"%s\" was successfully changed": "Das Passwort für den Benutzer „%s“ wurde erfolgreich geändert",
15
34
  "This message is no more actual and was generated by other instance start": "Diese Meldung ist nicht mehr aktuell und wurde beim Start einer anderen Instanz generiert.",
16
35
  "User \"%s\" has well known password. We suggest to change it.": "Das Betriebssystem scheint ein bekanntes Standardpasswort für System-Benutzer \"%s\" zu nutzen. Aus Sicherheitsgründen empfehlen wir dies zu ändern.",
@@ -1,18 +1,37 @@
1
1
  {
2
- "Offline message": "Instruction how to change password. Open CLI, login as user with root/sudo rights and enter:\n\"sudo passwd %s\"\nEnter your new password by prompt.",
3
- "The password for user \"%s\" was successfully changed": "The password for user \"%s\" was successfully changed",
2
+ "Adapter": "Adapter",
3
+ "Administratorgruppen für EOS Sicherheit": "EOS security administrator groups",
4
+ "Aktiv": "Active",
5
+ "Alten Admin für Installateur und Endkunde ausblenden": "Hide legacy admin from installer and end customer",
6
+ "Alten Admin sperren": "Lock legacy admin",
7
+ "Cannot change password for \"%s\": %s": "Cannot change password for \"%s\": %s",
4
8
  "Cannot change password for %s:": "The password for user \"%s\" cannot be changed. Please try to do it manually.\nOpen CLI, login as user with root/sudo rights and enter:",
9
+ "Dieser Bereich ist nur für Administratoren. Hier legst du fest, ob der alte Admin gesperrt wird und welche Systemadapter vor Änderungen durch Installateur- oder Endkundenbenutzer geschützt sind. Updates bleiben möglich.": "This area is only for administrators. It controls whether the legacy admin is locked and which system adapters are protected from installer or end-customer changes. Updates remain possible.",
10
+ "Empty password isn't allowed": "Empty password isn't allowed",
5
11
  "Enter your new password by prompt.": "Enter your new password by prompt.",
6
- "User \"%s\" has well known password. We suggest to change it.": "The operating system appears to be using a well-known default password for system user \"%s\". For security reasons, we recommend changing it.",
12
+ "Geschützte Adapter nur durch Administratoren ändern lassen": "Only administrators may change protected adapters",
13
+ "Geschützte Systemadapter": "Protected system adapters",
14
+ "Geschützte Systemadapter aktivieren": "Enable protected system adapters",
15
+ "Gruppe": "Group",
16
+ "Hinweis": "Note",
17
+ "Hält den alten admin.0 deaktiviert und verschiebt ihn auf den lokalen Fallback-Bind/Port. Nur Administratoren sollten diese Sperre für Wartung deaktivieren.": "Keeps the legacy admin.0 disabled and moves it to the local lock bind/port. Only administrators should disable this lock for maintenance.",
18
+ "Minimal length is 6 chars": "Minimal length is 6 chars",
7
19
  "New password": "New password",
8
- "Password repeat": "Password repeat",
9
- "Set password": "Set password",
10
- "This message is no more actual and was generated by other instance start": "This message is no more actual and was generated by other instance start",
11
- "Empty password isn't allowed": "Empty password isn't allowed",
20
+ "NexoWatt Sicherheit": "NexoWatt Security",
21
+ "Nur Benutzer der EOS-Administratorgruppen können den alten admin-Adapter und die Instanz admin.0 sehen oder bewusst entsperren.": "Only users in EOS administrator groups can see or intentionally unlock the legacy admin adapter and admin.0 instance.",
22
+ "Nur Mitglieder dieser Gruppen dürfen gesperrte EOS-Systembereiche sehen und warten. Die Gruppe administrator ist immer enthalten.": "Only members of these groups may see and maintain locked EOS system areas. The administrator group is always included.",
23
+ "Offline message": "Instruction how to change password. Open CLI, login as user with root/sudo rights and enter:\n\"sudo passwd %s\"\nEnter your new password by prompt.",
12
24
  "Password and password repeat are not equal": "Password and password repeat are not equal",
13
25
  "Password is too short (min 6 chars)": "Password is too short (min 6 chars)",
26
+ "Password repeat": "Password repeat",
14
27
  "Password successfully changed for \"%s\"": "Password successfully changed for \"%s\"",
15
- "Cannot change password for \"%s\": %s": "Cannot change password for \"%s\": %s",
16
- "Minimal length is 6 chars": "Minimal length is 6 chars",
28
+ "Schützt ausgewählte Adapter für Installateur-/Endkundenbenutzer über Administrator-ACLs und EOS-UI-Regeln. dontDelete und nondeletable bleiben false, damit Updates weiter funktionieren.": "Protects selected adapters from installer/end-customer users via administrator ACLs and EOS UI rules. dontDelete and nondeletable remain false so updates keep working.",
29
+ "Set password": "Set password",
30
+ "Setzt Administrator-ACLs auf die geschützte Adapterliste. Installateur-/Endkundenbenutzer können diese Adapter nicht stoppen, aktivieren oder löschen; Administratoren können sie weiterhin updaten und warten.": "Applies administrator ACLs to the protected adapter list. Installer/end-customer users cannot stop, enable or delete these adapters; administrators can still update and maintain them.",
31
+ "Sperr-Adresse des alten Admins": "Legacy admin lock bind address",
32
+ "Sperr-Port des alten Admins": "Legacy admin lock port",
33
+ "The password for user \"%s\" was successfully changed": "The password for user \"%s\" was successfully changed",
34
+ "This message is no more actual and was generated by other instance start": "This message is no more actual and was generated by other instance start",
35
+ "User \"%s\" has well known password. We suggest to change it.": "The operating system appears to be using a well-known default password for system user \"%s\". For security reasons, we recommend changing it.",
17
36
  "User: %s": "User: %s"
18
37
  }
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "eos-admin",
4
- "version": "7.9.29",
4
+ "version": "7.9.30",
5
5
  "titleLang": {
6
6
  "en": "NexoWatt EOS Admin",
7
7
  "de": "NexoWatt EOS Admin",
@@ -18,9 +18,9 @@
18
18
  "connectionType": "local",
19
19
  "dataSource": "push",
20
20
  "news": {
21
- "7.9.29": {
22
- "en": "Hotfix: restores the missing iobroker.mcp runtime dependency and prevents EOS Admin from crashing when MCP is unavailable.",
23
- "de": "Hotfix: stellt die fehlende iobroker.mcp-Laufzeitabhängigkeit wieder her und verhindert, dass EOS Admin abstürzt, wenn MCP nicht verfügbar ist."
21
+ "7.9.30": {
22
+ "en": "UI polish: moves the compact navigation button further left, improves the black NexoWatt logo badge, fixes EOS Assist opening and hides EOS Security from non-admin users.",
23
+ "de": "UI-Feinschliff: Kompakt-Navigationspfeil weiter nach links gesetzt, schwarzes NexoWatt-Logo verbessert, EOS Assist Öffnen repariert und EOS Security für Nicht-Administratoren ausgeblendet."
24
24
  },
25
25
  "7.9.29": {
26
26
  "en": "Self-update hardening: EOS Admin now uses its own webserver upgrade path, update-all skips the running EOS shell, and object-level delete locks are cleared so updates stay possible.",
@@ -194,7 +194,7 @@
194
194
  "icon": "admin.svg",
195
195
  "messagebox": true,
196
196
  "enabled": true,
197
- "extIcon": "https://unpkg.com/iobroker.eos-admin@7.9.29/admin/admin.png",
197
+ "extIcon": "https://unpkg.com/iobroker.eos-admin@7.9.30/admin/admin.png",
198
198
  "keywords": [
199
199
  "NexoWatt",
200
200
  "EOS",
@@ -205,7 +205,7 @@
205
205
  "licensed"
206
206
  ],
207
207
  "compact": true,
208
- "readme": "https://unpkg.com/iobroker.eos-admin@7.9.29/README.md",
208
+ "readme": "https://unpkg.com/iobroker.eos-admin@7.9.30/README.md",
209
209
  "authors": [
210
210
  "bluefox <bluefox@ccu.io>",
211
211
  "hobbyquaker <hq@ccu.io>"
@@ -274,7 +274,7 @@
274
274
  "nondeletable": false,
275
275
  "allowAdapterUpdate": true,
276
276
  "allowAdapterDelete": false,
277
- "meta": "https://unpkg.com/iobroker.eos-admin@7.9.29/io-package.json",
277
+ "meta": "https://unpkg.com/iobroker.eos-admin@7.9.30/io-package.json",
278
278
  "npmPackage": "iobroker.eos-admin"
279
279
  },
280
280
  "native": {
@@ -337,7 +337,9 @@
337
337
  }
338
338
  ],
339
339
  "eosAdminOnlyGroup": "system.group.administrator",
340
- "eosApplyAdminOnlyAclToProtectedAdapters": true
340
+ "eosApplyAdminOnlyAclToProtectedAdapters": true,
341
+ "eosAssistantEnabled": true,
342
+ "eosAssistantAdminOnly": false
341
343
  },
342
344
  "notifications": [
343
345
  {