Einstellungen: Gitea-Actions-Variablen per API übernehmen (Token nur für den Abruf)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
RubenRWU
2026-10-15 15:36:35 +02:00
parent 7d8c226da2
commit b6165bc0b2
4 changed files with 190 additions and 1 deletions

View File

@@ -76,6 +76,11 @@
<div class="fgrid"><label class="f">COST_API_BASE<input type="text" data-k="cost_api_base" value="{{ v.cost_api_base }}"></label><label class="f">COST_TRACKING_ENABLED<input type="text" data-k="cost_tracking_enabled" value="{{ v.cost_tracking_enabled }}" placeholder="true"></label></div>
</div>
<div class="card" style="grid-column:1/-1"><h3>Aus Gitea übernehmen <span class="muted" style="font-weight:400">· statt Abschreiben</span></h3>
<p class="sub">Liest die Actions-Variablen deines Repos (<span class="mono">DOMAIN, PROJECT_ID, STACK_ID, REGISTRY, LLM_*, SMTP_*, COST_* …</span>; nie Secrets) und trägt sie hier ein. Der Token wird nur für diesen Abruf genutzt und nicht gespeichert.</p>
<div class="fgrid c3"><label class="f">Gitea-URL<input type="text" id="g-url" value="https://gitea.onyva.dev"></label><label class="f">Repo (Besitzer/Name)<input type="text" id="g-repo" value="Onyva/transkriptipt-platform"></label><label class="f">Token (Lesezugriff)<input type="password" id="g-token" autocomplete="off"></label></div>
<div class="row" style="margin-top:8px"><button class="btn sm" onclick="gFetch()">Variablen abrufen</button><span class="hint" id="g-info"></span></div><div id="g-out" style="margin-top:8px"></div></div>
<div class="card" style="grid-column:1/-1"><h3>Weitere Core-Einstellungen <span class="muted" style="font-weight:400">· aus dem Schema des Cores erzeugt, gelten für alle Tenants</span></h3>
<p class="sub">Alles, was der Core als geteilte Einstellung deklariert und oben noch keine eigene Maske hat. Neue Core-Variablen erscheinen hier automatisch und gehen beim Deploy ins Container-Env. Leer = Standard des Cores.</p>
<div id="dyn"><span class="muted">Lade …</span></div></div>
@@ -105,6 +110,20 @@ async function testOidc(){
const i=document.getElementById('oidc-info'); i.textContent='Teste …';
try{const r=await api('POST','/api/oidc/test'); i.textContent='✔ Verbindung ok – '+r.apps+' App(s) im Login'}catch(e){i.textContent='✘ '+e.message}
}
let gRows = [];
async function gFetch(){
const i=document.getElementById('g-info'); i.textContent='Rufe ab …'; document.getElementById('g-out').innerHTML='';
try{
const r=await api('POST','/api/gitea/variables',{url:document.getElementById('g-url').value,repo:document.getElementById('g-repo').value,token:document.getElementById('g-token').value});
document.getElementById('g-token').value=''; gRows=r.rows; i.textContent=r.count+' Variablen gelesen';
document.getElementById('g-out').innerHTML=`<table class="t"><thead><tr><th></th><th>Gitea-Variable</th><th>→ Einstellung</th><th>Wert aus Gitea</th><th>aktuell hier</th><th>Status</th></tr></thead><tbody>`+r.rows.map((x,n)=>`<tr><td>${x.setting&&x.status!=='gleich'?`<input type="checkbox" data-g="${n}" checked>`:''}</td><td class="mono">${esc(x.name)}</td><td class="mono">${esc(x.setting||'–')}</td><td>${esc(x.value)}</td><td class="muted">${esc(x.current)}</td><td><span class="badge ${x.status==='neu'?'cyan':x.status==='geändert'?'warn':x.status==='gleich'?'ok':''}">${x.status}</span> <span class="hint">${esc(x.note)}</span></td></tr>`).join('')+`</tbody></table><div class="row" style="margin-top:8px"><button class="btn sm cyan" onclick="gApply()">Ausgewählte übernehmen</button><span class="hint">Danach „Alles speichern“ nicht nötig – wird direkt gespeichert.</span></div>`;
}catch(e){ i.textContent='✘ '+e.message; }
}
async function gApply(){
const body={}; document.querySelectorAll('[data-g]:checked').forEach(c=>{const x=gRows[+c.dataset.g]; if(x.setting&&x.raw!=null) body[x.setting]=x.raw;});
if(!Object.keys(body).length) return toast('Nichts ausgewählt',1);
try{ await api('PUT','/api/settings',body); toast(Object.keys(body).length+' Einstellungen übernommen'); setTimeout(()=>location.reload(),800); }catch(e){ toast(e.message,1) }
}
async function loadDyn(){
const box=document.getElementById('dyn');
try{