refactor: modularize backend security and observability

This commit is contained in:
237899745
2026-07-27 13:06:54 +08:00
parent f90311e68c
commit dce1e3622a
25 changed files with 1633 additions and 849 deletions

68
backend/utils/device.js Normal file
View File

@@ -0,0 +1,68 @@
function normalizeClientIp(rawIp) {
const ip = String(rawIp || '').trim();
if (!ip) return '';
if (ip.startsWith('::ffff:')) return ip.slice(7);
return ip === '::1' ? '127.0.0.1' : ip;
}
function detectDeviceTypeFromUserAgent(userAgent = '') {
const mobilePattern = /(Mobile|Android|iPhone|iPad|iPod|Windows Phone|HarmonyOS|Mobi)/i;
return mobilePattern.test(String(userAgent || '')) ? 'mobile' : 'desktop';
}
function inferPlatformFromUserAgent(userAgent = '') {
const value = String(userAgent || '');
if (!value) return '未知平台';
if (/windows/i.test(value)) return 'Windows';
if (/macintosh|mac os x/i.test(value)) return 'macOS';
if (/android/i.test(value)) return 'Android';
if (/iphone|ipad|ios/i.test(value)) return 'iOS';
if (/linux/i.test(value)) return 'Linux';
return '未知平台';
}
function normalizeClientType(value = '') {
const normalized = String(value || '').trim().toLowerCase();
return ['web', 'desktop', 'mobile', 'api'].includes(normalized) ? normalized : '';
}
function resolveClientType(clientType, userAgent = '') {
const normalized = normalizeClientType(clientType);
if (normalized) return normalized;
const userAgentValue = String(userAgent || '').toLowerCase();
if (
userAgentValue.includes('tauri')
|| userAgentValue.includes('electron')
|| userAgentValue.includes('wanwan-cloud-desktop')
|| userAgentValue.includes('玩玩云')
) {
return 'desktop';
}
return detectDeviceTypeFromUserAgent(userAgentValue) === 'mobile' ? 'mobile' : 'web';
}
function sanitizeDeviceText(value, maxLength = 120) {
return typeof value === 'string' ? value.trim().slice(0, maxLength) : '';
}
function buildDeviceName({ clientType, deviceName, platform }) {
const preferred = sanitizeDeviceText(deviceName, 120);
if (preferred) return preferred;
const platformText = sanitizeDeviceText(platform, 80) || '未知平台';
if (clientType === 'desktop') return `桌面客户端 · ${platformText}`;
if (clientType === 'mobile') return `移动端浏览器 · ${platformText}`;
if (clientType === 'api') return `API 客户端 · ${platformText}`;
return `网页端浏览器 · ${platformText}`;
}
module.exports = {
buildDeviceName,
detectDeviceTypeFromUserAgent,
inferPlatformFromUserAgent,
normalizeClientIp,
normalizeClientType,
resolveClientType,
sanitizeDeviceText
};