code.gitea.io/gitea@v1.19.3/modules/doctor/breaking.go (about) 1 // Copyright 2022 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package doctor 5 6 import ( 7 "context" 8 "fmt" 9 10 "code.gitea.io/gitea/models/db" 11 "code.gitea.io/gitea/models/user" 12 "code.gitea.io/gitea/modules/log" 13 14 "xorm.io/builder" 15 ) 16 17 func iterateUserAccounts(ctx context.Context, each func(*user.User) error) error { 18 err := db.Iterate( 19 ctx, 20 builder.Gt{"id": 0}, 21 func(ctx context.Context, bean *user.User) error { 22 return each(bean) 23 }, 24 ) 25 return err 26 } 27 28 // Since 1.16.4 new restrictions has been set on email addresses. However users with invalid email 29 // addresses would be currently facing a error due to their invalid email address. 30 // Ref: https://github.com/go-gitea/gitea/pull/19085 & https://github.com/go-gitea/gitea/pull/17688 31 func checkUserEmail(ctx context.Context, logger log.Logger, _ bool) error { 32 // We could use quirky SQL to get all users that start without a [a-zA-Z0-9], but that would mean 33 // DB provider-specific SQL and only works _now_. So instead we iterate through all user accounts 34 // and use the user.ValidateEmail function to be future-proof. 35 var invalidUserCount int64 36 if err := iterateUserAccounts(ctx, func(u *user.User) error { 37 // Only check for users, skip 38 if u.Type != user.UserTypeIndividual { 39 return nil 40 } 41 42 if err := user.ValidateEmail(u.Email); err != nil { 43 invalidUserCount++ 44 logger.Warn("User[id=%d name=%q] have not a valid e-mail: %v", u.ID, u.Name, err) 45 } 46 return nil 47 }); err != nil { 48 return fmt.Errorf("iterateUserAccounts: %w", err) 49 } 50 51 if invalidUserCount == 0 { 52 logger.Info("All users have a valid e-mail.") 53 } else { 54 logger.Warn("%d user(s) have a non-valid e-mail.", invalidUserCount) 55 } 56 return nil 57 } 58 59 // From time to time Gitea makes changes to the reserved usernames and which symbols 60 // are allowed for various reasons. This check helps with detecting users that, according 61 // to our reserved names, don't have a valid username. 62 func checkUserName(ctx context.Context, logger log.Logger, _ bool) error { 63 var invalidUserCount int64 64 if err := iterateUserAccounts(ctx, func(u *user.User) error { 65 if err := user.IsUsableUsername(u.Name); err != nil { 66 invalidUserCount++ 67 logger.Warn("User[id=%d] does not have a valid username: %v", u.ID, err) 68 } 69 return nil 70 }); err != nil { 71 return fmt.Errorf("iterateUserAccounts: %w", err) 72 } 73 74 if invalidUserCount == 0 { 75 logger.Info("All users have a valid username.") 76 } else { 77 logger.Warn("%d user(s) have a non-valid username.", invalidUserCount) 78 } 79 return nil 80 } 81 82 func init() { 83 Register(&Check{ 84 Title: "Check if users has an valid email address", 85 Name: "check-user-email", 86 IsDefault: false, 87 Run: checkUserEmail, 88 Priority: 9, 89 }) 90 Register(&Check{ 91 Title: "Check if users have a valid username", 92 Name: "check-user-names", 93 IsDefault: false, 94 Run: checkUserName, 95 Priority: 9, 96 }) 97 }