mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-03 21:08:25 +00:00 
			
		
		
		
	Backport #30472 by wxiaoguang Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
This commit is contained in:
		@@ -36,6 +36,7 @@ var microcmdUserChangePassword = &cli.Command{
 | 
				
			|||||||
		&cli.BoolFlag{
 | 
							&cli.BoolFlag{
 | 
				
			||||||
			Name:  "must-change-password",
 | 
								Name:  "must-change-password",
 | 
				
			||||||
			Usage: "User must change password",
 | 
								Usage: "User must change password",
 | 
				
			||||||
 | 
								Value: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -57,23 +58,18 @@ func runChangePassword(c *cli.Context) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var mustChangePassword optional.Option[bool]
 | 
					 | 
				
			||||||
	if c.IsSet("must-change-password") {
 | 
					 | 
				
			||||||
		mustChangePassword = optional.Some(c.Bool("must-change-password"))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	opts := &user_service.UpdateAuthOptions{
 | 
						opts := &user_service.UpdateAuthOptions{
 | 
				
			||||||
		Password:           optional.Some(c.String("password")),
 | 
							Password:           optional.Some(c.String("password")),
 | 
				
			||||||
		MustChangePassword: mustChangePassword,
 | 
							MustChangePassword: optional.Some(c.Bool("must-change-password")),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := user_service.UpdateAuth(ctx, user, opts); err != nil {
 | 
						if err := user_service.UpdateAuth(ctx, user, opts); err != nil {
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case errors.Is(err, password.ErrMinLength):
 | 
							case errors.Is(err, password.ErrMinLength):
 | 
				
			||||||
			return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength)
 | 
								return fmt.Errorf("password is not long enough, needs to be at least %d characters", setting.MinPasswordLength)
 | 
				
			||||||
		case errors.Is(err, password.ErrComplexity):
 | 
							case errors.Is(err, password.ErrComplexity):
 | 
				
			||||||
			return errors.New("Password does not meet complexity requirements")
 | 
								return errors.New("password does not meet complexity requirements")
 | 
				
			||||||
		case errors.Is(err, password.ErrIsPwned):
 | 
							case errors.Is(err, password.ErrIsPwned):
 | 
				
			||||||
			return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords")
 | 
								return errors.New("the password is in a list of stolen passwords previously exposed in public data breaches, please try again with a different password, to see more details: https://haveibeenpwned.com/Passwords")
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auth_model "code.gitea.io/gitea/models/auth"
 | 
						auth_model "code.gitea.io/gitea/models/auth"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/models/db"
 | 
				
			||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
	pwd "code.gitea.io/gitea/modules/auth/password"
 | 
						pwd "code.gitea.io/gitea/modules/auth/password"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/optional"
 | 
						"code.gitea.io/gitea/modules/optional"
 | 
				
			||||||
@@ -47,7 +48,8 @@ var microcmdUserCreate = &cli.Command{
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		&cli.BoolFlag{
 | 
							&cli.BoolFlag{
 | 
				
			||||||
			Name:               "must-change-password",
 | 
								Name:               "must-change-password",
 | 
				
			||||||
			Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
 | 
								Usage:              "Set to false to prevent forcing the user to change their password after initial login",
 | 
				
			||||||
 | 
								DisableDefaultText: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		&cli.IntFlag{
 | 
							&cli.IntFlag{
 | 
				
			||||||
			Name:  "random-password-length",
 | 
								Name:  "random-password-length",
 | 
				
			||||||
@@ -71,10 +73,10 @@ func runCreateUser(c *cli.Context) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c.IsSet("name") && c.IsSet("username") {
 | 
						if c.IsSet("name") && c.IsSet("username") {
 | 
				
			||||||
		return errors.New("Cannot set both --name and --username flags")
 | 
							return errors.New("cannot set both --name and --username flags")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !c.IsSet("name") && !c.IsSet("username") {
 | 
						if !c.IsSet("name") && !c.IsSet("username") {
 | 
				
			||||||
		return errors.New("One of --name or --username flags must be set")
 | 
							return errors.New("one of --name or --username flags must be set")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c.IsSet("password") && c.IsSet("random-password") {
 | 
						if c.IsSet("password") && c.IsSet("random-password") {
 | 
				
			||||||
@@ -110,17 +112,21 @@ func runCreateUser(c *cli.Context) error {
 | 
				
			|||||||
		return errors.New("must set either password or random-password flag")
 | 
							return errors.New("must set either password or random-password flag")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// always default to true
 | 
						isAdmin := c.Bool("admin")
 | 
				
			||||||
	changePassword := true
 | 
						mustChangePassword := true // always default to true
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If this is the first user being created.
 | 
					 | 
				
			||||||
	// Take it as the admin and don't force a password update.
 | 
					 | 
				
			||||||
	if n := user_model.CountUsers(ctx, nil); n == 0 {
 | 
					 | 
				
			||||||
		changePassword = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if c.IsSet("must-change-password") {
 | 
						if c.IsSet("must-change-password") {
 | 
				
			||||||
		changePassword = c.Bool("must-change-password")
 | 
							// if the flag is set, use the value provided by the user
 | 
				
			||||||
 | 
							mustChangePassword = c.Bool("must-change-password")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// check whether there are users in the database
 | 
				
			||||||
 | 
							hasUserRecord, err := db.IsTableNotEmpty(&user_model.User{})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("IsTableNotEmpty: %w", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !hasUserRecord && isAdmin {
 | 
				
			||||||
 | 
								// if this is the first admin being created, don't force to change password (keep the old behavior)
 | 
				
			||||||
 | 
								mustChangePassword = false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	restricted := optional.None[bool]()
 | 
						restricted := optional.None[bool]()
 | 
				
			||||||
@@ -136,8 +142,8 @@ func runCreateUser(c *cli.Context) error {
 | 
				
			|||||||
		Name:               username,
 | 
							Name:               username,
 | 
				
			||||||
		Email:              c.String("email"),
 | 
							Email:              c.String("email"),
 | 
				
			||||||
		Passwd:             password,
 | 
							Passwd:             password,
 | 
				
			||||||
		IsAdmin:            c.Bool("admin"),
 | 
							IsAdmin:            isAdmin,
 | 
				
			||||||
		MustChangePassword: changePassword,
 | 
							MustChangePassword: mustChangePassword,
 | 
				
			||||||
		Visibility:         visibility,
 | 
							Visibility:         visibility,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,8 +83,7 @@ Admin operations:
 | 
				
			|||||||
        - `--email value`: Email. Required.
 | 
					        - `--email value`: Email. Required.
 | 
				
			||||||
        - `--admin`: If provided, this makes the user an admin. Optional.
 | 
					        - `--admin`: If provided, this makes the user an admin. Optional.
 | 
				
			||||||
        - `--access-token`: If provided, an access token will be created for the user. Optional. (default: false).
 | 
					        - `--access-token`: If provided, an access token will be created for the user. Optional. (default: false).
 | 
				
			||||||
        - `--must-change-password`: If provided, the created user will be required to choose a newer password after the
 | 
					        - `--must-change-password`: The created user will be required to set a new password after the initial login, default: true. It could be disabled by `--must-change-password=false`.
 | 
				
			||||||
          initial login. Optional. (default: true).
 | 
					 | 
				
			||||||
        - `--random-password`: If provided, a randomly generated password will be used as the password of the created
 | 
					        - `--random-password`: If provided, a randomly generated password will be used as the password of the created
 | 
				
			||||||
          user. The value of `--password` will be discarded. Optional.
 | 
					          user. The value of `--password` will be discarded. Optional.
 | 
				
			||||||
        - `--random-password-length`: If provided, it will be used to configure the length of the randomly generated
 | 
					        - `--random-password-length`: If provided, it will be used to configure the length of the randomly generated
 | 
				
			||||||
@@ -95,7 +94,7 @@ Admin operations:
 | 
				
			|||||||
      - Options:
 | 
					      - Options:
 | 
				
			||||||
        - `--username value`, `-u value`: Username. Required.
 | 
					        - `--username value`, `-u value`: Username. Required.
 | 
				
			||||||
        - `--password value`, `-p value`: New password. Required.
 | 
					        - `--password value`, `-p value`: New password. Required.
 | 
				
			||||||
        - `--must-change-password`: If provided, the user is required to choose a new password after the login. Optional.
 | 
					        - `--must-change-password`: The user is required to set a new password after the login, default: true. It could be disabled by `--must-change-password=false`.
 | 
				
			||||||
      - Examples:
 | 
					      - Examples:
 | 
				
			||||||
        - `gitea admin user change-password --username myname --password asecurepassword`
 | 
					        - `gitea admin user change-password --username myname --password asecurepassword`
 | 
				
			||||||
    - `must-change-password`:
 | 
					    - `must-change-password`:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -284,8 +284,8 @@ func MaxBatchInsertSize(bean any) int {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsTableNotEmpty returns true if table has at least one record
 | 
					// IsTableNotEmpty returns true if table has at least one record
 | 
				
			||||||
func IsTableNotEmpty(tableName string) (bool, error) {
 | 
					func IsTableNotEmpty(beanOrTableName any) (bool, error) {
 | 
				
			||||||
	return x.Table(tableName).Exist()
 | 
						return x.Table(beanOrTableName).Exist()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteAllRecords will delete all the records of this table
 | 
					// DeleteAllRecords will delete all the records of this table
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user