code.gitea.io/gitea@v1.22.3/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 "context" 8 "errors" 9 "fmt" 10 11 auth_model "code.gitea.io/gitea/models/auth" 12 "code.gitea.io/gitea/models/db" 13 user_model "code.gitea.io/gitea/models/user" 14 pwd "code.gitea.io/gitea/modules/auth/password" 15 "code.gitea.io/gitea/modules/optional" 16 "code.gitea.io/gitea/modules/setting" 17 18 "github.com/urfave/cli/v2" 19 ) 20 21 var microcmdUserCreate = &cli.Command{ 22 Name: "create", 23 Usage: "Create a new user in database", 24 Action: runCreateUser, 25 Flags: []cli.Flag{ 26 &cli.StringFlag{ 27 Name: "name", 28 Usage: "Username. DEPRECATED: use username instead", 29 }, 30 &cli.StringFlag{ 31 Name: "username", 32 Usage: "Username", 33 }, 34 &cli.StringFlag{ 35 Name: "password", 36 Usage: "User password", 37 }, 38 &cli.StringFlag{ 39 Name: "email", 40 Usage: "User email address", 41 }, 42 &cli.BoolFlag{ 43 Name: "admin", 44 Usage: "User is an admin", 45 }, 46 &cli.BoolFlag{ 47 Name: "random-password", 48 Usage: "Generate a random password for the user", 49 }, 50 &cli.BoolFlag{ 51 Name: "must-change-password", 52 Usage: "User must change password after initial login, defaults to true for all users except the first one (can be disabled by --must-change-password=false)", 53 DisableDefaultText: true, 54 }, 55 &cli.IntFlag{ 56 Name: "random-password-length", 57 Usage: "Length of the random password to be generated", 58 Value: 12, 59 }, 60 &cli.BoolFlag{ 61 Name: "access-token", 62 Usage: "Generate access token for the user", 63 }, 64 &cli.BoolFlag{ 65 Name: "restricted", 66 Usage: "Make a restricted user account", 67 }, 68 }, 69 } 70 71 func runCreateUser(c *cli.Context) error { 72 if err := argsSet(c, "email"); err != nil { 73 return err 74 } 75 76 if c.IsSet("name") && c.IsSet("username") { 77 return errors.New("cannot set both --name and --username flags") 78 } 79 if !c.IsSet("name") && !c.IsSet("username") { 80 return errors.New("one of --name or --username flags must be set") 81 } 82 83 if c.IsSet("password") && c.IsSet("random-password") { 84 return errors.New("cannot set both -random-password and -password flags") 85 } 86 87 var username string 88 if c.IsSet("username") { 89 username = c.String("username") 90 } else { 91 username = c.String("name") 92 _, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n") 93 } 94 95 ctx := c.Context 96 if !setting.IsInTesting { 97 // FIXME: need to refactor the "installSignals/initDB" related code later 98 // it doesn't make sense to call it in (almost) every command action function 99 var cancel context.CancelFunc 100 ctx, cancel = installSignals() 101 defer cancel() 102 if err := initDB(ctx); err != nil { 103 return err 104 } 105 } 106 107 var password string 108 if c.IsSet("password") { 109 password = c.String("password") 110 } else if c.IsSet("random-password") { 111 var err error 112 password, err = pwd.Generate(c.Int("random-password-length")) 113 if err != nil { 114 return err 115 } 116 fmt.Printf("generated random password is '%s'\n", password) 117 } else { 118 return errors.New("must set either password or random-password flag") 119 } 120 121 isAdmin := c.Bool("admin") 122 mustChangePassword := true // always default to true 123 if c.IsSet("must-change-password") { 124 // if the flag is set, use the value provided by the user 125 mustChangePassword = c.Bool("must-change-password") 126 } else { 127 // check whether there are users in the database 128 hasUserRecord, err := db.IsTableNotEmpty(&user_model.User{}) 129 if err != nil { 130 return fmt.Errorf("IsTableNotEmpty: %w", err) 131 } 132 if !hasUserRecord { 133 // if this is the first one being created, don't force to change password (keep the old behavior) 134 mustChangePassword = false 135 } 136 } 137 138 restricted := optional.None[bool]() 139 140 if c.IsSet("restricted") { 141 restricted = optional.Some(c.Bool("restricted")) 142 } 143 144 // default user visibility in app.ini 145 visibility := setting.Service.DefaultUserVisibilityMode 146 147 u := &user_model.User{ 148 Name: username, 149 Email: c.String("email"), 150 Passwd: password, 151 IsAdmin: isAdmin, 152 MustChangePassword: mustChangePassword, 153 Visibility: visibility, 154 } 155 156 overwriteDefault := &user_model.CreateUserOverwriteOptions{ 157 IsActive: optional.Some(true), 158 IsRestricted: restricted, 159 } 160 161 if err := user_model.CreateUser(ctx, u, overwriteDefault); err != nil { 162 return fmt.Errorf("CreateUser: %w", err) 163 } 164 165 if c.Bool("access-token") { 166 t := &auth_model.AccessToken{ 167 Name: "gitea-admin", 168 UID: u.ID, 169 } 170 171 if err := auth_model.NewAccessToken(ctx, t); err != nil { 172 return err 173 } 174 175 fmt.Printf("Access token was successfully created... %s\n", t.Token) 176 } 177 178 fmt.Printf("New user '%s' has been successfully created!\n", username) 179 return nil 180 }