97 lines
3.0 KiB
Go
97 lines
3.0 KiB
Go
//go:build e2e
|
||
|
||
package e2e
|
||
|
||
import (
|
||
"encoding/json"
|
||
"net/http"
|
||
"testing"
|
||
|
||
"github.com/stretchr/testify/require"
|
||
)
|
||
|
||
// TestZZZ_AuthTokenRefreshAndLogout runs last (separate go test invocation).
|
||
// It uses an isolated refresh so seed tokens used by member/permission stay valid.
|
||
func TestZZZ_AuthTokenRefreshAndLogout(t *testing.T) {
|
||
e2eStep(t, "A-10/A-11", "POST", "/api/v1/auth/{token/refresh,logout}", "刷新 token → 用新 access 打 /me → logout → 黑名單後再打 /me=401")
|
||
c := isolatedAuthClient(t)
|
||
|
||
refreshEnv := c.DoExpectOK(t, http.MethodPost, "/api/v1/auth/token/refresh", map[string]string{
|
||
"refresh_token": c.Fixture.RefreshToken,
|
||
}, false)
|
||
var pair struct {
|
||
AccessToken string `json:"access_token"`
|
||
RefreshToken string `json:"refresh_token"`
|
||
UID string `json:"uid"`
|
||
}
|
||
require.NoError(t, json.Unmarshal(refreshEnv.Data, &pair))
|
||
require.Equal(t, c.Fixture.UID, pair.UID)
|
||
|
||
c.Fixture.AccessToken = pair.AccessToken
|
||
c.Fixture.RefreshToken = pair.RefreshToken
|
||
|
||
c.DoExpectOK(t, http.MethodGet, "/api/v1/members/me", nil, true)
|
||
c.DoExpectOK(t, http.MethodPost, "/api/v1/auth/logout", nil, true)
|
||
|
||
resp, env := c.Do(t, http.MethodGet, "/api/v1/members/me", nil, true)
|
||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||
require.NotEqual(t, int64(successCode), env.Code)
|
||
}
|
||
|
||
func TestAuth_MissingBearer_401(t *testing.T) {
|
||
e2eStep(t, "A-12", "GET", "/api/v1/members/me", "未帶 Bearer → 401(AuthJWT middleware)")
|
||
c := NewClient(t)
|
||
resp, env := c.Do(t, http.MethodGet, "/api/v1/members/me", nil, false)
|
||
require.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||
require.NotEqual(t, int64(successCode), env.Code)
|
||
}
|
||
|
||
func TestAuth_PublicValidationErrors(t *testing.T) {
|
||
e2eStep(t, "A-13", "POST", "/api/v1/auth/*", "公開 Auth 端點輸入驗證錯誤 → 400 + Facade scope")
|
||
c := NewClient(t)
|
||
|
||
cases := []struct {
|
||
name string
|
||
path string
|
||
body any
|
||
}{
|
||
{
|
||
name: "register missing required fields",
|
||
path: "/api/v1/auth/register",
|
||
body: map[string]any{},
|
||
},
|
||
{
|
||
name: "login invalid email and password",
|
||
path: "/api/v1/auth/login",
|
||
body: map[string]any{
|
||
"tenant_slug": c.Fixture.TenantSlug,
|
||
"email": "not-an-email",
|
||
"password": "short",
|
||
},
|
||
},
|
||
{
|
||
name: "token refresh missing token",
|
||
path: "/api/v1/auth/token/refresh",
|
||
body: map[string]any{},
|
||
},
|
||
{
|
||
name: "social login invalid provider",
|
||
path: "/api/v1/auth/login/social/start",
|
||
body: map[string]any{
|
||
"tenant_slug": c.Fixture.TenantSlug,
|
||
"provider": "github",
|
||
"redirect_uri": "http://127.0.0.1/callback",
|
||
},
|
||
},
|
||
}
|
||
|
||
for _, tc := range cases {
|
||
t.Run(tc.name, func(t *testing.T) {
|
||
env := c.DoExpectHTTP(t, http.MethodPost, tc.path, tc.body, false, http.StatusBadRequest)
|
||
require.NotEqual(t, int64(successCode), env.Code)
|
||
// Facade scope 10101000 = InputInvalidFormat(gateway parse / validate 進入點)
|
||
require.Equal(t, int64(10), env.Code/1_000_000, "expected Facade scope, got code=%d", env.Code)
|
||
})
|
||
}
|
||
}
|