Files
xinmi/internal/application/service/password_policy_test.go
T
yawan f7fc992f57
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
2026-09-22 16:19:06 +08:00

104 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"context"
"errors"
"strings"
"testing"
"github.com/Tencent/WeKnora/internal/config"
"github.com/Tencent/WeKnora/internal/types/interfaces"
)
type stubComplexPasswordSettings struct {
interfaces.SystemSettingService
enabled bool
}
func (s *stubComplexPasswordSettings) GetBool(context.Context, string, string, bool) bool {
return s.enabled
}
func TestValidatePasswordPolicy(t *testing.T) {
t.Parallel()
cases := []struct {
name string
password string
complex bool
want error
}{
{name: "simple letters only", password: "password"},
{name: "simple minimum length", password: "abc"},
{name: "simple digits only", password: "123"},
{name: "simple too short", password: "ab", want: ErrPasswordPolicy},
{name: "simple empty", password: "", want: ErrPasswordPolicy},
{name: "simple too long", password: "Abcdefg1" + "xxxxxxxxxxxxxxxxxxxxxxxxx", want: ErrPasswordPolicy},
{name: "simple ok", password: "password1"},
{name: "simple Unicode minimum", password: "三个字"},
{name: "simple Unicode too short", password: "两字", want: ErrPasswordPolicy},
{name: "simple invalid UTF8", password: "ab\xff", want: ErrPasswordPolicy},
{name: "simple maximum length", password: strings.Repeat("x", 32)},
{name: "bcrypt byte boundary", password: strings.Repeat("字", 24)},
{name: "bcrypt byte overflow", password: strings.Repeat("字", 24) + "x", want: ErrPasswordPolicy},
{name: "complex too short", password: "Ab1!", complex: true, want: ErrComplexPasswordPolicy},
{name: "complex missing special", password: "NewSecure9", complex: true, want: ErrComplexPasswordPolicy},
{name: "complex missing upper", password: "newsecure9!", complex: true, want: ErrComplexPasswordPolicy},
{name: "complex missing lower", password: "NEWSECURE9!", complex: true, want: ErrComplexPasswordPolicy},
{name: "complex ok", password: "NewSecure9!", complex: true},
{
name: "complex unicode digit is not ASCII",
password: "Password١!",
complex: true,
want: ErrComplexPasswordPolicy,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
err := ValidatePasswordPolicy(tc.password, tc.complex)
if !errors.Is(err, tc.want) {
t.Fatalf("ValidatePasswordPolicy(%q, %v) err = %v, want %v", tc.password, tc.complex, err, tc.want)
}
})
}
}
func TestResolveComplexPasswordEnabled(t *testing.T) {
t.Parallel()
ctx := context.Background()
if got := ResolveComplexPasswordEnabled(ctx, nil, nil); got {
t.Fatal("nil cfg and settings should default to false")
}
// The previous copy-paste checked cfg.Tenant; Auth-only configs must still work.
cfgAuthOnly := &config.Config{Auth: &config.AuthConfig{ComplexPasswordEnabled: true}}
if !ResolveComplexPasswordEnabled(ctx, cfgAuthOnly, nil) {
t.Fatal("Auth.ComplexPasswordEnabled should be honoured when Tenant is nil")
}
cfgTenantOnly := &config.Config{Tenant: &config.TenantConfig{}}
if got := ResolveComplexPasswordEnabled(ctx, cfgTenantOnly, nil); got {
t.Fatal("Tenant-only cfg must not panic or enable the switch")
}
if !ResolveComplexPasswordEnabled(ctx, cfgAuthOnly, &stubComplexPasswordSettings{enabled: true}) {
t.Fatal("settings override true")
}
if ResolveComplexPasswordEnabled(ctx, cfgAuthOnly, &stubComplexPasswordSettings{enabled: false}) {
t.Fatal("settings override false should win over cfg")
}
}
func TestIsPasswordPolicyError(t *testing.T) {
t.Parallel()
if !IsPasswordPolicyError(ErrPasswordPolicy) || !IsPasswordPolicyError(ErrComplexPasswordPolicy) {
t.Fatal("policy sentinels should match")
}
if IsPasswordPolicyError(ErrSamePassword) {
t.Fatal("unrelated sentinel must not match")
}
}