ADD CROSS DOMAIN SUPPORT

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-06-26 22:35:29 +02:00
parent a0c8199474
commit 41143ca5f8
26 changed files with 514 additions and 126 deletions

View File

@@ -15,14 +15,34 @@ export async function postEvent(
const ip = getClientIp(request)!;
const ua = request.headers['user-agent']!;
const origin = request.headers.origin!;
const salts = await getSalts();
const projectId = request.client?.projectId;
if (!projectId) {
reply.status(400).send('missing origin');
return;
}
const [salts, geo] = await Promise.all([getSalts(), parseIp(ip)]);
const currentDeviceId = generateDeviceId({
salt: salts.current,
origin: origin,
origin: projectId,
ip,
ua,
});
const previousDeviceId = generateDeviceId({
salt: salts.previous,
origin: projectId,
ip,
ua,
});
// TODO: Remove after 2024-09-26
const currentDeviceIdDeprecated = generateDeviceId({
salt: salts.current,
origin,
ip,
ua,
});
const previousDeviceIdDeprecated = generateDeviceId({
salt: salts.previous,
origin,
ip,
@@ -34,13 +54,15 @@ export async function postEvent(
payload: {
projectId: request.projectId,
headers: {
origin,
ua,
},
event: request.body,
geo: await parseIp(ip),
geo,
currentDeviceId,
previousDeviceId,
// TODO: Remove after 2024-09-26
currentDeviceIdDeprecated,
previousDeviceIdDeprecated,
},
});

View File

@@ -17,16 +17,15 @@ const eventRouter: FastifyPluginCallback = (fastify, opts, done) => {
reply
) => {
try {
const projectId = await validateSdkRequest(req.headers).catch(
(error) => {
logger.error(error, 'Failed to validate sdk request');
return null;
}
);
if (!projectId) {
const client = await validateSdkRequest(req.headers).catch((error) => {
logger.error(error, 'Failed to validate sdk request');
return null;
});
if (!client?.projectId) {
return reply.status(401).send();
}
req.projectId = projectId;
req.projectId = client.projectId;
req.client = client;
const bot = req.headers['user-agent']
? isBot(req.headers['user-agent'])
@@ -37,7 +36,7 @@ const eventRouter: FastifyPluginCallback = (fastify, opts, done) => {
req.body?.properties?.path) as string | undefined;
await createBotEvent({
...bot,
projectId,
projectId: client.projectId,
path: path ?? '',
createdAt: new Date(req.body?.timestamp),
});

View File

@@ -7,24 +7,25 @@ import type { FastifyPluginCallback } from 'fastify';
const eventRouter: FastifyPluginCallback = (fastify, opts, done) => {
fastify.addHook('preHandler', async (req, reply) => {
try {
const projectId = await validateSdkRequest(req.headers).catch((error) => {
const client = await validateSdkRequest(req.headers).catch((error) => {
logger.error(error, 'Failed to validate sdk request');
return null;
});
if (!projectId) {
if (!client?.projectId) {
return reply.status(401).send();
}
req.projectId = projectId;
req.projectId = client.projectId;
req.client = client;
const bot = req.headers['user-agent']
? isBot(req.headers['user-agent'])
: null;
if (bot) {
reply.log.warn({ ...req.headers, bot }, 'Bot detected (profile)');
reply.status(202).send('OK');
return reply.status(202).send('OK');
}
} catch (e) {
logger.error(e, 'Failed to create bot event');
reply.status(401).send();
return;
}

View File

@@ -2,7 +2,7 @@ import type { RawRequestDefaultExpression } from 'fastify';
import jwt from 'jsonwebtoken';
import { verifyPassword } from '@openpanel/common';
import type { IServiceClient } from '@openpanel/db';
import type { Client, IServiceClient } from '@openpanel/db';
import { ClientType, db } from '@openpanel/db';
import { logger } from './logger';
@@ -36,7 +36,7 @@ class SdkAuthError extends Error {
export async function validateSdkRequest(
headers: RawRequestDefaultExpression['headers']
): Promise<string> {
): Promise<Client> {
const clientIdNew = headers['openpanel-client-id'] as string;
const clientIdOld = headers['mixan-client-id'] as string;
const clientSecretNew = headers['openpanel-client-secret'] as string;
@@ -83,17 +83,17 @@ export async function validateSdkRequest(
});
if (domainAllowed) {
return client.projectId;
return client;
}
if (client.cors === '*' && origin) {
return client.projectId;
return client;
}
}
if (client.secret && clientSecret) {
if (await verifyPassword(clientSecret, client.secret)) {
return client.projectId;
return client;
}
}