Commit Graph

86 Commits

Author SHA1 Message Date
UNITRONIX 207a7467d0 fix(update): preserve operator config and passwords on upgrade (#158)
Merge .env keys instead of replacing files, patch systemd/NSSM in place,
block panel updates when the server cannot be rebuilt, and stop routine
updates from syncing admin passwords from .env into auth.db/PostgreSQL.
2026-06-04 00:13:12 +02:00
UNITRONIX f409ee09d7 feat(help): add API endpoints for managing help requests
Implement new functions to list, acknowledge, and resolve help requests via the API. The listHelpRequests function supports filtering by status and device ID, while acknowledgeHelpRequest and resolveHelpRequest handle acknowledgment and resolution of specific requests. These additions enhance the help request management capabilities in the application.
2026-06-02 03:03:10 +02:00
UNITRONIX 60d0227445 fix(settings): show Advanced tab file list and expand config catalog
Utils.api already unwraps API data, so the file list was always empty.
Add fixed paths for session secret, audit log, build.env, and Docker files.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 02:59:43 +02:00
UNITRONIX 5b361c7579 feat(settings): add Advanced tab for allowlisted config file editing
Let server.config admins edit .env, blocklist, and systemd units from the
panel with backups on save and service restart via the existing updater.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 02:55:38 +02:00
UNITRONIX b703db5e5f fix(auth): sync LDAP/OIDC provider and role from Go to panel (#148)
Node now persists auth_provider on SSO provisioning and re-syncs role/provider after Go login success, including SQLite auth.db backfill. Go login returns auth_provider; LDAP group mapping accepts CN keys and newlines. Default agent build cache under dataDir to avoid EACCES.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 02:42:25 +02:00
Knienartowicz 787caf8958 fix(auth): bind accounts to auth provider local/LDAP/OIDC (#148)
Add auth_provider attribute (local/ldap/oidc) to User model across SQLite and PostgreSQL with automatic migration (existing accounts default to local). Rewrite login to be provider-bound: LDAP-backed accounts never fall through to local password verification, OIDC accounts reject password login, and LDAP/OIDC provisioning stores an unusable random local password instead of the provider password. LDAP/OIDC accounts always re-apply provider role mapping on every login so a matching local account can no longer override AD-mapped permissions. Guard handleUpdateUser against setting a local password on non-local accounts. Propagate auth_provider through the Node.js sync layer and panel API, add a Provider column with badges in the users table, hide local password reset for provider-managed accounts, and add EN/PL i18n keys.

This commit was made possible thanks to Insolve.
2026-06-01 09:06:53 +02:00
UNITRONIX 684bd06c6e feat(backup): full disaster-recovery backup archive
Redesign the console backup into a complete .tar.gz disaster-recovery bundle that can be restored on a fresh machine to bring the entire server back online. Adds zero-dependency tar.gz writer/reader (backupArchive.js), logical dumpAllTables/importAllTables for SQLite and PostgreSQL, and packs the console database, auth.db, .env, .session_secret, branding uploads, and Go server identity (Ed25519 keys, .api_key, db_v2.sqlite3) plus a recovery README. Restore auto-detects archive vs legacy JSON snapshot, supports per-component selection (database/uploads/secrets/.env/Go DB) with restart-required signaling, and warns that the archive contains secrets. EN/PL/ZH i18n added.

This commit was made possible thanks to Insolve.
2026-06-01 05:21:07 +02:00
UNITRONIX 4d2ffeefc1 feat(branding): full white-label expansion of branding tab
Add console wallpaper, login page branding (title/subtitle/background/footer), global agent download page branding, footer/copyright with 'Powered by BetterDesk' toggle, and custom CSS injection. Includes background image upload route (8MB), sanitization for colors/gradients/CSS, dynamic theme CSS for app and login pages, sidebar attribution, and EN/PL/ZH i18n keys.

This commit was made possible thanks to Insolve.
2026-06-01 05:00:12 +02:00
UNITRONIX f4ecb7bfe5 fix(auth): delegate unknown-user logins to Go LDAP/OIDC (#148)
Issue #148 reporter @Kreol13 confirmed LDAP test connection works but
actual login fails with 'user not found in database'. Root cause: the
Node.js console only delegates unknown-user logins to the Go server when
BETTERDESK_AUTH_AUTOCREATE=true is set explicitly (security audit fix
H-01). When LDAP/OIDC is configured via the UI, that env var is not set,
so LDAP/OIDC users who don't have a local account are rejected before
Go gets a chance to authenticate them.

Go server:
- New public endpoint GET /api/auth/sso/status returning
  {ldap_enabled, oidc_enabled, any_enabled}.
- Restored missing POST /api/auth/oidc/exchange route registration and
  authMiddleware whitelist (regression from earlier OIDC hardening).

Node.js console:
- authService.getGoSSOStatus() — cached 60s lookup of Go SSO state.
- authenticate() now auto-provisions LDAP/OIDC-authenticated users when
  any SSO provider is enabled on Go, in addition to the existing
  BETTERDESK_AUTH_AUTOCREATE opt-in. Default role drops from 'admin' to
  'viewer' for safer first-login provisioning when Go does not return
  an explicit role mapping. Logs name which provider triggered
  provisioning for audit clarity.

The H-01 concern (compromised Go server auto-provisioning admins) is
mitigated because enabling LDAP/OIDC requires an admin with the
server.config permission to explicitly opt in via the Authentication
settings tab.

This commit was made possible thanks to Insolve.
2026-06-01 04:38:04 +02:00
UNITRONIX 03ca839d76 fix(update): force full Go source resync before build (#158)
The in-app updater computed changed files via the GitHub compare API, whose 'files' array is capped at 300 entries. Large updates were truncated, so changed Go callee files (codec/ws.go, peer/map.go, auth/ldap.go, auth/oidc.go) were never downloaded, leaving inconsistent on-disk source that failed 'go build' with 'undefined' errors. ensureServerSource() also short-circuited whenever go.mod existed, so the full-resync safety net never ran.

Fixes: ensureServerSource() gains a force option that performs a full, consistent source resync (git clone / tree API) regardless of go.mod presence; called with force from applyUpdate's server block and from rebuildServerBinary (the 'Rebuild server binary' button).

Installer parity (same #158 class): betterdesk.sh, betterdesk.ps1 and betterdesk-docker.sh copied the source *directory* into the destination, which nested the new tree inside the stale dir when the pre-update rename/mv failed on a locked file. They now copy *contents* into a guaranteed-existing dir while preserving data/ and node_modules/.

This commit was made possible thanks to Insolve.
2026-06-01 04:07:20 +02:00
UNITRONIX 4c1a9d5e88 fix(security): patch vulnerable deps + add Go server rebuild flow
Bump golang.org/x/crypto to v0.52.0 and x/sys to v0.45.0 in betterdesk-server, x/sys to v0.45.0 in betterdesk-agent, and aiohttp to >=3.10.11 in the rest-webhook bridge. Validated clean via govulncheck.

Add an explicit Go server rebuild path to the in-app updater so security/library updates actually reach the running binary: updateService now marks the server binary stale when the source changed but a non-critical rebuild/deploy step failed, exposes getServerBinaryStatus() and rebuildServerBinary(), and surfaces a warning banner plus a Rebuild button in the settings update panel. New REST endpoints GET/POST /api/settings/updates/server-binary/{status,rebuild} guarded by server.config permission. i18n keys added across all locales.

This commit was made possible thanks to Insolve.
2026-05-31 06:37:02 +02:00
UNITRONIX 923602d679 feat(enrollment): operator approval queue for stock RustDesk clients
Add a device verification/enrollment workflow so new registrations are
held for operator review instead of connecting silently.

Go server (signal + api):
- Signal-mode pending: in 'managed' mode, unknown stock RustDesk clients
  are queued (pending_device_<id>) instead of being silently rejected.
- Rich approve: handleApproveDevice accepts display_name, sync_mode and
  normalized tags; handleRejectDevice supports an optional ban.

Node.js console:
- registrations.ejs approve modal (name, sync mode, tags, folder) and
  reject modal with ban option; betterdeskApi + routes wire display_name,
  sync_mode, tags and folder assignment through to the Go server.
- EN/PL/ZH i18n for all new strings.

Installers (managed default for FRESH installs only; existing installs
stay on the Go default 'open' or their DB-persisted mode):
- betterdesk.sh / betterdesk.ps1 write ENROLLMENT_MODE=managed to the
  server env only when no existing database is detected (FRESH_INSTALL).
- Docker single + multi container entrypoints detect fresh volumes via a
  sentinel plus id_ed25519/db_v2.sqlite3 presence and default to managed;
  ENROLLMENT_MODE is now passed through supervisord and all compose files.

This commit was made possible thanks to Insolve.
2026-05-31 01:10:38 +02:00
UNITRONIX 0f161181f1 feat(installers): run services under unprivileged accounts by default
Privilege separation across all installers so the long-running services no longer run with full administrative rights:

betterdesk.sh: installer keeps root but systemd units now run as a dedicated unprivileged 'betterdesk' system account by default (auto-created via ensure_service_user). Added full systemd hardening for the Go server (NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, ReadWritePaths) and light hardening for the Node.js console. chown migrates existing root-owned data to the service account on update. Opt-out via --run-as-root / BETTERDESK_RUN_AS_ROOT=1; custom account via BETTERDESK_SERVICE_USER. Minimal mode covered too.

betterdesk.ps1: NSSM services now run under their per-service low-privilege virtual accounts (NT SERVICE\<service>) instead of LocalSystem, with scoped icacls grants on the install/data dirs (Set-ServiceLeastPrivilege helper). Applied to the Go server, Node.js console and minimal-mode service. Opt-out via -RunAsRoot / BETTERDESK_RUN_AS_ROOT=1.

Docker: verified already privilege-separated (supervisord drops both programs to user=betterdesk; multi-container images drop via su-exec).

Also bundles in-progress changes to the Go server API, Node.js console services and Docker compose/Dockerfiles.

This commit was made possible thanks to Insolve.
2026-05-31 00:35:28 +02:00
UNITRONIX 760c0e933d feat(agent-client): alpha bundle generator + cross-platform build pipeline
Generator UI: web-nodejs/views/generator.ejs + public/js/generator.js + public/css/generator.css. Logo upload up to 10 MB, 16 MB body parser, branding form (product name, colors, server URL, etc.), per-branding hash deduplication.

Build pipeline: web-nodejs/services/agentBundleService.js (queue API + branding hash) and agentBuildWorker.js (DB-backed queue, 5s poll, concurrency 1, 30 min timeout). Spawns 'cargo tauri build --bundles <fmt> [--target <triple>] [--runner cargo-xwin]' per platform under systemd User=root. Loads /etc/betterdesk/build.env at module top so BUILD_USER/CARGO_HOME/PATH survive empty service env. Uses absolute CARGO_BIN/NPM_BIN paths to avoid PATH-resolution issues. Artifact path resolution honors profile.target presence (no triple subdir when omitted).

Toolchain installer: scripts/install-build-toolchain.sh (Rust + targets + cargo-tauri + cargo-xwin + mingw + makensis + dpkg-deb + rpmbuild + appimagetool + pnpm + node), writes /etc/betterdesk/build.env, 12-tool verification. Wired into betterdesk.sh menu as option B with post-install rsync of agent source to /opt/BetterDeskConsole/agent-source/.

Agent download page: web-nodejs/views/agent-download.ejs + public/css/agent-download.css for end-user installer downloads per platform/format with live status.

Branding scaffold (Tauri side): betterdesk-agent-client/src-tauri/src/branding.rs (Branding struct + OnceLock cache + BETTERDESK_AGENT_BRANDING env override + BaseDirectory::Resource resolve). resources/branding.json (dev skeleton). lib.rs registers module + get_branding command. commands.rs exposes get_branding IPC. tauri.conf.json declares resources/branding.json. Frontend integration of get_branding is intentionally pending — alpha.

Database: web-nodejs/services/database.js + dbAdapter.js add agent_bundle_builds + agent_bundles tables with full PostgreSQL + SQLite parity.

i18n: en.json + pl.json + zh-TW.json get ~75 new keys covering generator wizard, build status, download page, and toolchain installer messages.

Validated end-to-end on prod (Ubuntu 24.04, 4-core, PostgreSQL): linux/x64/AppImage built successfully (83.7 MB, 283s) for branding hash 25e2f242. linux/deb in progress, rpm + windows/exe queued.

Known follow-ups (NOT in this commit): SolidJS invoke('get_branding') wiring in App.tsx, betterdesk.ps1 toolchain menu mirror, reset-password.js PostgreSQL support, Docker decision.

This commit was made possible thanks to Insolve.
2026-05-29 07:15:45 +02:00
UNITRONIX a9e217c165 fix(api): filter banned devices from client sync and fix tag/AB issues (#138)
Go server:
- mergeAdminTagsIntoAB: strip banned/deleted peers from AB data
- handleClientGroupList: exclude banned peers from tag groups
- handleClientPeersList: add device_name fallback to peer ID, add online field
- handleGetPeer/handleListPeers: return status as int (1/0) with status_text
- handleUsersWithClientFallback: only return users with assigned devices

Node.js console:
- mergeAddressBookData: filter banned devices from AB merge
- buildSyncedAddressBook: set includeDevices=false to prevent ghost AB entries
- normalisePeer: use status_text fallback for status_tier

This commit was made possible thanks to Insolve.
2026-05-29 03:26:40 +02:00
UNITRONIX 60bccb489a fix(auth): restore local-first login flow — fixes login lockout after SSO update
The SSO commit (188991d) changed authenticate() to delegate auth to the Go server first, falling back to local-only for admin roles in 'emergency mode'. This broke login for all users whose accounts exist only in auth.db (Node.js) but not in Go server's database — which is the default for ALL-IN-ONE installs. Go server returned 401 for unknown users, and the new code treated that as a hard rejection with no local fallback. Restored the original local-first flow: check auth.db first, verify password locally, use Go server only as a fallback when local password fails (LDAP/password change sync) or when user doesn't exist locally (opt-in auto-create).

This commit was made possible thanks to Insolve.
2026-05-29 02:49:21 +02:00
UNITRONIX f70123e703 fix(sso): normalize API URL + surface Go errors in test endpoints
auth.routes.js: strip trailing /api segment from BETTERDESK_API_URL when building the absolute OIDC authorize redirect, otherwise the env value (which intentionally ends with /api for axios baseURL) caused doubled /api/api/auth/oidc/authorize URLs.

betterdeskApi.js: testLDAPConnection and testOIDCDiscovery now extract e.response.data.error from axios failures, so the Settings -> SSO test buttons show real Go-side messages (e.g. 'LDAP host is required', DNS errors) instead of the generic 'Request failed with status code 400'.

This commit was made possible thanks to Insolve.
2026-05-29 02:40:28 +02:00
UNITRONIX 188991d91d feat(auth): add LDAP and OIDC/OAuth2 SSO authentication
Go server: auth/ldap.go (LDAP bind + group-to-role mapping), auth/oidc.go (OIDC provider with PKCE, discovery, token exchange), api/ldap_handlers.go (config CRUD + test connection), api/oidc_handlers.go (authorize/callback/exchange/status + config CRUD), auth_handlers.go (LDAP auth branch before local password check + PBKDF2 rehash on login), password.go (NeedsRehash helper), server.go (LDAP/OIDC route registration + Init methods), main.go (InitLDAP/InitOIDC calls). Node.js console: auth.routes.js (OIDC proxy routes with open-redirect sanitization), settings.routes.js (LDAP/OIDC config tabs), authService.js (LDAP/OIDC auth flows with emergency mode), betterdeskApi.js (6 new SSO API methods), middleware/auth.js (emergencyMode flag), login.ejs (SSO buttons), settings.ejs (LDAP/OIDC config panels), navbar.ejs (SSO indicator). i18n: ~90 SSO keys added to EN/PL/ZH.

This commit was made possible thanks to Insolve.
2026-05-29 02:29:10 +02:00
UNITRONIX 83f3617f98 fix(update): fix infinite update loop and add GitHub-pull update to ALL-IN-ONE scripts (#154)
updateService.js: distinguish critical vs non-critical failures in SHA tracking. Server binary compile/download failures are non-critical — SHA is saved so the same update is not shown again on restart. update-cli.js: match same logic, non-critical failures don't set exit code 1. betterdesk.sh: new update_from_github() with git clone + tarball fallback, 3-method menu. betterdesk.ps1: new Update-FromGitHub with git clone + ZIP fallback, 3-method menu. betterdesk-docker.sh: new update_docker_from_github() with 2-method menu.

This commit was made possible thanks to Insolve.
2026-05-29 02:28:57 +02:00
UNITRONIX 4d2a4e0488 fix(api,ui): fix tags/groups, status type, operator permissions (#138)
UI: group chip buttons changed to icon-only (matching folder chips), Create Group tile styling unified with Create Folder, old .group-chip-action CSS replaced with unified .chip-action class.

Go server: peerResponse and singlePeerResponse now return status as int (1=active, 0=disabled) instead of string, added status_text for admin panel backward compat. Fixes RustDesk client crash 'type String is not a subtype of type int?'.

Go server: new handleUsersWithClientFallback — detects RustDesk client requests to /api/users and returns current user without requiring user.view permission. Fixes disappearing folders/groups caused by _getUsers() 403 short-circuiting _pull().

Node.js: normalisePeer updated to use status_text fallback for status_tier.

Branding: RustDesk Server Management -> BetterDesk Server Management across themes, i18n, settings. Console version bumped to 3.0.0.

This commit was made possible thanks to Insolve.
2026-05-28 01:46:19 +02:00
UNITRONIX ab2dc5d3ab feat(scripts): add HTTP/HTTPS protocol toggle to installer scripts
- Add menu option T (Toggle HTTP/HTTPS) to betterdesk.sh and betterdesk.ps1
- Add --protocol http|https CLI flag (bash) and -Protocol param (PS1)
- Toggle updates .env, systemd/NSSM services, and Go server TLS flags
- Auto-generate self-signed cert when switching to HTTPS if none exists
- Go API (:21114) always stays HTTP (internal Node.js<->Go communication)
- Fix betterdeskApi.js: conditional httpsAgent/httpAgent based on URL scheme
- Fix deviceStatusPush.js: TLS options only applied for wss:// connections

This commit was made possible thanks to Insolve.
2026-05-27 00:10:51 +02:00
Knienartowicz de53408803 security: apply audit fixes (H-02/H-03/H-04/H-05) — branding, TOTP recovery codes, NodeSource SHA verification
Node.js (web-nodejs):

- H-02 (services/brandingService.js): tighten SVG sanitization (strip <style>/<use>/<image>, DOCTYPE/PI, CSS expression()/@import); export validateBrandingUrl() rejecting protocol-relative // and unknown schemes

- H-03 (routes/settings.routes.js): logo upload — whitelist /^logo-[0-9a-f]{16}.(png|jpg|jpeg|gif|webp|svg)$/i + path.resolve prefix check + fs.lstatSync symlink guard before deleting old logo

Go server (betterdesk-server):

- H-04 (auth/recovery.go NEW): TOTP recovery codes — GenerateRecoveryCodes (10 codes XXXX-XXXX-XX, unambiguous alphabet), HashRecoveryCodes (JSON array of bcrypt hashes, cost 10), ConsumeRecoveryCode (single-use, returns updated store)

- H-04 (db/database.go,sqlite.go,postgres.go): User.TOTPRecoveryCodes field with read/write via COALESCE-tolerant SELECTs (additive, backward-compat: column already existed from Phase 12 migration)

- H-04 (api/auth_handlers.go): handleConfirmTOTP returns plaintext recovery codes ONCE on enable; handleLogin2FA falls back to ConsumeRecoveryCode on invalid TOTP and audits with 2fa=recovery_code; handleDisableTOTP clears stored codes

Scripts:

- H-05 (betterdesk.sh): replace curl|bash piping with download-to-tempfile + validation — HTTPS-only (--proto=https --tlsv1.2), size sanity (1-500KB), shebang sanity check, SHA-256 logged, optional pinning via NODESOURCE_SHA256 env

Verification: go build ./... ✓, go vet ./... ✓ (exit 0), go test ./auth/... ./db/... ✓, jest 102/102 passed

This commit was made possible thanks to Insolve.
2026-05-26 14:57:01 +02:00
Knienartowicz 8da6f8c9fd security: fix 3 critical + 3 high findings from production audit
Critical:

- C-01: WebSocket Origin validation (CSWSH protection) via new middleware/wsOrigin.js, applied to wsRelay, chatRelay, remoteRelay, bdRelay, cdapTerminalProxy, cdapMediaProxy

- C-02: Remove Tauri Origin-based CSRF bypass in server.js; only /api/bd/* skipped

- C-03: Update vulnerable deps (express 4.21.2, multer 2.0.0, protobufjs 7.4.0, helmet 7.2.0, axios 1.9.0, cookie-parser 1.4.7, express-session 1.18.1)

High:

- H-01: Disable auto-create-local-user on login by default; opt-in via BETTERDESK_AUTH_AUTOCREATE=true (does not affect ensureDefaultAdmin fresh-install bootstrap)

- H-02: Bearer-only auth for /api/bd/*; session cookie fallback removed; tokens redacted in logs

- H-05: Replace custom PBKDF2 with golang.org/x/crypto/pbkdf2; 600k iterations; new format pbkdf2-sha256\\\ with backward-compat for legacy salt:hash

Backward compatibility: legacy password hashes still verify; CSRF tokens still obtainable via csrfTokenProvider; fresh-install admin bootstrap (.admin_credentials flow) unchanged.

Audit report: docs/security/AUDIT_PRODUCTION_2026-04-10.md

This commit was made possible thanks to Insolve.
2026-05-26 13:35:12 +02:00
UNITRONIX 415b6cf967 feat: add terminal updater and keep Go API HTTP 2026-05-23 00:49:49 +02:00
UNITRONIX 274a52d1cd feat: Enhance update process for BetterDesk console and Go server
- Updated Polish and Chinese language files to reflect changes in update descriptions and confirmations.
- Modified settings.js to automatically include server updates in the update process.
- Simplified the update installation API to automatically handle server updates without user intervention.
- Improved updateService.js to ensure all supported components are updated together, enhancing reliability.
- Added logic to check and install the Go toolchain as needed during updates, ensuring compatibility.
- Enhanced error handling and logging during the update process for better visibility of issues.
2026-05-23 00:29:19 +02:00
UNITRONIX c30d1a86aa Fix RustDesk folder tag sync 2026-05-18 02:34:38 +02:00
UNITRONIX 87e9251d31 feat: Implement user group management and access control
- Added user group membership functionality, allowing users to be assigned to groups.
- Introduced validation for group GUIDs and enhanced error handling in user routes.
- Updated device group routes to support allowed user groups, enabling better access control for devices.
- Enhanced database schema to include user group memberships and device group user group access.
- Updated services and database adapters to handle user group data and relationships.
- Modified front-end views to display and manage user groups effectively.
- Added tests to ensure proper functionality of user group assignments and device access control.
2026-05-18 02:23:57 +02:00
UNITRONIX 1460b55951 fix: separate RustDesk folder groups from tags (#138) 2026-05-15 01:19:21 +02:00
UNITRONIX 241d367ea7 fix: add tag-based dynamic device groups (#140) 2026-05-15 00:57:59 +02:00
UNITRONIX b9d4c77076 fix: update address book sync logic to exclude folder tags and enhance tag handling 2026-05-14 02:00:10 +02:00
UNITRONIX 783f2a8a43 fix: sync device tags with RustDesk client API
Refs #138

Reported-by: Skansmer (#138)
2026-05-11 22:56:19 +02:00
UNITRONIX 74300c916c Fix user recovery after update
Reported-by: @SterlynKong

Refs: #136
2026-05-09 01:02:00 +02:00
UNITRONIX a8d3259d43 feat(server-management): add server management service and terminal proxy
- Implemented server management service providing resource snapshots, file browser, service control, and audit logging.
- Added terminal proxy for WebSocket-backed PTY, allowing browser-based shell access with user authentication and role-based access control.
- Created server management view with tabs for overview, terminal, file management, and services, including UI elements for displaying system metrics and managing files/services.

Co-authored-by: Copilot <copilot@github.com>
2026-05-07 03:09:03 +02:00
UNITRONIX c5970657e7 feat(i18n): expose all panel languages in selector
Render language choices dynamically from loaded locale files instead of hardcoding EN/PL. Add selectors on the navbar, login screen, and desktop login screen so users can choose a language before or after authentication.

Persist the selected language in the browser via cookie/localStorage and on authenticated accounts via users.preferred_language. Merge client translations with the default locale fallback so incomplete language files do not surface raw keys in the UI.
2026-05-03 02:02:15 +02:00
UNITRONIX 452c76069c fix(users): mirror Node panel users to Go server for org linking (#125)
Panel accounts were created only in the Node auth.db while the
Organization 'Add User -> Add Existing' dropdown queries the Go
server's users table via db.ListUsersNotInOrg(). This produced a
mismatch where only the seeded admin appeared as linkable.

Add a userSync service that mirrors create / update / delete /
password-reset operations from the Node panel to the Go server's
/api/users endpoints, plus a one-shot backfill at startup that
creates Go-side records for any pre-existing panel users (random
throwaway password; Node bcrypt remains authoritative for panel
login).

Reported-by: SterlynKong <SterlynKong@users.noreply.github.com>
2026-05-03 01:48:08 +02:00
UNITRONIX b65a16c7b5 fix(signal,updater,ratelimit): address #121, #122, #123
Three independent bug fixes bundled together; none of the issues are
auto-closed by this commit so the reporters can confirm on a tagged build.

#121 — NAT hairpin: same-public-IP detection forces relay path

The signal handler now distinguishes 'same /24 private subnet' (genuine
LAN, keep direct path) from 'same public IP' (NAT hairpin scenario).
When both peers register from the same public IP, both the UDP and
TCP/WS punch-hole handlers skip the LAN-address exchange and steer the
client straight to the relay — matching upstream RustDesk behavior.
Most consumer routers and cellular gateways drop hairpinned UDP, which
was causing same-Wi-Fi connections to silently time out.

  - new helper isSamePublicIP() in signal/handler.go
  - new config flag SameNATRelay (default: enabled)
  - env: SAME_NAT_RELAY=N to opt out
  - cli: --same-nat-relay=false to opt out

Reported-by: @eternalliving (#121)

#122 — Rate limit configurable, 0 disables

The 20 registrations/min/IP cap was unworkable for any deployment with
real NAT/CGNAT in front of it. Made it tunable without recompiling and
hardened the limiter to short-circuit when disabled.

  - new config field SignalRateLimitPerIP (default: 20, unchanged)
  - env: SIGNAL_RATE_LIMIT_PER_IP=<n> (0 = unlimited)
  - cli: --signal-rate-limit-per-ip=<n>
  - ratelimit.IPLimiter.Allow() now returns true early when limit<=0

Reported-by: @Henry-739 (#122)

#123 — Updater corrupting live SQLite WAL files

A previous gitleaks-fix commit accidentally tracked live SQLite sidecar
files (auth.db-shm/wal, betterdesk.db-shm/wal, .session_secret,
.update_sha). The in-app updater's diff-against-GitHub logic then
'restored' those tracked-by-mistake files on user installs, which is
exactly how SQLite database corruption gets manufactured.

Layered defense:
  - .gitignore now covers *.db-shm, *.db-wal, *.sqlite3-{shm,wal,journal},
    web-nodejs/data/, .session_secret, .update_sha, .api_key,
    .admin_credentials, .force_password_update, .env*
  - removed the offending files from the index (data/.gitkeep retained)
  - updateService.js EXCLUDE_PATTERNS extended to match the new gitignore
  - new write-time guard isProtectedRuntimePath() wired into all four
    write sites in updateService.js so even a stale GitHub diff cannot
    overwrite a runtime state file on disk

Reported-by: @SterlynKong (#123)
2026-05-01 16:22:50 +02:00
UNITRONIX 4eed88673c fix(updates): atomic binary replace + accurate modal status
- deployServerBinary: use rename(2) for atomic replace, fixes ETXTBSY
  when target Go binary is busy (Linux kernel handles inode swap).
  Falls back to copyFileSync on cross-device rename or non-Linux.
  Windows: rename target out of the way first, then move new in.
- settings.js: mark 'server' phase as error when build succeeded but
  deploy failed (was incorrectly marking 'done' from build alone).
- settings.js: completion modal now shows error title, error message
  and pre-formatted stderr when serverDeploy.success === false.
- i18n: added complete_with_errors, modal_done_with_errors_title in
  en/pl.
2026-04-26 01:23:18 +02:00
UNITRONIX 323e2f1398 feat(updates): auto-install Go toolchain + modal-based update UX
- updateService: enhanced checkGoAvailable() to scan well-known paths
  (/usr/local/go, /snap, vendored data/go-toolchain, /usr/lib/go-1.x)
  and return absolute binary path so spawned exec works without PATH.
- New installGoToolchain(): dynamically fetches go.dev/dl/?mode=json,
  picks newest stable >= 1.23.0 for current OS/arch, downloads archive,
  verifies SHA-256 from manifest, extracts to data/go-toolchain/.
- buildGoServer() now uses absolute go path, 600s timeout.
- New 'install-go' update strategy + auto-fallback in 'auto' mode:
  when host has neither Go nor a prebuilt release, the toolchain is
  installed automatically and compilation proceeds.
- New POST /api/settings/updates/install-go endpoint for explicit
  install (audit-logged, server.config permission gated).
- Settings UI: third 'Auto-install Go and compile' radio. Update
  checkbox is no longer disabled when Go is missing — auto-install
  is always offered as a fallback.
- installUpdate() rewritten as Modal-based phased dialog:
  Confirmation -> Backup -> Console -> Server -> Restart -> Done.
  Live phase icons (pending/active/done/error/skipped), progress bar,
  log pane, completion modal with reload CTA, auto-reload after
  successful console restart.
- New i18n keys (EN+PL): strategy_install_go, auto_strategy,
  toolchain_*, modal_*, phase_*, confirm_*, etc.
- New CSS (.update-progress-modal, .update-phase, .update-progress-log).
2026-04-26 01:07:32 +02:00
UNITRONIX c7f03bbe6f settings: backup retention + delete + size display (#116)
- updateService: getDirectorySize, deleteBackup, pruneBackups; auto-prune
  in createPreUpdateBackup using DB setting backup_retention_count or env
  BACKUP_RETENTION_COUNT
- settings.routes: DELETE /api/settings/updates/backups/:name,
  POST /api/settings/updates/backups/prune,
  GET/PUT /api/settings/backup/retention
- settings.ejs: retention input + 'Apply now' button + total size summary
- settings.js: render size per backup, delete button, retention controls
- pages.css: backup-retention-row + update-backup-actions styles
- lang/en + pl: 11 new keys (delete, retention, prune, total_size)
2026-04-26 00:52:52 +02:00
UNITRONIX 50b77627b1 Add server prebuilt download & strategy UI
Expose an update strategy UI and support downloading pre-built server binaries as an alternative to compiling from source.

- Add new translation keys (en/pl/zh) for strategy labels, badges, download/build messages and install Go hint.
- Update settings UI: show strategy selection (download / compile), badges with availability/release/size, auto-select best strategy, and adjust status/info messages and progress text.
- settings.routes: make server-info handler async and include prebuilt info; accept serverStrategy in updates/install request and forward to updateService.
- updateService: add helpers getReleaseBinaryName, checkPrebuiltAvailable, downloadPrebuiltBinary and getPrebuiltInfo; extend getServerUpdateInfo to include expected binary/platform/arch. Implement server update flow to support compile or download strategies (auto fallback), download/prep binary, validate size, deploy binary, and record method/size in results.

This enables faster updates on platforms with prebuilt releases while preserving the compile-from-source path and providing clear UI feedback and fallbacks.
2026-04-18 03:32:06 +02:00
UNITRONIX e556b181df Gate agent admin UI by OS privileges
Add OS-level admin detection and use it to gate sensitive agent UI and tray actions. Introduce privileges.rs (Windows TokenElevation / Unix geteuid) and expose is_os_admin as a Tauri command; wire it into tray setup to hide admin-only menu items (Settings, Quit) and re-check privileges before executing those actions. Add show_window helper and emit navigate events from the tray; frontend listens for navigate and conditionally renders /settings (shows AdminRequired component for non-admins). Update App.tsx to query is_os_admin on startup and include navigation listener; add AdminRequired component, styles, and i18n keys. Update Cargo.toml with platform deps (windows features + libc for unix). Also add UI/locale assets and CSS for agent lazy-loaded device tabs and a notifications dropdown, plus several web-nodejs route/view/style updates and new task docs describing phase work.
2026-04-18 01:18:57 +02:00
UNITRONIX 7b453d852f Security hardening and audit cleanup
Multiple security and maintenance fixes across components:

- betterdesk-mgmt: validate peer_id format to prevent injection in connect_to_peer (reject empty/oversized/invalid chars).
- betterdesk-mgmt (tauri.conf.json): tighten CSP by removing 'unsafe-eval' from script-src.
- betterdesk-agent-client: increase device ID entropy from 4 to 8 bytes (BD- prefix) to reduce collision/brute-force risk.
- betterdesk-server: enforce RBAC (operator+) before upgrading CDAP video WebSocket to block unauthorized access.
- betterdesk-server DBs: exclude soft_deleted peers in GetPeer queries for Postgres and SQLite.
- web-nodejs: add audit log housekeeping (hourly cleanup), add indices for audit_log, and implement cleanupOldAuditLogs(days) in sqlite adapter.
- web-nodejs brandingService: validate logo/favicon URLs to allow only http(s) or relative paths, preventing javascript:/data: XSS/SSRF vectors.
- docs: add AUDIT_BETTERDESK_2026-04-17.md (security audit summary).

These changes tighten client CSP, improve input validation, increase device identifier entropy, ensure RBAC is enforced before websocket upgrades, hide soft-deleted peers from normal queries, and add audit log maintenance and DB indexes for better performance and retention management.
2026-04-17 23:21:11 +02:00
UNITRONIX d37b6c2c88 Add Go server build support to updater
Enable optional compilation and deployment of the Go server as part of the self-update flow. UI: add checkbox/status/info area in settings.js, check /api/settings/updates/server-info, include server component when selected, adjust progress/messages and longer timeouts. API/Server: add server-info endpoint and extend install request timeouts. Service: updateService now sets server localRoot and implements functions to detect Go, fetch server source (git or GitHub API), build the binary, and deploy it. i18n: add related translation keys across many locale files. Misc: improve input validation and error logging in desktop.routes, and return graceful defaults for missing policy routes in policies.routes.
2026-04-16 01:07:13 +02:00
UNITRONIX 04e6035ad7 Warn about TLS_API mismatch and enrollment mode
Add warnings for TLS API misconfiguration and enrollment restrictions. The Go server now logs a clear warning when TLS on the API port is enabled (explaining it breaks HTTP consumers and how to fix) and logs active enrollment restriction when restored from DB. The Node.js API client (betterdeskApi.js) and event bus handler (deviceStatusPush.js) now detect TLS/HTTP mismatches and surface actionable console/error messages to help operators debug the issue (references issue #104). Files changed: betterdesk-server/main.go, web-nodejs/services/betterdeskApi.js, web-nodejs/services/deviceStatusPush.js.
2026-04-16 00:38:27 +02:00
UNITRONIX 3f7c05d7ea Merge pull request #83 from clarencetw/feat/add-zh-tw-i18n
Add Traditional Chinese (zh-TW) i18n translations
2026-04-13 06:51:12 +02:00
UNITRONIX 89e4e0a592 Refactor routes, relay, auth & chat integrations
Several cross-cutting fixes and refactors:

- API routing: Consolidated multiple org policy PUT endpoints into a single parameterized route (/api/org/{id}/policy/{category}) to simplify handlers (api/server.go).
- Relay/LAN handling: Prefer server LAN IP for LAN relay addresses (with proper port detection from configured relay), added strconv import and fallback to configured relay when LAN IP unknown; improves reliability with NAT hairpin issues (signal/handler.go).
- Web security: Allow inline event handlers (scriptSrcAttr: 'unsafe-inline') while still requiring nonced <script> tags for scripts used by admin pages (web-nodejs/middleware/security.js).
- CSRF: Include x-csrf-token header when POSTing language fix requests from the UI (web-nodejs/public/js/languages.js).
- Admin roles: Broaden admin checks to accept multiple admin role names via ADMIN_ROLES and update requireAdmin and RustDesk payload is_admin logic (web-nodejs/routes/rustdesk-api.routes.js).
- Admin credentials & startup resilience: authService now searches additional candidate dirs (config.dataDir, extra Windows/RustDesk paths, /app/data in Docker), skips empty candidates, and increases retries/delays when waiting for .admin_credentials (web-nodejs/services/authService.js).
- Chat API paths: Updated chat-related API calls to use /chat/* (instead of /api/chat/*) across persistence, history, contacts, groups, read and other operations (web-nodejs/services/chatRelay.js).

These changes improve compatibility (LAN relay, admin detection), robustness (longer retries, Docker/Windows path checks), and frontend behavior (CSRF token, inline handlers, updated chat endpoints).
2026-04-12 19:28:16 +02:00
UNITRONIX 7307388015 Improve migrations, LAN detection, auth & UI logs
DB: Use current_schema() when checking columns for deferred index creation and add exception handling to skip index creation if column is absent (avoids cross-schema false positives and race errors).
Signal: Harden isSameNetwork by normalizing IPv4, handling mapped addresses, adding detailed debug logs for loopback/private/subnet checks, and logging LAN detection failures in the RequestRelay handler.
Auth/API: Add tighter debug logging and trimming for /api/login (redacting passwords), and reject empty/invalid usernames early in authenticate() to address Issue #104.
UI: Add save button feedback (spinner, disable/restore), extra logging and error handling when saving org settings, and make logo image URL input editable by removing readonly.
2026-04-11 19:31:07 +02:00
UNITRONIX 86582d84cb Add font picker, text-logo and TLS fixes
Add typography support and a text-based logo option plus several TLS/connectivity improvements. Introduces a new font service (web-nodejs/services/fontService.js) to search, download and serve Google Fonts for self-hosting, new API routes for font management, and client-side font picker UI/logic (settings.js) with CSS (pages.css, main.css) and i18n entries (en/pl/zh). BrandingService now supports logo text/accent and font heading/body and includes generated font CSS. Views (login/sidebar) updated to render text logos and a new theme (themes/insolve.json) added. Server and TLS updates: API server now prefers TLS on the API port when valid certs exist, and dual-mode listener in tls.go adds a short peek timeout to avoid deadlocks with RustDesk clients.
2026-04-11 02:24:14 +02:00
UNITRONIX a710580b7a Add RBAC permissions UI and server handlers
Implement RBAC Phase 52: add server-side role & permission handlers and wire API routes, plus frontend UI, styles and translations.

Server: new role_handlers.go exposing endpoints to list roles, get effective role permissions, list/set/delete role permission overrides; routes registered in server.go with permission checks (PermUserView / PermServerConfig). Protects super-admin defaults and validates inputs.

Frontend (management & web UI): add permissions page assets (CSS, JS, view), add i18n strings for en/pl/zh, update sidebar to filter items by canView, show user role badge in topbar and empty access-denied state when no permission. Add role badges styling in users.css and small UX/i18n improvements in organizationDetail.js.

Also several route and service adjustments to support the new permissions UI. This change introduces RBAC UI/API plumbing for managing role-based permissions and overrides.
2026-04-11 00:47:08 +02:00
UNITRONIX 45e5fda9d0 Implement RBAC v52, org scoping and assorted fixes
Adds a full Phase-52 RBAC implementation and multiple server/frontend fixes. Key changes: new auth/permissions.go with 28 granular permissions and DefaultRolePermissions, expanded 7-role hierarchy and helpers in auth/roles.go, JWT org context and GenerateOrgToken, requirePermission/requireOrgMembership middlewares (Go + Node.js), DB schema & adapter changes for role_permissions and is_server_admin, org role boundary checks and peer org scoping, and guards for last-admin demotion and self-demotion. Also: TCP EOF/connection-reset log filtering in signal/relay servers, improved startup banner port display, KEYS_PATH auto-detect warning, CSS hover/transition layout fixes, admin password race mitigation, ID-change ghost peer cleanup, added Tauri ACL schema files, and a new RBAC_PHASE52.md doc. Misc: numerous web-nodejs i18n, CSS, JS and route updates and an updated .github/copilot-instructions.md timestamp/summary.
2026-04-10 23:40:55 +02:00