mirror of
https://github.com/binwiederhier/ntfy.git
synced 2024-11-23 03:43:47 +01:00
More tests
This commit is contained in:
parent
a2e474c375
commit
f79348817f
5 changed files with 65 additions and 33 deletions
|
@ -36,13 +36,15 @@ import (
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO
|
TODO
|
||||||
|
limits:
|
||||||
|
message cache duration
|
||||||
|
Keep 10000 messages or keep X days?
|
||||||
|
Attachment expiration based on plan
|
||||||
database migration
|
database migration
|
||||||
reserve topics
|
reserve topics
|
||||||
purge accounts that were not logged into in X
|
purge accounts that were not logged into in X
|
||||||
reset daily limits for users
|
reset daily limits for users
|
||||||
Account usage not updated "in real time"
|
Account usage not updated "in real time"
|
||||||
Attachment expiration based on plan
|
|
||||||
Plan: Keep 10000 messages or keep X days?
|
|
||||||
Sync:
|
Sync:
|
||||||
- "mute" setting
|
- "mute" setting
|
||||||
- figure out what settings are "web" or "phone"
|
- figure out what settings are "web" or "phone"
|
||||||
|
|
|
@ -159,7 +159,7 @@ func (s *Server) handleAccountTokenIssue(w http.ResponseWriter, r *http.Request,
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*") // FIXME remove this
|
w.Header().Set("Access-Control-Allow-Origin", "*") // FIXME remove this
|
||||||
response := &apiAccountTokenResponse{
|
response := &apiAccountTokenResponse{
|
||||||
Token: token.Value,
|
Token: token.Value,
|
||||||
Expires: token.Expires,
|
Expires: token.Expires.Unix(),
|
||||||
}
|
}
|
||||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -182,7 +182,7 @@ func (s *Server) handleAccountTokenExtend(w http.ResponseWriter, r *http.Request
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*") // FIXME remove this
|
w.Header().Set("Access-Control-Allow-Origin", "*") // FIXME remove this
|
||||||
response := &apiAccountTokenResponse{
|
response := &apiAccountTokenResponse{
|
||||||
Token: token.Value,
|
Token: token.Value,
|
||||||
Expires: token.Expires,
|
Expires: token.Expires.Unix(),
|
||||||
}
|
}
|
||||||
if err := json.NewEncoder(w).Encode(response); err != nil {
|
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -188,6 +188,9 @@ func (a *Manager) Authenticate(username, password string) (*User, error) {
|
||||||
// AuthenticateToken checks if the token exists and returns the associated User if it does.
|
// AuthenticateToken checks if the token exists and returns the associated User if it does.
|
||||||
// The method sets the User.Token value to the token that was used for authentication.
|
// The method sets the User.Token value to the token that was used for authentication.
|
||||||
func (a *Manager) AuthenticateToken(token string) (*User, error) {
|
func (a *Manager) AuthenticateToken(token string) (*User, error) {
|
||||||
|
if len(token) != tokenLength {
|
||||||
|
return nil, ErrUnauthenticated
|
||||||
|
}
|
||||||
user, err := a.userByToken(token)
|
user, err := a.userByToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrUnauthenticated
|
return nil, ErrUnauthenticated
|
||||||
|
@ -205,7 +208,7 @@ func (a *Manager) CreateToken(user *User) (*Token, error) {
|
||||||
}
|
}
|
||||||
return &Token{
|
return &Token{
|
||||||
Value: token,
|
Value: token,
|
||||||
Expires: expires.Unix(),
|
Expires: expires,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +220,7 @@ func (a *Manager) ExtendToken(user *User) (*Token, error) {
|
||||||
}
|
}
|
||||||
return &Token{
|
return &Token{
|
||||||
Value: user.Token,
|
Value: user.Token,
|
||||||
Expires: newExpires.Unix(),
|
Expires: newExpires,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,17 +393,6 @@ func (a *Manager) Users() ([]*User, error) {
|
||||||
}
|
}
|
||||||
users = append(users, user)
|
users = append(users, user)
|
||||||
}
|
}
|
||||||
/*sort.Slice(users, func(i, j int) bool {
|
|
||||||
if users[i].Role != users[j].Role {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if users[i].Name == Everyone || users[j].Name == Everyone {
|
|
||||||
return users[i].Name != Everyone
|
|
||||||
} else if string(users[i].Role) < string(users[j].Role) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return users[i].Name < users[j].Name
|
|
||||||
})*/
|
|
||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
|
|
||||||
const minBcryptTimingMillis = int64(50) // Ideally should be >100ms, but this should also run on a Raspberry Pi without massive resources
|
const minBcryptTimingMillis = int64(50) // Ideally should be >100ms, but this should also run on a Raspberry Pi without massive resources
|
||||||
|
|
||||||
func TestSQLiteAuth_FullScenario_Default_DenyAll(t *testing.T) {
|
func TestManager_FullScenario_Default_DenyAll(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
require.Nil(t, a.AddUser("phil", "phil", user.RoleAdmin))
|
require.Nil(t, a.AddUser("phil", "phil", user.RoleAdmin))
|
||||||
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
||||||
require.Nil(t, a.AllowAccess("ben", "mytopic", true, true))
|
require.Nil(t, a.AllowAccess("ben", "mytopic", true, true))
|
||||||
|
@ -84,21 +84,21 @@ func TestSQLiteAuth_FullScenario_Default_DenyAll(t *testing.T) {
|
||||||
require.Nil(t, a.Authorize(nil, "up5678", user.PermissionWrite))
|
require.Nil(t, a.Authorize(nil, "up5678", user.PermissionWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteAuth_AddUser_Invalid(t *testing.T) {
|
func TestManager_AddUser_Invalid(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
require.Equal(t, user.ErrInvalidArgument, a.AddUser(" invalid ", "pass", user.RoleAdmin))
|
require.Equal(t, user.ErrInvalidArgument, a.AddUser(" invalid ", "pass", user.RoleAdmin))
|
||||||
require.Equal(t, user.ErrInvalidArgument, a.AddUser("validuser", "pass", "invalid-role"))
|
require.Equal(t, user.ErrInvalidArgument, a.AddUser("validuser", "pass", "invalid-role"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteAuth_AddUser_Timing(t *testing.T) {
|
func TestManager_AddUser_Timing(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
start := time.Now().UnixMilli()
|
start := time.Now().UnixMilli()
|
||||||
require.Nil(t, a.AddUser("user", "pass", user.RoleAdmin))
|
require.Nil(t, a.AddUser("user", "pass", user.RoleAdmin))
|
||||||
require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
|
require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteAuth_Authenticate_Timing(t *testing.T) {
|
func TestManager_Authenticate_Timing(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
require.Nil(t, a.AddUser("user", "pass", user.RoleAdmin))
|
require.Nil(t, a.AddUser("user", "pass", user.RoleAdmin))
|
||||||
|
|
||||||
// Timing a correct attempt
|
// Timing a correct attempt
|
||||||
|
@ -120,8 +120,8 @@ func TestSQLiteAuth_Authenticate_Timing(t *testing.T) {
|
||||||
require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
|
require.GreaterOrEqual(t, time.Now().UnixMilli()-start, minBcryptTimingMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteAuth_UserManagement(t *testing.T) {
|
func TestManager_UserManagement(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
require.Nil(t, a.AddUser("phil", "phil", user.RoleAdmin))
|
require.Nil(t, a.AddUser("phil", "phil", user.RoleAdmin))
|
||||||
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
||||||
require.Nil(t, a.AllowAccess("ben", "mytopic", true, true))
|
require.Nil(t, a.AllowAccess("ben", "mytopic", true, true))
|
||||||
|
@ -202,8 +202,8 @@ func TestSQLiteAuth_UserManagement(t *testing.T) {
|
||||||
require.Equal(t, "*", users[1].Name)
|
require.Equal(t, "*", users[1].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteAuth_ChangePassword(t *testing.T) {
|
func TestManager_ChangePassword(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
require.Nil(t, a.AddUser("phil", "phil", user.RoleAdmin))
|
require.Nil(t, a.AddUser("phil", "phil", user.RoleAdmin))
|
||||||
|
|
||||||
_, err := a.Authenticate("phil", "phil")
|
_, err := a.Authenticate("phil", "phil")
|
||||||
|
@ -216,8 +216,8 @@ func TestSQLiteAuth_ChangePassword(t *testing.T) {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSQLiteAuth_ChangeRole(t *testing.T) {
|
func TestManager_ChangeRole(t *testing.T) {
|
||||||
a := newTestAuth(t, false, false)
|
a := newTestManager(t, false, false)
|
||||||
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
||||||
require.Nil(t, a.AllowAccess("ben", "mytopic", true, true))
|
require.Nil(t, a.AllowAccess("ben", "mytopic", true, true))
|
||||||
require.Nil(t, a.AllowAccess("ben", "readme", true, false))
|
require.Nil(t, a.AllowAccess("ben", "readme", true, false))
|
||||||
|
@ -235,7 +235,44 @@ func TestSQLiteAuth_ChangeRole(t *testing.T) {
|
||||||
require.Equal(t, 0, len(ben.Grants))
|
require.Equal(t, 0, len(ben.Grants))
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestAuth(t *testing.T, defaultRead, defaultWrite bool) *user.Manager {
|
func TestManager_Token_Valid(t *testing.T) {
|
||||||
|
a := newTestManager(t, false, false)
|
||||||
|
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
||||||
|
|
||||||
|
u, err := a.User("ben")
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
// Create token for user
|
||||||
|
token, err := a.CreateToken(u)
|
||||||
|
require.NotEmpty(t, token.Value)
|
||||||
|
require.True(t, time.Now().Add(71*time.Hour).Unix() < token.Expires.Unix())
|
||||||
|
|
||||||
|
u2, err := a.AuthenticateToken(token.Value)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, u.Name, u2.Name)
|
||||||
|
require.Equal(t, token.Value, u2.Token)
|
||||||
|
|
||||||
|
// Remove token and auth again
|
||||||
|
require.Nil(t, a.RemoveToken(u2))
|
||||||
|
u3, err := a.AuthenticateToken(token.Value)
|
||||||
|
require.Equal(t, user.ErrUnauthenticated, err)
|
||||||
|
require.Nil(t, u3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_Token_Invalid(t *testing.T) {
|
||||||
|
a := newTestManager(t, false, false)
|
||||||
|
require.Nil(t, a.AddUser("ben", "ben", user.RoleUser))
|
||||||
|
|
||||||
|
u, err := a.AuthenticateToken(strings.Repeat("x", 32)) // 32 == token length
|
||||||
|
require.Nil(t, u)
|
||||||
|
require.Equal(t, user.ErrUnauthenticated, err)
|
||||||
|
|
||||||
|
u, err = a.AuthenticateToken("not long enough anyway")
|
||||||
|
require.Nil(t, u)
|
||||||
|
require.Equal(t, user.ErrUnauthenticated, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestManager(t *testing.T, defaultRead, defaultWrite bool) *user.Manager {
|
||||||
filename := filepath.Join(t.TempDir(), "user.db")
|
filename := filepath.Join(t.TempDir(), "user.db")
|
||||||
a, err := user.NewManager(filename, defaultRead, defaultWrite)
|
a, err := user.NewManager(filename, defaultRead, defaultWrite)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
|
@ -4,6 +4,7 @@ package user
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Auther interface {
|
type Auther interface {
|
||||||
|
@ -31,7 +32,7 @@ type User struct {
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
Value string
|
Value string
|
||||||
Expires int64
|
Expires time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type Prefs struct {
|
type Prefs struct {
|
||||||
|
|
Loading…
Reference in a new issue