mirror of
				https://github.com/binwiederhier/ntfy.git
				synced 2025-10-31 13:02:24 +01:00 
			
		
		
		
	
							parent
							
								
									4b86085a8c
								
							
						
					
					
						commit
						9684629549
					
				
					 7 changed files with 65 additions and 21 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,7 @@ | |||
| dist/ | ||||
| build/ | ||||
| .idea/ | ||||
| *.swp | ||||
| server/docs/ | ||||
| server/site/ | ||||
| tools/fbsend/fbsend | ||||
|  |  | |||
|  | @ -3,15 +3,16 @@ package cmd | |||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"github.com/urfave/cli/v2" | ||||
| 	"github.com/urfave/cli/v2/altsrc" | ||||
| 	"heckel.io/ntfy/server" | ||||
| 	"heckel.io/ntfy/util" | ||||
| 	"log" | ||||
| 	"math" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/urfave/cli/v2" | ||||
| 	"github.com/urfave/cli/v2/altsrc" | ||||
| 	"heckel.io/ntfy/server" | ||||
| 	"heckel.io/ntfy/util" | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
|  | @ -146,8 +147,10 @@ func execServe(c *cli.Context) error { | |||
| 		return errors.New("if set, web-root must be 'home' or 'app'") | ||||
| 	} | ||||
| 
 | ||||
| 	// Default auth permissions | ||||
| 	webRootIsApp := webRoot == "app" | ||||
| 	enableWeb := webRoot != "disable" | ||||
| 
 | ||||
| 	// Default auth permissions | ||||
| 	authDefaultRead := authDefaultAccess == "read-write" || authDefaultAccess == "read-only" | ||||
| 	authDefaultWrite := authDefaultAccess == "read-write" || authDefaultAccess == "write-only" | ||||
| 
 | ||||
|  | @ -227,6 +230,7 @@ func execServe(c *cli.Context) error { | |||
| 	conf.VisitorEmailLimitBurst = visitorEmailLimitBurst | ||||
| 	conf.VisitorEmailLimitReplenish = visitorEmailLimitReplenish | ||||
| 	conf.BehindProxy = behindProxy | ||||
| 	conf.EnableWeb = enableWeb | ||||
| 	s, err := server.New(conf) | ||||
| 	if err != nil { | ||||
| 		log.Fatalln(err) | ||||
|  |  | |||
|  | @ -802,7 +802,7 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`). | |||
| | `smtp-server-addr-prefix`                  | `NTFY_SMTP_SERVER_ADDR_PREFIX`                  | `[ip]:port`                                         | -            | Optional prefix for the e-mail addresses to prevent spam, e.g. `ntfy-`                                                                                                                                                          | | ||||
| | `keepalive-interval`                       | `NTFY_KEEPALIVE_INTERVAL`                       | *duration*                                          | 45s          | Interval in which keepalive messages are sent to the client. This is to prevent intermediaries closing the connection for inactivity. Note that the Android app has a hardcoded timeout at 77s, so it should be less than that. | | ||||
| | `manager-interval`                         | `$NTFY_MANAGER_INTERVAL`                        | *duration*                                          | 1m           | Interval in which the manager prunes old messages, deletes topics and prints the stats.                                                                                                                                         | | ||||
| | `web-root`                                 | `NTFY_WEB_ROOT`                                 | `app` or `home`                                     | `app`        | Sets web root to landing page (home) or web app (app)                                                                                                                                                                           | | ||||
| | `web-root`                                 | `NTFY_WEB_ROOT`                                 | `app` or `home`                                     | `app`        | Sets web root to landing page (home), web app (app) or (disable) for no WebUI.                                                                                                                                                  | | ||||
| | `global-topic-limit`                       | `NTFY_GLOBAL_TOPIC_LIMIT`                       | *number*                                            | 15,000       | Rate limiting: Total number of topics before the server rejects new topics.                                                                                                                                                     | | ||||
| | `visitor-subscription-limit`               | `NTFY_VISITOR_SUBSCRIPTION_LIMIT`               | *number*                                            | 30           | Rate limiting: Number of subscriptions per visitor (IP address)                                                                                                                                                                 | | ||||
| | `visitor-attachment-total-size-limit`      | `NTFY_VISITOR_ATTACHMENT_TOTAL_SIZE_LIMIT`      | *size*                                              | 100M         | Rate limiting: Total storage limit used for attachments per visitor, for all attachments combined. Storage is freed after attachments expire. See `attachment-expiry-duration`.                                                 | | ||||
|  |  | |||
|  | @ -88,6 +88,7 @@ type Config struct { | |||
| 	VisitorEmailLimitBurst               int | ||||
| 	VisitorEmailLimitReplenish           time.Duration | ||||
| 	BehindProxy                          bool | ||||
| 	EnableWeb                            bool | ||||
| } | ||||
| 
 | ||||
| // NewConfig instantiates a default new server config | ||||
|  | @ -126,5 +127,6 @@ func NewConfig() *Config { | |||
| 		VisitorEmailLimitBurst:               DefaultVisitorEmailLimitBurst, | ||||
| 		VisitorEmailLimitReplenish:           DefaultVisitorEmailLimitReplenish, | ||||
| 		BehindProxy:                          false, | ||||
| 		EnableWeb:                            true, | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -8,11 +8,6 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"github.com/emersion/go-smtp" | ||||
| 	"github.com/gorilla/websocket" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| 	"heckel.io/ntfy/auth" | ||||
| 	"heckel.io/ntfy/util" | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"net" | ||||
|  | @ -28,6 +23,12 @@ import ( | |||
| 	"sync" | ||||
| 	"time" | ||||
| 	"unicode/utf8" | ||||
| 
 | ||||
| 	"github.com/emersion/go-smtp" | ||||
| 	"github.com/gorilla/websocket" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| 	"heckel.io/ntfy/auth" | ||||
| 	"heckel.io/ntfy/util" | ||||
| ) | ||||
| 
 | ||||
| // Server is the main server, providing the UI and API for ntfy | ||||
|  | @ -262,19 +263,19 @@ func (s *Server) handle(w http.ResponseWriter, r *http.Request) { | |||
| } | ||||
| 
 | ||||
| func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visitor) error { | ||||
| 	if r.Method == http.MethodGet && r.URL.Path == "/" { | ||||
| 	if r.Method == http.MethodGet && r.URL.Path == "/" && s.config.EnableWeb { | ||||
| 		return s.handleHome(w, r) | ||||
| 	} else if r.Method == http.MethodGet && r.URL.Path == "/example.html" { | ||||
| 	} else if r.Method == http.MethodGet && r.URL.Path == "/example.html" && s.config.EnableWeb { | ||||
| 		return s.handleExample(w, r) | ||||
| 	} else if r.Method == http.MethodHead && r.URL.Path == "/" { | ||||
| 		return s.handleEmpty(w, r, v) | ||||
| 	} else if r.Method == http.MethodGet && r.URL.Path == webConfigPath { | ||||
| 	} else if r.Method == http.MethodGet && r.URL.Path == webConfigPath && s.config.EnableWeb { | ||||
| 		return s.handleWebConfig(w, r) | ||||
| 	} else if r.Method == http.MethodGet && r.URL.Path == userStatsPath { | ||||
| 		return s.handleUserStats(w, r, v) | ||||
| 	} else if r.Method == http.MethodGet && staticRegex.MatchString(r.URL.Path) { | ||||
| 	} else if r.Method == http.MethodGet && staticRegex.MatchString(r.URL.Path) && s.config.EnableWeb { | ||||
| 		return s.handleStatic(w, r) | ||||
| 	} else if r.Method == http.MethodGet && docsRegex.MatchString(r.URL.Path) { | ||||
| 	} else if r.Method == http.MethodGet && docsRegex.MatchString(r.URL.Path) && s.config.EnableWeb { | ||||
| 		return s.handleDocs(w, r) | ||||
| 	} else if r.Method == http.MethodGet && fileRegex.MatchString(r.URL.Path) && s.config.AttachmentCacheDir != "" { | ||||
| 		return s.limitRequests(s.handleFile)(w, r, v) | ||||
|  |  | |||
|  | @ -127,7 +127,8 @@ | |||
| # manager-interval: "1m" | ||||
| 
 | ||||
| # Defines if the root route (/) is pointing to the landing page (as on ntfy.sh) or the | ||||
| # web app. If you self-host, you don't want to change this. Can be "app" (default) or "home". | ||||
| # web app. If you self-host, you don't want to change this. | ||||
| # Can be "app" (default), "home" or "disable" to disable the WebUI. | ||||
| # | ||||
| # web-root: app | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,9 +6,6 @@ import ( | |||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"heckel.io/ntfy/auth" | ||||
| 	"heckel.io/ntfy/util" | ||||
| 	"math/rand" | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
|  | @ -18,6 +15,10 @@ import ( | |||
| 	"sync" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 	"heckel.io/ntfy/auth" | ||||
| 	"heckel.io/ntfy/util" | ||||
| ) | ||||
| 
 | ||||
| func TestServer_PublishAndPoll(t *testing.T) { | ||||
|  | @ -162,6 +163,40 @@ func TestServer_StaticSites(t *testing.T) { | |||
| 	require.Contains(t, rr.Body.String(), "</html>") | ||||
| } | ||||
| 
 | ||||
| func TestServer_WebEnabled(t *testing.T) { | ||||
| 	conf := newTestConfig(t) | ||||
| 	conf.EnableWeb = false | ||||
| 	s := newTestServer(t, conf) | ||||
| 
 | ||||
| 	rr := request(t, s, "GET", "/", "", nil) | ||||
| 	require.Equal(t, 404, rr.Code) | ||||
| 
 | ||||
| 	rr = request(t, s, "GET", "/example.html", "", nil) | ||||
| 	require.Equal(t, 404, rr.Code) | ||||
| 
 | ||||
| 	rr = request(t, s, "GET", "/config.js", "", nil) | ||||
| 	require.Equal(t, 404, rr.Code) | ||||
| 
 | ||||
| 	rr = request(t, s, "GET", "/static/css/home.css", "", nil) | ||||
| 	require.Equal(t, 404, rr.Code) | ||||
| 
 | ||||
| 	conf2 := newTestConfig(t) | ||||
| 	conf2.EnableWeb = true | ||||
| 	s2 := newTestServer(t, conf2) | ||||
| 
 | ||||
| 	rr = request(t, s2, "GET", "/", "", nil) | ||||
| 	require.Equal(t, 200, rr.Code) | ||||
| 
 | ||||
| 	rr = request(t, s2, "GET", "/example.html", "", nil) | ||||
| 	require.Equal(t, 200, rr.Code) | ||||
| 
 | ||||
| 	rr = request(t, s2, "GET", "/config.js", "", nil) | ||||
| 	require.Equal(t, 200, rr.Code) | ||||
| 
 | ||||
| 	rr = request(t, s2, "GET", "/static/css/home.css", "", nil) | ||||
| 	require.Equal(t, 200, rr.Code) | ||||
| } | ||||
| 
 | ||||
| func TestServer_PublishLargeMessage(t *testing.T) { | ||||
| 	c := newTestConfig(t) | ||||
| 	c.AttachmentCacheDir = "" // Disable attachments | ||||
|  | @ -1303,7 +1338,7 @@ func firebaseServiceAccountFile(t *testing.T) string { | |||
| 		return os.Getenv("NTFY_TEST_FIREBASE_SERVICE_ACCOUNT_FILE") | ||||
| 	} else if os.Getenv("NTFY_TEST_FIREBASE_SERVICE_ACCOUNT") != "" { | ||||
| 		filename := filepath.Join(t.TempDir(), "firebase.json") | ||||
| 		require.NotNil(t, os.WriteFile(filename, []byte(os.Getenv("NTFY_TEST_FIREBASE_SERVICE_ACCOUNT")), 0600)) | ||||
| 		require.NotNil(t, os.WriteFile(filename, []byte(os.Getenv("NTFY_TEST_FIREBASE_SERVICE_ACCOUNT")), 0o600)) | ||||
| 		return filename | ||||
| 	} | ||||
| 	t.SkipNow() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Curid
						Curid