//go:build mysql // +build mysql package mysql import ( "strings" "testing" ) func TestEnsureIMAdminGovernanceTablesDefinesLoginAuditTenantScope(t *testing.T) { exec := &recordingGroupSchemaExecutor{} if err := ensureIMAdminGovernanceTables(exec); err != nil { t.Fatal(err) } if len(exec.statements) != 4 { t.Fatalf("executed %d admin governance schema statements, want 4", len(exec.statements)) } joined := strings.ToLower(strings.Join(exec.statements, "\n")) for _, table := range []string{"im_user_login_logs", "im_message_admin_actions", "im_user_ip_whitelists"} { if !strings.Contains(joined, table) { t.Fatalf("missing table %s", table) } } for _, table := range []string{"im_login_failure_logs", "im_login_lockouts"} { if strings.Contains(joined, table) { t.Fatalf("hot login state table must not be created: %s", table) } } if strings.Contains(joined, "tinode.") || strings.Contains(joined, "create database") { t.Fatalf("admin governance schema must use the active shared database: %s", joined) } start := strings.Index(joined, "create table if not exists im_user_login_logs") if start < 0 { t.Fatal("missing im_user_login_logs") } end := strings.Index(joined[start:], ") engine=") if end < 0 || !strings.Contains(joined[start:start+end], "tenant_id bigint not null") { t.Fatal("im_user_login_logs must declare tenant_id") } if !strings.Contains(joined, "idx_im_user_login_session_close(tenant_id, session_id, logout_at)") && !strings.Contains(joined, "idx_im_user_login_session_close(tenant_id,session_id,logout_at)") { t.Fatal("im_user_login_logs must index tenant-scoped session close updates") } }