package web import ( "context" "io" "net/http" "net/http/httptest" "net/url" "strings" "testing" "time" "git.ravensburg.dev/cabele/opnsense-portal/internal/audit" "git.ravensburg.dev/cabele/opnsense-portal/internal/auth" ) // certsWithExport ist eine CertSource mit funktionierendem Export. type certsWithExport struct { entries []CertEntry listErr error exportErr error exportCall int lastArgs [4]string } func (c *certsWithExport) EntriesFor(ctx context.Context, username string) ([]CertEntry, error) { return c.entries, c.listErr } func (c *certsWithExport) Export(ctx context.Context, username, vpnID, refID, format string) (*ExportStream, error) { c.exportCall++ c.lastArgs = [4]string{username, vpnID, refID, format} if c.exportErr != nil { return nil, c.exportErr } return &ExportStream{ Filename: "vpn-homeoffice-mmueller.ovpn", ContentType: "application/x-openvpn-profile", Body: io.NopCloser(strings.NewReader("client\nremote fw01 1194\n")), InstanceName: "VPN Homeoffice", CommonName: "mmueller", ValidTo: time.Date(2027, 3, 1, 0, 0, 0, 0, time.UTC), }, nil } // Pattern macht certsWithExport zur Quelle des Audit-Feldes pattern. func (c *certsWithExport) Pattern(username string) string { return username } // loggedInServer liefert Server, Audit-Mitschrift, Cookie und Session eines // angemeldeten Benutzers. func loggedInServer(t *testing.T, certs CertSource) (*Server, *recordAudit, *http.Cookie, *Session) { t.Helper() store := NewSessionStore(10*time.Minute, nil) srv, rec := newTestServer(t, Deps{ Auth: &fakeAuth{id: &auth.Identity{Username: "mmueller", Groups: []string{"VPN-Users"}}}, Certs: certs, Sessions: store, SupportContact: "it-helpdesk@firma.de", }) login := postForm(srv.Handler(), "/login", url.Values{"username": {"m"}, "password": {"p"}}) cookie := sessionCookie(login) if cookie == nil { t.Fatal("Anmeldung lieferte kein Session-Cookie") } sess, ok := store.Get(cookie.Value) if !ok { t.Fatal("Anmeldung fehlgeschlagen") } return srv, rec, cookie, sess } func getWithCookie(h http.Handler, path string, c *http.Cookie) *httptest.ResponseRecorder { r := httptest.NewRequest(http.MethodGet, path, nil) r.RemoteAddr = "10.1.20.34:5000" if c != nil { r.AddCookie(c) } rec := httptest.NewRecorder() h.ServeHTTP(rec, r) return rec } func TestOverviewListsCertificates(t *testing.T) { certs := &certsWithExport{entries: []CertEntry{ {Token: "1:a1", InstanceName: "VPN Homeoffice", CommonName: "mmueller", ValidTo: time.Now().AddDate(1, 0, 0)}, {Token: "2:b1", InstanceName: "VPN Aussendienst", CommonName: "mmueller", ValidTo: time.Now().AddDate(1, 0, 0)}, }} srv, _, cookie, _ := loggedInServer(t, certs) rec := getWithCookie(srv.Handler(), "/", cookie) if rec.Code != http.StatusOK { t.Fatalf("Code = %d", rec.Code) } body := rec.Body.String() for _, want := range []string{"VPN Homeoffice", "VPN Aussendienst", S["download_ovpn"], S["download_viscosity"], `name="csrf_token"`} { if !strings.Contains(body, want) { t.Errorf("Übersicht enthält %q nicht", want) } } if strings.Contains(body, `