test(response): fix AbortWithError router tests and oauth/bootstrap reliability

- Add middleware_test.go covering ErrorHandlerMiddleware and Abort helpers
- Switch router test setups to testhelper.NewTestGinEngine for error JSON
- Fix OAuth provider cache to use mock HTTP client and normalize issuer URLs
- Add ResetInitRuntimeOnceForTest to make bootstrap tests hermetic under -count
- Update admin/task test imports for upload/task package move
This commit is contained in:
ryan
2026-06-18 12:05:56 +08:00
parent e5b3a60f73
commit dd991909af
13 changed files with 240 additions and 48 deletions
+24 -3
View File
@@ -176,6 +176,10 @@ func init() {
}
}
func normalizeIssuerURL(issuer string) string {
return strings.TrimRight(strings.TrimSpace(issuer), "/")
}
func seedTestAuthSource(t *testing.T, dbConn *gorm.DB) {
t.Helper()
if err := dbConn.Create(&model.AuthSource{
@@ -193,6 +197,7 @@ func seedTestAuthSource(t *testing.T, dbConn *gorm.DB) {
}
func oidcDiscoveryResponse() *http.Response {
issuer := normalizeIssuerURL(testIssuerURL)
body := fmt.Sprintf(`{
"issuer": %q,
"authorization_endpoint": %q,
@@ -201,7 +206,7 @@ func oidcDiscoveryResponse() *http.Response {
"response_types_supported": ["code"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"]
}`, testIssuerURL, testAuthURL, testTokenURL, testJWKSURL)
}`, issuer, issuer+"/oauth2/authorize", issuer+"/oauth2/token", issuer+"/oauth2/keys")
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(strings.NewReader(body)),
@@ -254,7 +259,7 @@ func generateMockIDToken(issuer, sub, aud, nonce, username, email, name string)
// -----------------------------------------------------------------------------
// Test Helpers
func newMockOIDCClient(issuer, clientID string, expectedState *string, sub, username, email, name string) *http.Client {
cleanIssuer := strings.TrimRight(issuer, "/")
cleanIssuer := normalizeIssuerURL(issuer)
return &http.Client{
Transport: &mockRoundTripper{
roundTripFunc: func(req *http.Request) (*http.Response, error) {
@@ -288,7 +293,7 @@ func newMockOIDCClient(issuer, clientID string, expectedState *string, sub, user
if expectedState != nil {
stateVal = *expectedState
}
idToken := generateMockIDToken(issuer, sub, clientID, stateVal, username, email, name)
idToken := generateMockIDToken(cleanIssuer, sub, clientID, stateVal, username, email, name)
body := fmt.Sprintf(`{"access_token":"mock_access_token","token_type":"Bearer","expires_in":3600,"id_token":"%s"}`, idToken)
return &http.Response{
StatusCode: http.StatusOK,
@@ -303,6 +308,8 @@ func newMockOIDCClient(issuer, clientID string, expectedState *string, sub, user
}
func setupTestDB(t *testing.T) *gorm.DB {
model.ResetSystemConfigRAMCacheForTest()
dbConn, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
if err != nil {
t.Fatalf("failed to open sqlite in memory: %v", err)
@@ -338,7 +345,14 @@ func mockContextMiddleware(mockClient *http.Client) gin.HandlerFunc {
}
}
func resetOIDCProviderCacheForTest() {
InvalidateOIDCProviderCache(normalizeIssuerURL(testIssuerURL))
InvalidateOIDCProviderCache("https://github.com")
}
func setupTestRouter(dbConn *gorm.DB, mockRedis *mockRedisClient, mockClient *http.Client) *gin.Engine {
resetOIDCProviderCacheForTest()
r := testhelper.NewTestGinEngine(gin.Recovery())
// Inject context mock middleware
@@ -454,6 +468,7 @@ func TestGetLoginSources(t *testing.T) {
// Test disabling OIDC
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeyOIDCLoginEnabled).Update("value", "false")
model.ResetSystemConfigRAMCacheForTest()
mockRedis.store = make(map[string]string)
w2 := performRequest(router, http.MethodGet, "/api/v1/oauth/sources", nil, nil, nil)
@@ -1094,6 +1109,7 @@ func TestOIDCPolicyEnforcement(t *testing.T) {
Key: model.ConfigKeyOIDCLoginEnabled,
Value: "false",
})
model.ResetSystemConfigRAMCacheForTest()
mockRedis.Del(context.Background(), db.PrefixedKey(model.SystemConfigRedisHashKey)+":"+model.ConfigKeyOIDCLoginEnabled)
wLoginDisabled := performRequest(router, http.MethodGet, "/api/v1/oauth/login?source="+testSourceName, nil, nil, nil)
if wLoginDisabled.Code != http.StatusBadRequest {
@@ -1102,6 +1118,7 @@ func TestOIDCPolicyEnforcement(t *testing.T) {
// Re-enable globally, but deactivate source
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeyOIDCLoginEnabled).Update("value", "true")
model.ResetSystemConfigRAMCacheForTest()
mockRedis.Del(context.Background(), db.PrefixedKey(model.SystemConfigRedisHashKey)+":"+model.ConfigKeyOIDCLoginEnabled)
dbConn.Model(&model.AuthSource{}).Where("name = ?", testSourceName).Update("is_active", false)
@@ -1113,6 +1130,7 @@ func TestOIDCPolicyEnforcement(t *testing.T) {
// --- 2. Test Authorize enforcement ---
// Deactivate globally again
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeyOIDCLoginEnabled).Update("value", "false")
model.ResetSystemConfigRAMCacheForTest()
mockRedis.Del(context.Background(), db.PrefixedKey(model.SystemConfigRedisHashKey)+":"+model.ConfigKeyOIDCLoginEnabled)
dbConn.Model(&model.AuthSource{}).Where("name = ?", testSourceName).Update("is_active", true)
@@ -1124,6 +1142,7 @@ func TestOIDCPolicyEnforcement(t *testing.T) {
// --- 3. Test Callback enforcement ---
// Set up a valid state beforehand (when enabled)
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeyOIDCLoginEnabled).Update("value", "true")
model.ResetSystemConfigRAMCacheForTest()
mockRedis.Del(context.Background(), db.PrefixedKey(model.SystemConfigRedisHashKey)+":"+model.ConfigKeyOIDCLoginEnabled)
dbConn.Model(&model.AuthSource{}).Where("name = ?", testSourceName).Update("is_active", true)
@@ -1149,6 +1168,7 @@ func TestOIDCPolicyEnforcement(t *testing.T) {
// Now disable OIDC globally and attempt callback
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeyOIDCLoginEnabled).Update("value", "false")
model.ResetSystemConfigRAMCacheForTest()
mockRedis.Del(context.Background(), db.PrefixedKey(model.SystemConfigRedisHashKey)+":"+model.ConfigKeyOIDCLoginEnabled)
reqBody := fmt.Sprintf(`{"state":"%s","code":"test_auth_code"}`, state)
wCallbackDisabled := performRequest(router, http.MethodPost, "/api/v1/oauth/callback", []byte(reqBody), map[string]string{
@@ -1160,6 +1180,7 @@ func TestOIDCPolicyEnforcement(t *testing.T) {
// Enable globally but deactivate source and attempt callback
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeyOIDCLoginEnabled).Update("value", "true")
model.ResetSystemConfigRAMCacheForTest()
mockRedis.Del(context.Background(), db.PrefixedKey(model.SystemConfigRedisHashKey)+":"+model.ConfigKeyOIDCLoginEnabled)
dbConn.Model(&model.AuthSource{}).Where("name = ?", testSourceName).Update("is_active", false)