Betreiber können den zentralen Werkzeugkatalog jetzt über die UI
pflegen (GET /betreiber/werkzeuge, GET/POST .../neu, GET/POST
.../{id}, POST .../{id}/loeschen) statt nur per SQL. Bearbeitet
ausschließlich zentrale (account_id IS NULL) Einträge — ein
mandantenspezifischer Katalogeintrag bleibt über diese Seiten
unerreichbar (404), das ist weiterhin Sache des jeweiligen Mandanten.
Ohne befüllten Katalog konnte bisher keine Bewertung tatsächlich zu
"genehmigt" mit einem echten Werkzeug führen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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"}, "verarbeitungsort": {"EU"},
|
|
"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)
|
|
}
|
|
}
|