Die USA sind DSGVO-rechtlich bereits ein Drittland wie jedes andere - der alte verarbeitungsort-Wertebereich (EU/USA/gemischt/on-prem) verschleierte das. Ersetzt durch verarbeitungslaender TEXT[] mit echter Weltländerliste im Formular (Mehrfachauswahl, kein JS nötig). Der harte Filter eu_verarbeitung verlangt jetzt, dass ALLE genannten Länder EU/EWR sind. Neues Feld dpf_zertifiziert macht die EU-US Data Privacy Framework-Zertifizierung strukturiert statt nur Fließtext. Öffnet nebenbei den Weg für Katalogeinträge außerhalb EU/USA (z. B. DeepSeek), die vorher am alten Wertebereich scheiterten. Zusätzlich Typografie-Nachbesserung nach Nutzer-Feedback: Formular- Abschnittsüberschriften (<legend>) saßen zu dicht am Kartenrand, weil <legend> das Padding des umschließenden <fieldset> ignoriert - jetzt mit eigenem Padding und größerer Schrift, h2/h3 einheitlich gesetzt.
119 lines
4.4 KiB
Go
119 lines
4.4 KiB
Go
package web_test
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/netcell-it/deklarix/internal/store"
|
|
)
|
|
|
|
func werkzeugForm() url.Values {
|
|
return url.Values{
|
|
"name": {"ChatGPT Enterprise"}, "anbieter": {"OpenAI"}, "verarbeitungslaender": {"Irland"},
|
|
"avv_verfuegbar": {"on"}, "avv_url": {"https://example.com/avv"},
|
|
"training_opt_out": {"on"}, "training_standard": {"on"}, "aufbewahrung_tage": {"30"},
|
|
"zertifizierungen": {"ISO 27001, SOC 2"}, "geeignete_zwecke": {"Textgenerierung"},
|
|
"einschraenkungen": {""}, "letzte_pruefung": {"2026-08-01"}, "quelle": {"https://example.com/beleg"},
|
|
}
|
|
}
|
|
|
|
func TestBetreiberCanCreateZentralesWerkzeug(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
betreiberCookie := seedAccountWithRole(t, fs, "Deklarix Betreiber", "betreiber@example.com", "betreiber")
|
|
|
|
resp := postForm(t, s, betreiberCookie, "/betreiber/werkzeuge", werkzeugForm())
|
|
if resp.Code != http.StatusSeeOther {
|
|
t.Fatalf("status = %d, want 303, body: %s", resp.Code, resp.Body.String())
|
|
}
|
|
|
|
var w store.Werkzeug
|
|
for _, wz := range fs.werkzeuge {
|
|
w = wz
|
|
}
|
|
if w.Name != "ChatGPT Enterprise" || w.AccountID != nil {
|
|
t.Fatalf("Werkzeug = %+v, unerwartete Werte", w)
|
|
}
|
|
if len(w.Zertifizierungen) != 2 {
|
|
t.Errorf("Zertifizierungen = %v, want 2 Einträge", w.Zertifizierungen)
|
|
}
|
|
|
|
list := getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge")
|
|
if !strings.Contains(list.Body.String(), "ChatGPT Enterprise") {
|
|
t.Errorf("expected the new werkzeug in the Katalogliste, got: %s", list.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestBetreiberWerkzeugCreateRequiresLetztePruefungUndQuelle(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
betreiberCookie := seedAccountWithRole(t, fs, "Deklarix Betreiber", "betreiber@example.com", "betreiber")
|
|
|
|
form := werkzeugForm()
|
|
form.Set("letzte_pruefung", "")
|
|
resp := postForm(t, s, betreiberCookie, "/betreiber/werkzeuge", form)
|
|
if resp.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200 (Formular mit Fehler) ohne letzte_pruefung", resp.Code)
|
|
}
|
|
if len(fs.werkzeuge) != 0 {
|
|
t.Errorf("expected no werkzeug to be created, got %d", len(fs.werkzeuge))
|
|
}
|
|
}
|
|
|
|
func TestBetreiberCanUpdateAndDeleteZentralesWerkzeug(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
betreiberCookie := seedAccountWithRole(t, fs, "Deklarix Betreiber", "betreiber@example.com", "betreiber")
|
|
postForm(t, s, betreiberCookie, "/betreiber/werkzeuge", werkzeugForm())
|
|
var id string
|
|
for wid := range fs.werkzeuge {
|
|
id = wid
|
|
}
|
|
|
|
editResp := getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge/"+id)
|
|
if editResp.Code != http.StatusOK || !strings.Contains(editResp.Body.String(), "ChatGPT Enterprise") {
|
|
t.Fatalf("edit form status = %d, body: %s", editResp.Code, editResp.Body.String())
|
|
}
|
|
|
|
updateForm := werkzeugForm()
|
|
updateForm.Set("name", "ChatGPT Enterprise (aktualisiert)")
|
|
updateResp := postForm(t, s, betreiberCookie, "/betreiber/werkzeuge/"+id, updateForm)
|
|
if updateResp.Code != http.StatusSeeOther {
|
|
t.Fatalf("update status = %d, body: %s", updateResp.Code, updateResp.Body.String())
|
|
}
|
|
if fs.werkzeuge[id].Name != "ChatGPT Enterprise (aktualisiert)" {
|
|
t.Errorf("Name = %q nach Update, unerwartet", fs.werkzeuge[id].Name)
|
|
}
|
|
|
|
deleteResp := postForm(t, s, betreiberCookie, "/betreiber/werkzeuge/"+id+"/loeschen", url.Values{})
|
|
if deleteResp.Code != http.StatusSeeOther {
|
|
t.Fatalf("delete status = %d, body: %s", deleteResp.Code, deleteResp.Body.String())
|
|
}
|
|
if _, ok := fs.werkzeuge[id]; ok {
|
|
t.Error("expected the werkzeug to be deleted")
|
|
}
|
|
}
|
|
|
|
// TestBetreiberCannotEditMandantenEigenesWerkzeug: ein mandantenspezifischer
|
|
// Katalogeintrag (account_id gesetzt) ist über die Betreiber-Seiten
|
|
// nicht erreichbar — das bleibt Sache des jeweiligen Mandanten.
|
|
func TestBetreiberCannotEditMandantenEigenesWerkzeug(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
betreiberCookie := seedAccountWithRole(t, fs, "Deklarix Betreiber", "betreiber@example.com", "betreiber")
|
|
acc, err := fs.CreateAccount(context.Background(), "Mandant mit eigenem Werkzeug")
|
|
if err != nil {
|
|
t.Fatalf("CreateAccount: %v", err)
|
|
}
|
|
eigenesID := "eigenes-werkzeug"
|
|
fs.werkzeuge[eigenesID] = store.Werkzeug{ID: eigenesID, AccountID: &acc.ID, Name: "Mandanten-eigenes Tool"}
|
|
|
|
resp := getWithCookie(t, s, betreiberCookie, "/betreiber/werkzeuge/"+eigenesID)
|
|
if resp.Code != http.StatusNotFound {
|
|
t.Fatalf("status = %d, want 404 for a mandanten-eigenes werkzeug", resp.Code)
|
|
}
|
|
}
|