feat: Home Assistant Benutzername/Passwort-Authentifizierung
Ergänzt die HA-Integration um Password-Grant OAuth2: Nutzer können sich nun wahlweise mit einem Long-Lived Token oder mit Benutzername/Passwort anmelden. Access Tokens werden automatisch per Refresh-Token erneuert.
This commit is contained in:
@@ -417,9 +417,30 @@
|
||||
<input type="url" id="ha-account-url" placeholder="http://homeassistant.local:8123" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Anmeldemethode</label>
|
||||
<div style="display:flex;gap:16px">
|
||||
<label class="toggle-label">
|
||||
<input type="radio" name="ha-auth-method" value="token" id="ha-auth-token" checked /> Long-Lived Token
|
||||
</label>
|
||||
<label class="toggle-label">
|
||||
<input type="radio" name="ha-auth-method" value="password" id="ha-auth-password" /> Benutzername/Passwort
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="ha-token-group">
|
||||
<label>Long-Lived Access Token</label>
|
||||
<input type="password" id="ha-account-token" placeholder="Token aus Profil → Sicherheit" autocomplete="off" />
|
||||
</div>
|
||||
<div id="ha-credentials-group" class="hidden">
|
||||
<div class="form-group">
|
||||
<label>Benutzername</label>
|
||||
<input type="text" id="ha-account-username" autocomplete="username" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Passwort</label>
|
||||
<input type="password" id="ha-account-userpass" autocomplete="current-password" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="ha-account-error" class="form-error hidden"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -1266,28 +1266,65 @@ function openHAAccountModal() {
|
||||
document.getElementById('ha-account-name').value = '';
|
||||
document.getElementById('ha-account-url').value = '';
|
||||
document.getElementById('ha-account-token').value = '';
|
||||
document.getElementById('ha-account-username').value = '';
|
||||
document.getElementById('ha-account-userpass').value = '';
|
||||
document.getElementById('ha-account-error').classList.add('hidden');
|
||||
// Reset to token method
|
||||
document.getElementById('ha-auth-token').checked = true;
|
||||
document.getElementById('ha-token-group').classList.remove('hidden');
|
||||
document.getElementById('ha-credentials-group').classList.add('hidden');
|
||||
openModal('modal-ha-account');
|
||||
}
|
||||
|
||||
function bindHAAccountModal() {
|
||||
// Toggle auth method fields
|
||||
document.querySelectorAll('[name="ha-auth-method"]').forEach(r => {
|
||||
r.addEventListener('change', () => {
|
||||
const isPw = document.getElementById('ha-auth-password').checked;
|
||||
document.getElementById('ha-token-group').classList.toggle('hidden', isPw);
|
||||
document.getElementById('ha-credentials-group').classList.toggle('hidden', !isPw);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('ha-account-save').onclick = async () => {
|
||||
const name = document.getElementById('ha-account-name').value.trim();
|
||||
const url = document.getElementById('ha-account-url').value.trim();
|
||||
const token = document.getElementById('ha-account-token').value.trim();
|
||||
const isPw = document.getElementById('ha-auth-password').checked;
|
||||
const errEl = document.getElementById('ha-account-error');
|
||||
if (!name || !url || !token) {
|
||||
errEl.textContent = 'Bitte alle Felder ausfüllen';
|
||||
|
||||
if (!name || !url) {
|
||||
errEl.textContent = 'Bitte Name und URL ausfüllen';
|
||||
errEl.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
const body = { name, url };
|
||||
if (isPw) {
|
||||
const username = document.getElementById('ha-account-username').value.trim();
|
||||
const password = document.getElementById('ha-account-userpass').value.trim();
|
||||
if (!username || !password) {
|
||||
errEl.textContent = 'Bitte Benutzername und Passwort ausfüllen';
|
||||
errEl.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
body.username = username;
|
||||
body.password = password;
|
||||
} else {
|
||||
const token = document.getElementById('ha-account-token').value.trim();
|
||||
if (!token) {
|
||||
errEl.textContent = 'Bitte Access Token ausfüllen';
|
||||
errEl.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
body.token = token;
|
||||
}
|
||||
errEl.classList.add('hidden');
|
||||
|
||||
const saveBtn = document.getElementById('ha-account-save');
|
||||
saveBtn.disabled = true;
|
||||
saveBtn.textContent = 'Verbinde…';
|
||||
try {
|
||||
const account = await api.post('/homeassistant/accounts', { name, url, token });
|
||||
const account = await api.post('/homeassistant/accounts', body);
|
||||
state.haAccounts.push(account);
|
||||
renderCalendarList();
|
||||
closeModal('modal-ha-account');
|
||||
|
||||
Reference in New Issue
Block a user