mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
Feature (System Settings): Implemented system settings management functionality (#13556)
### What problem does this PR solve? Feature (System Settings): Implemented system settings management functionality - Added a new SystemSettings model, including creation and update time fields. - Implemented SystemSettingsDAO, providing CRUD operations and transaction support. - Implemented management interfaces for variables, configurations, and environment variables in the admin service. ### Type of change - [x] New Feature (non-breaking change which adds functionality) Co-authored-by: Yingfeng <yingfeng.zhang@gmail.com>
This commit is contained in:
@@ -767,28 +767,46 @@ func (h *Handler) RestartService(c *gin.Context) {
|
||||
}
|
||||
|
||||
// GetVariables handle get variables
|
||||
// Python logic: if request body is empty, list all variables; otherwise get single variable by var_name from body
|
||||
func (h *Handler) GetVariables(c *gin.Context) {
|
||||
varName := c.Query("var_name")
|
||||
|
||||
if varName != "" {
|
||||
// Get single variable
|
||||
variable, err := h.service.GetVariable(varName)
|
||||
// Check if request has body content
|
||||
if c.Request.ContentLength == 0 || c.Request.ContentLength == -1 {
|
||||
// List all variables
|
||||
variables, err := h.service.GetAllVariables()
|
||||
if err != nil {
|
||||
errorResponse(c, err.Error(), 400)
|
||||
errorResponse(c, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
success(c, variable, "")
|
||||
success(c, variables, "")
|
||||
return
|
||||
}
|
||||
|
||||
// List all variables
|
||||
variables, err := h.service.GetAllVariables()
|
||||
// Get single variable by var_name from request body
|
||||
var req struct {
|
||||
VarName string `json:"var_name"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
errorResponse(c, "Invalid request body", 400)
|
||||
return
|
||||
}
|
||||
|
||||
if req.VarName == "" {
|
||||
errorResponse(c, "Var name is required", 400)
|
||||
return
|
||||
}
|
||||
|
||||
variable, err := h.service.GetVariable(req.VarName)
|
||||
if err != nil {
|
||||
// Check if it's an AdminException
|
||||
if adminErr, ok := err.(*AdminException); ok {
|
||||
errorResponse(c, adminErr.Message, 400)
|
||||
return
|
||||
}
|
||||
errorResponse(c, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
success(c, variables, "")
|
||||
success(c, variable, "")
|
||||
}
|
||||
|
||||
// SetVariableHTTPRequest set variable request
|
||||
@@ -798,15 +816,31 @@ type SetVariableHTTPRequest struct {
|
||||
}
|
||||
|
||||
// SetVariable handle set variable
|
||||
// Python logic: update or create a system setting with the given name and value
|
||||
func (h *Handler) SetVariable(c *gin.Context) {
|
||||
var req SetVariableHTTPRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
errorResponse(c, "Var name and value are required", 400)
|
||||
errorResponse(c, "Var name is required", 400)
|
||||
return
|
||||
}
|
||||
|
||||
if req.VarName == "" {
|
||||
errorResponse(c, "Var name is required", 400)
|
||||
return
|
||||
}
|
||||
|
||||
if req.VarValue == "" {
|
||||
errorResponse(c, "Var value is required", 400)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.SetVariable(req.VarName, req.VarValue); err != nil {
|
||||
errorResponse(c, err.Error(), 400)
|
||||
// Check if it's an AdminException
|
||||
if adminErr, ok := err.(*AdminException); ok {
|
||||
errorResponse(c, adminErr.Message, 400)
|
||||
return
|
||||
}
|
||||
errorResponse(c, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -814,10 +848,16 @@ func (h *Handler) SetVariable(c *gin.Context) {
|
||||
}
|
||||
|
||||
// GetConfigs handle get configs
|
||||
// Python logic: return all service configurations
|
||||
func (h *Handler) GetConfigs(c *gin.Context) {
|
||||
configs, err := h.service.GetAllConfigs()
|
||||
if err != nil {
|
||||
errorResponse(c, err.Error(), 400)
|
||||
// Check if it's an AdminException
|
||||
if adminErr, ok := err.(*AdminException); ok {
|
||||
errorResponse(c, adminErr.Message, 400)
|
||||
return
|
||||
}
|
||||
errorResponse(c, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -825,10 +865,16 @@ func (h *Handler) GetConfigs(c *gin.Context) {
|
||||
}
|
||||
|
||||
// GetEnvironments handle get environments
|
||||
// Python logic: return important environment variables
|
||||
func (h *Handler) GetEnvironments(c *gin.Context) {
|
||||
environments, err := h.service.GetAllEnvironments()
|
||||
if err != nil {
|
||||
errorResponse(c, err.Error(), 400)
|
||||
// Check if it's an AdminException
|
||||
if adminErr, ok := err.(*AdminException); ok {
|
||||
errorResponse(c, adminErr.Message, 400)
|
||||
return
|
||||
}
|
||||
errorResponse(c, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -46,15 +46,17 @@ var (
|
||||
|
||||
// Service admin service layer
|
||||
type Service struct {
|
||||
userDAO *dao.UserDAO
|
||||
licenseDAO *dao.LicenseDAO
|
||||
userDAO *dao.UserDAO
|
||||
licenseDAO *dao.LicenseDAO
|
||||
systemSettingsDAO *dao.SystemSettingsDAO
|
||||
}
|
||||
|
||||
// NewService create admin service
|
||||
func NewService() *Service {
|
||||
return &Service{
|
||||
userDAO: dao.NewUserDAO(),
|
||||
licenseDAO: dao.NewLicenseDAO(),
|
||||
userDAO: dao.NewUserDAO(),
|
||||
licenseDAO: dao.NewLicenseDAO(),
|
||||
systemSettingsDAO: dao.NewSystemSettingsDAO(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,43 +890,172 @@ func (s *Service) RestartService(serviceID string) (map[string]interface{}, erro
|
||||
|
||||
// Variable/Settings methods
|
||||
|
||||
// GetVariable get variable
|
||||
func (s *Service) GetVariable(varName string) (map[string]interface{}, error) {
|
||||
// TODO: Implement with settings manager
|
||||
return map[string]interface{}{
|
||||
"var_name": varName,
|
||||
"var_value": "",
|
||||
}, nil
|
||||
// AdminException admin exception error
|
||||
type AdminException struct {
|
||||
Message string
|
||||
Code int
|
||||
}
|
||||
|
||||
// Error implement error interface
|
||||
func (e *AdminException) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// NewAdminException create admin exception
|
||||
func NewAdminException(message string) *AdminException {
|
||||
return &AdminException{
|
||||
Message: message,
|
||||
Code: 400,
|
||||
}
|
||||
}
|
||||
|
||||
// GetVariable get variable by name
|
||||
// Returns the system setting with the given name
|
||||
// Returns AdminException if the setting is not found
|
||||
func (s *Service) GetVariable(varName string) ([]map[string]interface{}, error) {
|
||||
settings, err := s.systemSettingsDAO.GetByName(varName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(settings) == 0 {
|
||||
return nil, NewAdminException("Can't get setting: " + varName)
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, 0, len(settings))
|
||||
for _, setting := range settings {
|
||||
result = append(result, map[string]interface{}{
|
||||
"name": setting.Name,
|
||||
"source": setting.Source,
|
||||
"data_type": setting.DataType,
|
||||
"value": setting.Value,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetAllVariables get all variables
|
||||
// Returns all system settings from database
|
||||
func (s *Service) GetAllVariables() ([]map[string]interface{}, error) {
|
||||
// TODO: Implement with settings manager
|
||||
return []map[string]interface{}{}, nil
|
||||
settings, err := s.systemSettingsDAO.GetAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]map[string]interface{}, 0, len(settings))
|
||||
for _, setting := range settings {
|
||||
result = append(result, map[string]interface{}{
|
||||
"name": setting.Name,
|
||||
"source": setting.Source,
|
||||
"data_type": setting.DataType,
|
||||
"value": setting.Value,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SetVariable set variable
|
||||
// Creates or updates a system setting
|
||||
// If the setting exists, updates it; otherwise creates a new one
|
||||
func (s *Service) SetVariable(varName, varValue string) error {
|
||||
// TODO: Implement with settings manager
|
||||
_ = varName
|
||||
_ = varValue
|
||||
return nil
|
||||
settings, err := s.systemSettingsDAO.GetByName(varName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(settings) == 1 {
|
||||
setting := &settings[0]
|
||||
setting.Value = varValue
|
||||
return s.systemSettingsDAO.UpdateByName(varName, setting)
|
||||
} else if len(settings) > 1 {
|
||||
return NewAdminException("Can't update more than 1 setting: " + varName)
|
||||
}
|
||||
|
||||
// Create new setting if it doesn't exist
|
||||
// Determine data_type based on name and value
|
||||
dataType := "string"
|
||||
if len(varName) >= 7 && varName[:7] == "sandbox" {
|
||||
dataType = "json"
|
||||
} else if len(varName) >= 9 && varName[len(varName)-9:] == ".enabled" {
|
||||
dataType = "boolean"
|
||||
}
|
||||
|
||||
newSetting := &model.SystemSettings{
|
||||
Name: varName,
|
||||
Value: varValue,
|
||||
Source: "admin",
|
||||
DataType: dataType,
|
||||
}
|
||||
return s.systemSettingsDAO.Create(newSetting)
|
||||
}
|
||||
|
||||
// Config methods
|
||||
|
||||
// GetAllConfigs get all configs
|
||||
// Returns all service configurations from the config file
|
||||
func (s *Service) GetAllConfigs() ([]map[string]interface{}, error) {
|
||||
// TODO: Implement with config manager
|
||||
return []map[string]interface{}{}, nil
|
||||
result := server.GetAllConfigs()
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Environment methods
|
||||
|
||||
// GetAllEnvironments get all environments
|
||||
// Returns important environment variables
|
||||
func (s *Service) GetAllEnvironments() ([]map[string]interface{}, error) {
|
||||
// TODO: Implement with environment manager
|
||||
return []map[string]interface{}{}, nil
|
||||
result := make([]map[string]interface{}, 0)
|
||||
|
||||
// DOC_ENGINE
|
||||
docEngine := os.Getenv("DOC_ENGINE")
|
||||
if docEngine == "" {
|
||||
docEngine = "elasticsearch"
|
||||
}
|
||||
result = append(result, map[string]interface{}{
|
||||
"env": "DOC_ENGINE",
|
||||
"value": docEngine,
|
||||
})
|
||||
|
||||
// DEFAULT_SUPERUSER_EMAIL
|
||||
defaultSuperuserEmail := os.Getenv("DEFAULT_SUPERUSER_EMAIL")
|
||||
if defaultSuperuserEmail == "" {
|
||||
defaultSuperuserEmail = "admin@ragflow.io"
|
||||
}
|
||||
result = append(result, map[string]interface{}{
|
||||
"env": "DEFAULT_SUPERUSER_EMAIL",
|
||||
"value": defaultSuperuserEmail,
|
||||
})
|
||||
|
||||
// DB_TYPE
|
||||
dbType := os.Getenv("DB_TYPE")
|
||||
if dbType == "" {
|
||||
dbType = "mysql"
|
||||
}
|
||||
result = append(result, map[string]interface{}{
|
||||
"env": "DB_TYPE",
|
||||
"value": dbType,
|
||||
})
|
||||
|
||||
// DEVICE
|
||||
device := os.Getenv("DEVICE")
|
||||
if device == "" {
|
||||
device = "cpu"
|
||||
}
|
||||
result = append(result, map[string]interface{}{
|
||||
"env": "DEVICE",
|
||||
"value": device,
|
||||
})
|
||||
|
||||
// STORAGE_IMPL
|
||||
storageImpl := os.Getenv("STORAGE_IMPL")
|
||||
if storageImpl == "" {
|
||||
storageImpl = "MINIO"
|
||||
}
|
||||
result = append(result, map[string]interface{}{
|
||||
"env": "STORAGE_IMPL",
|
||||
"value": storageImpl,
|
||||
})
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Version methods
|
||||
|
||||
188
internal/dao/system_settings.go
Normal file
188
internal/dao/system_settings.go
Normal file
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// 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 dao
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"ragflow/internal/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// SystemSettingsDAO system settings data access object
|
||||
type SystemSettingsDAO struct{}
|
||||
|
||||
// NewSystemSettingsDAO create system settings DAO instance
|
||||
func NewSystemSettingsDAO() *SystemSettingsDAO {
|
||||
return &SystemSettingsDAO{}
|
||||
}
|
||||
|
||||
// GetAll get all system settings
|
||||
// Returns all system settings records from database
|
||||
func (d *SystemSettingsDAO) GetAll() ([]model.SystemSettings, error) {
|
||||
var settings []model.SystemSettings
|
||||
err := DB.Find(&settings).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// GetByName get system settings by name
|
||||
// Returns settings records that match the given name
|
||||
func (d *SystemSettingsDAO) GetByName(name string) ([]model.SystemSettings, error) {
|
||||
var settings []model.SystemSettings
|
||||
err := DB.Where("name = ?", name).Find(&settings).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// UpdateByName update system settings by name
|
||||
// Updates the setting with the given name using the provided data
|
||||
func (d *SystemSettingsDAO) UpdateByName(name string, setting *model.SystemSettings) error {
|
||||
now := time.Now().Unix()
|
||||
nowDate := time.Now()
|
||||
|
||||
return DB.Model(&model.SystemSettings{}).
|
||||
Where("name = ?", name).
|
||||
Updates(map[string]interface{}{
|
||||
"value": setting.Value,
|
||||
"source": setting.Source,
|
||||
"data_type": setting.DataType,
|
||||
"update_time": now,
|
||||
"update_date": nowDate,
|
||||
}).Error
|
||||
}
|
||||
|
||||
// Create create a new system setting
|
||||
// Inserts a new system setting record into database
|
||||
func (d *SystemSettingsDAO) Create(setting *model.SystemSettings) error {
|
||||
now := time.Now().Unix()
|
||||
nowDate := time.Now()
|
||||
|
||||
setting.CreateTime = &now
|
||||
setting.CreateDate = &nowDate
|
||||
setting.UpdateTime = &now
|
||||
setting.UpdateDate = &nowDate
|
||||
|
||||
return DB.Create(setting).Error
|
||||
}
|
||||
|
||||
// SaveOrCreate update existing setting or create new one
|
||||
// If setting exists, updates it; otherwise creates a new record
|
||||
func (d *SystemSettingsDAO) SaveOrCreate(name string, value string, source string, dataType string) error {
|
||||
settings, err := d.GetByName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(settings) == 1 {
|
||||
setting := &settings[0]
|
||||
setting.Value = value
|
||||
return d.UpdateByName(name, setting)
|
||||
} else if len(settings) > 1 {
|
||||
return errors.New("can't update more than 1 setting: " + name)
|
||||
}
|
||||
|
||||
newSetting := &model.SystemSettings{
|
||||
Name: name,
|
||||
Value: value,
|
||||
Source: source,
|
||||
DataType: dataType,
|
||||
}
|
||||
return d.Create(newSetting)
|
||||
}
|
||||
|
||||
// Count get total count of system settings
|
||||
func (d *SystemSettingsDAO) Count() (int64, error) {
|
||||
var count int64
|
||||
err := DB.Model(&model.SystemSettings{}).Count(&count).Error
|
||||
return count, err
|
||||
}
|
||||
|
||||
// DeleteByName delete system setting by name
|
||||
func (d *SystemSettingsDAO) DeleteByName(name string) error {
|
||||
return DB.Where("name = ?", name).Delete(&model.SystemSettings{}).Error
|
||||
}
|
||||
|
||||
// Exists check if setting exists by name
|
||||
func (d *SystemSettingsDAO) Exists(name string) (bool, error) {
|
||||
var count int64
|
||||
err := DB.Model(&model.SystemSettings{}).Where("name = ?", name).Count(&count).Error
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// GetBySource get system settings by source
|
||||
func (d *SystemSettingsDAO) GetBySource(source string) ([]model.SystemSettings, error) {
|
||||
var settings []model.SystemSettings
|
||||
err := DB.Where("source = ?", source).Find(&settings).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// GetByDataType get system settings by data type
|
||||
func (d *SystemSettingsDAO) GetByDataType(dataType string) ([]model.SystemSettings, error) {
|
||||
var settings []model.SystemSettings
|
||||
err := DB.Where("data_type = ?", dataType).Find(&settings).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// Transaction execute operations in a transaction
|
||||
func (d *SystemSettingsDAO) Transaction(fn func(tx *gorm.DB) error) error {
|
||||
return DB.Transaction(fn)
|
||||
}
|
||||
|
||||
// CreateWithTx create setting within transaction
|
||||
func (d *SystemSettingsDAO) CreateWithTx(tx *gorm.DB, setting *model.SystemSettings) error {
|
||||
now := time.Now().Unix()
|
||||
nowDate := time.Now()
|
||||
|
||||
setting.CreateTime = &now
|
||||
setting.CreateDate = &nowDate
|
||||
setting.UpdateTime = &now
|
||||
setting.UpdateDate = &nowDate
|
||||
|
||||
return tx.Create(setting).Error
|
||||
}
|
||||
|
||||
// UpdateByNameWithTx update setting within transaction
|
||||
func (d *SystemSettingsDAO) UpdateByNameWithTx(tx *gorm.DB, name string, setting *model.SystemSettings) error {
|
||||
now := time.Now().Unix()
|
||||
nowDate := time.Now()
|
||||
|
||||
return tx.Model(&model.SystemSettings{}).
|
||||
Where("name = ?", name).
|
||||
Updates(map[string]interface{}{
|
||||
"value": setting.Value,
|
||||
"source": setting.Source,
|
||||
"data_type": setting.DataType,
|
||||
"update_time": now,
|
||||
"update_date": nowDate,
|
||||
}).Error
|
||||
}
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// SystemSettings system settings model
|
||||
type SystemSettings struct {
|
||||
Name string `gorm:"column:name;primaryKey;size:128" json:"name"`
|
||||
Source string `gorm:"column:source;size:32;not null" json:"source"`
|
||||
DataType string `gorm:"column:data_type;size:32;not null" json:"data_type"`
|
||||
Value string `gorm:"column:value;type:longtext;not null" json:"value"`
|
||||
Name string `gorm:"column:name;primaryKey;size:128" json:"name"`
|
||||
Source string `gorm:"column:source;size:32;not null" json:"source"`
|
||||
DataType string `gorm:"column:data_type;size:32;not null" json:"data_type"`
|
||||
Value string `gorm:"column:value;type:longtext;not null" json:"value"`
|
||||
CreateTime *int64 `gorm:"column:create_time" json:"create_time"`
|
||||
CreateDate *time.Time `gorm:"column:create_date" json:"create_date"`
|
||||
UpdateTime *int64 `gorm:"column:update_time" json:"update_time"`
|
||||
UpdateDate *time.Time `gorm:"column:update_date" json:"update_date"`
|
||||
}
|
||||
|
||||
// TableName specify table name
|
||||
|
||||
Reference in New Issue
Block a user