mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 09:45:04 +01:00
Use next-basics package.
This commit is contained in:
parent
1a6af8fc41
commit
f4e0da481e
@ -4,7 +4,12 @@
|
|||||||
"es2020": true,
|
"es2020": true,
|
||||||
"node": true
|
"node": true
|
||||||
},
|
},
|
||||||
"extends": ["eslint:recommended", "plugin:prettier/recommended", "next"],
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:prettier/recommended",
|
||||||
|
"plugin:import/recommended",
|
||||||
|
"next"
|
||||||
|
],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"jsx": true
|
"jsx": true
|
||||||
@ -12,7 +17,27 @@
|
|||||||
"ecmaVersion": 11,
|
"ecmaVersion": 11,
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
|
"settings": {
|
||||||
|
"import/resolver": {
|
||||||
|
"alias": {
|
||||||
|
"map": [
|
||||||
|
["assets", "./assets"],
|
||||||
|
["components", "./components"],
|
||||||
|
["db", "./db"],
|
||||||
|
["hooks", "./hooks"],
|
||||||
|
["lang", "./lang"],
|
||||||
|
["lib", "./lib"],
|
||||||
|
["public", "./public"],
|
||||||
|
["queries", "./queries"],
|
||||||
|
["store", "./store"],
|
||||||
|
["styles", "./styles"]
|
||||||
|
],
|
||||||
|
"extensions": [".ts", ".js", ".jsx", ".json"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"no-console": "error",
|
||||||
"react/display-name": "off",
|
"react/display-name": "off",
|
||||||
"react/react-in-jsx-scope": "off",
|
"react/react-in-jsx-scope": "off",
|
||||||
"react/prop-types": "off",
|
"react/prop-types": "off",
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'next/link';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { safeDecodeURI } from 'next-basics';
|
||||||
import usePageQuery from 'hooks/usePageQuery';
|
import usePageQuery from 'hooks/usePageQuery';
|
||||||
import { safeDecodeURI } from 'lib/url';
|
|
||||||
import Icon from './Icon';
|
|
||||||
import External from 'assets/arrow-up-right-from-square.svg';
|
import External from 'assets/arrow-up-right-from-square.svg';
|
||||||
|
import Icon from './Icon';
|
||||||
import styles from './FilterLink.module.css';
|
import styles from './FilterLink.module.css';
|
||||||
|
|
||||||
export default function FilterLink({ id, value, label, externalUrl }) {
|
export default function FilterLink({ id, value, label, externalUrl }) {
|
||||||
@ -25,7 +25,7 @@ export default function FilterLink({ id, value, label, externalUrl }) {
|
|||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
{externalUrl && (
|
{externalUrl && (
|
||||||
<a href={externalUrl} target="_blank" rel="noreferrer noopener" className={styles.link}>
|
<a className={styles.link} href={externalUrl} target="_blank" rel="noreferrer noopener">
|
||||||
<Icon icon={<External />} className={styles.icon} />
|
<Icon icon={<External />} className={styles.icon} />
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import { setItem } from 'next-basics';
|
||||||
import ButtonLayout from 'components/layout/ButtonLayout';
|
import ButtonLayout from 'components/layout/ButtonLayout';
|
||||||
import useStore, { checkVersion } from 'store/version';
|
import useStore, { checkVersion } from 'store/version';
|
||||||
import { setItem } from 'lib/web';
|
|
||||||
import { REPO_URL, VERSION_CHECK } from 'lib/constants';
|
import { REPO_URL, VERSION_CHECK } from 'lib/constants';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
import styles from './UpdateNotice.module.css';
|
import styles from './UpdateNotice.module.css';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Formik, Form, Field } from 'formik';
|
import { Formik, Form, Field } from 'formik';
|
||||||
|
import { setItem } from 'next-basics';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import Button from 'components/common/Button';
|
import Button from 'components/common/Button';
|
||||||
import FormLayout, {
|
import FormLayout, {
|
||||||
@ -11,7 +12,6 @@ import FormLayout, {
|
|||||||
} from 'components/layout/FormLayout';
|
} from 'components/layout/FormLayout';
|
||||||
import Icon from 'components/common/Icon';
|
import Icon from 'components/common/Icon';
|
||||||
import useApi from 'hooks/useApi';
|
import useApi from 'hooks/useApi';
|
||||||
import { setItem } from 'lib/web';
|
|
||||||
import { AUTH_TOKEN } from 'lib/constants';
|
import { AUTH_TOKEN } from 'lib/constants';
|
||||||
import { setUser } from 'store/app';
|
import { setUser } from 'store/app';
|
||||||
import Logo from 'assets/logo.svg';
|
import Logo from 'assets/logo.svg';
|
||||||
|
@ -9,7 +9,7 @@ import HamburgerButton from 'components/common/HamburgerButton';
|
|||||||
import UpdateNotice from 'components/common/UpdateNotice';
|
import UpdateNotice from 'components/common/UpdateNotice';
|
||||||
import UserButton from 'components/settings/UserButton';
|
import UserButton from 'components/settings/UserButton';
|
||||||
import { HOMEPAGE_URL } from 'lib/constants';
|
import { HOMEPAGE_URL } from 'lib/constants';
|
||||||
import useConfig from '/hooks/useConfig';
|
import useConfig from 'hooks/useConfig';
|
||||||
import useUser from 'hooks/useUser';
|
import useUser from 'hooks/useUser';
|
||||||
import Logo from 'assets/logo.svg';
|
import Logo from 'assets/logo.svg';
|
||||||
import styles from './Header.module.css';
|
import styles from './Header.module.css';
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { safeDecodeURI } from 'next-basics';
|
||||||
import Button from 'components/common/Button';
|
import Button from 'components/common/Button';
|
||||||
import Times from 'assets/times.svg';
|
import Times from 'assets/times.svg';
|
||||||
import { safeDecodeURI } from 'lib/url';
|
|
||||||
import styles from './FilterTags.module.css';
|
import styles from './FilterTags.module.css';
|
||||||
|
|
||||||
export default function FilterTags({ params, onClick }) {
|
export default function FilterTags({ params, onClick }) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useIntl, defineMessages } from 'react-intl';
|
import { useIntl, defineMessages } from 'react-intl';
|
||||||
import MetricsTable from './MetricsTable';
|
import { safeDecodeURI } from 'next-basics';
|
||||||
import Tag from 'components/common/Tag';
|
import Tag from 'components/common/Tag';
|
||||||
|
import FilterButtons from 'components/common/FilterButtons';
|
||||||
import { paramFilter } from 'lib/filters';
|
import { paramFilter } from 'lib/filters';
|
||||||
import { safeDecodeURI } from 'lib/url';
|
import MetricsTable from './MetricsTable';
|
||||||
import FilterButtons from '../common/FilterButtons';
|
|
||||||
|
|
||||||
const FILTER_COMBINED = 0;
|
const FILTER_COMBINED = 0;
|
||||||
const FILTER_RAW = 1;
|
const FILTER_RAW = 1;
|
||||||
|
@ -23,8 +23,6 @@ export default function DashboardEdit({ websites }) {
|
|||||||
|
|
||||||
const ordered = useMemo(() => sortArrayByMap(websites, order, 'website_id'), [websites, order]);
|
const ordered = useMemo(() => sortArrayByMap(websites, order, 'website_id'), [websites, order]);
|
||||||
|
|
||||||
console.log({ order, ordered });
|
|
||||||
|
|
||||||
function handleWebsiteDrag({ destination, source }) {
|
function handleWebsiteDrag({ destination, source }) {
|
||||||
if (!destination || destination.index === source.index) return;
|
if (!destination || destination.index === source.index) return;
|
||||||
|
|
||||||
|
@ -28,8 +28,6 @@ export default function TestConsole() {
|
|||||||
const website = data.find(({ website_id }) => website_id === +websiteId);
|
const website = data.find(({ website_id }) => website_id === +websiteId);
|
||||||
const selectedValue = options.find(({ value }) => value === website?.website_id)?.value;
|
const selectedValue = options.find(({ value }) => value === website?.website_id)?.value;
|
||||||
|
|
||||||
console.log({ websiteId, data, options, website });
|
|
||||||
|
|
||||||
function handleSelect(value) {
|
function handleSelect(value) {
|
||||||
router.push(`/console/${value}`);
|
router.push(`/console/${value}`);
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,6 @@ export default function WebsiteList({ websites, showCharts, limit }) {
|
|||||||
const { websiteOrder } = useDashboard();
|
const { websiteOrder } = useDashboard();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
console.log({ websiteOrder });
|
|
||||||
|
|
||||||
const ordered = useMemo(
|
const ordered = useMemo(
|
||||||
() => sortArrayByMap(websites, websiteOrder, 'website_id'),
|
() => sortArrayByMap(websites, websiteOrder, 'website_id'),
|
||||||
[websites, websiteOrder],
|
[websites, websiteOrder],
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
import { removeItem } from 'next-basics';
|
||||||
import MenuButton from 'components/common/MenuButton';
|
import MenuButton from 'components/common/MenuButton';
|
||||||
import Icon from 'components/common/Icon';
|
import Icon from 'components/common/Icon';
|
||||||
import User from 'assets/user.svg';
|
import User from 'assets/user.svg';
|
||||||
import styles from './UserButton.module.css';
|
import styles from './UserButton.module.css';
|
||||||
import { removeItem } from 'lib/web';
|
|
||||||
import { AUTH_TOKEN } from 'lib/constants';
|
import { AUTH_TOKEN } from 'lib/constants';
|
||||||
import useUser from 'hooks/useUser';
|
import useUser from 'hooks/useUser';
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { get, post, put, del, getItem } from 'lib/web';
|
import { get, post, put, del, getItem } from 'next-basics';
|
||||||
import { AUTH_TOKEN, SHARE_TOKEN_HEADER } from 'lib/constants';
|
import { AUTH_TOKEN, SHARE_TOKEN_HEADER } from 'lib/constants';
|
||||||
import useStore from 'store/app';
|
import useStore from 'store/app';
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { get } from 'lib/web';
|
import { get } from 'next-basics';
|
||||||
import enUS from 'public/intl/country/en-US.json';
|
import enUS from 'public/intl/country/en-US.json';
|
||||||
|
|
||||||
const countryNames = {
|
const countryNames = {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { parseISO } from 'date-fns';
|
import { parseISO } from 'date-fns';
|
||||||
import { getDateRange } from 'lib/date';
|
import { getDateRange } from 'lib/date';
|
||||||
import { getItem, setItem } from 'lib/web';
|
import { getItem, setItem } from 'next-basics';
|
||||||
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE } from 'lib/constants';
|
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE } from 'lib/constants';
|
||||||
import useForceUpdate from './useForceUpdate';
|
import useForceUpdate from './useForceUpdate';
|
||||||
import useLocale from './useLocale';
|
import useLocale from './useLocale';
|
||||||
|
@ -8,7 +8,7 @@ export default function useFetch(url, options = {}, update = []) {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [count, setCount] = useState(0);
|
const [count, setCount] = useState(0);
|
||||||
const { get } = useApi();
|
const { get } = useApi();
|
||||||
const { params = {}, headers = {}, disabled, delay = 0, interval, onDataLoad } = options;
|
const { params = {}, headers = {}, disabled = false, delay = 0, interval, onDataLoad } = options;
|
||||||
|
|
||||||
async function loadData(params) {
|
async function loadData(params) {
|
||||||
try {
|
try {
|
||||||
@ -29,7 +29,9 @@ export default function useFetch(url, options = {}, update = []) {
|
|||||||
|
|
||||||
onDataLoad?.(data);
|
onDataLoad?.(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
||||||
setError(e);
|
setError(e);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@ -44,7 +46,7 @@ export default function useFetch(url, options = {}, update = []) {
|
|||||||
clearTimeout(id);
|
clearTimeout(id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [url, !!disabled, count, ...update]);
|
}, [url, disabled, count, ...update]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (interval && !disabled) {
|
if (interval && !disabled) {
|
||||||
@ -54,7 +56,7 @@ export default function useFetch(url, options = {}, update = []) {
|
|||||||
clearInterval(id);
|
clearInterval(id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [interval, !!disabled]);
|
}, [interval, disabled]);
|
||||||
|
|
||||||
return { ...response, error, loading };
|
return { ...response, error, loading };
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { get } from 'lib/web';
|
import { get } from 'next-basics';
|
||||||
import enUS from 'public/intl/language/en-US.json';
|
import enUS from 'public/intl/language/en-US.json';
|
||||||
|
|
||||||
const languageNames = {
|
const languageNames = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { get, setItem } from 'lib/web';
|
import { get, setItem } from 'next-basics';
|
||||||
import { LOCALE_CONFIG } from 'lib/constants';
|
import { LOCALE_CONFIG } from 'lib/constants';
|
||||||
import { getDateLocale, getTextDirection } from 'lib/lang';
|
import { getDateLocale, getTextDirection } from 'lib/lang';
|
||||||
import useStore, { setLocale } from 'store/app';
|
import useStore, { setLocale } from 'store/app';
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { getQueryString } from 'lib/url';
|
|
||||||
|
function getQueryString(params) {
|
||||||
|
return new URLSearchParams({ ...params }).toString();
|
||||||
|
}
|
||||||
|
|
||||||
export default function usePageQuery() {
|
export default function usePageQuery() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import useStore, { setTheme } from 'store/app';
|
import useStore, { setTheme } from 'store/app';
|
||||||
import { getItem, setItem } from 'lib/web';
|
import { getItem, setItem } from 'next-basics';
|
||||||
import { THEME_CONFIG } from 'lib/constants';
|
import { THEME_CONFIG } from 'lib/constants';
|
||||||
|
|
||||||
const selector = state => state.theme;
|
const selector = state => state.theme;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { getTimezone } from 'lib/date';
|
import { getTimezone } from 'lib/date';
|
||||||
import { getItem, setItem } from 'lib/web';
|
import { getItem, setItem } from 'next-basics';
|
||||||
import { TIMEZONE_CONFIG } from 'lib/constants';
|
import { TIMEZONE_CONFIG } from 'lib/constants';
|
||||||
|
|
||||||
export default function useTimezone() {
|
export default function useTimezone() {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { parseSecureToken, parseToken } from './crypto';
|
import { parseSecureToken, parseToken } from 'next-basics';
|
||||||
import { SHARE_TOKEN_HEADER } from './constants';
|
import { SHARE_TOKEN_HEADER } from './constants';
|
||||||
import { getWebsiteById } from 'queries';
|
import { getWebsiteById } from 'queries';
|
||||||
|
import { secret } from './crypto';
|
||||||
|
|
||||||
export async function getAuthToken(req) {
|
export async function getAuthToken(req) {
|
||||||
try {
|
try {
|
||||||
const token = req.headers.authorization;
|
const token = req.headers.authorization;
|
||||||
|
|
||||||
return parseSecureToken(token.split(' ')[1]);
|
return parseSecureToken(token.split(' ')[1], secret());
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -14,7 +15,7 @@ export async function getAuthToken(req) {
|
|||||||
|
|
||||||
export async function isValidToken(token, validation) {
|
export async function isValidToken(token, validation) {
|
||||||
try {
|
try {
|
||||||
const result = await parseToken(token);
|
const result = parseToken(token, secret());
|
||||||
|
|
||||||
if (typeof validation === 'object') {
|
if (typeof validation === 'object') {
|
||||||
return !Object.keys(validation).find(key => result[key] !== validation[key]);
|
return !Object.keys(validation).find(key => result[key] !== validation[key]);
|
||||||
|
@ -12,13 +12,9 @@ export const CLICKHOUSE_DATE_FORMATS = {
|
|||||||
year: '%Y-01-01',
|
year: '%Y-01-01',
|
||||||
};
|
};
|
||||||
|
|
||||||
const log = debug('clickhouse');
|
const log = debug('umami:clickhouse');
|
||||||
|
|
||||||
function getClient() {
|
function getClient() {
|
||||||
if (!process.env.CLICKHOUSE_URL) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
hostname,
|
hostname,
|
||||||
port,
|
port,
|
||||||
@ -149,13 +145,13 @@ function parseFilters(table, column, filters = {}, params = [], sessionKey = 'se
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceQuery(string, params = []) {
|
function formatQuery(str, params = []) {
|
||||||
let formattedString = string;
|
let formattedString = str;
|
||||||
|
|
||||||
params.forEach((a, i) => {
|
params.forEach((param, i) => {
|
||||||
let replace = a;
|
let replace = param;
|
||||||
|
|
||||||
if (typeof a === 'string' || a instanceof String) {
|
if (typeof param === 'string' || param instanceof String) {
|
||||||
replace = `'${replace}'`;
|
replace = `'${replace}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,11 +161,11 @@ function replaceQuery(string, params = []) {
|
|||||||
return formattedString;
|
return formattedString;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function rawQuery(query, params = [], debug = false) {
|
async function rawQuery(query, params = []) {
|
||||||
let formattedQuery = replaceQuery(query, params);
|
let formattedQuery = formatQuery(query, params);
|
||||||
|
|
||||||
if (debug || process.env.LOG_QUERY) {
|
if (process.env.LOG_QUERY) {
|
||||||
console.log(formattedQuery);
|
log(formattedQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clickhouse.query(formattedQuery).toPromise();
|
return clickhouse.query(formattedQuery).toPromise();
|
||||||
@ -188,7 +184,7 @@ async function findFirst(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
const clickhouse = global[CLICKHOUSE] || getClient();
|
const clickhouse = process.env.CLICKHOUSE_URL && (global[CLICKHOUSE] || getClient());
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
client: clickhouse,
|
client: clickhouse,
|
||||||
@ -199,8 +195,7 @@ export default {
|
|||||||
getBetweenDates,
|
getBetweenDates,
|
||||||
getFilterQuery,
|
getFilterQuery,
|
||||||
parseFilters,
|
parseFilters,
|
||||||
replaceQuery,
|
|
||||||
rawQuery,
|
|
||||||
findUnique,
|
findUnique,
|
||||||
findFirst,
|
findFirst,
|
||||||
|
rawQuery,
|
||||||
};
|
};
|
||||||
|
@ -1,24 +1,15 @@
|
|||||||
import crypto from 'crypto';
|
import { v4, v5 } from 'uuid';
|
||||||
import { v4, v5, validate } from 'uuid';
|
|
||||||
import bcrypt from 'bcryptjs';
|
|
||||||
import { JWT, JWE, JWK } from 'jose';
|
|
||||||
import { startOfMonth } from 'date-fns';
|
import { startOfMonth } from 'date-fns';
|
||||||
|
import { hash } from 'next-basics';
|
||||||
const SALT_ROUNDS = 10;
|
|
||||||
const KEY = JWK.asKey(Buffer.from(secret()));
|
|
||||||
const ROTATING_SALT = hash(startOfMonth(new Date()).toUTCString());
|
|
||||||
const CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
||||||
|
|
||||||
export function hash(...args) {
|
|
||||||
return crypto.createHash('sha512').update(args.join('')).digest('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function secret() {
|
export function secret() {
|
||||||
return hash(process.env.HASH_SALT || process.env.DATABASE_URL);
|
return hash(process.env.HASH_SALT || process.env.DATABASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function salt() {
|
export function salt() {
|
||||||
return v5(hash(secret(), ROTATING_SALT), v5.DNS);
|
const ROTATING_SALT = hash(startOfMonth(new Date()).toUTCString());
|
||||||
|
|
||||||
|
return hash([secret(), ROTATING_SALT]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uuid(...args) {
|
export function uuid(...args) {
|
||||||
@ -26,49 +17,3 @@ export function uuid(...args) {
|
|||||||
|
|
||||||
return v5(args.join(''), salt());
|
return v5(args.join(''), salt());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidUuid(s) {
|
|
||||||
return validate(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRandomChars(n) {
|
|
||||||
let s = '';
|
|
||||||
for (let i = 0; i < n; i++) {
|
|
||||||
s += CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hashPassword(password) {
|
|
||||||
return bcrypt.hashSync(password, SALT_ROUNDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkPassword(password, hash) {
|
|
||||||
return bcrypt.compareSync(password, hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createToken(payload) {
|
|
||||||
return JWT.sign(payload, KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function parseToken(token) {
|
|
||||||
try {
|
|
||||||
return JWT.verify(token, KEY);
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createSecureToken(payload) {
|
|
||||||
return JWE.encrypt(await createToken(payload), KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function parseSecureToken(token) {
|
|
||||||
try {
|
|
||||||
const result = await JWE.decrypt(token, KEY);
|
|
||||||
|
|
||||||
return parseToken(result.toString());
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,6 +4,7 @@ export const MYSQL = 'mysql';
|
|||||||
export const CLICKHOUSE = 'clickhouse';
|
export const CLICKHOUSE = 'clickhouse';
|
||||||
export const KAFKA = 'kafka';
|
export const KAFKA = 'kafka';
|
||||||
export const KAFKA_PRODUCER = 'kafka-producer';
|
export const KAFKA_PRODUCER = 'kafka-producer';
|
||||||
|
export const REDIS = 'redis';
|
||||||
|
|
||||||
// Fixes issue with converting bigint values
|
// Fixes issue with converting bigint values
|
||||||
BigInt.prototype.toJSON = function () {
|
BigInt.prototype.toJSON = function () {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { removeWWW } from './url';
|
|
||||||
|
|
||||||
export const urlFilter = data => {
|
export const urlFilter = data => {
|
||||||
const isValidUrl = url => {
|
const isValidUrl = url => {
|
||||||
return url !== '' && url !== null && !url.startsWith('#');
|
return url !== '' && url !== null && !url.startsWith('#');
|
||||||
@ -49,7 +47,7 @@ export const refFilter = data => {
|
|||||||
try {
|
try {
|
||||||
const url = new URL(x);
|
const url = new URL(x);
|
||||||
|
|
||||||
id = removeWWW(url.hostname) || url.href;
|
id = url.hostname.replace('www', '') || url.href;
|
||||||
} catch {
|
} catch {
|
||||||
id = '';
|
id = '';
|
||||||
}
|
}
|
||||||
@ -94,11 +92,7 @@ export const paramFilter = data => {
|
|||||||
return obj;
|
return obj;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const d = Object.keys(map).flatMap(key =>
|
return Object.keys(map).flatMap(key =>
|
||||||
Object.keys(map[key]).map(n => ({ x: `${key}=${n}`, p: key, v: n, y: map[key][n] })),
|
Object.keys(map[key]).map(n => ({ x: `${key}=${n}`, p: key, v: n, y: map[key][n] })),
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log({ map, d });
|
|
||||||
|
|
||||||
return d;
|
|
||||||
};
|
};
|
||||||
|
11
lib/kafka.js
11
lib/kafka.js
@ -3,13 +3,9 @@ import dateFormat from 'dateformat';
|
|||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { KAFKA, KAFKA_PRODUCER } from 'lib/db';
|
import { KAFKA, KAFKA_PRODUCER } from 'lib/db';
|
||||||
|
|
||||||
const log = debug('kafka');
|
const log = debug('umami:kafka');
|
||||||
|
|
||||||
function getClient() {
|
function getClient() {
|
||||||
if (!process.env.KAFKA_URL || !process.env.KAFKA_BROKER) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { username, password } = new URL(process.env.KAFKA_URL);
|
const { username, password } = new URL(process.env.KAFKA_URL);
|
||||||
const brokers = process.env.KAFKA_BROKER.split(',');
|
const brokers = process.env.KAFKA_BROKER.split(',');
|
||||||
|
|
||||||
@ -73,8 +69,11 @@ let kafka;
|
|||||||
let producer;
|
let producer;
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
kafka = global[KAFKA] || getClient();
|
kafka = process.env.KAFKA_URL && process.env.KAFKA_BROKER && (global[KAFKA] || getClient());
|
||||||
|
|
||||||
|
if (kafka) {
|
||||||
producer = global[KAFKA_PRODUCER] || (await getProducer());
|
producer = global[KAFKA_PRODUCER] || (await getProducer());
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,19 +1,7 @@
|
|||||||
|
import { createMiddleware, unauthorized, badRequest, serverError } from 'next-basics';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { getSession } from './session';
|
import { getSession } from './session';
|
||||||
import { getAuthToken } from './auth';
|
import { getAuthToken } from './auth';
|
||||||
import { unauthorized, badRequest, serverError } from './response';
|
|
||||||
|
|
||||||
export function createMiddleware(middleware) {
|
|
||||||
return (req, res) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
middleware(req, res, result => {
|
|
||||||
if (result instanceof Error) {
|
|
||||||
return reject(result);
|
|
||||||
}
|
|
||||||
return resolve(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useCors = createMiddleware(cors());
|
export const useCors = createMiddleware(cors());
|
||||||
|
|
||||||
@ -23,7 +11,9 @@ export const useSession = createMiddleware(async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
session = await getSession(req);
|
session = await getSession(req);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
||||||
return serverError(res, e.message);
|
return serverError(res, e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,8 @@ import { PrismaClient } from '@prisma/client';
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { PRISMA, MYSQL, POSTGRESQL } from 'lib/db';
|
import { PRISMA, MYSQL, POSTGRESQL, getDatabaseType } from 'lib/db';
|
||||||
import { FILTER_IGNORED } from 'lib/constants';
|
import { FILTER_IGNORED } from 'lib/constants';
|
||||||
import { getDatabaseType } from 'lib/db';
|
|
||||||
|
|
||||||
const MYSQL_DATE_FORMATS = {
|
const MYSQL_DATE_FORMATS = {
|
||||||
minute: '%Y-%m-%d %H:%i:00',
|
minute: '%Y-%m-%d %H:%i:00',
|
||||||
@ -22,7 +21,7 @@ const POSTGRESQL_DATE_FORMATS = {
|
|||||||
year: 'YYYY-01-01',
|
year: 'YYYY-01-01',
|
||||||
};
|
};
|
||||||
|
|
||||||
const log = debug('prisma');
|
const log = debug('umami:prisma');
|
||||||
|
|
||||||
const PRISMA_OPTIONS = {
|
const PRISMA_OPTIONS = {
|
||||||
log: [
|
log: [
|
||||||
|
17
lib/redis.js
17
lib/redis.js
@ -1,10 +1,11 @@
|
|||||||
import { createClient } from 'redis';
|
import { createClient } from 'redis';
|
||||||
import { startOfMonth } from 'date-fns';
|
import { startOfMonth } from 'date-fns';
|
||||||
import { getSessions, getAllWebsites } from '/queries';
|
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
import { getSessions, getAllWebsites } from 'queries';
|
||||||
|
import { REDIS } from 'lib/db';
|
||||||
|
|
||||||
const log = debug('db:redis');
|
const log = debug('umami:redis');
|
||||||
const REDIS = Symbol.for('redis');
|
const INITIALIZED = 'redis:initialized';
|
||||||
|
|
||||||
async function getClient() {
|
async function getClient() {
|
||||||
const redis = new createClient({
|
const redis = new createClient({
|
||||||
@ -38,7 +39,7 @@ async function stageData() {
|
|||||||
await addRedis(sessionUuids);
|
await addRedis(sessionUuids);
|
||||||
await addRedis(websiteIds);
|
await addRedis(websiteIds);
|
||||||
|
|
||||||
await redis.set('initialized', 'initialized');
|
await redis.set(INITIALIZED, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addRedis(ids) {
|
async function addRedis(ids) {
|
||||||
@ -52,13 +53,13 @@ async function addRedis(ids) {
|
|||||||
let redis = null;
|
let redis = null;
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
redis = global[REDIS] || (await getClient());
|
redis = process.env.REDIS_URL && (global[REDIS] || (await getClient()));
|
||||||
|
|
||||||
const value = await redis.get('initialized');
|
if (redis) {
|
||||||
|
if (!(await redis.get(INITIALIZED))) {
|
||||||
if (!value) {
|
|
||||||
await stageData();
|
await stageData();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export default redis;
|
export default redis;
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
export function ok(res, data = {}) {
|
|
||||||
return json(res, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function json(res, data = {}) {
|
|
||||||
return res.status(200).json(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function send(res, data, type = 'text/plain') {
|
|
||||||
res.setHeader('Content-Type', type);
|
|
||||||
|
|
||||||
return res.status(200).send(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function redirect(res, url) {
|
|
||||||
res.setHeader('Location', url);
|
|
||||||
|
|
||||||
return res.status(303).end();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function badRequest(res, msg = '400 Bad Request') {
|
|
||||||
return res.status(400).end(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unauthorized(res, msg = '401 Unauthorized') {
|
|
||||||
return res.status(401).end(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function forbidden(res, msg = '403 Forbidden') {
|
|
||||||
return res.status(403).end(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function notFound(res, msg = '404 Not Found') {
|
|
||||||
return res.status(404).end(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function methodNotAllowed(res, msg = '405 Method Not Allowed') {
|
|
||||||
res.status(405).end(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function serverError(res, msg = '500 Internal Server Error') {
|
|
||||||
res.status(500).end(msg);
|
|
||||||
}
|
|
8
lib/security.js
Normal file
8
lib/security.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { getItem } from 'next-basics';
|
||||||
|
import { AUTH_TOKEN } from './constants';
|
||||||
|
|
||||||
|
export function getAuthHeader() {
|
||||||
|
const token = getItem(AUTH_TOKEN);
|
||||||
|
|
||||||
|
return token ? { authorization: `Bearer ${token}` } : {};
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import { isValidUuid, parseToken, uuid } from 'lib/crypto';
|
import { parseToken } from 'next-basics';
|
||||||
|
import { validate } from 'uuid';
|
||||||
|
import { uuid } from 'lib/crypto';
|
||||||
import redis from 'lib/redis';
|
import redis from 'lib/redis';
|
||||||
import { getClientInfo, getJsonBody } from 'lib/request';
|
import { getClientInfo, getJsonBody } from 'lib/request';
|
||||||
import { createSession, getSessionByUuid, getWebsiteByUuid } from 'queries';
|
import { createSession, getSessionByUuid, getWebsiteByUuid } from 'queries';
|
||||||
@ -22,8 +24,8 @@ export async function getSession(req) {
|
|||||||
|
|
||||||
const { website: website_uuid, hostname, screen, language } = payload;
|
const { website: website_uuid, hostname, screen, language } = payload;
|
||||||
|
|
||||||
if (!isValidUuid(website_uuid)) {
|
if (!validate(website_uuid)) {
|
||||||
throw new Error(`Invalid website: ${website_uuid}`);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let websiteId = null;
|
let websiteId = null;
|
||||||
@ -52,7 +54,6 @@ export async function getSession(req) {
|
|||||||
if (process.env.REDIS_URL) {
|
if (process.env.REDIS_URL) {
|
||||||
sessionCreated = (await redis.get(`session:${session_uuid}`)) !== null;
|
sessionCreated = (await redis.get(`session:${session_uuid}`)) !== null;
|
||||||
} else {
|
} else {
|
||||||
console.log('test');
|
|
||||||
session = await getSessionByUuid(session_uuid);
|
session = await getSessionByUuid(session_uuid);
|
||||||
sessionCreated = !!session;
|
sessionCreated = !!session;
|
||||||
sessionId = session ? session.session_id : null;
|
sessionId = session ? session.session_id : null;
|
||||||
@ -60,7 +61,6 @@ export async function getSession(req) {
|
|||||||
|
|
||||||
if (!sessionCreated) {
|
if (!sessionCreated) {
|
||||||
try {
|
try {
|
||||||
console.log('test2');
|
|
||||||
session = await createSession(websiteId, {
|
session = await createSession(websiteId, {
|
||||||
session_uuid,
|
session_uuid,
|
||||||
hostname,
|
hostname,
|
||||||
|
35
lib/url.js
35
lib/url.js
@ -1,35 +0,0 @@
|
|||||||
export function removeTrailingSlash(url) {
|
|
||||||
return url && url.length > 1 && url.endsWith('/') ? url.slice(0, -1) : url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeWWW(url) {
|
|
||||||
return url && url.length > 1 && url.startsWith('www.') ? url.slice(4) : url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getQueryString(params = {}) {
|
|
||||||
const map = Object.keys(params).reduce((arr, key) => {
|
|
||||||
if (params[key] !== undefined) {
|
|
||||||
return arr.concat(`${key}=${encodeURIComponent(params[key])}`);
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (map.length) {
|
|
||||||
return `?${map.join('&')}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeUrl(url, params) {
|
|
||||||
return `${url}${getQueryString(params)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function safeDecodeURI(s) {
|
|
||||||
try {
|
|
||||||
return decodeURI(s);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
78
lib/web.js
78
lib/web.js
@ -1,78 +0,0 @@
|
|||||||
import { makeUrl } from './url';
|
|
||||||
|
|
||||||
export const apiRequest = (method, url, body, headers) => {
|
|
||||||
return fetch(url, {
|
|
||||||
method,
|
|
||||||
cache: 'no-cache',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
...headers,
|
|
||||||
},
|
|
||||||
body,
|
|
||||||
}).then(res => {
|
|
||||||
if (res.ok) {
|
|
||||||
return res.json().then(data => ({ ok: res.ok, status: res.status, data }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.text().then(data => ({ ok: res.ok, status: res.status, res: res, data }));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const get = (url, params, headers) =>
|
|
||||||
apiRequest('get', makeUrl(url, params), undefined, headers);
|
|
||||||
|
|
||||||
export const del = (url, params, headers) =>
|
|
||||||
apiRequest('delete', makeUrl(url, params), undefined, headers);
|
|
||||||
|
|
||||||
export const post = (url, params, headers) =>
|
|
||||||
apiRequest('post', url, JSON.stringify(params), headers);
|
|
||||||
|
|
||||||
export const put = (url, params, headers) =>
|
|
||||||
apiRequest('put', url, JSON.stringify(params), headers);
|
|
||||||
|
|
||||||
export const hook = (_this, method, callback) => {
|
|
||||||
const orig = _this[method];
|
|
||||||
|
|
||||||
return (...args) => {
|
|
||||||
callback.apply(null, args);
|
|
||||||
|
|
||||||
return orig.apply(_this, args);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const doNotTrack = () => {
|
|
||||||
const { doNotTrack, navigator, external } = window;
|
|
||||||
|
|
||||||
const msTrackProtection = 'msTrackingProtectionEnabled';
|
|
||||||
const msTracking = () => {
|
|
||||||
return external && msTrackProtection in external && external[msTrackProtection]();
|
|
||||||
};
|
|
||||||
|
|
||||||
const dnt = doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack || msTracking();
|
|
||||||
|
|
||||||
return dnt == '1' || dnt === 'yes';
|
|
||||||
};
|
|
||||||
|
|
||||||
export const setItem = (key, data, session) => {
|
|
||||||
if (typeof window !== 'undefined' && data) {
|
|
||||||
(session ? sessionStorage : localStorage).setItem(key, JSON.stringify(data));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getItem = (key, session) => {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
const value = (session ? sessionStorage : localStorage).getItem(key);
|
|
||||||
|
|
||||||
if (value !== 'undefined') {
|
|
||||||
return JSON.parse(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const removeItem = (key, session) => {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
(session ? sessionStorage : localStorage).removeItem(key);
|
|
||||||
}
|
|
||||||
};
|
|
@ -58,7 +58,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/inter": "4.5.7",
|
"@fontsource/inter": "4.5.7",
|
||||||
"@prisma/client": "4.2.1",
|
"@prisma/client": "4.2.1",
|
||||||
"bcryptjs": "^2.4.3",
|
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
"chart.js": "^2.9.4",
|
"chart.js": "^2.9.4",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
@ -81,11 +80,11 @@
|
|||||||
"is-docker": "^3.0.0",
|
"is-docker": "^3.0.0",
|
||||||
"is-localhost-ip": "^1.4.0",
|
"is-localhost-ip": "^1.4.0",
|
||||||
"isbot": "^3.4.5",
|
"isbot": "^3.4.5",
|
||||||
"jose": "2.0.5",
|
|
||||||
"kafkajs": "^2.1.0",
|
"kafkajs": "^2.1.0",
|
||||||
"maxmind": "^4.3.6",
|
"maxmind": "^4.3.6",
|
||||||
"moment-timezone": "^0.5.33",
|
"moment-timezone": "^0.5.33",
|
||||||
"next": "^12.2.5",
|
"next": "^12.2.5",
|
||||||
|
"next-basics": "^0.6.0",
|
||||||
"node-fetch": "^3.2.8",
|
"node-fetch": "^3.2.8",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
@ -115,6 +114,8 @@
|
|||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-next": "^12.2.4",
|
"eslint-config-next": "^12.2.4",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"extract-react-intl-messages": "^4.1.1",
|
"extract-react-intl-messages": "^4.1.1",
|
||||||
"husky": "^7.0.0",
|
"husky": "^7.0.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { getAccountById, deleteAccount } from 'queries';
|
import { getAccountById, deleteAccount } from 'queries';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { methodNotAllowed, ok, unauthorized } from 'lib/response';
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
import { ok, unauthorized, methodNotAllowed, badRequest, hashPassword } from 'next-basics';
|
||||||
import { getAccountById, getAccountByUsername, updateAccount, createAccount } from 'queries';
|
import { getAccountById, getAccountByUsername, updateAccount, createAccount } from 'queries';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { hashPassword } from 'lib/crypto';
|
|
||||||
import { ok, unauthorized, methodNotAllowed, badRequest } from 'lib/response';
|
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { getAccountById, updateAccount } from 'queries';
|
import { getAccountById, updateAccount } from 'queries';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { badRequest, methodNotAllowed, ok, unauthorized } from 'lib/response';
|
import {
|
||||||
import { checkPassword, hashPassword } from 'lib/crypto';
|
badRequest,
|
||||||
|
methodNotAllowed,
|
||||||
|
ok,
|
||||||
|
unauthorized,
|
||||||
|
checkPassword,
|
||||||
|
hashPassword,
|
||||||
|
} from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { getAccounts } from 'queries';
|
import { getAccounts } from 'queries';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, unauthorized, methodNotAllowed } from 'lib/response';
|
import { ok, unauthorized, methodNotAllowed } from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { checkPassword, createSecureToken } from 'lib/crypto';
|
import { ok, unauthorized, badRequest, checkPassword, createSecureToken } from 'next-basics';
|
||||||
import { getAccountByUsername } from 'queries/admin/account/getAccountByUsername';
|
import { getAccountByUsername } from 'queries/admin/account/getAccountByUsername';
|
||||||
import { ok, unauthorized, badRequest } from 'lib/response';
|
import { secret } from 'lib/crypto';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
@ -11,10 +11,10 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const account = await getAccountByUsername(username);
|
const account = await getAccountByUsername(username);
|
||||||
|
|
||||||
if (account && (await checkPassword(password, account.password))) {
|
if (account && checkPassword(password, account.password)) {
|
||||||
const { user_id, username, is_admin } = account;
|
const { user_id, username, is_admin } = account;
|
||||||
const user = { user_id, username, is_admin };
|
const user = { user_id, username, is_admin };
|
||||||
const token = await createSecureToken(user);
|
const token = createSecureToken(user, secret());
|
||||||
|
|
||||||
return ok(res, { token, user });
|
return ok(res, { token, user });
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, unauthorized } from 'lib/response';
|
import { ok, unauthorized } from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
const { Resolver } = require('dns').promises;
|
const { Resolver } = require('dns').promises;
|
||||||
import isbot from 'isbot';
|
import isbot from 'isbot';
|
||||||
import ipaddr from 'ipaddr.js';
|
import ipaddr from 'ipaddr.js';
|
||||||
|
import { createToken, unauthorized, send, badRequest, forbidden } from 'next-basics';
|
||||||
import { savePageView, saveEvent } from 'queries';
|
import { savePageView, saveEvent } from 'queries';
|
||||||
import { useCors, useSession } from 'lib/middleware';
|
import { useCors, useSession } from 'lib/middleware';
|
||||||
import { getJsonBody, getIpAddress } from 'lib/request';
|
import { getJsonBody, getIpAddress } from 'lib/request';
|
||||||
import { unauthorized, send, badRequest, forbidden } from 'lib/response';
|
|
||||||
import { createToken } from 'lib/crypto';
|
|
||||||
import { removeTrailingSlash } from 'lib/url';
|
|
||||||
import { uuid } from 'lib/crypto';
|
import { uuid } from 'lib/crypto';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
@ -69,7 +67,7 @@ export default async (req, res) => {
|
|||||||
let { url, referrer, event_name, event_data } = payload;
|
let { url, referrer, event_name, event_data } = payload;
|
||||||
|
|
||||||
if (process.env.REMOVE_TRAILING_SLASH) {
|
if (process.env.REMOVE_TRAILING_SLASH) {
|
||||||
url = removeTrailingSlash(url);
|
url = url.replace(/\/$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
const event_uuid = uuid();
|
const event_uuid = uuid();
|
||||||
@ -89,7 +87,7 @@ export default async (req, res) => {
|
|||||||
return badRequest(res);
|
return badRequest(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = await createToken({ website_id, session_id, session_uuid });
|
const token = createToken({ website_id, session_id, session_uuid });
|
||||||
|
|
||||||
return send(res, token);
|
return send(res, token);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ok, methodNotAllowed } from 'lib/response';
|
import { ok, methodNotAllowed } from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
if (req.method === 'GET') {
|
if (req.method === 'GET') {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ok } from 'lib/response';
|
import { ok } from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
return ok(res, 'nice');
|
return ok(res, 'nice');
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { subMinutes } from 'date-fns';
|
import { subMinutes } from 'date-fns';
|
||||||
|
import { ok, methodNotAllowed, createToken } from 'next-basics';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, methodNotAllowed } from 'lib/response';
|
|
||||||
import { getUserWebsites, getRealtimeData } from 'queries';
|
import { getUserWebsites, getRealtimeData } from 'queries';
|
||||||
import { createToken } from 'lib/crypto';
|
import { secret } from 'lib/crypto';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
@ -12,7 +12,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const websites = await getUserWebsites(user_id);
|
const websites = await getUserWebsites(user_id);
|
||||||
const ids = websites.map(({ website_id }) => website_id);
|
const ids = websites.map(({ website_id }) => website_id);
|
||||||
const token = await createToken({ websites: ids });
|
const token = createToken({ websites: ids }, secret());
|
||||||
const data = await getRealtimeData(ids, subMinutes(new Date(), 30));
|
const data = await getRealtimeData(ids, subMinutes(new Date(), 30));
|
||||||
|
|
||||||
return ok(res, {
|
return ok(res, {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
import { ok, methodNotAllowed, badRequest, parseToken } from 'next-basics';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, methodNotAllowed, badRequest } from 'lib/response';
|
|
||||||
import { getRealtimeData } from 'queries';
|
import { getRealtimeData } from 'queries';
|
||||||
import { parseToken } from 'lib/crypto';
|
|
||||||
import { SHARE_TOKEN_HEADER } from 'lib/constants';
|
import { SHARE_TOKEN_HEADER } from 'lib/constants';
|
||||||
|
import { secret } from 'lib/crypto';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
@ -16,7 +16,7 @@ export default async (req, res) => {
|
|||||||
return badRequest(res);
|
return badRequest(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { websites } = await parseToken(token);
|
const { websites } = parseToken(token, secret());
|
||||||
|
|
||||||
const data = await getRealtimeData(websites, new Date(+start_at));
|
const data = await getRealtimeData(websites, new Date(+start_at));
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { getWebsiteByShareId } from 'queries';
|
import { getWebsiteByShareId } from 'queries';
|
||||||
import { ok, notFound, methodNotAllowed } from 'lib/response';
|
import { ok, notFound, methodNotAllowed, createToken } from 'next-basics';
|
||||||
import { createToken } from 'lib/crypto';
|
import { secret } from 'lib/crypto';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const { id } = req.query;
|
const { id } = req.query;
|
||||||
@ -10,7 +10,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
if (website) {
|
if (website) {
|
||||||
const websiteId = website.website_id;
|
const websiteId = website.website_id;
|
||||||
const token = await createToken({ website_id: websiteId });
|
const token = createToken({ website_id: websiteId }, secret());
|
||||||
|
|
||||||
return ok(res, { websiteId, token });
|
return ok(res, { websiteId, token });
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { methodNotAllowed, ok, unauthorized } from 'lib/response';
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
import { useCors } from 'lib/middleware';
|
import { useCors } from 'lib/middleware';
|
||||||
import { getActiveVisitors } from 'queries';
|
import { getActiveVisitors } from 'queries';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import { getEventMetrics } from 'queries';
|
import { getEventMetrics } from 'queries';
|
||||||
import { ok, badRequest, methodNotAllowed, unauthorized } from 'lib/response';
|
import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
import { useCors } from 'lib/middleware';
|
import { useCors } from 'lib/middleware';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
import { deleteWebsite, getWebsiteById } from 'queries';
|
import { deleteWebsite, getWebsiteById } from 'queries';
|
||||||
import { methodNotAllowed, ok, unauthorized } from 'lib/response';
|
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
import { useCors } from 'lib/middleware';
|
import { useCors } from 'lib/middleware';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'queries';
|
import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'queries';
|
||||||
import { ok, methodNotAllowed, unauthorized, badRequest } from 'lib/response';
|
import { ok, methodNotAllowed, unauthorized, badRequest } from 'next-basics';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
import { useCors } from 'lib/middleware';
|
import { useCors } from 'lib/middleware';
|
||||||
import { FILTER_IGNORED } from 'lib/constants';
|
import { FILTER_IGNORED } from 'lib/constants';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import { getPageviewStats } from 'queries';
|
import { getPageviewStats } from 'queries';
|
||||||
import { ok, badRequest, methodNotAllowed, unauthorized } from 'lib/response';
|
import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
import { useCors } from 'lib/middleware';
|
import { useCors } from 'lib/middleware';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { resetWebsite } from 'queries';
|
import { resetWebsite } from 'queries';
|
||||||
import { methodNotAllowed, ok, unauthorized } from 'lib/response';
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getWebsiteStats } from 'queries';
|
import { getWebsiteStats } from 'queries';
|
||||||
import { methodNotAllowed, ok, unauthorized } from 'lib/response';
|
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
import { allowQuery } from 'lib/auth';
|
import { allowQuery } from 'lib/auth';
|
||||||
import { useCors } from 'lib/middleware';
|
import { useCors } from 'lib/middleware';
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import { ok, unauthorized, methodNotAllowed, getRandomChars } from 'next-basics';
|
||||||
import { updateWebsite, createWebsite, getWebsiteById } from 'queries';
|
import { updateWebsite, createWebsite, getWebsiteById } from 'queries';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { uuid, getRandomChars } from 'lib/crypto';
|
import { uuid } from 'lib/crypto';
|
||||||
import { ok, unauthorized, methodNotAllowed } from 'lib/response';
|
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { getAllWebsites, getUserWebsites } from 'queries';
|
import { getAllWebsites, getUserWebsites } from 'queries';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, methodNotAllowed, unauthorized } from 'lib/response';
|
import { ok, methodNotAllowed, unauthorized } from 'next-basics';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { removeItem } from 'lib/web';
|
import { removeItem } from 'next-basics';
|
||||||
import { AUTH_TOKEN } from 'lib/constants';
|
import { AUTH_TOKEN } from 'lib/constants';
|
||||||
import { setUser } from 'store/app';
|
import { setUser } from 'store/app';
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
const bcrypt = require('bcryptjs');
|
const { hashPassword } = require('next-basics');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const prompts = require('prompts');
|
const prompts = require('prompts');
|
||||||
const { PrismaClient } = require('@prisma/client');
|
const { PrismaClient } = require('@prisma/client');
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
const SALT_ROUNDS = 10;
|
|
||||||
|
|
||||||
const runQuery = async query => {
|
const runQuery = async query => {
|
||||||
return query.catch(e => {
|
return query.catch(e => {
|
||||||
@ -24,10 +24,6 @@ const updateAccountByUsername = (username, data) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hashPassword = password => {
|
|
||||||
return bcrypt.hashSync(password, SALT_ROUNDS);
|
|
||||||
};
|
|
||||||
|
|
||||||
const changePassword = async (username, newPassword) => {
|
const changePassword = async (username, newPassword) => {
|
||||||
const password = hashPassword(newPassword);
|
const password = hashPassword(newPassword);
|
||||||
return updateAccountByUsername(username, { password });
|
return updateAccountByUsername(username, { password });
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import create from 'zustand';
|
import create from 'zustand';
|
||||||
import { DEFAULT_LOCALE, DEFAULT_THEME, LOCALE_CONFIG, THEME_CONFIG } from 'lib/constants';
|
import { DEFAULT_LOCALE, DEFAULT_THEME, LOCALE_CONFIG, THEME_CONFIG } from 'lib/constants';
|
||||||
import { getItem } from 'lib/web';
|
import { getItem } from 'next-basics';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
locale: getItem(LOCALE_CONFIG) || DEFAULT_LOCALE,
|
locale: getItem(LOCALE_CONFIG) || DEFAULT_LOCALE,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import create from 'zustand';
|
import create from 'zustand';
|
||||||
import { DASHBOARD_CONFIG, DEFAULT_WEBSITE_LIMIT } from 'lib/constants';
|
import { DASHBOARD_CONFIG, DEFAULT_WEBSITE_LIMIT } from 'lib/constants';
|
||||||
import { getItem, setItem } from 'lib/web';
|
import { getItem, setItem } from 'next-basics';
|
||||||
|
|
||||||
export const initialState = {
|
export const initialState = {
|
||||||
showCharts: true,
|
showCharts: true,
|
||||||
|
@ -2,7 +2,7 @@ import create from 'zustand';
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import semver from 'semver';
|
import semver from 'semver';
|
||||||
import { CURRENT_VERSION, VERSION_CHECK, UPDATES_URL } from 'lib/constants';
|
import { CURRENT_VERSION, VERSION_CHECK, UPDATES_URL } from 'lib/constants';
|
||||||
import { getItem } from 'lib/web';
|
import { getItem } from 'next-basics';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
current: CURRENT_VERSION,
|
current: CURRENT_VERSION,
|
||||||
|
107
yarn.lock
107
yarn.lock
@ -1440,11 +1440,6 @@
|
|||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
"@panva/asn1.js@^1.0.0":
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz"
|
|
||||||
integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==
|
|
||||||
|
|
||||||
"@prisma/client@4.2.1":
|
"@prisma/client@4.2.1":
|
||||||
version "4.2.1"
|
version "4.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.2.1.tgz#b384587f6066070381ea4c90228a14697a0c271b"
|
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.2.1.tgz#b384587f6066070381ea4c90228a14697a0c271b"
|
||||||
@ -2373,6 +2368,11 @@ buble@^0.20.0:
|
|||||||
minimist "^1.2.5"
|
minimist "^1.2.5"
|
||||||
regexpu-core "4.5.4"
|
regexpu-core "4.5.4"
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||||
|
integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
|
||||||
|
|
||||||
buffer-from@^1.0.0:
|
buffer-from@^1.0.0:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
||||||
@ -3020,6 +3020,13 @@ ecc-jsbn@~0.1.1:
|
|||||||
jsbn "~0.1.0"
|
jsbn "~0.1.0"
|
||||||
safer-buffer "^2.1.0"
|
safer-buffer "^2.1.0"
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||||
|
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
electron-to-chromium@^1.4.118:
|
electron-to-chromium@^1.4.118:
|
||||||
version "1.4.143"
|
version "1.4.143"
|
||||||
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz"
|
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz"
|
||||||
@ -3144,6 +3151,11 @@ eslint-config-prettier@^8.5.0:
|
|||||||
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz"
|
||||||
integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
|
integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
|
||||||
|
|
||||||
|
eslint-import-resolver-alias@^1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz#297062890e31e4d6651eb5eba9534e1f6e68fc97"
|
||||||
|
integrity sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==
|
||||||
|
|
||||||
eslint-import-resolver-node@^0.3.6:
|
eslint-import-resolver-node@^0.3.6:
|
||||||
version "0.3.6"
|
version "0.3.6"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
|
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
|
||||||
@ -4146,13 +4158,6 @@ jest-worker@^26.2.1:
|
|||||||
merge-stream "^2.0.0"
|
merge-stream "^2.0.0"
|
||||||
supports-color "^7.0.0"
|
supports-color "^7.0.0"
|
||||||
|
|
||||||
jose@2.0.5:
|
|
||||||
version "2.0.5"
|
|
||||||
resolved "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz"
|
|
||||||
integrity sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==
|
|
||||||
dependencies:
|
|
||||||
"@panva/asn1.js" "^1.0.0"
|
|
||||||
|
|
||||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
@ -4254,6 +4259,22 @@ jsonparse@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
||||||
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
|
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
|
||||||
|
|
||||||
|
jsonwebtoken@^8.5.1:
|
||||||
|
version "8.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
|
||||||
|
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
|
||||||
|
dependencies:
|
||||||
|
jws "^3.2.2"
|
||||||
|
lodash.includes "^4.3.0"
|
||||||
|
lodash.isboolean "^3.0.3"
|
||||||
|
lodash.isinteger "^4.0.4"
|
||||||
|
lodash.isnumber "^3.0.3"
|
||||||
|
lodash.isplainobject "^4.0.6"
|
||||||
|
lodash.isstring "^4.0.1"
|
||||||
|
lodash.once "^4.0.0"
|
||||||
|
ms "^2.1.1"
|
||||||
|
semver "^5.6.0"
|
||||||
|
|
||||||
jsprim@^1.2.2:
|
jsprim@^1.2.2:
|
||||||
version "1.4.2"
|
version "1.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
|
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
|
||||||
@ -4272,6 +4293,23 @@ jsprim@^1.2.2:
|
|||||||
array-includes "^3.1.5"
|
array-includes "^3.1.5"
|
||||||
object.assign "^4.1.3"
|
object.assign "^4.1.3"
|
||||||
|
|
||||||
|
jwa@^1.4.1:
|
||||||
|
version "1.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||||
|
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time "1.0.1"
|
||||||
|
ecdsa-sig-formatter "1.0.11"
|
||||||
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
jws@^3.2.2:
|
||||||
|
version "3.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
|
||||||
|
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
|
||||||
|
dependencies:
|
||||||
|
jwa "^1.4.1"
|
||||||
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
kafkajs@^2.1.0:
|
kafkajs@^2.1.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/kafkajs/-/kafkajs-2.2.0.tgz#43b2d13c82395acee4500f09d6c7d503db8c77ea"
|
resolved "https://registry.yarnpkg.com/kafkajs/-/kafkajs-2.2.0.tgz#43b2d13c82395acee4500f09d6c7d503db8c77ea"
|
||||||
@ -4395,6 +4433,36 @@ lodash.debounce@^4.0.8:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||||
|
|
||||||
|
lodash.includes@^4.3.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||||
|
integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==
|
||||||
|
|
||||||
|
lodash.isboolean@^3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||||
|
integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
|
||||||
|
|
||||||
|
lodash.isinteger@^4.0.4:
|
||||||
|
version "4.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||||
|
integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==
|
||||||
|
|
||||||
|
lodash.isnumber@^3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
|
||||||
|
integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==
|
||||||
|
|
||||||
|
lodash.isplainobject@^4.0.6:
|
||||||
|
version "4.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||||
|
integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
|
||||||
|
|
||||||
|
lodash.isstring@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||||
|
integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
|
||||||
|
|
||||||
lodash.merge@^4.6.2:
|
lodash.merge@^4.6.2:
|
||||||
version "4.6.2"
|
version "4.6.2"
|
||||||
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
|
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
|
||||||
@ -4405,6 +4473,11 @@ lodash.mergewith@^4.6.2:
|
|||||||
resolved "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz"
|
resolved "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz"
|
||||||
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
|
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
|
||||||
|
|
||||||
|
lodash.once@^4.0.0:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||||
|
integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
|
||||||
|
|
||||||
lodash.pick@^4.4.0:
|
lodash.pick@^4.4.0:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz"
|
resolved "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz"
|
||||||
@ -4662,6 +4735,14 @@ natural-compare@^1.4.0:
|
|||||||
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
|
||||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||||
|
|
||||||
|
next-basics@^0.6.0:
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.6.0.tgz#bbb3b2dafa69931c3b7aad0cd456332ddcf019c7"
|
||||||
|
integrity sha512-S9deRGhQPj9tN9WSroK8UAcxFuoV38YNFO9B5qEQpt7ZUNCkAUITccW98LGlJ5WfNzkp7dnXVgmL3+yvRWlH4w==
|
||||||
|
dependencies:
|
||||||
|
bcryptjs "^2.4.3"
|
||||||
|
jsonwebtoken "^8.5.1"
|
||||||
|
|
||||||
next@^12.2.5:
|
next@^12.2.5:
|
||||||
version "12.2.5"
|
version "12.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717"
|
resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717"
|
||||||
@ -5866,7 +5947,7 @@ semver-compare@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz"
|
||||||
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.5.0:
|
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
Loading…
Reference in New Issue
Block a user