mirror of
https://github.com/umami-software/umami.git
synced 2026-02-06 13:47:15 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
6bd9916310
161 changed files with 4117 additions and 1753 deletions
|
|
@ -2,21 +2,19 @@ import { NextApiRequest, NextApiResponse } from 'next';
|
|||
import { ok, methodNotAllowed } from 'next-basics';
|
||||
|
||||
export interface ConfigResponse {
|
||||
basePath: string;
|
||||
trackerScriptName: string;
|
||||
updatesDisabled: boolean;
|
||||
telemetryDisabled: boolean;
|
||||
cloudMode: boolean;
|
||||
trackerScriptName: string;
|
||||
uiDisabled: boolean;
|
||||
updatesDisabled: boolean;
|
||||
}
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse<ConfigResponse>) => {
|
||||
if (req.method === 'GET') {
|
||||
return ok(res, {
|
||||
basePath: process.env.BASE_PATH || '',
|
||||
trackerScriptName: process.env.TRACKER_SCRIPT_NAME,
|
||||
updatesDisabled: !!process.env.DISABLE_UPDATES,
|
||||
telemetryDisabled: !!process.env.DISABLE_TELEMETRY,
|
||||
cloudMode: !!process.env.CLOUD_MODE,
|
||||
trackerScriptName: process.env.TRACKER_SCRIPT_NAME,
|
||||
uiDisabled: !!process.env.DISABLE_UI,
|
||||
updatesDisabled: !!process.env.DISABLE_UPDATES,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export interface UserPasswordRequestBody {
|
|||
|
||||
const schema = {
|
||||
POST: yup.object().shape({
|
||||
id: yup.string().uuid().required(),
|
||||
currentPassword: yup.string().required(),
|
||||
newPassword: yup.string().min(8).required(),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ import ipaddr from 'ipaddr.js';
|
|||
import isbot from 'isbot';
|
||||
import { COLLECTION_TYPE, HOSTNAME_REGEX } from 'lib/constants';
|
||||
import { secret } from 'lib/crypto';
|
||||
import { getIpAddress, getJsonBody } from 'lib/detect';
|
||||
import { getIpAddress } from 'lib/detect';
|
||||
import { useCors, useSession, useValidate } from 'lib/middleware';
|
||||
import { CollectionType, YupRequest } from 'lib/types';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { badRequest, createToken, forbidden, ok, send } from 'next-basics';
|
||||
import { badRequest, createToken, forbidden, methodNotAllowed, ok, send } from 'next-basics';
|
||||
import { saveEvent, saveSessionData } from 'queries';
|
||||
import * as yup from 'yup';
|
||||
|
||||
|
|
@ -73,71 +73,75 @@ const schema = {
|
|||
export default async (req: NextApiRequestCollect, res: NextApiResponse) => {
|
||||
await useCors(req, res);
|
||||
|
||||
if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) {
|
||||
return ok(res);
|
||||
}
|
||||
|
||||
const { type, payload } = getJsonBody<CollectRequestBody>(req);
|
||||
|
||||
req.yup = schema;
|
||||
await useValidate(req, res);
|
||||
|
||||
if (await hasBlockedIp(req)) {
|
||||
return forbidden(res);
|
||||
}
|
||||
|
||||
const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload;
|
||||
|
||||
await useSession(req, res);
|
||||
|
||||
const session = req.session;
|
||||
|
||||
if (type === COLLECTION_TYPE.event) {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [urlPath, urlQuery] = url?.split('?') || [];
|
||||
let [referrerPath, referrerQuery] = referrer?.split('?') || [];
|
||||
let referrerDomain;
|
||||
|
||||
if (!urlPath) {
|
||||
urlPath = '/';
|
||||
if (req.method === 'POST') {
|
||||
if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) {
|
||||
return ok(res);
|
||||
}
|
||||
|
||||
if (referrerPath?.startsWith('http')) {
|
||||
const refUrl = new URL(referrer);
|
||||
referrerPath = refUrl.pathname;
|
||||
referrerQuery = refUrl.search.substring(1);
|
||||
referrerDomain = refUrl.hostname.replace(/www\./, '');
|
||||
const { type, payload } = req.body;
|
||||
|
||||
req.yup = schema;
|
||||
await useValidate(req, res);
|
||||
|
||||
if (await hasBlockedIp(req)) {
|
||||
return forbidden(res);
|
||||
}
|
||||
|
||||
if (process.env.REMOVE_TRAILING_SLASH) {
|
||||
urlPath = urlPath.replace(/.+\/$/, '');
|
||||
const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload;
|
||||
|
||||
await useSession(req, res);
|
||||
|
||||
const session = req.session;
|
||||
|
||||
if (type === COLLECTION_TYPE.event) {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [urlPath, urlQuery] = url?.split('?') || [];
|
||||
let [referrerPath, referrerQuery] = referrer?.split('?') || [];
|
||||
let referrerDomain;
|
||||
|
||||
if (!urlPath) {
|
||||
urlPath = '/';
|
||||
}
|
||||
|
||||
if (referrerPath?.startsWith('http')) {
|
||||
const refUrl = new URL(referrer);
|
||||
referrerPath = refUrl.pathname;
|
||||
referrerQuery = refUrl.search.substring(1);
|
||||
referrerDomain = refUrl.hostname.replace(/www\./, '');
|
||||
}
|
||||
|
||||
if (process.env.REMOVE_TRAILING_SLASH) {
|
||||
urlPath = urlPath.replace(/.+\/$/, '');
|
||||
}
|
||||
|
||||
await saveEvent({
|
||||
urlPath,
|
||||
urlQuery,
|
||||
referrerPath,
|
||||
referrerQuery,
|
||||
referrerDomain,
|
||||
pageTitle,
|
||||
eventName,
|
||||
eventData,
|
||||
...session,
|
||||
sessionId: session.id,
|
||||
});
|
||||
}
|
||||
|
||||
await saveEvent({
|
||||
urlPath,
|
||||
urlQuery,
|
||||
referrerPath,
|
||||
referrerQuery,
|
||||
referrerDomain,
|
||||
pageTitle,
|
||||
eventName,
|
||||
eventData,
|
||||
...session,
|
||||
sessionId: session.id,
|
||||
});
|
||||
if (type === COLLECTION_TYPE.identify) {
|
||||
if (!eventData) {
|
||||
return badRequest(res, 'Data required.');
|
||||
}
|
||||
|
||||
await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id });
|
||||
}
|
||||
|
||||
const token = createToken(session, secret());
|
||||
|
||||
return send(res, token);
|
||||
}
|
||||
|
||||
if (type === COLLECTION_TYPE.identify) {
|
||||
if (!eventData) {
|
||||
return badRequest(res, 'Data required.');
|
||||
}
|
||||
|
||||
await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id });
|
||||
}
|
||||
|
||||
const token = createToken(session, secret());
|
||||
|
||||
return send(res, token);
|
||||
return methodNotAllowed(res);
|
||||
};
|
||||
|
||||
async function hasBlockedIp(req: NextApiRequestCollect) {
|
||||
|
|
|
|||
17
src/pages/api/version.ts
Normal file
17
src/pages/api/version.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { ok, methodNotAllowed } from 'next-basics';
|
||||
import { CURRENT_VERSION } from 'lib/constants';
|
||||
|
||||
export interface VersionResponse {
|
||||
version: string;
|
||||
}
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse<VersionResponse>) => {
|
||||
if (req.method === 'GET') {
|
||||
return ok(res, {
|
||||
version: CURRENT_VERSION,
|
||||
});
|
||||
}
|
||||
|
||||
return methodNotAllowed(res);
|
||||
};
|
||||
|
|
@ -13,23 +13,26 @@ export interface WebsiteMetricsRequestQuery {
|
|||
type: string;
|
||||
startAt: number;
|
||||
endAt: number;
|
||||
url: string;
|
||||
referrer: string;
|
||||
title: string;
|
||||
query: string;
|
||||
event: string;
|
||||
os: string;
|
||||
browser: string;
|
||||
device: string;
|
||||
country: string;
|
||||
region: string;
|
||||
city: string;
|
||||
language: string;
|
||||
url?: string;
|
||||
referrer?: string;
|
||||
title?: string;
|
||||
query?: string;
|
||||
os?: string;
|
||||
browser?: string;
|
||||
device?: string;
|
||||
country?: string;
|
||||
region?: string;
|
||||
city?: string;
|
||||
language?: string;
|
||||
event?: string;
|
||||
}
|
||||
|
||||
const schema = {
|
||||
GET: yup.object().shape({
|
||||
id: yup.string().uuid().required(),
|
||||
type: yup.string().required(),
|
||||
startAt: yup.number().required(),
|
||||
endAt: yup.number().required(),
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
@ -50,7 +53,6 @@ export default async (
|
|||
referrer,
|
||||
title,
|
||||
query,
|
||||
event,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
|
|
@ -58,6 +60,7 @@ export default async (
|
|||
region,
|
||||
city,
|
||||
language,
|
||||
event,
|
||||
} = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
|
|
@ -74,7 +77,6 @@ export default async (
|
|||
referrer,
|
||||
title,
|
||||
query,
|
||||
event,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
|
|
@ -82,10 +84,9 @@ export default async (
|
|||
region,
|
||||
city,
|
||||
language,
|
||||
event,
|
||||
};
|
||||
|
||||
filters[type] = undefined;
|
||||
|
||||
const column = FILTER_COLUMNS[type] || type;
|
||||
|
||||
if (SESSION_COLUMNS.includes(type)) {
|
||||
|
|
|
|||
|
|
@ -42,8 +42,13 @@ export default async (
|
|||
} = req.auth;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
req.query.id = userId;
|
||||
req.query.pageSize = 100;
|
||||
if (!req.query.id) {
|
||||
req.query.id = userId;
|
||||
}
|
||||
|
||||
if (!req.query.pageSize) {
|
||||
req.query.pageSize = 100;
|
||||
}
|
||||
|
||||
return userWebsites(req as any, res);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue