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  }