mirror of
https://github.com/supabase/supabase.git
synced 2026-10-16 22:59:11 +03:00
feat: add auth report
This commit is contained in:
1 parent
de385d38c9
commit
de04637d49
5 files changed
+147
-10
No files matched your search
@@ -33,9 +33,7 @@ export const DEFAULT_QUERY_PARAMS = {
|
||||
iso_timestamp_end: REPORTS_DATEPICKER_HELPERS[0].calcTo(),
|
||||
}
|
||||
|
||||
|
||||
export const PRESET_CONFIG : Record<Presets, PresetConfig> ={
|
||||
|
||||
export const PRESET_CONFIG: Record<Presets, PresetConfig> = {
|
||||
[Presets.API_OVERVIEW]: {
|
||||
title: '',
|
||||
sql: {
|
||||
@@ -97,7 +95,7 @@ ORDER BY
|
||||
},
|
||||
},
|
||||
[Presets.API_BOTS]: {
|
||||
title: "API Bots",
|
||||
title: 'API Bots',
|
||||
sql: {
|
||||
userAgents: `
|
||||
select
|
||||
@@ -117,7 +115,7 @@ order by
|
||||
count desc
|
||||
limit 12
|
||||
`,
|
||||
botScores:`
|
||||
botScores: `
|
||||
select
|
||||
h.cf_connecting_ip as ip,
|
||||
h.cf_ipcountry as country,
|
||||
@@ -143,10 +141,41 @@ group by
|
||||
order by
|
||||
bot_score desc
|
||||
limit 20
|
||||
|
||||
`
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
[Presets.AUTH]: {
|
||||
title: 'Auth',
|
||||
sql: {
|
||||
dailyActiveUsers: `
|
||||
select
|
||||
timestamp_trunc(timestamp, day) as timestamp,
|
||||
count(distinct json_extract(f.event_message, "$.user_id")) as count
|
||||
from gotrue_logs f
|
||||
cross join unnest(f.metadata) as m
|
||||
where json_extract(f.event_message, "$.user_id") is not null
|
||||
group by
|
||||
timestamp
|
||||
order by
|
||||
timestamp
|
||||
`,
|
||||
newUsers: `
|
||||
select
|
||||
TIMESTAMP_TRUNC(f.timestamp, DAY) as timestamp,
|
||||
count(id) as count
|
||||
from
|
||||
gotrue_logs f
|
||||
cross join unnest(f.metadata) as m
|
||||
where f.timestamp > "2022-11-20"
|
||||
and m.project = "tzljvicuuxegpzwuwife"
|
||||
and JSON_VALUE(f.event_message, "$.path") = "/signup"
|
||||
and JSON_VALUE(f.event_message, "$.auth_event.actor_id") is not null
|
||||
and JSON_VALUE(f.event_message, "$.auth_event.action") != "user_repeated_signup"
|
||||
group by
|
||||
timestamp
|
||||
`
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const DATETIME_FORMAT = 'MMM D, ha'
|
||||
@@ -1,6 +1,7 @@
|
||||
export enum Presets {
|
||||
API_OVERVIEW = 'overview',
|
||||
API_BOTS="api_bots"
|
||||
API_BOTS = 'api_bots',
|
||||
AUTH = 'auth',
|
||||
}
|
||||
|
||||
export interface PresetConfig {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { BarChart } from 'components/to-be-cleaned/Charts/ChartRenderer'
|
||||
import { DATETIME_FORMAT } from '../Reports.constants'
|
||||
import { ReportWidgetProps } from '../ReportWidget'
|
||||
|
||||
export const renderDailyActiveUsers = (
|
||||
props: ReportWidgetProps<{
|
||||
count: number
|
||||
timestamp: string
|
||||
}>
|
||||
) => {
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full flex-col">
|
||||
<BarChart
|
||||
data={props.data}
|
||||
attribute="count"
|
||||
label=""
|
||||
minimalHeader
|
||||
customDateFormat={DATETIME_FORMAT}
|
||||
noDataMessage={'No authenticated users during this time period'}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const renderNewUsers = (
|
||||
props: ReportWidgetProps<{
|
||||
count: number
|
||||
timestamp: string
|
||||
}>
|
||||
) => {
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full flex-col">
|
||||
<BarChart
|
||||
data={props.data}
|
||||
attribute="count"
|
||||
label=""
|
||||
minimalHeader
|
||||
customDateFormat={DATETIME_FORMAT}
|
||||
noDataMessage={'No new user signups during this time period'}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -34,6 +34,12 @@ export const generateReportsMenu = (project?: Project): ProductMenuGroup[] => {
|
||||
url: `/project/${ref}/reports/api-bots`,
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
name: 'Auth',
|
||||
key: 'auth',
|
||||
url: `/project/${ref}/reports/auth`,
|
||||
items: [],
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import { NextPageWithLayout } from 'types'
|
||||
import { Presets } from 'components/interfaces/Reports/Reports.types'
|
||||
import ReportsLayout from 'components/layouts/ReportsLayout/ReportsLayout'
|
||||
import { hooksFactory, usePresetReport } from 'components/interfaces/Reports/Reports.utils'
|
||||
import { PRESET_CONFIG } from 'components/interfaces/Reports/Reports.constants'
|
||||
import ReportWidget from 'components/interfaces/Reports/ReportWidget'
|
||||
import {
|
||||
renderDailyActiveUsers,
|
||||
renderNewUsers,
|
||||
} from 'components/interfaces/Reports/renderers/AuthRenderers'
|
||||
|
||||
export const ApiBotsPage: NextPageWithLayout = () => {
|
||||
const router = useRouter()
|
||||
const { ref } = router.query
|
||||
const config = PRESET_CONFIG[Presets.AUTH]
|
||||
const hooks = hooksFactory(ref as string, config)
|
||||
const [dailyActiveUsers, dailyActiveUsersHandlers] = hooks.dailyActiveUsers()
|
||||
const [newUsers, newUsersHandlers] = hooks.newUsers()
|
||||
const { isLoading, Layout } = usePresetReport(
|
||||
[dailyActiveUsers, newUsers],
|
||||
[dailyActiveUsersHandlers, newUsersHandlers]
|
||||
)
|
||||
return (
|
||||
<Layout title={config.title}>
|
||||
<div className="grid lg:grid-cols-4">
|
||||
<ReportWidget
|
||||
isLoading={isLoading}
|
||||
params={dailyActiveUsers.params}
|
||||
className="col-span-4 col-start-1"
|
||||
title="Daily Active Users"
|
||||
description="The daily count of active authenticated users"
|
||||
data={dailyActiveUsers.logData}
|
||||
renderer={renderDailyActiveUsers}
|
||||
/>
|
||||
<ReportWidget
|
||||
isLoading={isLoading}
|
||||
params={newUsers.params}
|
||||
className="col-span-4 col-start-1"
|
||||
title="Daily New Users"
|
||||
description="The daily count of new user signups"
|
||||
data={newUsers.logData}
|
||||
renderer={renderNewUsers}
|
||||
/>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
ApiBotsPage.getLayout = (page) => <ReportsLayout>{page}</ReportsLayout>
|
||||
|
||||
export default observer(ApiBotsPage)
|
||||
Reference in new issue
Block a user