caterium-app/public/core/account-security-v1771.js
2026-09-08 16:35:51 +03:00

82 lines
9.0 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.CateriumAccountSecurityV1771)return;
const VERSION='17.7.1';
const RELEASE='20260908-v17-7-1-password-security';
const $=id=>document.getElementById(id);
const cloud=()=>window.SunCloudV2||null;
const client=()=>cloud()?.getClient?.()||null;
const session=()=>cloud()?.getSession?.()||null;
const esc=v=>window.SunSafe?.escapeHTML?window.SunSafe.escapeHTML(String(v??'')):String(v??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
const mustChange=user=>Boolean(user?.app_metadata?.must_change_password||user?.user_metadata?.must_change_password);
let forcedOpen=false,checking=false;
function installStyle(){
if($('cateriumAccountSecurityV1771Style'))return;
const st=document.createElement('style');st.id='cateriumAccountSecurityV1771Style';st.textContent=`
.cat-password-gate-v1771{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-v1771-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-v1771-card h2{margin:0 0 6px}.cat-password-gate-v1771-card p{color:#6d746f;line-height:1.45}
.cat-password-gate-v1771-card label{display:block;margin-top:12px;font-size:12px;font-weight:800;color:#343a36}.cat-password-gate-v1771-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-v1771-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.cat-password-gate-v1771-actions button{border-radius:10px;padding:9px 12px;font-weight:850}.cat-password-gate-v1771-actions .primary{background:#1d2a22;color:#fff;border:1px solid #1d2a22}.cat-password-gate-v1771-actions .outline{background:#fff;border:1px solid #d5dad6}
.cat-password-gate-v1771-error{min-height:20px;margin-top:10px;color:#9f2d2d;font-size:12px}.cat-password-gate-v1771-success{color:#1e6a3d}
.cat-profile-password-v1771{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-v1771 small{display:block;color:#7a807c;margin-top:3px}
body.cat-password-required-v1771{overflow:hidden!important}
`;document.head.appendChild(st);
}
async function signOut(){try{await cloud()?.signOut?.()}catch(_){try{await client()?.auth.signOut()}catch(__){}}}
async function updatePassword({currentPassword='',newPassword,clearForced=false}){
const c=client(),ss=session();if(!c||!ss?.user)throw new Error('Сессия пользователя недоступна.');
const email=String(ss.user.email||'').trim();
if(currentPassword){const verify=await c.auth.signInWithPassword({email,password:currentPassword});if(verify.error)throw new Error('Текущий пароль введён неверно.');}
const metadata={...(ss.user.user_metadata||{})};if(clearForced)metadata.must_change_password=false;
const result=await c.auth.updateUser({password:newPassword,data:metadata});if(result.error)throw result.error;
try{await c.auth.refreshSession()}catch(_){}
return result.data?.user||null;
}
function openPasswordModal({forced=false}={}){
installStyle();$('cateriumPasswordGateV1771')?.remove();
const ss=session(),user=ss?.user;if(!user)return false;
forcedOpen=forced;
const host=document.createElement('div');host.id='cateriumPasswordGateV1771';host.className='cat-password-gate-v1771';
host.innerHTML=`<div class="cat-password-gate-v1771-card"><h2>${forced?'Создайте постоянный пароль':'Сменить пароль'}</h2><p>${forced?'Вы вошли по временному паролю. Для продолжения работы задайте свой новый пароль. Закрыть это окно без смены пароля нельзя.':'Пароль меняется только для вашего аккаунта Caterium.'}</p>${forced?'':`<label>Текущий пароль<input id="catCurrentPasswordV1771" type="password" autocomplete="current-password"></label>`}<label>Новый пароль<input id="catNewPasswordV1771" type="password" autocomplete="new-password"></label><label>Повторите новый пароль<input id="catNewPassword2V1771" type="password" autocomplete="new-password"></label><div id="catPasswordErrorV1771" class="cat-password-gate-v1771-error"></div><div class="cat-password-gate-v1771-actions">${forced?'<button class="outline" id="catPasswordSignOutV1771" type="button">Выйти</button>':'<button class="outline" id="catPasswordCancelV1771" type="button">Отмена</button>'}<button class="primary" id="catPasswordSaveV1771" type="button">Сохранить пароль</button></div></div>`;
document.body.appendChild(host);if(forced)document.body.classList.add('cat-password-required-v1771');
if(!forced)$('catPasswordCancelV1771').onclick=()=>host.remove();else $('catPasswordSignOutV1771').onclick=()=>signOut();
const save=$('catPasswordSaveV1771'),err=$('catPasswordErrorV1771');
const run=async()=>{
const p1=String($('catNewPasswordV1771')?.value||''),p2=String($('catNewPassword2V1771')?.value||''),current=String($('catCurrentPasswordV1771')?.value||'');
if(!forced&&!current){err.textContent='Введите текущий пароль.';return}if(p1.length<8){err.textContent='Новый пароль должен содержать минимум 8 символов.';return}if(p1!==p2){err.textContent='Пароли не совпадают.';return}if(!forced&&p1===current){err.textContent='Новый пароль должен отличаться от текущего.';return}
save.disabled=true;err.textContent='Сохраняю новый пароль…';err.classList.remove('cat-password-gate-v1771-success');
try{await updatePassword({currentPassword:forced?'':current,newPassword:p1,clearForced:forced});err.textContent='Пароль успешно изменён.';err.classList.add('cat-password-gate-v1771-success');document.body.classList.remove('cat-password-required-v1771');forcedOpen=false;setTimeout(()=>{host.remove();ensureForcedGate();decorateProfile()},450)}catch(e){err.textContent=String(e?.message||e||'Не удалось изменить пароль.');save.disabled=false}
};
save.onclick=run;$('catNewPassword2V1771').addEventListener('keydown',e=>{if(e.key==='Enter')run()});setTimeout(()=>$('catNewPasswordV1771')?.focus(),50);return true;
}
async function latestUser(){
const c=client();if(!c)return session()?.user||null;try{const r=await c.auth.getUser();return r.data?.user||session()?.user||null}catch(_){return session()?.user||null}
}
async function ensureForcedGate(){
if(checking)return;checking=true;try{const user=await latestUser();if(!user){$('cateriumPasswordGateV1771')?.remove();document.body.classList.remove('cat-password-required-v1771');forcedOpen=false;return}if(mustChange(user)){if(!$('cateriumPasswordGateV1771')||!forcedOpen)openPasswordModal({forced:true})}else if(forcedOpen){$('cateriumPasswordGateV1771')?.remove();document.body.classList.remove('cat-password-required-v1771');forcedOpen=false}}finally{checking=false}
}
function decorateProfile(){
const ss=session();if(!ss?.user)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-v1771'))return;
const row=document.createElement('div');row.className='cat-profile-password-v1771';row.innerHTML=`<div><b>Безопасность аккаунта</b><small>Сменить пароль для ${esc(ss.user.email||'этого аккаунта')}</small></div><button type="button" class="outline" id="catProfilePasswordV1771">Сменить пароль</button>`;profile.appendChild(row);row.querySelector('#catProfilePasswordV1771').onclick=()=>openPasswordModal({forced:false});
}
function maintain(){installStyle();ensureForcedGate();decorateProfile()}
const observer=new MutationObserver(()=>{if(document.hidden)return;setTimeout(()=>{decorateProfile();ensureForcedGate()},40)});
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.CateriumAccountSecurityV1771={VERSION,RELEASE,mustChange,openPasswordModal,ensureForcedGate,decorateProfile,checks:()=>({version:VERSION,forcedOpen,gate:Boolean($('cateriumPasswordGateV1771')),profileButton:Boolean($('catProfilePasswordV1771'))})};
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',maintain,{once:true});else maintain();
})();