Accounts with WebAuthn only (no TOTP) now exist ... fix code to handle that case (#18897)

This commit is contained in:
6543 2022-03-02 01:24:31 +01:00 committed by GitHub
parent 38f6322164
commit 1f45d1e130
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 16 deletions

View file

@ -30,13 +30,19 @@ func (users UserList) GetTwoFaStatus() map[int64]bool {
for _, user := range users { for _, user := range users {
results[user.ID] = false // Set default to false results[user.ID] = false // Set default to false
} }
tokenMaps, err := users.loadTwoFactorStatus(db.GetEngine(db.DefaultContext))
if err == nil { if tokenMaps, err := users.loadTwoFactorStatus(db.GetEngine(db.DefaultContext)); err == nil {
for _, token := range tokenMaps { for _, token := range tokenMaps {
results[token.UID] = true results[token.UID] = true
} }
} }
if ids, err := users.userIDsWithWebAuthn(db.GetEngine(db.DefaultContext)); err == nil {
for _, id := range ids {
results[id] = true
}
}
return results return results
} }
@ -47,15 +53,23 @@ func (users UserList) loadTwoFactorStatus(e db.Engine) (map[int64]*auth.TwoFacto
userIDs := users.GetUserIDs() userIDs := users.GetUserIDs()
tokenMaps := make(map[int64]*auth.TwoFactor, len(userIDs)) tokenMaps := make(map[int64]*auth.TwoFactor, len(userIDs))
err := e. if err := e.In("uid", userIDs).Find(&tokenMaps); err != nil {
In("uid", userIDs).
Find(&tokenMaps)
if err != nil {
return nil, fmt.Errorf("find two factor: %v", err) return nil, fmt.Errorf("find two factor: %v", err)
} }
return tokenMaps, nil return tokenMaps, nil
} }
func (users UserList) userIDsWithWebAuthn(e db.Engine) ([]int64, error) {
if len(users) == 0 {
return nil, nil
}
ids := make([]int64, 0, len(users))
if err := e.Table(new(auth.WebAuthnCredential)).In("user_id", users.GetUserIDs()).Select("user_id").Distinct("user_id").Find(&ids); err != nil {
return nil, fmt.Errorf("find two factor: %v", err)
}
return ids, nil
}
// GetUsersByIDs returns all resolved users from a list of Ids. // GetUsersByIDs returns all resolved users from a list of Ids.
func GetUsersByIDs(ids []int64) (UserList, error) { func GetUsersByIDs(ids []int64) (UserList, error) {
ous := make([]*User, 0, len(ids)) ous := make([]*User, 0, len(ids))

View file

@ -217,15 +217,17 @@ func prepareUserInfo(ctx *context.Context) *user_model.User {
} }
ctx.Data["Sources"] = sources ctx.Data["Sources"] = sources
ctx.Data["TwoFactorEnabled"] = true hasTOTP, err := auth.HasTwoFactorByUID(u.ID)
_, err = auth.GetTwoFactorByUID(u.ID)
if err != nil { if err != nil {
if !auth.IsErrTwoFactorNotEnrolled(err) { ctx.ServerError("auth.HasTwoFactorByUID", err)
ctx.ServerError("IsErrTwoFactorNotEnrolled", err) return nil
return nil
}
ctx.Data["TwoFactorEnabled"] = false
} }
hasWebAuthn, err := auth.HasWebAuthnRegistrationsByUID(u.ID)
if err != nil {
ctx.ServerError("auth.HasWebAuthnRegistrationsByUID", err)
return nil
}
ctx.Data["TwoFactorEnabled"] = hasTOTP || hasWebAuthn
return u return u
} }
@ -327,14 +329,27 @@ func EditUserPost(ctx *context.Context) {
if form.Reset2FA { if form.Reset2FA {
tf, err := auth.GetTwoFactorByUID(u.ID) tf, err := auth.GetTwoFactorByUID(u.ID)
if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) { if err != nil && !auth.IsErrTwoFactorNotEnrolled(err) {
ctx.ServerError("GetTwoFactorByUID", err) ctx.ServerError("auth.GetTwoFactorByUID", err)
return return
} else if tf != nil {
if err := auth.DeleteTwoFactorByID(tf.ID, u.ID); err != nil {
ctx.ServerError("auth.DeleteTwoFactorByID", err)
return
}
} }
if err = auth.DeleteTwoFactorByID(tf.ID, u.ID); err != nil { wn, err := auth.GetWebAuthnCredentialsByUID(u.ID)
ctx.ServerError("DeleteTwoFactorByID", err) if err != nil {
ctx.ServerError("auth.GetTwoFactorByUID", err)
return return
} }
for _, cred := range wn {
if _, err := auth.DeleteCredential(cred.ID, u.ID); err != nil {
ctx.ServerError("auth.DeleteCredential", err)
return
}
}
} }
u.LoginName = form.LoginName u.LoginName = form.LoginName