Статус: карточка ключа организации — контур и пометка «ИСТЁК»; SMB-пароль папок шлюза — генерация и показ

Ключ организации на странице «Статус» теперь строится из своего сертификата
в справочнике активного профиля ИШ (ownStoreCerts), включая истёкший: карточка
показывает владельца, издателя, контур (боевой/тестовый) и срок. Истёкший ключ
виден явной пометкой «ИСТЁК» и отдельным заголовком, а не маскируется под
«ключ не подключён». Показать владельца ДО установки ключа нельзя — сертификата
нет в файлах флешки, он появляется в справочнике профиля только после установки.

Папки шлюза по сети (простой режим): кнопка «Сгенерировать» создаёт надёжный
пароль (16 символов, crypto.getRandomValues) прямо в поле, поле теперь видимое;
после сохранения пароль показывается один раз с кнопкой «Скопировать» —
записать, так как позже bj его не покажет. Пустое поле по-прежнему оставляет
прежний пароль при повторном сохранении.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
fontvielle
2026-10-21 11:29:48 +03:00
parent 847f858cd9
commit 365ec1196d
3 changed files with 32 additions and 14 deletions
@@ -94,8 +94,9 @@
<label style="display:flex;gap:8px;align-items:center;font-weight:500;margin:12px 0 0"><input type="checkbox" name="enabled" style="width:auto"> Открыть папки шлюза по сети</label>
<div id="ig-sh-simple" class="ig-sh-grid">
<label class="f">Логин<input name="user" value="igate-share" autocomplete="off" spellcheck="false"></label>
<label class="f">Пароль (от 8 символов)<input name="password" type="password" autocomplete="new-password" spellcheck="false" placeholder="пусто — прежний"></label>
<label class="f">Пароль (от 8 символов)<span style="display:flex;gap:6px"><input name="password" type="text" autocomplete="new-password" spellcheck="false" placeholder="пусто — прежний" style="flex:1;min-width:0"><button type="button" class="btn sm" id="ig-sh-gen" title="Создать надёжный пароль">Сгенерировать</button></span></label>
</div>
<small id="ig-sh-pwnote" class="muted" style="display:block;font-size:12.5px;margin-top:6px">Пароль вводят в Windows при первом открытии папок. Запишите его: bj передаёт пароль в Samba и показать позже не сможет. Пустое поле при повторном сохранении оставляет прежний пароль.</small>
<div id="ig-sh-domain" hidden>
<div id="ig-sh-access" class="muted" style="font-size:13px;margin-top:10px"></div>
<div id="ig-sh-join" hidden style="margin-top:10px">
@@ -214,6 +215,13 @@
}
function load(){ return fetch('/admin/setup/igate/share',{cache:'no-store'}).then(function(r){return r.json()}).then(show).catch(function(){ stl.textContent='Состояние не получено.'; }); }
f.addEventListener('change',function(e){ if(e.target.name==='mode') sync(); });
var genbtn=document.getElementById('ig-sh-gen');
if(genbtn) genbtn.addEventListener('click',function(){
var cs='ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789', a=new Uint32Array(16), s='';
crypto.getRandomValues(a); for(var i=0;i<16;i++) s+=cs[a[i]%cs.length];
f.password.type='text'; f.password.value=s; f.password.focus(); f.password.select();
o.innerHTML='<span class="muted">Пароль создан — запишите его перед сохранением.</span>';
});
f.addEventListener('submit',function(e){ e.preventDefault();
var p=new URLSearchParams(), url='/admin/setup/igate/share', d=mode()==='domain';
if(d && !cur.joined){
@@ -225,7 +233,13 @@
if(!d){ p.set('user',f.user.value.trim()); p.set('password',f.password.value); }
o.textContent='Сохраняю… (первый раз — установка Samba, до пары минут)';
}
post(url,p).then(function(r){ o.innerHTML=r.ok?ok(r.output):bad(r.error); f.password.value=''; f.adminpw.value=''; return load(); }).catch(function(){ o.innerHTML=bad('не сохранено'); }); });
var pwSet=(!d)?f.password.value:'';
post(url,p).then(function(r){
if(r.ok){ o.innerHTML=ok(r.output)+(pwSet?' <b>Пароль:</b> <code>'+esc(pwSet)+'</code> <button type="button" class="btn sm" data-copy="'+esc(pwSet)+'">Скопировать</button> — запишите, посмотреть позже нельзя.':'');
var cb=o.querySelector('[data-copy]'); if(cb) cb.onclick=function(){ (window.bjCopy||function(t){navigator.clipboard&&navigator.clipboard.writeText(t)})(cb.dataset.copy); cb.textContent='Скопировано ✓'; };
} else o.innerHTML=bad(r.error);
f.password.value=''; f.adminpw.value=''; return load();
}).catch(function(){ o.innerHTML=bad('не сохранено'); }); });
load();
})();
var st=null;