Merge branch 'dev' into analytics

This commit is contained in:
Mike Cao 2023-08-31 10:13:57 -07:00
commit e3bf3e5dc2
4 changed files with 70 additions and 67 deletions

View file

@ -12,8 +12,8 @@ RUN yarn install --frozen-lockfile
FROM node:18-alpine AS builder FROM node:18-alpine AS builder
WORKDIR /app WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/node_modules ./node_modules
COPY docker/middleware.js .
COPY . . COPY . .
COPY docker/middleware.js ./src
ARG DATABASE_TYPE ARG DATABASE_TYPE
ARG BASE_PATH ARG BASE_PATH

View file

@ -1,4 +1,5 @@
import { useEffect, useCallback, useState } from 'react'; import { useEffect, useCallback, useState } from 'react';
import { createPortal } from 'react-dom';
import { Button, Row, Column } from 'react-basics'; import { Button, Row, Column } from 'react-basics';
import { setItem } from 'next-basics'; import { setItem } from 'next-basics';
import useStore, { checkVersion } from 'store/version'; import useStore, { checkVersion } from 'store/version';
@ -44,7 +45,7 @@ export function UpdateNotice({ user, config }) {
return null; return null;
} }
return ( return createPortal(
<Row className={styles.notice}> <Row className={styles.notice}>
<Column variant="two" className={styles.message}> <Column variant="two" className={styles.message}>
{formatMessage(messages.newVersionAvailable, { version: `v${latest}` })} {formatMessage(messages.newVersionAvailable, { version: `v${latest}` })}
@ -55,7 +56,8 @@ export function UpdateNotice({ user, config }) {
</Button> </Button>
<Button onClick={handleDismissClick}>{formatMessage(labels.dismiss)}</Button> <Button onClick={handleDismissClick}>{formatMessage(labels.dismiss)}</Button>
</Column> </Column>
</Row> </Row>,
document.body,
); );
} }

View file

@ -2,13 +2,14 @@
position: absolute; position: absolute;
max-width: 800px; max-width: 800px;
gap: 20px; gap: 20px;
margin: 20px auto; margin: 80px auto;
justify-self: center; align-self: center;
background: var(--base50); background: var(--base50);
padding: 20px; padding: 20px;
border: 1px solid var(--base300); border: 1px solid var(--base300);
border-radius: var(--border-radius); border-radius: var(--border-radius);
z-index: var(--z-index-popup); z-index: var(--z-index-popup);
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1);
} }
.message { .message {

View file

@ -7,7 +7,7 @@ import { getIpAddress } from 'lib/detect';
import { useCors, useSession, useValidate } from 'lib/middleware'; import { useCors, useSession, useValidate } from 'lib/middleware';
import { CollectionType, YupRequest } from 'lib/types'; import { CollectionType, YupRequest } from 'lib/types';
import { NextApiRequest, NextApiResponse } from 'next'; 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 { saveEvent, saveSessionData } from 'queries';
import * as yup from 'yup'; import * as yup from 'yup';
@ -73,75 +73,75 @@ const schema = {
export default async (req: NextApiRequestCollect, res: NextApiResponse) => { export default async (req: NextApiRequestCollect, res: NextApiResponse) => {
await useCors(req, res); await useCors(req, res);
if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) { if (req.method === 'POST') {
return ok(res); if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) {
} return ok(res);
const { type, payload } = req.body;
if (!type || !payload) {
return badRequest(res);
}
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 (referrerPath?.startsWith('http')) { const { type, payload } = req.body;
const refUrl = new URL(referrer);
referrerPath = refUrl.pathname; req.yup = schema;
referrerQuery = refUrl.search.substring(1); await useValidate(req, res);
referrerDomain = refUrl.hostname.replace(/www\./, '');
if (await hasBlockedIp(req)) {
return forbidden(res);
} }
if (process.env.REMOVE_TRAILING_SLASH) { const { url, referrer, name: eventName, data: eventData, title: pageTitle } = payload;
urlPath = urlPath.replace(/.+\/$/, '');
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({ if (type === COLLECTION_TYPE.identify) {
urlPath, if (!eventData) {
urlQuery, return badRequest(res, 'Data required.');
referrerPath, }
referrerQuery,
referrerDomain, await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id });
pageTitle, }
eventName,
eventData, const token = createToken(session, secret());
...session,
sessionId: session.id, return send(res, token);
});
} }
if (type === COLLECTION_TYPE.identify) { return methodNotAllowed(res);
if (!eventData) {
return badRequest(res, 'Data required.');
}
await saveSessionData({ ...session, sessionData: eventData, sessionId: session.id });
}
const token = createToken(session, secret());
return send(res, token);
}; };
async function hasBlockedIp(req: NextApiRequestCollect) { async function hasBlockedIp(req: NextApiRequestCollect) {