refactor: modularize backend security and observability
This commit is contained in:
68
backend/utils/device.js
Normal file
68
backend/utils/device.js
Normal 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
|
||||
};
|
||||
Reference in New Issue
Block a user