mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-04 23:00:30 +08:00
Go: refactor config (#17678)
Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@@ -23,7 +23,6 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"ragflow/internal/common"
|
||||
"ragflow/internal/dao"
|
||||
"ragflow/internal/engine"
|
||||
@@ -1192,72 +1191,6 @@ func (s *Service) getInfinityStatus(serviceType string) map[string]interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
// checkRAGFlowServerAlive checks if RAGFlow server is alive
|
||||
func (s *Service) checkRAGFlowServerAlive(name string) (map[string]interface{}, error) {
|
||||
startTime := time.Now()
|
||||
|
||||
// Get ragflow config from allConfigs
|
||||
var host string
|
||||
var port int
|
||||
allConfigs := server.GetAllConfigs()
|
||||
for _, config := range allConfigs {
|
||||
if serviceType, ok := config["service_type"].(string); ok && serviceType == "ragflow_server" {
|
||||
if h, ok := config["host"].(string); ok {
|
||||
host = h
|
||||
}
|
||||
if p, ok := config["port"].(int); ok {
|
||||
port = p
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Default values
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
if port == 0 {
|
||||
port = 9380
|
||||
}
|
||||
|
||||
// Replace 0.0.0.0 with 127.0.0.1 for local check
|
||||
if host == "0.0.0.0" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("http://%s:%d/v1/system/ping", host, port)
|
||||
|
||||
// Create HTTP client with timeout
|
||||
client := &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"service_name": name,
|
||||
"status": "timeout",
|
||||
"message": fmt.Sprintf("error: %s", err.Error()),
|
||||
}, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
elapsed := time.Since(startTime).Milliseconds()
|
||||
if resp.StatusCode == 200 {
|
||||
return map[string]interface{}{
|
||||
"service_name": name,
|
||||
"status": "alive",
|
||||
"message": fmt.Sprintf("Confirm elapsed: %.1f ms.", float64(elapsed)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"service_name": name,
|
||||
"status": "timeout",
|
||||
"message": fmt.Sprintf("Confirm elapsed: %.1f ms.", float64(elapsed)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// checkTaskExecutorAlive checks if task executor is alive
|
||||
func (s *Service) checkTaskExecutorAlive(name string) (map[string]interface{}, error) {
|
||||
// TODO: Implement actual task executor health check
|
||||
@@ -1439,7 +1372,10 @@ func (s *Service) SetVariable(ctx context.Context, varName, varValue string) err
|
||||
// ListAllConfigs list all configs
|
||||
// Returns all service configurations from the config file
|
||||
func (s *Service) ListAllConfigs() ([]map[string]interface{}, error) {
|
||||
result := server.GetAllConfigs()
|
||||
result, err := server.GetAllConfigs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -319,8 +319,6 @@ func (c *CLI) ExecuteUserCommand(cmd *Command) (ResponseIf, error) {
|
||||
return c.Logout()
|
||||
case "api_ping_server":
|
||||
return c.PingServerByCommand(cmd)
|
||||
case "api_list_configs":
|
||||
return c.ListConfigs(cmd)
|
||||
case "api_set_log_level":
|
||||
return c.APISetLogLevelCommand(cmd)
|
||||
case "benchmark":
|
||||
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Show server version to show RAGFlow server version
|
||||
// APIShowVersionCommand show RAGFlow server version
|
||||
// Returns benchmark result map if iterations > 1, otherwise prints status
|
||||
func (c *CLI) APIShowVersionCommand(cmd *Command) (ResponseIf, error) {
|
||||
// Get iterations from command params (for benchmark)
|
||||
@@ -73,160 +73,6 @@ func (c *CLI) APIShowVersionCommand(cmd *Command) (ResponseIf, error) {
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (c *CLI) ListConfigs(cmd *Command) (ResponseIf, error) {
|
||||
if c.Config.CLIMode != APIMode {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
}
|
||||
// Get iterations from command params (for benchmark)
|
||||
iterations := 1
|
||||
if val, ok := cmd.Params["iterations"].(int); ok && val > 1 {
|
||||
iterations = val
|
||||
}
|
||||
|
||||
httpClient := c.APIServerClientMap[c.Config.APIClientConfig.CurrentAPIServer]
|
||||
|
||||
if iterations > 1 {
|
||||
// Benchmark mode: multiple iterations
|
||||
return httpClient.RequestWithIterations("GET", "/system/configs", "web", nil, nil, iterations)
|
||||
}
|
||||
|
||||
// Single mode
|
||||
resp, err := httpClient.Request("GET", "/system/configs", "web", nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list configs: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("failed to list configs: HTTP %d, body: %s", resp.StatusCode, string(resp.Body))
|
||||
}
|
||||
|
||||
var response CommonDataResponse
|
||||
if err = json.Unmarshal(resp.Body, &response); err != nil {
|
||||
return nil, fmt.Errorf("list configs failed: invalid JSON (%w)", err)
|
||||
}
|
||||
|
||||
var result CommonResponse
|
||||
result.Code = 0
|
||||
result.Data, err = GetConfigs(&response.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list configs: %w", err)
|
||||
}
|
||||
result.Duration = resp.Duration
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func GetConfigs(config *map[string]interface{}) ([]map[string]interface{}, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("config is nil")
|
||||
}
|
||||
result := []map[string]interface{}{}
|
||||
{
|
||||
redisHost := GetHost(config, "Redis", "Host", "Port")
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "redis_host",
|
||||
"value": redisHost})
|
||||
}
|
||||
{
|
||||
if docEngine, ok := (*config)["DocEngine"].(map[string]interface{}); ok {
|
||||
engineType, _ := docEngine["Type"].(string)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "doc_engine",
|
||||
"value": engineType})
|
||||
if engineType == "elasticsearch" {
|
||||
esCfg, _ := docEngine["ES"].(map[string]interface{})
|
||||
esHost, _ := esCfg["Hosts"].(string)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "elasticsearch_host",
|
||||
"value": esHost})
|
||||
} else if engineType == "Infinity" {
|
||||
infinityCfg, _ := docEngine["Infinity"].(map[string]interface{})
|
||||
infinityHost, _ := infinityCfg["URI"]
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "infinity_host",
|
||||
"value": infinityHost})
|
||||
} else {
|
||||
return nil, fmt.Errorf("unknown doc engine: %s", engineType)
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
if logConfig, ok := (*config)["Log"].(map[string]interface{}); ok {
|
||||
level, _ := logConfig["Level"].(string)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "log_level",
|
||||
"value": level})
|
||||
}
|
||||
}
|
||||
{
|
||||
if databaseConfig, ok := (*config)["Database"].(map[string]interface{}); ok {
|
||||
driver, _ := databaseConfig["Driver"].(string)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "database",
|
||||
"value": driver})
|
||||
driverAddr, _ := databaseConfig["Host"].(string)
|
||||
driverPort, _ := databaseConfig["Port"].(float64)
|
||||
driverHost := fmt.Sprintf("%s:%0.f", driverAddr, driverPort)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "database_host",
|
||||
"value": driverHost})
|
||||
}
|
||||
}
|
||||
{
|
||||
if language, ok := (*config)["Language"].(map[string]interface{}); ok {
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "language",
|
||||
"value": language})
|
||||
}
|
||||
}
|
||||
{
|
||||
if adminConfig, ok := (*config)["Admin"].(map[string]interface{}); ok {
|
||||
adminAddr, _ := adminConfig["Host"].(string)
|
||||
adminPort, _ := adminConfig["Port"].(float64)
|
||||
adminHost := fmt.Sprintf("%s:%0.f", adminAddr, adminPort)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "admin",
|
||||
"value": adminHost})
|
||||
}
|
||||
}
|
||||
{
|
||||
if storageEngineConfig, ok := (*config)["StorageEngine"].(map[string]interface{}); ok {
|
||||
engineType, _ := storageEngineConfig["Type"].(string)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "storage_engine",
|
||||
"value": engineType})
|
||||
if engineType == "minio" {
|
||||
minioCfg, _ := storageEngineConfig["Minio"].(map[string]interface{})
|
||||
miniHost, _ := minioCfg["Host"].(string)
|
||||
result = append(result, map[string]interface{}{
|
||||
"key": "minio_host",
|
||||
"value": miniHost})
|
||||
} else {
|
||||
return nil, fmt.Errorf("unknown storage engine: %s", engineType)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GetHost(config *map[string]interface{}, serverType, address, port string) string {
|
||||
if config == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
result := ""
|
||||
|
||||
if redis, ok := (*config)[serverType].(map[string]interface{}); ok {
|
||||
serverAddr, hostOk := redis[address].(string)
|
||||
serverPort, portOk := redis[port].(float64)
|
||||
|
||||
if hostOk && portOk {
|
||||
result = fmt.Sprintf("%s:%.0f", serverAddr, serverPort)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *CLI) APISetLogLevelCommand(cmd *Command) (ResponseIf, error) {
|
||||
if c.Config.CLIMode != APIMode {
|
||||
return nil, fmt.Errorf("this command is only allowed in USER mode")
|
||||
|
||||
@@ -129,8 +129,6 @@ func (p *Parser) parseAPIListCommands() (*Command, error) {
|
||||
p.nextToken() // consume LIST
|
||||
|
||||
switch p.curToken.Type {
|
||||
case TokenConfigs:
|
||||
return p.parseAPIListConfigs()
|
||||
case TokenDatasets:
|
||||
return p.parseAPIListDatasets()
|
||||
case TokenDataset:
|
||||
@@ -168,17 +166,6 @@ func (p *Parser) parseAPIListCommands() (*Command, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// LIST CONFIGS;
|
||||
func (p *Parser) parseAPIListConfigs() (*Command, error) {
|
||||
p.nextToken()
|
||||
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
return NewCommand("api_list_configs"), nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseAPIListDatasets() (*Command, error) {
|
||||
cmd := NewCommand("api_list_datasets")
|
||||
p.nextToken() // consume DATASETS
|
||||
|
||||
@@ -38,7 +38,7 @@ func (FileCommit) TableName() string {
|
||||
// FileCommitItem represents a single file change within a commit.
|
||||
type FileCommitItem struct {
|
||||
ID string `gorm:"column:id;primaryKey;size:32" json:"id"`
|
||||
Seq uint `gorm:"column:seq;autoIncrement;index" json:"seq,omitempty"`
|
||||
Seq uint `gorm:"column:seq;index" json:"seq,omitempty"`
|
||||
CommitID string `gorm:"column:commit_id;size:32;not null;uniqueIndex:idx_commit_file" json:"commit_id"`
|
||||
FileID string `gorm:"column:file_id;size:255;not null;uniqueIndex:idx_commit_file" json:"file_id"`
|
||||
Operation string `gorm:"column:operation;size:16;not null;index" json:"operation"`
|
||||
|
||||
@@ -153,10 +153,6 @@ func (r *Router) Setup(engine *gin.Engine) {
|
||||
// Health check
|
||||
engine.GET("/health", r.systemHandler.Health)
|
||||
|
||||
// System endpoints
|
||||
engine.GET("/v1/system/configs", r.systemHandler.GetConfigs)
|
||||
//engine.POST("/v1/user/register", r.userHandler.Register)
|
||||
|
||||
// User logout endpoint
|
||||
engine.GET("/v1/user/logout", r.userHandler.Logout)
|
||||
|
||||
@@ -669,7 +665,6 @@ func (r *Router) Setup(engine *gin.Engine) {
|
||||
|
||||
system := v1.Group("/system")
|
||||
{
|
||||
system.GET("/configs", r.systemHandler.GetConfigs)
|
||||
system.GET("/status", r.systemHandler.GetStatus)
|
||||
system.GET("/stats", r.statsHandler.GetStats) // TODO: need to reconsider this endpoint and function
|
||||
|
||||
|
||||
@@ -19,15 +19,10 @@ package server
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"ragflow/internal/server/config"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ragflow/internal/common"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -35,117 +30,6 @@ import (
|
||||
// DefaultConnectTimeout default connection timeout for external services
|
||||
const DefaultConnectTimeout = 5 * time.Second
|
||||
|
||||
// Config application configuration
|
||||
type Config struct {
|
||||
General GeneralConfig `mapstructure:"general"`
|
||||
Authentication AuthenticationConfig `mapstructure:"authentication"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
Nats NatsConfig `mapstructure:"nats"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
DocEngine DocEngineConfig `mapstructure:"doc_engine"`
|
||||
StorageEngine StorageConfig `mapstructure:"storage_engine"`
|
||||
RegisterEnabled int `mapstructure:"register_enabled"`
|
||||
OAuth map[string]OAuthConfig `mapstructure:"oauth"`
|
||||
SMTP common.SMTPConfig `mapstructure:"smtp"`
|
||||
Admin AdminConfig `mapstructure:"admin"`
|
||||
APIServer APIServerConfig `mapstructure:"ragflow"`
|
||||
UserDefaultLLM UserDefaultLLMConfig `mapstructure:"user_default_llm"`
|
||||
DefaultSuperUser DefaultSuperUser `mapstructure:"default_super_user"`
|
||||
Language string `mapstructure:"language"`
|
||||
Ingestor IngestorConfig `mapstructure:"ingestor"`
|
||||
FileSyncer FileSyncerConfig `mapstructure:"file_syncer"`
|
||||
OTel OtelConfig `mapstructure:"otel"`
|
||||
Clickhouse ClickhouseConfig `mapstructure:"clickhouse"`
|
||||
}
|
||||
|
||||
// GeneralConfig general configuration
|
||||
type GeneralConfig struct {
|
||||
HeartbeatInterval time.Duration `mapstructure:"heartbeat_interval"`
|
||||
Mode string `mapstructure:"mode"` // debug, release
|
||||
SecretKey *string `mapstructure:"secret_key"`
|
||||
DocEngine string `mapstructure:"doc_engine"` // Infinity, Elasticsearch
|
||||
StorageEngine string `mapstructure:"storage_engine"` // Minio, S3
|
||||
CacheEngine string `mapstructure:"cache_engine"` // Redis
|
||||
QueueEngine string `mapstructure:"queue_engine"` // NATS
|
||||
AnalyticEngine string `mapstructure:"analytic_engine"` // Clickhouse
|
||||
}
|
||||
|
||||
// AdminConfig admin server configuration
|
||||
type AdminConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"http_port"`
|
||||
}
|
||||
|
||||
type APIServerConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"http_port"`
|
||||
}
|
||||
|
||||
type AuthenticationConfig struct {
|
||||
DisablePasswordLogin bool `mapstructure:"disable_password_login"`
|
||||
RegisterEnabled bool `mapstructure:"register_enabled"`
|
||||
}
|
||||
|
||||
type DefaultSuperUser struct {
|
||||
Email string `mapstructure:"email"`
|
||||
Password string `mapstructure:"password"`
|
||||
Nickname string `mapstructure:"nickname"`
|
||||
}
|
||||
|
||||
type IngestorConfig struct {
|
||||
MQType string `mapstructure:"mq_type"`
|
||||
}
|
||||
|
||||
type TaskExecutorConfig struct {
|
||||
MessageQueueType string `mapstructure:"message_queue_type"`
|
||||
}
|
||||
|
||||
type FileSyncerConfig struct {
|
||||
MaxConcurrentSyncs int `mapstructure:"max_concurrent_syncs"`
|
||||
SyncInterval int `mapstructure:"sync_interval"`
|
||||
}
|
||||
|
||||
type OtelConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
SampleRatio float64 `mapstructure:"sample_ratio"`
|
||||
Secure bool `mapstructure:"secure"`
|
||||
Stdout bool `mapstructure:"stdout"`
|
||||
Enable bool `mapstructure:"enable"`
|
||||
}
|
||||
|
||||
type ClickhouseConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
User string `mapstructure:"user"`
|
||||
Password string `mapstructure:"password"`
|
||||
Database string `mapstructure:"database"`
|
||||
}
|
||||
|
||||
type UserDefaultLLMConfig struct {
|
||||
DefaultModels DefaultModelsConfig `mapstructure:"default_models"`
|
||||
}
|
||||
|
||||
// DefaultModelsConfig default models configuration
|
||||
type DefaultModelsConfig struct {
|
||||
ChatModel ModelConfig `mapstructure:"chat_model"`
|
||||
EmbeddingModel ModelConfig `mapstructure:"embedding_model"`
|
||||
RerankModel ModelConfig `mapstructure:"rerank_model"`
|
||||
ASRModel ModelConfig `mapstructure:"asr_model"`
|
||||
Image2TextModel ModelConfig `mapstructure:"image2text_model"`
|
||||
OCRModel ModelConfig `mapstructure:"ocr_model"`
|
||||
TTSModel ModelConfig `mapstructure:"tts_model"`
|
||||
}
|
||||
|
||||
// ModelConfig model configuration
|
||||
type ModelConfig struct {
|
||||
Name string `mapstructure:"name"`
|
||||
APIKey string `mapstructure:"api_key"`
|
||||
BaseURL string `mapstructure:"base_url"`
|
||||
Factory string `mapstructure:"factory"`
|
||||
}
|
||||
|
||||
// OAuthConfig OAuth configuration for a channel.
|
||||
// Mirrors api/apps/auth/__init__.py's OAUTH_CONFIG entries: a Type that
|
||||
// selects the auth client flavor (oauth2 / oidc / GitHub), plus the
|
||||
@@ -166,346 +50,15 @@ type OAuthConfig struct {
|
||||
Issuer string `mapstructure:"issuer"`
|
||||
}
|
||||
|
||||
// DatabaseConfig database configuration
|
||||
type DatabaseConfig struct {
|
||||
Driver string `mapstructure:"driver"` // mysql
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
Database string `mapstructure:"database"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
Charset string `mapstructure:"charset"`
|
||||
}
|
||||
|
||||
// LogConfig logging configuration.
|
||||
//
|
||||
// Path, MaxSize, MaxBackups, MaxAge, and Compress configure the rotated
|
||||
// log file. The cmd/* entry points hardcode per-service defaults
|
||||
// (e.g. "server_main.log" for the API server, "admin_server.log" for
|
||||
// the admin server, "ingestion_server.log" for the ingestion worker),
|
||||
// so a typical deployment gets a rotated file without any YAML
|
||||
// configuration. When Path is empty (the default) the binary's
|
||||
// hardcoded default filename is used — it does NOT disable file
|
||||
// output. Set log.path in service_conf.yaml to override the
|
||||
// per-service default filename.
|
||||
//
|
||||
// Compress is a pointer so callers can distinguish "not set" (nil,
|
||||
// defaults to true) from "explicitly false" (*bool=false). All other
|
||||
// numeric fields use plain int because their zero values are sensible
|
||||
// defaults (100 MB / 10 files / 30 days) and there is no operator-meaningful
|
||||
// reason to distinguish "not set" from "0".
|
||||
type LogConfig struct {
|
||||
Level string `mapstructure:"level"` // debug, info, warn, error
|
||||
Format string `mapstructure:"format"` // json, text (reserved for future use)
|
||||
Path string `mapstructure:"path"` // per-binary file override; empty = use cmd/* hardcoded default
|
||||
MaxSize int `mapstructure:"max_size"` // MB before rotation; default 100
|
||||
MaxBackups int `mapstructure:"max_backups"` // retained rotated files; default 10
|
||||
MaxAge int `mapstructure:"max_age"` // days; default 30
|
||||
Compress *bool `mapstructure:"compress"` // gzip rotated files; nil = default true
|
||||
}
|
||||
|
||||
// DocEngineConfig document engine configuration
|
||||
type DocEngineConfig struct {
|
||||
Type EngineType `mapstructure:"type"`
|
||||
ES *ElasticsearchConfig `mapstructure:"es"`
|
||||
Infinity *InfinityConfig `mapstructure:"infinity"`
|
||||
}
|
||||
|
||||
// EngineType document engine type
|
||||
type EngineType string
|
||||
|
||||
const (
|
||||
EngineElasticsearch EngineType = "elasticsearch"
|
||||
EngineInfinity EngineType = "infinity"
|
||||
)
|
||||
|
||||
// ElasticsearchConfig Elasticsearch configuration
|
||||
type ElasticsearchConfig struct {
|
||||
Hosts string `mapstructure:"hosts"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
}
|
||||
|
||||
// InfinityConfig Infinity configuration
|
||||
type InfinityConfig struct {
|
||||
URI string `mapstructure:"uri"`
|
||||
PostgresPort int `mapstructure:"postgres_port"`
|
||||
DBName string `mapstructure:"db_name"`
|
||||
MappingFileName string `mapstructure:"mapping_file_name"`
|
||||
DocMetaMappingFileName string `mapstructure:"doc_meta_mapping_file_name"`
|
||||
}
|
||||
|
||||
type StorageType string
|
||||
|
||||
// StorageConfig holds all storage-related configurations
|
||||
type StorageConfig struct {
|
||||
Type StorageType `mapstructure:"type"`
|
||||
Minio *MinioConfig `mapstructure:"minio"`
|
||||
S3 *S3Config `mapstructure:"s3"`
|
||||
OSS *OSSConfig `mapstructure:"oss"`
|
||||
GCS *GCSConfig `mapstructure:"gcs"`
|
||||
}
|
||||
|
||||
const (
|
||||
StorageOSS StorageType = "oss"
|
||||
StorageS3 StorageType = "s3"
|
||||
StorageMinio StorageType = "minio"
|
||||
StorageGCS StorageType = "gcs"
|
||||
)
|
||||
|
||||
// OSSConfig holds Aliyun OSS storage configuration
|
||||
// OSS is compatible with S3 API
|
||||
type OSSConfig struct {
|
||||
AccessKey string `mapstructure:"access_key"` // OSS Access Key ID
|
||||
SecretKey string `mapstructure:"secret_key"` // OSS Secret Access Key
|
||||
EndpointURL string `mapstructure:"endpoint_url"` // OSS Endpoint (e.g., "https://oss-cn-hangzhou.aliyuncs.com")
|
||||
Region string `mapstructure:"region"` // Region (e.g., "cn-hangzhou")
|
||||
Bucket string `mapstructure:"bucket"` // Default bucket (optional)
|
||||
PrefixPath string `mapstructure:"prefix_path"` // Path prefix (optional)
|
||||
SignatureVersion string `mapstructure:"signature_version"` // Signature version
|
||||
AddressingStyle string `mapstructure:"addressing_style"` // Addressing style
|
||||
}
|
||||
|
||||
type GCSConfig struct {
|
||||
Bucket string `mapstructure:"bucket"` // Default bucket (optional)
|
||||
PrefixPath string `mapstructure:"prefix_path"` // Path prefix (optional)
|
||||
EndpointURL string `mapstructure:"endpoint_url"` // Custom endpoint (optional)
|
||||
}
|
||||
|
||||
// MinioConfig holds MinIO storage configuration
|
||||
type MinioConfig struct {
|
||||
Host string `mapstructure:"host"` // MinIO server host (e.g., "localhost:9000")
|
||||
User string `mapstructure:"user"` // Access key
|
||||
Password string `mapstructure:"password"` // Secret key
|
||||
Secure bool `mapstructure:"secure"` // Use HTTPS
|
||||
Verify bool `mapstructure:"verify"` // Verify SSL certificates
|
||||
Region string `mapstructure:"region"` // optional
|
||||
Bucket string `mapstructure:"bucket"` // Default bucket (optional)
|
||||
PrefixPath string `mapstructure:"prefix_path"` // Path prefix (optional)
|
||||
}
|
||||
|
||||
// S3Config holds AWS S3 storage configuration
|
||||
type S3Config struct {
|
||||
AccessKey string `mapstructure:"access_key"` // AWS Access Key ID
|
||||
SecretKey string `mapstructure:"secret_key"` // AWS Secret Access Key
|
||||
Region string `mapstructure:"region_name"` // AWS Region
|
||||
SessionToken string `mapstructure:"session_token"` // AWS Session Token (optional)
|
||||
EndpointURL string `mapstructure:"endpoint_url"` // Custom endpoint (optional)
|
||||
SignatureVersion string `mapstructure:"signature_version"` // Signature version
|
||||
AddressingStyle string `mapstructure:"addressing_style"` // Addressing style
|
||||
Bucket string `mapstructure:"bucket"` // Default bucket (optional)
|
||||
PrefixPath string `mapstructure:"prefix_path"` // Path prefix (optional)
|
||||
}
|
||||
|
||||
// RedisConfig Redis configuration
|
||||
type RedisConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
Password string `mapstructure:"password"`
|
||||
DB int `mapstructure:"db"`
|
||||
}
|
||||
|
||||
type NatsConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
}
|
||||
|
||||
var (
|
||||
globalConfig *config.Config
|
||||
globalViper *viper.Viper
|
||||
zapLogger *zap.Logger
|
||||
allConfigs []map[string]interface{}
|
||||
)
|
||||
|
||||
// Init initialize configuration
|
||||
func Init(configPath string) error {
|
||||
|
||||
err := FromConfigFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = FromEnvironments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//id := 0
|
||||
//for k, v := range globalViper.AllSettings() {
|
||||
// configDict, ok := v.(map[string]interface{})
|
||||
// if !ok {
|
||||
// continue
|
||||
// }
|
||||
//
|
||||
// switch k {
|
||||
// case "ragflow":
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = fmt.Sprintf("ragflow_%d", id)
|
||||
// configDict["service_type"] = "ragflow_server"
|
||||
// configDict["extra"] = map[string]interface{}{}
|
||||
// configDict["port"] = configDict["http_port"]
|
||||
// delete(configDict, "http_port")
|
||||
// case "es":
|
||||
// // Skip if retrieval_type doesn't match doc_engine
|
||||
// if globalConfig.DocEngine.Type != "elasticsearch" {
|
||||
// continue
|
||||
// }
|
||||
// hosts := getString(configDict, "hosts")
|
||||
// host, port := parseHostPort(hosts)
|
||||
// username := getString(configDict, "username")
|
||||
// password := getString(configDict, "password")
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "elasticsearch"
|
||||
// configDict["host"] = host
|
||||
// configDict["port"] = port
|
||||
// configDict["service_type"] = "retrieval"
|
||||
// configDict["extra"] = map[string]interface{}{
|
||||
// "retrieval_type": "elasticsearch",
|
||||
// "username": username,
|
||||
// "password": password,
|
||||
// }
|
||||
// delete(configDict, "hosts")
|
||||
// delete(configDict, "username")
|
||||
// delete(configDict, "password")
|
||||
// case "infinity":
|
||||
// // Skip if retrieval_type doesn't match doc_engine
|
||||
// if globalConfig.DocEngine.Type != "infinity" {
|
||||
// continue
|
||||
// }
|
||||
// uri := getString(configDict, "uri")
|
||||
// host, port := parseHostPort(uri)
|
||||
// dbName := getString(configDict, "db_name")
|
||||
// if dbName == "" {
|
||||
// dbName = "default_db"
|
||||
// }
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "infinity"
|
||||
// configDict["host"] = host
|
||||
// configDict["port"] = port
|
||||
// configDict["service_type"] = "retrieval"
|
||||
// configDict["extra"] = map[string]interface{}{
|
||||
// "retrieval_type": "infinity",
|
||||
// "db_name": dbName,
|
||||
// }
|
||||
// case "minio":
|
||||
// hostPort := getString(configDict, "host")
|
||||
// host, port := parseHostPort(hostPort)
|
||||
// user := getString(configDict, "user")
|
||||
// password := getString(configDict, "password")
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "minio"
|
||||
// configDict["host"] = host
|
||||
// configDict["port"] = port
|
||||
// configDict["service_type"] = "file_store"
|
||||
// configDict["extra"] = map[string]interface{}{
|
||||
// "store_type": "minio",
|
||||
// "user": user,
|
||||
// "password": password,
|
||||
// }
|
||||
// delete(configDict, "bucket")
|
||||
// delete(configDict, "user")
|
||||
// delete(configDict, "password")
|
||||
// case "redis":
|
||||
// hostPort := getString(configDict, "host")
|
||||
// host, port := parseHostPort(hostPort)
|
||||
// password := getString(configDict, "password")
|
||||
// db := getInt(configDict, "db")
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "redis"
|
||||
// configDict["host"] = host
|
||||
// configDict["port"] = port
|
||||
// configDict["service_type"] = "cache"
|
||||
// configDict["extra"] = map[string]interface{}{
|
||||
// "mq_type": "redis",
|
||||
// "database": db,
|
||||
// "password": password,
|
||||
// }
|
||||
// delete(configDict, "password")
|
||||
// delete(configDict, "db")
|
||||
// case "mysql":
|
||||
// host := getString(configDict, "host")
|
||||
// port := getInt(configDict, "port")
|
||||
// user := getString(configDict, "user")
|
||||
// password := getString(configDict, "password")
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "mysql"
|
||||
// configDict["host"] = host
|
||||
// configDict["port"] = port
|
||||
// configDict["service_type"] = "meta_data"
|
||||
// configDict["extra"] = map[string]interface{}{
|
||||
// "meta_type": "mysql",
|
||||
// "username": user,
|
||||
// "password": password,
|
||||
// }
|
||||
// delete(configDict, "stale_timeout")
|
||||
// delete(configDict, "max_connections")
|
||||
// delete(configDict, "max_allowed_packet")
|
||||
// delete(configDict, "user")
|
||||
// delete(configDict, "password")
|
||||
// case "ingestor":
|
||||
// mqType := getString(configDict, "mq_type")
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "ingestor"
|
||||
// configDict["service_type"] = "ingestor"
|
||||
// configDict["extra"] = map[string]interface{}{
|
||||
// "message_queue_type": mqType,
|
||||
// }
|
||||
// delete(configDict, "message_queue_type")
|
||||
// case "nats":
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "nats"
|
||||
// configDict["service_type"] = "message_queue"
|
||||
// case "otel":
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "jaeger"
|
||||
// configDict["service_type"] = "tracing"
|
||||
// case "clickhouse":
|
||||
// configDict["id"] = id
|
||||
// configDict["name"] = "clickhouse"
|
||||
// configDict["service_type"] = "olap"
|
||||
// case "admin":
|
||||
// // Skip admin section
|
||||
// continue
|
||||
// default:
|
||||
// // Skip unknown sections
|
||||
// continue
|
||||
// }
|
||||
//
|
||||
// // Set default values for empty host/port
|
||||
// if configDict["host"] == "" {
|
||||
// configDict["host"] = "-"
|
||||
// }
|
||||
// if configDict["port"] == 0 {
|
||||
// configDict["port"] = "-"
|
||||
// }
|
||||
//
|
||||
// delete(configDict, "prefix_path")
|
||||
// delete(configDict, "username")
|
||||
// allConfigs = append(allConfigs, configDict)
|
||||
// id++
|
||||
//}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func FromEnvironments() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func minioEndpoint(host, configuredEndpoint string) string {
|
||||
if _, _, err := net.SplitHostPort(host); err == nil {
|
||||
return host
|
||||
}
|
||||
|
||||
port := "9000"
|
||||
if _, configuredPort, err := net.SplitHostPort(configuredEndpoint); err == nil && configuredPort != "" {
|
||||
port = configuredPort
|
||||
}
|
||||
|
||||
return net.JoinHostPort(strings.Trim(host, "[]"), port)
|
||||
}
|
||||
|
||||
func FromConfigFile(configPath string) error {
|
||||
v := viper.New()
|
||||
|
||||
// Set configuration file path
|
||||
@@ -628,278 +181,6 @@ func FromConfigFile(configPath string) error {
|
||||
return fmt.Errorf("parse OAuth config error: %w", err)
|
||||
}
|
||||
|
||||
//// Set default values for admin configuration if not configured
|
||||
//if globalConfig.Admin.Host == "" {
|
||||
// globalConfig.Admin.Host = "127.0.0.1"
|
||||
//}
|
||||
//if globalConfig.Admin.Port == 0 {
|
||||
// globalConfig.Admin.Port = 9383
|
||||
//} else {
|
||||
// globalConfig.Admin.Port += 2
|
||||
//}
|
||||
|
||||
//// authentication section
|
||||
//if globalConfig != nil {
|
||||
// // Try to map from mysql section
|
||||
// globalConfig.Authentication.DisablePasswordLogin = false
|
||||
// globalConfig.Authentication.RegisterEnabled = true
|
||||
// if v.IsSet("authentication") {
|
||||
// authenticationConfig := v.Sub("authentication")
|
||||
// if authenticationConfig != nil {
|
||||
// if authenticationConfig.IsSet("disable_password_login") {
|
||||
// globalConfig.Authentication.DisablePasswordLogin = authenticationConfig.GetBool("disable_password_login")
|
||||
// }
|
||||
// if authenticationConfig.IsSet("enable_register") {
|
||||
// globalConfig.Authentication.RegisterEnabled = authenticationConfig.GetBool("enable_register")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// If we loaded service_conf.yaml, map mysql fields to DatabaseConfig
|
||||
//if globalConfig != nil && globalConfig.Database.Host == "" {
|
||||
// // Try to map from mysql section
|
||||
// if v.IsSet("mysql") {
|
||||
// mysqlConfig := v.Sub("mysql")
|
||||
// if mysqlConfig != nil {
|
||||
// globalConfig.Database.Driver = "mysql"
|
||||
// globalConfig.Database.Host = mysqlConfig.GetString("host")
|
||||
// globalConfig.Database.Port = mysqlConfig.GetInt("port")
|
||||
// globalConfig.Database.Database = mysqlConfig.GetString("name")
|
||||
// globalConfig.Database.Username = mysqlConfig.GetString("user")
|
||||
// globalConfig.Database.Password = mysqlConfig.GetString("password")
|
||||
// globalConfig.Database.Charset = "utf8mb4"
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// Map ragflow section to ServerConfig
|
||||
//if globalConfig != nil && globalConfig.APIServer.Port == 0 {
|
||||
// // Try to map from ragflow section
|
||||
// if v.IsSet("ragflow") {
|
||||
// ragflowConfig := v.Sub("ragflow")
|
||||
// if ragflowConfig != nil {
|
||||
// globalConfig.APIServer.Port = ragflowConfig.GetInt("http_port") + 4 // 9384, by default
|
||||
// //globalConfig.Server.Port = ragflowConfig.GetInt("http_port") // Correct
|
||||
// // If mode is not set, default to debug
|
||||
// if globalConfig.General.Mode == "" {
|
||||
// globalConfig.General.Mode = "release"
|
||||
// }
|
||||
// secretKey := ragflowConfig.GetString("secret_key")
|
||||
// if secretKey != "" {
|
||||
// globalConfig.General.SecretKey = &secretKey
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//if globalConfig.APIServer.Port == 0 {
|
||||
// globalConfig.APIServer.Port = 9384
|
||||
//} else {
|
||||
// globalConfig.APIServer.Port += 4
|
||||
//}
|
||||
//
|
||||
//// Map redis section to RedisConfig
|
||||
//if globalConfig != nil && globalConfig.Redis.Host != "" {
|
||||
// if v.IsSet("redis") {
|
||||
// redisConfig := v.Sub("redis")
|
||||
// if redisConfig != nil {
|
||||
// hostStr := redisConfig.GetString("host")
|
||||
// // Handle host:port format (e.g., "localhost:6379")
|
||||
// if hostStr == "" {
|
||||
// return fmt.Errorf("empty host of Redis configuration")
|
||||
// }
|
||||
//
|
||||
// if idx := strings.LastIndex(hostStr, ":"); idx != -1 {
|
||||
// globalConfig.Redis.Host = hostStr[:idx]
|
||||
// if portStr := hostStr[idx+1:]; portStr != "" {
|
||||
// if port, err := strconv.Atoi(portStr); err == nil {
|
||||
// globalConfig.Redis.Port = port
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// return fmt.Errorf("error address format of Redis: %s", hostStr)
|
||||
// }
|
||||
//
|
||||
// globalConfig.Redis.Password = redisConfig.GetString("password")
|
||||
// globalConfig.Redis.DB = redisConfig.GetInt("db")
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// Map doc_engine section to DocEngineConfig
|
||||
//if globalConfig != nil {
|
||||
// // First, ensure engine type is set
|
||||
// if globalConfig.DocEngine.Type == "" {
|
||||
// if v.IsSet("doc_engine") {
|
||||
// docEngineConfig := v.Sub("doc_engine")
|
||||
// if docEngineConfig != nil {
|
||||
// globalConfig.DocEngine.Type = EngineType(docEngineConfig.GetString("type"))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Map es section from top-level (service_conf.yaml format)
|
||||
// if v.IsSet("es") {
|
||||
// esConfig := v.Sub("es")
|
||||
// if esConfig != nil {
|
||||
// // Set default engine type if not set
|
||||
// if globalConfig.DocEngine.Type == "" {
|
||||
// globalConfig.DocEngine.Type = EngineElasticsearch
|
||||
// }
|
||||
// // Always populate ES config if es section exists
|
||||
// if globalConfig.DocEngine.ES == nil {
|
||||
// globalConfig.DocEngine.ES = &ElasticsearchConfig{
|
||||
// Hosts: esConfig.GetString("hosts"),
|
||||
// Username: esConfig.GetString("username"),
|
||||
// Password: esConfig.GetString("password"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Map infinity section from top-level (service_conf.yaml format)
|
||||
// if v.IsSet("infinity") {
|
||||
// infConfig := v.Sub("infinity")
|
||||
// if infConfig != nil {
|
||||
// // Set default engine type if not set
|
||||
// if globalConfig.DocEngine.Type == "" {
|
||||
// globalConfig.DocEngine.Type = EngineInfinity
|
||||
// }
|
||||
// // Always populate Infinity config if infinity section exists
|
||||
// if globalConfig.DocEngine.Infinity == nil {
|
||||
// globalConfig.DocEngine.Infinity = &InfinityConfig{
|
||||
// URI: infConfig.GetString("uri"),
|
||||
// PostgresPort: infConfig.GetInt("postgres_port"),
|
||||
// DBName: infConfig.GetString("db_name"),
|
||||
// MappingFileName: infConfig.GetString("mapping_file_name"),
|
||||
// DocMetaMappingFileName: infConfig.GetString("doc_meta_mapping_file_name"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//if globalConfig != nil && globalConfig.StorageEngine.Type == "" {
|
||||
// // Also check legacy es section for backward compatibility
|
||||
// if v.IsSet("minio") {
|
||||
// minioConfig := v.Sub("minio")
|
||||
// if minioConfig != nil {
|
||||
// if globalConfig.StorageEngine.Minio == nil {
|
||||
// globalConfig.StorageEngine.Minio = &MinioConfig{
|
||||
// Host: minioConfig.GetString("host"),
|
||||
// User: minioConfig.GetString("user"),
|
||||
// Password: minioConfig.GetString("password"),
|
||||
// Secure: minioConfig.GetBool("secure"),
|
||||
// PrefixPath: minioConfig.GetString("prefix_path"),
|
||||
// Verify: minioConfig.GetBool("verify"),
|
||||
// Region: minioConfig.GetString("region"),
|
||||
// Bucket: minioConfig.GetString("bucket"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if v.IsSet("gcs") {
|
||||
// gcsConfig := v.Sub("gcs")
|
||||
// if gcsConfig != nil {
|
||||
// if globalConfig.StorageEngine.GCS == nil {
|
||||
// globalConfig.StorageEngine.GCS = &GCSConfig{
|
||||
// Bucket: gcsConfig.GetString("bucket"),
|
||||
// PrefixPath: gcsConfig.GetString("prefix_path"),
|
||||
// EndpointURL: gcsConfig.GetString("endpoint_url"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if v.IsSet("minio_0") {
|
||||
// minioConfig := v.Sub("minio_0")
|
||||
// if minioConfig != nil {
|
||||
// if globalConfig.StorageEngine.Minio == nil {
|
||||
// globalConfig.StorageEngine.Minio = &MinioConfig{
|
||||
// Host: minioConfig.GetString("host"),
|
||||
// User: minioConfig.GetString("user"),
|
||||
// Password: minioConfig.GetString("password"),
|
||||
// Secure: minioConfig.GetBool("secure"),
|
||||
// PrefixPath: minioConfig.GetString("prefix_path"),
|
||||
// Verify: minioConfig.GetBool("verify"),
|
||||
// Bucket: minioConfig.GetString("bucket"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if v.IsSet("s3") {
|
||||
// s3Config := v.Sub("s3")
|
||||
// if s3Config != nil {
|
||||
// if globalConfig.StorageEngine.S3 == nil {
|
||||
// globalConfig.StorageEngine.S3 = &S3Config{
|
||||
// AccessKey: s3Config.GetString("access_key"),
|
||||
// SecretKey: s3Config.GetString("secret_key"),
|
||||
// Region: s3Config.GetString("region"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if v.IsSet("oss") {
|
||||
// ossConfig := v.Sub("oss")
|
||||
// if ossConfig != nil {
|
||||
// if globalConfig.StorageEngine.OSS == nil {
|
||||
// globalConfig.StorageEngine.OSS = &OSSConfig{
|
||||
// AccessKey: ossConfig.GetString("access_key"),
|
||||
// SecretKey: ossConfig.GetString("secret_key"),
|
||||
// EndpointURL: ossConfig.GetString("endpoint_url"),
|
||||
// Region: ossConfig.GetString("region"),
|
||||
// Bucket: ossConfig.GetString("bucket"),
|
||||
// SignatureVersion: ossConfig.GetString("signature_version"),
|
||||
// AddressingStyle: ossConfig.GetString("addressing_style"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//// Map user_default_llm section to UserDefaultLLMConfig
|
||||
//if v.IsSet("user_default_llm") {
|
||||
// userDefaultLLMConfig := v.Sub("user_default_llm")
|
||||
// if userDefaultLLMConfig != nil {
|
||||
// if defaultModels := userDefaultLLMConfig.Sub("default_models"); defaultModels != nil {
|
||||
// globalConfig.UserDefaultLLM.DefaultModels.ChatModel = ModelConfig{
|
||||
// Name: defaultModels.GetString("chat_model.name"),
|
||||
// APIKey: defaultModels.GetString("chat_model.api_key"),
|
||||
// BaseURL: defaultModels.GetString("chat_model.base_url"),
|
||||
// Factory: defaultModels.GetString("chat_model.factory"),
|
||||
// }
|
||||
// globalConfig.UserDefaultLLM.DefaultModels.EmbeddingModel = ModelConfig{
|
||||
// Name: defaultModels.GetString("embedding_model.name"),
|
||||
// APIKey: defaultModels.GetString("embedding_model.api_key"),
|
||||
// BaseURL: defaultModels.GetString("embedding_model.base_url"),
|
||||
// Factory: defaultModels.GetString("embedding_model.factory"),
|
||||
// }
|
||||
// globalConfig.UserDefaultLLM.DefaultModels.RerankModel = ModelConfig{
|
||||
// Name: defaultModels.GetString("rerank_model.name"),
|
||||
// APIKey: defaultModels.GetString("rerank_model.api_key"),
|
||||
// BaseURL: defaultModels.GetString("rerank_model.base_url"),
|
||||
// Factory: defaultModels.GetString("rerank_model.factory"),
|
||||
// }
|
||||
// globalConfig.UserDefaultLLM.DefaultModels.ASRModel = ModelConfig{
|
||||
// Name: defaultModels.GetString("asr_model.name"),
|
||||
// APIKey: defaultModels.GetString("asr_model.api_key"),
|
||||
// BaseURL: defaultModels.GetString("asr_model.base_url"),
|
||||
// Factory: defaultModels.GetString("asr_model.factory"),
|
||||
// }
|
||||
// globalConfig.UserDefaultLLM.DefaultModels.Image2TextModel = ModelConfig{
|
||||
// Name: defaultModels.GetString("image2text_model.name"),
|
||||
// APIKey: defaultModels.GetString("image2text_model.api_key"),
|
||||
// BaseURL: defaultModels.GetString("image2text_model.base_url"),
|
||||
// Factory: defaultModels.GetString("image2text_model.factory"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -908,21 +189,102 @@ func GetConfig() *config.Config {
|
||||
return globalConfig
|
||||
}
|
||||
|
||||
// GetAdminServerConfig gets the admin server configuration
|
||||
//func GetAdminServerConfig() *config.AdminConfig {
|
||||
// if globalConfig == nil {
|
||||
// return nil
|
||||
// }
|
||||
// return &globalConfig.Admin
|
||||
//}
|
||||
|
||||
// SetLogger sets the logger instance
|
||||
func SetLogger(l *zap.Logger) {
|
||||
zapLogger = l
|
||||
}
|
||||
|
||||
func GetAllConfigs() []map[string]interface{} {
|
||||
return allConfigs
|
||||
func GetAllConfigs() ([]map[string]interface{}, error) {
|
||||
var allConfigs []map[string]interface{}
|
||||
|
||||
// Database
|
||||
databaseType := globalConfig.DatabaseType()
|
||||
switch databaseType {
|
||||
case "mysql":
|
||||
mysqlConfig := globalConfig.GetMySQLConfig()
|
||||
exportedMySQLConfigs := mysqlConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedMySQLConfigs)
|
||||
default:
|
||||
return nil, fmt.Errorf("not supported database: %s", databaseType)
|
||||
}
|
||||
|
||||
// Doc engine
|
||||
docEngineType := globalConfig.DocEngineType()
|
||||
switch docEngineType {
|
||||
case "elasticsearch":
|
||||
elasticConfig := globalConfig.GetElasticsearchConfig()
|
||||
exportedESConfigs := elasticConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedESConfigs)
|
||||
case "infinity":
|
||||
infinityConfig := globalConfig.GetInfinityConfig()
|
||||
exportedInfinityConfigs := infinityConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedInfinityConfigs)
|
||||
default:
|
||||
return nil, fmt.Errorf("not supported doc engine: %s", docEngineType)
|
||||
}
|
||||
|
||||
// storage engine
|
||||
storageType := globalConfig.StorageEngineType()
|
||||
switch storageType {
|
||||
case "minio":
|
||||
minioConfig := globalConfig.GetMinioConfig()
|
||||
exportedMinioConfigs := minioConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedMinioConfigs)
|
||||
case "s3":
|
||||
s3Config := globalConfig.GetS3Config()
|
||||
exportedS3Configs := s3Config.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedS3Configs)
|
||||
case "oss":
|
||||
ossConfig := globalConfig.GetOSSConfig()
|
||||
exportedOSSConfigs := ossConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedOSSConfigs)
|
||||
case "gcs":
|
||||
gcsConfig := globalConfig.GetGCSConfig()
|
||||
exportedGCSConfigs := gcsConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedGCSConfigs)
|
||||
default:
|
||||
return nil, fmt.Errorf("not supported storage engine: %s", storageType)
|
||||
}
|
||||
|
||||
// cache engine
|
||||
cacheType := globalConfig.CacheEngineType()
|
||||
switch cacheType {
|
||||
case "redis":
|
||||
redisConfig := globalConfig.GetRedisConfig()
|
||||
exportedRedisConfigs := redisConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedRedisConfigs)
|
||||
default:
|
||||
return nil, fmt.Errorf("not supported cache engine: %s", cacheType)
|
||||
}
|
||||
|
||||
// message queue
|
||||
messageQueueType := globalConfig.QueueEngineType()
|
||||
switch messageQueueType {
|
||||
case "nats":
|
||||
natsConfig := globalConfig.GetNATSConfig()
|
||||
exportedNatsConfigs := natsConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedNatsConfigs)
|
||||
default:
|
||||
return nil, fmt.Errorf("not supported message queue: %s", messageQueueType)
|
||||
}
|
||||
|
||||
// analytical engine
|
||||
olapType := globalConfig.AnalyticEngineType()
|
||||
switch olapType {
|
||||
case "clickhouse":
|
||||
clickhouseConfig := globalConfig.GetClickhouseConfig()
|
||||
exportedClickhouseConfigs := clickhouseConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedClickhouseConfigs)
|
||||
default:
|
||||
return nil, fmt.Errorf("not supported analytical engine: %s", olapType)
|
||||
}
|
||||
|
||||
// tracing engine
|
||||
oTelConfig := globalConfig.GetOpenTelemetryConfig()
|
||||
exportedOTELConfigs := oTelConfig.ExportConfigs()
|
||||
allConfigs = append(allConfigs, exportedOTELConfigs)
|
||||
|
||||
return allConfigs, nil
|
||||
}
|
||||
|
||||
// PrintAll prints all configuration settings
|
||||
@@ -939,46 +301,3 @@ func PrintAll() {
|
||||
}
|
||||
zapLogger.Info("=== End Configurations ===")
|
||||
}
|
||||
|
||||
// parseHostPort parses host:port string and returns host and port
|
||||
func parseHostPort(hostPort string) (string, int) {
|
||||
if hostPort == "" {
|
||||
return "", 0
|
||||
}
|
||||
|
||||
// Handle URL format like http://host:port
|
||||
if strings.Contains(hostPort, "://") {
|
||||
u, err := url.Parse(hostPort)
|
||||
if err == nil {
|
||||
hostPort = u.Host
|
||||
}
|
||||
}
|
||||
|
||||
// Split host:port
|
||||
parts := strings.Split(hostPort, ":")
|
||||
host := parts[0]
|
||||
port := 0
|
||||
if len(parts) > 1 {
|
||||
port, _ = strconv.Atoi(parts[1])
|
||||
}
|
||||
return host, port
|
||||
}
|
||||
|
||||
// getString gets string value from map
|
||||
func getString(m map[string]interface{}, key string) string {
|
||||
if v, ok := m[key].(string); ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getInt gets int value from map
|
||||
func getInt(m map[string]interface{}, key string) int {
|
||||
if v, ok := m[key].(int); ok {
|
||||
return v
|
||||
}
|
||||
if v, ok := m[key].(float64); ok {
|
||||
return int(v)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -86,3 +86,14 @@ func (c *Config) parseClickhouseConfig(v *viper.Viper) error {
|
||||
func (c *Config) GetClickhouseConfig() ClickhouseConfig {
|
||||
return c.analyticEngine.Clickhouse
|
||||
}
|
||||
|
||||
func (c *ClickhouseConfig) ExportConfigs() map[string]interface{} {
|
||||
var clickhouseConfigs map[string]interface{}
|
||||
clickhouseConfigs = make(map[string]interface{})
|
||||
clickhouseConfigs["host"] = c.Host
|
||||
clickhouseConfigs["port"] = c.Port
|
||||
clickhouseConfigs["user"] = c.User
|
||||
clickhouseConfigs["password"] = c.Password
|
||||
clickhouseConfigs["database"] = c.Database
|
||||
return clickhouseConfigs
|
||||
}
|
||||
|
||||
@@ -103,3 +103,14 @@ func (c *Config) parseRedisConfig(v *viper.Viper) error {
|
||||
func (c *Config) GetRedisConfig() RedisConfig {
|
||||
return c.cacheEngine.Redis
|
||||
}
|
||||
|
||||
func (r RedisConfig) ExportConfigs() map[string]interface{} {
|
||||
var redisConfigs map[string]interface{}
|
||||
redisConfigs = make(map[string]interface{})
|
||||
redisConfigs["host"] = r.Host
|
||||
redisConfigs["port"] = r.Port
|
||||
redisConfigs["username"] = r.Username
|
||||
redisConfigs["password"] = r.Password
|
||||
redisConfigs["db"] = r.DB
|
||||
return redisConfigs
|
||||
}
|
||||
|
||||
@@ -111,3 +111,18 @@ func (c *Config) parseMySQLConfig(v *viper.Viper) {
|
||||
func (c *Config) GetMySQLConfig() MySQLConfig {
|
||||
return c.database.MySQL
|
||||
}
|
||||
|
||||
func (m *MySQLConfig) ExportConfigs() map[string]interface{} {
|
||||
var mysqlConfigs map[string]interface{}
|
||||
mysqlConfigs = make(map[string]interface{})
|
||||
mysqlConfigs["host"] = m.Host
|
||||
mysqlConfigs["port"] = m.Port
|
||||
mysqlConfigs["database_name"] = m.DatabaseName
|
||||
mysqlConfigs["username"] = m.User
|
||||
mysqlConfigs["password"] = m.Password
|
||||
mysqlConfigs["charset"] = m.Charset
|
||||
mysqlConfigs["max_connections"] = m.MaxConnections
|
||||
mysqlConfigs["stale_timeout"] = m.StaleTimeout
|
||||
mysqlConfigs["max_allowed_packet"] = m.MaxAllowedPacket
|
||||
return mysqlConfigs
|
||||
}
|
||||
|
||||
@@ -115,6 +115,15 @@ func (c *Config) GetElasticsearchConfig() ElasticsearchConfig {
|
||||
return c.docEngine.ES
|
||||
}
|
||||
|
||||
func (e ElasticsearchConfig) ExportConfigs() map[string]interface{} {
|
||||
var esConfigs map[string]interface{}
|
||||
esConfigs = make(map[string]interface{})
|
||||
esConfigs["hosts"] = e.Hosts
|
||||
esConfigs["username"] = e.Username
|
||||
esConfigs["password"] = e.Password
|
||||
return esConfigs
|
||||
}
|
||||
|
||||
func (c *Config) IsElasticConfigured() bool {
|
||||
return c.docEngine.ES.Hosts != ""
|
||||
}
|
||||
@@ -122,3 +131,14 @@ func (c *Config) IsElasticConfigured() bool {
|
||||
func (c *Config) GetInfinityConfig() InfinityConfig {
|
||||
return c.docEngine.Infinity
|
||||
}
|
||||
|
||||
func (i InfinityConfig) ExportConfigs() map[string]interface{} {
|
||||
var infinityConfigs map[string]interface{}
|
||||
infinityConfigs = make(map[string]interface{})
|
||||
infinityConfigs["uri"] = i.URI
|
||||
infinityConfigs["postgres_port"] = i.PostgresPort
|
||||
infinityConfigs["db_name"] = i.DBName
|
||||
infinityConfigs["mapping_file_name"] = i.MappingFileName
|
||||
infinityConfigs["doc_meta_mapping_file_name"] = i.DocMetaMappingFileName
|
||||
return infinityConfigs
|
||||
}
|
||||
|
||||
@@ -74,3 +74,15 @@ func (c *Config) ParseOpenTelemetryConfig(v *viper.Viper) error {
|
||||
func (c *Config) GetOpenTelemetryConfig() OpenTelemetryConfig {
|
||||
return c.oTel
|
||||
}
|
||||
|
||||
func (o OpenTelemetryConfig) ExportConfigs() map[string]interface{} {
|
||||
var oTelConfigs map[string]interface{}
|
||||
oTelConfigs = make(map[string]interface{})
|
||||
oTelConfigs["host"] = o.Host
|
||||
oTelConfigs["port"] = o.Port
|
||||
oTelConfigs["secure"] = o.Secure
|
||||
oTelConfigs["sample_ratio"] = o.SampleRatio
|
||||
oTelConfigs["stdout"] = o.Stdout
|
||||
oTelConfigs["enable"] = o.Enable
|
||||
return oTelConfigs
|
||||
}
|
||||
|
||||
@@ -72,3 +72,11 @@ func (c *Config) parseNATSConfig(v *viper.Viper) error {
|
||||
func (c *Config) GetNATSConfig() NATSConfig {
|
||||
return c.queueEngine.NATS
|
||||
}
|
||||
|
||||
func (n NATSConfig) ExportConfigs() map[string]interface{} {
|
||||
var natsConfigs map[string]interface{}
|
||||
natsConfigs = make(map[string]interface{})
|
||||
natsConfigs["host"] = n.Host
|
||||
natsConfigs["port"] = n.Port
|
||||
return natsConfigs
|
||||
}
|
||||
|
||||
@@ -284,14 +284,66 @@ func (c *Config) GetMinioConfig() MinioConfig {
|
||||
return c.storageEngine.Minio
|
||||
}
|
||||
|
||||
func (m MinioConfig) ExportConfigs() map[string]interface{} {
|
||||
var minioConfigs map[string]interface{}
|
||||
minioConfigs = make(map[string]interface{})
|
||||
minioConfigs["host"] = m.Host
|
||||
minioConfigs["user"] = m.User
|
||||
minioConfigs["password"] = m.Password
|
||||
minioConfigs["bucket"] = m.Bucket
|
||||
minioConfigs["prefix_path"] = m.PrefixPath
|
||||
minioConfigs["secure"] = m.Secure
|
||||
minioConfigs["verify"] = m.Verify
|
||||
minioConfigs["region"] = m.Region
|
||||
return minioConfigs
|
||||
}
|
||||
|
||||
func (c *Config) GetS3Config() S3Config {
|
||||
return c.storageEngine.S3
|
||||
}
|
||||
|
||||
func (s S3Config) ExportConfigs() map[string]interface{} {
|
||||
var s3Configs map[string]interface{}
|
||||
s3Configs = make(map[string]interface{})
|
||||
s3Configs["access_key"] = s.AccessKey
|
||||
s3Configs["secret_key"] = s.SecretKey
|
||||
s3Configs["region"] = s.Region
|
||||
s3Configs["session_token"] = s.SessionToken
|
||||
s3Configs["endpoint_url"] = s.EndpointURL
|
||||
s3Configs["signature_version"] = s.SignatureVersion
|
||||
s3Configs["addressing_style"] = s.AddressingStyle
|
||||
s3Configs["bucket"] = s.Bucket
|
||||
s3Configs["prefix_path"] = s.PrefixPath
|
||||
return s3Configs
|
||||
}
|
||||
|
||||
func (c *Config) GetOSSConfig() OSSConfig {
|
||||
return c.storageEngine.OSS
|
||||
}
|
||||
|
||||
func (o OSSConfig) ExportConfigs() map[string]interface{} {
|
||||
var ossConfigs map[string]interface{}
|
||||
ossConfigs = make(map[string]interface{})
|
||||
ossConfigs["access_key"] = o.AccessKey
|
||||
ossConfigs["secret_key"] = o.SecretKey
|
||||
ossConfigs["endpoint_url"] = o.EndpointURL
|
||||
ossConfigs["region"] = o.Region
|
||||
ossConfigs["bucket"] = o.Bucket
|
||||
ossConfigs["prefix_path"] = o.PrefixPath
|
||||
ossConfigs["signature_version"] = o.SignatureVersion
|
||||
ossConfigs["addressing_style"] = o.AddressingStyle
|
||||
return ossConfigs
|
||||
}
|
||||
|
||||
func (c *Config) GetGCSConfig() GCSConfig {
|
||||
return c.storageEngine.GCS
|
||||
}
|
||||
|
||||
func (g GCSConfig) ExportConfigs() map[string]interface{} {
|
||||
var gcsConfigs map[string]interface{}
|
||||
gcsConfigs = make(map[string]interface{})
|
||||
gcsConfigs["bucket"] = g.Bucket
|
||||
gcsConfigs["prefix_path"] = g.PrefixPath
|
||||
gcsConfigs["endpoint_url"] = g.EndpointURL
|
||||
return gcsConfigs
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -255,6 +256,8 @@ func wikiFileID(datasetID, pageType, slug string) string {
|
||||
return datasetID + "/" + pageType + "/" + slug
|
||||
}
|
||||
|
||||
var pageCommitSeq atomic.Uint64
|
||||
|
||||
// RecordPageEdit records a wiki/skill page edit as an audit commit with a
|
||||
// git-style parent chain (each edit points at the previous commit for the same
|
||||
// page). The new content_after is referenced in ES by doc_id; a unified diff of
|
||||
@@ -297,6 +300,8 @@ func (s *FileCommitService) RecordPageEdit(ctx context.Context, in PageEditCommi
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
item.Seq = uint(pageCommitSeq.Add(1))
|
||||
|
||||
// Read the parent inside the lock, on the shared connection, so it always
|
||||
// reflects the previously committed edit for this page.
|
||||
parentID, perr := s.commitItemDAO.GetLatestCommitIDByFileID(ctx, dao.DB, fileID)
|
||||
|
||||
32
internal/service/oauth_ee.go
Normal file
32
internal/service/oauth_ee.go
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"ragflow/internal/common"
|
||||
"ragflow/internal/engine/redis"
|
||||
)
|
||||
|
||||
func (s *UserService) OAuthLoginInitiate(channel string, redis *redis.Client) (*OAuthLoginInit, common.ErrorCode, error) {
|
||||
return nil, common.CodeServerError, fmt.Errorf("oauth login initiate not implemented")
|
||||
}
|
||||
|
||||
func (s *UserService) OAuthCallback(ctx context.Context, channel, code, callbackState, expectedState string, redis *redis.Client) (*OAuthCallbackResult, common.ErrorCode, error) {
|
||||
return nil, common.CodeDataError, fmt.Errorf("oauth callback not implemented")
|
||||
}
|
||||
@@ -80,7 +80,7 @@ type OAuthLoginInit struct {
|
||||
// OAuthLoginInitiate generates a state, persists it in Redis with a TTL,
|
||||
// and returns the authorization URL the browser should be redirected to.
|
||||
// Mirrors the body of Python's oauth_login.
|
||||
func (s *UserService) OAuthLoginInitiate(channel string, redis *redis.Client) (*OAuthLoginInit, common.ErrorCode, error) {
|
||||
func (s *UserService) OAuthLoginInitiateDeprecated(channel string, redis *redis.Client) (*OAuthLoginInit, common.ErrorCode, error) {
|
||||
cfg, ok := lookupOAuthConfig(channel)
|
||||
if !ok {
|
||||
return nil, common.CodeDataError, fmt.Errorf("%w: %s", ErrOAuthInvalidChannel, channel)
|
||||
@@ -127,7 +127,7 @@ type OAuthCallbackResult struct {
|
||||
// When redis is non-nil the state is also verified against and consumed
|
||||
// from Redis, defending against a replay where an attacker fishes a valid
|
||||
// state out of a victim's URL but does not have the cookie.
|
||||
func (s *UserService) OAuthCallback(ctx context.Context, channel, code, callbackState, expectedState string, redis *redis.Client) (*OAuthCallbackResult, common.ErrorCode, error) {
|
||||
func (s *UserService) OAuthCallbackDeprecated(ctx context.Context, channel, code, callbackState, expectedState string, redis *redis.Client) (*OAuthCallbackResult, common.ErrorCode, error) {
|
||||
cfg, ok := lookupOAuthConfig(channel)
|
||||
if !ok {
|
||||
return nil, common.CodeDataError, fmt.Errorf("%w: %s", ErrOAuthInvalidChannel, channel)
|
||||
|
||||
@@ -469,7 +469,10 @@ func (s *SystemService) SetVariable(ctx context.Context, varName, varValue strin
|
||||
// ListAllConfigs list all configs
|
||||
// Returns all service configurations from the config file
|
||||
func (s *SystemService) ListAllConfigs() ([]map[string]interface{}, error) {
|
||||
result := server.GetAllConfigs()
|
||||
result, err := server.GetAllConfigs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -836,15 +836,8 @@ func (s *UserService) ChangePassword(ctx context.Context, user *entity.User, req
|
||||
return common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// LoginChannel represents a login channel response
|
||||
type LoginChannel struct {
|
||||
Channel string `json:"channel"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
// GetLoginChannels gets all supported authentication channels
|
||||
func (s *UserService) GetLoginChannels() ([]*LoginChannel, common.ErrorCode, error) {
|
||||
func (s *UserService) GetLoginChannelsDeprecated() ([]*LoginChannel, common.ErrorCode, error) {
|
||||
//cfg := server.GetConfig()
|
||||
channels := make([]*LoginChannel, 0)
|
||||
|
||||
|
||||
32
internal/service/user_ee.go
Normal file
32
internal/service/user_ee.go
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package service
|
||||
|
||||
import "ragflow/internal/common"
|
||||
|
||||
type LoginChannel struct {
|
||||
Channel string `json:"channel"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
// GetLoginChannels gets all supported authentication channels
|
||||
func (s *UserService) GetLoginChannels() ([]*LoginChannel, common.ErrorCode, error) {
|
||||
channels := make([]*LoginChannel, 0)
|
||||
|
||||
return channels, common.CodeSuccess, nil
|
||||
}
|
||||
Reference in New Issue
Block a user