105 lines
3.0 KiB
JavaScript
105 lines
3.0 KiB
JavaScript
const AUTH_KEY = "pts_authdata";
|
||
const statusEl = document.getElementById("status");
|
||
const backendInput = document.getElementById("backendUrl");
|
||
|
||
chrome.storage.local.get(["backendUrl"], (data) => {
|
||
if (data.backendUrl) backendInput.value = data.backendUrl;
|
||
});
|
||
|
||
function isPtsUrl(url) {
|
||
return !!url && url.includes("tw-timesheet.supermicro.com");
|
||
}
|
||
|
||
async function getActiveTab() {
|
||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||
return tab;
|
||
}
|
||
|
||
function readAuthViaMessage(tabId) {
|
||
return new Promise((resolve) => {
|
||
chrome.tabs.sendMessage(tabId, { type: "GET_PTS_AUTH" }, (response) => {
|
||
if (chrome.runtime.lastError) {
|
||
resolve({
|
||
ok: false,
|
||
error: chrome.runtime.lastError.message,
|
||
});
|
||
return;
|
||
}
|
||
resolve(response || { ok: false, error: "No response from content script" });
|
||
});
|
||
});
|
||
}
|
||
|
||
async function readAuthViaInjection(tabId) {
|
||
const results = await chrome.scripting.executeScript({
|
||
target: { tabId },
|
||
func: (key) => {
|
||
const raw = localStorage.getItem(key);
|
||
if (!raw) return null;
|
||
try {
|
||
return JSON.parse(raw);
|
||
} catch {
|
||
return null;
|
||
}
|
||
},
|
||
args: [AUTH_KEY],
|
||
});
|
||
const auth = results?.[0]?.result ?? null;
|
||
return { ok: true, auth };
|
||
}
|
||
|
||
async function readAuthFromPage(tab) {
|
||
let result = await readAuthViaMessage(tab.id);
|
||
|
||
if (!result.ok || !result.auth) {
|
||
result = await readAuthViaInjection(tab.id);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
async function syncSession(auth, backendUrl) {
|
||
if (!auth?.accessToken) {
|
||
throw new Error("找不到登入憑證,請確認已登入工時系統");
|
||
}
|
||
const res = await fetch(`${backendUrl}/api/session`, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({
|
||
accessToken: auth.accessToken,
|
||
refreshToken: auth.refreshToken,
|
||
groupCode: auth.groupCode,
|
||
raw: auth,
|
||
}),
|
||
});
|
||
const data = await res.json().catch(() => ({}));
|
||
if (!res.ok) throw new Error(data.detail || res.statusText);
|
||
return data;
|
||
}
|
||
|
||
document.getElementById("syncBtn").addEventListener("click", async () => {
|
||
statusEl.textContent = "同步中...";
|
||
const backendUrl = backendInput.value.trim().replace(/\/$/, "");
|
||
chrome.storage.local.set({ backendUrl });
|
||
|
||
try {
|
||
const tab = await getActiveTab();
|
||
if (!tab?.id || !isPtsUrl(tab.url)) {
|
||
throw new Error("請先切到工時系統分頁(tw-timesheet.supermicro.com)再按同步");
|
||
}
|
||
|
||
const pageAuth = await readAuthFromPage(tab);
|
||
if (!pageAuth.auth) {
|
||
throw new Error(
|
||
pageAuth.error
|
||
? `${pageAuth.error}。請重新整理工時系統頁面後再試`
|
||
: "無法讀取登入憑證,請重新整理工時系統頁面並確認已登入"
|
||
);
|
||
}
|
||
|
||
const result = await syncSession(pageAuth.auth, backendUrl);
|
||
statusEl.textContent = `成功:${result.message || "已同步"}`;
|
||
} catch (err) {
|
||
statusEl.textContent = `失敗:${err.message}`;
|
||
}
|
||
}); |