setting.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package setting
  5. import (
  6. "fmt"
  7. "net/url"
  8. "os"
  9. "os/exec"
  10. "path"
  11. "path/filepath"
  12. "runtime"
  13. "strings"
  14. "time"
  15. "github.com/Unknwon/com"
  16. _ "github.com/go-macaron/cache/memcache"
  17. _ "github.com/go-macaron/cache/redis"
  18. "github.com/go-macaron/session"
  19. _ "github.com/go-macaron/session/redis"
  20. "github.com/strk/go-libravatar"
  21. "gopkg.in/ini.v1"
  22. "github.com/gogits/gogs/modules/bindata"
  23. "github.com/gogits/gogs/modules/log"
  24. "github.com/gogits/gogs/modules/user"
  25. )
  26. type Scheme string
  27. const (
  28. HTTP Scheme = "http"
  29. HTTPS Scheme = "https"
  30. FCGI Scheme = "fcgi"
  31. )
  32. type LandingPage string
  33. const (
  34. LANDING_PAGE_HOME LandingPage = "/"
  35. LANDING_PAGE_EXPLORE LandingPage = "/explore"
  36. )
  37. var (
  38. // Build information
  39. BuildTime string
  40. BuildGitHash string
  41. // App settings
  42. AppVer string
  43. AppName string
  44. AppUrl string
  45. AppSubUrl string
  46. AppSubUrlDepth int // Number of slashes
  47. AppPath string
  48. AppDataPath string
  49. // Server settings
  50. Protocol Scheme
  51. Domain string
  52. HttpAddr, HttpPort string
  53. LocalURL string
  54. OfflineMode bool
  55. DisableRouterLog bool
  56. CertFile, KeyFile string
  57. StaticRootPath string
  58. EnableGzip bool
  59. LandingPageUrl LandingPage
  60. SSH struct {
  61. Disabled bool `ini:"DISABLE_SSH"`
  62. StartBuiltinServer bool `ini:"START_SSH_SERVER"`
  63. Domain string `ini:"SSH_DOMAIN"`
  64. Port int `ini:"SSH_PORT"`
  65. ListenPort int `ini:"SSH_LISTEN_PORT"`
  66. RootPath string `ini:"SSH_ROOT_PATH"`
  67. KeyTestPath string `ini:"SSH_KEY_TEST_PATH"`
  68. KeygenPath string `ini:"SSH_KEYGEN_PATH"`
  69. MinimumKeySizeCheck bool `ini:"-"`
  70. MinimumKeySizes map[string]int `ini:"-"`
  71. }
  72. // Security settings
  73. InstallLock bool
  74. SecretKey string
  75. LogInRememberDays int
  76. CookieUserName string
  77. CookieRememberName string
  78. ReverseProxyAuthUser string
  79. // Database settings
  80. UseSQLite3 bool
  81. UseMySQL bool
  82. UsePostgreSQL bool
  83. UseTiDB bool
  84. // Webhook settings
  85. Webhook struct {
  86. QueueLength int
  87. DeliverTimeout int
  88. SkipTLSVerify bool
  89. Types []string
  90. PagingNum int
  91. }
  92. // Repository settings
  93. Repository struct {
  94. AnsiCharset string
  95. ForcePrivate bool
  96. MaxCreationLimit int
  97. PullRequestQueueLength int
  98. }
  99. RepoRootPath string
  100. ScriptType string
  101. // UI settings
  102. UI struct {
  103. ExplorePagingNum int
  104. IssuePagingNum int
  105. FeedMaxCommitNum int
  106. ThemeColorMetaTag string
  107. MaxDisplayFileSize int64
  108. Admin struct {
  109. UserPagingNum int
  110. RepoPagingNum int
  111. NoticePagingNum int
  112. OrgPagingNum int
  113. } `ini:"ui.admin"`
  114. User struct {
  115. RepoPagingNum int
  116. } `ini:"ui.user"`
  117. }
  118. // Markdown sttings
  119. Markdown struct {
  120. EnableHardLineBreak bool
  121. CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"`
  122. }
  123. // Picture settings
  124. AvatarUploadPath string
  125. GravatarSource string
  126. DisableGravatar bool
  127. EnableFederatedAvatar bool
  128. LibravatarService *libravatar.Libravatar
  129. // Log settings
  130. LogRootPath string
  131. LogModes []string
  132. LogConfigs []string
  133. // Attachment settings
  134. AttachmentPath string
  135. AttachmentAllowedTypes string
  136. AttachmentMaxSize int64
  137. AttachmentMaxFiles int
  138. AttachmentEnabled bool
  139. // Time settings
  140. TimeFormat string
  141. // Cache settings
  142. CacheAdapter string
  143. CacheInternal int
  144. CacheConn string
  145. // Session settings
  146. SessionConfig session.Options
  147. CSRFCookieName = "_csrf"
  148. // Cron tasks
  149. Cron struct {
  150. UpdateMirror struct {
  151. Enabled bool
  152. RunAtStart bool
  153. Schedule string
  154. } `ini:"cron.update_mirrors"`
  155. RepoHealthCheck struct {
  156. Enabled bool
  157. RunAtStart bool
  158. Schedule string
  159. Timeout time.Duration
  160. Args []string `delim:" "`
  161. } `ini:"cron.repo_health_check"`
  162. CheckRepoStats struct {
  163. Enabled bool
  164. RunAtStart bool
  165. Schedule string
  166. } `ini:"cron.check_repo_stats"`
  167. }
  168. // Git settings
  169. Git struct {
  170. DisableDiffHighlight bool
  171. MaxGitDiffLines int
  172. MaxGitDiffLineCharacters int
  173. MaxGitDiffFiles int
  174. GCArgs []string `delim:" "`
  175. Timeout struct {
  176. Migrate int
  177. Mirror int
  178. Clone int
  179. Pull int
  180. GC int `ini:"GC"`
  181. } `ini:"git.timeout"`
  182. }
  183. // API settings
  184. API struct {
  185. MaxResponseItems int
  186. }
  187. // I18n settings
  188. Langs, Names []string
  189. dateLangs map[string]string
  190. // Highlight settings are loaded in modules/template/hightlight.go
  191. // Other settings
  192. ShowFooterBranding bool
  193. ShowFooterVersion bool
  194. SupportMiniWinService bool
  195. // Global setting objects
  196. Cfg *ini.File
  197. CustomPath string // Custom directory path
  198. CustomConf string
  199. ProdMode bool
  200. RunUser string
  201. IsWindows bool
  202. HasRobotsTxt bool
  203. )
  204. func DateLang(lang string) string {
  205. name, ok := dateLangs[lang]
  206. if ok {
  207. return name
  208. }
  209. return "en"
  210. }
  211. // execPath returns the executable path.
  212. func execPath() (string, error) {
  213. file, err := exec.LookPath(os.Args[0])
  214. if err != nil {
  215. return "", err
  216. }
  217. return filepath.Abs(file)
  218. }
  219. func init() {
  220. IsWindows = runtime.GOOS == "windows"
  221. log.NewLogger(0, "console", `{"level": 0}`)
  222. var err error
  223. if AppPath, err = execPath(); err != nil {
  224. log.Fatal(4, "fail to get app path: %v\n", err)
  225. }
  226. // Note: we don't use path.Dir here because it does not handle case
  227. // which path starts with two "/" in Windows: "//psf/Home/..."
  228. AppPath = strings.Replace(AppPath, "\\", "/", -1)
  229. }
  230. // WorkDir returns absolute path of work directory.
  231. func WorkDir() (string, error) {
  232. wd := os.Getenv("GOGS_WORK_DIR")
  233. if len(wd) > 0 {
  234. return wd, nil
  235. }
  236. i := strings.LastIndex(AppPath, "/")
  237. if i == -1 {
  238. return AppPath, nil
  239. }
  240. return AppPath[:i], nil
  241. }
  242. func forcePathSeparator(path string) {
  243. if strings.Contains(path, "\\") {
  244. log.Fatal(4, "Do not use '\\' or '\\\\' in paths, instead, please use '/' in all places")
  245. }
  246. }
  247. // IsRunUserMatchCurrentUser returns false if configured run user does not match
  248. // actual user that runs the app. The first return value is the actual user name.
  249. // This check is ignored under Windows since SSH remote login is not the main
  250. // method to login on Windows.
  251. func IsRunUserMatchCurrentUser(runUser string) (string, bool) {
  252. if IsWindows {
  253. return "", true
  254. }
  255. currentUser := user.CurrentUsername()
  256. return currentUser, runUser == currentUser
  257. }
  258. // NewContext initializes configuration context.
  259. // NOTE: do not print any log except error.
  260. func NewContext() {
  261. workDir, err := WorkDir()
  262. if err != nil {
  263. log.Fatal(4, "Fail to get work directory: %v", err)
  264. }
  265. Cfg, err = ini.Load(bindata.MustAsset("conf/app.ini"))
  266. if err != nil {
  267. log.Fatal(4, "Fail to parse 'conf/app.ini': %v", err)
  268. }
  269. CustomPath = os.Getenv("GOGS_CUSTOM")
  270. if len(CustomPath) == 0 {
  271. CustomPath = workDir + "/custom"
  272. }
  273. if len(CustomConf) == 0 {
  274. CustomConf = CustomPath + "/conf/app.ini"
  275. }
  276. if com.IsFile(CustomConf) {
  277. if err = Cfg.Append(CustomConf); err != nil {
  278. log.Fatal(4, "Fail to load custom conf '%s': %v", CustomConf, err)
  279. }
  280. } else {
  281. log.Warn("Custom config '%s' not found, ignore this if you're running first time", CustomConf)
  282. }
  283. Cfg.NameMapper = ini.AllCapsUnderscore
  284. homeDir, err := com.HomeDir()
  285. if err != nil {
  286. log.Fatal(4, "Fail to get home directory: %v", err)
  287. }
  288. homeDir = strings.Replace(homeDir, "\\", "/", -1)
  289. LogRootPath = Cfg.Section("log").Key("ROOT_PATH").MustString(path.Join(workDir, "log"))
  290. forcePathSeparator(LogRootPath)
  291. sec := Cfg.Section("server")
  292. AppName = Cfg.Section("").Key("APP_NAME").MustString("Gogs: Go Git Service")
  293. AppUrl = sec.Key("ROOT_URL").MustString("http://localhost:3000/")
  294. if AppUrl[len(AppUrl)-1] != '/' {
  295. AppUrl += "/"
  296. }
  297. // Check if has app suburl.
  298. url, err := url.Parse(AppUrl)
  299. if err != nil {
  300. log.Fatal(4, "Invalid ROOT_URL '%s': %s", AppUrl, err)
  301. }
  302. // Suburl should start with '/' and end without '/', such as '/{subpath}'.
  303. // This value is empty if site does not have sub-url.
  304. AppSubUrl = strings.TrimSuffix(url.Path, "/")
  305. AppSubUrlDepth = strings.Count(AppSubUrl, "/")
  306. Protocol = HTTP
  307. if sec.Key("PROTOCOL").String() == "https" {
  308. Protocol = HTTPS
  309. CertFile = sec.Key("CERT_FILE").String()
  310. KeyFile = sec.Key("KEY_FILE").String()
  311. } else if sec.Key("PROTOCOL").String() == "fcgi" {
  312. Protocol = FCGI
  313. }
  314. Domain = sec.Key("DOMAIN").MustString("localhost")
  315. HttpAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
  316. HttpPort = sec.Key("HTTP_PORT").MustString("3000")
  317. LocalURL = sec.Key("LOCAL_ROOT_URL").MustString(string(Protocol) + "://localhost:" + HttpPort + "/")
  318. OfflineMode = sec.Key("OFFLINE_MODE").MustBool()
  319. DisableRouterLog = sec.Key("DISABLE_ROUTER_LOG").MustBool()
  320. StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(workDir)
  321. AppDataPath = sec.Key("APP_DATA_PATH").MustString("data")
  322. EnableGzip = sec.Key("ENABLE_GZIP").MustBool()
  323. switch sec.Key("LANDING_PAGE").MustString("home") {
  324. case "explore":
  325. LandingPageUrl = LANDING_PAGE_EXPLORE
  326. default:
  327. LandingPageUrl = LANDING_PAGE_HOME
  328. }
  329. SSH.RootPath = path.Join(homeDir, ".ssh")
  330. SSH.KeyTestPath = os.TempDir()
  331. if err = Cfg.Section("server").MapTo(&SSH); err != nil {
  332. log.Fatal(4, "Fail to map SSH settings: %v", err)
  333. }
  334. // When disable SSH, start builtin server value is ignored.
  335. if SSH.Disabled {
  336. SSH.StartBuiltinServer = false
  337. }
  338. if !SSH.Disabled && !SSH.StartBuiltinServer {
  339. if err := os.MkdirAll(SSH.RootPath, 0700); err != nil {
  340. log.Fatal(4, "Fail to create '%s': %v", SSH.RootPath, err)
  341. } else if err = os.MkdirAll(SSH.KeyTestPath, 0644); err != nil {
  342. log.Fatal(4, "Fail to create '%s': %v", SSH.KeyTestPath, err)
  343. }
  344. }
  345. SSH.MinimumKeySizeCheck = sec.Key("MINIMUM_KEY_SIZE_CHECK").MustBool()
  346. SSH.MinimumKeySizes = map[string]int{}
  347. minimumKeySizes := Cfg.Section("ssh.minimum_key_sizes").Keys()
  348. for _, key := range minimumKeySizes {
  349. if key.MustInt() != -1 {
  350. SSH.MinimumKeySizes[strings.ToLower(key.Name())] = key.MustInt()
  351. }
  352. }
  353. sec = Cfg.Section("security")
  354. InstallLock = sec.Key("INSTALL_LOCK").MustBool()
  355. SecretKey = sec.Key("SECRET_KEY").String()
  356. LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt()
  357. CookieUserName = sec.Key("COOKIE_USERNAME").String()
  358. CookieRememberName = sec.Key("COOKIE_REMEMBER_NAME").String()
  359. ReverseProxyAuthUser = sec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER")
  360. sec = Cfg.Section("attachment")
  361. AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments"))
  362. if !filepath.IsAbs(AttachmentPath) {
  363. AttachmentPath = path.Join(workDir, AttachmentPath)
  364. }
  365. AttachmentAllowedTypes = strings.Replace(sec.Key("ALLOWED_TYPES").MustString("image/jpeg,image/png"), "|", ",", -1)
  366. AttachmentMaxSize = sec.Key("MAX_SIZE").MustInt64(4)
  367. AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5)
  368. AttachmentEnabled = sec.Key("ENABLE").MustBool(true)
  369. TimeFormat = map[string]string{
  370. "ANSIC": time.ANSIC,
  371. "UnixDate": time.UnixDate,
  372. "RubyDate": time.RubyDate,
  373. "RFC822": time.RFC822,
  374. "RFC822Z": time.RFC822Z,
  375. "RFC850": time.RFC850,
  376. "RFC1123": time.RFC1123,
  377. "RFC1123Z": time.RFC1123Z,
  378. "RFC3339": time.RFC3339,
  379. "RFC3339Nano": time.RFC3339Nano,
  380. "Kitchen": time.Kitchen,
  381. "Stamp": time.Stamp,
  382. "StampMilli": time.StampMilli,
  383. "StampMicro": time.StampMicro,
  384. "StampNano": time.StampNano,
  385. }[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")]
  386. RunUser = Cfg.Section("").Key("RUN_USER").String()
  387. // Does not check run user when the install lock is off.
  388. if InstallLock {
  389. currentUser, match := IsRunUserMatchCurrentUser(RunUser)
  390. if !match {
  391. log.Fatal(4, "Expect user '%s' but current user is: %s", RunUser, currentUser)
  392. }
  393. }
  394. // Determine and create root git repository path.
  395. sec = Cfg.Section("repository")
  396. RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gogs-repositories"))
  397. forcePathSeparator(RepoRootPath)
  398. if !filepath.IsAbs(RepoRootPath) {
  399. RepoRootPath = path.Join(workDir, RepoRootPath)
  400. } else {
  401. RepoRootPath = path.Clean(RepoRootPath)
  402. }
  403. ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
  404. if err = Cfg.Section("repository").MapTo(&Repository); err != nil {
  405. log.Fatal(4, "Fail to map Repository settings: %v", err)
  406. }
  407. sec = Cfg.Section("picture")
  408. AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString(path.Join(AppDataPath, "avatars"))
  409. forcePathSeparator(AvatarUploadPath)
  410. if !filepath.IsAbs(AvatarUploadPath) {
  411. AvatarUploadPath = path.Join(workDir, AvatarUploadPath)
  412. }
  413. switch source := sec.Key("GRAVATAR_SOURCE").MustString("gravatar"); source {
  414. case "duoshuo":
  415. GravatarSource = "http://gravatar.duoshuo.com/avatar/"
  416. case "gravatar":
  417. GravatarSource = "https://secure.gravatar.com/avatar/"
  418. default:
  419. GravatarSource = source
  420. }
  421. DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool()
  422. EnableFederatedAvatar = sec.Key("ENABLE_FEDERATED_AVATAR").MustBool()
  423. if OfflineMode {
  424. DisableGravatar = true
  425. EnableFederatedAvatar = false
  426. }
  427. if DisableGravatar {
  428. EnableFederatedAvatar = false
  429. }
  430. if EnableFederatedAvatar {
  431. LibravatarService = libravatar.New()
  432. parts := strings.Split(GravatarSource, "/")
  433. if len(parts) >= 3 {
  434. if parts[0] == "https:" {
  435. LibravatarService.SetUseHTTPS(true)
  436. LibravatarService.SetSecureFallbackHost(parts[2])
  437. } else {
  438. LibravatarService.SetUseHTTPS(false)
  439. LibravatarService.SetFallbackHost(parts[2])
  440. }
  441. }
  442. }
  443. if err = Cfg.Section("ui").MapTo(&UI); err != nil {
  444. log.Fatal(4, "Fail to map UI settings: %v", err)
  445. } else if err = Cfg.Section("markdown").MapTo(&Markdown); err != nil {
  446. log.Fatal(4, "Fail to map Markdown settings: %v", err)
  447. } else if err = Cfg.Section("cron").MapTo(&Cron); err != nil {
  448. log.Fatal(4, "Fail to map Cron settings: %v", err)
  449. } else if err = Cfg.Section("git").MapTo(&Git); err != nil {
  450. log.Fatal(4, "Fail to map Git settings: %v", err)
  451. } else if err = Cfg.Section("api").MapTo(&API); err != nil {
  452. log.Fatal(4, "Fail to map API settings: %v", err)
  453. }
  454. Langs = Cfg.Section("i18n").Key("LANGS").Strings(",")
  455. Names = Cfg.Section("i18n").Key("NAMES").Strings(",")
  456. dateLangs = Cfg.Section("i18n.datelang").KeysHash()
  457. ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool()
  458. ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool()
  459. HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt"))
  460. }
  461. var Service struct {
  462. ActiveCodeLives int
  463. ResetPwdCodeLives int
  464. RegisterEmailConfirm bool
  465. DisableRegistration bool
  466. ShowRegistrationButton bool
  467. RequireSignInView bool
  468. EnableNotifyMail bool
  469. EnableReverseProxyAuth bool
  470. EnableReverseProxyAutoRegister bool
  471. EnableCaptcha bool
  472. }
  473. func newService() {
  474. sec := Cfg.Section("service")
  475. Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180)
  476. Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180)
  477. Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool()
  478. Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!Service.DisableRegistration)
  479. Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
  480. Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
  481. Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
  482. Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool()
  483. }
  484. var logLevels = map[string]string{
  485. "Trace": "0",
  486. "Debug": "1",
  487. "Info": "2",
  488. "Warn": "3",
  489. "Error": "4",
  490. "Critical": "5",
  491. }
  492. func newLogService() {
  493. log.Info("%s %s", AppName, AppVer)
  494. if len(BuildTime) > 0 {
  495. log.Info("Build Time: %s", BuildTime)
  496. log.Info("Build Git Hash: %s", BuildGitHash)
  497. }
  498. // Get and check log mode.
  499. LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",")
  500. LogConfigs = make([]string, len(LogModes))
  501. for i, mode := range LogModes {
  502. mode = strings.TrimSpace(mode)
  503. sec, err := Cfg.GetSection("log." + mode)
  504. if err != nil {
  505. log.Fatal(4, "Unknown log mode: %s", mode)
  506. }
  507. validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
  508. // Log level.
  509. levelName := Cfg.Section("log."+mode).Key("LEVEL").In(
  510. Cfg.Section("log").Key("LEVEL").In("Trace", validLevels),
  511. validLevels)
  512. level, ok := logLevels[levelName]
  513. if !ok {
  514. log.Fatal(4, "Unknown log level: %s", levelName)
  515. }
  516. // Generate log configuration.
  517. switch mode {
  518. case "console":
  519. LogConfigs[i] = fmt.Sprintf(`{"level":%s}`, level)
  520. case "file":
  521. logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "gogs.log"))
  522. if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
  523. panic(err.Error())
  524. }
  525. LogConfigs[i] = fmt.Sprintf(
  526. `{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
  527. logPath,
  528. sec.Key("LOG_ROTATE").MustBool(true),
  529. sec.Key("MAX_LINES").MustInt(1000000),
  530. 1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)),
  531. sec.Key("DAILY_ROTATE").MustBool(true),
  532. sec.Key("MAX_DAYS").MustInt(7))
  533. case "conn":
  534. LogConfigs[i] = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level,
  535. sec.Key("RECONNECT_ON_MSG").MustBool(),
  536. sec.Key("RECONNECT").MustBool(),
  537. sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}),
  538. sec.Key("ADDR").MustString(":7020"))
  539. case "smtp":
  540. LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"%s","password":"%s","host":"%s","sendTos":"%s","subject":"%s"}`, level,
  541. sec.Key("USER").MustString("[email protected]"),
  542. sec.Key("PASSWD").MustString("******"),
  543. sec.Key("HOST").MustString("127.0.0.1:25"),
  544. sec.Key("RECEIVERS").MustString("[]"),
  545. sec.Key("SUBJECT").MustString("Diagnostic message from serve"))
  546. case "database":
  547. LogConfigs[i] = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level,
  548. sec.Key("DRIVER").String(),
  549. sec.Key("CONN").String())
  550. }
  551. log.NewLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, LogConfigs[i])
  552. log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName)
  553. }
  554. }
  555. func newCacheService() {
  556. CacheAdapter = Cfg.Section("cache").Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"})
  557. switch CacheAdapter {
  558. case "memory":
  559. CacheInternal = Cfg.Section("cache").Key("INTERVAL").MustInt(60)
  560. case "redis", "memcache":
  561. CacheConn = strings.Trim(Cfg.Section("cache").Key("HOST").String(), "\" ")
  562. default:
  563. log.Fatal(4, "Unknown cache adapter: %s", CacheAdapter)
  564. }
  565. log.Info("Cache Service Enabled")
  566. }
  567. func newSessionService() {
  568. SessionConfig.Provider = Cfg.Section("session").Key("PROVIDER").In("memory",
  569. []string{"memory", "file", "redis", "mysql"})
  570. SessionConfig.ProviderConfig = strings.Trim(Cfg.Section("session").Key("PROVIDER_CONFIG").String(), "\" ")
  571. SessionConfig.CookieName = Cfg.Section("session").Key("COOKIE_NAME").MustString("i_like_gogits")
  572. SessionConfig.CookiePath = AppSubUrl
  573. SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool()
  574. SessionConfig.Gclifetime = Cfg.Section("session").Key("GC_INTERVAL_TIME").MustInt64(86400)
  575. SessionConfig.Maxlifetime = Cfg.Section("session").Key("SESSION_LIFE_TIME").MustInt64(86400)
  576. log.Info("Session Service Enabled")
  577. }
  578. // Mailer represents mail service.
  579. type Mailer struct {
  580. QueueLength int
  581. Name string
  582. Host string
  583. From string
  584. User, Passwd string
  585. DisableHelo bool
  586. HeloHostname string
  587. SkipVerify bool
  588. UseCertificate bool
  589. CertFile, KeyFile string
  590. EnableHTMLAlternative bool
  591. }
  592. var (
  593. MailService *Mailer
  594. )
  595. func newMailService() {
  596. sec := Cfg.Section("mailer")
  597. // Check mailer setting.
  598. if !sec.Key("ENABLED").MustBool() {
  599. return
  600. }
  601. MailService = &Mailer{
  602. QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100),
  603. Name: sec.Key("NAME").MustString(AppName),
  604. Host: sec.Key("HOST").String(),
  605. User: sec.Key("USER").String(),
  606. Passwd: sec.Key("PASSWD").String(),
  607. DisableHelo: sec.Key("DISABLE_HELO").MustBool(),
  608. HeloHostname: sec.Key("HELO_HOSTNAME").String(),
  609. SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
  610. UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
  611. CertFile: sec.Key("CERT_FILE").String(),
  612. KeyFile: sec.Key("KEY_FILE").String(),
  613. EnableHTMLAlternative: sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(),
  614. }
  615. MailService.From = sec.Key("FROM").MustString(MailService.User)
  616. log.Info("Mail Service Enabled")
  617. }
  618. func newRegisterMailService() {
  619. if !Cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").MustBool() {
  620. return
  621. } else if MailService == nil {
  622. log.Warn("Register Mail Service: Mail Service is not enabled")
  623. return
  624. }
  625. Service.RegisterEmailConfirm = true
  626. log.Info("Register Mail Service Enabled")
  627. }
  628. func newNotifyMailService() {
  629. if !Cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").MustBool() {
  630. return
  631. } else if MailService == nil {
  632. log.Warn("Notify Mail Service: Mail Service is not enabled")
  633. return
  634. }
  635. Service.EnableNotifyMail = true
  636. log.Info("Notify Mail Service Enabled")
  637. }
  638. func newWebhookService() {
  639. sec := Cfg.Section("webhook")
  640. Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000)
  641. Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
  642. Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
  643. Webhook.Types = []string{"gogs", "slack"}
  644. Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
  645. }
  646. func NewServices() {
  647. newService()
  648. newLogService()
  649. newCacheService()
  650. newSessionService()
  651. newMailService()
  652. newRegisterMailService()
  653. newNotifyMailService()
  654. newWebhookService()
  655. }