mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-11-10 21:32:43 +08:00
Fix: connector validation error (#18489)
surface connector validation error detail so test connect can return detail error
This commit is contained in:
1 parent
d648d19137
commit
b46180fa2c
6 files changed
+75
-2
No files matched your search
@@ -391,8 +391,9 @@ func (h *ConnectorHandler) TestConnector(c *gin.Context) {
|
||||
var (
|
||||
valErr *syncerconnector.ConnectorValidationError
|
||||
credErr *syncerconnector.ConnectorMissingCredentialError
|
||||
rateErr *syncerconnector.RateLimitTriedTooManyTimesError
|
||||
)
|
||||
if errors.As(err, &valErr) || errors.As(err, &credErr) {
|
||||
if errors.As(err, &valErr) || errors.As(err, &credErr) || errors.As(err, &rateErr) {
|
||||
common.ResponseWithCodeData(c, common.CodeDataError, false, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -275,6 +275,11 @@ func TestConnectorHandlerTestConnector(t *testing.T) {
|
||||
err: &syncerconnector.ConnectorMissingCredentialError{Message: "REST API (bearer) requires 'token' in credentials"},
|
||||
wantCode: common.CodeDataError,
|
||||
},
|
||||
{
|
||||
name: "rate limit failure",
|
||||
err: &syncerconnector.RateLimitTriedTooManyTimesError{Message: "REST API rate limited"},
|
||||
wantCode: common.CodeDataError,
|
||||
},
|
||||
{
|
||||
name: "unexpected failure",
|
||||
err: fmt.Errorf("boom"),
|
||||
|
||||
@@ -428,7 +428,22 @@ func (s *ConnectorService) TestConnector(ctx context.Context, connectorID, userI
|
||||
if !ok {
|
||||
return ErrConnectorTestUnsupported
|
||||
}
|
||||
return validator.ValidateConnectorSetting(ctx, connectorConfig)
|
||||
return wrapConnectorValidationError(validator.ValidateConnectorSetting(ctx, connectorConfig))
|
||||
}
|
||||
|
||||
func wrapConnectorValidationError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
valErr *syncerconnector.ConnectorValidationError
|
||||
credErr *syncerconnector.ConnectorMissingCredentialError
|
||||
rateErr *syncerconnector.RateLimitTriedTooManyTimesError
|
||||
)
|
||||
if errors.As(err, &valErr) || errors.As(err, &credErr) || errors.As(err, &rateErr) {
|
||||
return err
|
||||
}
|
||||
return &syncerconnector.ConnectorValidationError{Message: err.Error()}
|
||||
}
|
||||
|
||||
func testConnectorSettings(stored *entity.Connector, request entity.JSONMap) (string, entity.JSONMap, error) {
|
||||
|
||||
@@ -73,6 +73,30 @@ func TestConnectorServiceTestConnectorAllowsUnsavedConnectorWithSource(t *testin
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectorServiceTestConnectorSurfacesRawValidationError(t *testing.T) {
|
||||
db := setupServiceTestDB(t)
|
||||
pushServiceDB(t, db)
|
||||
if err := db.AutoMigrate(&entity.Connector{}, &entity.UserTenant{}); err != nil {
|
||||
t.Fatalf("migrate connector tables: %v", err)
|
||||
}
|
||||
|
||||
registry := syncerconnector.NewRegistry()
|
||||
registry.RegisterConfigFactory("mock", func(config map[string]any) (syncerconnector.Connector, error) {
|
||||
return &connectormock.Connector{ValidateConnectorSettingErr: errors.New("raw validation failure")}, nil
|
||||
})
|
||||
svc := NewConnectorService()
|
||||
svc.connectorRegistry = registry
|
||||
|
||||
err := svc.TestConnector(context.Background(), "missing", "tenant-1", entity.JSONMap{
|
||||
"source": "mock",
|
||||
"config": entity.JSONMap{"ok": true},
|
||||
})
|
||||
var valErr *syncerconnector.ConnectorValidationError
|
||||
if !errors.As(err, &valErr) || !strings.Contains(valErr.Message, "raw validation failure") {
|
||||
t.Fatalf("error = %v, want *ConnectorValidationError with raw message", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectorServiceTestConnectorRejectsMissingConfigForMissingConnector(t *testing.T) {
|
||||
db := setupServiceTestDB(t)
|
||||
pushServiceDB(t, db)
|
||||
|
||||
@@ -134,6 +134,13 @@ func (c *WebDAVConnector) Validate(ctx context.Context) error {
|
||||
return fmt.Errorf("WebDAV validation failed for path '%s': %v", testPath, err)
|
||||
}
|
||||
|
||||
// ValidateConnectorSetting validates WebDAV settings from an unsaved config.
|
||||
func (c *WebDAVConnector) ValidateConnectorSetting(ctx context.Context, request map[string]any) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, connectorSettingValidationTimeout)
|
||||
defer cancel()
|
||||
return c.Validate(ctx)
|
||||
}
|
||||
|
||||
// OpenSync opens one WebDAV sync session.
|
||||
func (c *WebDAVConnector) OpenSync(ctx context.Context, request SyncRequest) (SyncSession, error) {
|
||||
files, err := c.listFiles(ctx, c.remotePath)
|
||||
|
||||
@@ -219,6 +219,27 @@ func TestWebDAVConnectorValidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebDAVConnectorValidateConnectorSetting(t *testing.T) {
|
||||
server, _, _ := newWebDAVTestServer(t, webDAVTestTree())
|
||||
|
||||
connector := webDAVTestConnector(t, server.URL, false, 2)
|
||||
if err := connector.ValidateConnectorSetting(context.Background(), nil); err != nil {
|
||||
t.Fatalf("ValidateConnectorSetting failed: %v", err)
|
||||
}
|
||||
|
||||
missingCredentials, err := NewWebDAVConnector(map[string]any{
|
||||
"base_url": server.URL,
|
||||
"credentials": map[string]any{},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("NewWebDAVConnector failed: %v", err)
|
||||
}
|
||||
err = missingCredentials.ValidateConnectorSetting(context.Background(), nil)
|
||||
if err == nil || !strings.Contains(err.Error(), "username and password") {
|
||||
t.Fatalf("missing credentials error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebDAVConnectorOpenSyncFull(t *testing.T) {
|
||||
t.Setenv("BLOB_STORAGE_SIZE_THRESHOLD", "20")
|
||||
server, authHeaders, _ := newWebDAVTestServer(t, webDAVTestTree())
|
||||
|
||||
Reference in new issue
Block a user