Commit Graph

169 Commits

Author SHA1 Message Date
d977ec9a47 Merge pull request 'remove Firebase service account file from repo (keep local only)' (#69) from feat/fcm-config into master
Reviewed-on: #69
2026-06-13 14:27:14 -04:00
d8425a69dc remove Firebase service account file from repo (keep local only) 2026-06-13 14:26:45 -04:00
6eaf3811db Merge pull request 'add Firebase service account for FCM push notifications' (#68) from feat/fcm-config into master
Reviewed-on: #68
Reviewed-by: rafaga21 <rafaelminaya20@hotmail.com>
2026-06-13 14:25:36 -04:00
f34c10df91 add Firebase service account file for FCM push notifications 2026-06-13 14:23:47 -04:00
63e55ecf7e Merge pull request 'feat: Firebase Cloud Messaging push notifications' (#66) from feat/fcm-notifications into master
Reviewed-on: #66
2026-06-13 14:05:44 -04:00
7876a730c8 Merge branch 'master' into feat/fcm-notifications 2026-06-13 14:05:13 -04:00
a988b88077 bump to 1.8.1 (versionCode 13) and rebuild APK 2026-06-13 14:04:10 -04:00
60e91b56d3 fix: register FCM token on app startup and improve error logging 2026-06-13 14:04:10 -04:00
e1e68f5f11 fix: actively fetch FCM token on login if not cached
- LoginViewModel now calls Tasks.await(FirebaseMessaging.getInstance().token)
  to actively fetch the FCM token if not yet saved in prefs
- Previous code relied solely on onNewToken callback, which may not fire
  before the user logs in on a fresh install
2026-06-13 14:04:10 -04:00
45dc21461c fix: FCM push not sending — add v1 API + better diagnostics
- FCMService now supports both HTTP v1 API (service account) and legacy API (server key)
- v1 API uses OAuth2 JWT auth with Firebase service account; tries this first
- Falls back to legacy HTTP API if only server key is configured
- Removes invalid tokens from DB automatically (NotRegistered, INVALID_ARGUMENT, etc.)
- AdminController now logs push result status and shows in UI response
- .env updated with FCM_SERVER_KEY placeholder and docs
- Migration 010 run in dev
2026-06-13 14:04:09 -04:00
c3a736f927 chore: add real Firebase config and messaging dependency
- google-services.json now has real Firebase project values
- Added firebase-messaging-ktx dependency (was missing)
- Updated google-services plugin to 4.4.4
2026-06-13 14:04:09 -04:00
32740b1ee0 feat: Firebase Cloud Messaging push notifications
Backend:
- New user_fcm_tokens table (migration 010) for storing device tokens
- FCMService sends push via Firebase HTTP legacy API (server key from .env)
- POST /api/fcm/register endpoint for Android to register its FCM token
- AdminController::sendNotification() triggers FCM push after DB insert
- FCM config added to config.php

Android:
- Firebase Cloud Messaging service (ServerManagerFirebaseService)
  receives push notifications and shows them via NotificationHelper
- FCM token registered with backend on new token and on login
- google-services.json template (must be replaced with real Firebase config)
- firebase-setup.sh script with configuration instructions
- FCM dependency + google-services plugin added to Gradle
- Bump to v1.8.0 (versionCode 12)
2026-06-13 14:04:09 -04:00
4c71beb180 Merge pull request 'fix: register FCM token on app startup + rebuild APK 1.8.1' (#65) from feat/dashboard-aggregated-chart into master
Reviewed-on: #65
Reviewed-by: rafaga21 <rafaelminaya20@hotmail.com>
2026-06-13 13:49:52 -04:00
5ff3b255c4 bump to 1.8.1 (versionCode 13) and rebuild APK 2026-06-13 13:48:51 -04:00
35c5d43f74 Merge pull request 'fix: register FCM token on app startup and improve error logging' (#64) from feat/dashboard-aggregated-chart into master
Reviewed-on: #64
2026-06-13 13:47:06 -04:00
94e3dfe236 fix: register FCM token on app startup and improve error logging 2026-06-13 13:46:03 -04:00
80833cf256 Merge pull request 'fix: actively fetch FCM token on login if not cached' (#63) from feat/dashboard-aggregated-chart into master
Reviewed-on: #63
2026-06-13 13:24:22 -04:00
395c84f75e fix: actively fetch FCM token on login if not cached
- LoginViewModel now calls Tasks.await(FirebaseMessaging.getInstance().token)
  to actively fetch the FCM token if not yet saved in prefs
- Previous code relied solely on onNewToken callback, which may not fire
  before the user logs in on a fresh install
2026-06-13 13:23:29 -04:00
dcc57e08f0 Merge pull request 'fix: FCM push not sending — add v1 API + better diagnostics' (#62) from feat/dashboard-aggregated-chart into master
Reviewed-on: #62
2026-06-13 13:15:36 -04:00
f1f263225f fix: FCM push not sending — add v1 API + better diagnostics
- FCMService now supports both HTTP v1 API (service account) and legacy API (server key)
- v1 API uses OAuth2 JWT auth with Firebase service account; tries this first
- Falls back to legacy HTTP API if only server key is configured
- Removes invalid tokens from DB automatically (NotRegistered, INVALID_ARGUMENT, etc.)
- AdminController now logs push result status and shows in UI response
- .env updated with FCM_SERVER_KEY placeholder and docs
- Migration 010 run in dev
2026-06-13 13:11:12 -04:00
1277a460b6 Merge pull request 'feat: Firebase Cloud Messaging push notifications' (#61) from feat/dashboard-aggregated-chart into master
Reviewed-on: #61
2026-06-13 13:01:58 -04:00
988ea118b0 chore: add real Firebase config and messaging dependency
- google-services.json now has real Firebase project values
- Added firebase-messaging-ktx dependency (was missing)
- Updated google-services plugin to 4.4.4
2026-06-13 13:00:54 -04:00
136eebc4c3 feat: Firebase Cloud Messaging push notifications
Backend:
- New user_fcm_tokens table (migration 010) for storing device tokens
- FCMService sends push via Firebase HTTP legacy API (server key from .env)
- POST /api/fcm/register endpoint for Android to register its FCM token
- AdminController::sendNotification() triggers FCM push after DB insert
- FCM config added to config.php

Android:
- Firebase Cloud Messaging service (ServerManagerFirebaseService)
  receives push notifications and shows them via NotificationHelper
- FCM token registered with backend on new token and on login
- google-services.json template (must be replaced with real Firebase config)
- firebase-setup.sh script with configuration instructions
- FCM dependency + google-services plugin added to Gradle
- Bump to v1.8.0 (versionCode 12)
2026-06-13 12:37:40 -04:00
090294d856 Merge pull request 'feat(android): foreground service for real-time notification polling' (#60) from feat/dashboard-aggregated-chart into master
Reviewed-on: #60
2026-06-13 12:21:07 -04:00
bdc4d73d89 feat(android): foreground service for real-time notification polling
- New NotificationForegroundService: persistent foreground coroutine-based
  polling every 30s, keeps app alive in background
- Manifest: FOREGROUND_SERVICE + FOREGROUND_SERVICE_DATA_SYNC permissions,
  service declaration with foregroundServiceType=dataSync
- NotificationHelper: added silent channel for persistent service notification
- ServerManagerApp: starts foreground service on app launch
- MainActivity: removed redundant NotificationWorker.checkNow (service handles
  background polling; NotificationPoller still handles in-app refresh)
- Bump to v1.8.0 (versionCode 12)
2026-06-13 12:20:09 -04:00
d5431353dd Merge pull request 'refactor: drop is_read and read_at from notifications table' (#59) from feat/dashboard-aggregated-chart into master
Reviewed-on: #59
2026-06-13 12:05:24 -04:00
80f5893d92 refactor: drop is_read and read_at from notifications table
- is_read and read_at columns are now obsolete since notification_reads
  tracks per-user read receipts
- Removed UPDATE statements in markAsRead/markAllAsRead that touched
  the old columns
- API response still includes computed is_read field via SQL CASE in
  getForUser() JOIN with notification_reads, maintaining Android
  compatibility
- Migration 009 drops both columns
2026-06-13 11:57:56 -04:00
839d5a190f Merge pull request 'fix: remove duplicate old() function causing 500 on create page' (#58) from feat/dashboard-aggregated-chart into master
Reviewed-on: #58
2026-06-13 11:54:18 -04:00
12c3e23d9c feat: track notification read receipts per user
- New notification_reads table (migration 008) with unique (notification_id, user_id)
- Notification model: markAsRead inserts into notification_reads; getForUser JOINs
  to show per-user read status; getUnreadCount checks NOT EXISTS in reads table
- getAll() includes read_count subquery for admin view
- Admin view shows 'X / Y' read count for broadcast notifications,
  'Read'/'Unread' badge for user-targeted ones
- Migrates existing read notifications into notification_reads
- AGENTS.md updated with new conventions
2026-06-13 11:48:05 -04:00
b94ae16f69 fix: remove duplicate old() function causing 500 on create page
- Removed the local old() function definition from views/servers/create.php
  which conflicted with the global old() in src/Helpers/functions.php:37
- Replaced all old() calls with direct htmlspecialchars([...]) lookups
2026-06-13 11:31:52 -04:00
7b9f66b0c8 Merge pull request 'fix: handle missing server_permissions table gracefully' (#57) from feat/dashboard-aggregated-chart into master
Reviewed-on: #57
2026-06-13 11:23:12 -04:00
bb1192c164 fix: handle missing server_permissions table gracefully
- Wrap ServerPermission queries in try-catch so show/edit don't 500
  when the migration hasn't been run yet
- Same protection for save calls in store/update (both web and API)
2026-06-13 10:55:14 -04:00
81c8626df5 Merge pull request 'feat: validate required SSH permissions before creating server' (#56) from feat/dashboard-aggregated-chart into master
Reviewed-on: #56
Reviewed-by: rafaga21 <rafaelminaya20@hotmail.com>
2026-06-13 10:44:21 -04:00
0cfed5bf27 feat: validate required SSH permissions before creating server
- New server_permissions table (migration 007) stores required SSH permissions per server
- PermissionValidator service connects via SSH and validates each permission before save
- ServerPermission model for CRUD on server_permissions table
- Web flow: create/edit forms include dynamic permission rows with quick-add presets
- API flow: serverAdd/serverUpdate accept permissions array, return 400 on failure
- Show view displays required permissions on server detail page
- Form input preserved on validation failure (credentials excluded)
- AGENTS.md updated with new conventions
2026-06-13 10:41:18 -04:00
c916ed175c Merge pull request 'feat: add aggregated resource usage chart to dashboard' (#55) from feat/dashboard-aggregated-chart into master
Reviewed-on: #55
2026-06-11 21:46:57 -04:00
8f3b5bd7ce feat: add aggregated resource usage chart to dashboard 2026-06-11 21:46:33 -04:00
957d4494b1 Merge pull request 'fix: remove bottom nav padding on server detail screen' (#54) from feat/push-monitoring-agent-v2 into master
Reviewed-on: #54
2026-06-11 21:33:04 -04:00
ae09af3e02 Bump app version to 1.7.2 (versionCode 11) and rebuild APK 2026-06-11 21:31:39 -04:00
c88b46ec80 fix: remove bottom nav padding on server detail screen
Scaffold's innerPadding reserved NavigationBar height even when the
bar was hidden (on detail screens). Content like the services list
had extra empty space at the bottom.

Fix: build custom PaddingValues that only includes bottom padding
when inLoggedInArea is true.
2026-06-11 21:26:34 -04:00
3f95b061d3 Merge pull request 'fix: 401 logout loop — sync state update, prevent re-navigation' (#53) from feat/push-monitoring-agent-v2 into master
Reviewed-on: #53
2026-06-11 21:13:27 -04:00
1885693f8d fix: 401 logout loop — sync state update, prevent re-navigation
Root cause: LoginViewModel.logout() was async (viewModelScope.launch),
so _uiState.isConnected remained true after navigating to login.
LoginScreen's LaunchedEffect immediately navigated back to dashboard,
where APIs failed with 401 again → infinite loop.

Fixes:
- SessionManager: add _invalidating flag to prevent concurrent 401 handling
- AuthInterceptor: check isSessionValid before invalidating
- LoginViewModel: update _uiState synchronously in logout(), clear token
  before launching coroutine for prefs.clear()
- LoginViewModel: call SessionManager.restoreSession() after successful login
- MainActivity: remove restoreSession() from logout handler (was incorrectly
  re-validating session right after invalidation)

Bump to v1.7.1 (versionCode 10)
2026-06-11 21:12:39 -04:00
3f80f2c484 Merge pull request 'feat: start agent immediately in background after user-mode install' (#52) from feat/push-monitoring-agent-v2 into master
Reviewed-on: #52
2026-06-11 20:56:19 -04:00
4bb383f127 feat: start agent immediately in background after user-mode install
After installing cron, the agent now starts right away via
nohup ... & disown instead of waiting for the next boot.
2026-06-11 20:55:15 -04:00
ab9e5d9cf3 Merge pull request 'fix: force LC_ALL=C for metric commands to avoid comma decimal separator' (#51) from feat/push-monitoring-agent-v2 into master
Reviewed-on: #51
2026-06-11 20:50:31 -04:00
552e30751d fix: force LC_ALL=C for metric commands to avoid comma decimal separator
Some locales use comma as decimal separator (e.g., es_DO.UTF-8).
This caused invalid JSON like "cpu": 2,4 instead of "cpu": 2.4.
Prefixed CPU and RAM commands with LC_ALL=C to force dot decimals.

Also removed debug logging from pushMetrics endpoint.
2026-06-11 20:49:14 -04:00
50f1574954 Merge pull request 'feat/push-monitoring-agent-v2' (#50) from feat/push-monitoring-agent-v2 into master
Reviewed-on: #50
2026-06-11 20:43:53 -04:00
2340fce8f8 fix: use warning level for push metrics log 2026-06-11 20:39:28 -04:00
ef23dd0b08 fix: add logging to pushMetrics endpoint for debugging 401 2026-06-11 20:39:14 -04:00
b90c600573 Merge pull request 'fix: unquote PAYLOAD heredoc so runtime vars are expanded' (#49) from feat/push-monitoring-agent-v2 into master
Reviewed-on: #49
2026-06-11 20:35:58 -04:00
ddf4d744c6 fix: unquote PAYLOAD heredoc so runtime vars are expanded
The inner PAYLOAD heredoc had a quoted delimiter ('PAYLOAD') which
prevented runtime variable expansion. Changed to unquoted (PAYLOAD)
so $AGENT_KEY, $CPU, etc. are correctly expanded at runtime.

The double-escaping works as:
  install time (outer EOF):  $AGENT_KEY  →   (in file)
  runtime (inner PAYLOAD):     →  abc123... (actual value)
2026-06-11 20:35:24 -04:00