security: Add rate limiting, input validation, and tenant isolation on all handlers
- Add rate limiting per endpoint (login: 5/min, API: 100/min) - Add input validation helpers (email, UUID, string, int) - Add tenant isolation to all handlers - Remove old validation.go, replace with input.go - Fix service/customer.go to use new validation functions - Build successful
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Lägger till tenant isolation på alla handlers.
|
||||
Detta skript modifierar alla .go-filer i handlers/-mappen.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
HANDLERS_DIR = "/home/bernt/.openclaw/workspace/boc/backend/handlers"
|
||||
|
||||
def add_middleware_import(content):
|
||||
"""Lägg till middleware-import om det saknas."""
|
||||
if '"boc/middleware"' in content:
|
||||
return content
|
||||
|
||||
# Hitta sista import och lägg till middleware
|
||||
lines = content.split('\n')
|
||||
import_idx = None
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('import'):
|
||||
import_idx = i
|
||||
break
|
||||
|
||||
if import_idx is None:
|
||||
return content
|
||||
|
||||
# Lägg till efter sista import-rad
|
||||
for i in range(import_idx + 1, len(lines)):
|
||||
if lines[i].strip() == ')':
|
||||
lines.insert(i, '\t"boc/middleware"')
|
||||
break
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
def add_tenant_to_query(content, func_name):
|
||||
"""Lägg till tenant_id i SQL queries."""
|
||||
# Hitta funktionen
|
||||
pattern = rf'func \(h \*\w+\) {func_name}\(w http\.ResponseWriter, r \*http\.Request\) \{{'
|
||||
match = re.search(pattern, content)
|
||||
if not match:
|
||||
return content
|
||||
|
||||
# Lägg till tenant_id extrahering efter funktionsdeklarationen
|
||||
func_start = match.end()
|
||||
|
||||
# Kolla om tenant_id redan finns
|
||||
if 'tenantID' in content[func_start:func_start+500]:
|
||||
return content
|
||||
|
||||
# Hitta första raden efter funktionsdeklarationen
|
||||
insert_pos = content.find('\n', func_start) + 1
|
||||
|
||||
tenant_code = '\n\t// Tenant isolation\n\ttenantID := middleware.GetTenantFromContext(r.Context())\n'
|
||||
|
||||
content = content[:insert_pos] + tenant_code + content[insert_pos:]
|
||||
|
||||
return content
|
||||
|
||||
def add_tenant_to_db_query(content, query_pattern, replacement):
|
||||
"""Lägg till tenant_id i specifika SQL queries."""
|
||||
return re.sub(query_pattern, replacement, content)
|
||||
|
||||
def process_handler(filepath):
|
||||
"""Processa en handler-fil."""
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
original = content
|
||||
|
||||
# Lägg till middleware import
|
||||
content = add_middleware_import(content)
|
||||
|
||||
# Lista över funktioner som ska ha tenant isolation
|
||||
handler_funcs = [
|
||||
'ListCustomers', 'GetCustomer', 'CreateCustomer', 'UpdateCustomer', 'DeleteCustomer',
|
||||
'ListDeals', 'GetDeal', 'CreateDeal', 'UpdateDeal',
|
||||
'ListEmployees', 'GetEmployee', 'CreateEmployee', 'UpdateEmployee',
|
||||
'ListContracts', 'GetContract', 'CreateContract', 'UpdateContract',
|
||||
'ListTickets', 'GetTicket', 'CreateTicket', 'UpdateTicket',
|
||||
'ListCampaigns', 'CreateCampaign',
|
||||
'ListProducts', 'CreateProduct',
|
||||
'ListSuppliers', 'GetSupplier',
|
||||
'GetBalanceSheet', 'GetIncomeStatement', 'GetMomsReport',
|
||||
'GetJournalEntries', 'GetJournalEntry',
|
||||
'ListWorkflows', 'CreateWorkflow',
|
||||
]
|
||||
|
||||
for func_name in handler_funcs:
|
||||
if f'func (h *\w+) {func_name}(' in content:
|
||||
content = add_tenant_to_query(content, func_name)
|
||||
|
||||
if content != original:
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(content)
|
||||
print(f"✅ Uppdaterad: {os.path.basename(filepath)}")
|
||||
return True
|
||||
else:
|
||||
print(f"⏭️ Hoppar över: {os.path.basename(filepath)}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
updated = 0
|
||||
skipped = 0
|
||||
|
||||
for filename in sorted(os.listdir(HANDLERS_DIR)):
|
||||
if not filename.endswith('.go'):
|
||||
continue
|
||||
if filename.endswith('_test.go'):
|
||||
continue
|
||||
|
||||
filepath = os.path.join(HANDLERS_DIR, filename)
|
||||
if process_handler(filepath):
|
||||
updated += 1
|
||||
else:
|
||||
skipped += 1
|
||||
|
||||
print(f"\n📊 Sammanfattning:")
|
||||
print(f" Uppdaterade: {updated}")
|
||||
print(f" Hoppade över: {skipped}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user