code.gitea.io/gitea@v1.21.7/cmd/admin_user_create.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package cmd
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  
    10  	auth_model "code.gitea.io/gitea/models/auth"
    11  	user_model "code.gitea.io/gitea/models/user"
    12  	pwd "code.gitea.io/gitea/modules/auth/password"
    13  	"code.gitea.io/gitea/modules/setting"
    14  	"code.gitea.io/gitea/modules/util"
    15  
    16  	"github.com/urfave/cli/v2"
    17  )
    18  
    19  var microcmdUserCreate = &cli.Command{
    20  	Name:   "create",
    21  	Usage:  "Create a new user in database",
    22  	Action: runCreateUser,
    23  	Flags: []cli.Flag{
    24  		&cli.StringFlag{
    25  			Name:  "name",
    26  			Usage: "Username. DEPRECATED: use username instead",
    27  		},
    28  		&cli.StringFlag{
    29  			Name:  "username",
    30  			Usage: "Username",
    31  		},
    32  		&cli.StringFlag{
    33  			Name:  "password",
    34  			Usage: "User password",
    35  		},
    36  		&cli.StringFlag{
    37  			Name:  "email",
    38  			Usage: "User email address",
    39  		},
    40  		&cli.BoolFlag{
    41  			Name:  "admin",
    42  			Usage: "User is an admin",
    43  		},
    44  		&cli.BoolFlag{
    45  			Name:  "random-password",
    46  			Usage: "Generate a random password for the user",
    47  		},
    48  		&cli.BoolFlag{
    49  			Name:  "must-change-password",
    50  			Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
    51  		},
    52  		&cli.IntFlag{
    53  			Name:  "random-password-length",
    54  			Usage: "Length of the random password to be generated",
    55  			Value: 12,
    56  		},
    57  		&cli.BoolFlag{
    58  			Name:  "access-token",
    59  			Usage: "Generate access token for the user",
    60  		},
    61  		&cli.BoolFlag{
    62  			Name:  "restricted",
    63  			Usage: "Make a restricted user account",
    64  		},
    65  	},
    66  }
    67  
    68  func runCreateUser(c *cli.Context) error {
    69  	if err := argsSet(c, "email"); err != nil {
    70  		return err
    71  	}
    72  
    73  	if c.IsSet("name") && c.IsSet("username") {
    74  		return errors.New("Cannot set both --name and --username flags")
    75  	}
    76  	if !c.IsSet("name") && !c.IsSet("username") {
    77  		return errors.New("One of --name or --username flags must be set")
    78  	}
    79  
    80  	if c.IsSet("password") && c.IsSet("random-password") {
    81  		return errors.New("cannot set both -random-password and -password flags")
    82  	}
    83  
    84  	var username string
    85  	if c.IsSet("username") {
    86  		username = c.String("username")
    87  	} else {
    88  		username = c.String("name")
    89  		_, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n")
    90  	}
    91  
    92  	ctx, cancel := installSignals()
    93  	defer cancel()
    94  
    95  	if err := initDB(ctx); err != nil {
    96  		return err
    97  	}
    98  
    99  	var password string
   100  	if c.IsSet("password") {
   101  		password = c.String("password")
   102  	} else if c.IsSet("random-password") {
   103  		var err error
   104  		password, err = pwd.Generate(c.Int("random-password-length"))
   105  		if err != nil {
   106  			return err
   107  		}
   108  		fmt.Printf("generated random password is '%s'\n", password)
   109  	} else {
   110  		return errors.New("must set either password or random-password flag")
   111  	}
   112  
   113  	// always default to true
   114  	changePassword := true
   115  
   116  	// If this is the first user being created.
   117  	// Take it as the admin and don't force a password update.
   118  	if n := user_model.CountUsers(ctx, nil); n == 0 {
   119  		changePassword = false
   120  	}
   121  
   122  	if c.IsSet("must-change-password") {
   123  		changePassword = c.Bool("must-change-password")
   124  	}
   125  
   126  	restricted := util.OptionalBoolNone
   127  
   128  	if c.IsSet("restricted") {
   129  		restricted = util.OptionalBoolOf(c.Bool("restricted"))
   130  	}
   131  
   132  	// default user visibility in app.ini
   133  	visibility := setting.Service.DefaultUserVisibilityMode
   134  
   135  	u := &user_model.User{
   136  		Name:               username,
   137  		Email:              c.String("email"),
   138  		Passwd:             password,
   139  		IsAdmin:            c.Bool("admin"),
   140  		MustChangePassword: changePassword,
   141  		Visibility:         visibility,
   142  	}
   143  
   144  	overwriteDefault := &user_model.CreateUserOverwriteOptions{
   145  		IsActive:     util.OptionalBoolTrue,
   146  		IsRestricted: restricted,
   147  	}
   148  
   149  	if err := user_model.CreateUser(ctx, u, overwriteDefault); err != nil {
   150  		return fmt.Errorf("CreateUser: %w", err)
   151  	}
   152  
   153  	if c.Bool("access-token") {
   154  		t := &auth_model.AccessToken{
   155  			Name: "gitea-admin",
   156  			UID:  u.ID,
   157  		}
   158  
   159  		if err := auth_model.NewAccessToken(ctx, t); err != nil {
   160  			return err
   161  		}
   162  
   163  		fmt.Printf("Access token was successfully created... %s\n", t.Token)
   164  	}
   165  
   166  	fmt.Printf("New user '%s' has been successfully created!\n", username)
   167  	return nil
   168  }