From eda2c07ea3480c5e5f5e7833a4f447c8f9406dce Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Sat, 11 Nov 2023 20:45:09 -0800 Subject: [PATCH] Allow embedding of share page. --- next.config.js | 51 +++++++++++-------- src/app/(main)/{Shell.tsx => App.tsx} | 4 +- src/app/(main)/dashboard/page.tsx | 2 +- src/app/(main)/layout.tsx | 8 +-- ...portsDataTable.js => ReportsDataTable.tsx} | 4 +- src/app/(main)/reports/page.tsx | 2 +- src/app/layout.tsx | 14 ++--- src/app/logout/page.tsx | 5 ++ src/app/share/[...id]/page.tsx | 5 ++ src/pages/api/send.ts | 2 +- 10 files changed, 58 insertions(+), 39 deletions(-) rename src/app/(main)/{Shell.tsx => App.tsx} (90%) rename src/app/(main)/reports/{ReportsDataTable.js => ReportsDataTable.tsx} (80%) diff --git a/next.config.js b/next.config.js index cf7dce7f..03c30c55 100644 --- a/next.config.js +++ b/next.config.js @@ -3,29 +3,32 @@ require('dotenv').config(); const path = require('path'); const pkg = require('./package.json'); -const contentSecurityPolicy = ` - default-src 'self'; - img-src *; - script-src 'self' 'unsafe-eval' 'unsafe-inline'; - style-src 'self' 'unsafe-inline'; - connect-src 'self' api.umami.is; - frame-ancestors 'self' ${process.env.ALLOWED_FRAME_URLS}; -`; +const contentSecurityPolicy = [ + `default-src 'self'`, + `img-src *`, + `script-src 'self' 'unsafe-eval' 'unsafe-inline'`, + `style-src 'self' 'unsafe-inline'`, + `connect-src 'self' api.umami.is`, +]; const headers = [ { key: 'X-DNS-Prefetch-Control', value: 'on', }, - { + !process.env.ALLOWED_FRAME_URLS && { key: 'X-Frame-Options', value: 'SAMEORIGIN', }, - { - key: 'Content-Security-Policy', - value: contentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(), - }, -]; +].filter(n => n); + +const cspHeader = (values = []) => ({ + key: 'Content-Security-Policy', + value: [...contentSecurityPolicy, ...values] + .join(';') + .replace(/\s{2,}/g, ' ') + .trim(), +}); if (process.env.FORCE_SSL) { headers.push({ @@ -81,14 +84,13 @@ const config = { reactStrictMode: false, env: { basePath: basePath || '', - cloudMode: !!process.env.CLOUD_MODE, - cloudUrl: process.env.CLOUD_URL, + cloudMode: process.env.CLOUD_MODE || '', + cloudUrl: process.env.CLOUD_URL || '', configUrl: '/config', currentVersion: pkg.version, - defaultLocale: process.env.DEFAULT_LOCALE, - disableLogin: process.env.DISABLE_LOGIN, - disableUI: process.env.DISABLE_UI, - isProduction: process.env.NODE_ENV === 'production', + defaultLocale: process.env.DEFAULT_LOCALE || '', + disableLogin: process.env.DISABLE_LOGIN || '', + disableUI: process.env.DISABLE_UI || '', }, basePath, output: 'standalone', @@ -125,7 +127,14 @@ const config = { return [ { source: '/:path*', - headers, + headers: [ + ...headers, + cspHeader([`frame-ancestors 'self' ${process.env.ALLOWED_FRAME_URLS || ''}`]), + ], + }, + { + source: '/share/:path*', + headers: [...headers, cspHeader()], }, ]; }, diff --git a/src/app/(main)/Shell.tsx b/src/app/(main)/App.tsx similarity index 90% rename from src/app/(main)/Shell.tsx rename to src/app/(main)/App.tsx index 980abb62..daf98fb1 100644 --- a/src/app/(main)/Shell.tsx +++ b/src/app/(main)/App.tsx @@ -4,7 +4,7 @@ import { usePathname } from 'next/navigation'; import UpdateNotice from 'components/common/UpdateNotice'; import { useRequireLogin, useConfig } from 'components/hooks'; -export function Shell({ children }) { +export function App({ children }) { const { user } = useRequireLogin(); const config = useConfig(); const pathname = usePathname(); @@ -24,4 +24,4 @@ export function Shell({ children }) { ); } -export default Shell; +export default App; diff --git a/src/app/(main)/dashboard/page.tsx b/src/app/(main)/dashboard/page.tsx index 91cc9c6e..1853a9f5 100644 --- a/src/app/(main)/dashboard/page.tsx +++ b/src/app/(main)/dashboard/page.tsx @@ -1,7 +1,7 @@ import Dashboard from 'app/(main)/dashboard/Dashboard'; import { Metadata } from 'next'; -export default function DashboardPage() { +export default function () { return ; } diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index 1c9cc277..f5aeab67 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -1,11 +1,11 @@ -import Shell from './Shell'; +import App from './App'; import NavBar from './NavBar'; import Page from 'components/layout/Page'; import styles from './layout.module.css'; -export default function AppLayout({ children }) { +export default function ({ children }) { return ( - +
-
+ ); } diff --git a/src/app/(main)/reports/ReportsDataTable.js b/src/app/(main)/reports/ReportsDataTable.tsx similarity index 80% rename from src/app/(main)/reports/ReportsDataTable.js rename to src/app/(main)/reports/ReportsDataTable.tsx index 0daa3d06..0ca853dc 100644 --- a/src/app/(main)/reports/ReportsDataTable.js +++ b/src/app/(main)/reports/ReportsDataTable.tsx @@ -5,9 +5,9 @@ import useFilterQuery from 'components/hooks/useFilterQuery'; import DataTable from 'components/common/DataTable'; import useCache from 'store/cache'; -export default function ReportsDataTable({ websiteId }) { +export default function ReportsDataTable({ websiteId }: { websiteId?: string }) { const { get } = useApi(); - const modified = useCache(state => state?.reports); + const modified = useCache(state => (state as any)?.reports); const queryResult = useFilterQuery(['reports', { websiteId, modified }], params => get(websiteId ? `/websites/${websiteId}/reports` : `/reports`, params), ); diff --git a/src/app/(main)/reports/page.tsx b/src/app/(main)/reports/page.tsx index aba59db2..22e6e2a7 100644 --- a/src/app/(main)/reports/page.tsx +++ b/src/app/(main)/reports/page.tsx @@ -1,7 +1,7 @@ import ReportsHeader from './ReportsHeader'; import ReportsDataTable from './ReportsDataTable'; -export default function ReportsPage() { +export default function () { return ( <> diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e2478a95..970c33f0 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -8,16 +8,16 @@ import 'styles/locale.css'; import 'styles/index.css'; import 'styles/variables.css'; -export default function RootLayout({ children }) { +export default function ({ children }) { return ( - - - - - - + + + + + + diff --git a/src/app/logout/page.tsx b/src/app/logout/page.tsx index bce24736..89a3bce9 100644 --- a/src/app/logout/page.tsx +++ b/src/app/logout/page.tsx @@ -1,5 +1,10 @@ import Logout from './Logout'; +import { Metadata } from 'next'; export default function () { return ; } + +export const metadata: Metadata = { + title: 'Logout | umami', +}; diff --git a/src/app/share/[...id]/page.tsx b/src/app/share/[...id]/page.tsx index ca154165..2a69f406 100644 --- a/src/app/share/[...id]/page.tsx +++ b/src/app/share/[...id]/page.tsx @@ -1,5 +1,10 @@ import Share from './Share'; +import { Metadata } from 'next'; export default function ({ params: { id } }) { return ; } + +export const metadata: Metadata = { + title: 'umami', +}; diff --git a/src/pages/api/send.ts b/src/pages/api/send.ts index e8d3e386..cf3004f3 100644 --- a/src/pages/api/send.ts +++ b/src/pages/api/send.ts @@ -74,7 +74,7 @@ export default async (req: NextApiRequestCollect, res: NextApiResponse) => { await useCors(req, res); if (req.method === 'POST') { - if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) { + if (!process.env.DISABLE_BOT_CHECK && isbot(req.headers['user-agent'])) { return ok(res); }