forked from baron/baron-sso
110 lines
3.5 KiB
Go
110 lines
3.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestUpdateMe_InvalidatesProfileCacheForTokenSession(t *testing.T) {
|
|
token := "token-abc"
|
|
identityID := "user-1"
|
|
traits := map[string]interface{}{
|
|
"email": "qa@example.com",
|
|
"name": "QA User",
|
|
"phone_number": "+821012345678",
|
|
"department": "Old Dept",
|
|
"affiliationType": "employee",
|
|
"companyCode": "",
|
|
"role": domain.RoleUser,
|
|
}
|
|
|
|
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
|
|
switch {
|
|
case r.URL.Host == "kratos.test" &&
|
|
r.URL.Path == "/sessions/whoami" &&
|
|
r.Method == http.MethodGet:
|
|
if r.Header.Get("X-Session-Token") != token {
|
|
return httpResponse(r, http.StatusUnauthorized, `{"error":"invalid token"}`), nil
|
|
}
|
|
return httpJSONAny(r, http.StatusOK, map[string]interface{}{
|
|
"identity": map[string]interface{}{
|
|
"id": identityID,
|
|
"traits": traits,
|
|
},
|
|
}), nil
|
|
|
|
case r.URL.Host == "kratos.test" &&
|
|
r.URL.Path == "/admin/identities/"+identityID &&
|
|
r.Method == http.MethodPut:
|
|
var payload struct {
|
|
Traits map[string]interface{} `json:"traits"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
return httpResponse(r, http.StatusBadRequest, `{"error":"invalid body"}`), nil
|
|
}
|
|
for k, v := range payload.Traits {
|
|
traits[k] = v
|
|
}
|
|
return httpResponse(r, http.StatusOK, `{"ok":true}`), nil
|
|
}
|
|
|
|
return httpResponse(r, http.StatusNotFound, "not found"), nil
|
|
})
|
|
setDefaultHTTPClientForTest(t, transport)
|
|
t.Setenv("KRATOS_PUBLIC_URL", "http://kratos.test")
|
|
t.Setenv("KRATOS_ADMIN_URL", "http://kratos.test")
|
|
|
|
redis := &mockRedisRepo{data: make(map[string]string)}
|
|
h := &AuthHandler{
|
|
RedisService: redis,
|
|
}
|
|
app := fiber.New()
|
|
app.Get("/api/v1/user/me", h.GetMe)
|
|
app.Put("/api/v1/user/me", h.UpdateMe)
|
|
|
|
// 1) 첫 조회로 Old Dept가 캐시에 저장됨
|
|
getReq1 := httptest.NewRequest(http.MethodGet, "/api/v1/user/me", nil)
|
|
getReq1.Header.Set("Authorization", "Bearer "+token)
|
|
getResp1, err := app.Test(getReq1, -1)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, getResp1.StatusCode)
|
|
var profile1 map[string]interface{}
|
|
require.NoError(t, json.NewDecoder(getResp1.Body).Decode(&profile1))
|
|
require.Equal(t, "Old Dept", profile1["department"])
|
|
|
|
// 2) 소속을 New Dept로 변경
|
|
updateBody, _ := json.Marshal(map[string]string{
|
|
"name": "QA User",
|
|
"phone": "01012345678",
|
|
"department": "New Dept",
|
|
})
|
|
updateReq := httptest.NewRequest(
|
|
http.MethodPut,
|
|
"/api/v1/user/me",
|
|
bytes.NewReader(updateBody),
|
|
)
|
|
updateReq.Header.Set("Content-Type", "application/json")
|
|
updateReq.Header.Set("Authorization", "Bearer "+token)
|
|
updateResp, err := app.Test(updateReq, -1)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, updateResp.StatusCode)
|
|
require.Equal(t, "New Dept", traits["department"])
|
|
|
|
// 3) 새로고침 재조회 시 New Dept가 보여야 함(캐시 무효화 회귀 방지)
|
|
getReq2 := httptest.NewRequest(http.MethodGet, "/api/v1/user/me", nil)
|
|
getReq2.Header.Set("Authorization", "Bearer "+token)
|
|
getResp2, err := app.Test(getReq2, -1)
|
|
require.NoError(t, err)
|
|
require.Equal(t, http.StatusOK, getResp2.StatusCode)
|
|
var profile2 map[string]interface{}
|
|
require.NoError(t, json.NewDecoder(getResp2.Body).Decode(&profile2))
|
|
require.Equal(t, "New Dept", profile2["department"])
|
|
}
|