From 5068ab12a944e46f46ef8a2f128bd85d1b0fe5c3 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Wed, 30 Sep 2020 22:34:16 -0700 Subject: [PATCH] Support basePath in all queries. --- components/forms/AccountEditForm.js | 4 +++- components/forms/ChangePasswordForm.js | 4 +++- components/forms/DeleteForm.js | 12 ++++++---- components/forms/LoginForm.js | 10 +++++--- components/forms/WebsiteEditForm.js | 4 +++- hooks/useCountryNames.js | 4 +++- hooks/useFetch.js | 4 +++- hooks/useRequireLogin.js | 32 +++++++++++++++----------- package.json | 2 +- pages/api/auth/logout.js | 4 ++-- pages/logout.js | 6 ++++- 11 files changed, 57 insertions(+), 29 deletions(-) diff --git a/components/forms/AccountEditForm.js b/components/forms/AccountEditForm.js index f2deea9b..ccce3463 100644 --- a/components/forms/AccountEditForm.js +++ b/components/forms/AccountEditForm.js @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { Formik, Form, Field } from 'formik'; +import { useRouter } from 'next/router'; import { post } from 'lib/web'; import Button from 'components/common/Button'; import FormLayout, { @@ -29,10 +30,11 @@ const validate = ({ user_id, username, password }) => { }; export default function AccountEditForm({ values, onSave, onClose }) { + const { basePath } = useRouter(); const [message, setMessage] = useState(); const handleSubmit = async values => { - const { ok, data } = await post(`/api/account`, values); + const { ok, data } = await post(`${basePath}/api/account`, values); if (ok) { onSave(); diff --git a/components/forms/ChangePasswordForm.js b/components/forms/ChangePasswordForm.js index 1878ffef..c41b6e6b 100644 --- a/components/forms/ChangePasswordForm.js +++ b/components/forms/ChangePasswordForm.js @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import { FormattedMessage } from 'react-intl'; +import { useRouter } from 'next/router'; import { Formik, Form, Field } from 'formik'; import { post } from 'lib/web'; import Button from 'components/common/Button'; @@ -37,10 +38,11 @@ const validate = ({ current_password, new_password, confirm_password }) => { }; export default function ChangePasswordForm({ values, onSave, onClose }) { + const { basePath } = useRouter(); const [message, setMessage] = useState(); const handleSubmit = async values => { - const { ok, data } = await post(`/api/account/password`, values); + const { ok, data } = await post(`${basePath}/api/account/password`, values); if (ok) { onSave(); diff --git a/components/forms/DeleteForm.js b/components/forms/DeleteForm.js index f53b286f..689cd1fc 100644 --- a/components/forms/DeleteForm.js +++ b/components/forms/DeleteForm.js @@ -1,4 +1,6 @@ import React, { useState } from 'react'; +import { FormattedMessage } from 'react-intl'; +import { useRouter } from 'next/router'; import { Formik, Form, Field } from 'formik'; import { del } from 'lib/web'; import Button from 'components/common/Button'; @@ -8,7 +10,6 @@ import FormLayout, { FormMessage, FormRow, } from 'components/layout/FormLayout'; -import { FormattedMessage } from 'react-intl'; const CONFIRMATION_WORD = 'DELETE'; @@ -27,15 +28,18 @@ const validate = ({ confirmation }) => { }; export default function DeleteForm({ values, onSave, onClose }) { + const { basePath } = useRouter(); const [message, setMessage] = useState(); const handleSubmit = async ({ type, id }) => { - const response = await del(`/api/${type}/${id}`); + const { ok, data } = await del(`${basePath}/api/${type}/${id}`); - if (typeof response !== 'string') { + if (ok) { onSave(); } else { - setMessage(); + setMessage( + data || , + ); } }; diff --git a/components/forms/LoginForm.js b/components/forms/LoginForm.js index 074da868..3866f240 100644 --- a/components/forms/LoginForm.js +++ b/components/forms/LoginForm.js @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { Formik, Form, Field } from 'formik'; -import Router from 'next/router'; +import { useRouter } from 'next/router'; import { post } from 'lib/web'; import Button from 'components/common/Button'; import FormLayout, { @@ -28,13 +28,17 @@ const validate = ({ username, password }) => { }; export default function LoginForm() { + const router = useRouter(); const [message, setMessage] = useState(); const handleSubmit = async ({ username, password }) => { - const { ok, status, data } = await post('/api/auth/login', { username, password }); + const { ok, status, data } = await post(`${router.basePath}/api/auth/login`, { + username, + password, + }); if (ok) { - await Router.push('/'); + return router.push('/'); } else { setMessage( status === 401 ? ( diff --git a/components/forms/WebsiteEditForm.js b/components/forms/WebsiteEditForm.js index 822b7ea5..3432c2a4 100644 --- a/components/forms/WebsiteEditForm.js +++ b/components/forms/WebsiteEditForm.js @@ -11,6 +11,7 @@ import FormLayout, { } from 'components/layout/FormLayout'; import Checkbox from 'components/common/Checkbox'; import { DOMAIN_REGEX } from 'lib/constants'; +import { useRouter } from 'next/router'; const initialValues = { name: '', @@ -34,10 +35,11 @@ const validate = ({ name, domain }) => { }; export default function WebsiteEditForm({ values, onSave, onClose }) { + const { basePath } = useRouter(); const [message, setMessage] = useState(); const handleSubmit = async values => { - const { ok, data } = await post(`/api/website`, values); + const { ok, data } = await post(`${basePath}/api/website`, values); if (ok) { onSave(); diff --git a/hooks/useCountryNames.js b/hooks/useCountryNames.js index ca19c166..e631aecd 100644 --- a/hooks/useCountryNames.js +++ b/hooks/useCountryNames.js @@ -1,4 +1,5 @@ import { useState, useEffect } from 'react'; +import { useRouter } from 'next/router'; import { get } from 'lib/web'; import enUS from 'public/country/en-US.json'; @@ -8,9 +9,10 @@ const countryNames = { export default function useCountryNames(locale) { const [list, setList] = useState(countryNames[locale] || enUS); + const { basePath } = useRouter(); async function loadData(locale) { - const { ok, data } = await get(`/country/${locale}.json`); + const { ok, data } = await get(`${basePath}/country/${locale}.json`); if (ok) { countryNames[locale] = data; diff --git a/hooks/useFetch.js b/hooks/useFetch.js index 3250acd3..907f45af 100644 --- a/hooks/useFetch.js +++ b/hooks/useFetch.js @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { get } from 'lib/web'; import { updateQuery } from 'redux/actions/queries'; +import { useRouter } from 'next/router'; export default function useFetch(url, params = {}, options = {}) { const dispatch = useDispatch(); @@ -9,6 +10,7 @@ export default function useFetch(url, params = {}, options = {}) { const [status, setStatus] = useState(); const [error, setError] = useState(); const [loading, setLoadiing] = useState(false); + const { basePath } = useRouter(); const keys = Object.keys(params) .sort() .map(key => params[key]); @@ -19,7 +21,7 @@ export default function useFetch(url, params = {}, options = {}) { setLoadiing(true); setError(null); const time = performance.now(); - const { data, status } = await get(url, params); + const { data, status } = await get(`${basePath}${url}`, params); dispatch(updateQuery({ url, time: performance.now() - time, completed: Date.now() })); diff --git a/hooks/useRequireLogin.js b/hooks/useRequireLogin.js index ffebfca8..5fb93e76 100644 --- a/hooks/useRequireLogin.js +++ b/hooks/useRequireLogin.js @@ -1,6 +1,8 @@ import { useState, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { updateUser } from 'redux/actions/user'; +import { useRouter } from 'next/router'; +import { get } from '../lib/web'; export async function fetchUser() { const res = await fetch('/api/auth/verify'); @@ -13,29 +15,33 @@ export async function fetchUser() { } export default function useRequireLogin() { + const router = useRouter(); const dispatch = useDispatch(); const storeUser = useSelector(state => state.user); const [loading, setLoading] = useState(!storeUser); const [user, setUser] = useState(storeUser); + async function loadUser() { + setLoading(true); + + const { ok, data } = await get(`${router.basePath}/api/auth/verify`); + + if (!ok) { + return router.push('/login'); + } + + await dispatch(updateUser(data)); + + setUser(user); + setLoading(false); + } + useEffect(() => { if (!loading && user) { return; } - setLoading(true); - - fetchUser().then(async user => { - if (!user) { - window.location.href = '/login'; - return; - } - - await dispatch(updateUser(user)); - - setUser(user); - setLoading(false); - }); + loadUser(); }, []); return { user, loading }; diff --git a/package.json b/package.json index 9ddd6abb..5aeaf30e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "umami", - "version": "0.65.0", + "version": "0.66.0", "description": "A simple, fast, website analytics alternative to Google Analytics. ", "author": "Mike Cao ", "license": "MIT", diff --git a/pages/api/auth/logout.js b/pages/api/auth/logout.js index a78152f7..8d551dea 100644 --- a/pages/api/auth/logout.js +++ b/pages/api/auth/logout.js @@ -1,6 +1,6 @@ import { serialize } from 'cookie'; import { AUTH_COOKIE_NAME } from 'lib/constants'; -import { redirect } from 'lib/response'; +import { ok } from 'lib/response'; export default async (req, res) => { const cookie = serialize(AUTH_COOKIE_NAME, '', { @@ -11,5 +11,5 @@ export default async (req, res) => { res.setHeader('Set-Cookie', [cookie]); - return redirect(res, '/login'); + return ok(res); }; diff --git a/pages/logout.js b/pages/logout.js index 540a93e1..6f5af610 100644 --- a/pages/logout.js +++ b/pages/logout.js @@ -1,8 +1,12 @@ import { useEffect } from 'react'; +import { useRouter } from 'next/router'; export default function LogoutPage() { + const router = useRouter(); + const { basePath } = router; + useEffect(() => { - fetch('/api/auth/logout').then(() => (window.location.href = '/login')); + fetch(`${basePath}/api/auth/logout`).then(() => router.push('/login')); }, []); return null;