Просмотр исходного кода

Merge remote-tracking branch 'theatischbein/feat_optional_require_login' into require-login

binwiederhier 6 месяцев назад
Родитель
Сommit
ec1f97b726

+ 1 - 0
cmd/serve.go

@@ -63,6 +63,7 @@ var flagsServe = append(
 	altsrc.NewBoolFlag(&cli.BoolFlag{Name: "enable-signup", Aliases: []string{"enable_signup"}, EnvVars: []string{"NTFY_ENABLE_SIGNUP"}, Value: false, Usage: "allows users to sign up via the web app, or API"}),
 	altsrc.NewBoolFlag(&cli.BoolFlag{Name: "enable-login", Aliases: []string{"enable_login"}, EnvVars: []string{"NTFY_ENABLE_LOGIN"}, Value: false, Usage: "allows users to log in via the web app, or API"}),
 	altsrc.NewBoolFlag(&cli.BoolFlag{Name: "enable-reservations", Aliases: []string{"enable_reservations"}, EnvVars: []string{"NTFY_ENABLE_RESERVATIONS"}, Value: false, Usage: "allows users to reserve topics (if their tier allows it)"}),
+	altsrc.NewBoolFlag(&cli.BoolFlag{Name: "require-login", Aliases: []string{"require_login"}, EnvVars: []string{"NTFY_REQUIRE_LOGIN"}, Value: false, Usage: "all actions via the web app requires a login"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "upstream-base-url", Aliases: []string{"upstream_base_url"}, EnvVars: []string{"NTFY_UPSTREAM_BASE_URL"}, Value: "", Usage: "forward poll request to an upstream server, this is needed for iOS push notifications for self-hosted servers"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "upstream-access-token", Aliases: []string{"upstream_access_token"}, EnvVars: []string{"NTFY_UPSTREAM_ACCESS_TOKEN"}, Value: "", Usage: "access token to use for the upstream server; needed only if upstream rate limits are exceeded or upstream server requires auth"}),
 	altsrc.NewStringFlag(&cli.StringFlag{Name: "smtp-sender-addr", Aliases: []string{"smtp_sender_addr"}, EnvVars: []string{"NTFY_SMTP_SENDER_ADDR"}, Usage: "SMTP server address (host:port) for outgoing emails"}),

+ 1 - 0
docs/config.md

@@ -1698,6 +1698,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
 | `enable-signup`                            | `NTFY_ENABLE_SIGNUP`                            | *boolean* (`true` or `false`)                       | `false`           | Allows users to sign up via the web app, or API                                                                                                                                                                                 |
 | `enable-login`                             | `NTFY_ENABLE_LOGIN`                             | *boolean* (`true` or `false`)                       | `false`           | Allows users to log in via the web app, or API                                                                                                                                                                                  |
 | `enable-reservations`                      | `NTFY_ENABLE_RESERVATIONS`                      | *boolean* (`true` or `false`)                       | `false`           | Allows users to reserve topics (if their tier allows it)                                                                                                                                                                        |
+| `require-login`                            | `NTFY_REQUIRE_LOGIN`                            | *boolean* (`true` or `false`)                       | `false`           | All actions via the web app require a login                                                                                                                                                                        |
 | `stripe-secret-key`                        | `NTFY_STRIPE_SECRET_KEY`                        | *string*                                            | -                 | Payments: Key used for the Stripe API communication, this enables payments                                                                                                                                                      |
 | `stripe-webhook-key`                       | `NTFY_STRIPE_WEBHOOK_KEY`                       | *string*                                            | -                 | Payments: Key required to validate the authenticity of incoming webhooks from Stripe                                                                                                                                            |
 | `billing-contact`                          | `NTFY_BILLING_CONTACT`                          | *email address* or *website*                        | -                 | Payments: Email or website displayed in Upgrade dialog as a billing contact                                                                                                                                                     |

+ 1 - 0
server/config.go

@@ -256,6 +256,7 @@ func NewConfig() *Config {
 		EnableSignup:                         false,
 		EnableLogin:                          false,
 		EnableReservations:                   false,
+		RequireLogin:                         false,
 		AccessControlAllowOrigin:             "*",
 		Version:                              "",
 		WebPushPrivateKey:                    "",

+ 1 - 0
server/server.go

@@ -605,6 +605,7 @@ func (s *Server) handleWebConfig(w http.ResponseWriter, _ *http.Request, _ *visi
 		EnableCalls:        s.config.TwilioAccount != "",
 		EnableEmails:       s.config.SMTPSenderFrom != "",
 		EnableReservations: s.config.EnableReservations,
+		ReuqireLogin:       s.config.RequireLogin,
 		EnableWebPush:      s.config.WebPushPublicKey != "",
 		BillingContact:     s.config.BillingContact,
 		WebPushPublicKey:   s.config.WebPushPublicKey,

+ 2 - 0
server/server.yml

@@ -259,10 +259,12 @@
 # - enable-signup allows users to sign up via the web app, or API
 # - enable-login allows users to log in via the web app, or API
 # - enable-reservations allows users to reserve topics (if their tier allows it)
+# - require-login all user actions via the web app require a login
 #
 # enable-signup: false
 # enable-login: false
 # enable-reservations: false
+# require-login: false
 
 # Server URL of a Firebase/APNS-connected ntfy server (likely "https://ntfy.sh").
 #

+ 1 - 0
server/types.go

@@ -455,6 +455,7 @@ type apiConfigResponse struct {
 	EnableEmails       bool     `json:"enable_emails"`
 	EnableReservations bool     `json:"enable_reservations"`
 	EnableWebPush      bool     `json:"enable_web_push"`
+	RequireLogin       bool     `json:"require_login"`
 	BillingContact     string   `json:"billing_contact"`
 	WebPushPublicKey   string   `json:"web_push_public_key"`
 	DisallowedTopics   []string `json:"disallowed_topics"`

+ 2 - 0
web/public/static/langs/en.json

@@ -97,6 +97,8 @@
   "notifications_none_for_any_description": "To send notifications to a topic, simply PUT or POST to the topic URL. Here's an example using one of your topics.",
   "notifications_no_subscriptions_title": "It looks like you don't have any subscriptions yet.",
   "notifications_no_subscriptions_description": "Click the \"{{linktext}}\" link to create or subscribe to a topic. After that, you can send messages via PUT or POST and you'll receive notifications here.",
+  "notifications_no_subscriptions_login_title": "This page requires a Login.",
+  "notifications_no_subscriptions_login_description": "Click \"{{linktext}}\" to login into your account.",
   "notifications_example": "Example",
   "notifications_more_details": "For more information, check out the <websiteLink>website</websiteLink> or <docsLink>documentation</docsLink>.",
   "display_name_dialog_title": "Change display name",

+ 7 - 1
web/src/components/Navigation.jsx

@@ -135,7 +135,7 @@ const NavList = (props) => {
         {showNotificationContextNotSupportedBox && <NotificationContextNotSupportedAlert />}
         {showNotificationIOSInstallRequired && <NotificationIOSInstallRequiredAlert />}
         {alertVisible && <Divider />}
-        {!showSubscriptionsList && (
+        {!showSubscriptionsList && (session.exists() || !config.require_login) && (
           <ListItemButton onClick={() => navigate(routes.app)} selected={location.pathname === config.app_root}>
             <ListItemIcon>
               <ChatBubble />
@@ -164,30 +164,36 @@ const NavList = (props) => {
             <ListItemText primary={t("nav_button_account")} />
           </ListItemButton>
         )}
+        {session.exists() || !config.require_login && (
         <ListItemButton onClick={() => navigate(routes.settings)} selected={location.pathname === routes.settings}>
           <ListItemIcon>
             <SettingsIcon />
           </ListItemIcon>
           <ListItemText primary={t("nav_button_settings")} />
         </ListItemButton>
+        )}
         <ListItemButton onClick={() => openUrl("/docs")}>
           <ListItemIcon>
             <ArticleIcon />
           </ListItemIcon>
           <ListItemText primary={t("nav_button_documentation")} />
         </ListItemButton>
+        {session.exists() || !config.require_login && (
         <ListItemButton onClick={() => props.onPublishMessageClick()}>
           <ListItemIcon>
             <Send />
           </ListItemIcon>
           <ListItemText primary={t("nav_button_publish_message")} />
         </ListItemButton>
+        )}
+        {session.exists() || !config.require_login && (
         <ListItemButton onClick={() => setSubscribeDialogOpen(true)}>
           <ListItemIcon>
             <AddIcon />
           </ListItemIcon>
           <ListItemText primary={t("nav_button_subscribe")} />
         </ListItemButton>
+        )}
         {showUpgradeBanner && (
           // The text background gradient didn't seem to do well with switching between light/dark mode,
           // So adding a `key` forces React to replace the entire component when the theme changes

+ 7 - 2
web/src/components/Notifications.jsx

@@ -46,6 +46,7 @@ import priority5 from "../img/priority-5.svg";
 import logoOutline from "../img/ntfy-outline.svg";
 import AttachmentIcon from "./AttachmentIcon";
 import { useAutoSubscribe } from "./hooks";
+import session from "../app/Session";
 
 const priorityFiles = {
   1: priority1,
@@ -644,12 +645,16 @@ const NoSubscriptions = () => {
       <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}>
         <img src={logoOutline} height="64" width="64" alt={t("action_bar_logo_alt")} />
         <br />
-        {t("notifications_no_subscriptions_title")}
+        {!session.exists() && !config.require_login && t("notifications_no_subscriptions_title")}
+        {!session.exists() && config.require_login && t("notifications_no_subscriptions_login_title")}
       </Typography>
       <Paragraph>
-        {t("notifications_no_subscriptions_description", {
+        {!session.exists() && !config.require_login && t("notifications_no_subscriptions_description", {
           linktext: t("nav_button_subscribe"),
         })}
+        {!session.exists() && config.require_login && t("notifications_no_subscriptions_login_description", {
+          linktext: t("action_bar_sign_in"),
+        })}
       </Paragraph>
       <Paragraph>
         <ForMoreDetails />

+ 16 - 10
web/src/components/Preferences.jsx

@@ -65,16 +65,22 @@ const maybeUpdateAccountSettings = async (payload) => {
   }
 };
 
-const Preferences = () => (
-  <Container maxWidth="md" sx={{ marginTop: 3, marginBottom: 3 }}>
-    <Stack spacing={3}>
-      <Notifications />
-      <Reservations />
-      <Users />
-      <Appearance />
-    </Stack>
-  </Container>
-);
+const Preferences = () => {
+  if (!session.exists() or !config.requireLogin) {
+    window.location.href = routes.app;
+    return <></>;
+  }
+    return (
+        <Container maxWidth="md" sx={{ marginTop: 3, marginBottom: 3 }}>
+            <Stack spacing={3}>
+              <Notifications />
+              <Reservations />
+              <Users />
+              <Appearance />
+            </Stack>
+        </Container>
+    );
+};
 
 const Notifications = () => {
   const { t } = useTranslation();