Login flow fixes
- Validate push URL - Default values for push URL and topic if not set - setup-ntfy uses already set or default values if input is empty
This commit is contained in:
parent
635548699f
commit
796303fc05
|
@ -5,6 +5,10 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/0ranki/hydroxide-push/auth"
|
"github.com/0ranki/hydroxide-push/auth"
|
||||||
"github.com/0ranki/hydroxide-push/config"
|
"github.com/0ranki/hydroxide-push/config"
|
||||||
"github.com/0ranki/hydroxide-push/events"
|
"github.com/0ranki/hydroxide-push/events"
|
||||||
|
@ -13,9 +17,6 @@ import (
|
||||||
"github.com/0ranki/hydroxide-push/protonmail"
|
"github.com/0ranki/hydroxide-push/protonmail"
|
||||||
imapserver "github.com/emersion/go-imap/server"
|
imapserver "github.com/emersion/go-imap/server"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -57,7 +58,7 @@ func askPass(prompt string) ([]byte, error) {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func listenEventsAndNotify(addr string, debug bool, authManager *auth.Manager, eventsManager *events.Manager, tlsConfig *tls.Config) error {
|
func listenEventsAndNotify(addr string, debug bool, authManager *auth.Manager, eventsManager *events.Manager, tlsConfig *tls.Config) {
|
||||||
be := imapbackend.New(authManager, eventsManager)
|
be := imapbackend.New(authManager, eventsManager)
|
||||||
s := imapserver.New(be)
|
s := imapserver.New(be)
|
||||||
s.Addr = addr
|
s.Addr = addr
|
||||||
|
@ -71,39 +72,6 @@ func listenEventsAndNotify(addr string, debug bool, authManager *auth.Manager, e
|
||||||
for {
|
for {
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupNtfy() {
|
|
||||||
err := cfg.Read()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
var n string
|
|
||||||
if cfg.URL != "" && cfg.Topic != "" {
|
|
||||||
fmt.Printf("Current push endpoint: %s\n", cfg.String())
|
|
||||||
n = "new "
|
|
||||||
}
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
|
||||||
fmt.Printf("Input %spush server URL (e.g. 'http://ntfy.sh') : ", n)
|
|
||||||
scanner.Scan()
|
|
||||||
cfg.URL = scanner.Text()
|
|
||||||
scanner = bufio.NewScanner(os.Stdin)
|
|
||||||
fmt.Printf("Input push topic (e.g. my-proton-notifications): ")
|
|
||||||
scanner.Scan()
|
|
||||||
cfg.Topic = scanner.Text()
|
|
||||||
fmt.Printf("Using URL %s\n", cfg.String())
|
|
||||||
err = cfg.Save()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
err = ntfy.LoginBridge(&cfg)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
fmt.Println("Notification configuration saved")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const usage = `usage: hydroxide-push [options...] <command>
|
const usage = `usage: hydroxide-push [options...] <command>
|
||||||
|
@ -146,6 +114,11 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = cfg.Read()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
cmd := flag.Arg(0)
|
cmd := flag.Arg(0)
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case "auth":
|
case "auth":
|
||||||
|
@ -244,14 +217,7 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
cfg.BridgePw = bridgePassword
|
cfg.BridgePw = bridgePassword
|
||||||
reply, err := ntfy.AskToSaveBridgePw(&cfg)
|
cfg.Setup()
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if reply != "yes" {
|
|
||||||
fmt.Println("Bridge password:", bridgePassword)
|
|
||||||
}
|
|
||||||
setupNtfy()
|
|
||||||
case "status":
|
case "status":
|
||||||
usernames, err := auth.ListUsernames()
|
usernames, err := auth.ListUsernames()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -268,11 +234,11 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case "setup-ntfy":
|
case "setup-ntfy":
|
||||||
setupNtfy()
|
cfg.Setup()
|
||||||
case "notify":
|
case "notify":
|
||||||
authManager := auth.NewManager(newClient)
|
authManager := auth.NewManager(newClient)
|
||||||
eventsManager := events.NewManager()
|
eventsManager := events.NewManager()
|
||||||
log.Fatal(listenEventsAndNotify("0", debug, authManager, eventsManager, tlsConfig))
|
listenEventsAndNotify("0", debug, authManager, eventsManager, tlsConfig)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Print(usage)
|
fmt.Print(usage)
|
||||||
|
|
105
ntfy/ntfy.go
105
ntfy/ntfy.go
|
@ -2,12 +2,14 @@ package ntfy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -23,7 +25,22 @@ type NtfyConfig struct {
|
||||||
BridgePw string `json:"bridgePw"`
|
BridgePw string `json:"bridgePw"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *NtfyConfig) String() string {
|
func (cfg *NtfyConfig) Init() {
|
||||||
|
if cfg.Topic == "" {
|
||||||
|
r := make([]byte, 12)
|
||||||
|
_, err := rand.Read(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
cfg.Topic = strings.Replace(base64.StdEncoding.EncodeToString(r), "/", "+", -1)
|
||||||
|
|
||||||
|
}
|
||||||
|
if cfg.URL == "" {
|
||||||
|
cfg.URL = "http://ntfy.sh"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *NtfyConfig) URI() string {
|
||||||
return fmt.Sprintf("%s/%s", cfg.URL, cfg.Topic)
|
return fmt.Sprintf("%s/%s", cfg.URL, cfg.Topic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,39 +66,38 @@ func Notify() {
|
||||||
log.Printf("error reading notification: %v", err)
|
log.Printf("error reading notification: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest("POST", cfg.String(), strings.NewReader("New message received"))
|
req, _ := http.NewRequest("POST", cfg.URI(), strings.NewReader("New message received"))
|
||||||
req.Header.Set("Title", "ProtoMail")
|
req.Header.Set("Title", "ProtoMail")
|
||||||
req.Header.Set("Click", "dismiss")
|
req.Header.Set("Click", "dismiss")
|
||||||
req.Header.Set("Tags", "envelope")
|
req.Header.Set("Tags", "envelope")
|
||||||
http.DefaultClient.Do(req)
|
if _, err := http.DefaultClient.Do(req); err != nil {
|
||||||
|
log.Printf("failed to publish to push topic: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("Push event sent")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read reads the configuration from file. Creates the file
|
||||||
|
// if it does not exist
|
||||||
func (cfg *NtfyConfig) Read() error {
|
func (cfg *NtfyConfig) Read() error {
|
||||||
f, err := ntfyConfigFile()
|
f, err := ntfyConfigFile()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
b, err := os.ReadFile(f)
|
b, err := os.ReadFile(f)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = json.Unmarshal(b, &cfg)
|
err = json.Unmarshal(b, &cfg)
|
||||||
|
} else if strings.HasSuffix(err.Error(), "no such file or directory") {
|
||||||
|
cfg.Init()
|
||||||
|
err = cfg.Save()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
cfg.Init()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AskToSaveBridgePw(cfg *NtfyConfig) (string, error) {
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
|
||||||
//fmt.Printf("Save bridge password to config?\nThe password is stored in plain text, but (yes/n): ")
|
|
||||||
//scanner.Scan()
|
|
||||||
//if scanner.Text() == "yes" {
|
|
||||||
if err := cfg.Save(); err != nil {
|
|
||||||
return "", errors.New("failed to save notification config")
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
return scanner.Text(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoginBridge(cfg *NtfyConfig) error {
|
func LoginBridge(cfg *NtfyConfig) error {
|
||||||
if cfg.BridgePw == "" {
|
if cfg.BridgePw == "" {
|
||||||
cfg.BridgePw = os.Getenv("HYDROXIDE_BRIDGE_PASSWORD")
|
cfg.BridgePw = os.Getenv("HYDROXIDE_BRIDGE_PASSWORD")
|
||||||
|
@ -91,10 +107,7 @@ func LoginBridge(cfg *NtfyConfig) error {
|
||||||
fmt.Printf("Bridge password: ")
|
fmt.Printf("Bridge password: ")
|
||||||
scanner.Scan()
|
scanner.Scan()
|
||||||
cfg.BridgePw = scanner.Text()
|
cfg.BridgePw = scanner.Text()
|
||||||
_, err := AskToSaveBridgePw(cfg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -133,3 +146,53 @@ func Login(cfg *NtfyConfig, be backend.Backend) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cfg *NtfyConfig) Setup() {
|
||||||
|
var n string
|
||||||
|
if cfg.URL != "" && cfg.Topic != "" {
|
||||||
|
fmt.Printf("Current push endpoint: %s\n", cfg.URI())
|
||||||
|
n = "new "
|
||||||
|
}
|
||||||
|
// Read push base URL
|
||||||
|
notValid := true
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
for notValid {
|
||||||
|
tmpURL := cfg.URL
|
||||||
|
fmt.Printf("Input %spush server URL ('%s') : ", n, cfg.URL)
|
||||||
|
scanner.Scan()
|
||||||
|
if len(scanner.Text()) > 0 {
|
||||||
|
tmpURL = scanner.Text()
|
||||||
|
}
|
||||||
|
if _, err := url.ParseRequestURI(tmpURL); err != nil {
|
||||||
|
fmt.Printf("Not a valid URL: %s\n", tmpURL)
|
||||||
|
} else {
|
||||||
|
notValid = false
|
||||||
|
cfg.URL = tmpURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scanner = bufio.NewScanner(os.Stdin)
|
||||||
|
// Read push topic
|
||||||
|
fmt.Printf("Input push topic ('%s'): ", cfg.Topic)
|
||||||
|
scanner.Scan()
|
||||||
|
if len(scanner.Text()) > 0 {
|
||||||
|
cfg.Topic = scanner.Text()
|
||||||
|
}
|
||||||
|
fmt.Printf("Using URL %s\n", cfg.URI())
|
||||||
|
// Save bridge password
|
||||||
|
if len(cfg.BridgePw) == 0 {
|
||||||
|
err := LoginBridge(cfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Bridge password is set")
|
||||||
|
}
|
||||||
|
// Save configuration
|
||||||
|
err := cfg.Save()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Println("Notification configuration saved")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue