caterium-app/public/core/account-security-v1774.js
2026-09-11 10:09:04 +03:00

122 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(()=>{
'use strict';
if(window.CateriumAccountSecurityV1774)return;
const VERSION='17.7.4';
const MIN_PASSWORD_LENGTH=8;
const $=id=>document.getElementById(id);
const cloud=()=>window.SunCloudV2||null;
const client=()=>cloud()?.getClient?.()||null;
const mustChange=user=>Boolean(user?.app_metadata?.must_change_password===true);
let forcedOpen=false,checking=false;
function installStyle(){
if($('cateriumAccountSecurityV1774Style'))return;
const st=document.createElement('style');
st.id='cateriumAccountSecurityV1774Style';
st.textContent=`
.cat-password-gate-v1774{position:fixed;inset:0;z-index:200500;background:rgba(12,16,14,.72);backdrop-filter:blur(8px);display:grid;place-items:center;padding:18px}
.cat-password-gate-v1774-card{width:min(460px,100%);background:#fff;border-radius:20px;padding:22px;box-shadow:0 28px 90px rgba(0,0,0,.32)}
.cat-password-gate-v1774-card h2{margin:0 0 6px;color:#15364c}.cat-password-gate-v1774-card p{color:#6d746f;line-height:1.45}
.cat-password-gate-v1774-card label{display:block;margin-top:12px;font-size:12px;font-weight:800;color:#343a36}.cat-password-gate-v1774-card input{width:100%;box-sizing:border-box;margin-top:6px;padding:11px 12px;border:1px solid #d8ded9;border-radius:10px;font:inherit}
.cat-password-gate-v1774-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.cat-password-gate-v1774-actions button{border-radius:10px;padding:9px 12px;font-weight:850}.cat-password-gate-v1774-actions .primary{background:#15364c;color:#fff;border:1px solid #15364c}.cat-password-gate-v1774-actions .outline{background:#fff;border:1px solid #d5dad6;color:#15364c}
.cat-password-gate-v1774-error{min-height:20px;margin-top:10px;color:#9f2d2d;font-size:12px}.cat-password-gate-v1774-success{color:#1e6a3d}
.cat-profile-password-v1774{margin-top:10px;padding-top:10px;border-top:1px solid #e6e9e7;display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}.cat-profile-password-v1774 small{display:block;color:#7a807c;margin-top:3px}
body.cat-password-required-v1774{overflow:hidden!important}
`;
document.head.appendChild(st);
}
async function latestUser(){
const c=client();if(!c)return null;
try{const result=await c.auth.getUser();return result.data?.user||null}catch(_){return null}
}
async function signOutAndReload(){
const c=client();
try{await c?.auth?.signOut?.({scope:'local'})}catch(_){try{await cloud()?.signOut?.()}catch(__){}}
location.reload();
}
async function changePassword(currentPassword,newPassword){
const c=client();if(!c)throw new Error('Сессия пользователя недоступна.');
const result=await c.functions.invoke('caterium-change-password',{body:{current_password:currentPassword,new_password:newPassword}});
const message=result.data?.error||result.error?.message;
if(result.error||result.data?.error)throw new Error(message||'Не удалось изменить пароль.');
if(result.data?.status!=='changed')throw new Error('Сервер не подтвердил смену пароля.');
return result.data;
}
function closeVoluntary(host){if(!forcedOpen)host?.remove()}
function openPasswordModal({forced=false}={}){
installStyle();
$('cateriumPasswordGateV1774')?.remove();
forcedOpen=forced;
const host=document.createElement('div');
host.id='cateriumPasswordGateV1774';
host.className='cat-password-gate-v1774';
host.innerHTML=`<div class="cat-password-gate-v1774-card"><h2>${forced?'Создайте постоянный пароль':'Сменить пароль'}</h2><p>${forced?'Вы вошли по временному паролю. Чтобы продолжить работу в Caterium, замените его на постоянный пароль.':'После смены пароля потребуется войти в Caterium заново.'}</p><label>Текущий пароль<input id="catCurrentPasswordV1774" type="password" autocomplete="current-password"></label><label>Новый пароль<input id="catNewPasswordV1774" type="password" autocomplete="new-password"></label><label>Повторите новый пароль<input id="catNewPassword2V1774" type="password" autocomplete="new-password"></label><div id="catPasswordErrorV1774" class="cat-password-gate-v1774-error"></div><div class="cat-password-gate-v1774-actions">${forced?'<button class="outline" id="catPasswordSignOutV1774" type="button">Выйти</button>':'<button class="outline" id="catPasswordCancelV1774" type="button">Отмена</button>'}<button class="primary" id="catPasswordSaveV1774" type="button">Сохранить пароль</button></div></div>`;
document.body.appendChild(host);
if(forced)document.body.classList.add('cat-password-required-v1774');
if(forced)$('catPasswordSignOutV1774').onclick=()=>signOutAndReload();
else $('catPasswordCancelV1774').onclick=()=>closeVoluntary(host);
const save=$('catPasswordSaveV1774'),err=$('catPasswordErrorV1774');
const run=async()=>{
const current=String($('catCurrentPasswordV1774')?.value||'');
const next=String($('catNewPasswordV1774')?.value||'');
const confirm=String($('catNewPassword2V1774')?.value||'');
if(!current){err.textContent='Введите текущий пароль.';return}
if(next.length<MIN_PASSWORD_LENGTH){err.textContent=`Новый пароль должен содержать минимум ${MIN_PASSWORD_LENGTH} символов.`;return}
if(next!==confirm){err.textContent='Пароли не совпадают.';return}
if(next===current){err.textContent='Новый пароль должен отличаться от текущего.';return}
save.disabled=true;err.textContent='Сохраняю новый пароль…';err.classList.remove('cat-password-gate-v1774-success');
try{
await changePassword(current,next);
err.textContent='Пароль изменён. Сейчас потребуется войти заново.';
err.classList.add('cat-password-gate-v1774-success');
setTimeout(()=>signOutAndReload(),650);
}catch(error){err.textContent=String(error?.message||error||'Не удалось изменить пароль.');save.disabled=false}
};
save.onclick=run;
$('catNewPassword2V1774').addEventListener('keydown',e=>{if(e.key==='Enter')run()});
setTimeout(()=>$('catCurrentPasswordV1774')?.focus(),50);
return true;
}
async function ensureForcedGate(){
if(checking)return;checking=true;
try{
const user=await latestUser();
if(!user){$('cateriumPasswordGateV1774')?.remove();document.body.classList.remove('cat-password-required-v1774');forcedOpen=false;return}
if(mustChange(user)){
if(!$('cateriumPasswordGateV1774')||!forcedOpen)openPasswordModal({forced:true});
}else if(forcedOpen){
$('cateriumPasswordGateV1774')?.remove();document.body.classList.remove('cat-password-required-v1774');forcedOpen=false;
}
}finally{checking=false}
}
function decorateProfile(){
const c=client();if(!c)return;
const card=$('sunCloudV2Card');if(!card)return;
const profile=[...card.querySelectorAll('.sun-cloud-v2-box')].find(x=>x.querySelector('h3')?.textContent.trim()==='Профиль');
if(!profile||profile.querySelector('.cat-profile-password-v1774'))return;
const row=document.createElement('div');row.className='cat-profile-password-v1774';
row.innerHTML='<div><b>Безопасность аккаунта</b><small>Смена пароля для текущего аккаунта</small></div><button type="button" class="outline" id="catProfilePasswordV1774">Сменить пароль</button>';
profile.appendChild(row);row.querySelector('#catProfilePasswordV1774').onclick=()=>openPasswordModal({forced:false});
}
function maintain(){installStyle();ensureForcedGate();decorateProfile()}
const observer=new MutationObserver(()=>{if(document.hidden)return;setTimeout(()=>{decorateProfile();ensureForcedGate()},50)});
if(document.documentElement)observer.observe(document.documentElement,{childList:true,subtree:true});
window.addEventListener('sun:cloud-state-applied',()=>setTimeout(maintain,80));
window.addEventListener('focus',maintain);
document.addEventListener('visibilitychange',()=>{if(!document.hidden)maintain()});
setInterval(()=>{if(!document.hidden)ensureForcedGate()},5000);
window.CateriumAccountSecurityV1774={VERSION,mustChange,openPasswordModal,ensureForcedGate,changePassword,checks:()=>({version:VERSION,forcedOpen,gate:Boolean($('cateriumPasswordGateV1774')),profileButton:Boolean($('catProfilePasswordV1774'))})};
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',maintain,{once:true});else maintain();
})();