diff --git a/app/Controllers/NotificationGroupController.php b/app/Controllers/NotificationGroupController.php index 99b131a..5a319f0 100644 --- a/app/Controllers/NotificationGroupController.php +++ b/app/Controllers/NotificationGroupController.php @@ -468,6 +468,7 @@ class NotificationGroupController extends Controller 'discord' => 'Discord', 'slack' => 'Slack', 'mattermost' => 'Mattermost', + 'pushover' => 'Pushover', 'webhook' => 'Webhook' ]; diff --git a/app/Views/groups/edit.php b/app/Views/groups/edit.php index 27e8211..3549302 100644 --- a/app/Views/groups/edit.php +++ b/app/Views/groups/edit.php @@ -673,6 +673,23 @@ function testChannel(channelType, existingConfig = null) { errorMessage = 'Please enter a Webhook URL'; } break; + case 'pushover': + const pushoverApiToken = document.getElementById('pushover_api_token').value.trim(); + const pushoverUserKey = document.getElementById('pushover_user_key').value.trim(); + if (!pushoverApiToken) { + isValid = false; + errorMessage = 'Please enter a Pushover API token'; + } else if (!/^[a-zA-Z0-9]{30}$/.test(pushoverApiToken)) { + isValid = false; + errorMessage = 'Please enter a valid Pushover API token (30 alphanumeric characters)'; + } else if (!pushoverUserKey) { + isValid = false; + errorMessage = 'Please enter a Pushover user key'; + } else if (!/^[a-zA-Z0-9]{30}$/.test(pushoverUserKey)) { + isValid = false; + errorMessage = 'Please enter a valid Pushover user key (30 alphanumeric characters)'; + } + break; } if (!isValid) { @@ -725,6 +742,16 @@ function testChannel(channelType, existingConfig = null) { case 'webhook': formData.append('webhook_url', existingConfig.webhook_url); break; + case 'pushover': + formData.append('pushover_api_token', existingConfig.api_token); + formData.append('pushover_user_key', existingConfig.user_key); + if (existingConfig.device) { + formData.append('pushover_device', existingConfig.device); + } + if (existingConfig.sound) { + formData.append('pushover_sound', existingConfig.sound); + } + break; } } else { // Use form values for new channels @@ -748,6 +775,18 @@ function testChannel(channelType, existingConfig = null) { case 'webhook': formData.append('webhook_url', document.getElementById('generic_webhook_url').value); break; + case 'pushover': + formData.append('pushover_api_token', document.getElementById('pushover_api_token').value); + formData.append('pushover_user_key', document.getElementById('pushover_user_key').value); + const pushoverDevice = document.getElementById('pushover_device'); + if (pushoverDevice && pushoverDevice.value) { + formData.append('pushover_device', pushoverDevice.value); + } + const pushoverSound = document.getElementById('pushover_sound'); + if (pushoverSound && pushoverSound.value) { + formData.append('pushover_sound', pushoverSound.value); + } + break; } } diff --git a/domain-monitor-docker/bootstrap.sh b/domain-monitor-docker/bootstrap.sh index d2c6225..e9e482c 100644 --- a/domain-monitor-docker/bootstrap.sh +++ b/domain-monitor-docker/bootstrap.sh @@ -114,6 +114,18 @@ for d in logs storage cache tmp runtime; do fi done +# Create and set permissions for avatar uploads directory +UPLOADS_DIR="$APP_DIR/public/assets/uploads/avatars" +if [ ! -d "$UPLOADS_DIR" ]; then + echo " - Creating avatar uploads directory" + mkdir -p "$UPLOADS_DIR" || true +fi +if [ -d "$APP_DIR/public/assets/uploads" ]; then + echo " - Making uploads directory writable by ${WWW_UID}:${WWW_GID}" + chown -R ${WWW_UID}:${WWW_GID} "$APP_DIR/public/assets/uploads" || true + chmod -R 775 "$APP_DIR/public/assets/uploads" || true +fi + # Allow installer to create .installed at project root chmod 775 "$APP_DIR"