2023-02-15 01:12:19 +03:00
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"errors"
"fmt"
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
2023-02-19 10:35:20 +03:00
pwd "code.gitea.io/gitea/modules/auth/password"
2024-02-23 05:18:33 +03:00
"code.gitea.io/gitea/modules/optional"
2023-02-15 01:12:19 +03:00
"code.gitea.io/gitea/modules/setting"
2023-07-21 12:28:19 +03:00
"github.com/urfave/cli/v2"
2023-02-15 01:12:19 +03:00
)
2023-07-21 12:28:19 +03:00
var microcmdUserCreate = & cli . Command {
2023-02-15 01:12:19 +03:00
Name : "create" ,
Usage : "Create a new user in database" ,
Action : runCreateUser ,
Flags : [ ] cli . Flag {
2023-07-21 12:28:19 +03:00
& cli . StringFlag {
2023-02-15 01:12:19 +03:00
Name : "name" ,
Usage : "Username. DEPRECATED: use username instead" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . StringFlag {
2023-02-15 01:12:19 +03:00
Name : "username" ,
Usage : "Username" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . StringFlag {
2023-02-15 01:12:19 +03:00
Name : "password" ,
Usage : "User password" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . StringFlag {
2023-02-15 01:12:19 +03:00
Name : "email" ,
Usage : "User email address" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . BoolFlag {
2023-02-15 01:12:19 +03:00
Name : "admin" ,
Usage : "User is an admin" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . BoolFlag {
2023-02-15 01:12:19 +03:00
Name : "random-password" ,
Usage : "Generate a random password for the user" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . BoolFlag {
2023-02-15 01:12:19 +03:00
Name : "must-change-password" ,
2024-03-17 14:07:06 +03:00
Usage : "Set this option to false to prevent forcing the user to change their password after initial login" ,
Value : true ,
2023-02-15 01:12:19 +03:00
} ,
2023-07-21 12:28:19 +03:00
& cli . IntFlag {
2023-02-15 01:12:19 +03:00
Name : "random-password-length" ,
Usage : "Length of the random password to be generated" ,
Value : 12 ,
} ,
2023-07-21 12:28:19 +03:00
& cli . BoolFlag {
2023-02-15 01:12:19 +03:00
Name : "access-token" ,
Usage : "Generate access token for the user" ,
} ,
2023-07-21 12:28:19 +03:00
& cli . BoolFlag {
2023-02-15 01:12:19 +03:00
Name : "restricted" ,
Usage : "Make a restricted user account" ,
} ,
} ,
}
func runCreateUser ( c * cli . Context ) error {
if err := argsSet ( c , "email" ) ; err != nil {
return err
}
if c . IsSet ( "name" ) && c . IsSet ( "username" ) {
return errors . New ( "Cannot set both --name and --username flags" )
}
if ! c . IsSet ( "name" ) && ! c . IsSet ( "username" ) {
return errors . New ( "One of --name or --username flags must be set" )
}
if c . IsSet ( "password" ) && c . IsSet ( "random-password" ) {
return errors . New ( "cannot set both -random-password and -password flags" )
}
var username string
if c . IsSet ( "username" ) {
username = c . String ( "username" )
} else {
username = c . String ( "name" )
2023-08-13 15:49:30 +03:00
_ , _ = fmt . Fprintf ( c . App . ErrWriter , "--name flag is deprecated. Use --username instead.\n" )
2023-02-15 01:12:19 +03:00
}
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
return err
}
var password string
if c . IsSet ( "password" ) {
password = c . String ( "password" )
} else if c . IsSet ( "random-password" ) {
var err error
password , err = pwd . Generate ( c . Int ( "random-password-length" ) )
if err != nil {
return err
}
fmt . Printf ( "generated random password is '%s'\n" , password )
} else {
return errors . New ( "must set either password or random-password flag" )
}
2024-03-17 14:07:06 +03:00
changePassword := c . Bool ( "must-change-password" )
2023-02-15 01:12:19 +03:00
// If this is the first user being created.
// Take it as the admin and don't force a password update.
2023-09-14 20:09:32 +03:00
if n := user_model . CountUsers ( ctx , nil ) ; n == 0 {
2023-02-15 01:12:19 +03:00
changePassword = false
}
2024-02-23 05:18:33 +03:00
restricted := optional . None [ bool ] ( )
2023-02-15 01:12:19 +03:00
if c . IsSet ( "restricted" ) {
2024-02-23 05:18:33 +03:00
restricted = optional . Some ( c . Bool ( "restricted" ) )
2023-02-15 01:12:19 +03:00
}
// default user visibility in app.ini
visibility := setting . Service . DefaultUserVisibilityMode
u := & user_model . User {
Name : username ,
Email : c . String ( "email" ) ,
Passwd : password ,
IsAdmin : c . Bool ( "admin" ) ,
MustChangePassword : changePassword ,
Visibility : visibility ,
}
overwriteDefault := & user_model . CreateUserOverwriteOptions {
2024-02-23 05:18:33 +03:00
IsActive : optional . Some ( true ) ,
2023-02-15 01:12:19 +03:00
IsRestricted : restricted ,
}
2023-09-14 20:09:32 +03:00
if err := user_model . CreateUser ( ctx , u , overwriteDefault ) ; err != nil {
2023-02-15 01:12:19 +03:00
return fmt . Errorf ( "CreateUser: %w" , err )
}
if c . Bool ( "access-token" ) {
t := & auth_model . AccessToken {
Name : "gitea-admin" ,
UID : u . ID ,
}
2023-09-15 09:13:19 +03:00
if err := auth_model . NewAccessToken ( ctx , t ) ; err != nil {
2023-02-15 01:12:19 +03:00
return err
}
fmt . Printf ( "Access token was successfully created... %s\n" , t . Token )
}
fmt . Printf ( "New user '%s' has been successfully created!\n" , username )
return nil
}