From 820e28c9044bbd9d398dd1617323665bb0935e13 Mon Sep 17 00:00:00 2001
From: Lunny Xiao <xiaolunwen@gmail.com>
Date: Sun, 10 Feb 2019 09:37:37 +0800
Subject: [PATCH] Split setting.go as multiple files (#6014)

* split setting.go as multiple files

* fix comments
---
 modules/setting/cache.go   |  43 ++++
 modules/setting/log.go     | 186 ++++++++++++++++
 modules/setting/mailer.go  | 126 +++++++++++
 modules/setting/service.go |  89 ++++++++
 modules/setting/session.go |  35 +++
 modules/setting/setting.go | 442 -------------------------------------
 modules/setting/webhook.go |  30 +++
 7 files changed, 509 insertions(+), 442 deletions(-)
 create mode 100644 modules/setting/cache.go
 create mode 100644 modules/setting/log.go
 create mode 100644 modules/setting/mailer.go
 create mode 100644 modules/setting/service.go
 create mode 100644 modules/setting/session.go
 create mode 100644 modules/setting/webhook.go

diff --git a/modules/setting/cache.go b/modules/setting/cache.go
new file mode 100644
index 0000000000..cbe73cf4e3
--- /dev/null
+++ b/modules/setting/cache.go
@@ -0,0 +1,43 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"strings"
+	"time"
+
+	"code.gitea.io/gitea/modules/log"
+)
+
+// Cache represents cache settings
+type Cache struct {
+	Adapter  string
+	Interval int
+	Conn     string
+	TTL      time.Duration
+}
+
+var (
+	// CacheService the global cache
+	CacheService *Cache
+)
+
+func newCacheService() {
+	sec := Cfg.Section("cache")
+	CacheService = &Cache{
+		Adapter: sec.Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"}),
+	}
+	switch CacheService.Adapter {
+	case "memory":
+		CacheService.Interval = sec.Key("INTERVAL").MustInt(60)
+	case "redis", "memcache":
+		CacheService.Conn = strings.Trim(sec.Key("HOST").String(), "\" ")
+	default:
+		log.Fatal(4, "Unknown cache adapter: %s", CacheService.Adapter)
+	}
+	CacheService.TTL = sec.Key("ITEM_TTL").MustDuration(16 * time.Hour)
+
+	log.Info("Cache Service Enabled")
+}
diff --git a/modules/setting/log.go b/modules/setting/log.go
new file mode 100644
index 0000000000..7b0832c0c8
--- /dev/null
+++ b/modules/setting/log.go
@@ -0,0 +1,186 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"fmt"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+
+	"code.gitea.io/gitea/modules/log"
+	"github.com/go-xorm/core"
+)
+
+var logLevels = map[string]string{
+	"Trace":    "0",
+	"Debug":    "1",
+	"Info":     "2",
+	"Warn":     "3",
+	"Error":    "4",
+	"Critical": "5",
+}
+
+func getLogLevel(section string, key string, defaultValue string) string {
+	validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
+	return Cfg.Section(section).Key(key).In(defaultValue, validLevels)
+}
+
+func newLogService() {
+	log.Info("Gitea v%s%s", AppVer, AppBuiltWith)
+
+	LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",")
+	LogConfigs = make([]string, len(LogModes))
+
+	useConsole := false
+	for i := 0; i < len(LogModes); i++ {
+		LogModes[i] = strings.TrimSpace(LogModes[i])
+		if LogModes[i] == "console" {
+			useConsole = true
+		}
+	}
+
+	if !useConsole {
+		log.DelLogger("console")
+	}
+
+	for i, mode := range LogModes {
+		sec, err := Cfg.GetSection("log." + mode)
+		if err != nil {
+			sec, _ = Cfg.NewSection("log." + mode)
+		}
+
+		// Log level.
+		levelName := getLogLevel("log."+mode, "LEVEL", LogLevel)
+		level, ok := logLevels[levelName]
+		if !ok {
+			log.Fatal(4, "Unknown log level: %s", levelName)
+		}
+
+		// Generate log configuration.
+		switch mode {
+		case "console":
+			LogConfigs[i] = fmt.Sprintf(`{"level":%s}`, level)
+		case "file":
+			logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "gitea.log"))
+			if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
+				panic(err.Error())
+			}
+
+			LogConfigs[i] = fmt.Sprintf(
+				`{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
+				logPath,
+				sec.Key("LOG_ROTATE").MustBool(true),
+				1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
+				sec.Key("DAILY_ROTATE").MustBool(true),
+				sec.Key("MAX_DAYS").MustInt(7))
+		case "conn":
+			LogConfigs[i] = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level,
+				sec.Key("RECONNECT_ON_MSG").MustBool(),
+				sec.Key("RECONNECT").MustBool(),
+				sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}),
+				sec.Key("ADDR").MustString(":7020"))
+		case "smtp":
+			LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":["%s"],"subject":"%s"}`, level,
+				sec.Key("USER").MustString("example@example.com"),
+				sec.Key("PASSWD").MustString("******"),
+				sec.Key("HOST").MustString("127.0.0.1:25"),
+				strings.Replace(sec.Key("RECEIVERS").MustString("example@example.com"), ",", "\",\"", -1),
+				sec.Key("SUBJECT").MustString("Diagnostic message from serve"))
+		case "database":
+			LogConfigs[i] = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level,
+				sec.Key("DRIVER").String(),
+				sec.Key("CONN").String())
+		}
+
+		log.NewLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, LogConfigs[i])
+		log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName)
+	}
+}
+
+// NewXORMLogService initializes xorm logger service
+func NewXORMLogService(disableConsole bool) {
+	logModes := strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",")
+	var logConfigs string
+	for _, mode := range logModes {
+		mode = strings.TrimSpace(mode)
+
+		if disableConsole && mode == "console" {
+			continue
+		}
+
+		sec, err := Cfg.GetSection("log." + mode)
+		if err != nil {
+			sec, _ = Cfg.NewSection("log." + mode)
+		}
+
+		// Log level.
+		levelName := getLogLevel("log."+mode, "LEVEL", LogLevel)
+		level, ok := logLevels[levelName]
+		if !ok {
+			log.Fatal(4, "Unknown log level: %s", levelName)
+		}
+
+		// Generate log configuration.
+		switch mode {
+		case "console":
+			logConfigs = fmt.Sprintf(`{"level":%s}`, level)
+		case "file":
+			logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "xorm.log"))
+			if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
+				panic(err.Error())
+			}
+			logPath = path.Join(filepath.Dir(logPath), "xorm.log")
+
+			logConfigs = fmt.Sprintf(
+				`{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
+				logPath,
+				sec.Key("LOG_ROTATE").MustBool(true),
+				1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
+				sec.Key("DAILY_ROTATE").MustBool(true),
+				sec.Key("MAX_DAYS").MustInt(7))
+		case "conn":
+			logConfigs = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level,
+				sec.Key("RECONNECT_ON_MSG").MustBool(),
+				sec.Key("RECONNECT").MustBool(),
+				sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}),
+				sec.Key("ADDR").MustString(":7020"))
+		case "smtp":
+			logConfigs = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":"%s","subject":"%s"}`, level,
+				sec.Key("USER").MustString("example@example.com"),
+				sec.Key("PASSWD").MustString("******"),
+				sec.Key("HOST").MustString("127.0.0.1:25"),
+				sec.Key("RECEIVERS").MustString("[]"),
+				sec.Key("SUBJECT").MustString("Diagnostic message from serve"))
+		case "database":
+			logConfigs = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level,
+				sec.Key("DRIVER").String(),
+				sec.Key("CONN").String())
+		}
+
+		log.NewXORMLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, logConfigs)
+		if !disableConsole {
+			log.Info("XORM Log Mode: %s(%s)", strings.Title(mode), levelName)
+		}
+
+		var lvl core.LogLevel
+		switch levelName {
+		case "Trace", "Debug":
+			lvl = core.LOG_DEBUG
+		case "Info":
+			lvl = core.LOG_INFO
+		case "Warn":
+			lvl = core.LOG_WARNING
+		case "Error", "Critical":
+			lvl = core.LOG_ERR
+		}
+		log.XORMLogger.SetLevel(lvl)
+	}
+
+	if len(logConfigs) == 0 {
+		log.DiscardXORMLogger()
+	}
+}
diff --git a/modules/setting/mailer.go b/modules/setting/mailer.go
new file mode 100644
index 0000000000..27c3d3a9f2
--- /dev/null
+++ b/modules/setting/mailer.go
@@ -0,0 +1,126 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"net/mail"
+
+	"code.gitea.io/gitea/modules/log"
+	shellquote "github.com/kballard/go-shellquote"
+)
+
+// Mailer represents mail service.
+type Mailer struct {
+	// Mailer
+	QueueLength     int
+	Name            string
+	From            string
+	FromName        string
+	FromEmail       string
+	SendAsPlainText bool
+	MailerType      string
+
+	// SMTP sender
+	Host              string
+	User, Passwd      string
+	DisableHelo       bool
+	HeloHostname      string
+	SkipVerify        bool
+	UseCertificate    bool
+	CertFile, KeyFile string
+	IsTLSEnabled      bool
+
+	// Sendmail sender
+	SendmailPath string
+	SendmailArgs []string
+}
+
+var (
+	// MailService the global mailer
+	MailService *Mailer
+)
+
+func newMailService() {
+	sec := Cfg.Section("mailer")
+	// Check mailer setting.
+	if !sec.Key("ENABLED").MustBool() {
+		return
+	}
+
+	MailService = &Mailer{
+		QueueLength:     sec.Key("SEND_BUFFER_LEN").MustInt(100),
+		Name:            sec.Key("NAME").MustString(AppName),
+		SendAsPlainText: sec.Key("SEND_AS_PLAIN_TEXT").MustBool(false),
+		MailerType:      sec.Key("MAILER_TYPE").In("", []string{"smtp", "sendmail", "dummy"}),
+
+		Host:           sec.Key("HOST").String(),
+		User:           sec.Key("USER").String(),
+		Passwd:         sec.Key("PASSWD").String(),
+		DisableHelo:    sec.Key("DISABLE_HELO").MustBool(),
+		HeloHostname:   sec.Key("HELO_HOSTNAME").String(),
+		SkipVerify:     sec.Key("SKIP_VERIFY").MustBool(),
+		UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
+		CertFile:       sec.Key("CERT_FILE").String(),
+		KeyFile:        sec.Key("KEY_FILE").String(),
+		IsTLSEnabled:   sec.Key("IS_TLS_ENABLED").MustBool(),
+
+		SendmailPath: sec.Key("SENDMAIL_PATH").MustString("sendmail"),
+	}
+	MailService.From = sec.Key("FROM").MustString(MailService.User)
+
+	if sec.HasKey("ENABLE_HTML_ALTERNATIVE") {
+		log.Warn("ENABLE_HTML_ALTERNATIVE is deprecated, use SEND_AS_PLAIN_TEXT")
+		MailService.SendAsPlainText = !sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false)
+	}
+
+	if sec.HasKey("USE_SENDMAIL") {
+		log.Warn("USE_SENDMAIL is deprecated, use MAILER_TYPE=sendmail")
+		if MailService.MailerType == "" && sec.Key("USE_SENDMAIL").MustBool(false) {
+			MailService.MailerType = "sendmail"
+		}
+	}
+
+	parsed, err := mail.ParseAddress(MailService.From)
+	if err != nil {
+		log.Fatal(4, "Invalid mailer.FROM (%s): %v", MailService.From, err)
+	}
+	MailService.FromName = parsed.Name
+	MailService.FromEmail = parsed.Address
+
+	if MailService.MailerType == "" {
+		MailService.MailerType = "smtp"
+	}
+
+	if MailService.MailerType == "sendmail" {
+		MailService.SendmailArgs, err = shellquote.Split(sec.Key("SENDMAIL_ARGS").String())
+		if err != nil {
+			log.Error(4, "Failed to parse Sendmail args: %v", CustomConf, err)
+		}
+	}
+
+	log.Info("Mail Service Enabled")
+}
+
+func newRegisterMailService() {
+	if !Cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").MustBool() {
+		return
+	} else if MailService == nil {
+		log.Warn("Register Mail Service: Mail Service is not enabled")
+		return
+	}
+	Service.RegisterEmailConfirm = true
+	log.Info("Register Mail Service Enabled")
+}
+
+func newNotifyMailService() {
+	if !Cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").MustBool() {
+		return
+	} else if MailService == nil {
+		log.Warn("Notify Mail Service: Mail Service is not enabled")
+		return
+	}
+	Service.EnableNotifyMail = true
+	log.Info("Notify Mail Service Enabled")
+}
diff --git a/modules/setting/service.go b/modules/setting/service.go
new file mode 100644
index 0000000000..4b9ddb055b
--- /dev/null
+++ b/modules/setting/service.go
@@ -0,0 +1,89 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import "regexp"
+
+// Service settings
+var Service struct {
+	ActiveCodeLives                         int
+	ResetPwdCodeLives                       int
+	RegisterEmailConfirm                    bool
+	EmailDomainWhitelist                    []string
+	DisableRegistration                     bool
+	AllowOnlyExternalRegistration           bool
+	ShowRegistrationButton                  bool
+	RequireSignInView                       bool
+	EnableNotifyMail                        bool
+	EnableReverseProxyAuth                  bool
+	EnableReverseProxyAutoRegister          bool
+	EnableReverseProxyEmail                 bool
+	EnableCaptcha                           bool
+	CaptchaType                             string
+	RecaptchaSecret                         string
+	RecaptchaSitekey                        string
+	DefaultKeepEmailPrivate                 bool
+	DefaultAllowCreateOrganization          bool
+	EnableTimetracking                      bool
+	DefaultEnableTimetracking               bool
+	DefaultEnableDependencies               bool
+	DefaultAllowOnlyContributorsToTrackTime bool
+	NoReplyAddress                          string
+	EnableUserHeatmap                       bool
+	AutoWatchNewRepos                       bool
+
+	// OpenID settings
+	EnableOpenIDSignIn bool
+	EnableOpenIDSignUp bool
+	OpenIDWhitelist    []*regexp.Regexp
+	OpenIDBlacklist    []*regexp.Regexp
+}
+
+func newService() {
+	sec := Cfg.Section("service")
+	Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180)
+	Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180)
+	Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool()
+	Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool()
+	Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",")
+	Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
+	Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
+	Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
+	Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
+	Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
+	Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
+	Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
+	Service.RecaptchaSecret = sec.Key("RECAPTCHA_SECRET").MustString("")
+	Service.RecaptchaSitekey = sec.Key("RECAPTCHA_SITEKEY").MustString("")
+	Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
+	Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
+	Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
+	if Service.EnableTimetracking {
+		Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
+	}
+	Service.DefaultEnableDependencies = sec.Key("DEFAULT_ENABLE_DEPENDENCIES").MustBool(true)
+	Service.DefaultAllowOnlyContributorsToTrackTime = sec.Key("DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME").MustBool(true)
+	Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply.example.org")
+	Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true)
+	Service.AutoWatchNewRepos = sec.Key("AUTO_WATCH_NEW_REPOS").MustBool(true)
+
+	sec = Cfg.Section("openid")
+	Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock)
+	Service.EnableOpenIDSignUp = sec.Key("ENABLE_OPENID_SIGNUP").MustBool(!Service.DisableRegistration && Service.EnableOpenIDSignIn)
+	pats := sec.Key("WHITELISTED_URIS").Strings(" ")
+	if len(pats) != 0 {
+		Service.OpenIDWhitelist = make([]*regexp.Regexp, len(pats))
+		for i, p := range pats {
+			Service.OpenIDWhitelist[i] = regexp.MustCompilePOSIX(p)
+		}
+	}
+	pats = sec.Key("BLACKLISTED_URIS").Strings(" ")
+	if len(pats) != 0 {
+		Service.OpenIDBlacklist = make([]*regexp.Regexp, len(pats))
+		for i, p := range pats {
+			Service.OpenIDBlacklist[i] = regexp.MustCompilePOSIX(p)
+		}
+	}
+}
diff --git a/modules/setting/session.go b/modules/setting/session.go
new file mode 100644
index 0000000000..97ac50d861
--- /dev/null
+++ b/modules/setting/session.go
@@ -0,0 +1,35 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"path"
+	"path/filepath"
+	"strings"
+
+	"code.gitea.io/gitea/modules/log"
+	"github.com/go-macaron/session"
+)
+
+var (
+	// SessionConfig difines Session settings
+	SessionConfig session.Options
+)
+
+func newSessionService() {
+	SessionConfig.Provider = Cfg.Section("session").Key("PROVIDER").In("memory",
+		[]string{"memory", "file", "redis", "mysql", "postgres", "couchbase", "memcache", "nodb"})
+	SessionConfig.ProviderConfig = strings.Trim(Cfg.Section("session").Key("PROVIDER_CONFIG").MustString(path.Join(AppDataPath, "sessions")), "\" ")
+	if SessionConfig.Provider == "file" && !filepath.IsAbs(SessionConfig.ProviderConfig) {
+		SessionConfig.ProviderConfig = path.Join(AppWorkPath, SessionConfig.ProviderConfig)
+	}
+	SessionConfig.CookieName = Cfg.Section("session").Key("COOKIE_NAME").MustString("i_like_gitea")
+	SessionConfig.CookiePath = AppSubURL
+	SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool(false)
+	SessionConfig.Gclifetime = Cfg.Section("session").Key("GC_INTERVAL_TIME").MustInt64(86400)
+	SessionConfig.Maxlifetime = Cfg.Section("session").Key("SESSION_LIFE_TIME").MustInt64(86400)
+
+	log.Info("Session Service Enabled")
+}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index c878fbe92f..0e3dc46882 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -7,9 +7,7 @@ package setting
 
 import (
 	"encoding/base64"
-	"fmt"
 	"net"
-	"net/mail"
 	"net/url"
 	"os"
 	"os/exec"
@@ -30,14 +28,12 @@ import (
 	"github.com/Unknwon/com"
 	_ "github.com/go-macaron/cache/memcache" // memcache plugin for cache
 	_ "github.com/go-macaron/cache/redis"
-	"github.com/go-macaron/session"
 	_ "github.com/go-macaron/session/couchbase" // couchbase plugin for session store
 	_ "github.com/go-macaron/session/memcache"  // memcache plugin for session store
 	_ "github.com/go-macaron/session/mysql"     // mysql plugin for session store
 	_ "github.com/go-macaron/session/nodb"      // nodb plugin for session store
 	_ "github.com/go-macaron/session/postgres"  // postgres plugin for session store
 	_ "github.com/go-macaron/session/redis"     // redis plugin for store session
-	"github.com/go-xorm/core"
 	shellquote "github.com/kballard/go-shellquote"
 	version "github.com/mcuadros/go-version"
 	ini "gopkg.in/ini.v1"
@@ -192,20 +188,6 @@ var (
 		MaxIndexerFileSize int64
 	}
 
-	// Webhook settings
-	Webhook = struct {
-		QueueLength    int
-		DeliverTimeout int
-		SkipTLSVerify  bool
-		Types          []string
-		PagingNum      int
-	}{
-		QueueLength:    1000,
-		DeliverTimeout: 5,
-		SkipTLSVerify:  false,
-		PagingNum:      10,
-	}
-
 	// Repository settings
 	Repository = struct {
 		AnsiCharset              string
@@ -409,8 +391,6 @@ var (
 	// Time settings
 	TimeFormat string
 
-	// Session settings
-	SessionConfig  session.Options
 	CSRFCookieName = "_csrf"
 
 	// Cron tasks
@@ -1235,428 +1215,6 @@ func NewContext() {
 	}
 }
 
-// Service settings
-var Service struct {
-	ActiveCodeLives                         int
-	ResetPwdCodeLives                       int
-	RegisterEmailConfirm                    bool
-	EmailDomainWhitelist                    []string
-	DisableRegistration                     bool
-	AllowOnlyExternalRegistration           bool
-	ShowRegistrationButton                  bool
-	RequireSignInView                       bool
-	EnableNotifyMail                        bool
-	EnableReverseProxyAuth                  bool
-	EnableReverseProxyAutoRegister          bool
-	EnableReverseProxyEmail                 bool
-	EnableCaptcha                           bool
-	CaptchaType                             string
-	RecaptchaSecret                         string
-	RecaptchaSitekey                        string
-	DefaultKeepEmailPrivate                 bool
-	DefaultAllowCreateOrganization          bool
-	EnableTimetracking                      bool
-	DefaultEnableTimetracking               bool
-	DefaultEnableDependencies               bool
-	DefaultAllowOnlyContributorsToTrackTime bool
-	NoReplyAddress                          string
-	EnableUserHeatmap                       bool
-	AutoWatchNewRepos                       bool
-
-	// OpenID settings
-	EnableOpenIDSignIn bool
-	EnableOpenIDSignUp bool
-	OpenIDWhitelist    []*regexp.Regexp
-	OpenIDBlacklist    []*regexp.Regexp
-}
-
-func newService() {
-	sec := Cfg.Section("service")
-	Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180)
-	Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180)
-	Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool()
-	Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool()
-	Service.EmailDomainWhitelist = sec.Key("EMAIL_DOMAIN_WHITELIST").Strings(",")
-	Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
-	Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
-	Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
-	Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
-	Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
-	Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
-	Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
-	Service.RecaptchaSecret = sec.Key("RECAPTCHA_SECRET").MustString("")
-	Service.RecaptchaSitekey = sec.Key("RECAPTCHA_SITEKEY").MustString("")
-	Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
-	Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
-	Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
-	if Service.EnableTimetracking {
-		Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
-	}
-	Service.DefaultEnableDependencies = sec.Key("DEFAULT_ENABLE_DEPENDENCIES").MustBool(true)
-	Service.DefaultAllowOnlyContributorsToTrackTime = sec.Key("DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME").MustBool(true)
-	Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply.example.org")
-	Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true)
-	Service.AutoWatchNewRepos = sec.Key("AUTO_WATCH_NEW_REPOS").MustBool(true)
-
-	sec = Cfg.Section("openid")
-	Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock)
-	Service.EnableOpenIDSignUp = sec.Key("ENABLE_OPENID_SIGNUP").MustBool(!Service.DisableRegistration && Service.EnableOpenIDSignIn)
-	pats := sec.Key("WHITELISTED_URIS").Strings(" ")
-	if len(pats) != 0 {
-		Service.OpenIDWhitelist = make([]*regexp.Regexp, len(pats))
-		for i, p := range pats {
-			Service.OpenIDWhitelist[i] = regexp.MustCompilePOSIX(p)
-		}
-	}
-	pats = sec.Key("BLACKLISTED_URIS").Strings(" ")
-	if len(pats) != 0 {
-		Service.OpenIDBlacklist = make([]*regexp.Regexp, len(pats))
-		for i, p := range pats {
-			Service.OpenIDBlacklist[i] = regexp.MustCompilePOSIX(p)
-		}
-	}
-}
-
-var logLevels = map[string]string{
-	"Trace":    "0",
-	"Debug":    "1",
-	"Info":     "2",
-	"Warn":     "3",
-	"Error":    "4",
-	"Critical": "5",
-}
-
-func getLogLevel(section string, key string, defaultValue string) string {
-	validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
-	return Cfg.Section(section).Key(key).In(defaultValue, validLevels)
-}
-
-func newLogService() {
-	log.Info("Gitea v%s%s", AppVer, AppBuiltWith)
-
-	LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",")
-	LogConfigs = make([]string, len(LogModes))
-
-	useConsole := false
-	for i := 0; i < len(LogModes); i++ {
-		LogModes[i] = strings.TrimSpace(LogModes[i])
-		if LogModes[i] == "console" {
-			useConsole = true
-		}
-	}
-
-	if !useConsole {
-		log.DelLogger("console")
-	}
-
-	for i, mode := range LogModes {
-		sec, err := Cfg.GetSection("log." + mode)
-		if err != nil {
-			sec, _ = Cfg.NewSection("log." + mode)
-		}
-
-		// Log level.
-		levelName := getLogLevel("log."+mode, "LEVEL", LogLevel)
-		level, ok := logLevels[levelName]
-		if !ok {
-			log.Fatal(4, "Unknown log level: %s", levelName)
-		}
-
-		// Generate log configuration.
-		switch mode {
-		case "console":
-			LogConfigs[i] = fmt.Sprintf(`{"level":%s}`, level)
-		case "file":
-			logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "gitea.log"))
-			if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
-				panic(err.Error())
-			}
-
-			LogConfigs[i] = fmt.Sprintf(
-				`{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
-				logPath,
-				sec.Key("LOG_ROTATE").MustBool(true),
-				1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
-				sec.Key("DAILY_ROTATE").MustBool(true),
-				sec.Key("MAX_DAYS").MustInt(7))
-		case "conn":
-			LogConfigs[i] = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level,
-				sec.Key("RECONNECT_ON_MSG").MustBool(),
-				sec.Key("RECONNECT").MustBool(),
-				sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}),
-				sec.Key("ADDR").MustString(":7020"))
-		case "smtp":
-			LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":["%s"],"subject":"%s"}`, level,
-				sec.Key("USER").MustString("example@example.com"),
-				sec.Key("PASSWD").MustString("******"),
-				sec.Key("HOST").MustString("127.0.0.1:25"),
-				strings.Replace(sec.Key("RECEIVERS").MustString("example@example.com"), ",", "\",\"", -1),
-				sec.Key("SUBJECT").MustString("Diagnostic message from serve"))
-		case "database":
-			LogConfigs[i] = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level,
-				sec.Key("DRIVER").String(),
-				sec.Key("CONN").String())
-		}
-
-		log.NewLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, LogConfigs[i])
-		log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName)
-	}
-}
-
-// NewXORMLogService initializes xorm logger service
-func NewXORMLogService(disableConsole bool) {
-	logModes := strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",")
-	var logConfigs string
-	for _, mode := range logModes {
-		mode = strings.TrimSpace(mode)
-
-		if disableConsole && mode == "console" {
-			continue
-		}
-
-		sec, err := Cfg.GetSection("log." + mode)
-		if err != nil {
-			sec, _ = Cfg.NewSection("log." + mode)
-		}
-
-		// Log level.
-		levelName := getLogLevel("log."+mode, "LEVEL", LogLevel)
-		level, ok := logLevels[levelName]
-		if !ok {
-			log.Fatal(4, "Unknown log level: %s", levelName)
-		}
-
-		// Generate log configuration.
-		switch mode {
-		case "console":
-			logConfigs = fmt.Sprintf(`{"level":%s}`, level)
-		case "file":
-			logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "xorm.log"))
-			if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
-				panic(err.Error())
-			}
-			logPath = path.Join(filepath.Dir(logPath), "xorm.log")
-
-			logConfigs = fmt.Sprintf(
-				`{"level":%s,"filename":"%s","rotate":%v,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
-				logPath,
-				sec.Key("LOG_ROTATE").MustBool(true),
-				1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
-				sec.Key("DAILY_ROTATE").MustBool(true),
-				sec.Key("MAX_DAYS").MustInt(7))
-		case "conn":
-			logConfigs = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level,
-				sec.Key("RECONNECT_ON_MSG").MustBool(),
-				sec.Key("RECONNECT").MustBool(),
-				sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}),
-				sec.Key("ADDR").MustString(":7020"))
-		case "smtp":
-			logConfigs = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":"%s","subject":"%s"}`, level,
-				sec.Key("USER").MustString("example@example.com"),
-				sec.Key("PASSWD").MustString("******"),
-				sec.Key("HOST").MustString("127.0.0.1:25"),
-				sec.Key("RECEIVERS").MustString("[]"),
-				sec.Key("SUBJECT").MustString("Diagnostic message from serve"))
-		case "database":
-			logConfigs = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level,
-				sec.Key("DRIVER").String(),
-				sec.Key("CONN").String())
-		}
-
-		log.NewXORMLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, logConfigs)
-		if !disableConsole {
-			log.Info("XORM Log Mode: %s(%s)", strings.Title(mode), levelName)
-		}
-
-		var lvl core.LogLevel
-		switch levelName {
-		case "Trace", "Debug":
-			lvl = core.LOG_DEBUG
-		case "Info":
-			lvl = core.LOG_INFO
-		case "Warn":
-			lvl = core.LOG_WARNING
-		case "Error", "Critical":
-			lvl = core.LOG_ERR
-		}
-		log.XORMLogger.SetLevel(lvl)
-	}
-
-	if len(logConfigs) == 0 {
-		log.DiscardXORMLogger()
-	}
-}
-
-// Cache represents cache settings
-type Cache struct {
-	Adapter  string
-	Interval int
-	Conn     string
-	TTL      time.Duration
-}
-
-var (
-	// CacheService the global cache
-	CacheService *Cache
-)
-
-func newCacheService() {
-	sec := Cfg.Section("cache")
-	CacheService = &Cache{
-		Adapter: sec.Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"}),
-	}
-	switch CacheService.Adapter {
-	case "memory":
-		CacheService.Interval = sec.Key("INTERVAL").MustInt(60)
-	case "redis", "memcache":
-		CacheService.Conn = strings.Trim(sec.Key("HOST").String(), "\" ")
-	default:
-		log.Fatal(4, "Unknown cache adapter: %s", CacheService.Adapter)
-	}
-	CacheService.TTL = sec.Key("ITEM_TTL").MustDuration(16 * time.Hour)
-
-	log.Info("Cache Service Enabled")
-}
-
-func newSessionService() {
-	SessionConfig.Provider = Cfg.Section("session").Key("PROVIDER").In("memory",
-		[]string{"memory", "file", "redis", "mysql", "postgres", "couchbase", "memcache", "nodb"})
-	SessionConfig.ProviderConfig = strings.Trim(Cfg.Section("session").Key("PROVIDER_CONFIG").MustString(path.Join(AppDataPath, "sessions")), "\" ")
-	if SessionConfig.Provider == "file" && !filepath.IsAbs(SessionConfig.ProviderConfig) {
-		SessionConfig.ProviderConfig = path.Join(AppWorkPath, SessionConfig.ProviderConfig)
-	}
-	SessionConfig.CookieName = Cfg.Section("session").Key("COOKIE_NAME").MustString("i_like_gitea")
-	SessionConfig.CookiePath = AppSubURL
-	SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool(false)
-	SessionConfig.Gclifetime = Cfg.Section("session").Key("GC_INTERVAL_TIME").MustInt64(86400)
-	SessionConfig.Maxlifetime = Cfg.Section("session").Key("SESSION_LIFE_TIME").MustInt64(86400)
-
-	log.Info("Session Service Enabled")
-}
-
-// Mailer represents mail service.
-type Mailer struct {
-	// Mailer
-	QueueLength     int
-	Name            string
-	From            string
-	FromName        string
-	FromEmail       string
-	SendAsPlainText bool
-	MailerType      string
-
-	// SMTP sender
-	Host              string
-	User, Passwd      string
-	DisableHelo       bool
-	HeloHostname      string
-	SkipVerify        bool
-	UseCertificate    bool
-	CertFile, KeyFile string
-	IsTLSEnabled      bool
-
-	// Sendmail sender
-	SendmailPath string
-	SendmailArgs []string
-}
-
-var (
-	// MailService the global mailer
-	MailService *Mailer
-)
-
-func newMailService() {
-	sec := Cfg.Section("mailer")
-	// Check mailer setting.
-	if !sec.Key("ENABLED").MustBool() {
-		return
-	}
-
-	MailService = &Mailer{
-		QueueLength:     sec.Key("SEND_BUFFER_LEN").MustInt(100),
-		Name:            sec.Key("NAME").MustString(AppName),
-		SendAsPlainText: sec.Key("SEND_AS_PLAIN_TEXT").MustBool(false),
-		MailerType:      sec.Key("MAILER_TYPE").In("", []string{"smtp", "sendmail", "dummy"}),
-
-		Host:           sec.Key("HOST").String(),
-		User:           sec.Key("USER").String(),
-		Passwd:         sec.Key("PASSWD").String(),
-		DisableHelo:    sec.Key("DISABLE_HELO").MustBool(),
-		HeloHostname:   sec.Key("HELO_HOSTNAME").String(),
-		SkipVerify:     sec.Key("SKIP_VERIFY").MustBool(),
-		UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
-		CertFile:       sec.Key("CERT_FILE").String(),
-		KeyFile:        sec.Key("KEY_FILE").String(),
-		IsTLSEnabled:   sec.Key("IS_TLS_ENABLED").MustBool(),
-
-		SendmailPath: sec.Key("SENDMAIL_PATH").MustString("sendmail"),
-	}
-	MailService.From = sec.Key("FROM").MustString(MailService.User)
-
-	if sec.HasKey("ENABLE_HTML_ALTERNATIVE") {
-		log.Warn("ENABLE_HTML_ALTERNATIVE is deprecated, use SEND_AS_PLAIN_TEXT")
-		MailService.SendAsPlainText = !sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false)
-	}
-
-	if sec.HasKey("USE_SENDMAIL") {
-		log.Warn("USE_SENDMAIL is deprecated, use MAILER_TYPE=sendmail")
-		if MailService.MailerType == "" && sec.Key("USE_SENDMAIL").MustBool(false) {
-			MailService.MailerType = "sendmail"
-		}
-	}
-
-	parsed, err := mail.ParseAddress(MailService.From)
-	if err != nil {
-		log.Fatal(4, "Invalid mailer.FROM (%s): %v", MailService.From, err)
-	}
-	MailService.FromName = parsed.Name
-	MailService.FromEmail = parsed.Address
-
-	if MailService.MailerType == "" {
-		MailService.MailerType = "smtp"
-	}
-
-	if MailService.MailerType == "sendmail" {
-		MailService.SendmailArgs, err = shellquote.Split(sec.Key("SENDMAIL_ARGS").String())
-		if err != nil {
-			log.Error(4, "Failed to parse Sendmail args: %v", CustomConf, err)
-		}
-	}
-
-	log.Info("Mail Service Enabled")
-}
-
-func newRegisterMailService() {
-	if !Cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").MustBool() {
-		return
-	} else if MailService == nil {
-		log.Warn("Register Mail Service: Mail Service is not enabled")
-		return
-	}
-	Service.RegisterEmailConfirm = true
-	log.Info("Register Mail Service Enabled")
-}
-
-func newNotifyMailService() {
-	if !Cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").MustBool() {
-		return
-	} else if MailService == nil {
-		log.Warn("Notify Mail Service: Mail Service is not enabled")
-		return
-	}
-	Service.EnableNotifyMail = true
-	log.Info("Notify Mail Service Enabled")
-}
-
-func newWebhookService() {
-	sec := Cfg.Section("webhook")
-	Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000)
-	Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
-	Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
-	Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk"}
-	Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
-}
-
 // NewServices initializes the services
 func NewServices() {
 	newService()
diff --git a/modules/setting/webhook.go b/modules/setting/webhook.go
new file mode 100644
index 0000000000..741963e545
--- /dev/null
+++ b/modules/setting/webhook.go
@@ -0,0 +1,30 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+var (
+	// Webhook settings
+	Webhook = struct {
+		QueueLength    int
+		DeliverTimeout int
+		SkipTLSVerify  bool
+		Types          []string
+		PagingNum      int
+	}{
+		QueueLength:    1000,
+		DeliverTimeout: 5,
+		SkipTLSVerify:  false,
+		PagingNum:      10,
+	}
+)
+
+func newWebhookService() {
+	sec := Cfg.Section("webhook")
+	Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000)
+	Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
+	Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
+	Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk"}
+	Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
+}