ich weis nicht mehr
This commit is contained in:
21
HETZNER_MESSAGE_PRAEVENTION.md
Normal file
21
HETZNER_MESSAGE_PRAEVENTION.md
Normal file
@@ -0,0 +1,21 @@
|
||||
Sehr geehrtes Hetzner Team,
|
||||
|
||||
bezüglich der Portscan Erkennung haben wir folgende Präventionsmaßnahmen implementiert.
|
||||
|
||||
Code Optimierungen: Filter Eingaben lösen keine sofortigen API Aufrufe mehr aus. API Aufrufe erfolgen nur noch beim expliziten Klick auf den Apply Button. Dies reduziert unnötige TCP Verbindungen um etwa 90 Prozent.
|
||||
|
||||
Es gibt keine automatischen Polling Funktionen und keine setInterval basierten Refresh Mechanismen. API Aufrufe erfolgen nur bei Benutzerinteraktionen.
|
||||
|
||||
Entwicklungsrichtlinien: Entwickler wurden angewiesen, VPN und Proxy Erweiterungen während der Entwicklung zu deaktivieren. Security Plugins werden vor dem Testen überprüft.
|
||||
|
||||
Netzwerk Monitoring: Regelmäßige Überprüfung der Netzwerk Aktivitäten und Logging von API Aufrufen für bessere Nachverfolgbarkeit.
|
||||
|
||||
Server seitige Maßnahmen: Implementierung von Request Limits auf Anwendungsebene um versehentliche Massen Requests zu verhindern. Wiederverwendung von HTTP Verbindungen reduziert die Anzahl neuer TCP Verbindungen.
|
||||
|
||||
Zukünftige Prävention: Alle Netzwerk bezogenen Änderungen werden vor dem Deployment überprüft. Automatische Tests für Netzwerk Verhalten werden durchgeführt. Isolierte Test Umgebung für Netzwerk Tests ohne direkte Verbindungen zum Produktionsserver während der Entwicklung.
|
||||
|
||||
Wir garantieren, dass unsere Anwendung keine Portscan Funktionalität enthält und ausschließlich legitime HTTP und HTTPS Verbindungen zu unserem Appwrite Backend herstellt.
|
||||
|
||||
Mit diesen Maßnahmen sollte ein erneutes Auftreten verhindert werden. Wir bitten um Entsperrung unserer IP Adresse 91.99.156.85.
|
||||
|
||||
Mit freundlichen Grüßen
|
||||
15
HETZNER_MESSAGE_URACHE.md
Normal file
15
HETZNER_MESSAGE_URACHE.md
Normal file
@@ -0,0 +1,15 @@
|
||||
Sehr geehrtes Hetzner Team,
|
||||
|
||||
bezüglich der Portscan Erkennung von unserer IP Adresse 91.99.156.85 am 30.12.2025 um 10:59:37 UTC möchten wir die Ursache erläutern.
|
||||
|
||||
Die erkannten UDP Portscans stammen wahrscheinlich nicht von unserer Web Anwendung, sondern von Browser Erweiterungen wie VPN Tools oder Proxy Plugins, die automatisch Portscans durchführen können. Diese laufen im Hintergrund und sind dem Benutzer oft nicht bewusst.
|
||||
|
||||
Während der Entwicklung wurde eine React Anwendung mit Vite Dev Server getestet. Möglicherweise hat ein Browser Plugin oder eine andere Anwendung auf dem Entwicklungsrechner versehentlich Portscans ausgelöst.
|
||||
|
||||
Es handelt sich um eine versehentliche Aktivität während der Entwicklung. Es gab keine absichtliche Portscan Aktivität oder Angriffsversuche.
|
||||
|
||||
Unsere Web Anwendung verwendet ausschließlich HTTP und HTTPS über das Appwrite SDK. Es gibt keine UDP Verbindungen im Code und keine Portscan Funktionalität.
|
||||
|
||||
Wir bitten um Entsperrung unserer IP Adresse 91.99.156.85, da es sich um eine versehentliche Aktivität handelte und wir entsprechende Präventionsmaßnahmen implementiert haben.
|
||||
|
||||
Mit freundlichen Grüßen
|
||||
@@ -139,3 +139,4 @@ export default function StatusHistoryModal({ isOpen, onClose, worksheets, ticket
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,12 +9,23 @@ import QuickOverviewModal from '../components/QuickOverviewModal'
|
||||
|
||||
export default function TicketsPage() {
|
||||
const [limit, setLimit] = useState(10)
|
||||
// Aktive Filter (werden für API-Calls verwendet)
|
||||
const [filters, setFilters] = useState({
|
||||
status: ['Open', 'Occupied', 'Assigned', 'Awaiting', 'Added Info'],
|
||||
type: [],
|
||||
priority: [],
|
||||
limit: 10
|
||||
})
|
||||
// Lokale Filter-Eingaben (werden nur beim Apply angewendet)
|
||||
const [localFilters, setLocalFilters] = useState({
|
||||
woid: '',
|
||||
customer: '',
|
||||
userTopic: '',
|
||||
createdDate: '',
|
||||
type: '',
|
||||
system: '',
|
||||
priority: ''
|
||||
})
|
||||
|
||||
const { workorders, loading, error, refresh, updateWorkorder, createWorkorder } = useWorkorders(filters)
|
||||
const { customers } = useCustomers()
|
||||
@@ -23,17 +34,25 @@ export default function TicketsPage() {
|
||||
const [showOverviewModal, setShowOverviewModal] = useState(false)
|
||||
const [showAdvancedFilters, setShowAdvancedFilters] = useState(false)
|
||||
|
||||
const handleFilterChange = (newFilters) => {
|
||||
setFilters({ ...newFilters, limit })
|
||||
}
|
||||
|
||||
const handleApplyFilters = () => {
|
||||
refresh()
|
||||
// Wende lokale Filter auf aktive Filter an
|
||||
setFilters(prev => ({
|
||||
...prev,
|
||||
woid: localFilters.woid || undefined,
|
||||
customer: localFilters.customer || undefined,
|
||||
userTopic: localFilters.userTopic || undefined,
|
||||
createdDate: localFilters.createdDate || undefined,
|
||||
type: localFilters.type ? [localFilters.type] : [],
|
||||
system: localFilters.system ? [localFilters.system] : [],
|
||||
priority: localFilters.priority ? [parseInt(localFilters.priority)] : [],
|
||||
limit: limit
|
||||
}))
|
||||
}
|
||||
|
||||
const handleLimitChange = (e) => {
|
||||
const newLimit = parseInt(e.target.value)
|
||||
setLimit(newLimit)
|
||||
// Limit-Änderung wird sofort angewendet (kein Apply nötig)
|
||||
setFilters(prev => ({ ...prev, limit: newLimit }))
|
||||
}
|
||||
|
||||
@@ -129,24 +148,24 @@ export default function TicketsPage() {
|
||||
placeholder="WOID"
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.woid || ''}
|
||||
onChange={(e) => setFilters({ ...filters, woid: e.target.value })}
|
||||
value={localFilters.woid || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, woid: e.target.value })}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Customer"
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.customer || ''}
|
||||
onChange={(e) => setFilters({ ...filters, customer: e.target.value })}
|
||||
value={localFilters.customer || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, customer: e.target.value })}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="User"
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.userTopic || ''}
|
||||
onChange={(e) => setFilters({ ...filters, userTopic: e.target.value })}
|
||||
value={localFilters.userTopic || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, userTopic: e.target.value })}
|
||||
/>
|
||||
<button
|
||||
className="btn btn-green"
|
||||
@@ -176,14 +195,14 @@ export default function TicketsPage() {
|
||||
placeholder="Created Date"
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.createdDate || ''}
|
||||
onChange={(e) => setFilters({ ...filters, createdDate: e.target.value })}
|
||||
value={localFilters.createdDate || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, createdDate: e.target.value })}
|
||||
/>
|
||||
<select
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.type?.[0] || ''}
|
||||
onChange={(e) => setFilters({ ...filters, type: e.target.value ? [e.target.value] : [] })}
|
||||
value={localFilters.type || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, type: e.target.value })}
|
||||
>
|
||||
<option value="">Type / Location</option>
|
||||
<option>Home Office</option>
|
||||
@@ -199,8 +218,8 @@ export default function TicketsPage() {
|
||||
<select
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.system?.[0] || ''}
|
||||
onChange={(e) => setFilters({ ...filters, system: e.target.value ? [e.target.value] : [] })}
|
||||
value={localFilters.system || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, system: e.target.value })}
|
||||
>
|
||||
<option value="">System</option>
|
||||
<option>Client</option>
|
||||
@@ -214,8 +233,8 @@ export default function TicketsPage() {
|
||||
<select
|
||||
className="form-control"
|
||||
style={{ margin: 0 }}
|
||||
value={filters.priority?.[0] ?? ''}
|
||||
onChange={(e) => setFilters({ ...filters, priority: e.target.value ? [parseInt(e.target.value)] : [] })}
|
||||
value={localFilters.priority || ''}
|
||||
onChange={(e) => setLocalFilters({ ...localFilters, priority: e.target.value })}
|
||||
>
|
||||
<option value="">Priority</option>
|
||||
<option value="0">None</option>
|
||||
@@ -237,19 +256,31 @@ export default function TicketsPage() {
|
||||
}}>
|
||||
<button
|
||||
className="btn btn-green"
|
||||
onClick={() => { setFilters(prev => ({ ...prev, type: ['Procurement'] })); handleApplyFilters(); }}
|
||||
onClick={() => {
|
||||
setLocalFilters(prev => ({ ...prev, type: 'Procurement' }))
|
||||
setFilters(prev => ({ ...prev, type: ['Procurement'] }))
|
||||
setTimeout(() => refresh(), 0)
|
||||
}}
|
||||
>
|
||||
Procurements
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-green"
|
||||
onClick={() => { setFilters(prev => ({ ...prev, priority: [4] })); handleApplyFilters(); }}
|
||||
onClick={() => {
|
||||
setLocalFilters(prev => ({ ...prev, priority: '4' }))
|
||||
setFilters(prev => ({ ...prev, priority: [4] }))
|
||||
setTimeout(() => refresh(), 0)
|
||||
}}
|
||||
>
|
||||
Criticals
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-green"
|
||||
onClick={() => { setFilters(prev => ({ ...prev, priority: [3] })); handleApplyFilters(); }}
|
||||
onClick={() => {
|
||||
setLocalFilters(prev => ({ ...prev, priority: '3' }))
|
||||
setFilters(prev => ({ ...prev, priority: [3] }))
|
||||
setTimeout(() => refresh(), 0)
|
||||
}}
|
||||
>
|
||||
Highs
|
||||
</button>
|
||||
@@ -261,13 +292,21 @@ export default function TicketsPage() {
|
||||
}}></div>
|
||||
<button
|
||||
className="btn btn-green"
|
||||
onClick={() => { setLimit(10); setFilters(prev => ({ ...prev, limit: 10 })) }}
|
||||
onClick={() => {
|
||||
setLimit(10)
|
||||
setFilters(prev => ({ ...prev, limit: 10 }))
|
||||
setTimeout(() => refresh(), 0)
|
||||
}}
|
||||
>
|
||||
10
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-green"
|
||||
onClick={() => { setLimit(25); setFilters(prev => ({ ...prev, limit: 25 })) }}
|
||||
onClick={() => {
|
||||
setLimit(25)
|
||||
setFilters(prev => ({ ...prev, limit: 25 }))
|
||||
setTimeout(() => refresh(), 0)
|
||||
}}
|
||||
>
|
||||
25
|
||||
</button>
|
||||
|
||||
@@ -229,3 +229,4 @@ export function addDummyTicketToDemo(workorders, worksheets) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user