test(19.6.1-03): last-superuser race, lifecycle, revocation, seam and roles tests
- TestAdministratorsLastSuperuser (D-09): A and B reduce each other on the five paths while a test transaction holds the guard's advisory lock until pg_locks shows both requests waiting; one succeeds, one gets last_superuser - TestAdministratorsLastSuperuserConcurrent: ten unsynchronized rounds - TestAdministratorsLifecycle (D-10) and TestAdministratorsRevocation (D-12), two-row bulk selections included - TestActionExtensionBoot (-short) and TestActionExtensionRun (D-14, D-15) - TestRolesLifecycle (D-16, D-17), TestRolesPermissionCeiling (D-07) - TestBackendScreensActivation (-short, D-01, D-04)
This commit is contained in:
63
modules/cabana/action_extensions_postgres_test.go
Normal file
63
modules/cabana/action_extensions_postgres_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package cabana_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"git.golem15.com/golem15/summercms/modules/cabana"
|
||||
)
|
||||
|
||||
// TestActionExtensionRun (D-14, D-15): a contributed record action on the
|
||||
// Administrators screen is offered and runs only for principals holding both
|
||||
// the screen's and the action's permissions, answers 409 once it no longer
|
||||
// applies, and runs in the row-locked transaction with the record.
|
||||
func TestActionExtensionRun(t *testing.T) {
|
||||
env := newScreensEnv(t)
|
||||
both := env.seedAdmin(t, adminSeed{Name: "ext-both", RolePermissions: map[string]int{cabana.PermissionManageUsers: 1, pingPermission: 1}})
|
||||
bothToken := env.login(t, both.Login)
|
||||
screenOnly := env.seedAdmin(t, adminSeed{Name: "ext-screen", RolePermissions: manageUsers})
|
||||
screenToken := env.login(t, screenOnly.Login)
|
||||
actionOnly := env.seedAdmin(t, adminSeed{Name: "ext-action", RolePermissions: map[string]int{pingPermission: 1}})
|
||||
actionToken := env.login(t, actionOnly.Login)
|
||||
target := env.seedAdmin(t, adminSeed{Name: "ext-target"})
|
||||
ping := userURL(target.ID, "actions", "acme_ping")
|
||||
|
||||
names := recordActionNames(env.expect(t, http.StatusOK, http.MethodGet, userURL(target.ID), bothToken, nil))
|
||||
if len(names) == 0 || names[len(names)-1] != "acme_ping" || names[0] != "deactivate" {
|
||||
t.Fatalf("offered to the holder of both = %v, want the owner's actions then acme_ping", names)
|
||||
}
|
||||
if names := recordActionNames(env.expect(t, http.StatusOK, http.MethodGet, userURL(target.ID), screenToken, nil)); containsName(names, "acme_ping") {
|
||||
t.Fatalf("offered without %s = %v", pingPermission, names)
|
||||
}
|
||||
env.expectRefusal(t, http.StatusForbidden, http.MethodPost, ping, screenToken, map[string]any{}, "")
|
||||
env.expectRefusal(t, http.StatusForbidden, http.MethodGet, userURL(target.ID), actionToken, nil, "")
|
||||
env.expectRefusal(t, http.StatusForbidden, http.MethodPost, ping, actionToken, map[string]any{}, "")
|
||||
if runs, _ := env.spy.runs(); len(runs) != 0 {
|
||||
t.Fatalf("refused requests ran the action: %v", runs)
|
||||
}
|
||||
|
||||
// Shown while it applies, then Applies turns false before the POST.
|
||||
env.spy.refuse.Store(true)
|
||||
if rec := env.call(t, http.MethodPost, ping, bothToken, map[string]any{}); rec.Code != http.StatusConflict {
|
||||
t.Fatalf("POST after Applies turned false status=%d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
if names := recordActionNames(env.expect(t, http.StatusOK, http.MethodGet, userURL(target.ID), bothToken, nil)); containsName(names, "acme_ping") {
|
||||
t.Fatalf("offered while it does not apply: %v", names)
|
||||
}
|
||||
env.spy.refuse.Store(false)
|
||||
if runs, _ := env.spy.runs(); len(runs) != 0 {
|
||||
t.Fatalf("a 409 ran the action: %v", runs)
|
||||
}
|
||||
|
||||
result := dataOf(env.expect(t, http.StatusOK, http.MethodPost, ping, bothToken, map[string]any{}))
|
||||
if result["message"] != "Pinged" {
|
||||
t.Fatalf("result = %v", result)
|
||||
}
|
||||
runs, withTx := env.spy.runs()
|
||||
if len(runs) != 1 || runs[0] != uint64(target.ID) || !withTx[0] {
|
||||
t.Fatalf("runs = %v tx = %v, want one run on %d inside the transaction", runs, withTx, target.ID)
|
||||
}
|
||||
// A record the screen hides is not found for the action either.
|
||||
hidden := env.seedAdmin(t, adminSeed{Name: "ext-hidden", Superuser: true})
|
||||
env.expectRefusal(t, http.StatusNotFound, http.MethodPost, userURL(hidden.ID, "actions", "acme_ping"), bothToken, map[string]any{}, "")
|
||||
}
|
||||
Reference in New Issue
Block a user