mirror of
https://github.com/binwiederhier/ntfy.git
synced 2026-11-13 16:10:55 +08:00
Like the Postgres pool: user.OpenSQLite opens the auth-file (case-sensitive LIKE), NewSQLiteManager takes the handle and migrates it, and the usage store gets the same handle instead of reaching into the manager (Manager.DB is gone). The usage table stays part of the user schema.
213 lines
7.0 KiB
Go
213 lines
7.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/urfave/cli/v2"
|
|
"heckel.io/ntfy/v2/server"
|
|
"heckel.io/ntfy/v2/test"
|
|
"heckel.io/ntfy/v2/user"
|
|
)
|
|
|
|
func TestCLI_User_Add(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, stdout, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil added with role user")
|
|
}
|
|
|
|
func TestCLI_User_Add_Exists(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, stdout, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil added with role user")
|
|
|
|
app, stdin, _, _ = newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
err := runUserCommand(app, conf, "add", "phil")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "user phil already exists")
|
|
}
|
|
|
|
func TestCLI_User_Add_Admin(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, stdout, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "--role=admin", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil added with role admin")
|
|
}
|
|
|
|
func TestCLI_User_Add_Password_Mismatch(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, _, _ := newTestApp()
|
|
stdin.WriteString("mypass\nNOTMATCH")
|
|
err := runUserCommand(app, conf, "add", "phil")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "passwords do not match: try it again, but this time type slooowwwlly")
|
|
}
|
|
|
|
func TestCLI_User_ChangePass(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
conf.AuthUsers = []*user.User{
|
|
{Name: "philuser", Hash: "$2a$10$U4WSIYY6evyGmZaraavM2e2JeVG6EMGUKN1uUwufUeeRd4Jpg6cGC", Role: user.RoleUser}, // philuser:philpass
|
|
}
|
|
defer test.StopServer(t, s, port)
|
|
|
|
// Add user
|
|
app, stdin, stdout, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil added with role user")
|
|
|
|
// Change pass
|
|
app, stdin, stdout, _ = newTestApp()
|
|
stdin.WriteString("newpass\nnewpass")
|
|
require.Nil(t, runUserCommand(app, conf, "change-pass", "phil"))
|
|
require.Contains(t, stdout.String(), "changed password for user phil")
|
|
|
|
// Cannot change provisioned user's pass
|
|
app, stdin, _, _ = newTestApp()
|
|
stdin.WriteString("newpass\nnewpass")
|
|
require.Error(t, runUserCommand(app, conf, "change-pass", "philuser"))
|
|
}
|
|
|
|
func TestCLI_User_ChangeRole(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
// Add user
|
|
app, stdin, stdout, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil added with role user")
|
|
|
|
// Change role
|
|
app, _, stdout, _ = newTestApp()
|
|
require.Nil(t, runUserCommand(app, conf, "change-role", "phil", "admin"))
|
|
require.Contains(t, stdout.String(), "changed role for user phil to admin")
|
|
}
|
|
|
|
func TestCLI_User_Delete(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
// Add user
|
|
app, stdin, stdout, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil added with role user")
|
|
|
|
// Delete user
|
|
app, _, stdout, _ = newTestApp()
|
|
require.Nil(t, runUserCommand(app, conf, "del", "phil"))
|
|
require.Contains(t, stdout.String(), "user phil removed")
|
|
|
|
// Delete user again (does not exist)
|
|
app, _, _, _ = newTestApp()
|
|
err := runUserCommand(app, conf, "del", "phil")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "user phil does not exist")
|
|
}
|
|
|
|
func TestCLI_User_ResetPass(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, _, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
|
|
// Prints a working-looking reset link when base-url is set
|
|
app, _, stdout, _ := newTestApp()
|
|
require.Nil(t, runUserCommand(app, conf, "--base-url=https://ntfy.example.com", "reset-pass", "phil"))
|
|
require.Contains(t, stdout.String(), "https://ntfy.example.com/account/password/reset/")
|
|
}
|
|
|
|
func TestCLI_User_ResetPass_NoBaseURL(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, _, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
|
|
app, _, _, _ = newTestApp()
|
|
err := runUserCommand(app, conf, "reset-pass", "phil")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "base-url")
|
|
}
|
|
|
|
func TestCLI_User_ResetPass_SendEmailNoPrimary(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
app, stdin, _, _ := newTestApp()
|
|
stdin.WriteString("mypass\nmypass")
|
|
require.Nil(t, runUserCommand(app, conf, "add", "phil"))
|
|
|
|
// --send-email requires a primary email; phil has none
|
|
app, _, _, _ = newTestApp()
|
|
err := runUserCommand(app, conf, "--base-url=https://ntfy.example.com", "reset-pass", "--send-email", "phil")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "no primary email")
|
|
}
|
|
|
|
func TestCLI_User_ResetPass_ProvisionedRejected(t *testing.T) {
|
|
s, conf, port := newTestServerWithAuth(t)
|
|
defer test.StopServer(t, s, port)
|
|
|
|
// Seed a provisioned user into the auth database via config provisioning
|
|
d, err := user.OpenSQLite(conf.AuthFile)
|
|
require.Nil(t, err)
|
|
m, err := user.NewSQLiteManager(d, "", &user.Config{
|
|
ProvisionEnabled: true,
|
|
Users: []*user.User{
|
|
{Name: "provuser", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: user.RoleUser},
|
|
},
|
|
})
|
|
require.Nil(t, err)
|
|
require.Nil(t, m.Close())
|
|
|
|
app, _, _, _ := newTestApp()
|
|
err = runUserCommand(app, conf, "--base-url=https://ntfy.example.com", "reset-pass", "provuser")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "provisioned")
|
|
}
|
|
|
|
func newTestServerWithAuth(t *testing.T) (s *server.Server, conf *server.Config, port int) {
|
|
configFile := filepath.Join(t.TempDir(), "server-dummy.yml")
|
|
require.Nil(t, os.WriteFile(configFile, []byte(""), 0600)) // Dummy config file to avoid lookup of real server.yml
|
|
conf = server.NewConfig()
|
|
conf.File = configFile
|
|
conf.AuthFile = filepath.Join(t.TempDir(), "user.db")
|
|
conf.AuthDefault = user.PermissionDenyAll
|
|
conf.AuthAccessCacheEnabled = false
|
|
s, port = test.StartServerWithConfig(t, conf)
|
|
return
|
|
}
|
|
|
|
func runUserCommand(app *cli.App, conf *server.Config, args ...string) error {
|
|
userArgs := []string{
|
|
"ntfy",
|
|
"--log-level=ERROR",
|
|
"user",
|
|
"--config=" + conf.File, // Dummy config file to avoid lookups of real file
|
|
"--auth-file=" + conf.AuthFile,
|
|
"--auth-default-access=" + conf.AuthDefault.String(),
|
|
}
|
|
return app.Run(append(userArgs, args...))
|
|
}
|