mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19:05:06 +03:00
## 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? - Update to the audit log schema (changes were already applied in staging) - Updates the org & project audit log page to reflect the changes to the schema - The schema should be agnostic to whether logs were emitted to logflare with the old & new schema format - the backend adjusts old logs to the new format. ## What is the current behavior? Currently, the frontend is parsing the legacy schema as the backend returns this by default. It also doesn't show some of these new fields yet. ## What is the new behavior? ### Org Audit Logs - Table View <img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 27 22" src="https://github.com/user-attachments/assets/47fec068-1ffa-4e52-bc46-3bffdef55adb" /> ### Org Audit Logs - Single log View <img width="1842" height="1494" alt="CleanShot 2026-04-29 at 18 27 37" src="https://github.com/user-attachments/assets/3cff3bdf-4a6a-4981-acaa-7f95bb3ae9cf" /> Note that the `Target` field is no longer there. We just show the `metadata` JSON. <img width="1842" height="1494" alt="CleanShot 2026-04-29 at 18 27 40" src="https://github.com/user-attachments/assets/d2e681f0-41a6-4bc7-a3d7-ec7e8101616c" /> ### Account (Profile) Audit Logs - Table View <img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 25 20" src="https://github.com/user-attachments/assets/c72e19df-9b82-4611-8889-7af463769550" /> ### Account (Profile) Audit Logs - Single log View <img width="1810" height="1310" alt="CleanShot 2026-04-29 at 18 25 32" src="https://github.com/user-attachments/assets/46f8d3b6-4f2f-4944-b891-431a93e5f3c3" /> ## Additional context ⚠️ currently leaving the `do not merge` tag on, until: - [x] I have verified it works in staging - [x] We've deployed the new schema to production <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Audit logs now use the v2 format with microsecond-accurate timestamps, improved ordering, and a revamped details panel showing clearer actor/action/request/project/org fields and fallback labels. * Page/header layout updated so audit logs render at top level with adjusted spacing. * **Refactor** * Shared sorting and filtering utilities added for consistent user/project filtering and non-mutating log sorting. * **Tests** * Added tests for timestamp conversion, sorting, filtering, and date-range formatting. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
84 lines
2.3 KiB
TypeScript
84 lines
2.3 KiB
TypeScript
import dayjs from 'dayjs'
|
|
import { afterEach, describe, expect, test, vi } from 'vitest'
|
|
|
|
import { formatSelectedDateRange } from '@/components/interfaces/Organization/AuditLogs/AuditLogs.utils'
|
|
|
|
// Pin "now" to a fixed point so date comparisons are deterministic
|
|
const NOW = dayjs('2024-06-15T14:30:00')
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers()
|
|
})
|
|
|
|
function fakeNow() {
|
|
vi.setSystemTime(NOW.toDate())
|
|
}
|
|
|
|
describe('formatSelectedDateRange', () => {
|
|
test('two different dates: preserves current time on both ends', () => {
|
|
fakeNow()
|
|
const result = formatSelectedDateRange({
|
|
from: '2024-06-10',
|
|
to: '2024-06-14',
|
|
})
|
|
const from = dayjs(result.from)
|
|
const to = dayjs(result.to)
|
|
expect(from.date()).toBe(10)
|
|
expect(to.date()).toBe(14)
|
|
// Both should carry current H:M:S
|
|
expect(from.hour()).toBe(NOW.hour())
|
|
expect(to.hour()).toBe(NOW.hour())
|
|
})
|
|
|
|
test('single date matching today: from is set to 00:00:00', () => {
|
|
fakeNow()
|
|
const today = NOW.format('YYYY-MM-DD')
|
|
const result = formatSelectedDateRange({ from: today, to: today })
|
|
const from = dayjs(result.from)
|
|
expect(from.hour()).toBe(0)
|
|
expect(from.minute()).toBe(0)
|
|
expect(from.second()).toBe(0)
|
|
})
|
|
|
|
test('single date matching today: to keeps current time', () => {
|
|
fakeNow()
|
|
const today = NOW.format('YYYY-MM-DD')
|
|
const result = formatSelectedDateRange({ from: today, to: today })
|
|
const to = dayjs(result.to)
|
|
expect(to.hour()).toBe(NOW.hour())
|
|
expect(to.minute()).toBe(NOW.minute())
|
|
})
|
|
|
|
test('single date in the past: to is set to 23:59:59', () => {
|
|
fakeNow()
|
|
const result = formatSelectedDateRange({
|
|
from: '2024-06-01',
|
|
to: '2024-06-01',
|
|
})
|
|
const to = dayjs(result.to)
|
|
expect(to.hour()).toBe(23)
|
|
expect(to.minute()).toBe(59)
|
|
expect(to.second()).toBe(59)
|
|
})
|
|
|
|
test('single date in the past: from keeps current time', () => {
|
|
fakeNow()
|
|
const result = formatSelectedDateRange({
|
|
from: '2024-06-01',
|
|
to: '2024-06-01',
|
|
})
|
|
const from = dayjs(result.from)
|
|
expect(from.hour()).toBe(NOW.hour())
|
|
})
|
|
|
|
test('output is in UTC ISO format', () => {
|
|
fakeNow()
|
|
const result = formatSelectedDateRange({
|
|
from: '2024-06-10',
|
|
to: '2024-06-14',
|
|
})
|
|
expect(result.from).toMatch(/Z$/)
|
|
expect(result.to).toMatch(/Z$/)
|
|
})
|
|
})
|