fix: 支持系统域名完整邮箱标识直接解析有效账号与协议认证
Some checks are pending
Security Checks / security (push) Waiting to run
Some checks are pending
Security Checks / security (push) Waiting to run
This commit is contained in:
parent
875b83fa2a
commit
343d038ee3
@ -72,24 +72,44 @@ func ResolveIdentifier(identifier string) (ResolvedIdentity, error) {
|
|||||||
Find(&bindings); err != nil {
|
Find(&bindings); err != nil {
|
||||||
return ResolvedIdentity{}, fmt.Errorf("load login email binding: %w", err)
|
return ResolvedIdentity{}, fmt.Errorf("load login email binding: %w", err)
|
||||||
}
|
}
|
||||||
if len(bindings) != 1 || bindings[0].UserID <= 0 {
|
if len(bindings) == 1 && bindings[0].UserID > 0 {
|
||||||
return ResolvedIdentity{}, errors.New("invalid identifier")
|
var user models.User
|
||||||
|
has, err := db.Instance.ID(bindings[0].UserID).Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
return ResolvedIdentity{}, fmt.Errorf("load login user: %w", err)
|
||||||
|
}
|
||||||
|
if has && user.ID > 0 && user.Account != "" && user.Disabled == 0 {
|
||||||
|
return ResolvedIdentity{
|
||||||
|
UserID: user.ID,
|
||||||
|
Account: user.Account,
|
||||||
|
LoginAddress: normalized,
|
||||||
|
Kind: IdentifierEmail,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var user models.User
|
// 回退机制:若未绑定独立外部邮箱,但属于系统配置的域名,则按账号匹配有效系统用户
|
||||||
has, err := db.Instance.ID(bindings[0].UserID).Get(&user)
|
parts := strings.SplitN(normalized, "@", 2)
|
||||||
if err != nil {
|
if len(parts) == 2 && isConfiguredLoginDomain(parts[1]) {
|
||||||
return ResolvedIdentity{}, fmt.Errorf("load login user: %w", err)
|
account, err := validation.NormalizeAccount(parts[0])
|
||||||
|
if err == nil {
|
||||||
|
var user models.User
|
||||||
|
has, err := db.Instance.Where("account = ? AND disabled = 0", account).Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
return ResolvedIdentity{}, fmt.Errorf("load domain user: %w", err)
|
||||||
|
}
|
||||||
|
if has && user.ID > 0 && user.Account != "" {
|
||||||
|
return ResolvedIdentity{
|
||||||
|
UserID: user.ID,
|
||||||
|
Account: user.Account,
|
||||||
|
LoginAddress: normalized,
|
||||||
|
Kind: IdentifierEmail,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !has || user.ID <= 0 || user.Account == "" {
|
|
||||||
return ResolvedIdentity{}, errors.New("invalid identifier")
|
return ResolvedIdentity{}, errors.New("invalid identifier")
|
||||||
}
|
|
||||||
return ResolvedIdentity{
|
|
||||||
UserID: user.ID,
|
|
||||||
Account: user.Account,
|
|
||||||
LoginAddress: normalized,
|
|
||||||
Kind: IdentifierEmail,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLoginIdentifier(identifier string) (string, IdentifierKind, error) {
|
func parseLoginIdentifier(identifier string) (string, IdentifierKind, error) {
|
||||||
|
|||||||
@ -92,3 +92,53 @@ func TestNormalizeIdentifierKeepsLegacyAccountCompatibility(t *testing.T) {
|
|||||||
t.Fatalf("normalized email key = %q, err = %v", got, err)
|
t.Fatalf("normalized email key = %q, err = %v", got, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func TestResolveIdentifierFallbackToConfiguredDomainUser(t *testing.T) {
|
||||||
|
oldConfig := config.Instance
|
||||||
|
oldDB := db.Instance
|
||||||
|
config.Instance = &config.Config{
|
||||||
|
DbType: config.DBTypeSQLite,
|
||||||
|
DbDSN: filepath.Join(t.TempDir(), "domain_fallback.db"),
|
||||||
|
Domain: "solit.cn",
|
||||||
|
Domains: []string{"solit.cn"},
|
||||||
|
}
|
||||||
|
if err := db.Init(""); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Cleanup(func() {
|
||||||
|
if db.Instance != nil && db.Instance != oldDB {
|
||||||
|
_ = db.Instance.Close()
|
||||||
|
}
|
||||||
|
db.Instance = oldDB
|
||||||
|
config.Instance = oldConfig
|
||||||
|
})
|
||||||
|
|
||||||
|
user := models.User{Account: "bob", Name: "Bob", Disabled: 0}
|
||||||
|
if err := SetPassword(&user, "CorrectP12"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := db.Instance.Insert(&user); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
identity, err := ResolveIdentifier(" Bob@Solit.cn ")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("resolve configured domain user failed: %v", err)
|
||||||
|
}
|
||||||
|
if identity.Kind != IdentifierEmail || identity.UserID != user.ID || identity.Account != "bob" || identity.LoginAddress != "bob@solit.cn" {
|
||||||
|
t.Fatalf("unexpected resolved identity: %+v", identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
disabledUser := models.User{Account: "charlie", Name: "Charlie", Disabled: 1}
|
||||||
|
if _, err := db.Instance.Insert(&disabledUser); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := ResolveIdentifier("charlie@solit.cn"); err == nil {
|
||||||
|
t.Fatal("disabled domain user must not be resolved")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := ResolveIdentifier("bob@other.com"); err == nil {
|
||||||
|
t.Fatal("unconfigured domain must not be resolved")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user