diff --git a/src/public/app/widgets/type_widgets/options/other/share_settings.ts b/src/public/app/widgets/type_widgets/options/other/share_settings.ts index 199605082..abc540b49 100644 --- a/src/public/app/widgets/type_widgets/options/other/share_settings.ts +++ b/src/public/app/widgets/type_widgets/options/other/share_settings.ts @@ -2,44 +2,91 @@ import OptionsWidget from "../options_widget.js"; import options from "../../../../services/options.js"; import { t } from "../../../../services/i18n.js"; import type { OptionMap, OptionNames } from "../../../../../../services/options_interface.js"; +import searchService from "../../../../services/search.js"; const TPL = `
-

${t("share.title")}

-

${t("share.redirect_bare_domain_description")}

+ + -

${t("share.show_login_link_description")}

`; export default class ShareSettingsOptions extends OptionsWidget { + private $shareRootCheck!: JQuery; + private $shareRootStatus!: JQuery; + doRender() { this.$widget = $(TPL); this.contentSized(); + this.$shareRootCheck = this.$widget.find('.share-root-check'); + this.$shareRootStatus = this.$widget.find('.share-root-status'); + // Add change handlers for both checkboxes - this.$widget.find('input[type="checkbox"]').on("change", () => this.save()); + this.$widget.find('input[type="checkbox"]').on("change", (e: JQuery.ChangeEvent) => { + this.save(); + + // Show/hide share root status section based on redirectBareDomain checkbox + const target = e.target as HTMLInputElement; + if (target.name === 'redirectBareDomain') { + this.$shareRootCheck.toggle(target.checked); + if (target.checked) { + this.checkShareRoot(); + } + } + }); + + // Add click handler for check share root button + this.$widget.find('.check-share-root').on("click", () => this.checkShareRoot()); } async optionsLoaded(options: OptionMap) { - this.$widget.find('input[name="redirectBareDomain"]').prop("checked", options.redirectBareDomain === "true"); + const redirectBareDomain = options.redirectBareDomain === "true"; + this.$widget.find('input[name="redirectBareDomain"]').prop("checked", redirectBareDomain); + this.$shareRootCheck.toggle(redirectBareDomain); + if (redirectBareDomain) { + await this.checkShareRoot(); + } - this.$widget.find('input[name="showLoginInShareTheme"]').prop("checked", options.showLoginInShareTheme === "true"); + this.$widget.find('input[name="shareSubtree"]').prop("checked", options.shareSubtree === "true"); + } + + async checkShareRoot() { + const shareRootNotes = await searchService.searchNotes("#shareRoot", { + includeArchivedNotes: true, + ignoreHoistedNote: true + }); + + if (shareRootNotes.length > 0) { + this.$shareRootStatus + .removeClass('text-danger') + .addClass('text-success') + .text(t("share.share_root_found", {noteTitle: shareRootNotes[0].title})); + } else { + this.$shareRootStatus + .removeClass('text-success') + .addClass('text-danger') + .text(t("share.share_root_not_found")); + } } async save() { const redirectBareDomain = this.$widget.find('input[name="redirectBareDomain"]').prop("checked"); await this.updateOption<"redirectBareDomain">("redirectBareDomain", redirectBareDomain.toString()); - const showLoginInShareTheme = this.$widget.find('input[name="showLoginInShareTheme"]').prop("checked"); - await this.updateOption<"showLoginInShareTheme">("showLoginInShareTheme", showLoginInShareTheme.toString()); + const showLoginInShareTheme = this.$widget.find('input[name="shareSubtree"]').prop("checked"); + await this.updateOption<"shareSubtree">("shareSubtree", showLoginInShareTheme.toString()); } } diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json index f2978237d..c0ee99e4b 100644 --- a/src/public/translations/en/translation.json +++ b/src/public/translations/en/translation.json @@ -1660,7 +1660,10 @@ "redirect_bare_domain": "Redirect bare domain to Share page", "redirect_bare_domain_description": "When enabled, accessing the root URL will redirect to the Share page instead of Login", "show_login_link": "Show Login link in Share theme", - "show_login_link_description": "Add a login link to the Share page footer" + "show_login_link_description": "Add a login link to the Share page footer", + "check_share_root": "Check Share Root Status", + "share_root_found": "Share root found: {{noteTitle}}", + "share_root_not_found": "No note with #shareRoot label found. Set up a note with #shareRoot label first." }, "time_selector": { "invalid_input": "The entered time value is not a valid number." diff --git a/src/services/auth.ts b/src/services/auth.ts index 68c497b91..03f40e6e7 100644 --- a/src/services/auth.ts +++ b/src/services/auth.ts @@ -8,6 +8,7 @@ import passwordEncryptionService from "./encryption/password_encryption.js"; import config from "./config.js"; import passwordService from "./encryption/password.js"; import options from "./options.js"; +import attributes from "./attributes.js"; import type { NextFunction, Request, Response } from "express"; const noAuthentication = config.General && config.General.noAuthentication === true; @@ -16,7 +17,15 @@ function checkAuth(req: Request, res: Response, next: NextFunction) { if (!sqlInit.isDbInitialized()) { res.redirect("setup"); } else if (!req.session.loggedIn && !isElectron && !noAuthentication) { - const redirectToShare = options.getOption("redirectBareDomain") === "true"; + const redirectToShare = options.getOptionBool("redirectBareDomain"); + if (redirectToShare) { + // Check if any note has the #shareRoot label + const shareRootNotes = attributes.getNotesWithLabel("shareRoot"); + if (shareRootNotes.length === 0) { + res.status(404).json({ message: "Share root not found. Please set up a note with #shareRoot label first." }); + return; + } + } res.redirect(redirectToShare ? "share" : "login"); } else { next();