diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 4dc4107ff..ae13a8a69 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -25,6 +25,7 @@ This is a bug fix release. See the documentation for more information on the [up In addition to the following notable bug fixes, you can browse the [full list of commits](https://codeberg.org/forgejo/forgejo/compare/v7.0.0...v7.0.1) included in this release. * **Bug fixes:** + * The regression in the [`fogejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [is fixed](https://codeberg.org/forgejo/forgejo/issues/3399) and it is backward compatible. ## 7.0.0 diff --git a/cmd/admin_user_create.go b/cmd/admin_user_create.go index caafef536..dfc484aeb 100644 --- a/cmd/admin_user_create.go +++ b/cmd/admin_user_create.go @@ -124,7 +124,7 @@ func runCreateUser(c *cli.Context) error { if err != nil { return fmt.Errorf("IsTableNotEmpty: %w", err) } - if !hasUserRecord && isAdmin { + if !hasUserRecord { // if this is the first admin being created, don't force to change password (keep the old behavior) mustChangePassword = false } diff --git a/tests/integration/cmd_admin_test.go b/tests/integration/cmd_admin_test.go new file mode 100644 index 000000000..6a8546045 --- /dev/null +++ b/tests/integration/cmd_admin_test.go @@ -0,0 +1,146 @@ +// Copyright 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "net/url" + "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 Test_Cmd_AdminUser(t *testing.T) { + onGiteaRun(t, func(*testing.T, *url.URL) { + for _, testCase := range []struct { + name string + options []string + mustChangePassword bool + }{ + { + name: "default", + options: []string{}, + mustChangePassword: true, + }, + { + name: "--must-change-password=false", + options: []string{"--must-change-password=false"}, + mustChangePassword: false, + }, + { + name: "--must-change-password=true", + options: []string{"--must-change-password=true"}, + mustChangePassword: true, + }, + { + name: "--must-change-password", + options: []string{"--must-change-password"}, + mustChangePassword: true, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + name := "testuser" + + options := []string{"user", "create", "--username", name, "--password", "password", "--email", name + "@example.com"} + options = append(options, testCase.options...) + output, err := runMainApp("admin", options...) + assert.NoError(t, err) + assert.Contains(t, output, "has been successfully created") + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: name}) + assert.Equal(t, testCase.mustChangePassword, user.MustChangePassword) + + options = []string{"user", "change-password", "--username", name, "--password", "password"} + options = append(options, testCase.options...) + output, err = runMainApp("admin", options...) + assert.NoError(t, err) + assert.Contains(t, output, "has been successfully updated") + user = unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: name}) + assert.Equal(t, testCase.mustChangePassword, user.MustChangePassword) + + _, err = runMainApp("admin", "user", "delete", "--username", name) + assert.NoError(t, err) + unittest.AssertNotExistsBean(t, &user_model.User{Name: name}) + }) + } + }) +} + +func Test_Cmd_AdminFirstUser(t *testing.T) { + onGiteaRun(t, func(*testing.T, *url.URL) { + for _, testCase := range []struct { + name string + options []string + mustChangePassword bool + isAdmin bool + }{ + { + name: "default", + options: []string{}, + mustChangePassword: false, + isAdmin: false, + }, + { + name: "--must-change-password=false", + options: []string{"--must-change-password=false"}, + mustChangePassword: false, + isAdmin: false, + }, + { + name: "--must-change-password=true", + options: []string{"--must-change-password=true"}, + mustChangePassword: true, + isAdmin: false, + }, + { + name: "--must-change-password", + options: []string{"--must-change-password"}, + mustChangePassword: true, + isAdmin: false, + }, + { + name: "--admin default", + options: []string{"--admin"}, + mustChangePassword: false, + isAdmin: true, + }, + { + name: "--admin --must-change-password=false", + options: []string{"--admin", "--must-change-password=false"}, + mustChangePassword: false, + isAdmin: true, + }, + { + name: "--admin --must-change-password=true", + options: []string{"--admin", "--must-change-password=true"}, + mustChangePassword: true, + isAdmin: true, + }, + { + name: "--admin --must-change-password", + options: []string{"--admin", "--must-change-password"}, + mustChangePassword: true, + isAdmin: true, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + db.GetEngine(db.DefaultContext).Exec("DELETE FROM `user`") + db.GetEngine(db.DefaultContext).Exec("DELETE FROM `email_address`") + assert.Equal(t, int64(0), user_model.CountUsers(db.DefaultContext, nil)) + name := "testuser" + + options := []string{"user", "create", "--username", name, "--password", "password", "--email", name + "@example.com"} + options = append(options, testCase.options...) + output, err := runMainApp("admin", options...) + assert.NoError(t, err) + assert.Contains(t, output, "has been successfully created") + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: name}) + assert.Equal(t, testCase.mustChangePassword, user.MustChangePassword) + assert.Equal(t, testCase.isAdmin, user.IsAdmin) + }) + } + }) +}