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
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
|
|
}
|
|
|