/* Browser identity is a random credential, never a fingerprint or a report. */ window.AccountClient = (function () { 'use strict'; var key = 'juzi.identity.v1', kindKey = 'juzi.auth.kind.v1', user = null; function read(name) { try { return localStorage.getItem(name || key); } catch (_) { return null; } } function rememberKind() { try { if (user) localStorage.setItem(kindKey, user.kind); } catch (_) {} } function request(url, data) { var controller = new AbortController(); // Bound only authentication waits. Full report snapshots contain photos and // must retain their existing download budget on a slow mobile connection. var timer = url.indexOf('api/auth/') === 0 ? setTimeout(function () { controller.abort(); }, 12000) : null; return fetch(url, { credentials: 'same-origin', method: data ? 'POST' : 'GET', signal: controller.signal, headers: data ? { 'Content-Type': 'application/json' } : {}, body: data ? JSON.stringify(data) : undefined }).then(function (r) { return r.json().then(function (v) { if (!r.ok || !v.ok) throw new Error(v.message || '请求失败'); return v; }); }).catch(function (error) { if (error.name === 'AbortError') throw new Error('网络响应超时,请检查网络后重试'); throw error; }).finally(function () { clearTimeout(timer); }); } function browser(consent) { return request('api/auth/browser', { consent: consent, token: read() }).then(function (v) { try { localStorage.setItem(key, v.token); } catch (_) { /* session cookie still works */ } user = v.user; rememberKind(); return v; }); } function init(options) { return request('api/auth/session').then(function (v) { user = v.user; rememberKind(); // A missing WeChat session is not permission to switch to a browser account. // OAuth returns must also stay explicit when its cookie was not retained. if (!user && !(options && options.restoreBrowser === false) && read(kindKey) !== 'wechat' && read()) return browser(true).catch(function (e) { // Do not replace an existing credential on a transient server/network error. if (/身份已失效/.test(e.message)) { try { localStorage.removeItem(key); } catch (_) {} } throw e; }); return v; }); } return { request: request, init: init, browser: browser, user: function () { return user; } }; })();