code.gitea.io/gitea@v1.21.7/routers/web/admin/config.go (about)

     1  // Copyright 2014 The Gogs Authors. All rights reserved.
     2  // Copyright 2019 The Gitea Authors. All rights reserved.
     3  // SPDX-License-Identifier: MIT
     4  
     5  package admin
     6  
     7  import (
     8  	"net/http"
     9  	"net/url"
    10  	"strings"
    11  
    12  	system_model "code.gitea.io/gitea/models/system"
    13  	"code.gitea.io/gitea/modules/base"
    14  	"code.gitea.io/gitea/modules/container"
    15  	"code.gitea.io/gitea/modules/context"
    16  	"code.gitea.io/gitea/modules/git"
    17  	"code.gitea.io/gitea/modules/json"
    18  	"code.gitea.io/gitea/modules/log"
    19  	"code.gitea.io/gitea/modules/setting"
    20  	"code.gitea.io/gitea/modules/setting/config"
    21  	"code.gitea.io/gitea/modules/util"
    22  	"code.gitea.io/gitea/services/mailer"
    23  
    24  	"gitea.com/go-chi/session"
    25  )
    26  
    27  const tplConfig base.TplName = "admin/config"
    28  
    29  // SendTestMail send test mail to confirm mail service is OK
    30  func SendTestMail(ctx *context.Context) {
    31  	email := ctx.FormString("email")
    32  	// Send a test email to the user's email address and redirect back to Config
    33  	if err := mailer.SendTestMail(email); err != nil {
    34  		ctx.Flash.Error(ctx.Tr("admin.config.test_mail_failed", email, err))
    35  	} else {
    36  		ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email))
    37  	}
    38  
    39  	ctx.Redirect(setting.AppSubURL + "/admin/config")
    40  }
    41  
    42  func shadowPasswordKV(cfgItem, splitter string) string {
    43  	fields := strings.Split(cfgItem, splitter)
    44  	for i := 0; i < len(fields); i++ {
    45  		if strings.HasPrefix(fields[i], "password=") {
    46  			fields[i] = "password=******"
    47  			break
    48  		}
    49  	}
    50  	return strings.Join(fields, splitter)
    51  }
    52  
    53  func shadowURL(provider, cfgItem string) string {
    54  	u, err := url.Parse(cfgItem)
    55  	if err != nil {
    56  		log.Error("Shadowing Password for %v failed: %v", provider, err)
    57  		return cfgItem
    58  	}
    59  	if u.User != nil {
    60  		atIdx := strings.Index(cfgItem, "@")
    61  		if atIdx > 0 {
    62  			colonIdx := strings.LastIndex(cfgItem[:atIdx], ":")
    63  			if colonIdx > 0 {
    64  				return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:]
    65  			}
    66  		}
    67  	}
    68  	return cfgItem
    69  }
    70  
    71  func shadowPassword(provider, cfgItem string) string {
    72  	switch provider {
    73  	case "redis":
    74  		return shadowPasswordKV(cfgItem, ",")
    75  	case "mysql":
    76  		// root:@tcp(localhost:3306)/macaron?charset=utf8
    77  		atIdx := strings.Index(cfgItem, "@")
    78  		if atIdx > 0 {
    79  			colonIdx := strings.Index(cfgItem[:atIdx], ":")
    80  			if colonIdx > 0 {
    81  				return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:]
    82  			}
    83  		}
    84  		return cfgItem
    85  	case "postgres":
    86  		// user=jiahuachen dbname=macaron port=5432 sslmode=disable
    87  		if !strings.HasPrefix(cfgItem, "postgres://") {
    88  			return shadowPasswordKV(cfgItem, " ")
    89  		}
    90  		fallthrough
    91  	case "couchbase":
    92  		return shadowURL(provider, cfgItem)
    93  		// postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full
    94  		// Notice: use shadowURL
    95  	}
    96  	return cfgItem
    97  }
    98  
    99  // Config show admin config page
   100  func Config(ctx *context.Context) {
   101  	ctx.Data["Title"] = ctx.Tr("admin.config")
   102  	ctx.Data["PageIsAdminConfig"] = true
   103  
   104  	ctx.Data["CustomConf"] = setting.CustomConf
   105  	ctx.Data["AppUrl"] = setting.AppURL
   106  	ctx.Data["AppBuiltWith"] = setting.AppBuiltWith
   107  	ctx.Data["Domain"] = setting.Domain
   108  	ctx.Data["OfflineMode"] = setting.OfflineMode
   109  	ctx.Data["RunUser"] = setting.RunUser
   110  	ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode)
   111  	ctx.Data["GitVersion"] = git.VersionInfo()
   112  
   113  	ctx.Data["AppDataPath"] = setting.AppDataPath
   114  	ctx.Data["RepoRootPath"] = setting.RepoRootPath
   115  	ctx.Data["CustomRootPath"] = setting.CustomPath
   116  	ctx.Data["LogRootPath"] = setting.Log.RootPath
   117  	ctx.Data["ScriptType"] = setting.ScriptType
   118  	ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser
   119  	ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail
   120  
   121  	ctx.Data["SSH"] = setting.SSH
   122  	ctx.Data["LFS"] = setting.LFS
   123  
   124  	ctx.Data["Service"] = setting.Service
   125  	ctx.Data["DbCfg"] = setting.Database
   126  	ctx.Data["Webhook"] = setting.Webhook
   127  
   128  	ctx.Data["MailerEnabled"] = false
   129  	if setting.MailService != nil {
   130  		ctx.Data["MailerEnabled"] = true
   131  		ctx.Data["Mailer"] = setting.MailService
   132  	}
   133  
   134  	ctx.Data["CacheAdapter"] = setting.CacheService.Adapter
   135  	ctx.Data["CacheInterval"] = setting.CacheService.Interval
   136  
   137  	ctx.Data["CacheConn"] = shadowPassword(setting.CacheService.Adapter, setting.CacheService.Conn)
   138  	ctx.Data["CacheItemTTL"] = setting.CacheService.TTL
   139  
   140  	sessionCfg := setting.SessionConfig
   141  	if sessionCfg.Provider == "VirtualSession" {
   142  		var realSession session.Options
   143  		if err := json.Unmarshal([]byte(sessionCfg.ProviderConfig), &realSession); err != nil {
   144  			log.Error("Unable to unmarshall session config for virtual provider config: %s\nError: %v", sessionCfg.ProviderConfig, err)
   145  		}
   146  		sessionCfg.Provider = realSession.Provider
   147  		sessionCfg.ProviderConfig = realSession.ProviderConfig
   148  		sessionCfg.CookieName = realSession.CookieName
   149  		sessionCfg.CookiePath = realSession.CookiePath
   150  		sessionCfg.Gclifetime = realSession.Gclifetime
   151  		sessionCfg.Maxlifetime = realSession.Maxlifetime
   152  		sessionCfg.Secure = realSession.Secure
   153  		sessionCfg.Domain = realSession.Domain
   154  	}
   155  	sessionCfg.ProviderConfig = shadowPassword(sessionCfg.Provider, sessionCfg.ProviderConfig)
   156  	ctx.Data["SessionConfig"] = sessionCfg
   157  
   158  	ctx.Data["Git"] = setting.Git
   159  	ctx.Data["AccessLogTemplate"] = setting.Log.AccessLogTemplate
   160  	ctx.Data["LogSQL"] = setting.Database.LogSQL
   161  
   162  	ctx.Data["Loggers"] = log.GetManager().DumpLoggers()
   163  	config.GetDynGetter().InvalidateCache()
   164  	ctx.Data["SystemConfig"] = setting.Config()
   165  	prepareDeprecatedWarningsAlert(ctx)
   166  
   167  	ctx.HTML(http.StatusOK, tplConfig)
   168  }
   169  
   170  func ChangeConfig(ctx *context.Context) {
   171  	key := strings.TrimSpace(ctx.FormString("key"))
   172  	value := ctx.FormString("value")
   173  	cfg := setting.Config()
   174  	allowedKeys := container.SetOf(cfg.Picture.DisableGravatar.DynKey(), cfg.Picture.EnableFederatedAvatar.DynKey())
   175  	if !allowedKeys.Contains(key) {
   176  		ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
   177  		return
   178  	}
   179  	if err := system_model.SetSettings(ctx, map[string]string{key: value}); err != nil {
   180  		log.Error("set setting failed: %v", err)
   181  		ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
   182  		return
   183  	}
   184  
   185  	config.GetDynGetter().InvalidateCache()
   186  	ctx.JSONOK()
   187  }