Files
NianAIGC/backend/internal/httpapi/auth_password_change_test.go

72 lines
3.4 KiB
Go

package httpapi
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"git.nianxx.cn/wangxuming/NianAIGC/backend/internal/identity"
)
type passwordChangerStub struct {
command identity.PasswordChangeCommand
session identity.Session
err error
}
func (s *passwordChangerStub) Change(_ context.Context, command identity.PasswordChangeCommand) (identity.Session, error) {
s.command = command
return s.session, s.err
}
func TestAuthPasswordChangeReplacesSignedSessionCookie(t *testing.T) {
secret := "password-change-secret-with-enough-entropy"
now := time.Now().UTC().Truncate(time.Second)
version := 4
changer := &passwordChangerStub{session: identity.Session{Version: 1, AuthMode: identity.AuthModeUser, IssuedAt: now.Unix(), ExpiresAt: now.Add(time.Hour).Unix(), SessionVersion: &version, User: identity.User{ID: "u", Subject: "u", Phone: "13800138000", DisplayName: "User", ClientID: "platform", Role: "user", Status: "active", Authorities: []string{"ROLE_USER"}, Scope: []string{}}}}
resolver := &platformSessionResolverStub{outcome: "authenticated", session: identity.Session{AuthMode: identity.AuthModeUser, User: identity.User{ID: "u", Role: "user"}}}
authorizer, _ := NewPlatformAuthorizer(AuthState{Required: true, Configured: true}, resolver)
handler, err := NewAuthPasswordChangeHandler(PasswordChangeConfig{SessionSecret: secret}, authorizer, changer)
if err != nil {
t.Fatal(err)
}
r := httptest.NewRequest(http.MethodPost, "https://app.test/api/auth/password/change", strings.NewReader(`{"currentPassword":" current-password ","newPassword":"next-password","confirmPassword":"next-password"}`))
r.AddCookie(&http.Cookie{Name: identity.SessionCookieName, Value: "existing"})
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK || changer.command.AccountID != "u" || changer.command.CurrentPassword != "current-password" {
t.Fatalf("status=%d command=%+v body=%q", w.Code, changer.command, w.Body.String())
}
cookies := w.Result().Cookies()
if len(cookies) != identity.CookieMaxChunks {
t.Fatalf("cookies=%d", len(cookies))
}
signed := cookies[0].Value
parsed, err := identity.Parse(signed, secret, now)
if err != nil || parsed.SessionVersion == nil || *parsed.SessionVersion != 4 {
t.Fatalf("parse=%+v err=%v", parsed, err)
}
var body map[string]any
if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil || body["ok"] != true {
t.Fatalf("body=%q err=%v", w.Body.String(), err)
}
}
func TestAuthPasswordChangeValidatesConfirmation(t *testing.T) {
resolver := &platformSessionResolverStub{outcome: "authenticated", session: identity.Session{AuthMode: identity.AuthModeUser, User: identity.User{ID: "u", Role: "user"}}}
authorizer, _ := NewPlatformAuthorizer(AuthState{Required: true, Configured: true}, resolver)
changer := &passwordChangerStub{}
handler, _ := NewAuthPasswordChangeHandler(PasswordChangeConfig{SessionSecret: "secret"}, authorizer, changer)
r := httptest.NewRequest(http.MethodPost, "/api/auth/password/change", strings.NewReader(`{"currentPassword":"old-password","newPassword":"new-password","confirmPassword":"different"}`))
r.AddCookie(&http.Cookie{Name: identity.SessionCookieName, Value: "cookie"})
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusBadRequest || changer.command.AccountID != "" {
t.Fatalf("status=%d command=%+v", w.Code, changer.command)
}
}