fix: conflate frontend_url and server_url

This commit is contained in:
tigattack
2025-09-21 23:08:45 +01:00
parent f23f075e41
commit c3365fedb2
4 changed files with 70 additions and 151 deletions

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "settings" DROP COLUMN "frontend_url";

View File

@@ -157,7 +157,6 @@ model settings {
server_protocol String @default("http")
server_host String @default("localhost")
server_port Int @default(3001)
frontend_url String @default("http://localhost:3000")
created_at DateTime @default(now())
updated_at DateTime
update_interval Int @default(60)

View File

@@ -107,7 +107,6 @@ router.get('/', authenticateToken, requireManageSettings, async (req, res) => {
server_protocol: 'http',
server_host: 'localhost',
server_port: 3001,
frontend_url: 'http://localhost:3000',
update_interval: 60,
auto_update: false,
signup_enabled: false,
@@ -128,7 +127,6 @@ router.put('/', authenticateToken, requireManageSettings, [
body('serverProtocol').isIn(['http', 'https']).withMessage('Protocol must be http or https'),
body('serverHost').isLength({ min: 1 }).withMessage('Server host is required'),
body('serverPort').isInt({ min: 1, max: 65535 }).withMessage('Port must be between 1 and 65535'),
body('frontendUrl').isLength({ min: 1 }).withMessage('Frontend URL is required'),
body('updateInterval').isInt({ min: 5, max: 1440 }).withMessage('Update interval must be between 5 and 1440 minutes'),
body('autoUpdate').isBoolean().withMessage('Auto update must be a boolean'),
body('signupEnabled').isBoolean().withMessage('Signup enabled must be a boolean'),
@@ -151,7 +149,7 @@ router.put('/', authenticateToken, requireManageSettings, [
return res.status(400).json({ errors: errors.array() });
}
const { serverProtocol, serverHost, serverPort, frontendUrl, updateInterval, autoUpdate, signupEnabled, githubRepoUrl, repositoryType, sshKeyPath } = req.body;
const { serverProtocol, serverHost, serverPort, updateInterval, autoUpdate, signupEnabled, githubRepoUrl, repositoryType, sshKeyPath } = req.body;
// Construct server URL from components
const serverUrl = `${serverProtocol}://${serverHost}:${serverPort}`;
@@ -171,7 +169,6 @@ router.put('/', authenticateToken, requireManageSettings, [
server_protocol: serverProtocol,
server_host: serverHost,
server_port: serverPort,
frontend_url: frontendUrl,
update_interval: updateInterval || 60,
auto_update: autoUpdate || false,
signup_enabled: signupEnabled || false,
@@ -181,7 +178,6 @@ router.put('/', authenticateToken, requireManageSettings, [
updated_at: new Date()
}
});
// If update interval changed, trigger crontab updates on all hosts with auto-update enabled
if (oldUpdateInterval !== (updateInterval || 60)) {
console.log(`Update interval changed from ${oldUpdateInterval} to ${updateInterval || 60} minutes. Triggering crontab updates...`);
@@ -196,7 +192,6 @@ router.put('/', authenticateToken, requireManageSettings, [
server_protocol: serverProtocol,
server_host: serverHost,
server_port: serverPort,
frontend_url: frontendUrl,
update_interval: updateInterval || 60,
auto_update: autoUpdate || false,
signup_enabled: signupEnabled || false,

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Save, Server, Globe, Shield, AlertCircle, CheckCircle, Code, Plus, Trash2, Star, Download, X, Settings as SettingsIcon, Clock } from 'lucide-react';
import { Save, Server, Shield, AlertCircle, CheckCircle, Code, Plus, Trash2, Star, Download, X, Settings as SettingsIcon, Clock } from 'lucide-react';
import { settingsAPI, agentVersionAPI, versionAPI } from '../utils/api';
import { useUpdateNotification } from '../contexts/UpdateNotificationContext';
import UpgradeNotificationIcon from '../components/UpgradeNotificationIcon';
@@ -10,7 +10,6 @@ const Settings = () => {
serverProtocol: 'http',
serverHost: 'localhost',
serverPort: 3001,
frontendUrl: 'http://localhost:3000',
updateInterval: 60,
autoUpdate: false,
signupEnabled: false,
@@ -31,7 +30,6 @@ const Settings = () => {
// Tab configuration
const tabs = [
{ id: 'server', name: 'Server Configuration', icon: Server },
{ id: 'frontend', name: 'Frontend Configuration', icon: Globe },
{ id: 'agent', name: 'Agent Management', icon: SettingsIcon },
{ id: 'version', name: 'Server Version', icon: Code, showUpgradeIcon: updateAvailable }
];
@@ -77,7 +75,6 @@ const Settings = () => {
serverProtocol: settings.server_protocol || 'http',
serverHost: settings.server_host || 'localhost',
serverPort: settings.server_port || 3001,
frontendUrl: settings.frontend_url || 'http://localhost:3000',
updateInterval: settings.update_interval || 60,
autoUpdate: settings.auto_update || false,
signupEnabled: settings.signup_enabled === true ? true : false, // Explicit boolean conversion
@@ -284,12 +281,6 @@ const Settings = () => {
newErrors.serverPort = 'Port must be between 1 and 65535';
}
try {
new URL(formData.frontendUrl);
} catch {
newErrors.frontendUrl = 'Frontend URL must be a valid URL';
}
if (!formData.updateInterval || formData.updateInterval < 5 || formData.updateInterval > 1440) {
newErrors.updateInterval = 'Update interval must be between 5 and 1440 minutes';
}
@@ -627,74 +618,6 @@ const Settings = () => {
</form>
)}
{/* Frontend Configuration Tab */}
{activeTab === 'frontend' && (
<form onSubmit={handleSubmit} className="space-y-6">
<div className="flex items-center mb-6">
<Globe className="h-6 w-6 text-primary-600 mr-3" />
<h2 className="text-xl font-semibold text-secondary-900 dark:text-white">Frontend Configuration</h2>
</div>
<div>
<label className="block text-sm font-medium text-secondary-700 dark:text-secondary-200 mb-2">
Frontend URL *
</label>
<input
type="url"
value={formData.frontendUrl}
onChange={(e) => handleInputChange('frontendUrl', e.target.value)}
className={`w-full border rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white ${
errors.frontendUrl ? 'border-red-300 dark:border-red-500' : 'border-secondary-300 dark:border-secondary-600'
}`}
placeholder="https://patchmon.example.com"
/>
{errors.frontendUrl && (
<p className="mt-1 text-sm text-red-600 dark:text-red-400">{errors.frontendUrl}</p>
)}
<p className="mt-1 text-sm text-secondary-500 dark:text-secondary-400">
The URL where users will access the PatchMon web interface.
</p>
</div>
{/* Save Button */}
<div className="flex justify-end">
<button
type="button"
onClick={handleSave}
disabled={!isDirty || updateSettingsMutation.isPending}
className={`inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white ${
!isDirty || updateSettingsMutation.isPending
? 'bg-secondary-400 cursor-not-allowed'
: 'bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500'
}`}
>
{updateSettingsMutation.isPending ? (
<>
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
Saving...
</>
) : (
<>
<Save className="h-4 w-4 mr-2" />
Save Settings
</>
)}
</button>
</div>
{updateSettingsMutation.isSuccess && (
<div className="bg-green-50 dark:bg-green-900 border border-green-200 dark:border-green-700 rounded-md p-4">
<div className="flex">
<CheckCircle className="h-5 w-5 text-green-400 dark:text-green-300" />
<div className="ml-3">
<p className="text-sm text-green-700 dark:text-green-300">Settings saved successfully!</p>
</div>
</div>
</div>
)}
</form>
)}
{/* Agent Management Tab */}
{activeTab === 'agent' && (
<div className="space-y-6">