mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 17:45:42 +00:00
425a2ad89a
Panel shows soft-deleted devices with restore and permanent delete, hard delete works for already-soft-deleted peers, and change-ID conflicts return a clear localized message across all locales.
267 lines
8.3 KiB
JavaScript
267 lines
8.3 KiB
JavaScript
/**
|
|
* BetterDesk Console - Server Backend Abstraction Layer
|
|
*
|
|
* Provides a unified interface for device/peer operations.
|
|
* Always uses BetterDesk Go server (betterdesk mode).
|
|
*
|
|
* Legacy 'rustdesk' (hbbs/hbbr) backend has been removed.
|
|
* All operations delegate to betterdeskApi.js (Go server REST API).
|
|
*
|
|
* The active backend is always 'betterdesk'.
|
|
*/
|
|
|
|
const config = require('../config/config');
|
|
const db = require('./database');
|
|
const betterdeskApi = require('./betterdeskApi');
|
|
|
|
/**
|
|
* Return the active backend name: always 'betterdesk'
|
|
*/
|
|
async function getActiveBackend() {
|
|
return 'betterdesk';
|
|
}
|
|
|
|
/**
|
|
* Change the active backend. Only 'betterdesk' is supported.
|
|
* @param {'betterdesk'} name
|
|
*/
|
|
async function setActiveBackend(name) {
|
|
if (name !== 'betterdesk') {
|
|
throw new Error(`Invalid backend: ${name}. Only 'betterdesk' is supported.`);
|
|
}
|
|
await db.setSetting('server_backend', name);
|
|
}
|
|
|
|
/**
|
|
* Returns true — always BetterDesk (Go server).
|
|
*/
|
|
async function isBetterDesk() {
|
|
return true;
|
|
}
|
|
|
|
// ========================== Health / Stats ===================================
|
|
|
|
async function getHealth() {
|
|
return betterdeskApi.getHealth();
|
|
}
|
|
|
|
async function getStats() {
|
|
const result = await betterdeskApi.getServerStats();
|
|
if (result.success && result.data) {
|
|
// Normalise Go shape → panel shape
|
|
const d = result.data;
|
|
const total = d.peers_total ?? d.total_peers ?? d.total ?? 0;
|
|
const online = d.peers_online ?? d.peers_online_live ?? d.online_peers ?? d.online ?? 0;
|
|
return {
|
|
total,
|
|
online,
|
|
offline: total - online,
|
|
banned: d.peers_banned ?? d.banned_peers ?? d.banned ?? 0,
|
|
withNotes: d.with_notes ?? 0
|
|
};
|
|
}
|
|
// Fallthrough: fetch from local DB as fallback
|
|
return await db.getStats();
|
|
}
|
|
|
|
async function getServerInfo() {
|
|
return betterdeskApi.getServerInfo();
|
|
}
|
|
|
|
// ========================== Devices / Peers ==================================
|
|
|
|
async function getAllDevices(filters = {}) {
|
|
if (await isBetterDesk()) {
|
|
let peers = await betterdeskApi.getAllPeers({
|
|
includeDeleted: !!filters.includeDeleted
|
|
});
|
|
|
|
// Overlay folder_id from auth.db assignments (Go server doesn't track folders)
|
|
try {
|
|
const assignments = await db.getAllFolderAssignments();
|
|
for (const peer of peers) {
|
|
if (assignments[peer.id] !== undefined) {
|
|
const folderId = Number(assignments[peer.id]);
|
|
peer.folder_id = Number.isFinite(folderId) ? folderId : assignments[peer.id];
|
|
}
|
|
}
|
|
} catch (err) {
|
|
// Non-critical: folders simply won't be assigned
|
|
console.error('Failed to overlay folder assignments:', err.message);
|
|
}
|
|
|
|
// Overlay sysinfo from auth.db (Node.js receives richer data from RustDesk Client API)
|
|
try {
|
|
const allSysinfo = await db.getAllPeerSysinfo();
|
|
const sysinfoMap = {};
|
|
for (const si of allSysinfo) {
|
|
sysinfoMap[si.peer_id] = si;
|
|
}
|
|
for (const peer of peers) {
|
|
const si = sysinfoMap[peer.id];
|
|
if (!si) continue;
|
|
if (!peer.hostname && si.hostname) peer.hostname = si.hostname;
|
|
if ((!peer.platform || peer.platform === '-') && si.platform) peer.platform = si.platform;
|
|
if ((!peer.os || peer.os === '-') && si.os_full) peer.os = si.os_full;
|
|
if (!peer.version && si.version) peer.version = si.version;
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to overlay sysinfo:', err.message);
|
|
}
|
|
|
|
// Apply client-side filtering (the Go API may not support all filter params)
|
|
if (filters.search) {
|
|
const s = filters.search.toLowerCase();
|
|
peers = peers.filter(p =>
|
|
(p.id && p.id.toLowerCase().includes(s)) ||
|
|
(p.username && p.username.toLowerCase().includes(s)) ||
|
|
(p.hostname && p.hostname.toLowerCase().includes(s)) ||
|
|
(p.note && p.note.toLowerCase().includes(s))
|
|
);
|
|
}
|
|
if (filters.status === 'online') {
|
|
peers = peers.filter(p => p.online);
|
|
} else if (filters.status === 'offline') {
|
|
peers = peers.filter(p => !p.online && !p.banned);
|
|
} else if (filters.status === 'banned') {
|
|
peers = peers.filter(p => p.banned);
|
|
}
|
|
if (filters.hasNotes) {
|
|
peers = peers.filter(p => p.note && p.note.trim() !== '');
|
|
}
|
|
// Sort
|
|
const col = filters.sortBy || 'last_online';
|
|
const asc = filters.sortOrder === 'asc';
|
|
peers.sort((a, b) => {
|
|
const va = a[col] || '';
|
|
const vb = b[col] || '';
|
|
return asc ? String(va).localeCompare(String(vb)) : String(vb).localeCompare(String(va));
|
|
});
|
|
return peers;
|
|
}
|
|
return await db.getAllDevices(filters);
|
|
}
|
|
|
|
async function getDeviceById(id, options = {}) {
|
|
const peer = options.includeDeleted
|
|
? await betterdeskApi.getPeerIncludingDeleted(id)
|
|
: await betterdeskApi.getPeer(id);
|
|
// Overlay folder_id from auth.db
|
|
if (peer) {
|
|
try {
|
|
const assignments = await db.getAllFolderAssignments();
|
|
if (assignments[peer.id] !== undefined) {
|
|
const folderId = Number(assignments[peer.id]);
|
|
peer.folder_id = Number.isFinite(folderId) ? folderId : assignments[peer.id];
|
|
}
|
|
} catch { /* non-critical */ }
|
|
}
|
|
return peer;
|
|
}
|
|
|
|
async function deleteDevice(id, options = {}) {
|
|
return betterdeskApi.deletePeer(id, options);
|
|
}
|
|
|
|
async function setBanStatus(id, banned, reason = '') {
|
|
return banned
|
|
? betterdeskApi.banPeer(id, reason)
|
|
: betterdeskApi.unbanPeer(id);
|
|
}
|
|
|
|
async function restoreDevice(id) {
|
|
return betterdeskApi.restorePeer(id);
|
|
}
|
|
|
|
async function updateDevice(id, data) {
|
|
// Route through Go API PATCH /api/peers/:id for note/user/display_name fields
|
|
const fields = {};
|
|
if (data.note !== undefined) fields.note = String(data.note);
|
|
if (data.user !== undefined) fields.user = String(data.user);
|
|
if (data.display_name !== undefined) fields.display_name = String(data.display_name);
|
|
|
|
if (Object.keys(fields).length > 0) {
|
|
const result = await betterdeskApi.updatePeer(id, fields);
|
|
if (!result || !result.success) {
|
|
return { changes: 0, error: result?.error || 'Failed to update peer' };
|
|
}
|
|
}
|
|
|
|
// Also update local auth.db as fallback for overlaid fields
|
|
try {
|
|
await db.updateDevice(id, data);
|
|
} catch { /* non-critical: auth.db is secondary storage */ }
|
|
|
|
return { changes: 1 };
|
|
}
|
|
|
|
async function changePeerId(oldId, newId) {
|
|
return betterdeskApi.changePeerId(oldId, newId);
|
|
}
|
|
|
|
// ========================== Online Status Sync ===============================
|
|
|
|
async function syncOnlineStatus() {
|
|
// BetterDesk Go server owns the peer map — no sync needed.
|
|
return betterdeskApi.syncOnlineStatus();
|
|
}
|
|
|
|
// ========================== BetterDesk Features ==============================
|
|
|
|
async function getStatusSummary() {
|
|
return betterdeskApi.getStatusSummary();
|
|
}
|
|
|
|
async function getBlocklist() {
|
|
return betterdeskApi.getBlocklist();
|
|
}
|
|
|
|
async function addBlocklistEntry(entry) {
|
|
return betterdeskApi.addBlocklistEntry(entry);
|
|
}
|
|
|
|
async function removeBlocklistEntry(entry) {
|
|
return betterdeskApi.removeBlocklistEntry(entry);
|
|
}
|
|
|
|
async function setPeerTags(id, tags) {
|
|
return betterdeskApi.setPeerTags(id, tags);
|
|
}
|
|
|
|
async function getPeersByTag(tag) {
|
|
return betterdeskApi.getPeersByTag(tag);
|
|
}
|
|
|
|
async function getAuditEvents(limit) {
|
|
return betterdeskApi.getAuditEvents(limit);
|
|
}
|
|
|
|
module.exports = {
|
|
// Backend management
|
|
getActiveBackend,
|
|
setActiveBackend,
|
|
isBetterDesk,
|
|
// Health / Stats
|
|
getHealth,
|
|
getStats,
|
|
getServerInfo,
|
|
// Devices
|
|
getAllDevices,
|
|
getDeviceById,
|
|
deleteDevice,
|
|
restoreDevice,
|
|
setBanStatus,
|
|
updateDevice,
|
|
changePeerId,
|
|
// Status sync
|
|
syncOnlineStatus,
|
|
// BetterDesk-only
|
|
getStatusSummary,
|
|
getBlocklist,
|
|
addBlocklistEntry,
|
|
removeBlocklistEntry,
|
|
setPeerTags,
|
|
getPeersByTag,
|
|
getAuditEvents
|
|
};
|