ENRE_WEB/gestor/pedir_test.go
SITO 7d5dbeec60 Cuenta de externas, arreglos de seguridad, títulos arriba y despliegue
- Rol «externas» para la asamblea de externas: pide sin cupo, siempre con el
  colectivo de fuera y su contacto, y sus solicitudes salen en naranja hasta
  que la asamblea de la Enre las confirma.
- /pedir/ explica en una línea que los colectivos externos piden fecha en la
  asamblea de externas, los lunes de 19:00 a 20:00.
- Seguridad: argon2 limitado a dos cálculos a la vez y el intento se cuenta
  antes de calcular (60 accesos simultáneos llevaban el proceso a 3,8 GB);
  bloqueo por cuenta a 20 fallos para que no se pueda dejar fuera a la
  asamblea; avisos por sesión en vez de por URL; sig sin «..»; eventos de
  31 días como mucho; parámetros de argon2 acotados.
- Títulos pegados arriba en todas las páginas; la franja de la enredadera
  recupera ese alto para seguir llenando la pantalla.
- despliegue/: instalar.sh, cuenta.sh, servicio de systemd con el proceso
  encerrado, fragmento de nginx que además deja de servir .git y las notas
  internas, y configuración de ejemplo. Ninguna contraseña en el repositorio.
2026-09-23 12:15:33 +02:00

68 lines
1.9 KiB
Go

package main
import (
"testing"
"time"
)
func TestDestinoSeguro(t *testing.T) {
casos := map[string]string{
"/pedir/nueva?fecha=2026-10-09": "/pedir/nueva?fecha=2026-10-09",
"/pedir/mis-fechas": "/pedir/mis-fechas",
"": "",
"/": "",
"/index.html": "",
"//evil.example/pedir/": "",
"https://evil.example/pedir/": "",
"/\\evil.example/pedir/": "",
"/pedir/\r\nSet-Cookie: x=1": "",
"javascript:alert(1)": "",
}
for entrada, quiero := range casos {
if got := destinoSeguro(entrada); got != quiero {
t.Errorf("destinoSeguro(%q) = %q, quiero %q", entrada, got, quiero)
}
}
}
func TestDestinoSeguroSinPuntos(t *testing.T) {
for _, sig := range []string{"/pedir/../index.html", "/pedir/./nueva", "/pedir//nueva", "/pedir/x/../../evil"} {
if got := destinoSeguro(sig); got != "" {
t.Errorf("destinoSeguro(%q) = %q, quiero vacío", sig, got)
}
}
if got := destinoSeguro("/pedir/"); got != "/pedir/" {
t.Errorf("destinoSeguro(/pedir/) = %q", got)
}
}
func TestCerrojoApuntaAntesDeCalcular(t *testing.T) {
c := NuevoCerrojo(5, time.Minute, time.Minute)
pasan := 0
for i := 0; i < 50; i++ {
if ok, _ := c.Intentar("ip:1.2.3.4"); ok {
pasan++
}
}
if pasan != 5 {
t.Fatalf("pasaron %d intentos, quiero 5", pasan)
}
}
func TestArgonParametrosAcotados(t *testing.T) {
// Un hash manipulado que pide 4 GiB de memoria no se calcula.
malo := "$argon2id$v=19$m=4194304,t=3,p=4$c2FsdHNhbHRzYWx0$aGFzaGhhc2hoYXNoaGFzaGhhc2hoYXNoaGFzaGhhc2g"
if VerificarClave(malo, "loquesea") {
t.Fatal("no deberia verificar")
}
}
func TestConfigEjemploValida(t *testing.T) {
c, err := CargarConfig("../despliegue/config.ejemplo.json")
if err != nil {
t.Fatalf("despliegue/config.ejemplo.json no carga: %v", err)
}
if !c.CookieSegura || c.Local {
t.Fatal("el ejemplo de producción tiene que llevar cookie_segura y no local")
}
}