Files
David Camacho Cateura 1a483ab255 feat: Show all partner audit logs fields (#49305)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Changes to the audit logs UI

## What is the current behavior?

Partner related fields in the audit logs are not shown

## What is the new behavior?

- Shows all partner related fields in the audit logs
- Also uses the new fields to compute the user name



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Audit log entries now display partner names, installation IDs, user
emails, and user IDs when available.
* Partner identity and email are shown when standard actor details are
unavailable.
  * Partner names are consistently formatted for clearer display.
* Entries without partner information continue to display cleanly
without blank or confusing actor details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-20 14:39:38 +02:00

63 lines
2.4 KiB
TypeScript

import dayjs from 'dayjs'
import { DatePickerToFrom } from '@/components/interfaces/Settings/Logs/Logs.types'
import type { AuditLog } from '@/data/organizations/organization-audit-logs-query'
export function sortAuditLogs(logs: AuditLog[], descending: boolean): AuditLog[] {
return [...logs].sort((a, b) =>
descending ? b.timestamp - a.timestamp : a.timestamp - b.timestamp
)
}
export function filterByUsers(logs: AuditLog[], userIds: string[]): AuditLog[] {
if (userIds.length === 0) return logs
return logs.filter((log) => userIds.includes(log.actor.user_id ?? ''))
}
export function filterByProjects(logs: AuditLog[], projectRefs: string[]): AuditLog[] {
if (projectRefs.length === 0) return logs
return logs.filter((log) => projectRefs.includes(log.project_ref ?? ''))
}
// [Joshen] Mainly to handle if a single date is selected - currently just for Audit Logs as
// i'm on the fence if this logic should be within the DatePicker component itself
// e.g for Logs.DatePicker which uses this component, the component itself has its own time selection UI
// JFYI currentDate is just a parameter so that I can run tests for this
export const formatSelectedDateRange = (value: DatePickerToFrom) => {
const current = dayjs()
const from = dayjs(value.from)
.hour(current.hour())
.minute(current.minute())
.second(current.second())
const to = dayjs(value.to).hour(current.hour()).minute(current.minute()).second(current.second())
if (from.date() === to.date()) {
// [Joshen] If a single date is selected, we either set the "from" to start from 00:00
// or "to" to end at 23:59 depending on which date was selected
if (from.date() === current.date()) {
return {
from: from.set('hour', 0).set('minute', 0).set('second', 0).utc().toISOString(),
to: to.utc().toISOString(),
}
} else {
return {
from: from.utc().toISOString(),
to: to.set('hour', 23).set('minute', 59).set('second', 59).utc().toISOString(),
}
}
} else {
return { from: from.utc().toISOString(), to: to.utc().toISOString() }
}
}
export function formatPartnerIfExists(
partner: string | undefined,
partnerEmail: string | undefined
) {
if (!partner) return undefined
const capitalized = `${partner[0].toUpperCase()}${partner.slice(1).toLowerCase()}`
return partnerEmail ? `${partnerEmail} (${capitalized})` : capitalized
}