fix: guard profile auth and logout

This commit is contained in:
rain
2026-07-11 09:32:06 +08:00
parent 8b896f4ba3
commit f60cc67749
5 changed files with 82 additions and 4 deletions
+2 -2
View File
@@ -78,7 +78,7 @@
><span>帮助与服务</span><b>帮助、反馈、推广</b></a ><span>帮助与服务</span><b>帮助、反馈、推广</b></a
> >
<a class="logout-link" href="#logout" data-logout-open <a class="logout-link" href="#logout" data-logout-open
><span>退出登录</span><b>返回登录</b></a ><span>退出登录</span><b>返回</b></a
> >
</div> </div>
<div class="side-card todo-card tilt-card" id="messages"> <div class="side-card todo-card tilt-card" id="messages">
@@ -355,7 +355,7 @@
<button class="btn ghost magnetic" type="button" data-logout-close> <button class="btn ghost magnetic" type="button" data-logout-close>
取消 取消
</button> </button>
<a class="btn primary magnetic" href="login.html">确认退出</a> <a class="btn primary magnetic" href="index.html" data-logout-confirm>确认退出</a>
</div> </div>
</div> </div>
</div> </div>
+22 -2
View File
@@ -55,9 +55,23 @@
}); });
} }
function performLogout(targetUrl) {
var api = window.GenealogyApi && window.GenealogyApi.defaultClient;
var redirect = function () {
window.location.href = targetUrl || 'index.html';
};
if (!api || !api.logout) {
redirect();
return;
}
api.logout().catch(function () {}).then(redirect);
}
function bindLogout() { function bindLogout() {
$(document).on('click', '[data-logout-open]', function (event) { $(document).on('click', '[data-logout-open]', function (event) {
var targetUrl = $(this).attr('data-logout-url') || 'login.html'; var targetUrl = $(this).attr('data-logout-url') || 'index.html';
event.preventDefault(); event.preventDefault();
if (!layerApi) { if (!layerApi) {
@@ -70,11 +84,17 @@
content: '确认退出当前账号吗?退出后需要重新登录才能继续管理家谱。', content: '确认退出当前账号吗?退出后需要重新登录才能继续管理家谱。',
confirmText: '确认退出', confirmText: '确认退出',
onConfirm: function () { onConfirm: function () {
window.location.href = targetUrl; performLogout(targetUrl);
} }
}); });
}); });
$(document).on('click', '[data-logout-confirm]', function (event) {
event.preventDefault();
closeLegacyLogout();
performLogout($(this).attr('href') || 'index.html');
});
$(document).on('click', '[data-logout-close]', function () { $(document).on('click', '[data-logout-close]', function () {
closeLegacyLogout(); closeLegacyLogout();
}); });
+27
View File
@@ -92,6 +92,28 @@
return root.GenealogyApi && root.GenealogyApi.defaultClient; return root.GenealogyApi && root.GenealogyApi.defaultClient;
} }
function shouldRedirectToHome(api, error) {
var status = error && (error.status || error.code);
return !api || !api.getToken || !api.getToken() || Number(status) === 401;
}
function redirectToHome() {
if (!root.location) return;
if (typeof root.location.replace === 'function') {
root.location.replace('index.html');
return;
}
root.location.href = 'index.html';
}
function redirectUnauthorized(api, error) {
if (!shouldRedirectToHome(api, error)) return false;
if (api && api.clearToken) api.clearToken();
redirectToHome();
return true;
}
function query(selector, rootNode) { function query(selector, rootNode) {
if (!documentRef) return null; if (!documentRef) return null;
return (rootNode || documentRef).querySelector(selector); return (rootNode || documentRef).querySelector(selector);
@@ -167,12 +189,14 @@
var profile; var profile;
if (!api || !documentRef || !documentRef.querySelector('[data-profile-page]')) return; if (!api || !documentRef || !documentRef.querySelector('[data-profile-page]')) return;
if (redirectUnauthorized(api)) return;
try { try {
profile = await api.currentProfile(); profile = await api.currentProfile();
renderProfile(buildProfileView(profile)); renderProfile(buildProfileView(profile));
fillProfileForm(profile); fillProfileForm(profile);
} catch (error) { } catch (error) {
if (redirectUnauthorized(api, error)) return;
showMessage(error.message || '个人资料加载失败'); showMessage(error.message || '个人资料加载失败');
} }
} }
@@ -181,6 +205,7 @@
var api = getApi(); var api = getApi();
if (!api || !form) return; if (!api || !form) return;
if (redirectUnauthorized(api)) return;
try { try {
setSubmitting(form, true); setSubmitting(form, true);
@@ -190,6 +215,7 @@
showMessage('个人资料已保存'); showMessage('个人资料已保存');
await loadProfile(); await loadProfile();
} catch (error) { } catch (error) {
if (redirectUnauthorized(api, error)) return;
setStatus(form, '保存失败'); setStatus(form, '保存失败');
showMessage(error.message || '个人资料保存失败'); showMessage(error.message || '个人资料保存失败');
} finally { } finally {
@@ -218,6 +244,7 @@
getAvatarText: getAvatarText, getAvatarText: getAvatarText,
buildProfileView: buildProfileView, buildProfileView: buildProfileView,
buildProfileUpdateBody: buildProfileUpdateBody, buildProfileUpdateBody: buildProfileUpdateBody,
shouldRedirectToHome: shouldRedirectToHome,
init: init init: init
}; };
}); });
+15
View File
@@ -0,0 +1,15 @@
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const profileHtml = fs.readFileSync(path.join(__dirname, '..', 'profile.html'), 'utf8');
const profileCommon = fs.readFileSync(path.join(__dirname, '..', 'public', 'js', 'profile-common.js'), 'utf8');
assert.match(profileHtml, /data-logout-confirm/);
assert.match(profileHtml, /<a class="btn primary magnetic" href="index\.html" data-logout-confirm>/);
assert.match(profileHtml, /<span>退出登录<\/span><b>返回首页<\/b>/);
assert.match(profileCommon, /function performLogout\(targetUrl\)/);
assert.match(profileCommon, /api\.logout\(\)/);
assert.match(profileCommon, /targetUrl \|\| 'index\.html'/);
console.log('profile logout structure tests passed');
+16
View File
@@ -61,6 +61,22 @@ function run() {
districtCode: undefined districtCode: undefined
}); });
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => ''
}), true);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}), false);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}, { status: 401 }), true);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}, { code: 401 }), true);
assert.strictEqual(ProfilePages.shouldRedirectToHome({
getToken: () => 'token-x'
}, { status: 500 }), false);
console.log('profile-pages tests passed'); console.log('profile-pages tests passed');
} }