Add notification channels and a provider abstraction
Users get a notification_channels table (replacing users.ntfy_topic); pages fan
out to every enabled channel through a notify.Provider registry, with ntfy as
the first provider. Fallbacks are typed {type, address}. Schema edited in place:
existing databases must be recreated.
Claude-Session: https://claude.ai/code/session_016mBLURvJoMuUEr9cB2RpUN
This commit is contained in:
@@ -7,6 +7,8 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"git.ryuvia.com/niklas/terdut-server/internal/api"
|
||||
)
|
||||
|
||||
// The bootstrap user is an administrator; everybody it creates afterwards is
|
||||
@@ -96,8 +98,9 @@ func TestAdmin_MemberIsRefusedAdministration(t *testing.T) {
|
||||
map[string]string{"password": "hunter2-hunter2"}},
|
||||
{"mint a key for the admin", http.MethodPost, "/api/users/1/api-keys",
|
||||
map[string]string{"name": "borrowed"}},
|
||||
{"retarget the admin's notifications", http.MethodPut, "/api/users/1/notify",
|
||||
map[string]string{"ntfy_topic": "attacker-topic"}},
|
||||
{"add a channel to the admin's notifications", http.MethodPost, "/api/users/1/channels",
|
||||
map[string]string{"type": "ntfy", "address": "attacker-topic"}},
|
||||
{"read the admin's channels", http.MethodGet, "/api/users/1/channels", nil},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@@ -111,14 +114,14 @@ func TestAdmin_MemberIsRefusedAdministration(t *testing.T) {
|
||||
|
||||
// Being refused other people's accounts must not cost a user their own.
|
||||
func TestAdmin_MemberKeepsTheirOwnAccount(t *testing.T) {
|
||||
s := newTS(t)
|
||||
s := newTS(t, api.NotifyConfig{Providers: newFakeNtfy(t).providers()})
|
||||
memberID, call := member(t, s, "member")
|
||||
self := "/api/users/" + id64(memberID)
|
||||
|
||||
resp := call(http.MethodPut, self+"/notify", map[string]string{"ntfy_topic": "terdut-member"})
|
||||
resp := call(http.MethodPost, self+"/channels", map[string]string{"type": "ntfy", "address": "terdut-member"})
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("own notify target: %d", resp.StatusCode)
|
||||
if resp.StatusCode != http.StatusCreated {
|
||||
t.Errorf("own notification channel: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
resp = call(http.MethodPut, self+"/password", map[string]string{"password": "correct-horse-battery"})
|
||||
|
||||
Reference in New Issue
Block a user