diff --git a/server/auth_audit_test.go b/server/auth_audit_test.go index 5ea0890..0429dcc 100644 --- a/server/auth_audit_test.go +++ b/server/auth_audit_test.go @@ -100,6 +100,20 @@ func TestGroupMessageQuerySupportsOperationalFilters(t *testing.T) { } } +func TestLoginAuditQuerySpecsExposeUserIDAsString(t *testing.T) { + for label, spec := range map[string]*internalQuerySpec{ + "user-login-logs": internalTenantResourceSpecs["user-login-logs"], + "login-failure-logs": internalTenantResourceSpecs["login-failure-logs"], + } { + if spec == nil { + t.Fatalf("%s query spec missing", label) + } + if !strings.Contains(spec.Select, "CAST(user_id AS CHAR) AS user_id") { + t.Fatalf("%s query must expose 64-bit user IDs as strings: %s", label, spec.Select) + } + } +} + func TestUserQuerySupportsKeywordAndUserIDs(t *testing.T) { req := httptest.NewRequest("GET", "/?keyword=alice&user_ids=101,202&account_no=1000", nil) query, countQuery, args, _, _, err := buildInternalAdminListQuery(req, usersInternalQuerySpec(), "") diff --git a/server/internal_admin_query_resources.go b/server/internal_admin_query_resources.go index 65d724b..e4e9fdb 100644 --- a/server/internal_admin_query_resources.go +++ b/server/internal_admin_query_resources.go @@ -63,12 +63,12 @@ var internalTenantResourceSpecs = map[string]*internalQuerySpec{ "private-messages": privateMessagesInternalQuerySpec(), "group-messages": groupMessagesInternalQuerySpec(), "user-login-logs": { - Select: `SELECT id,user_id,username,account_type,account_mask,login_type,event_type,session_id,device_id,platform,app_version,ip,region,user_agent,risk_level,request_id,login_at,logout_at,metadata`, + Select: `SELECT id,CAST(user_id AS CHAR) AS user_id,username,account_type,account_mask,login_type,event_type,session_id,device_id,platform,app_version,ip,region,user_agent,risk_level,request_id,login_at,logout_at,metadata`, From: "FROM im_user_login_logs", DefaultSort: "ORDER BY id DESC", DetailKey: "id", Filters: []internalQueryFilter{{"user_id", "user_id", "=", "uid"}, {"account", "account_mask", "LIKE", "string"}, {"login_type", "login_type", "=", "string"}, {"event_type", "event_type", "=", "string"}, {"platform", "platform", "=", "string"}, {"ip", "ip", "LIKE", "string"}, {"login_at_start", "login_at", ">=", "time"}, {"login_at_end", "login_at", "<=", "time"}}, }, "login-failure-logs": { - Select: `SELECT id,user_id,account_type,account_mask,failure_type,reason,detail,ip,region,device_id,platform,app_version,user_agent,risk_level,risk_action,request_id,attempt_at,metadata`, + Select: `SELECT id,CAST(user_id AS CHAR) AS user_id,account_type,account_mask,failure_type,reason,detail,ip,region,device_id,platform,app_version,user_agent,risk_level,risk_action,request_id,attempt_at,metadata`, From: "FROM im_login_failure_logs", DefaultSort: "ORDER BY id DESC", DetailKey: "id", Filters: []internalQueryFilter{{"user_id", "user_id", "=", "uid"}, {"account", "account_mask", "LIKE", "string"}, {"failure_type", "failure_type", "=", "string"}, {"platform", "platform", "=", "string"}, {"ip", "ip", "LIKE", "string"}, {"attempt_at_start", "attempt_at", ">=", "time"}, {"attempt_at_end", "attempt_at", "<=", "time"}}, },