76 lines
2.3 KiB
JavaScript
76 lines
2.3 KiB
JavaScript
/** OAuth 提供商列表与回调结果适配;跳转地址必须经过站内/HTTP(S)规则校验。 */
|
||
import { o as backend_menu_o } from "~/lib/backend-menu.js";
|
||
// 仅接受合法提供商标识,标准化图片与绑定状态;不可信的任意协议地址不会直接使用。
|
||
function t(t) {
|
||
return Array.isArray(t)
|
||
? t.flatMap((t) => {
|
||
if (
|
||
!t ||
|
||
typeof t != `object` ||
|
||
typeof t.name != `string` ||
|
||
!/^[a-z][a-z0-9_]*$/i.test(t.name)
|
||
)
|
||
return [];
|
||
let n = typeof t.img == `string` ? t.img : ``,
|
||
r =
|
||
// eslint-disable-next-line no-control-regex -- 安全边界:拒绝登录图标路径中的控制字符。
|
||
/^\/(?!\/)/.test(n) && !/[\\\u0000-\u0020]/.test(n)
|
||
? n
|
||
: backend_menu_o(n);
|
||
return [
|
||
{
|
||
name: t.name,
|
||
title: typeof t.title == `string` ? t.title : t.name,
|
||
image: r,
|
||
linked: t.link === !0 || t.link === 1 || t.link === `1`,
|
||
},
|
||
];
|
||
})
|
||
: [];
|
||
}
|
||
function n(t, n) {
|
||
return typeof t == `string`
|
||
? // eslint-disable-next-line no-control-regex -- 安全边界:拒绝登录跳转地址中的控制字符。
|
||
/^\/(?!\/)/.test(t) && !/[\\\u0000-\u0020]/.test(t)
|
||
? new URL(t, n).href
|
||
: backend_menu_o(t)
|
||
: ``;
|
||
}
|
||
/**
|
||
* 将轮询结果分为 login、bind、expired;t 为前端 origin,r 可为后端 origin。
|
||
* 旧 oauth.htm 仅在可信 origin 上迁移为前端 /oauth/bind,不放行任意外站回跳。
|
||
*/
|
||
function r(e, t, r = t) {
|
||
if (!e || typeof e != `object` || Array.isArray(e))
|
||
return {
|
||
kind: `expired`,
|
||
};
|
||
let i = e;
|
||
if (typeof i.jwt == `string` && i.jwt.trim())
|
||
return {
|
||
kind: `login`,
|
||
jwt: i.jwt.trim(),
|
||
};
|
||
let a = n(i.url, t);
|
||
if (a) {
|
||
let e = new URL(a);
|
||
if (e.pathname === `/oauth.htm` && [t, r].includes(e.origin))
|
||
return (
|
||
(e.pathname = `/oauth/bind`),
|
||
{
|
||
kind: `bind`,
|
||
url: t + e.pathname + e.search + e.hash,
|
||
}
|
||
);
|
||
if (e.origin === t && e.pathname === `/oauth/bind`)
|
||
return {
|
||
kind: `bind`,
|
||
url: a,
|
||
};
|
||
}
|
||
return {
|
||
kind: `expired`,
|
||
};
|
||
}
|
||
export { r as n, n as r, t };
|