mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-22 09:13:37 +01:00
Added CORS middleware. Updated umami script.
This commit is contained in:
parent
bb04015b46
commit
58a1c63407
20
lib/middleware.js
Normal file
20
lib/middleware.js
Normal file
@ -0,0 +1,20 @@
|
||||
import cors from 'cors';
|
||||
|
||||
export function use(middleware) {
|
||||
return (req, res) =>
|
||||
new Promise((resolve, reject) => {
|
||||
middleware(req, res, result => {
|
||||
if (result instanceof Error) {
|
||||
return reject(result);
|
||||
}
|
||||
return resolve(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const allowPost = use(
|
||||
cors({
|
||||
origin: '*',
|
||||
methods: ['POST', 'OPTIONS'],
|
||||
}),
|
||||
);
|
75
lib/utils.js
75
lib/utils.js
@ -61,48 +61,55 @@ export async function getCountry(req, ip) {
|
||||
}
|
||||
|
||||
export async function parseSessionRequest(req) {
|
||||
const ip = getIpAddress(req);
|
||||
const { website_id, screen, language } = req.body;
|
||||
const { userAgent, browser, os } = getDevice(req);
|
||||
const country = await getCountry(req, ip);
|
||||
const session_id = hash(`${website_id}${ip}${userAgent}${os}`);
|
||||
if (req.method === 'POST') {
|
||||
const ip = getIpAddress(req);
|
||||
const { website_id, hostname, screen, language } = req.body;
|
||||
const { userAgent, browser, os } = getDevice(req);
|
||||
const country = await getCountry(req, ip);
|
||||
const session_id = hash(`${website_id}${hostname}${ip}${userAgent}${os}`);
|
||||
|
||||
return {
|
||||
website_id,
|
||||
session_id,
|
||||
browser,
|
||||
os,
|
||||
screen,
|
||||
language,
|
||||
country,
|
||||
};
|
||||
return {
|
||||
website_id,
|
||||
session_id,
|
||||
hostname,
|
||||
browser,
|
||||
os,
|
||||
screen,
|
||||
language,
|
||||
country,
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
export function parseCollectRequest(req) {
|
||||
const { type, payload } = req.body;
|
||||
if (req.method === 'POST') {
|
||||
const { type, payload } = req.body;
|
||||
|
||||
if (payload.session) {
|
||||
const {
|
||||
url,
|
||||
referrer,
|
||||
session: { website_id, session_id, time, hash: validationHash },
|
||||
} = payload;
|
||||
|
||||
if (
|
||||
validHash(website_id) &&
|
||||
validHash(session_id) &&
|
||||
validHash(validationHash) &&
|
||||
hash(`${website_id}${session_id}${time}`) === validationHash
|
||||
) {
|
||||
return {
|
||||
valid: true,
|
||||
type,
|
||||
session_id,
|
||||
if (payload.session) {
|
||||
const {
|
||||
url,
|
||||
referrer,
|
||||
};
|
||||
session: { website_id, session_id, time, hash: validationHash },
|
||||
} = payload;
|
||||
|
||||
if (
|
||||
validHash(website_id) &&
|
||||
validHash(session_id) &&
|
||||
validHash(validationHash) &&
|
||||
hash(`${website_id}${session_id}${time}`) === validationHash
|
||||
) {
|
||||
return {
|
||||
success: 1,
|
||||
type,
|
||||
session_id,
|
||||
url,
|
||||
referrer,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: false };
|
||||
return { success: 0 };
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
"@prisma/client": "2.2.2",
|
||||
"chart.js": "^2.9.3",
|
||||
"classnames": "^2.2.6",
|
||||
"cors": "^2.8.5",
|
||||
"date-fns": "^2.14.0",
|
||||
"detect-browser": "^5.1.1",
|
||||
"dotenv": "^8.2.0",
|
||||
|
@ -1,18 +1,21 @@
|
||||
import { parseCollectRequest } from 'lib/utils';
|
||||
import { savePageView } from 'lib/db';
|
||||
import { allowPost } from 'lib/middleware';
|
||||
|
||||
export default async (req, res) => {
|
||||
await allowPost(req, res);
|
||||
|
||||
const values = parseCollectRequest(req);
|
||||
|
||||
if (values.valid) {
|
||||
if (values.success) {
|
||||
const { type, session_id, url, referrer } = values;
|
||||
|
||||
if (type === 'pageview') {
|
||||
await savePageView(session_id, url, referrer);
|
||||
await savePageView(session_id, url, referrer).catch(() => {
|
||||
values.success = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
|
||||
res.status(200).json({ status: values.valid });
|
||||
res.status(200).json({ success: values.success });
|
||||
};
|
||||
|
@ -1,11 +1,16 @@
|
||||
import { getWebsite, getSession, createSession } from 'lib/db';
|
||||
import { hash, parseSessionRequest } from 'lib/utils';
|
||||
import { allowPost } from 'lib/middleware';
|
||||
|
||||
export default async (req, res) => {
|
||||
let result = { time: Date.now() };
|
||||
await allowPost(req, res);
|
||||
|
||||
let result = { success: 0, time: Date.now() };
|
||||
|
||||
const {
|
||||
website_id,
|
||||
session_id,
|
||||
hostname,
|
||||
browser,
|
||||
os,
|
||||
screen,
|
||||
@ -13,24 +18,32 @@ export default async (req, res) => {
|
||||
country,
|
||||
} = await parseSessionRequest(req);
|
||||
|
||||
const website = await getWebsite(website_id);
|
||||
if (website_id && session_id) {
|
||||
const website = await getWebsite(website_id);
|
||||
|
||||
if (website) {
|
||||
const session = await getSession(session_id);
|
||||
if (website) {
|
||||
const session = await getSession(session_id);
|
||||
|
||||
if (!session) {
|
||||
await createSession(website_id, session_id, { browser, os, screen, language, country });
|
||||
if (!session) {
|
||||
await createSession(website_id, session_id, {
|
||||
hostname,
|
||||
browser,
|
||||
os,
|
||||
screen,
|
||||
language,
|
||||
country,
|
||||
});
|
||||
}
|
||||
|
||||
result = {
|
||||
...result,
|
||||
success: 1,
|
||||
session_id,
|
||||
website_id,
|
||||
hash: hash(`${website_id}${session_id}${result.time}`),
|
||||
};
|
||||
}
|
||||
|
||||
result = {
|
||||
...result,
|
||||
session_id,
|
||||
website_id,
|
||||
hash: hash(`${website_id}${session_id}${result.time}`),
|
||||
};
|
||||
}
|
||||
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
|
||||
res.status(200).json(result);
|
||||
};
|
||||
|
@ -34,6 +34,7 @@ model session {
|
||||
browser String?
|
||||
country String?
|
||||
created_at DateTime? @default(now())
|
||||
hostname String?
|
||||
language String?
|
||||
os String?
|
||||
screen String?
|
||||
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
@ -11,16 +11,37 @@ const {
|
||||
document,
|
||||
} = window;
|
||||
|
||||
function post(url, params) {
|
||||
return fetch(url, {
|
||||
const post = (url, params) =>
|
||||
fetch(url, {
|
||||
method: 'post',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: params,
|
||||
body: JSON.stringify(params),
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
const createSession = data =>
|
||||
post(`${HOST_URL}/api/session`, data).then(({ success, ...session }) => {
|
||||
if (success) {
|
||||
store.setItem(SESSION_VAR, JSON.stringify(session));
|
||||
return success;
|
||||
}
|
||||
});
|
||||
|
||||
const getSession = () => JSON.parse(store.getItem(SESSION_VAR));
|
||||
|
||||
const pageView = (url, referrer) =>
|
||||
post(`${HOST_URL}/api/collect`, {
|
||||
type: 'pageview',
|
||||
payload: { url, referrer, session: getSession() },
|
||||
}).then(({ success }) => {
|
||||
if (!success) {
|
||||
store.removeItem(SESSION_VAR);
|
||||
}
|
||||
return success;
|
||||
});
|
||||
|
||||
const script = document.querySelector('script[data-website-id]');
|
||||
|
||||
@ -31,26 +52,12 @@ if (script) {
|
||||
const referrer = document.referrer;
|
||||
const screen = `${width}x${height}`;
|
||||
const url = `${pathname}${search}`;
|
||||
const data = { website_id, hostname, url, screen, language };
|
||||
|
||||
if (!store.getItem(SESSION_VAR)) {
|
||||
post(`${HOST_URL}/api/session`, {
|
||||
website_id,
|
||||
hostname,
|
||||
url,
|
||||
screen,
|
||||
language,
|
||||
}).then(session => {
|
||||
store.setItem(SESSION_VAR, JSON.stringify(session));
|
||||
});
|
||||
createSession(data).then(success => success && pageView(url, referrer));
|
||||
} else {
|
||||
pageView(url, referrer).then(success => !success && createSession(data));
|
||||
}
|
||||
|
||||
post(`${HOST_URL}/api/collect`, {
|
||||
type: 'pageview',
|
||||
payload: { url, referrer, session: JSON.parse(store.getItem(SESSION_VAR)) },
|
||||
}).then(response => {
|
||||
if (!response.status) {
|
||||
store.removeItem(SESSION_VAR);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
create table website (
|
||||
website_id uuid primary key,
|
||||
hostname varchar(255) unique not null,
|
||||
hostname varchar(100) unique not null,
|
||||
created_at timestamp with time zone default current_timestamp
|
||||
);
|
||||
|
||||
@ -8,6 +8,7 @@ create table session (
|
||||
session_id uuid primary key,
|
||||
website_id uuid references website(website_id) on delete cascade,
|
||||
created_at timestamp with time zone default current_timestamp,
|
||||
hostname varchar(100),
|
||||
browser varchar(20),
|
||||
os varchar(20),
|
||||
screen varchar(11),
|
||||
|
15
yarn.lock
15
yarn.lock
@ -2619,6 +2619,14 @@ core-util-is@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cors@^2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
|
||||
dependencies:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
cosmiconfig@^5.0.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||
@ -5513,7 +5521,7 @@ num2fraction@^1.2.2:
|
||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||
integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
@ -8386,6 +8394,11 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vary@^1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
|
||||
|
||||
vendors@^1.0.0:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
|
||||
|
Loading…
Reference in New Issue
Block a user