Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some tests to clarify the "must-change-password" behavior #30693

Merged
merged 6 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/admin_user_change_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var microcmdUserChangePassword = &cli.Command{
},
&cli.BoolFlag{
Name: "must-change-password",
Usage: "User must change password",
Usage: "User must change password (can be disabled by --must-change-password=false)",
Value: true,
},
},
Expand Down
18 changes: 12 additions & 6 deletions cmd/admin_user_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package cmd

import (
"context"
"errors"
"fmt"

Expand Down Expand Up @@ -48,7 +49,7 @@ var microcmdUserCreate = &cli.Command{
},
&cli.BoolFlag{
Name: "must-change-password",
Usage: "Set to false to prevent forcing the user to change their password after initial login",
Usage: "User must change password after initial login, defaults to true for all users except the first admin user (can be disabled by --must-change-password=false)",
DisableDefaultText: true,
},
&cli.IntFlag{
Expand Down Expand Up @@ -91,11 +92,16 @@ func runCreateUser(c *cli.Context) error {
_, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n")
}

ctx, cancel := installSignals()
defer cancel()

if err := initDB(ctx); err != nil {
return err
ctx := c.Context
if !setting.IsInTesting {
// FIXME: need to refactor the "installSignals/initDB" related code later
// it doesn't make sense to call it in (almost) every command action function
var cancel context.CancelFunc
ctx, cancel = installSignals()
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
}

var password string
Expand Down
44 changes: 44 additions & 0 deletions cmd/admin_user_create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package cmd

import (
"fmt"
"strings"
"testing"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"

"github.com/stretchr/testify/assert"
)

func TestAdminUserCreate(t *testing.T) {
app := NewMainApp(AppVersion{})

reset := func() {
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
}

type createCheck struct{ IsAdmin, MustChangePassword bool }
createUser := func(name, args string) createCheck {
assert.NoError(t, app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %s@gitea.local %s --password foobar", name, name, args))))
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: name})
return createCheck{u.IsAdmin, u.MustChangePassword}
}
reset()
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: true}, createUser("u", ""), "first non-admin user must change password")

reset()
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u", "--admin"), "first admin user doesn't need to change password")

reset()
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u", "--admin --must-change-password"))
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u2", "--admin"))
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u3", "--admin --must-change-password=false"))
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: true}, createUser("u4", ""))
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u5", "--must-change-password=false"))
}
9 changes: 7 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,18 @@ func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context)
}
}

func NewMainApp(version, versionExtra string) *cli.App {
type AppVersion struct {
Version string
Extra string
}

func NewMainApp(appVer AppVersion) *cli.App {
app := cli.NewApp()
app.Name = "Gitea"
app.HelpName = "gitea"
app.Usage = "A painless self-hosted Git service"
app.Description = `Gitea program contains "web" and other subcommands. If no subcommand is given, it starts the web server by default. Use "web" subcommand for more web server arguments, use other subcommands for other purposes.`
app.Version = version + versionExtra
app.Version = appVer.Version + appVer.Extra
app.EnableBashCompletion = true

// these sub-commands need to use config file
Expand Down
2 changes: 1 addition & 1 deletion cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func makePathOutput(workPath, customPath, customConf string) string {
}

func newTestApp(testCmdAction func(ctx *cli.Context) error) *cli.App {
app := NewMainApp("version", "version-extra")
app := NewMainApp(AppVersion{})
testCmd := &cli.Command{Name: "test-cmd", Action: testCmdAction}
prepareSubcommandWithConfig(testCmd, appGlobalFlags())
app.Commands = append(app.Commands, testCmd)
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func main() {
log.GetManager().Close()
os.Exit(code)
}
app := cmd.NewMainApp(Version, formatBuiltWith())
app := cmd.NewMainApp(cmd.AppVersion{Version: Version, Extra: formatBuiltWith()})
_ = cmd.RunMainApp(app, os.Args...) // all errors should have been handled by the RunMainApp
log.GetManager().Close()
}
Expand Down
12 changes: 10 additions & 2 deletions models/unittest/testdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package unittest
import (
"context"
"fmt"
"log"
"os"
"path/filepath"
"strings"
Expand All @@ -17,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/auth/password/hash"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/setting/config"
"code.gitea.io/gitea/modules/storage"
Expand Down Expand Up @@ -45,6 +45,14 @@ func fatalTestError(fmtStr string, args ...any) {

// InitSettings initializes config provider and load common settings for tests
func InitSettings() {
setting.IsInTesting = true
log.OsExiter = func(code int) {
if code != 0 {
// non-zero exit code (log.Fatal) shouldn't occur during testing, if it happens, show a full stacktrace for more details
panic(fmt.Errorf("non-zero exit code during testing: %d", code))
}
os.Exit(0)
}
if setting.CustomConf == "" {
setting.CustomConf = filepath.Join(setting.CustomPath, "conf/app-unittest-tmp.ini")
_ = os.Remove(setting.CustomConf)
Expand All @@ -53,7 +61,7 @@ func InitSettings() {
setting.LoadCommonSettings()

if err := setting.PrepareAppDataPath(); err != nil {
log.Fatalf("Can not prepare APP_DATA_PATH: %v", err)
log.Fatal("Can not prepare APP_DATA_PATH: %v", err)
}
// register the dummy hash algorithm function used in the test fixtures
_ = hash.Register("dummy", hash.NewDummyHasher)
Expand Down
4 changes: 3 additions & 1 deletion modules/log/logger_global.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ func Critical(format string, v ...any) {
Log(1, ERROR, format, v...)
}

var OsExiter = os.Exit

wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
// Fatal records fatal log and exit process
func Fatal(format string, v ...any) {
Log(1, FATAL, format, v...)
GetManager().Close()
os.Exit(1)
OsExiter(1)
}

func GetLogger(name string) Logger {
Expand Down
1 change: 0 additions & 1 deletion tests/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ func InitTest(requireGitea bool) {
// TODO: Speedup tests that rely on the event source ticker, confirm whether there is any bug or failure.
// setting.UI.Notification.EventSourceUpdateTime = time.Second

setting.IsInTesting = true
setting.AppWorkPath = giteaRoot
setting.CustomPath = filepath.Join(setting.AppWorkPath, "custom")
if requireGitea {
Expand Down