mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-04 22:13:21 +00:00
fix: conflate frontend_url and server_url
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "settings" DROP COLUMN "frontend_url";
|
||||||
@@ -157,7 +157,6 @@ model settings {
|
|||||||
server_protocol String @default("http")
|
server_protocol String @default("http")
|
||||||
server_host String @default("localhost")
|
server_host String @default("localhost")
|
||||||
server_port Int @default(3001)
|
server_port Int @default(3001)
|
||||||
frontend_url String @default("http://localhost:3000")
|
|
||||||
created_at DateTime @default(now())
|
created_at DateTime @default(now())
|
||||||
updated_at DateTime
|
updated_at DateTime
|
||||||
update_interval Int @default(60)
|
update_interval Int @default(60)
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ router.get('/', authenticateToken, requireManageSettings, async (req, res) => {
|
|||||||
server_protocol: 'http',
|
server_protocol: 'http',
|
||||||
server_host: 'localhost',
|
server_host: 'localhost',
|
||||||
server_port: 3001,
|
server_port: 3001,
|
||||||
frontend_url: 'http://localhost:3000',
|
|
||||||
update_interval: 60,
|
update_interval: 60,
|
||||||
auto_update: false,
|
auto_update: false,
|
||||||
signup_enabled: 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('serverProtocol').isIn(['http', 'https']).withMessage('Protocol must be http or https'),
|
||||||
body('serverHost').isLength({ min: 1 }).withMessage('Server host is required'),
|
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('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('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('autoUpdate').isBoolean().withMessage('Auto update must be a boolean'),
|
||||||
body('signupEnabled').isBoolean().withMessage('Signup enabled 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() });
|
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
|
// Construct server URL from components
|
||||||
const serverUrl = `${serverProtocol}://${serverHost}:${serverPort}`;
|
const serverUrl = `${serverProtocol}://${serverHost}:${serverPort}`;
|
||||||
@@ -171,7 +169,6 @@ router.put('/', authenticateToken, requireManageSettings, [
|
|||||||
server_protocol: serverProtocol,
|
server_protocol: serverProtocol,
|
||||||
server_host: serverHost,
|
server_host: serverHost,
|
||||||
server_port: serverPort,
|
server_port: serverPort,
|
||||||
frontend_url: frontendUrl,
|
|
||||||
update_interval: updateInterval || 60,
|
update_interval: updateInterval || 60,
|
||||||
auto_update: autoUpdate || false,
|
auto_update: autoUpdate || false,
|
||||||
signup_enabled: signupEnabled || false,
|
signup_enabled: signupEnabled || false,
|
||||||
@@ -181,7 +178,6 @@ router.put('/', authenticateToken, requireManageSettings, [
|
|||||||
updated_at: new Date()
|
updated_at: new Date()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// If update interval changed, trigger crontab updates on all hosts with auto-update enabled
|
// If update interval changed, trigger crontab updates on all hosts with auto-update enabled
|
||||||
if (oldUpdateInterval !== (updateInterval || 60)) {
|
if (oldUpdateInterval !== (updateInterval || 60)) {
|
||||||
console.log(`Update interval changed from ${oldUpdateInterval} to ${updateInterval || 60} minutes. Triggering crontab updates...`);
|
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_protocol: serverProtocol,
|
||||||
server_host: serverHost,
|
server_host: serverHost,
|
||||||
server_port: serverPort,
|
server_port: serverPort,
|
||||||
frontend_url: frontendUrl,
|
|
||||||
update_interval: updateInterval || 60,
|
update_interval: updateInterval || 60,
|
||||||
auto_update: autoUpdate || false,
|
auto_update: autoUpdate || false,
|
||||||
signup_enabled: signupEnabled || false,
|
signup_enabled: signupEnabled || false,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
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 { settingsAPI, agentVersionAPI, versionAPI } from '../utils/api';
|
||||||
import { useUpdateNotification } from '../contexts/UpdateNotificationContext';
|
import { useUpdateNotification } from '../contexts/UpdateNotificationContext';
|
||||||
import UpgradeNotificationIcon from '../components/UpgradeNotificationIcon';
|
import UpgradeNotificationIcon from '../components/UpgradeNotificationIcon';
|
||||||
@@ -10,7 +10,6 @@ const Settings = () => {
|
|||||||
serverProtocol: 'http',
|
serverProtocol: 'http',
|
||||||
serverHost: 'localhost',
|
serverHost: 'localhost',
|
||||||
serverPort: 3001,
|
serverPort: 3001,
|
||||||
frontendUrl: 'http://localhost:3000',
|
|
||||||
updateInterval: 60,
|
updateInterval: 60,
|
||||||
autoUpdate: false,
|
autoUpdate: false,
|
||||||
signupEnabled: false,
|
signupEnabled: false,
|
||||||
@@ -31,7 +30,6 @@ const Settings = () => {
|
|||||||
// Tab configuration
|
// Tab configuration
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ id: 'server', name: 'Server Configuration', icon: Server },
|
{ id: 'server', name: 'Server Configuration', icon: Server },
|
||||||
{ id: 'frontend', name: 'Frontend Configuration', icon: Globe },
|
|
||||||
{ id: 'agent', name: 'Agent Management', icon: SettingsIcon },
|
{ id: 'agent', name: 'Agent Management', icon: SettingsIcon },
|
||||||
{ id: 'version', name: 'Server Version', icon: Code, showUpgradeIcon: updateAvailable }
|
{ id: 'version', name: 'Server Version', icon: Code, showUpgradeIcon: updateAvailable }
|
||||||
];
|
];
|
||||||
@@ -77,7 +75,6 @@ const Settings = () => {
|
|||||||
serverProtocol: settings.server_protocol || 'http',
|
serverProtocol: settings.server_protocol || 'http',
|
||||||
serverHost: settings.server_host || 'localhost',
|
serverHost: settings.server_host || 'localhost',
|
||||||
serverPort: settings.server_port || 3001,
|
serverPort: settings.server_port || 3001,
|
||||||
frontendUrl: settings.frontend_url || 'http://localhost:3000',
|
|
||||||
updateInterval: settings.update_interval || 60,
|
updateInterval: settings.update_interval || 60,
|
||||||
autoUpdate: settings.auto_update || false,
|
autoUpdate: settings.auto_update || false,
|
||||||
signupEnabled: settings.signup_enabled === true ? true : false, // Explicit boolean conversion
|
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';
|
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) {
|
if (!formData.updateInterval || formData.updateInterval < 5 || formData.updateInterval > 1440) {
|
||||||
newErrors.updateInterval = 'Update interval must be between 5 and 1440 minutes';
|
newErrors.updateInterval = 'Update interval must be between 5 and 1440 minutes';
|
||||||
}
|
}
|
||||||
@@ -627,74 +618,6 @@ const Settings = () => {
|
|||||||
</form>
|
</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 */}
|
{/* Agent Management Tab */}
|
||||||
{activeTab === 'agent' && (
|
{activeTab === 'agent' && (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|||||||
Reference in New Issue
Block a user