diff --git a/options/locale_next/locale_en-US.json b/options/locale_next/locale_en-US.json
index cc06102c46..23e35af318 100644
--- a/options/locale_next/locale_en-US.json
+++ b/options/locale_next/locale_en-US.json
@@ -12,5 +12,6 @@
"one": "wants to merge %[1]d commit from %[2]s
into %[3]s
",
"other": "wants to merge %[1]d commits from %[2]s
into %[3]s
"
},
- "search.milestone_kind": "Search milestones..."
+ "search.milestone_kind": "Search milestones...",
+ "incorrect_root_url": "This Forgejo instance is configured to be served on \"%s\". You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini."
}
diff --git a/templates/base/head_script.tmpl b/templates/base/head_script.tmpl
index 22e08e9c8f..d2774010b6 100644
--- a/templates/base/head_script.tmpl
+++ b/templates/base/head_script.tmpl
@@ -42,6 +42,7 @@ If you introduce mistakes in it, Gitea JavaScript code wouldn't run correctly.
modal_confirm: {{ctx.Locale.Tr "modal.confirm"}},
modal_cancel: {{ctx.Locale.Tr "modal.cancel"}},
more_items: {{ctx.Locale.Tr "more_items"}},
+ incorrect_root_url: {{ctx.Locale.Tr "incorrect_root_url" AppUrl}},
},
};
{{/* in case some pages don't render the pageData, we make sure it is an object to prevent null access */}}
diff --git a/tests/e2e/login.test.e2e.ts b/tests/e2e/login.test.e2e.ts
new file mode 100644
index 0000000000..1ffa0b2e5d
--- /dev/null
+++ b/tests/e2e/login.test.e2e.ts
@@ -0,0 +1,33 @@
+// Copyright 2025 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// @watch start
+// templates/user/auth/**
+// web_src/js/features/user-**
+// web_src/js/features/common-global.js
+// @watch end
+
+import {expect} from '@playwright/test';
+import {test, save_visual, test_context} from './utils_e2e.ts';
+
+test('Mismatched ROOT_URL', async ({browser}) => {
+ const context = await test_context(browser);
+ const page = await context.newPage();
+
+ // Ugly hack to override the appUrl of `window.config`.
+ await page.addInitScript(() => {
+ setInterval(() => {
+ if (window.config) {
+ window.config.appUrl = 'https://example.com';
+ }
+ }, 1);
+ });
+
+ const response = await page.goto('/user/login');
+ expect(response?.status()).toBe(200);
+
+ await save_visual(page);
+ const globalError = page.locator('.js-global-error');
+ await expect(globalError).toContainText('This Forgejo instance is configured to be served on ');
+ await expect(globalError).toContainText('You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini.');
+});
diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js
index b05f6e07fe..7848a14b66 100644
--- a/web_src/js/features/common-global.js
+++ b/web_src/js/features/common-global.js
@@ -458,6 +458,6 @@ export function checkAppUrl() {
if (curUrl.startsWith(appUrl) || `${curUrl}/` === appUrl) {
return;
}
- showGlobalErrorMessage(`Your ROOT_URL in app.ini is "${appUrl}", it's unlikely matching the site you are visiting.
-Mismatched ROOT_URL config causes wrong URL links for web UI/mail content/webhook notification/OAuth2 sign-in.`);
+
+ showGlobalErrorMessage(i18n.incorrect_root_url);
}
diff --git a/web_src/js/features/user-auth.js b/web_src/js/features/user-auth.js
index a871ac471c..64519037c7 100644
--- a/web_src/js/features/user-auth.js
+++ b/web_src/js/features/user-auth.js
@@ -5,8 +5,6 @@ export function initUserAuthOauth2() {
if (!outer) return;
const inner = document.getElementById('oauth2-login-navigator-inner');
- checkAppUrl();
-
for (const link of outer.querySelectorAll('.oauth-login-link')) {
link.addEventListener('click', () => {
inner.classList.add('tw-invisible');
@@ -20,3 +18,8 @@ export function initUserAuthOauth2() {
});
}
}
+
+export function initUserAuth() {
+ if (!document.querySelector('.user.signin')) return;
+ checkAppUrl();
+}
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 6797617414..7d44b9ff56 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -24,7 +24,7 @@ import {initFindFileInRepo} from './features/repo-findfile.js';
import {initCommentContent, initMarkupContent} from './markup/content.js';
import {initPdfViewer} from './render/pdf.js';
-import {initUserAuthOauth2} from './features/user-auth.js';
+import {initUserAuthOauth2, initUserAuth} from './features/user-auth.js';
import {
initRepoIssueDue,
initRepoIssueReferenceRepositorySearch,
@@ -184,6 +184,7 @@ onDomReady(() => {
initUserAuthOauth2();
initUserAuthWebAuthn();
initUserAuthWebAuthnRegister();
+ initUserAuth();
initRepoDiffView();
initPdfViewer();
initScopedAccessTokenCategories();