You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

admin_user_create.go 4.3KB

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