package main import ( "fmt" "time" "kra/internal/service/dto" "gorm.io/gorm" ) func verifyAdminSurface(admin, viewer *apiClient, f *fixtures, db *gorm.DB, report *acceptanceReport) { for _, path := range []string{ "/live/admin/dashboard", "/live/admin/categories?pageSize=100", "/live/admin/rooms?pageSize=100", "/live/admin/gifts?pageSize=100", fmt.Sprintf("/live/admin/gifts/%d", f.GiftID), "/live/admin/sends?pageSize=100", "/live/admin/orders?pageSize=100", "/live/admin/users?pageSize=100", } { must(admin.call("GET", path, nil, nil)) check(viewer.call("GET", path, nil, nil) != nil, "client accessed %s", path) } must(admin.call("PUT", "/live/admin/rooms/sort", dto.LiveSortRequest{Values: map[uint]int{f.RoomID: 3, f.ReplayID: 4}}, nil)) must(admin.call("PUT", "/live/admin/gifts/sort", dto.LiveSortRequest{Values: map[uint]int{f.GiftID: 1}}, nil)) var room dto.LiveRoomResponse must(admin.call("GET", adminRoomPath(f.RoomID), nil, &room)) check(room.Sort == 3, "room sorting was not persisted") var settings dto.PlatformSetting must(newClient().call("GET", "/live/settings", nil, &settings)) check(settings.DiamondRateCents > 0, "diamond rate missing") must(admin.call("PUT", "/live/admin/settings", settings, nil)) before := wallet(db, f.Viewer.ID) path := fmt.Sprintf("/live/admin/users/%d", f.Viewer.ID) var account dto.AssetUserResponse must(admin.call("GET", path, nil, &account)) check(account.DiamondBalance == before.DiamondBalance, "admin asset balance differs from ledger") for _, operation := range []string{"increase", "decrease"} { must(admin.call("POST", path+"/balance", dto.AssetAdjustmentRequest{Type: operation, Amount: 5, Reason: "local acceptance adjustment"}, &account)) } check(wallet(db, f.Viewer.ID).DiamondBalance == before.DiamondBalance, "balanced manual adjustments changed wallet") check(viewer.call("POST", path+"/balance", dto.AssetAdjustmentRequest{Type: "increase", Amount: 5, Reason: "unauthorized adjustment"}, nil) != nil, "client adjusted their own wallet") passed(report, "all administration list/detail surfaces, sorting, settings and audited balance adjustment; clients denied administration access") } func verifyClientAccount(report *acceptanceReport) { client := newClient() username := fmt.Sprintf("accept_%d", time.Now().UnixMilli()) var registered dto.LiveClientAuthResponse must(client.call("POST", "/live/client/auth/register", dto.LiveClientRegisterRequest{ Username: username, Nickname: "Local viewer", Password: userPassword, ConfirmPassword: userPassword, }, ®istered)) check(registered.User != nil && registered.User.DiamondBalance == 100, "new account did not receive exactly 100 diamonds") client.token = registered.Token var profile dto.LiveClientAccountResponse must(client.call("PUT", "/live/client/me", dto.LiveClientProfileRequest{Nickname: "Updated viewer", Avatar: "/uploads/acceptance-cover.jpg"}, &profile)) check(profile.Nickname == "Updated viewer", "profile update not applied") var balance dto.LiveClientBalanceResponse must(client.call("GET", "/live/client/balance", nil, &balance)) check(balance.DiamondBalance == 100, "profile update changed wallet") check(client.call("PUT", "/live/client/me/password", dto.LiveClientPasswordRequest{ OldPassword: "WrongPassword!", NewPassword: "ChangedLocal_2026!", ConfirmPassword: "ChangedLocal_2026!", }, nil) != nil, "wrong previous password accepted") var changed dto.LiveClientAuthResponse must(client.call("PUT", "/live/client/me/password", dto.LiveClientPasswordRequest{ OldPassword: userPassword, NewPassword: "ChangedLocal_2026!", ConfirmPassword: "ChangedLocal_2026!", }, &changed)) check(changed.Token != "" && changed.Token != registered.Token, "password change did not rotate session") stale := newClient() stale.token = registered.Token check(stale.call("GET", "/live/client/me", nil, nil) != nil, "previous session remained valid after password change") client.token = changed.Token must(client.call("GET", "/live/client/me", nil, &profile)) must(client.call("POST", "/live/client/auth/logout", nil, nil)) check(client.call("GET", "/live/client/me", nil, nil) != nil, "logged-out session remained authorized") report.Records["accountLifecycleUserID"] = profile.UserID passed(report, "fresh registration grants 100 diamonds; profile/balance, password validation and rotation, expired session and logout") }