mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
181 lines
5.2 KiB
Go
181 lines
5.2 KiB
Go
// Copyright 2026 Arctel.net
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package user_test
|
|
|
|
import (
|
|
"Wavelet/core"
|
|
"Wavelet/core/contracts"
|
|
"Wavelet/pkg/idgen"
|
|
"Wavelet/plugins/domain/user"
|
|
"bytes"
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"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"
|
|
|
|
database "Wavelet/plugins/infra/database"
|
|
)
|
|
|
|
func setupTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
_ = idgen.Init(1)
|
|
dbPath := filepath.Join(t.TempDir(), "user_test.db")
|
|
testDB, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, testDB.AutoMigrate(
|
|
&user.User{},
|
|
&user.AccessToken{},
|
|
))
|
|
|
|
database.SetDB(testDB)
|
|
return testDB
|
|
}
|
|
|
|
func TestUserPluginUnit(t *testing.T) {
|
|
ctx := core.NewContext(context.Background())
|
|
ctx.Config().SetSource(core.NewMapSource(nil))
|
|
require.NoError(t, ctx.Config().Resolve())
|
|
testDB := setupTestDB(t)
|
|
|
|
dbPlugin := database.New(database.WithDB(testDB))
|
|
require.NoError(t, dbPlugin.Apply(ctx))
|
|
|
|
p := user.New()
|
|
assert.Equal(t, "user", p.Name())
|
|
assert.Equal(t, "1.0.0", p.Manifest().Version)
|
|
require.NoError(t, p.Apply(ctx))
|
|
|
|
userSvc, err := core.Inject[contracts.UserService](ctx)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, userSvc)
|
|
|
|
testCtx := context.Background()
|
|
|
|
// 1. Create User
|
|
u, err := userSvc.CreateUser(testCtx, contracts.CreateUserRequest{
|
|
Username: "charlie",
|
|
Password: "Password789!",
|
|
Email: "charlie@example.com",
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "charlie", u.Username)
|
|
|
|
// 2. Empty username error
|
|
_, err = userSvc.CreateUser(testCtx, contracts.CreateUserRequest{})
|
|
assert.Error(t, err)
|
|
|
|
// 3. Verify Password
|
|
assert.True(t, userSvc.VerifyPassword(testCtx, u.ID, "Password789!"))
|
|
assert.False(t, userSvc.VerifyPassword(testCtx, u.ID, "Wrong"))
|
|
|
|
// 4. Update Password with wrong old password
|
|
err = userSvc.UpdatePassword(testCtx, u.ID, "WrongOld", "NewPass999!")
|
|
assert.Error(t, err)
|
|
|
|
// Update Password success
|
|
err = userSvc.UpdatePassword(testCtx, u.ID, "Password789!", "NewPass999!")
|
|
require.NoError(t, err)
|
|
assert.True(t, userSvc.VerifyPassword(testCtx, u.ID, "NewPass999!"))
|
|
|
|
// 5. Update Profile
|
|
nickname := "Charlie Brown"
|
|
email := "charlie.new@example.com"
|
|
gender := "male"
|
|
website := "https://charlie.me"
|
|
loc := "SF"
|
|
updated, err := userSvc.UpdateProfile(testCtx, u.ID, contracts.UpdateUserProfileRequest{
|
|
Nickname: &nickname,
|
|
Email: &email,
|
|
Gender: &gender,
|
|
Website: &website,
|
|
Location: &loc,
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Charlie Brown", updated.Nickname)
|
|
assert.Equal(t, "charlie.new@example.com", updated.Email)
|
|
assert.Equal(t, "male", updated.Gender)
|
|
assert.Equal(t, "https://charlie.me", updated.Website)
|
|
assert.Equal(t, "SF", updated.Location)
|
|
|
|
// 6. List and Status
|
|
require.NoError(t, userSvc.SetUserAdmin(testCtx, u.ID, true))
|
|
require.NoError(t, userSvc.SetUserActive(testCtx, u.ID, true))
|
|
|
|
list, total, err := userSvc.ListUsers(testCtx, 1, 10, "")
|
|
require.NoError(t, err)
|
|
assert.GreaterOrEqual(t, total, int64(1))
|
|
assert.NotEmpty(t, list)
|
|
}
|
|
|
|
func TestUserLoginHTTPHandler(t *testing.T) {
|
|
ctx := core.NewContext(context.Background())
|
|
ctx.Config().SetSource(core.NewMapSource(nil))
|
|
require.NoError(t, ctx.Config().Resolve())
|
|
testDB := setupTestDB(t)
|
|
|
|
dbPlugin := database.New(database.WithDB(testDB))
|
|
require.NoError(t, dbPlugin.Apply(ctx))
|
|
|
|
p := user.New()
|
|
require.NoError(t, p.Apply(ctx))
|
|
|
|
userSvc, err := core.Inject[contracts.UserService](ctx)
|
|
require.NoError(t, err)
|
|
|
|
_, err = userSvc.CreateUser(context.Background(), contracts.CreateUserRequest{
|
|
Username: "admin",
|
|
Password: "Password123!",
|
|
Email: "admin@example.com",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
r := gin.New()
|
|
cookieStore := cookie.NewStore([]byte("test-session-secret"))
|
|
r.Use(sessions.Sessions("wavelet_session", cookieStore))
|
|
r.POST("/api/v1/user/login", user.Login)
|
|
|
|
reqBody := `{"username":"admin","password":"Password123!"}`
|
|
req, _ := http.NewRequest(http.MethodPost, "/api/v1/user/login", bytes.NewBufferString(reqBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
|
|
r.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
assert.Contains(t, w.Body.String(), `"username":"admin"`)
|
|
setCookie := w.Header().Get("Set-Cookie")
|
|
assert.NotEmpty(t, setCookie)
|
|
assert.Contains(t, setCookie, "wavelet_session=")
|
|
|
|
// Plaintext default password seeded user
|
|
plainUser := &user.User{
|
|
Username: "plain_admin",
|
|
Password: "12345678", // Plaintext seed
|
|
Email: "plain@example.com",
|
|
IsActive: true,
|
|
}
|
|
require.NoError(t, user.CreateUser(context.Background(), plainUser))
|
|
|
|
reqBodyPlain := `{"username":"plain_admin","password":"12345678"}`
|
|
reqPlain, _ := http.NewRequest(http.MethodPost, "/api/v1/user/login", bytes.NewBufferString(reqBodyPlain))
|
|
reqPlain.Header.Set("Content-Type", "application/json")
|
|
wPlain := httptest.NewRecorder()
|
|
|
|
r.ServeHTTP(wPlain, reqPlain)
|
|
|
|
assert.Equal(t, http.StatusOK, wPlain.Code)
|
|
assert.Contains(t, wPlain.Body.String(), `"username":"plain_admin"`)
|
|
assert.Contains(t, wPlain.Body.String(), `"need_change_password":true`)
|
|
}
|