Domain validation. Filter domain from referrers.

This commit is contained in:
Mike Cao 2020-08-28 21:34:20 -07:00
parent a9765c7ea7
commit 5a4cde854a
13 changed files with 51 additions and 23 deletions

View File

@ -65,9 +65,9 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
const tableProps = {
...dataProps,
websiteDomain: data?.domain,
limit: 10,
onExpand: handleExpand,
websiteDomain: data?.domain,
};
const DetailsComponent = expand?.component;

View File

@ -8,7 +8,8 @@ import FormLayout, {
FormMessage,
FormRow,
} from 'components/layout/FormLayout';
import Checkbox from '../common/Checkbox';
import Checkbox from 'components/common/Checkbox';
import { DOMAIN_REGEX } from 'lib/constants';
const initialValues = {
name: '',
@ -24,6 +25,8 @@ const validate = ({ name, domain }) => {
}
if (!domain) {
errors.domain = 'Required';
} else if (!DOMAIN_REGEX.test(domain)) {
errors.domain = 'Invalid domain';
}
return errors;

View File

@ -14,6 +14,7 @@ export default function MetricsTable({
title,
metric,
websiteId,
websiteDomain,
startDate,
endDate,
type,
@ -47,6 +48,7 @@ export default function MetricsTable({
type,
start_at: +startDate,
end_at: +endDate,
domain: websiteDomain,
});
setData(data);

View File

@ -30,6 +30,7 @@ export default function Referrers({
metric="Views"
headerComponent={limit ? null : <FilterButtons selected={filter} onClick={setFilter} />}
websiteId={websiteId}
websiteDomain={websiteDomain}
startDate={startDate}
endDate={endDate}
limit={limit}

View File

@ -1,5 +1,7 @@
export const AUTH_COOKIE_NAME = 'umami.auth';
export const DOMAIN_REGEX = /(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/;
export const DESKTOP_SCREEN_WIDTH = 1920;
export const LAPTOP_SCREEN_WIDTH = 1024;
export const MOBILE_SCREEN_WIDTH = 479;

View File

@ -98,12 +98,6 @@ export function getDateArray(data, startDate, endDate, unit) {
function findData(t) {
const x = data.find(e => {
console.log(
new Date(e.t),
getLocalTime(new Date(e.t)),
getLocalTime(new Date(e.t)).getTime(),
normalize(new Date(t)).getTime(),
);
return getLocalTime(new Date(e.t)).getTime() === normalize(new Date(t)).getTime();
});

View File

@ -1,8 +1,8 @@
import firstBy from 'thenby';
import { BROWSERS, ISO_COUNTRIES, DEVICES } from './constants';
import { removeTrailingSlash } from './format';
import { removeTrailingSlash, getDomainName } from './url';
export const urlFilter = (data, { domain, raw }) => {
export const urlFilter = (data, { raw }) => {
const isValidUrl = url => {
return url !== '' && !url.startsWith('#');
};
@ -30,7 +30,7 @@ export const urlFilter = (data, { domain, raw }) => {
return obj;
}
const url = cleanUrl(x.startsWith('/') ? `http://${domain}${x}` : x);
const url = cleanUrl(`http://x${x}`);
if (url) {
if (!obj[url]) {
@ -49,7 +49,8 @@ export const urlFilter = (data, { domain, raw }) => {
};
export const refFilter = (data, { domain, domainOnly, raw }) => {
const regex = new RegExp(domain.startsWith('http') ? domain : `http[s]?://${domain}`);
const domainName = getDomainName(domain);
const regex = new RegExp(`http[s]?://${domainName}`);
const isValidRef = ref => {
return ref !== '' && !ref.startsWith('/') && !ref.startsWith('#');
@ -63,7 +64,7 @@ export const refFilter = (data, { domain, domainOnly, raw }) => {
try {
const { hostname, origin, pathname, searchParams, protocol } = new URL(url);
if (hostname === domain || regex.test(url)) {
if (hostname === domainName) {
return null;
}

View File

@ -62,7 +62,3 @@ export function formatLongNumber(value) {
return formatNumber(n);
}
export function removeTrailingSlash(url) {
return url.length > 1 && url.endsWith('/') ? url.slice(0, -1) : url;
}

View File

@ -347,9 +347,11 @@ export function getPageviews(
return Promise.resolve([]);
}
export function getRankings(website_id, start_at, end_at, type, table) {
export function getRankings(website_id, start_at, end_at, type, table, domain) {
const db = getDatabase();
const filter = domain ? `and ${type} not like '%${domain}%'` : '';
if (db === POSTGRESQL) {
return prisma.$queryRaw(
`
@ -357,6 +359,7 @@ export function getRankings(website_id, start_at, end_at, type, table) {
from ${table}
where website_id=$1
and created_at between $2 and $3
${filter}
group by 1
order by 2 desc
`,
@ -373,6 +376,7 @@ export function getRankings(website_id, start_at, end_at, type, table) {
from ${table}
where website_id=?
and created_at between ? and ?
${filter}
group by 1
order by 2 desc
`,

11
lib/url.js Normal file
View File

@ -0,0 +1,11 @@
export function removeTrailingSlash(url) {
return url.length > 1 && url.endsWith('/') ? url.slice(0, -1) : url;
}
export function getDomainName(str) {
try {
return new URL(str).hostname;
} catch {
return str;
}
}

View File

@ -1,6 +1,6 @@
{
"name": "umami",
"version": "0.17.0",
"version": "0.18.0",
"description": "A simple, fast, website analytics alternative to Google Analytics. ",
"author": "Mike Cao <mike@mikecao.com>",
"license": "MIT",
@ -25,11 +25,13 @@
},
"lint-staged": {
"**/*.js": [
"prettier --write"
"prettier --write",
"eslint"
],
"**/*.css": [
"stylelint --fix",
"prettier --write"
"prettier --write",
"eslint"
]
},
"husky": {

View File

@ -1,5 +1,6 @@
import { getRankings } from 'lib/queries';
import { ok, badRequest } from 'lib/response';
import { DOMAIN_REGEX } from '../../../../lib/constants';
const sessionColumns = ['browser', 'os', 'device', 'country'];
const pageviewColumns = ['url', 'referrer'];
@ -24,12 +25,18 @@ function getColumn(type) {
}
export default async (req, res) => {
const { id, type, start_at, end_at } = req.query;
const { id, type, start_at, end_at, domain } = req.query;
const websiteId = +id;
const startDate = new Date(+start_at);
const endDate = new Date(+end_at);
if (type !== 'event' && !sessionColumns.includes(type) && !pageviewColumns.includes(type)) {
if (
type !== 'event' &&
!sessionColumns.includes(type) &&
!pageviewColumns.includes(type) &&
domain &&
DOMAIN_REGEX.test(domain)
) {
return badRequest(res);
}
@ -39,6 +46,7 @@ export default async (req, res) => {
endDate,
getColumn(type),
getTable(type),
domain,
);
return ok(res, rankings);

View File

@ -73,6 +73,10 @@ create index pageview_session_id_idx on pageview(session_id);
create index pageview_website_id_created_at_idx on pageview(website_id, created_at);
create index pageview_website_id_session_id_created_at_idx on pageview(website_id, session_id, created_at);
-- test
create index pageview_created_at_session_id_website_id_idx on pageview(created_at, session_id, website_id);
create index pageview_created_at_website_id_session_id_idx on pageview(created_at, website_id, session_id);
create index event_created_at_idx on event(created_at);
create index event_website_id_idx on event(website_id);
create index event_session_id_idx on event(session_id);