You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

116 lines
3.6 KiB

package auth
import (
"errors"
"path/filepath"
"testing"
"time"
)
func TestSeedAdminAuthenticatesAndRequiresPasswordChange(t *testing.T) {
store := openTestStore(t, t.TempDir())
user, err := store.Authenticate(SeedAdminEmail, SeedAdminPassword)
if err != nil {
t.Fatalf("Authenticate(seed admin) error = %v", err)
}
if user.Role != RoleAdmin {
t.Errorf("seed admin role = %q, want %q", user.Role, RoleAdmin)
}
if !user.MustChangePassword {
t.Error("seed admin MustChangePassword = false, want true")
}
if _, err := store.Authenticate(SeedAdminEmail, "wrong-password"); !errors.Is(err, ErrInvalidCredentials) {
t.Errorf("Authenticate(wrong password) error = %v, want ErrInvalidCredentials", err)
}
}
func TestPasswordHashingAndChangePassword(t *testing.T) {
password := "Start1234!"
hash, err := HashPassword(password)
if err != nil {
t.Fatalf("HashPassword() error = %v", err)
}
if hash == password {
t.Error("HashPassword() returned the plaintext password")
}
if !CheckPassword(hash, password) {
t.Error("CheckPassword() = false for the password used to create the hash")
}
if CheckPassword(hash, "different-password") {
t.Error("CheckPassword() = true for a different password")
}
store := openTestStore(t, t.TempDir())
user, err := store.Authenticate(SeedAdminEmail, SeedAdminPassword)
if err != nil {
t.Fatal(err)
}
if err := store.ChangePassword(user.ID, SeedAdminPassword, SeedAdminPassword); !errors.Is(err, ErrPasswordUnchanged) {
t.Errorf("ChangePassword(same password) error = %v, want ErrPasswordUnchanged", err)
}
const newPassword = "A-new-password-123!"
if err := store.ChangePassword(user.ID, SeedAdminPassword, newPassword); err != nil {
t.Fatalf("ChangePassword() error = %v", err)
}
if _, err := store.Authenticate(SeedAdminEmail, SeedAdminPassword); !errors.Is(err, ErrInvalidCredentials) {
t.Errorf("Authenticate(old password) error = %v, want ErrInvalidCredentials", err)
}
updatedUser, err := store.Authenticate(SeedAdminEmail, newPassword)
if err != nil {
t.Fatalf("Authenticate(new password) error = %v", err)
}
if updatedUser.MustChangePassword {
t.Error("MustChangePassword remains true after a password change")
}
}
func TestSessionsPersistAcrossStoreRestartAndSlideExpiry(t *testing.T) {
now := time.Date(2026, time.September, 24, 12, 0, 0, 0, time.UTC)
clock := func() time.Time { return now }
databasePath := filepath.Join(t.TempDir(), "webfilebrowser.db")
store, err := Open(databasePath, Options{Clock: clock, SessionLifetime: 7 * 24 * time.Hour})
if err != nil {
t.Fatalf("Open() error = %v", err)
}
user, err := store.Authenticate(SeedAdminEmail, SeedAdminPassword)
if err != nil {
t.Fatal(err)
}
token, err := store.CreateSession(user.ID)
if err != nil {
t.Fatalf("CreateSession() error = %v", err)
}
if err := store.Close(); err != nil {
t.Fatal(err)
}
now = now.Add(6 * 24 * time.Hour)
reopenedStore, err := Open(databasePath, Options{Clock: clock, SessionLifetime: 7 * 24 * time.Hour})
if err != nil {
t.Fatalf("Open() after restart error = %v", err)
}
t.Cleanup(func() { _ = reopenedStore.Close() })
if _, err := reopenedStore.LookupSession(token); err != nil {
t.Fatalf("LookupSession() after restart error = %v", err)
}
now = now.Add(2 * 24 * time.Hour)
if _, err := reopenedStore.LookupSession(token); err != nil {
t.Fatalf("LookupSession() after sliding expiry error = %v", err)
}
}
func openTestStore(t *testing.T, directory string) *Store {
t.Helper()
store, err := Open(filepath.Join(directory, "webfilebrowser.db"), Options{})
if err != nil {
t.Fatalf("Open() error = %v", err)
}
t.Cleanup(func() { _ = store.Close() })
return store
}