fix(ops-auth): 매직 링크 URL을 URL API로 조립해 본문 문장과 분리

- buildMagicVerifyUrl(BASE_URL, token) 추가

Made-with: Cursor
This commit is contained in:
2026-04-03 22:54:03 +09:00
parent 1baf13abf6
commit e0e8d8d662

View File

@@ -107,6 +107,18 @@ function getBaseUrl() {
return `http://localhost:${port}`;
}
/**
* 매직 링크 절대 URL — BASE_URL + `/auth/verify/:token` 만 조합 (본문 문장·조사와 문자열 결합 금지)
*/
function buildMagicVerifyUrl(baseUrl, token) {
const base = String(baseUrl || "").trim().replace(/\/$/, "");
const t = String(token || "").trim();
if (!base) throw new Error("BASE_URL이 비어 있습니다.");
if (!t) throw new Error("인증 토큰이 비어 있습니다.");
const path = `/auth/verify/${encodeURIComponent(t)}`;
return new URL(path, `${base}/`).href;
}
function sanitizeReturnTo(v) {
const s = (v || "").toString().trim();
if (!s.startsWith("/") || s.startsWith("//")) return "/learning";
@@ -402,7 +414,7 @@ module.exports = function createOpsAuth(DATA_DIR, hooks = {}) {
});
saveMagicLinks(MAGIC_LINK_PATH, list);
/** 경로에 토큰만 두기 (쿼리 `?token=`는 일부 웹메일/Outlook에서 href가 잘림) */
const linkUrl = `${BASE_URL}/auth/verify/${encodeURIComponent(token)}`;
const linkUrl = buildMagicVerifyUrl(BASE_URL, token);
await sendMagicLinkEmail(email, linkUrl);
if (typeof hooks.onMagicLinkRequested === "function") {
try {