|
|
|
|
|
|
|
|
|
package config |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"html/template" |
|
"os" |
|
"path/filepath" |
|
"reflect" |
|
"strconv" |
|
"strings" |
|
"sync" |
|
"sync/atomic" |
|
"time" |
|
|
|
"github.com/GoAdminGroup/go-admin/modules/logger" |
|
"github.com/GoAdminGroup/go-admin/modules/utils" |
|
"github.com/GoAdminGroup/go-admin/plugins/admin/modules/form" |
|
"gopkg.in/ini.v1" |
|
"gopkg.in/yaml.v2" |
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type Database struct { |
|
Host string `json:"host,omitempty" yaml:"host,omitempty" ini:"host,omitempty"` |
|
Port string `json:"port,omitempty" yaml:"port,omitempty" ini:"port,omitempty"` |
|
User string `json:"user,omitempty" yaml:"user,omitempty" ini:"user,omitempty"` |
|
Pwd string `json:"pwd,omitempty" yaml:"pwd,omitempty" ini:"pwd,omitempty"` |
|
Name string `json:"name,omitempty" yaml:"name,omitempty" ini:"name,omitempty"` |
|
Driver string `json:"driver,omitempty" yaml:"driver,omitempty" ini:"driver,omitempty"` |
|
DriverMode string `json:"driver_mode,omitempty" yaml:"driver_mode,omitempty" ini:"driver_mode,omitempty"` |
|
File string `json:"file,omitempty" yaml:"file,omitempty" ini:"file,omitempty"` |
|
Dsn string `json:"dsn,omitempty" yaml:"dsn,omitempty" ini:"dsn,omitempty"` |
|
|
|
MaxIdleConns int `json:"max_idle_con,omitempty" yaml:"max_idle_con,omitempty" ini:"max_idle_con,omitempty"` |
|
MaxOpenConns int `json:"max_open_con,omitempty" yaml:"max_open_con,omitempty" ini:"max_open_con,omitempty"` |
|
ConnMaxLifetime time.Duration `json:"conn_max_life_time,omitempty" yaml:"conn_max_life_time,omitempty" ini:"conn_max_life_time,omitempty"` |
|
ConnMaxIdleTime time.Duration `json:"conn_max_idle_time,omitempty" yaml:"conn_max_idle_time,omitempty" ini:"conn_max_idle_time,omitempty"` |
|
|
|
Params map[string]string `json:"params,omitempty" yaml:"params,omitempty" ini:"params,omitempty"` |
|
} |
|
|
|
func (d Database) GetDSN() string { |
|
if d.Dsn != "" { |
|
return d.Dsn |
|
} |
|
|
|
if d.Driver == DriverMysql { |
|
return d.User + ":" + d.Pwd + "@tcp(" + d.Host + ":" + d.Port + ")/" + |
|
d.Name + d.ParamStr() |
|
} |
|
if d.Driver == DriverPostgresql { |
|
return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s"+d.ParamStr(), |
|
d.Host, d.Port, d.User, d.Pwd, d.Name) |
|
} |
|
if d.Driver == DriverMssql { |
|
return fmt.Sprintf("user id=%s;password=%s;server=%s;port=%s;database=%s;"+d.ParamStr(), |
|
d.User, d.Pwd, d.Host, d.Port, d.Name) |
|
} |
|
if d.Driver == DriverSqlite { |
|
return d.File + d.ParamStr() |
|
} |
|
if d.Driver == DriverOceanBase { |
|
return d.User + ":" + d.Pwd + "@tcp(" + d.Host + ":" + d.Port + ")/" + |
|
d.Name + d.ParamStr() |
|
} |
|
return "" |
|
} |
|
|
|
func (d Database) ParamStr() string { |
|
p := "" |
|
if d.Params == nil { |
|
d.Params = make(map[string]string) |
|
} |
|
if d.Driver == DriverMysql || d.Driver == DriverSqlite || d.Driver == DriverOceanBase { |
|
if d.Driver == DriverMysql || d.Driver == DriverOceanBase { |
|
if _, ok := d.Params["charset"]; !ok { |
|
d.Params["charset"] = "utf8mb4" |
|
} |
|
} |
|
if len(d.Params) > 0 { |
|
p = "?" |
|
for k, v := range d.Params { |
|
p += k + "=" + v + "&" |
|
} |
|
p = p[:len(p)-1] |
|
} |
|
} |
|
if d.Driver == DriverMssql { |
|
if _, ok := d.Params["encrypt"]; !ok { |
|
d.Params["encrypt"] = "disable" |
|
} |
|
for k, v := range d.Params { |
|
p += k + "=" + v + ";" |
|
} |
|
p = p[:len(p)-1] |
|
} |
|
if d.Driver == DriverPostgresql { |
|
if _, ok := d.Params["sslmode"]; !ok { |
|
d.Params["sslmode"] = "disable" |
|
} |
|
p = " " |
|
for k, v := range d.Params { |
|
p += k + "=" + v + " " |
|
} |
|
p = p[:len(p)-1] |
|
} |
|
return p |
|
} |
|
|
|
|
|
type DatabaseList map[string]Database |
|
|
|
|
|
func (d DatabaseList) GetDefault() Database { |
|
return d["default"] |
|
} |
|
|
|
|
|
func (d DatabaseList) Add(key string, db Database) { |
|
d[key] = db |
|
} |
|
|
|
|
|
func (d DatabaseList) GroupByDriver() map[string]DatabaseList { |
|
drivers := make(map[string]DatabaseList) |
|
for key, item := range d { |
|
if driverList, ok := drivers[item.Driver]; ok { |
|
driverList.Add(key, item) |
|
} else { |
|
drivers[item.Driver] = make(DatabaseList) |
|
drivers[item.Driver].Add(key, item) |
|
} |
|
} |
|
return drivers |
|
} |
|
|
|
func (d DatabaseList) JSON() string { |
|
return utils.JSON(d) |
|
} |
|
|
|
func (d DatabaseList) Copy() DatabaseList { |
|
var c = make(DatabaseList) |
|
for k, v := range d { |
|
c[k] = v |
|
} |
|
return c |
|
} |
|
|
|
func (d DatabaseList) Connections() []string { |
|
conns := make([]string, len(d)) |
|
count := 0 |
|
for key := range d { |
|
conns[count] = key |
|
count++ |
|
} |
|
return conns |
|
} |
|
|
|
func GetDatabaseListFromJSON(m string) DatabaseList { |
|
var d = make(DatabaseList) |
|
if m == "" { |
|
panic("wrong config") |
|
} |
|
_ = json.Unmarshal([]byte(m), &d) |
|
return d |
|
} |
|
|
|
const ( |
|
|
|
EnvTest = "test" |
|
|
|
EnvLocal = "local" |
|
|
|
EnvProd = "prod" |
|
|
|
|
|
DriverMysql = "mysql" |
|
|
|
DriverSqlite = "sqlite" |
|
|
|
DriverPostgresql = "postgresql" |
|
|
|
DriverMssql = "mssql" |
|
|
|
DriverOceanBase = "oceanbase" |
|
) |
|
|
|
|
|
|
|
type Store struct { |
|
Path string `json:"path,omitempty" yaml:"path,omitempty" ini:"path,omitempty"` |
|
Prefix string `json:"prefix,omitempty" yaml:"prefix,omitempty" ini:"prefix,omitempty"` |
|
} |
|
|
|
func (s Store) URL(suffix string) string { |
|
if len(suffix) > 4 && suffix[:4] == "http" { |
|
return suffix |
|
} |
|
if s.Prefix == "" { |
|
if suffix[0] == '/' { |
|
return suffix |
|
} |
|
return "/" + suffix |
|
} |
|
if s.Prefix[0] == '/' { |
|
if suffix[0] == '/' { |
|
return s.Prefix + suffix |
|
} |
|
return s.Prefix + "/" + suffix |
|
} |
|
if suffix[0] == '/' { |
|
if len(s.Prefix) > 4 && s.Prefix[:4] == "http" { |
|
return s.Prefix + suffix |
|
} |
|
return "/" + s.Prefix + suffix |
|
} |
|
if len(s.Prefix) > 4 && s.Prefix[:4] == "http" { |
|
return s.Prefix + "/" + suffix |
|
} |
|
return "/" + s.Prefix + "/" + suffix |
|
} |
|
|
|
func (s Store) JSON() string { |
|
if s.Path == "" && s.Prefix == "" { |
|
return "" |
|
} |
|
return utils.JSON(s) |
|
} |
|
|
|
func GetStoreFromJSON(m string) Store { |
|
var s Store |
|
if m == "" { |
|
return s |
|
} |
|
_ = json.Unmarshal([]byte(m), &s) |
|
return s |
|
} |
|
|
|
|
|
|
|
type Config struct { |
|
|
|
|
|
|
|
Databases DatabaseList `json:"database,omitempty" yaml:"database,omitempty" ini:"database,omitempty"` |
|
|
|
|
|
AppID string `json:"app_id,omitempty" yaml:"app_id,omitempty" ini:"app_id,omitempty"` |
|
|
|
|
|
|
|
Domain string `json:"domain,omitempty" yaml:"domain,omitempty" ini:"domain,omitempty"` |
|
|
|
|
|
|
|
Language string `json:"language,omitempty" yaml:"language,omitempty" ini:"language,omitempty"` |
|
|
|
|
|
UrlPrefix string `json:"prefix,omitempty" yaml:"prefix,omitempty" ini:"prefix,omitempty"` |
|
|
|
|
|
Theme string `json:"theme,omitempty" yaml:"theme,omitempty" ini:"theme,omitempty"` |
|
|
|
|
|
Store Store `json:"store,omitempty" yaml:"store,omitempty" ini:"store,omitempty"` |
|
|
|
|
|
Title string `json:"title,omitempty" yaml:"title,omitempty" ini:"title,omitempty"` |
|
|
|
|
|
Logo template.HTML `json:"logo,omitempty" yaml:"logo,omitempty" ini:"logo,omitempty"` |
|
|
|
|
|
MiniLogo template.HTML `json:"mini_logo,omitempty" yaml:"mini_logo,omitempty" ini:"mini_logo,omitempty"` |
|
|
|
|
|
IndexUrl string `json:"index,omitempty" yaml:"index,omitempty" ini:"index,omitempty"` |
|
|
|
|
|
LoginUrl string `json:"login_url,omitempty" yaml:"login_url,omitempty" ini:"login_url,omitempty"` |
|
|
|
|
|
Debug bool `json:"debug,omitempty" yaml:"debug,omitempty" ini:"debug,omitempty"` |
|
|
|
|
|
Env string `json:"env,omitempty" yaml:"env,omitempty" ini:"env,omitempty"` |
|
|
|
|
|
InfoLogPath string `json:"info_log,omitempty" yaml:"info_log,omitempty" ini:"info_log,omitempty"` |
|
|
|
|
|
ErrorLogPath string `json:"error_log,omitempty" yaml:"error_log,omitempty" ini:"error_log,omitempty"` |
|
|
|
|
|
AccessLogPath string `json:"access_log,omitempty" yaml:"access_log,omitempty" ini:"access_log,omitempty"` |
|
|
|
|
|
AccessAssetsLogOff bool `json:"access_assets_log_off,omitempty" yaml:"access_assets_log_off,omitempty" ini:"access_assets_log_off,omitempty"` |
|
|
|
|
|
SqlLog bool `json:"sql_log,omitempty" yaml:"sql_log,omitempty" ini:"sql_log,omitempty"` |
|
|
|
AccessLogOff bool `json:"access_log_off,omitempty" yaml:"access_log_off,omitempty" ini:"access_log_off,omitempty"` |
|
InfoLogOff bool `json:"info_log_off,omitempty" yaml:"info_log_off,omitempty" ini:"info_log_off,omitempty"` |
|
ErrorLogOff bool `json:"error_log_off,omitempty" yaml:"error_log_off,omitempty" ini:"error_log_off,omitempty"` |
|
|
|
Logger Logger `json:"logger,omitempty" yaml:"logger,omitempty" ini:"logger,omitempty"` |
|
|
|
|
|
ColorScheme string `json:"color_scheme,omitempty" yaml:"color_scheme,omitempty" ini:"color_scheme,omitempty"` |
|
|
|
|
|
SessionLifeTime int `json:"session_life_time,omitempty" yaml:"session_life_time,omitempty" ini:"session_life_time,omitempty"` |
|
|
|
|
|
AssetUrl string `json:"asset_url,omitempty" yaml:"asset_url,omitempty" ini:"asset_url,omitempty"` |
|
|
|
|
|
FileUploadEngine FileUploadEngine `json:"file_upload_engine,omitempty" yaml:"file_upload_engine,omitempty" ini:"file_upload_engine,omitempty"` |
|
|
|
|
|
CustomHeadHtml template.HTML `json:"custom_head_html,omitempty" yaml:"custom_head_html,omitempty" ini:"custom_head_html,omitempty"` |
|
|
|
|
|
CustomFootHtml template.HTML `json:"custom_foot_html,omitempty" yaml:"custom_foot_html,omitempty" ini:"custom_foot_html,omitempty"` |
|
|
|
|
|
FooterInfo template.HTML `json:"footer_info,omitempty" yaml:"footer_info,omitempty" ini:"footer_info,omitempty"` |
|
|
|
|
|
LoginTitle string `json:"login_title,omitempty" yaml:"login_title,omitempty" ini:"login_title,omitempty"` |
|
|
|
|
|
LoginLogo template.HTML `json:"login_logo,omitempty" yaml:"login_logo,omitempty" ini:"login_logo,omitempty"` |
|
|
|
|
|
AuthUserTable string `json:"auth_user_table,omitempty" yaml:"auth_user_table,omitempty" ini:"auth_user_table,omitempty"` |
|
|
|
|
|
Extra ExtraInfo `json:"extra,omitempty" yaml:"extra,omitempty" ini:"extra,omitempty"` |
|
|
|
|
|
Animation PageAnimation `json:"animation,omitempty" yaml:"animation,omitempty" ini:"animation,omitempty"` |
|
|
|
|
|
NoLimitLoginIP bool `json:"no_limit_login_ip,omitempty" yaml:"no_limit_login_ip,omitempty" ini:"no_limit_login_ip,omitempty"` |
|
|
|
|
|
SiteOff bool `json:"site_off,omitempty" yaml:"site_off,omitempty" ini:"site_off,omitempty"` |
|
|
|
|
|
HideConfigCenterEntrance bool `json:"hide_config_center_entrance,omitempty" yaml:"hide_config_center_entrance,omitempty" ini:"hide_config_center_entrance,omitempty"` |
|
|
|
|
|
ProhibitConfigModification bool `json:"prohibit_config_modification,omitempty" yaml:"prohibit_config_modification,omitempty" ini:"prohibit_config_modification,omitempty"` |
|
|
|
|
|
HideAppInfoEntrance bool `json:"hide_app_info_entrance,omitempty" yaml:"hide_app_info_entrance,omitempty" ini:"hide_app_info_entrance,omitempty"` |
|
|
|
|
|
HideToolEntrance bool `json:"hide_tool_entrance,omitempty" yaml:"hide_tool_entrance,omitempty" ini:"hide_tool_entrance,omitempty"` |
|
|
|
HidePluginEntrance bool `json:"hide_plugin_entrance,omitempty" yaml:"hide_plugin_entrance,omitempty" ini:"hide_plugin_entrance,omitempty"` |
|
|
|
Custom404HTML template.HTML `json:"custom_404_html,omitempty" yaml:"custom_404_html,omitempty" ini:"custom_404_html,omitempty"` |
|
|
|
Custom403HTML template.HTML `json:"custom_403_html,omitempty" yaml:"custom_403_html,omitempty" ini:"custom_403_html,omitempty"` |
|
|
|
Custom500HTML template.HTML `json:"custom_500_html,omitempty" yaml:"custom_500_html,omitempty" ini:"custom_500_html,omitempty"` |
|
|
|
|
|
UpdateProcessFn UpdateConfigProcessFn `json:"-" yaml:"-" ini:"-"` |
|
|
|
|
|
|
|
|
|
OpenAdminApi bool `json:"open_admin_api,omitempty" yaml:"open_admin_api,omitempty" ini:"open_admin_api,omitempty"` |
|
|
|
HideVisitorUserCenterEntrance bool `json:"hide_visitor_user_center_entrance,omitempty" yaml:"hide_visitor_user_center_entrance,omitempty" ini:"hide_visitor_user_center_entrance,omitempty"` |
|
|
|
ExcludeThemeComponents []string `json:"exclude_theme_components,omitempty" yaml:"exclude_theme_components,omitempty" ini:"exclude_theme_components,omitempty"` |
|
|
|
BootstrapFilePath string `json:"bootstrap_file_path,omitempty" yaml:"bootstrap_file_path,omitempty" ini:"bootstrap_file_path,omitempty"` |
|
|
|
GoModFilePath string `json:"go_mod_file_path,omitempty" yaml:"go_mod_file_path,omitempty" ini:"go_mod_file_path,omitempty"` |
|
|
|
AllowDelOperationLog bool `json:"allow_del_operation_log,omitempty" yaml:"allow_del_operation_log,omitempty" ini:"allow_del_operation_log,omitempty"` |
|
|
|
OperationLogOff bool `json:"operation_log_off,omitempty" yaml:"operation_log_off,omitempty" ini:"operation_log_off,omitempty"` |
|
|
|
AssetRootPath string `json:"asset_root_path,omitempty" yaml:"asset_root_path,omitempty" ini:"asset_root_path,omitempty"` |
|
|
|
URLFormat URLFormat `json:"url_format,omitempty" yaml:"url_format,omitempty" ini:"url_format,omitempty"` |
|
|
|
prefix string `json:"-" yaml:"-" ini:"-"` |
|
lock sync.RWMutex `json:"-" yaml:"-" ini:"-"` |
|
} |
|
|
|
type Logger struct { |
|
Encoder EncoderCfg `json:"encoder,omitempty" yaml:"encoder,omitempty" ini:"encoder,omitempty"` |
|
Rotate RotateCfg `json:"rotate,omitempty" yaml:"rotate,omitempty" ini:"rotate,omitempty"` |
|
Level int8 `json:"level,omitempty" yaml:"level,omitempty" ini:"level,omitempty"` |
|
} |
|
|
|
type EncoderCfg struct { |
|
TimeKey string `json:"time_key,omitempty" yaml:"time_key,omitempty" ini:"time_key,omitempty"` |
|
LevelKey string `json:"level_key,omitempty" yaml:"level_key,omitempty" ini:"level_key,omitempty"` |
|
NameKey string `json:"name_key,omitempty" yaml:"name_key,omitempty" ini:"name_key,omitempty"` |
|
CallerKey string `json:"caller_key,omitempty" yaml:"caller_key,omitempty" ini:"caller_key,omitempty"` |
|
MessageKey string `json:"message_key,omitempty" yaml:"message_key,omitempty" ini:"message_key,omitempty"` |
|
StacktraceKey string `json:"stacktrace_key,omitempty" yaml:"stacktrace_key,omitempty" ini:"stacktrace_key,omitempty"` |
|
Level string `json:"level,omitempty" yaml:"level,omitempty" ini:"level,omitempty"` |
|
Time string `json:"time,omitempty" yaml:"time,omitempty" ini:"time,omitempty"` |
|
Duration string `json:"duration,omitempty" yaml:"duration,omitempty" ini:"duration,omitempty"` |
|
Caller string `json:"caller,omitempty" yaml:"caller,omitempty" ini:"caller,omitempty"` |
|
Encoding string `json:"encoding,omitempty" yaml:"encoding,omitempty" ini:"encoding,omitempty"` |
|
} |
|
|
|
type RotateCfg struct { |
|
MaxSize int `json:"max_size,omitempty" yaml:"max_size,omitempty" ini:"max_size,omitempty"` |
|
MaxBackups int `json:"max_backups,omitempty" yaml:"max_backups,omitempty" ini:"max_backups,omitempty"` |
|
MaxAge int `json:"max_age,omitempty" yaml:"max_age,omitempty" ini:"max_age,omitempty"` |
|
Compress bool `json:"compress,omitempty" yaml:"compress,omitempty" ini:"compress,omitempty"` |
|
} |
|
|
|
type URLFormat struct { |
|
Info string `json:"info,omitempty" yaml:"info,omitempty" ini:"info,omitempty"` |
|
Detail string `json:"detail,omitempty" yaml:"detail,omitempty" ini:"detail,omitempty"` |
|
Create string `json:"create,omitempty" yaml:"create,omitempty" ini:"create,omitempty"` |
|
Delete string `json:"delete,omitempty" yaml:"delete,omitempty" ini:"delete,omitempty"` |
|
Export string `json:"export,omitempty" yaml:"export,omitempty" ini:"export,omitempty"` |
|
Edit string `json:"edit,omitempty" yaml:"edit,omitempty" ini:"edit,omitempty"` |
|
ShowEdit string `json:"show_edit,omitempty" yaml:"show_edit,omitempty" ini:"show_edit,omitempty"` |
|
ShowCreate string `json:"show_create,omitempty" yaml:"show_create,omitempty" ini:"show_create,omitempty"` |
|
Update string `json:"update,omitempty" yaml:"update,omitempty" ini:"update,omitempty"` |
|
} |
|
|
|
func (f URLFormat) SetDefault() URLFormat { |
|
f.Detail = utils.SetDefault(f.Detail, "", "/info/:__prefix/detail") |
|
f.ShowEdit = utils.SetDefault(f.ShowEdit, "", "/info/:__prefix/edit") |
|
f.ShowCreate = utils.SetDefault(f.ShowCreate, "", "/info/:__prefix/new") |
|
f.Edit = utils.SetDefault(f.Edit, "", "/edit/:__prefix") |
|
f.Create = utils.SetDefault(f.Create, "", "/new/:__prefix") |
|
f.Delete = utils.SetDefault(f.Delete, "", "/delete/:__prefix") |
|
f.Export = utils.SetDefault(f.Export, "", "/export/:__prefix") |
|
f.Info = utils.SetDefault(f.Info, "", "/info/:__prefix") |
|
f.Update = utils.SetDefault(f.Update, "", "/update/:__prefix") |
|
return f |
|
} |
|
|
|
type ExtraInfo map[string]interface{} |
|
|
|
type UpdateConfigProcessFn func(values form.Values) (form.Values, error) |
|
|
|
|
|
type PageAnimation struct { |
|
Type string `json:"type,omitempty" yaml:"type,omitempty" ini:"type,omitempty"` |
|
Duration float32 `json:"duration,omitempty" yaml:"duration,omitempty" ini:"duration,omitempty"` |
|
Delay float32 `json:"delay,omitempty" yaml:"delay,omitempty" ini:"delay,omitempty"` |
|
} |
|
|
|
func (p PageAnimation) JSON() string { |
|
if p.Type == "" { |
|
return "" |
|
} |
|
return utils.JSON(p) |
|
} |
|
|
|
|
|
type FileUploadEngine struct { |
|
Name string `json:"name,omitempty" yaml:"name,omitempty" ini:"name,omitempty"` |
|
Config map[string]interface{} `json:"config,omitempty" yaml:"config,omitempty" ini:"config,omitempty"` |
|
} |
|
|
|
func (f FileUploadEngine) JSON() string { |
|
if f.Name == "" { |
|
return "" |
|
} |
|
if len(f.Config) == 0 { |
|
f.Config = nil |
|
} |
|
return utils.JSON(f) |
|
} |
|
|
|
func GetFileUploadEngineFromJSON(m string) FileUploadEngine { |
|
var f FileUploadEngine |
|
if m == "" { |
|
return f |
|
} |
|
_ = json.Unmarshal([]byte(m), &f) |
|
return f |
|
} |
|
|
|
|
|
func (c *Config) GetIndexURL() string { |
|
index := c.Index() |
|
if index == "/" { |
|
return c.Prefix() |
|
} |
|
|
|
return c.Prefix() + index |
|
} |
|
|
|
|
|
func (c *Config) Url(suffix string) string { |
|
if c.prefix == "/" { |
|
return suffix |
|
} |
|
if suffix == "/" { |
|
return c.prefix |
|
} |
|
return c.prefix + suffix |
|
} |
|
|
|
|
|
func (c *Config) IsTestEnvironment() bool { |
|
return c.Env == EnvTest |
|
} |
|
|
|
|
|
func (c *Config) IsLocalEnvironment() bool { |
|
return c.Env == EnvLocal |
|
} |
|
|
|
|
|
func (c *Config) IsProductionEnvironment() bool { |
|
return c.Env == EnvProd |
|
} |
|
|
|
|
|
func (c *Config) IsNotProductionEnvironment() bool { |
|
return c.Env != EnvProd |
|
} |
|
|
|
func (c *Config) IsAllowConfigModification() bool { |
|
return !c.ProhibitConfigModification |
|
} |
|
|
|
|
|
func (c *Config) URLRemovePrefix(url string) string { |
|
if url == c.prefix { |
|
return "/" |
|
} |
|
if c.prefix == "/" { |
|
return url |
|
} |
|
return strings.Replace(url, c.prefix, "", 1) |
|
} |
|
|
|
|
|
func (c *Config) Index() string { |
|
if c.IndexUrl == "" { |
|
return "/" |
|
} |
|
if c.IndexUrl[0] != '/' { |
|
return "/" + c.IndexUrl |
|
} |
|
return c.IndexUrl |
|
} |
|
|
|
|
|
func (c *Config) Prefix() string { |
|
return c.prefix |
|
} |
|
|
|
|
|
func (c *Config) AssertPrefix() string { |
|
if c.prefix == "/" { |
|
return "" |
|
} |
|
return c.prefix |
|
} |
|
|
|
func (c *Config) AddUpdateProcessFn(fn UpdateConfigProcessFn) *Config { |
|
c.UpdateProcessFn = fn |
|
return c |
|
} |
|
|
|
|
|
func (c *Config) PrefixFixSlash() string { |
|
if c.UrlPrefix == "/" { |
|
return "" |
|
} |
|
if c.UrlPrefix != "" && c.UrlPrefix[0] != '/' { |
|
return "/" + c.UrlPrefix |
|
} |
|
return c.UrlPrefix |
|
} |
|
|
|
func (c *Config) Copy() *Config { |
|
|
|
c.lock.RLock() |
|
defer c.lock.RUnlock() |
|
|
|
var ( |
|
newCfg = new(Config) |
|
srcType = reflect.TypeOf(c).Elem() |
|
srcVal = reflect.ValueOf(c).Elem() |
|
distType = reflect.TypeOf(newCfg).Elem() |
|
distVal = reflect.ValueOf(newCfg).Elem() |
|
) |
|
|
|
for i := 0; i < distType.NumField(); i++ { |
|
v := distVal.Field(i) |
|
if distType.Field(i).Type.String() == "config.DatabaseList" { |
|
newCfg.Databases = c.Databases.Copy() |
|
} else if v.CanInterface() { |
|
for j := 0; j < srcType.NumField(); j++ { |
|
if distType.Field(i).Name == srcType.Field(j).Name { |
|
v.Set(reflect.ValueOf(srcVal.Field(i).Interface())) |
|
break |
|
} |
|
} |
|
} |
|
} |
|
|
|
newCfg.prefix = c.prefix |
|
|
|
return newCfg |
|
} |
|
|
|
func (c *Config) ToMap() map[string]string { |
|
c.lock.RLock() |
|
defer c.lock.RUnlock() |
|
|
|
var ( |
|
m = make(map[string]string) |
|
rType = reflect.TypeOf(c).Elem() |
|
rVal = reflect.ValueOf(c).Elem() |
|
) |
|
|
|
for i := 0; i < rType.NumField(); i++ { |
|
v := rVal.Field(i) |
|
if !v.CanInterface() { |
|
continue |
|
} |
|
t := rType.Field(i) |
|
keyName := t.Tag.Get("json") |
|
if keyName == "-" { |
|
continue |
|
} |
|
keyName = keyName[:len(keyName)-10] |
|
switch t.Type.Kind() { |
|
case reflect.Bool: |
|
m[keyName] = strconv.FormatBool(v.Bool()) |
|
case reflect.String: |
|
if keyName == "prefix" { |
|
keyName = "url_prefix" |
|
} else if keyName == "index" { |
|
keyName = "index_url" |
|
} else if keyName == "info_log" || keyName == "error_log" || keyName == "access_log" { |
|
keyName += "_path" |
|
} |
|
m[keyName] = v.String() |
|
case reflect.Int: |
|
m[keyName] = fmt.Sprintf("%d", v.Int()) |
|
case reflect.Struct: |
|
switch t.Type.String() { |
|
case "config.PageAnimation": |
|
m["animation_type"] = c.Animation.Type |
|
m["animation_duration"] = fmt.Sprintf("%.2f", c.Animation.Duration) |
|
m["animation_delay"] = fmt.Sprintf("%.2f", c.Animation.Delay) |
|
case "config.Logger": |
|
m["logger_rotate_max_size"] = strconv.Itoa(c.Logger.Rotate.MaxSize) |
|
m["logger_rotate_max_backups"] = strconv.Itoa(c.Logger.Rotate.MaxBackups) |
|
m["logger_rotate_max_age"] = strconv.Itoa(c.Logger.Rotate.MaxAge) |
|
m["logger_rotate_compress"] = strconv.FormatBool(c.Logger.Rotate.Compress) |
|
|
|
m["logger_encoder_time_key"] = c.Logger.Encoder.TimeKey |
|
m["logger_encoder_level_key"] = c.Logger.Encoder.LevelKey |
|
m["logger_encoder_name_key"] = c.Logger.Encoder.NameKey |
|
m["logger_encoder_caller_key"] = c.Logger.Encoder.CallerKey |
|
m["logger_encoder_message_key"] = c.Logger.Encoder.MessageKey |
|
m["logger_encoder_stacktrace_key"] = c.Logger.Encoder.StacktraceKey |
|
m["logger_encoder_level"] = c.Logger.Encoder.Level |
|
m["logger_encoder_time"] = c.Logger.Encoder.Time |
|
m["logger_encoder_duration"] = c.Logger.Encoder.Duration |
|
m["logger_encoder_caller"] = c.Logger.Encoder.Caller |
|
m["logger_encoder_encoding"] = c.Logger.Encoder.Encoding |
|
m["logger_level"] = strconv.Itoa(int(c.Logger.Level)) |
|
case "config.DatabaseList": |
|
m["databases"] = utils.JSON(v.Interface()) |
|
case "config.FileUploadEngine": |
|
m["file_upload_engine"] = c.FileUploadEngine.JSON() |
|
} |
|
case reflect.Map: |
|
if t.Type.String() == "config.ExtraInfo" { |
|
if len(c.Extra) == 0 { |
|
m["extra"] = "" |
|
} else { |
|
m["extra"] = utils.JSON(c.Extra) |
|
} |
|
} |
|
default: |
|
m[keyName] = utils.JSON(v.Interface()) |
|
} |
|
} |
|
return m |
|
} |
|
|
|
func (c *Config) Update(m map[string]string) error { |
|
c.lock.Lock() |
|
defer c.lock.Unlock() |
|
rType := reflect.TypeOf(c).Elem() |
|
rVal := reflect.ValueOf(c).Elem() |
|
for i := 0; i < rType.NumField(); i++ { |
|
v := rVal.Field(i) |
|
if !v.CanInterface() { |
|
continue |
|
} |
|
t := rType.Field(i) |
|
keyName := t.Tag.Get("json") |
|
if keyName == "-" { |
|
continue |
|
} |
|
keyName = keyName[:len(keyName)-10] |
|
switch t.Type.Kind() { |
|
case reflect.Bool: |
|
if mv, ok := m[keyName]; ok { |
|
v.Set(reflect.ValueOf(utils.ParseBool(mv))) |
|
} |
|
case reflect.String: |
|
if t.Type.String() == "template.HTML" { |
|
if mv, ok := m[keyName]; ok { |
|
v.Set(reflect.ValueOf(template.HTML(mv))) |
|
} |
|
continue |
|
} |
|
if keyName == "prefix" { |
|
keyName = "url_prefix" |
|
} else if keyName == "index" { |
|
keyName = "index_url" |
|
} else if keyName == "info_log" || keyName == "error_log" || keyName == "access_log" { |
|
keyName += "_path" |
|
} |
|
if mv, ok := m[keyName]; ok { |
|
if keyName == "info_log" || keyName == "error_log" || keyName == "access_log" { |
|
v.Set(reflect.ValueOf(utils.SetDefault(mv, v.String(), v.String()))) |
|
} else if keyName == "app_id" { |
|
v.Set(reflect.ValueOf(utils.SetDefault(mv, "", v.String()))) |
|
} else if keyName == "color_scheme" { |
|
if m["theme"] == "adminlte" { |
|
v.Set(reflect.ValueOf(mv)) |
|
} |
|
} else { |
|
v.Set(reflect.ValueOf(mv)) |
|
} |
|
} |
|
case reflect.Int: |
|
ses, _ := strconv.Atoi(m[keyName]) |
|
if ses != 0 { |
|
v.Set(reflect.ValueOf(ses)) |
|
} |
|
case reflect.Struct: |
|
switch t.Type.String() { |
|
case "config.PageAnimation": |
|
c.Animation.Type = m["animation_type"] |
|
c.Animation.Duration = utils.ParseFloat32(m["animation_duration"]) |
|
c.Animation.Delay = utils.ParseFloat32(m["animation_delay"]) |
|
case "config.Logger": |
|
c.Logger.Rotate.MaxSize, _ = strconv.Atoi(m["logger_rotate_max_size"]) |
|
c.Logger.Rotate.MaxBackups, _ = strconv.Atoi(m["logger_rotate_max_backups"]) |
|
c.Logger.Rotate.MaxAge, _ = strconv.Atoi(m["logger_rotate_max_age"]) |
|
c.Logger.Rotate.Compress = utils.ParseBool(m["logger_rotate_compress"]) |
|
|
|
c.Logger.Encoder.Encoding = m["logger_encoder_encoding"] |
|
loggerLevel, _ := strconv.Atoi(m["logger_level"]) |
|
c.Logger.Level = int8(loggerLevel) |
|
|
|
if c.Logger.Encoder.Encoding == "json" { |
|
c.Logger.Encoder.TimeKey = m["logger_encoder_time_key"] |
|
c.Logger.Encoder.LevelKey = m["logger_encoder_level_key"] |
|
c.Logger.Encoder.NameKey = m["logger_encoder_name_key"] |
|
c.Logger.Encoder.CallerKey = m["logger_encoder_caller_key"] |
|
c.Logger.Encoder.MessageKey = m["logger_encoder_message_key"] |
|
c.Logger.Encoder.StacktraceKey = m["logger_encoder_stacktrace_key"] |
|
c.Logger.Encoder.Level = m["logger_encoder_level"] |
|
c.Logger.Encoder.Time = m["logger_encoder_time"] |
|
c.Logger.Encoder.Duration = m["logger_encoder_duration"] |
|
c.Logger.Encoder.Caller = m["logger_encoder_caller"] |
|
} |
|
|
|
initLogger(c) |
|
case "config.FileUploadEngine": |
|
c.FileUploadEngine = GetFileUploadEngineFromJSON(m["file_upload_engine"]) |
|
} |
|
case reflect.Map: |
|
if t.Type.String() == "config.ExtraInfo" && m["extra"] != "" { |
|
var extra = make(map[string]interface{}) |
|
_ = json.Unmarshal([]byte(m["extra"]), &extra) |
|
c.Extra = extra |
|
} |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
|
|
func (c *Config) EraseSens() *Config { |
|
for key := range c.Databases { |
|
c.Databases[key] = Database{ |
|
Driver: c.Databases[key].Driver, |
|
} |
|
} |
|
return c |
|
} |
|
|
|
var ( |
|
_global = new(Config) |
|
count uint32 |
|
initializeLock sync.Mutex |
|
) |
|
|
|
|
|
func ReadFromJson(path string) Config { |
|
jsonByte, err := os.ReadFile(path) |
|
|
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
var cfg Config |
|
|
|
err = json.Unmarshal(jsonByte, &cfg) |
|
|
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
return cfg |
|
} |
|
|
|
|
|
func ReadFromYaml(path string) Config { |
|
jsonByte, err := os.ReadFile(path) |
|
|
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
var cfg Config |
|
|
|
err = yaml.Unmarshal(jsonByte, &cfg) |
|
|
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
return cfg |
|
} |
|
|
|
|
|
func ReadFromINI(path string) Config { |
|
iniCfg, err := ini.Load(path) |
|
|
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
var cfg = Config{ |
|
Databases: make(DatabaseList), |
|
} |
|
|
|
err = iniCfg.MapTo(&cfg) |
|
|
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
for _, child := range iniCfg.ChildSections("database") { |
|
var d Database |
|
err = child.MapTo(&d) |
|
if err != nil { |
|
panic(err) |
|
} |
|
cfg.Databases[child.Name()[9:]] = d |
|
} |
|
|
|
return cfg |
|
} |
|
|
|
func SetDefault(cfg *Config) *Config { |
|
cfg.Title = utils.SetDefault(cfg.Title, "", "GoAdmin") |
|
cfg.LoginTitle = utils.SetDefault(cfg.LoginTitle, "", "GoAdmin") |
|
cfg.Logo = template.HTML(utils.SetDefault(string(cfg.Logo), "", "<b>Go</b>Admin")) |
|
cfg.MiniLogo = template.HTML(utils.SetDefault(string(cfg.MiniLogo), "", "<b>G</b>A")) |
|
cfg.Theme = utils.SetDefault(cfg.Theme, "", "adminlte") |
|
cfg.IndexUrl = utils.SetDefault(cfg.IndexUrl, "", "/info/manager") |
|
cfg.LoginUrl = utils.SetDefault(cfg.LoginUrl, "", "/login") |
|
cfg.AuthUserTable = utils.SetDefault(cfg.AuthUserTable, "", "goadmin_users") |
|
cfg.ColorScheme = utils.SetDefault(cfg.ColorScheme, "", "skin-black") |
|
cfg.AssetRootPath = utils.SetDefault(cfg.AssetRootPath, "", "./public/") |
|
cfg.AssetRootPath = filepath.ToSlash(cfg.AssetRootPath) |
|
cfg.FileUploadEngine.Name = utils.SetDefault(cfg.FileUploadEngine.Name, "", "local") |
|
cfg.Env = utils.SetDefault(cfg.Env, "", EnvProd) |
|
if cfg.SessionLifeTime == 0 { |
|
|
|
cfg.SessionLifeTime = 7200 |
|
} |
|
cfg.AppID = utils.Uuid(12) |
|
if cfg.UrlPrefix == "" { |
|
cfg.prefix = "/" |
|
} else if cfg.UrlPrefix[0] != '/' { |
|
cfg.prefix = "/" + cfg.UrlPrefix |
|
} else { |
|
cfg.prefix = cfg.UrlPrefix |
|
} |
|
cfg.URLFormat = cfg.URLFormat.SetDefault() |
|
return cfg |
|
} |
|
|
|
|
|
func Initialize(cfg *Config) *Config { |
|
|
|
initializeLock.Lock() |
|
defer initializeLock.Unlock() |
|
|
|
if atomic.LoadUint32(&count) != 0 { |
|
panic("can not initialize config twice") |
|
} |
|
atomic.StoreUint32(&count, 1) |
|
|
|
initLogger(SetDefault(cfg)) |
|
|
|
_global = cfg |
|
|
|
return _global |
|
} |
|
|
|
func initLogger(cfg *Config) { |
|
logger.InitWithConfig(logger.Config{ |
|
InfoLogOff: cfg.InfoLogOff, |
|
ErrorLogOff: cfg.ErrorLogOff, |
|
AccessLogOff: cfg.AccessLogOff, |
|
SqlLogOpen: cfg.SqlLog, |
|
InfoLogPath: cfg.InfoLogPath, |
|
ErrorLogPath: cfg.ErrorLogPath, |
|
AccessLogPath: cfg.AccessLogPath, |
|
AccessAssetsLogOff: cfg.AccessAssetsLogOff, |
|
Rotate: logger.RotateCfg{ |
|
MaxSize: cfg.Logger.Rotate.MaxSize, |
|
MaxBackups: cfg.Logger.Rotate.MaxBackups, |
|
MaxAge: cfg.Logger.Rotate.MaxAge, |
|
Compress: cfg.Logger.Rotate.Compress, |
|
}, |
|
Encode: logger.EncoderCfg{ |
|
TimeKey: cfg.Logger.Encoder.TimeKey, |
|
LevelKey: cfg.Logger.Encoder.LevelKey, |
|
NameKey: cfg.Logger.Encoder.NameKey, |
|
CallerKey: cfg.Logger.Encoder.CallerKey, |
|
MessageKey: cfg.Logger.Encoder.MessageKey, |
|
StacktraceKey: cfg.Logger.Encoder.StacktraceKey, |
|
Level: cfg.Logger.Encoder.Level, |
|
Time: cfg.Logger.Encoder.Time, |
|
Duration: cfg.Logger.Encoder.Duration, |
|
Caller: cfg.Logger.Encoder.Caller, |
|
Encoding: cfg.Logger.Encoder.Encoding, |
|
}, |
|
Debug: cfg.Debug, |
|
Level: cfg.Logger.Level, |
|
}) |
|
} |
|
|
|
|
|
func AssertPrefix() string { |
|
return _global.AssertPrefix() |
|
} |
|
|
|
|
|
func GetIndexURL() string { |
|
return _global.GetIndexURL() |
|
} |
|
|
|
|
|
func IsProductionEnvironment() bool { |
|
return _global.IsProductionEnvironment() |
|
} |
|
|
|
|
|
func IsNotProductionEnvironment() bool { |
|
return _global.IsNotProductionEnvironment() |
|
} |
|
|
|
|
|
func URLRemovePrefix(url string) string { |
|
return _global.URLRemovePrefix(url) |
|
} |
|
|
|
func Url(suffix string) string { |
|
return _global.Url(suffix) |
|
} |
|
|
|
func GetURLFormats() URLFormat { |
|
return _global.URLFormat |
|
} |
|
|
|
|
|
func Prefix() string { |
|
return _global.prefix |
|
} |
|
|
|
|
|
func PrefixFixSlash() string { |
|
return _global.PrefixFixSlash() |
|
} |
|
|
|
|
|
func Get() *Config { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
|
|
return _global.Copy().EraseSens() |
|
} |
|
|
|
|
|
|
|
|
|
func GetDatabases() DatabaseList { |
|
var list = make(DatabaseList, len(_global.Databases)) |
|
for key := range _global.Databases { |
|
list[key] = Database{ |
|
Driver: _global.Databases[key].Driver, |
|
DriverMode: _global.Databases[key].DriverMode, |
|
} |
|
} |
|
return list |
|
} |
|
|
|
func GetDomain() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Domain |
|
} |
|
|
|
func GetLanguage() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Language |
|
} |
|
|
|
func GetAppID() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AppID |
|
} |
|
|
|
func GetUrlPrefix() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.UrlPrefix |
|
} |
|
|
|
func GetOpenAdminApi() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.OpenAdminApi |
|
} |
|
|
|
func GetAllowDelOperationLog() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AllowDelOperationLog |
|
} |
|
|
|
func GetOperationLogOff() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.OperationLogOff |
|
} |
|
|
|
func GetCustom500HTML() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Custom500HTML |
|
} |
|
|
|
func GetCustom404HTML() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Custom404HTML |
|
} |
|
|
|
func GetCustom403HTML() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Custom403HTML |
|
} |
|
|
|
func GetTheme() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Theme |
|
} |
|
|
|
func GetStore() Store { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Store |
|
} |
|
|
|
func GetTitle() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Title |
|
} |
|
|
|
func GetAssetRootPath() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AssetRootPath |
|
} |
|
|
|
func GetLogo() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Logo |
|
} |
|
|
|
func GetSiteOff() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.SiteOff |
|
} |
|
|
|
func GetMiniLogo() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.MiniLogo |
|
} |
|
|
|
func GetIndexUrl() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.IndexUrl |
|
} |
|
|
|
func GetLoginUrl() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.LoginUrl |
|
} |
|
|
|
func GetDebug() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Debug |
|
} |
|
|
|
func GetEnv() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Env |
|
} |
|
|
|
func GetInfoLogPath() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.InfoLogPath |
|
} |
|
|
|
func GetErrorLogPath() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.ErrorLogPath |
|
} |
|
|
|
func GetAccessLogPath() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AccessLogPath |
|
} |
|
|
|
func GetSqlLog() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.SqlLog |
|
} |
|
|
|
func GetAccessLogOff() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AccessLogOff |
|
} |
|
func GetInfoLogOff() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.InfoLogOff |
|
} |
|
func GetErrorLogOff() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.ErrorLogOff |
|
} |
|
|
|
func GetColorScheme() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.ColorScheme |
|
} |
|
|
|
func GetSessionLifeTime() int { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.SessionLifeTime |
|
} |
|
|
|
func GetAssetUrl() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AssetUrl |
|
} |
|
|
|
func GetFileUploadEngine() FileUploadEngine { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.FileUploadEngine |
|
} |
|
|
|
func GetCustomHeadHtml() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.CustomHeadHtml |
|
} |
|
|
|
func GetCustomFootHtml() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.CustomFootHtml |
|
} |
|
|
|
func GetFooterInfo() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.FooterInfo |
|
} |
|
|
|
func GetLoginTitle() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.LoginTitle |
|
} |
|
|
|
func GetLoginLogo() template.HTML { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.LoginLogo |
|
} |
|
|
|
func GetAuthUserTable() string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.AuthUserTable |
|
} |
|
|
|
func GetExtra() map[string]interface{} { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Extra |
|
} |
|
|
|
func GetAnimation() PageAnimation { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.Animation |
|
} |
|
|
|
func GetNoLimitLoginIP() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.NoLimitLoginIP |
|
} |
|
|
|
func GetHideVisitorUserCenterEntrance() bool { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.HideVisitorUserCenterEntrance |
|
} |
|
|
|
func GetExcludeThemeComponents() []string { |
|
_global.lock.RLock() |
|
defer _global.lock.RUnlock() |
|
return _global.ExcludeThemeComponents |
|
} |
|
|
|
type Service struct { |
|
C *Config |
|
} |
|
|
|
func (s *Service) Name() string { |
|
return "config" |
|
} |
|
|
|
func SrvWithConfig(c *Config) *Service { |
|
return &Service{c} |
|
} |
|
|
|
func GetService(s interface{}) *Config { |
|
if srv, ok := s.(*Service); ok { |
|
return srv.C |
|
} |
|
panic("wrong service") |
|
} |
|
|