feat: complete registration invitation and auth redesign

This commit is contained in:
richjohnrambo
2026-08-19 00:30:11 +08:00
parent e063e7879e
commit 219ecadf4c
47 changed files with 9014 additions and 224 deletions
+1 -1
View File
@@ -278,7 +278,7 @@ type AuthHandler interface {
// continue the authentication process to the next step, or return an error code.
// The remoteAddr (i.e. the IP address of the client) can be used by custom authenticators for
// additional validation. The stock authenticators don't use it.
// store.Users.GetAuthRecord("scheme", "unique")
// The selected handler resolves its account through the tenant-scoped auth store.
// Returns: user auth record, challenge, error.
Authenticate(ctx AuthContext, secret []byte) (*Rec, []byte, error)
+10 -10
View File
@@ -17,7 +17,7 @@ import (
// Define default constraints on login and password
const (
defaultMinLoginLength = 2
defaultMinLoginLength = 1
defaultMaxLoginLength = 32
defaultMinPasswordLength = 3
@@ -26,7 +26,7 @@ const (
// Token suitable as a login: either an E.164 phone number or a name which starts
// and ends with a Unicode letter (class L) or number (class N), and contains
// Unicode letters, numbers, dot and underscore.
var loginPattern = regexp.MustCompile(`^(\+[\pN]+|[\pL\pN][_.\pL\pN]*[\pL\pN]+)$`)
var loginPattern = regexp.MustCompile(`^(\+[0-9]+|[\pL\pN](?:[_.\pL\pN]*[\pL\pN])?)$`)
// authenticator is the type to map authentication methods to.
type authenticator struct {
@@ -143,7 +143,7 @@ func (a *authenticator) AddRecord(ctx auth.AuthContext, rec *auth.Rec, secret []
authLevel = auth.LevelAuth
}
err = store.Users.AddAuthRecord(ctx.TenantID, rec.Uid, authLevel, a.name, uname, passhash, expires)
err = store.Users.AddAuthRecord(ctx.TenantID, rec.Uid, authLevel, passhash, expires)
if err != nil {
return nil, err
}
@@ -165,7 +165,7 @@ func (a *authenticator) UpdateRecord(ctx auth.AuthContext, rec *auth.Rec, secret
return nil, err
}
login, authLevel, _, _, err := store.Users.GetAuthRecord(ctx.TenantID, rec.Uid, a.name)
login, authLevel, _, _, err := store.Users.GetAuthRecord(ctx.TenantID, rec.Uid)
if err != nil {
return nil, err
}
@@ -179,7 +179,7 @@ func (a *authenticator) UpdateRecord(ctx auth.AuthContext, rec *auth.Rec, secret
uname = login
} else if err = a.checkLoginPolicy(uname); err != nil {
return nil, err
} else if uid, _, _, _, err := store.Users.GetAuthUniqueRecord(ctx.TenantID, a.name, uname); err != nil {
} else if uid, _, _, _, err := store.Users.GetAuthByLogin(ctx.TenantID, uname); err != nil {
return nil, err
} else if !uid.IsZero() {
// The (new) user name already exists. Report an error.
@@ -198,7 +198,7 @@ func (a *authenticator) UpdateRecord(ctx auth.AuthContext, rec *auth.Rec, secret
if rec.Lifetime > 0 {
expires = types.TimeNow().Add(time.Duration(rec.Lifetime))
}
err = store.Users.UpdateAuthRecord(ctx.TenantID, rec.Uid, authLevel, a.name, uname, passhash, expires)
err = store.Users.UpdateAuthRecord(ctx.TenantID, rec.Uid, authLevel, uname, passhash, expires)
if err != nil {
return nil, err
}
@@ -228,7 +228,7 @@ func (a *authenticator) Authenticate(ctx auth.AuthContext, secret []byte) (*auth
return nil, nil, err
}
uid, authLvl, passhash, expires, err := store.Users.GetAuthUniqueRecord(ctx.TenantID, a.name, uname)
uid, authLvl, passhash, expires, err := store.Users.GetAuthByLogin(ctx.TenantID, uname)
if err != nil {
return nil, nil, err
}
@@ -287,7 +287,7 @@ func (a *authenticator) IsUnique(ctx auth.AuthContext, secret []byte) (bool, err
return false, err
}
uid, _, _, _, err := store.Users.GetAuthUniqueRecord(ctx.TenantID, a.name, uname)
uid, _, _, _, err := store.Users.GetAuthByLogin(ctx.TenantID, uname)
if err != nil {
return false, err
}
@@ -305,7 +305,7 @@ func (authenticator) GenSecret(rec *auth.Rec) ([]byte, time.Time, error) {
// DelRecords deletes saved authentication records of the given user.
func (a *authenticator) DelRecords(tenantID types.TenantID, uid types.Uid) error {
return store.Users.DelAuthRecords(tenantID, uid, a.name)
return store.Users.DeleteAuthRecord(tenantID, uid)
}
// RestrictedTags returns tag namespaces (prefixes) restricted by this adapter.
@@ -319,7 +319,7 @@ func (a *authenticator) RestrictedTags() ([]string, error) {
// GetResetParams returns authenticator parameters passed to password reset handler.
func (a *authenticator) GetResetParams(tenantID types.TenantID, uid types.Uid) (map[string]any, error) {
login, _, _, _, err := store.Users.GetAuthRecord(tenantID, uid, a.name)
login, _, _, _, err := store.Users.GetAuthRecord(tenantID, uid)
if err != nil {
return nil, err
}
+3 -3
View File
@@ -26,9 +26,9 @@ func TestAuthenticateScopesLoginByTenant(t *testing.T) {
if err != nil {
t.Fatal(err)
}
users.EXPECT().GetAuthUniqueRecord(types.TenantID(7), "basic", "alice").
users.EXPECT().GetAuthByLogin(types.TenantID(7), "alice").
Return(types.Uid(70), auth.LevelAuth, hash, time.Time{}, nil)
users.EXPECT().GetAuthUniqueRecord(types.TenantID(8), "basic", "alice").
users.EXPECT().GetAuthByLogin(types.TenantID(8), "alice").
Return(types.Uid(80), auth.LevelAuth, hash, time.Time{}, nil)
a := &authenticator{name: "basic", minLoginLength: defaultMinLoginLength,
@@ -73,7 +73,7 @@ func TestAddRecordAcceptsE164PhoneLogin(t *testing.T) {
})
users.EXPECT().AddAuthRecord(types.TenantID(7), types.Uid(42), auth.LevelAuth,
"basic", "+8615521120255", gomock.Any(), time.Time{}).Return(nil)
gomock.Any(), time.Time{}).Return(nil)
a := &authenticator{name: "basic", addToTags: true, minLoginLength: defaultMinLoginLength,
minPasswordLength: 6}