fix(accounts): login with account give device name

This commit is contained in:
2026-06-25 19:32:53 +09:30
parent 969c3bbdd5
commit e400890eee
3 changed files with 93 additions and 11 deletions
+18 -9
View File
@@ -11,6 +11,7 @@ import {
requestCloudSettingsDebouncedUpload,
runCloudSettingsPoll,
} from "./background/cloudSettingsAutoSync";
import { getBsplusDeviceName } from "@/seqta/utils/bsplusDeviceName";
/**
* Session-only dev-mode override of the content API base.
@@ -178,25 +179,33 @@ function handleCloudReserveClient(request: any, sendResponse: MessageSender): bo
}
function handleCloudLogin(request: any, sendResponse: MessageSender): boolean {
const { client_id, redirect_uri, login, password } = request;
const { client_id, redirect_uri, login, password, device_name } = request;
if (!client_id || !redirect_uri || !login || !password) {
sendResponse({ error: "Missing client_id, redirect_uri, login, or password" });
return false;
}
fetch("https://accounts.betterseqta.org/api/bsplus/login", {
void (async () => {
const loginBody: Record<string, string> = {
client_id,
redirect_uri,
login,
password,
device_name: device_name ?? await getBsplusDeviceName(),
};
try {
const r = await fetch("https://accounts.betterseqta.org/api/bsplus/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ client_id, redirect_uri, login, password }),
})
.then(async (r) => {
body: JSON.stringify(loginBody),
});
const data = await parseJsonResponse(r);
if (!r.ok) sendResponse({ error: data?.error ?? "Login failed" });
else sendResponse(data);
})
.catch((err) => {
} catch (err) {
console.error("[Background] cloudLogin error:", err);
sendResponse({ error: err?.message ?? "Network error" });
});
sendResponse({ error: (err as Error)?.message ?? "Network error" });
}
})();
return true;
}
+3
View File
@@ -1,4 +1,5 @@
import browser from "webextension-polyfill";
import { getBsplusDeviceName } from "@/seqta/utils/bsplusDeviceName";
import { clearCloudPfpCache } from "@/seqta/utils/cloudPfpCache";
import { clearLastUploadedSnapshot } from "@/seqta/utils/cloudSettingsSync";
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
@@ -167,12 +168,14 @@ class CloudAuthService {
): Promise<{ success: boolean; error?: string }> {
try {
const clientId = await this.getClientId();
const device_name = await getBsplusDeviceName();
const result = (await browser.runtime.sendMessage({
type: "cloudLogin",
client_id: clientId,
redirect_uri: REDIRECT_URI,
login: login.trim(),
password,
device_name,
})) as {
access_token?: string;
refresh_token?: string;
+70
View File
@@ -0,0 +1,70 @@
import browser from "webextension-polyfill";
function detectOsNameFromNavigator(): string {
const ua = navigator.userAgent;
const platform = navigator.platform ?? "";
const userAgentData = (navigator as Navigator & { userAgentData?: { platform?: string } })
.userAgentData;
if (userAgentData?.platform) {
const mapped: Record<string, string> = {
Windows: "Windows",
macOS: "macOS",
Linux: "Linux",
Android: "Android",
iOS: "iOS",
"Chrome OS": "ChromeOS",
};
return mapped[userAgentData.platform] ?? userAgentData.platform;
}
if (/Win/i.test(platform) || ua.includes("Windows")) return "Windows";
if (/Mac/i.test(platform) || ua.includes("Mac OS X") || ua.includes("Macintosh")) return "macOS";
if (/Linux/i.test(platform) || ua.includes("Linux")) return "Linux";
if (/Android/i.test(ua)) return "Android";
if (/iPhone|iPad|iPod/i.test(ua)) return "iOS";
if (/CrOS/i.test(ua)) return "ChromeOS";
return platform || "Unknown OS";
}
function detectBrowserNameFromUserAgent(ua: string): string {
if (ua.includes("Edg/")) return "Edge";
if (ua.includes("OPR/") || ua.includes("Opera")) return "Opera";
if (ua.includes("Firefox/")) return "Firefox";
if (ua.includes("Chrome/") && !ua.includes("Edg/")) return "Chrome";
if (ua.includes("Safari/") && !ua.includes("Chrome/")) return "Safari";
return "Browser";
}
async function detectBrowserName(): Promise<string> {
try {
const runtime = browser.runtime as typeof browser.runtime & {
getBrowserInfo?: () => Promise<{ name?: string }>;
};
if (typeof runtime.getBrowserInfo === "function") {
const info = await runtime.getBrowserInfo();
if (info.name === "Firefox") return "Firefox";
if (info.name) return info.name;
}
} catch {
// Fall back to user-agent parsing below.
}
if (typeof navigator !== "undefined") {
return detectBrowserNameFromUserAgent(navigator.userAgent);
}
return "Browser";
}
/**
* Friendly device label for BetterSEQTA+ cloud login (`device_name` on POST /api/bsplus/login).
* Format: "Chrome on Windows", "Firefox on macOS", etc.
*/
export async function getBsplusDeviceName(): Promise<string> {
const browserName = await detectBrowserName();
const osName =
typeof navigator !== "undefined" ? detectOsNameFromNavigator() : "Unknown OS";
return `${browserName} on ${osName}`;
}