diff --git a/src/public/app/widgets/type_widgets/options/other/share_settings.js b/src/public/app/widgets/type_widgets/options/other/share_settings.js
index bee1b56fc..c0727a852 100644
--- a/src/public/app/widgets/type_widgets/options/other/share_settings.js
+++ b/src/public/app/widgets/type_widgets/options/other/share_settings.js
@@ -6,31 +6,19 @@ const TPL = `
${t('share.settings_title')}
-
-
`;
@@ -38,24 +26,18 @@ const TPL = `
export default class ShareSettingsWidget extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
-
- this.$shareRedirectUrl = this.$widget.find(".share-redirect-url");
- this.$loginRedirectUrl = this.$widget.find(".login-redirect-url");
+ this.$redirectBareDomain = this.$widget.find(".redirect-bare-domain");
this.$showLoginInShare = this.$widget.find(".show-login-in-share");
- this.$shareRedirectUrl.on('change', () =>
- this.updateOption('shareRedirectUrl', this.$shareRedirectUrl.val() || 'share'));
-
- this.$loginRedirectUrl.on('change', () =>
- this.updateOption('loginRedirectUrl', this.$loginRedirectUrl.val() || 'login'));
+ this.$redirectBareDomain.on('change', () =>
+ this.updateCheckboxOption('redirectBareDomain', this.$redirectBareDomain));
this.$showLoginInShare.on('change', () =>
this.updateCheckboxOption('showLoginInShareTheme', this.$showLoginInShare));
}
optionsLoaded(options) {
- this.$shareRedirectUrl.val(options.shareRedirectUrl || 'share');
- this.$loginRedirectUrl.val(options.loginRedirectUrl || 'login');
+ this.setCheckboxState(this.$redirectBareDomain, options.redirectBareDomain);
this.setCheckboxState(this.$showLoginInShare, options.showLoginInShareTheme);
}
}
diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json
index 76236412c..26a8f533d 100644
--- a/src/public/translations/en/translation.json
+++ b/src/public/translations/en/translation.json
@@ -1562,12 +1562,10 @@
"clipped-from": "Clipped from: %s"
},
"share": {
- "settings_title": "Share and Login Settings",
- "redirect_url_label": "Share Redirect URL",
- "redirect_url_description": "URL to redirect to when user is not logged in (default: 'share')",
- "login_redirect_url_label": "Login Redirect URL",
- "login_redirect_url_description": "URL to redirect to for login page (default: '/login')",
- "show_login_label": "Show login link in share theme",
- "show_login_description": "When enabled, displays a login link in the share theme interface (default: false)"
+ "settings_title": "Share Settings",
+ "redirect_bare_domain": "Redirect bare domain to share",
+ "redirect_bare_domain_description": "When enabled, accessing the root URL (/) will redirect to the share page (/share)",
+ "show_login_in_share": "Show login in share theme",
+ "show_login_in_share_description": "When enabled, shows a login button in the share theme"
}
}
diff --git a/src/routes/routes.ts b/src/routes/routes.ts
index 52faa1b57..1e11f65cb 100644
--- a/src/routes/routes.ts
+++ b/src/routes/routes.ts
@@ -54,7 +54,7 @@ import clipperRoute from "./api/clipper.js";
import similarNotesRoute from "./api/similar_notes.js";
import keysRoute from "./api/keys.js";
import backendLogRoute from "./api/backend_log.js";
-import statsRoute from "./api/stats.js";
+import statsRoute from "../stats/stats.js";
import fontsRoute from "./api/fonts.js";
import etapiTokensApiRoutes from "./api/etapi_tokens.js";
import relationMapApiRoute from "./api/relation-map.js";
@@ -102,6 +102,15 @@ const uploadMiddlewareWithErrorHandling = function (req: express.Request, res: e
};
function register(app: express.Application) {
+ // Add bare domain redirect handler
+ app.use((req, res, next) => {
+ if (req.path === '/' && optionService.getOption('redirectBareDomain')) {
+ res.redirect('/share');
+ } else {
+ next();
+ }
+ });
+
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
route(GET, '/login', [auth.checkAppInitialized, auth.checkPasswordSet], loginRoute.loginPage);
route(GET, '/set-password', [auth.checkAppInitialized, auth.checkPasswordNotSet], loginRoute.setPasswordPage);
@@ -110,6 +119,9 @@ function register(app: express.Application) {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // limit each IP to 10 requests per windowMs
skipSuccessfulRequests: true // successful auth to rate-limited ETAPI routes isn't counted. However, successful auth to /login is still counted!
+ message: 'Too many login attempts, please try again later.',
+ standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
+ legacyHeaders: false // Disable the `X-RateLimit-*` headers
});
route(PST, '/login', [loginRateLimiter], loginRoute.login);