Add ntfy Basic auth, sign-out button, config-only credentials
- ntfy client supports HTTP Basic auth (username/password) for servers with access control; [ntfy] config gains username/password. Scheduler + Test Ntfy use it instead of the old settings-only bearer token. - Settings page no longer has credential inputs (Apify/eBay/ntfy/Resend); they are managed in config.toml. Read-only status + Test buttons remain. - Sidebar gains a Sign out button; in forward-auth mode it routes through the Authentik outpost sign_out so the IdP session is cleared.
This commit is contained in:
@@ -13,7 +13,12 @@ import (
|
||||
type Client struct {
|
||||
BaseURL string
|
||||
Token string
|
||||
HTTP *http.Client
|
||||
// Username/Password take precedence over Token when set, using HTTP Basic
|
||||
// auth (for ntfy servers that authenticate with user accounts rather than
|
||||
// access tokens).
|
||||
Username string
|
||||
Password string
|
||||
HTTP *http.Client
|
||||
}
|
||||
|
||||
func New(baseURL string) *Client {
|
||||
@@ -24,13 +29,23 @@ func New(baseURL string) *Client {
|
||||
}
|
||||
|
||||
// NewWithToken returns a ntfy Client with bearer-token auth set. Use this
|
||||
// when the ntfy server requires authentication.
|
||||
// when the ntfy server requires token authentication.
|
||||
func NewWithToken(baseURL, token string) *Client {
|
||||
c := New(baseURL)
|
||||
c.Token = strings.TrimSpace(token)
|
||||
return c
|
||||
}
|
||||
|
||||
// NewWithBasicAuth returns a ntfy Client that authenticates publishes with an
|
||||
// ntfy user account (HTTP Basic auth). Use this for servers configured with
|
||||
// auth-default-access: deny-all and per-user topic ACLs.
|
||||
func NewWithBasicAuth(baseURL, username, password string) *Client {
|
||||
c := New(baseURL)
|
||||
c.Username = strings.TrimSpace(username)
|
||||
c.Password = password
|
||||
return c
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
Topic string
|
||||
Title string
|
||||
@@ -58,7 +73,9 @@ func (c *Client) Send(ctx context.Context, n Notification) error {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
|
||||
if c.Token != "" {
|
||||
if c.Username != "" {
|
||||
req.SetBasicAuth(c.Username, c.Password)
|
||||
} else if c.Token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.Token)
|
||||
}
|
||||
if n.Title != "" {
|
||||
@@ -73,17 +90,18 @@ func (c *Client) Send(ctx context.Context, n Notification) error {
|
||||
if n.Click != "" {
|
||||
req.Header.Set("Click", n.Click)
|
||||
}
|
||||
tokenLen := len(c.Token)
|
||||
tokenPrefix := ""
|
||||
if tokenLen >= 4 {
|
||||
tokenPrefix = c.Token[:4]
|
||||
authMode := "none"
|
||||
switch {
|
||||
case c.Username != "":
|
||||
authMode = "basic"
|
||||
case c.Token != "":
|
||||
authMode = "bearer"
|
||||
}
|
||||
slog.Info("ntfy publish",
|
||||
"url", url,
|
||||
"topic", n.Topic,
|
||||
"auth_header_set", c.Token != "",
|
||||
"token_prefix", tokenPrefix,
|
||||
"token_len", tokenLen,
|
||||
"auth", authMode,
|
||||
"user", c.Username,
|
||||
)
|
||||
resp, err := c.HTTP.Do(req)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user