#!/usr/bin/env python3 """Agrega al bloque `location /api/` de nginx las dos líneas que necesita el acta de campo: proxy_set_header X-Remote-User $remote_user; -> identifica al técnico (y evita que un usuario se haga pasar por otro) client_max_body_size 25m; -> sin esto las fotos y los logs se cortan en 1 MB Es idempotente: si ya están, no toca nada. Hace respaldo antes de escribir. Uso (en el servidor): sudo python3 parche-nginx-api.py # busca el archivo solo sudo python3 parche-nginx-api.py /ruta/al/archivo.conf Después: sudo nginx -t && sudo systemctl reload nginx """ import sys, os, glob, datetime, re LINEAS = [ ('X-Remote-User', ' proxy_set_header X-Remote-User $remote_user;'), ('client_max_body_size', ' client_max_body_size 25m;'), ('proxy_read_timeout', ' proxy_read_timeout 120s;'), ] def candidatos(): vistos = [] for pat in ('/etc/nginx/sites-enabled/*', '/etc/nginx/sites-available/*', '/etc/nginx/conf.d/*'): for f in glob.glob(pat): if os.path.isfile(f) or os.path.islink(f): real = os.path.realpath(f) try: if 'drogheda' in open(real, encoding='utf-8', errors='ignore').read() and real not in vistos: vistos.append(real) except OSError: pass return vistos def bloque_api(txt): """Devuelve (inicio_cuerpo, fin_bloque) del location /api/ o None.""" m = re.search(r'location\s+/api/\s*\{', txt) if not m: return None i = m.end() # justo después de la llave que abre nivel, j = 1, i while j < len(txt) and nivel: if txt[j] == '{': nivel += 1 elif txt[j] == '}': nivel -= 1 j += 1 return (i, j) def main(): archivos = [sys.argv[1]] if len(sys.argv) > 1 else candidatos() if not archivos: sys.exit("No encontré ningún archivo de nginx que mencione 'drogheda'.\n" "Pásalo a mano: sudo python3 parche-nginx-api.py /etc/nginx/sites-available/EL-ARCHIVO") if len(archivos) > 1: print("Hay varios candidatos; elige uno y vuelve a correr con la ruta:") for f in archivos: print(" ", f) sys.exit(1) ruta = archivos[0] txt = open(ruta, encoding='utf-8').read() pos = bloque_api(txt) if not pos: sys.exit(f"{ruta} no tiene un bloque `location /api/ {{ … }}`.\n" "Agrégalo a mano ANTES del `location / {` (ver DESPLIEGUE.md §4).") ini, fin = pos cuerpo = txt[ini:fin] faltan = [l for clave, l in LINEAS if clave not in cuerpo] if not faltan: print(f"✓ {ruta}: el bloque /api/ ya tiene todo. No cambié nada.") print(txt[ini - len('location /api/ {'):fin]) return respaldo = ruta + '.bak-' + datetime.datetime.now().strftime('%Y%m%d-%H%M%S') open(respaldo, 'w', encoding='utf-8').write(txt) nuevo = txt[:ini] + '\n' + '\n'.join(faltan) + txt[ini:] open(ruta, 'w', encoding='utf-8').write(nuevo) print(f"Respaldo: {respaldo}") print(f"Agregadas {len(faltan)} línea(s) a {ruta}:") for l in faltan: print(" " + l.strip()) pos2 = bloque_api(nuevo) print("\nEl bloque quedó así:\n") print(nuevo[pos2[0] - len('location /api/ {'):pos2[1]]) print("\nAhora: sudo nginx -t && sudo systemctl reload nginx") if __name__ == '__main__': main()