97 lines
3.9 KiB
Go
97 lines
3.9 KiB
Go
package test
|
|
|
|
import (
|
|
"RenewCMS/api/pkg/apperr"
|
|
validator "RenewCMS/api/pkg/validator"
|
|
"RenewCMS/internal/domain/user"
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestPasswordLengthLimit(t *testing.T) {
|
|
validator.InitValidator()
|
|
longest := strings.Repeat("p", user.MaxPasswordBytes)
|
|
tooLong := longest + "p"
|
|
multibyteTooLong := strings.Repeat("é", 37)
|
|
|
|
t.Run("The domain accepts 72 bytes and refuses 73, counting bytes rather than characters", func(t *testing.T) {
|
|
if err := user.ValidatePassword(longest); err != nil {
|
|
t.Errorf("72 bytes: expected no error, got %v", err)
|
|
}
|
|
if err := user.ValidatePassword(tooLong); !errors.Is(err, user.ErrPasswordTooLong) {
|
|
t.Errorf("73 bytes: expected ErrPasswordTooLong, got %v", err)
|
|
}
|
|
if err := user.ValidatePassword(multibyteTooLong); !errors.Is(err, user.ErrPasswordTooLong) {
|
|
t.Errorf("37 two-byte characters: expected ErrPasswordTooLong, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Registering with a password over 72 bytes answers 400 and creates nothing", func(t *testing.T) {
|
|
userRepo := newMockUserRepo()
|
|
mailRepo := newMockMailRepo()
|
|
router := newRegistrationGateRouter(userRepo, mailRepo, "https://cms.example.com")
|
|
|
|
rec := registerRequest(t, router, "alice", multibyteTooLong, "alice@example.com")
|
|
|
|
if rec.Code != http.StatusBadRequest || strings.TrimSpace(rec.Body.String()) != apperr.PasswordTooLongErrorMessage {
|
|
t.Errorf("expected 400 %q, got %d %q", apperr.PasswordTooLongErrorMessage, rec.Code, rec.Body.String())
|
|
}
|
|
if len(userRepo.users) != 0 || len(mailRepo.SentEmails) != 0 {
|
|
t.Errorf("expected no user and no mail, got %d users and %d mails", len(userRepo.users), len(mailRepo.SentEmails))
|
|
}
|
|
})
|
|
|
|
t.Run("Registering with exactly 72 bytes still works", func(t *testing.T) {
|
|
userRepo := newMockUserRepo()
|
|
router := newRegistrationGateRouter(userRepo, newMockMailRepo(), "https://cms.example.com")
|
|
|
|
if rec := registerRequest(t, router, "alice", longest, "alice@example.com"); rec.Code != http.StatusOK {
|
|
t.Errorf("expected 200, got %d: %s", rec.Code, rec.Body.String())
|
|
}
|
|
})
|
|
|
|
t.Run("Resetting to a password over 72 bytes answers 400 and keeps the old password and code", func(t *testing.T) {
|
|
userRepo := newAliceResetPasswordRepo(time.Now().Add(time.Hour))
|
|
router := newResetPasswordRouter(userRepo, &stubHasher{})
|
|
|
|
rec := sendResetPasswordRequest(router, `{"email": "alice@example.com", "code": "reset-code-1", "password": "`+tooLong+`"}`)
|
|
|
|
if rec.Code != http.StatusBadRequest || strings.TrimSpace(rec.Body.String()) != apperr.PasswordTooLongErrorMessage {
|
|
t.Errorf("expected 400 %q, got %d %q", apperr.PasswordTooLongErrorMessage, rec.Code, rec.Body.String())
|
|
}
|
|
stored := userRepo.users[1]
|
|
if stored.Password != "hashed:oldpassword" || stored.PasswordResetCode != "hashed:reset-code-1" {
|
|
t.Errorf("expected the account untouched, got %+v", stored)
|
|
}
|
|
})
|
|
|
|
t.Run("A wrong reset code is reported as such even with an over-long password", func(t *testing.T) {
|
|
userRepo := newAliceResetPasswordRepo(time.Now().Add(time.Hour))
|
|
router := newResetPasswordRouter(userRepo, &stubHasher{})
|
|
|
|
rec := sendResetPasswordRequest(router, `{"email": "alice@example.com", "code": "wrong", "password": "`+tooLong+`"}`)
|
|
|
|
if rec.Code != http.StatusForbidden {
|
|
t.Errorf("expected 403, got %d", rec.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("Accepting an invite with a password over 72 bytes answers 400 and creates nothing", func(t *testing.T) {
|
|
f := newAcceptInviteFixture(t, 100)
|
|
f.seedPending()
|
|
usersBefore := len(f.users.users)
|
|
|
|
rec := f.accept(acceptBody(acceptCode, "newadmin", tooLong))
|
|
|
|
if rec.Code != http.StatusBadRequest || strings.TrimSpace(rec.Body.String()) != apperr.PasswordTooLongErrorMessage {
|
|
t.Errorf("expected 400 %q, got %d %q", apperr.PasswordTooLongErrorMessage, rec.Code, rec.Body.String())
|
|
}
|
|
if len(f.users.users) != usersBefore {
|
|
t.Errorf("expected no user created")
|
|
}
|
|
})
|
|
}
|