From 98c75c125d7d8c7ea13199db7d18bf8270ca9600 Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Sat, 13 Sep 2025 13:57:40 +0200 Subject: [PATCH] Fix jwt-token --- client/src/pages/Login.jsx | 11 -- management/src/components/TenantModal.jsx | 164 ++++++++++++++++- server/index.js | 5 + server/middleware/ip-restriction.js | 206 ++++++++++++++++++++++ server/models/Tenant.js | 19 ++ 5 files changed, 392 insertions(+), 13 deletions(-) create mode 100644 server/middleware/ip-restriction.js diff --git a/client/src/pages/Login.jsx b/client/src/pages/Login.jsx index 12c4479..df49dcb 100644 --- a/client/src/pages/Login.jsx +++ b/client/src/pages/Login.jsx @@ -216,17 +216,6 @@ const Login = () => { )} - {/* Demo credentials for local/ldap auth */} - {(tenantConfig?.auth_provider === 'local' || tenantConfig?.auth_provider === 'ldap') && ( -
-

- Demo credentials:
- Username: admin
- Password: admin123 -

-
- )} - {/* Error message if auth provider not configured */} {!tenantConfig?.auth_provider && (
diff --git a/management/src/components/TenantModal.jsx b/management/src/components/TenantModal.jsx index 3d86853..ea7f363 100644 --- a/management/src/components/TenantModal.jsx +++ b/management/src/components/TenantModal.jsx @@ -69,11 +69,16 @@ const TenantModal = ({ isOpen, onClose, tenant = null, onSave }) => { primary_color: '#3B82F6', secondary_color: '#1F2937', company_name: '' - } + }, + // IP Restriction settings + ip_restriction_enabled: false, + ip_whitelist: [], + ip_restriction_message: 'Access denied. Your IP address is not authorized to access this tenant.' }) const [showSecrets, setShowSecrets] = useState(false) const [loading, setLoading] = useState(false) + const [newIP, setNewIP] = useState('') // Load tenant data when editing useEffect(() => { @@ -85,7 +90,11 @@ const TenantModal = ({ isOpen, onClose, tenant = null, onSave }) => { user_mapping: { ...formData.user_mapping, ...tenant.user_mapping }, role_mapping: { ...formData.role_mapping, ...tenant.role_mapping }, features: { ...formData.features, ...tenant.features }, - branding: { ...formData.branding, ...tenant.branding } + branding: { ...formData.branding, ...tenant.branding }, + // IP restriction fields with fallbacks + ip_restriction_enabled: tenant.ip_restriction_enabled || false, + ip_whitelist: tenant.ip_whitelist || [], + ip_restriction_message: tenant.ip_restriction_message || 'Access denied. Your IP address is not authorized to access this tenant.' }) } }, [tenant]) @@ -106,6 +115,43 @@ const TenantModal = ({ isOpen, onClose, tenant = null, onSave }) => { })) } + // IP Management functions + const addIPToWhitelist = () => { + if (!newIP.trim()) { + toast.error('Please enter an IP address or CIDR block') + return + } + + // Basic validation for IP format + const ipPattern = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:\/(?:[0-9]|[1-2][0-9]|3[0-2]))?$|^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^\d{1,3}\.\d{1,3}\.\d{1,3}\.\*$/ + + if (!ipPattern.test(newIP.trim())) { + toast.error('Please enter a valid IP address, CIDR block (e.g., 192.168.1.0/24), or wildcard (e.g., 192.168.1.*)') + return + } + + const ip = newIP.trim() + if (formData.ip_whitelist.includes(ip)) { + toast.error('This IP is already in the whitelist') + return + } + + setFormData(prev => ({ + ...prev, + ip_whitelist: [...prev.ip_whitelist, ip] + })) + setNewIP('') + toast.success('IP added to whitelist') + } + + const removeIPFromWhitelist = (ipToRemove) => { + setFormData(prev => ({ + ...prev, + ip_whitelist: prev.ip_whitelist.filter(ip => ip !== ipToRemove) + })) + toast.success('IP removed from whitelist') + } + const handleSubmit = async (e) => { e.preventDefault() setLoading(true) @@ -604,6 +650,120 @@ const TenantModal = ({ isOpen, onClose, tenant = null, onSave }) => {
+ {/* IP Restriction Configuration */} +
+

IP Access Control

+ +
+ setFormData(prev => ({ + ...prev, + ip_restriction_enabled: e.target.checked + }))} + className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" + /> + +
+ + {formData.ip_restriction_enabled && ( +
+

+ Only IPs in the whitelist below will be able to access this tenant. You can add individual IP addresses, CIDR blocks, or wildcards. +

+ + {/* Add IP Input */} +
+ setNewIP(e.target.value)} + onKeyPress={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + addIPToWhitelist() + } + }} + className="flex-1 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+ + {/* IP Whitelist */} + {formData.ip_whitelist.length > 0 && ( +
+ +
+ {formData.ip_whitelist.map((ip, index) => ( +
+ {ip} + +
+ ))} +
+
+ )} + + {/* Custom restriction message */} +
+ +