mirror of
https://github.com/kremalicious/umami.git
synced 2024-06-30 13:41:50 +02:00
Add user usage.
This commit is contained in:
parent
c41fb5ee1b
commit
9e2a478001
74
pages/api/users/[id]/usage.ts
Normal file
74
pages/api/users/[id]/usage.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import { useAuth, useCors } from 'lib/middleware';
|
||||||
|
import { NextApiRequestQueryBody } from 'lib/types';
|
||||||
|
import { NextApiResponse } from 'next';
|
||||||
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
|
import { getEventDataUsage, getEventUsage, getUserWebsites } from 'queries';
|
||||||
|
|
||||||
|
export interface UserUsageRequestQuery {
|
||||||
|
id: string;
|
||||||
|
startAt: string;
|
||||||
|
endAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserUsageRequestResponse {
|
||||||
|
websiteEventUsage: number;
|
||||||
|
eventDataUsage: number;
|
||||||
|
websites: {
|
||||||
|
websiteEventUsage: number;
|
||||||
|
eventDataUsage: number;
|
||||||
|
websiteId: string;
|
||||||
|
websiteName: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async (
|
||||||
|
req: NextApiRequestQueryBody<UserUsageRequestQuery>,
|
||||||
|
res: NextApiResponse<UserUsageRequestResponse>,
|
||||||
|
) => {
|
||||||
|
await useCors(req, res);
|
||||||
|
await useAuth(req, res);
|
||||||
|
|
||||||
|
const { user } = req.auth;
|
||||||
|
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
if (!user.isAdmin) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id: userId, startAt, endAt } = req.query;
|
||||||
|
|
||||||
|
const startDate = new Date(+startAt);
|
||||||
|
const endDate = new Date(+endAt);
|
||||||
|
|
||||||
|
const websites = await getUserWebsites(userId);
|
||||||
|
|
||||||
|
const websiteIds = websites.map(a => a.id);
|
||||||
|
|
||||||
|
const websiteEventUsage = await getEventUsage(websiteIds, startDate, endDate);
|
||||||
|
const eventDataUsage = await getEventDataUsage(websiteIds, startDate, endDate);
|
||||||
|
|
||||||
|
const websiteUsage = websites.map(a => ({
|
||||||
|
websiteId: a.id,
|
||||||
|
websiteName: a.name,
|
||||||
|
websiteEventUsage: websiteEventUsage.find(b => a.id === b.websiteId)?.count || 0,
|
||||||
|
eventDataUsage: eventDataUsage.find(b => a.id === b.websiteId)?.count || 0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const usage = websiteUsage.reduce(
|
||||||
|
(acc, cv) => {
|
||||||
|
acc.websiteEventUsage += cv.websiteEventUsage;
|
||||||
|
acc.eventDataUsage += cv.eventDataUsage;
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ websiteEventUsage: 0, eventDataUsage: 0 },
|
||||||
|
);
|
||||||
|
|
||||||
|
return ok(res, {
|
||||||
|
...usage,
|
||||||
|
websites: websiteUsage,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodNotAllowed(res);
|
||||||
|
};
|
|
@ -4,14 +4,14 @@ import { NextApiResponse } from 'next';
|
||||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
import { getUserWebsites } from 'queries';
|
import { getUserWebsites } from 'queries';
|
||||||
|
|
||||||
export interface WebsitesRequestBody {
|
export interface UserWebsitesRequestBody {
|
||||||
name: string;
|
name: string;
|
||||||
domain: string;
|
domain: string;
|
||||||
shareId: string;
|
shareId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async (
|
export default async (
|
||||||
req: NextApiRequestQueryBody<any, WebsitesRequestBody>,
|
req: NextApiRequestQueryBody<any, UserWebsitesRequestBody>,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
) => {
|
) => {
|
||||||
await useCors(req, res);
|
await useCors(req, res);
|
||||||
|
|
32
queries/analytics/event/getEventUsage.ts
Normal file
32
queries/analytics/event/getEventUsage.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import clickhouse from 'lib/clickhouse';
|
||||||
|
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
|
||||||
|
|
||||||
|
export function getEventUsage(...args: [websiteIds: string[], startDate: Date, endDate: Date]) {
|
||||||
|
return runQuery({
|
||||||
|
[PRISMA]: () => relationalQuery(...args),
|
||||||
|
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function relationalQuery(websiteIds: string[], startDate: Date, endDate: Date) {
|
||||||
|
throw new Error('Not Implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickhouseQuery(websiteIds: string[], startDate: Date, endDate: Date) {
|
||||||
|
const { rawQuery } = clickhouse;
|
||||||
|
|
||||||
|
return rawQuery(
|
||||||
|
`select
|
||||||
|
website_id as websiteId,
|
||||||
|
count(*) as count
|
||||||
|
from website_event
|
||||||
|
where created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
|
and website_id in {websiteIds:Array(UUID)}
|
||||||
|
group by website_id`,
|
||||||
|
{
|
||||||
|
websiteIds,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
32
queries/analytics/eventData/getEventDataUsage.ts
Normal file
32
queries/analytics/eventData/getEventDataUsage.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import clickhouse from 'lib/clickhouse';
|
||||||
|
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
|
||||||
|
|
||||||
|
export function getEventDataUsage(...args: [websiteIds: string[], startDate: Date, endDate: Date]) {
|
||||||
|
return runQuery({
|
||||||
|
[PRISMA]: () => relationalQuery(...args),
|
||||||
|
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function relationalQuery(websiteIds: string[], startDate: Date, endDate: Date) {
|
||||||
|
throw new Error('Not Implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickhouseQuery(websiteIds: string[], startDate: Date, endDate: Date) {
|
||||||
|
const { rawQuery } = clickhouse;
|
||||||
|
|
||||||
|
return rawQuery(
|
||||||
|
`select
|
||||||
|
website_id as websiteId,
|
||||||
|
count(*) as count
|
||||||
|
from event_data
|
||||||
|
where created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
|
and website_id in {websiteIds:Array(UUID)}
|
||||||
|
group by website_id`,
|
||||||
|
{
|
||||||
|
websiteIds,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
|
@ -3,8 +3,10 @@ export * from './admin/teamUser';
|
||||||
export * from './admin/user';
|
export * from './admin/user';
|
||||||
export * from './admin/website';
|
export * from './admin/website';
|
||||||
export * from './analytics/event/getEventMetrics';
|
export * from './analytics/event/getEventMetrics';
|
||||||
|
export * from './analytics/event/getEventUsage';
|
||||||
export * from './analytics/event/getEvents';
|
export * from './analytics/event/getEvents';
|
||||||
export * from './analytics/eventData/getEventData';
|
export * from './analytics/eventData/getEventData';
|
||||||
|
export * from './analytics/eventData/getEventDataUsage';
|
||||||
export * from './analytics/event/saveEvent';
|
export * from './analytics/event/saveEvent';
|
||||||
export * from './analytics/pageview/getPageviewMetrics';
|
export * from './analytics/pageview/getPageviewMetrics';
|
||||||
export * from './analytics/pageview/getPageviewStats';
|
export * from './analytics/pageview/getPageviewStats';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user