feat: eigene Werkzeugkatalog-Einträge für Mandanten
Ein Mandant kann jetzt zusätzlich zum Sperren zentraler Katalogeinträge
auch eigene, nur für sich sichtbare Werkzeuge anlegen/bearbeiten/
löschen (GET/POST /verwaltung/werkzeuge/neu bzw. /{id}, POST
/{id}/loeschen — werkzeug.account_id = eigener Account). Nutzt
dasselbe Formular wie der zentrale Katalog des Betreibers
(werkzeugFormData/betreiber-werkzeug-form.html, ein neues ActionBase-
Feld unterscheidet die Ziel-URL); ein zentraler oder fremder Eintrag
bleibt über diese Route unerreichbar (404). Schließt die letzte
dokumentierte Lücke bei "eigene Werkzeug-Freigaben/-Sperrungen" (Ebene 4).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
103
internal/web/mandant_eigenes_werkzeug_test.go
Normal file
103
internal/web/mandant_eigenes_werkzeug_test.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package web_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/netcell-it/deklarix/internal/store"
|
||||
)
|
||||
|
||||
func TestAdminCanCreateEditAndDeleteEigenesWerkzeug(t *testing.T) {
|
||||
fs := newFakeStore()
|
||||
s := newServer(t, fs)
|
||||
adminCookie := seedAccountWithRole(t, fs, "Test-Mandant", "admin@example.com", "admin")
|
||||
|
||||
resp := postForm(t, s, adminCookie, "/verwaltung/werkzeuge", werkzeugForm())
|
||||
if resp.Code != http.StatusSeeOther {
|
||||
t.Fatalf("create status = %d, body: %s", resp.Code, resp.Body.String())
|
||||
}
|
||||
|
||||
var id string
|
||||
admin, err := fs.GetUserByEmail(context.Background(), "admin@example.com")
|
||||
if err != nil {
|
||||
t.Fatalf("GetUserByEmail: %v", err)
|
||||
}
|
||||
for wid, w := range fs.werkzeuge {
|
||||
if w.AccountID != nil && *w.AccountID == admin.AccountID {
|
||||
id = wid
|
||||
}
|
||||
}
|
||||
if id == "" {
|
||||
t.Fatal("expected an eigenes werkzeug to exist")
|
||||
}
|
||||
|
||||
list := getWithCookie(t, s, adminCookie, "/verwaltung/werkzeuge")
|
||||
if !strings.Contains(list.Body.String(), "ChatGPT Enterprise") {
|
||||
t.Errorf("expected the eigenes werkzeug in the list, got: %s", list.Body.String())
|
||||
}
|
||||
|
||||
editForm := getWithCookie(t, s, adminCookie, "/verwaltung/werkzeuge/"+id)
|
||||
if editForm.Code != http.StatusOK || !strings.Contains(editForm.Body.String(), "ChatGPT Enterprise") {
|
||||
t.Fatalf("edit form status = %d, body: %s", editForm.Code, editForm.Body.String())
|
||||
}
|
||||
|
||||
updateForm := werkzeugForm()
|
||||
updateForm.Set("name", "ChatGPT Enterprise (eigene Version)")
|
||||
updateResp := postForm(t, s, adminCookie, "/verwaltung/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 (eigene Version)" {
|
||||
t.Errorf("Name = %q nach Update, unerwartet", fs.werkzeuge[id].Name)
|
||||
}
|
||||
|
||||
deleteResp := postForm(t, s, adminCookie, "/verwaltung/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 eigenes werkzeug to be deleted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminCannotEditZentralesWerkzeugUeberMandantenRoute(t *testing.T) {
|
||||
fs := newFakeStore()
|
||||
s := newServer(t, fs)
|
||||
adminCookie := seedAccountWithRole(t, fs, "Test-Mandant", "admin@example.com", "admin")
|
||||
fs.werkzeuge["werkzeug-central"] = store.Werkzeug{ID: "werkzeug-central", Name: "ChatGPT Enterprise", Anbieter: "OpenAI"}
|
||||
|
||||
resp := getWithCookie(t, s, adminCookie, "/verwaltung/werkzeuge/werkzeug-central")
|
||||
if resp.Code != http.StatusNotFound {
|
||||
t.Fatalf("status = %d, want 404 for a central werkzeug via the tenant route", resp.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminCannotEditFremdesEigenesWerkzeug(t *testing.T) {
|
||||
fs := newFakeStore()
|
||||
s := newServer(t, fs)
|
||||
adminA := seedAccountWithRole(t, fs, "Mandant A", "admin-a@example.com", "admin")
|
||||
postForm(t, s, adminA, "/verwaltung/werkzeuge", werkzeugForm())
|
||||
adminAUser, err := fs.GetUserByEmail(context.Background(), "admin-a@example.com")
|
||||
if err != nil {
|
||||
t.Fatalf("GetUserByEmail: %v", err)
|
||||
}
|
||||
var id string
|
||||
for wid, w := range fs.werkzeuge {
|
||||
if w.AccountID != nil && *w.AccountID == adminAUser.AccountID {
|
||||
id = wid
|
||||
}
|
||||
}
|
||||
|
||||
adminB := seedAccountWithRole(t, fs, "Mandant B", "admin-b@example.com", "admin")
|
||||
resp := getWithCookie(t, s, adminB, "/verwaltung/werkzeuge/"+id)
|
||||
if resp.Code != http.StatusNotFound {
|
||||
t.Fatalf("status = %d, want 404 for a foreign account's eigenes werkzeug", resp.Code)
|
||||
}
|
||||
deleteResp := postForm(t, s, adminB, "/verwaltung/werkzeuge/"+id+"/loeschen", url.Values{})
|
||||
if deleteResp.Code != http.StatusNotFound {
|
||||
t.Fatalf("delete status = %d, want 404 for a foreign account's eigenes werkzeug", deleteResp.Code)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user