From 24ddf41331bc9138760984c6edd9e8a9adcfe074 Mon Sep 17 00:00:00 2001 From: Maxime-J Date: Wed, 6 Jul 2022 13:56:37 +0000 Subject: [PATCH 01/12] tracker: collect in one place with fetch --- tracker/index.js | 69 ++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/tracker/index.js b/tracker/index.js index f6329633..6b571499 100644 --- a/tracker/index.js +++ b/tracker/index.js @@ -43,21 +43,6 @@ import { removeTrailingSlash } from '../lib/url'; /* Collect metrics */ - const post = (url, data, callback) => { - const req = new XMLHttpRequest(); - req.open('POST', url, true); - req.setRequestHeader('Content-Type', 'application/json'); - if (cache) req.setRequestHeader('x-umami-cache', cache); - - req.onreadystatechange = () => { - if (req.readyState === 4) { - callback(req.response); - } - }; - - req.send(JSON.stringify(data)); - }; - const getPayload = () => ({ website, hostname, @@ -73,17 +58,22 @@ import { removeTrailingSlash } from '../lib/url'; return a; }; - const collect = (type, payload) => { + const collect = (type, payload, persist = false) => { if (trackingDisabled()) return; - - post( - `${root}/api/collect`, - { - type, - payload, - }, - res => (cache = res), - ); + const endpoint = `${root}/api/collect`; + let headers = { 'Content-Type': 'application/json' }; + if (cache) headers['x-umami-cache'] = cache; + let options = { + method: 'POST', + body: JSON.stringify({type, payload}), + headers + }; + if (!persist) { + fetch(endpoint, options).then(res => res.text()).then(resText => { cache = resText }); + } else { + options['keepalive'] = true; + fetch(endpoint, options); + } }; const trackView = (url = currentUrl, referrer = currentRef, uuid = website) => { @@ -93,7 +83,7 @@ import { removeTrailingSlash } from '../lib/url'; website: uuid, url, referrer, - }), + }) ); }; @@ -105,28 +95,21 @@ import { removeTrailingSlash } from '../lib/url'; url, event_type, event_value, - }), + }) ); }; /* Handle events */ - const sendEvent = (value, type) => { - const payload = getPayload(); - - payload.event_type = type; - payload.event_value = value; - - const data = JSON.stringify({ - type: 'event', - payload, - }); - - fetch(`${root}/api/collect`, { - method: 'POST', - body: data, - keepalive: true, - }); + const sendEvent = (event_value, event_type) => { + collect( + 'event', + assign(getPayload(), { + event_type, + event_value, + }), + true + ); }; const addEvents = node => { From 9b7e472410aa87f377fc4f3f60e456488fabd0ff Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 8 Aug 2022 11:31:36 -0700 Subject: [PATCH 02/12] Added CURRENT_VERSION constant. --- components/layout/Footer.js | 8 +++----- lib/constants.js | 1 + pages/api/scripts/telemetry.js | 18 +++++++++--------- store/version.js | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/components/layout/Footer.js b/components/layout/Footer.js index f9c2ba87..c8035fef 100644 --- a/components/layout/Footer.js +++ b/components/layout/Footer.js @@ -4,11 +4,9 @@ import classNames from 'classnames'; import { FormattedMessage } from 'react-intl'; import Link from 'components/common/Link'; import styles from './Footer.module.css'; -import useStore from 'store/version'; -import { HOMEPAGE_URL, REPO_URL } from 'lib/constants'; +import { CURRENT_VERSION, HOMEPAGE_URL, REPO_URL } from 'lib/constants'; export default function Footer() { - const { current } = useStore(); const { pathname } = useRouter(); return ( @@ -28,9 +26,9 @@ export default function Footer() { />
- {`v${current}`} + {`v${CURRENT_VERSION}`}
- {!pathname.includes('/share/') && `} + defaultValue={``} readOnly /> From 6cfe910ba95e05c19c125c3f90bd20dfbd742655 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 9 Aug 2022 13:09:41 -0700 Subject: [PATCH 04/12] Added update-tracker script. Updated docker build. --- Dockerfile | 7 +------ package.json | 3 ++- scripts/update-tracker.js | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 scripts/update-tracker.js diff --git a/Dockerfile b/Dockerfile index e6cc888c..672e19bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,15 +12,11 @@ WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . -ARG DATABASE_URL ARG DATABASE_TYPE ARG BASE_PATH -ARG DISABLE_LOGIN -ENV DATABASE_URL $DATABASE_URL ENV DATABASE_TYPE $DATABASE_TYPE ENV BASE_PATH $BASE_PATH -ENV DISABLE_LOGIN $DISABLE_LOGIN ENV NEXT_TELEMETRY_DISABLED 1 @@ -36,8 +32,7 @@ ENV NEXT_TELEMETRY_DISABLED 1 RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs -RUN yarn global add prisma -RUN yarn add npm-run-all dotenv +RUN yarn add npm-run-all dotenv prisma # You only need to copy next.config.js if you are NOT using the default configuration COPY --from=builder /app/next.config.js . diff --git a/package.json b/package.json index ddca158b..f5c43c06 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dev": "next dev", "build": "npm-run-all build-tracker build-geo build-db build-app", "start": "npm-run-all check-db start-next", - "start-docker": "npm-run-all check-db build-tracker start-server", + "start-docker": "npm-run-all check-db update-tracker start-server", "start-env": "node scripts/start-env.js", "start-server": "node server.js", "start-next": "next start", @@ -24,6 +24,7 @@ "build-geo": "node scripts/build-geo.js", "build-db-schema": "prisma db pull", "build-db-client": "prisma generate", + "update-tracker": "node scripts/update-tracker.js", "update-db": "prisma migrate deploy", "check-db": "node scripts/check-db.js", "copy-db-files": "node scripts/copy-db-files.js", diff --git a/scripts/update-tracker.js b/scripts/update-tracker.js new file mode 100644 index 00000000..3955d45e --- /dev/null +++ b/scripts/update-tracker.js @@ -0,0 +1,18 @@ +require('dotenv').config(); +const fs = require('fs'); +const path = require('path'); + +const endPoint = process.env.COLLECT_API_ENDPOINT; + +if (endPoint) { + const file = path.resolve(__dirname, '../public/umami.js'); + + const tracker = fs.readFileSync(file); + + fs.writeFileSync( + path.resolve(file), + tracker.toString().replace(/"\/api\/collect"/g, `"${endPoint}"`), + ); + + console.log(`Updated tracker endpoint with "${endPoint}"`); +} From d556806c640fe7f0ea09d74a6efb826038a8415d Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 9 Aug 2022 13:36:24 -0700 Subject: [PATCH 05/12] Updated docker tracker update. --- Dockerfile | 2 +- scripts/update-tracker.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 672e19bf..48f3df32 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,7 +36,7 @@ RUN yarn add npm-run-all dotenv prisma # You only need to copy next.config.js if you are NOT using the default configuration COPY --from=builder /app/next.config.js . -COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/public ./public COPY --from=builder /app/package.json ./package.json COPY --from=builder /app/prisma ./prisma COPY --from=builder /app/scripts ./scripts diff --git a/scripts/update-tracker.js b/scripts/update-tracker.js index 3955d45e..6b9e96c7 100644 --- a/scripts/update-tracker.js +++ b/scripts/update-tracker.js @@ -14,5 +14,5 @@ if (endPoint) { tracker.toString().replace(/"\/api\/collect"/g, `"${endPoint}"`), ); - console.log(`Updated tracker endpoint with "${endPoint}"`); + console.log(`Updated tracker endpoint: ${endPoint}.`); } From 5873a56fff048e2e87a2cb6b63bcec270340d588 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 9 Aug 2022 14:58:27 -0700 Subject: [PATCH 06/12] Updated check updates logic. --- components/common/UpdateNotice.js | 9 ++------- components/layout/Header.js | 10 +++++++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/components/common/UpdateNotice.js b/components/common/UpdateNotice.js index bc27215e..8bba1694 100644 --- a/components/common/UpdateNotice.js +++ b/components/common/UpdateNotice.js @@ -6,15 +6,10 @@ import { setItem } from 'lib/web'; import { REPO_URL, VERSION_CHECK } from 'lib/constants'; import Button from './Button'; import styles from './UpdateNotice.module.css'; -import useUser from 'hooks/useUser'; -import useConfig from 'hooks/useConfig'; export default function UpdateNotice() { - const { user } = useUser(); - const { updatesDisabled } = useConfig(); const { latest, checked, hasUpdate, releaseUrl } = useStore(); const [dismissed, setDismissed] = useState(false); - const allowCheck = user?.is_admin && !updatesDisabled; const updateCheck = useCallback(() => { setItem(VERSION_CHECK, { version: latest, time: Date.now() }); @@ -32,12 +27,12 @@ export default function UpdateNotice() { } useEffect(() => { - if (!checked && allowCheck) { + if (!checked) { checkVersion(); } }, [checked]); - if (!hasUpdate || dismissed || !allowCheck) { + if (!hasUpdate || dismissed) { return null; } diff --git a/components/layout/Header.js b/components/layout/Header.js index 0d36429d..c6942ef5 100644 --- a/components/layout/Header.js +++ b/components/layout/Header.js @@ -8,22 +8,26 @@ import ThemeButton from 'components/settings/ThemeButton'; import HamburgerButton from 'components/common/HamburgerButton'; import UpdateNotice from 'components/common/UpdateNotice'; import UserButton from 'components/settings/UserButton'; -import useUser from 'hooks/useUser'; import { HOMEPAGE_URL } from 'lib/constants'; +import useConfig from '/hooks/useConfig'; +import useUser from 'hooks/useUser'; import Logo from 'assets/logo.svg'; import styles from './Header.module.css'; export default function Header() { const { user } = useUser(); const { pathname } = useRouter(); + const { updatesDisabled } = useConfig(); + const isSharePage = pathname.includes('/share/'); + const allowUpdate = user?.is_admin && !updatesDisabled && !isSharePage; return ( <> - + {allowUpdate && }
} size="large" className={styles.logo} /> - umami + umami
{user && ( From b426bbd8129fd27cb97b4789624da68ef5198e86 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 10 Aug 2022 00:01:00 -0700 Subject: [PATCH 07/12] add console log. look for 01 last applied --- scripts/check-db.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/check-db.js b/scripts/check-db.js index df1c50ab..821e7f74 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -63,8 +63,11 @@ async function run(cmd, args) { async function checkMigrations() { const output = await run('prisma', ['migrate', 'status']); + console.log(output); + const missingMigrations = output.includes('have not yet been applied'); - const missingInitialMigration = output.includes('01_init'); + const missingInitialMigration = + output.includes('01_init') && !output.includes('The last common migration is: 01_init'); const notManaged = output.includes('The current database is not managed'); if (notManaged || missingMigrations) { From 8068b26df704d125175b212345106c8d0ef4174c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Radenac?= <47008408+clem3109@users.noreply.github.com> Date: Wed, 10 Aug 2022 11:32:11 +0200 Subject: [PATCH 08/12] Update fr-FR.json --- lang/fr-FR.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/fr-FR.json b/lang/fr-FR.json index 72ca575e..ca0b7e41 100644 --- a/lang/fr-FR.json +++ b/lang/fr-FR.json @@ -67,7 +67,7 @@ "message.confirm-reset": "Êtes-vous sûr de vouloir réinistialiser les statistiques de {target} ?", "message.copied": "Copié !", "message.delete-warning": "Toutes les données associées seront également supprimées.", - "message.edit-dashboard": "Edit dashboard", + "message.edit-dashboard": "Modifier l'ordre des sites", "message.failure": "Un problème est survenu.", "message.get-share-url": "Obtenir l'URL de partage", "message.get-tracking-code": "Obtenir le code de suivi", From a34de1084436a2edaeb35f1180c5ca21a2ef3e2d Mon Sep 17 00:00:00 2001 From: MagicLike Date: Wed, 10 Aug 2022 13:54:49 +0200 Subject: [PATCH 09/12] Update de-DE.json Added translations for "query-parameters" and "edit-dashboard" --- lang/de-DE.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/de-DE.json b/lang/de-DE.json index d0346417..297de6a2 100644 --- a/lang/de-DE.json +++ b/lang/de-DE.json @@ -67,7 +67,7 @@ "message.confirm-reset": "Sind Sie sicher, dass Sie die Statistiken von {target} zurücksetzen wollen?", "message.copied": "In Zwischenablage kopiert!", "message.delete-warning": "Alle zugehörigen Daten werden ebenfalls gelöscht.", - "message.edit-dashboard": "Edit dashboard", + "message.edit-dashboard": "Dashboard bearbeiten", "message.failure": "Es ist ein Fehler aufgetreten.", "message.get-share-url": "Freigabe-URL abrufen", "message.get-tracking-code": "Erstelle Tracking Kennung", @@ -103,7 +103,7 @@ "metrics.operating-systems": "Betriebssysteme", "metrics.page-views": "Seitenaufrufe", "metrics.pages": "Seiten", - "metrics.query-parameters": "Query parameters", + "metrics.query-parameters": "Abfrageparameter", "metrics.referrers": "Referrer", "metrics.screens": "Bildschirmauflösungen", "metrics.unique-visitors": "Eindeutige Besucher", From 8c504ff9230cb95219bf5765a740c9b06a585c4d Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 11 Aug 2022 10:07:26 -0700 Subject: [PATCH 10/12] align index names if error --- db/postgresql/migrations/02_add_event_data/migration.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/db/postgresql/migrations/02_add_event_data/migration.sql b/db/postgresql/migrations/02_add_event_data/migration.sql index 62587e29..24c22e35 100644 --- a/db/postgresql/migrations/02_add_event_data/migration.sql +++ b/db/postgresql/migrations/02_add_event_data/migration.sql @@ -54,13 +54,13 @@ CREATE UNIQUE INDEX "event_data_event_id_key" ON "event_data"("event_id"); ALTER TABLE "event_data" ADD CONSTRAINT "event_data_event_id_fkey" FOREIGN KEY ("event_id") REFERENCES "event"("event_id") ON DELETE RESTRICT ON UPDATE CASCADE; -- RenameIndex -ALTER INDEX "account.username_unique" RENAME TO "account_username_key"; +ALTER INDEX IF EXISTS "account.username_unique" RENAME TO "account_username_key"; -- RenameIndex -ALTER INDEX "session.session_uuid_unique" RENAME TO "session_session_uuid_key"; +ALTER INDEX IF EXISTS "session.session_uuid_unique" RENAME TO "session_session_uuid_key"; -- RenameIndex -ALTER INDEX "website.share_id_unique" RENAME TO "website_share_id_key"; +ALTER INDEX IF EXISTS "website.share_id_unique" RENAME TO "website_share_id_key"; -- RenameIndex -ALTER INDEX "website.website_uuid_unique" RENAME TO "website_website_uuid_key"; \ No newline at end of file +ALTER INDEX IF EXISTS "website.website_uuid_unique" RENAME TO "website_website_uuid_key"; \ No newline at end of file From e269ace88f33c012a2abe1ea358afafd820983bd Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 11 Aug 2022 11:33:21 -0700 Subject: [PATCH 11/12] add logic to mysql migration --- .../02_add_event_data/migration.sql | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/db/mysql/migrations/02_add_event_data/migration.sql b/db/mysql/migrations/02_add_event_data/migration.sql index c210895d..b781984c 100644 --- a/db/mysql/migrations/02_add_event_data/migration.sql +++ b/db/mysql/migrations/02_add_event_data/migration.sql @@ -49,14 +49,42 @@ CREATE TABLE `event_data` ( -- AddForeignKey ALTER TABLE `event_data` ADD CONSTRAINT `event_data_event_id_fkey` FOREIGN KEY (`event_id`) REFERENCES `event`(`event_id`) ON DELETE RESTRICT ON UPDATE CASCADE; --- RenameIndex -ALTER TABLE `account` RENAME INDEX `username` TO `account_username_key`; +-- CreateProcedureRenameIndex +CREATE PROCEDURE `UmamiRenameIndexIfExists`( + IN i_table_name VARCHAR(128), + IN i_current_index_name VARCHAR(128), + IN i_new_index_name VARCHAR(128) + ) + BEGIN + + SET @tableName = i_table_name; + SET @currentIndexName = i_current_index_name; + SET @newIndexName = i_new_index_name; + SET @indexExists = 0; + + SELECT + 1 + INTO @indexExists FROM + INFORMATION_SCHEMA.STATISTICS + WHERE + TABLE_NAME = @tableName + AND INDEX_NAME = @currentIndexName; + + SET @query = CONCAT( + 'ALTER TABLE `', @tableName, '` RENAME INDEX `', @currentIndexName, '` TO `', @newIndexName, '`;' + ); + IF @indexExists THEN + PREPARE stmt FROM @query; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + END IF; +END; -- RenameIndex -ALTER TABLE `session` RENAME INDEX `session_uuid` TO `session_session_uuid_key`; +CALL UmamiRenameIndexIfExists('account', 'username', 'account_username_key'); +CALL UmamiRenameIndexIfExists('session', 'session_uuid', 'session_session_uuid_key'); +CALL UmamiRenameIndexIfExists('website', 'share_id', 'website_share_id_key'); +CALL UmamiRenameIndexIfExists('website', 'website_uuid', 'website_website_uuid_key'); --- RenameIndex -ALTER TABLE `website` RENAME INDEX `share_id` TO `website_share_id_key`; - --- RenameIndex -ALTER TABLE `website` RENAME INDEX `website_uuid` TO `website_website_uuid_key`; \ No newline at end of file +-- Drop CreateProcedureRenameIndex +drop procedure `UmamiRenameIndexIfExists`; \ No newline at end of file From 0f976be5d812010a589c5b755672df525bbd5262 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 11 Aug 2022 22:29:18 -0700 Subject: [PATCH 12/12] Updated docker urls. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f29fd217..0967220f 100644 --- a/README.md +++ b/README.md @@ -76,12 +76,12 @@ docker-compose up Alternatively, to pull just the Umami Docker image with PostgreSQL support: ```bash -docker pull docker.umami.is/umami-software/umami:postgresql-latest +docker pull docker.umami.dev/umami-software/umami:postgresql-latest ``` Or with MySQL support: ```bash -docker pull docker.umami.is/umami-software/umami:mysql-latest +docker pull docker.umami.dev/umami-software/umami:mysql-latest ``` ## Getting updates