import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useFlag, useParams } from 'common'
import { useEffect } from 'react'
import { useForm, useWatch } from 'react-hook-form'
import { toast } from 'sonner'
import { Button, Card, CardContent, CardFooter, Form, FormControl, FormField, Switch } from 'ui'
import { Admonition } from 'ui-patterns/Admonition'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import {
PageSection,
PageSectionContent,
PageSectionMeta,
PageSectionSummary,
PageSectionTitle,
} from 'ui-patterns/PageSection'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import * as z from 'zod'
import { AlertError } from '@/components/ui/AlertError'
import { InlineLink } from '@/components/ui/InlineLink'
import { useAuthConfigQuery } from '@/data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from '@/data/auth/auth-config-update-mutation'
import { pickLogsQueryBuilder } from '@/data/logs/logs-endpoint'
import { safeSql } from '@/data/logs/safe-analytics-sql'
import { useTablesQuery } from '@/data/tables/tables-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
const schema = z.object({
AUDIT_LOG_DISABLE_POSTGRES: z.boolean(),
})
const AUDIT_LOG_ENTRIES_TABLE = 'audit_log_entries'
const AUTH_AUDIT_LOGS_QUERY = safeSql`
select
cast(timestamp as datetime) as timestamp,
event_message,
metadata
from auth_audit_logs
limit 10
`
const AUTH_AUDIT_LOGS_QUERY_OTEL = safeSql`
select
timestamp,
event_message,
log_attributes
from logs
where source = 'auth_audit_logs'
order by timestamp desc
limit 10
`
export const AuditLogsForm = () => {
const { ref: projectRef } = useParams()
const useOtel = useFlag('otelLegacyLogs')
const { data: project } = useSelectedProjectQuery()
const authAuditLogsQuery = pickLogsQueryBuilder(
useOtel,
AUTH_AUDIT_LOGS_QUERY_OTEL,
AUTH_AUDIT_LOGS_QUERY
)
const authAuditLogsUrl = `/project/${projectRef}/logs/explorer?q=${encodeURIComponent(authAuditLogsQuery)}`
const { can: canUpdateConfig } = useAsyncCheckPermissions(
PermissionAction.UPDATE,
'custom_config_gotrue'
)
const { data: tables = [] } = useTablesQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
includeColumns: false,
schema: 'auth',
})
const auditLogTable = tables.find((x) => x.name === AUDIT_LOG_ENTRIES_TABLE)
const {
data: authConfig,
error: authConfigError,
isError,
isPending: isLoading,
} = useAuthConfigQuery({ projectRef })
const { mutate: updateAuthConfig, isPending: isUpdatingConfig } = useAuthConfigUpdateMutation({
onError: (error) => {
toast.error(`Failed to update audit logs: ${error?.message}`)
},
onSuccess: () => {
toast.success('Successfully updated audit logs settings')
},
})
const form = useForm({
resolver: zodResolver(schema),
defaultValues: { AUDIT_LOG_DISABLE_POSTGRES: false },
})
const { isDirty } = form.formState
const { AUDIT_LOG_DISABLE_POSTGRES: formValueDisablePostgres } = useWatch({
control: form.control,
})
const currentlyDisabled = authConfig?.AUDIT_LOG_DISABLE_POSTGRES ?? false
const isDisabling = !currentlyDisabled && formValueDisablePostgres
const onSubmitAuditLogs = (values: any) => {
if (!projectRef) return console.error('Project ref is required')
updateAuthConfig({ projectRef: projectRef, config: values })
}
useEffect(() => {
if (authConfig) {
form.reset({ AUDIT_LOG_DISABLE_POSTGRES: authConfig?.AUDIT_LOG_DISABLE_POSTGRES ?? false })
}
}, [authConfig])
if (isError) {
return (
{AUDIT_LOG_ENTRIES_TABLE}
{' '}
table if needed.
}
/>
)}