Commit 4a64b870 by CaIon

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.
parent 56dbaab1
...@@ -14,8 +14,11 @@ import ( ...@@ -14,8 +14,11 @@ import (
"github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/model"
"github.com/QuantumNous/new-api/setting/config" "github.com/QuantumNous/new-api/setting/config"
"github.com/QuantumNous/new-api/setting/operation_setting" "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/gin-gonic/gin"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gorm.io/gorm" "gorm.io/gorm"
) )
...@@ -284,3 +287,81 @@ func TestListModelsTokenLimitIncludesTieredBillingModel(t *testing.T) { ...@@ -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-tiered-missing-expr-model")
require.NotContains(t, ids, "zz-token-unpriced-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)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment