Updated share token logic. Closes #1113.

This commit is contained in:
Mike Cao 2022-05-05 19:04:28 -07:00
parent b5de6b997e
commit e735a1c50d
12 changed files with 44 additions and 42 deletions

View File

@ -3,20 +3,16 @@ import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import useFetch from 'hooks/useFetch';
import Dot from 'components/common/Dot';
import { TOKEN_HEADER } from 'lib/constants';
import useShareToken from 'hooks/useShareToken';
import styles from './ActiveUsers.module.css';
export default function ActiveUsers({ websiteId, className, value, interval = 60000 }) {
const shareToken = useShareToken();
const url = websiteId ? `/website/${websiteId}/active` : null;
const { data } = useFetch(url, {
interval,
headers: { [TOKEN_HEADER]: shareToken?.token },
});
const count = useMemo(() => {
if (websiteId) {
return data?.[0]?.x || 0
return data?.[0]?.x || 0;
}
return value !== undefined ? value : 0;

View File

@ -6,8 +6,7 @@ import useFetch from 'hooks/useFetch';
import useDateRange from 'hooks/useDateRange';
import useTimezone from 'hooks/useTimezone';
import usePageQuery from 'hooks/usePageQuery';
import useShareToken from 'hooks/useShareToken';
import { EVENT_COLORS, TOKEN_HEADER } from 'lib/constants';
import { EVENT_COLORS } from 'lib/constants';
export default function EventsChart({ websiteId, className, token }) {
const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId);
@ -15,7 +14,6 @@ export default function EventsChart({ websiteId, className, token }) {
const {
query: { url, eventType },
} = usePageQuery();
const shareToken = useShareToken();
const { data, loading } = useFetch(
`/website/${websiteId}/events`,
@ -29,7 +27,6 @@ export default function EventsChart({ websiteId, className, token }) {
event_type: eventType,
token,
},
headers: { [TOKEN_HEADER]: shareToken?.token },
},
[modified, eventType],
);

View File

@ -6,14 +6,11 @@ import ErrorMessage from 'components/common/ErrorMessage';
import useFetch from 'hooks/useFetch';
import useDateRange from 'hooks/useDateRange';
import usePageQuery from 'hooks/usePageQuery';
import useShareToken from 'hooks/useShareToken';
import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
import { TOKEN_HEADER } from 'lib/constants';
import MetricCard from './MetricCard';
import styles from './MetricsBar.module.css';
export default function MetricsBar({ websiteId, className }) {
const shareToken = useShareToken();
const [dateRange] = useDateRange(websiteId);
const { startDate, endDate, modified } = dateRange;
const [format, setFormat] = useState(true);
@ -34,7 +31,6 @@ export default function MetricsBar({ websiteId, className }) {
device,
country,
},
headers: { [TOKEN_HEADER]: shareToken?.token },
},
[modified, url, referrer, os, browser, device, country],
);

View File

@ -9,10 +9,9 @@ import Arrow from 'assets/arrow-right.svg';
import { percentFilter } from 'lib/filters';
import useDateRange from 'hooks/useDateRange';
import usePageQuery from 'hooks/usePageQuery';
import useShareToken from 'hooks/useShareToken';
import ErrorMessage from 'components/common/ErrorMessage';
import DataTable from './DataTable';
import { DEFAULT_ANIMATION_DURATION, TOKEN_HEADER } from 'lib/constants';
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
import styles from './MetricsTable.module.css';
export default function MetricsTable({
@ -25,7 +24,6 @@ export default function MetricsTable({
onDataLoad,
...props
}) {
const shareToken = useShareToken();
const [{ startDate, endDate, modified }] = useDateRange(websiteId);
const {
resolve,
@ -49,7 +47,6 @@ export default function MetricsTable({
},
onDataLoad,
delay: DEFAULT_ANIMATION_DURATION,
headers: { [TOKEN_HEADER]: shareToken?.token },
},
[modified, url, referrer, os, browser, device, country],
);

View File

@ -12,9 +12,7 @@ import useDateRange from 'hooks/useDateRange';
import useTimezone from 'hooks/useTimezone';
import usePageQuery from 'hooks/usePageQuery';
import { getDateArray, getDateLength, getDateRangeValues } from 'lib/date';
import useShareToken from 'hooks/useShareToken';
import useApi from 'hooks/useApi';
import { TOKEN_HEADER } from 'lib/constants';
import styles from './WebsiteChart.module.css';
export default function WebsiteChart({
@ -26,7 +24,6 @@ export default function WebsiteChart({
showChart = true,
onDataLoad = () => {},
}) {
const shareToken = useShareToken();
const [dateRange, setDateRange] = useDateRange(websiteId);
const { startDate, endDate, unit, value, modified } = dateRange;
const [timezone] = useTimezone();
@ -53,7 +50,6 @@ export default function WebsiteChart({
country,
},
onDataLoad,
headers: { [TOKEN_HEADER]: shareToken?.token },
},
[modified, url, referrer, os, browser, device, country],
);

View File

@ -14,7 +14,7 @@ import useFetch from 'hooks/useFetch';
import useLocale from 'hooks/useLocale';
import useCountryNames from 'hooks/useCountryNames';
import { percentFilter } from 'lib/filters';
import { TOKEN_HEADER, REALTIME_RANGE, REALTIME_INTERVAL } from 'lib/constants';
import { SHARE_TOKEN_HEADER, REALTIME_RANGE, REALTIME_INTERVAL } from 'lib/constants';
import styles from './RealtimeDashboard.module.css';
function mergeData(state, data, time) {
@ -38,7 +38,7 @@ export default function RealtimeDashboard() {
params: { start_at: data?.timestamp },
disabled: !init?.websites?.length || !data,
interval: REALTIME_INTERVAL,
headers: { [TOKEN_HEADER]: init?.token },
headers: { [SHARE_TOKEN_HEADER]: init?.token },
});
const renderCountryName = useCallback(

View File

@ -20,8 +20,7 @@ import EventsTable from 'components/metrics/EventsTable';
import EventsChart from 'components/metrics/EventsChart';
import useFetch from 'hooks/useFetch';
import usePageQuery from 'hooks/usePageQuery';
import useShareToken from 'hooks/useShareToken';
import { DEFAULT_ANIMATION_DURATION, TOKEN_HEADER } from 'lib/constants';
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
import styles from './WebsiteDetails.module.css';
const views = {
@ -36,10 +35,7 @@ const views = {
};
export default function WebsiteDetails({ websiteId }) {
const shareToken = useShareToken();
const { data } = useFetch(`/website/${websiteId}`, {
headers: { [TOKEN_HEADER]: shareToken?.token },
});
const { data } = useFetch(`/website/${websiteId}`);
const [chartLoaded, setChartLoaded] = useState(false);
const [countryData, setCountryData] = useState();
const [eventsData, setEventsData] = useState();

View File

@ -1,13 +1,18 @@
import { useCallback } from 'react';
import { useRouter } from 'next/router';
import { get, post, put, del, getItem } from 'lib/web';
import { AUTH_TOKEN } from 'lib/constants';
import { AUTH_TOKEN, SHARE_TOKEN_HEADER } from 'lib/constants';
import useStore from 'store/app';
function includeAuthToken(headers = {}) {
const authToken = getItem(AUTH_TOKEN);
const selector = state => state.shareToken;
function parseHeaders(headers = {}, { authToken, shareToken }) {
if (authToken) {
headers.Authorization = `Bearer ${authToken}`;
headers.authorization = `Bearer ${authToken}`;
}
if (shareToken) {
headers[SHARE_TOKEN_HEADER] = shareToken.token;
}
return headers;
@ -15,32 +20,50 @@ function includeAuthToken(headers = {}) {
export default function useApi() {
const { basePath } = useRouter();
const authToken = getItem(AUTH_TOKEN);
const shareToken = useStore(selector);
return {
get: useCallback(
async (url, params, headers) => {
return get(`${basePath}/api${url}`, params, includeAuthToken(headers));
return get(
`${basePath}/api${url}`,
params,
parseHeaders(headers, { authToken, shareToken }),
);
},
[get],
),
post: useCallback(
async (url, params, headers) => {
return post(`${basePath}/api${url}`, params, includeAuthToken(headers));
return post(
`${basePath}/api${url}`,
params,
parseHeaders(headers, { authToken, shareToken }),
);
},
[post],
),
put: useCallback(
async (url, params, headers) => {
return put(`${basePath}/api${url}`, params, includeAuthToken(headers));
return put(
`${basePath}/api${url}`,
params,
parseHeaders(headers, { authToken, shareToken }),
);
},
[put],
),
del: useCallback(
async (url, params, headers) => {
return del(`${basePath}/api${url}`, params, includeAuthToken(headers));
return del(
`${basePath}/api${url}`,
params,
parseHeaders(headers, { authToken, shareToken }),
);
},
[del],
),

View File

@ -6,6 +6,7 @@ const selector = state => state.shareToken;
export default function useShareToken(shareId) {
const shareToken = useStore(selector);
console.log({ shareToken });
const { get } = useApi();
async function loadToken(id) {

View File

@ -1,5 +1,5 @@
import { parseSecureToken, parseToken } from './crypto';
import { TOKEN_HEADER } from './constants';
import { SHARE_TOKEN_HEADER } from './constants';
import { getWebsiteById } from './queries';
export async function getAuthToken(req) {
@ -30,7 +30,7 @@ export async function isValidToken(token, validation) {
export async function allowQuery(req, skipToken) {
const { id } = req.query;
const token = req.headers[TOKEN_HEADER];
const token = req.headers[SHARE_TOKEN_HEADER];
const websiteId = +id;
const website = await getWebsiteById(websiteId);

View File

@ -5,7 +5,7 @@ export const DATE_RANGE_CONFIG = 'umami.date-range';
export const THEME_CONFIG = 'umami.theme';
export const DASHBOARD_CONFIG = 'umami.dashboard';
export const VERSION_CHECK = 'umami.version-check';
export const TOKEN_HEADER = 'x-umami-token';
export const SHARE_TOKEN_HEADER = 'x-umami-share-token';
export const HOMEPAGE_URL = 'https://umami.is';
export const VERSION_URL = 'https://github.com/mikecao/umami/releases';

View File

@ -2,7 +2,7 @@ import { useAuth } from 'lib/middleware';
import { ok, methodNotAllowed, badRequest } from 'lib/response';
import { getRealtimeData } from 'lib/queries';
import { parseToken } from 'lib/crypto';
import { TOKEN_HEADER } from 'lib/constants';
import { SHARE_TOKEN_HEADER } from 'lib/constants';
export default async (req, res) => {
await useAuth(req, res);
@ -10,7 +10,7 @@ export default async (req, res) => {
if (req.method === 'GET') {
const { start_at } = req.query;
const token = req.headers[TOKEN_HEADER];
const token = req.headers[SHARE_TOKEN_HEADER];
if (!token) {
return badRequest(res);