test(user): cover self-service password update guard
Pin down the checkUpdatePassword contract: - changing a password requires the correct current password - OAuth/passwordless accounts (empty password hash) cannot set a password through the self-service endpoint and must use the password reset flow instead - setupLogin never writes back the password column These guard against regressing the password-change path back into a short-circuit that lets passwordless accounts set a password directly.
This commit is contained in:
@@ -14,8 +14,11 @@ import (
|
||||
"github.com/QuantumNous/new-api/model"
|
||||
"github.com/QuantumNous/new-api/setting/config"
|
||||
"github.com/QuantumNous/new-api/setting/operation_setting"
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-contrib/sessions/cookie"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -284,3 +287,81 @@ func TestListModelsTokenLimitIncludesTieredBillingModel(t *testing.T) {
|
||||
require.NotContains(t, ids, "zz-token-tiered-missing-expr-model")
|
||||
require.NotContains(t, ids, "zz-token-unpriced-model")
|
||||
}
|
||||
|
||||
func TestCheckUpdatePasswordRequiresCurrentPassword(t *testing.T) {
|
||||
db := setupModelListControllerTestDB(t)
|
||||
hashedPassword, err := common.Password2Hash("CurrentPassword123")
|
||||
require.NoError(t, err)
|
||||
user := &model.User{
|
||||
Username: "password-user",
|
||||
Password: hashedPassword,
|
||||
Status: common.UserStatusEnabled,
|
||||
}
|
||||
require.NoError(t, db.Create(user).Error)
|
||||
|
||||
updatePassword, err := checkUpdatePassword("", "", user.Id)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, updatePassword)
|
||||
|
||||
updatePassword, err = checkUpdatePassword("", "NewPassword123", user.Id)
|
||||
require.Error(t, err)
|
||||
assert.False(t, updatePassword)
|
||||
assert.ErrorIs(t, err, errOriginalPasswordFail)
|
||||
|
||||
updatePassword, err = checkUpdatePassword("CurrentPassword123", "NewPassword123", user.Id)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, updatePassword)
|
||||
}
|
||||
|
||||
func TestCheckUpdatePasswordRejectsHistoricalEmptyPassword(t *testing.T) {
|
||||
db := setupModelListControllerTestDB(t)
|
||||
user := &model.User{
|
||||
Username: "legacy-passwordless-user",
|
||||
Password: "",
|
||||
Status: common.UserStatusEnabled,
|
||||
}
|
||||
require.NoError(t, db.Create(user).Error)
|
||||
|
||||
updatePassword, err := checkUpdatePassword("", "NewPassword123", user.Id)
|
||||
require.Error(t, err)
|
||||
assert.False(t, updatePassword)
|
||||
assert.ErrorIs(t, err, errUserPasswordUnset)
|
||||
}
|
||||
|
||||
func TestSetupLoginDoesNotTouchPasswordWhenPasswordFieldOmitted(t *testing.T) {
|
||||
db := setupModelListControllerTestDB(t)
|
||||
require.NoError(t, db.AutoMigrate(&model.Log{}))
|
||||
|
||||
hashedPassword, err := common.Password2Hash("CurrentPassword123")
|
||||
require.NoError(t, err)
|
||||
user := &model.User{
|
||||
Username: "twofa-user",
|
||||
Password: hashedPassword,
|
||||
Role: common.RoleCommonUser,
|
||||
Status: common.UserStatusEnabled,
|
||||
Group: "default",
|
||||
}
|
||||
require.NoError(t, db.Create(user).Error)
|
||||
|
||||
router := gin.New()
|
||||
store := cookie.NewStore([]byte("test-session-secret"))
|
||||
router.Use(sessions.Sessions("session", store))
|
||||
router.GET("/", func(c *gin.Context) {
|
||||
setupLogin(&model.User{
|
||||
Id: user.Id,
|
||||
Username: user.Username,
|
||||
Role: user.Role,
|
||||
Status: user.Status,
|
||||
Group: user.Group,
|
||||
}, c)
|
||||
})
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
request := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
router.ServeHTTP(recorder, request)
|
||||
|
||||
require.Equal(t, http.StatusOK, recorder.Code)
|
||||
var stored model.User
|
||||
require.NoError(t, db.First(&stored, user.Id).Error)
|
||||
assert.Equal(t, hashedPassword, stored.Password)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user