A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

200 lines
5.1 KiB

  1. /*
  2. * Copyright © 2018-2019 A Bunch Tell LLC.
  3. *
  4. * This file is part of WriteFreely.
  5. *
  6. * WriteFreely is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License, included
  8. * in the LICENSE file in this source code package.
  9. */
  10. // Package config holds and assists in the configuration of a writefreely instance.
  11. package config
  12. import (
  13. "gopkg.in/ini.v1"
  14. "strings"
  15. )
  16. const (
  17. // FileName is the default configuration file name
  18. FileName = "config.ini"
  19. UserNormal UserType = "user"
  20. UserAdmin = "admin"
  21. )
  22. type (
  23. UserType string
  24. // ServerCfg holds values that affect how the HTTP server runs
  25. ServerCfg struct {
  26. HiddenHost string `ini:"hidden_host"`
  27. Port int `ini:"port"`
  28. Bind string `ini:"bind"`
  29. TLSCertPath string `ini:"tls_cert_path"`
  30. TLSKeyPath string `ini:"tls_key_path"`
  31. Autocert bool `ini:"autocert"`
  32. TemplatesParentDir string `ini:"templates_parent_dir"`
  33. StaticParentDir string `ini:"static_parent_dir"`
  34. PagesParentDir string `ini:"pages_parent_dir"`
  35. KeysParentDir string `ini:"keys_parent_dir"`
  36. Dev bool `ini:"-"`
  37. }
  38. // DatabaseCfg holds values that determine how the application connects to a datastore
  39. DatabaseCfg struct {
  40. Type string `ini:"type"`
  41. FileName string `ini:"filename"`
  42. User string `ini:"username"`
  43. Password string `ini:"password"`
  44. Database string `ini:"database"`
  45. Host string `ini:"host"`
  46. Port int `ini:"port"`
  47. }
  48. // AppCfg holds values that affect how the application functions
  49. AppCfg struct {
  50. SiteName string `ini:"site_name"`
  51. SiteDesc string `ini:"site_description"`
  52. Host string `ini:"host"`
  53. // Site appearance
  54. Theme string `ini:"theme"`
  55. Editor string `ini:"editor"`
  56. JSDisabled bool `ini:"disable_js"`
  57. WebFonts bool `ini:"webfonts"`
  58. Landing string `ini:"landing"`
  59. SimpleNav bool `ini:"simple_nav"`
  60. WFModesty bool `ini:"wf_modesty"`
  61. // Site functionality
  62. Chorus bool `ini:"chorus"`
  63. DisableDrafts bool `ini:"disable_drafts"`
  64. // Users
  65. SingleUser bool `ini:"single_user"`
  66. OpenRegistration bool `ini:"open_registration"`
  67. MinUsernameLen int `ini:"min_username_len"`
  68. MaxBlogs int `ini:"max_blogs"`
  69. // Federation
  70. Federation bool `ini:"federation"`
  71. PublicStats bool `ini:"public_stats"`
  72. // Access
  73. Private bool `ini:"private"`
  74. // Additional functions
  75. LocalTimeline bool `ini:"local_timeline"`
  76. UserInvites string `ini:"user_invites"`
  77. // OAuth
  78. EnableOAuth bool `ini:"enable_oauth"`
  79. OAuthProviderAuthLocation string `ini:"oauth_auth_location"`
  80. OAuthProviderTokenLocation string `ini:"oauth_token_location"`
  81. OAuthProviderInspectLocation string `ini:"oauth_inspect_location"`
  82. OAuthClientCallbackLocation string `ini:"oauth_callback_location"`
  83. OAuthClientID string `ini:"oauth_client_id"`
  84. OAuthClientSecret string `ini:"oauth_client_secret"`
  85. // Defaults
  86. DefaultVisibility string `ini:"default_visibility"`
  87. }
  88. // Config holds the complete configuration for running a writefreely instance
  89. Config struct {
  90. Server ServerCfg `ini:"server"`
  91. Database DatabaseCfg `ini:"database"`
  92. App AppCfg `ini:"app"`
  93. }
  94. )
  95. // New creates a new Config with sane defaults
  96. func New() *Config {
  97. c := &Config{
  98. Server: ServerCfg{
  99. Port: 8080,
  100. Bind: "localhost", /* IPV6 support when not using localhost? */
  101. },
  102. App: AppCfg{
  103. Host: "http://localhost:8080",
  104. Theme: "write",
  105. WebFonts: true,
  106. SingleUser: true,
  107. MinUsernameLen: 3,
  108. MaxBlogs: 1,
  109. Federation: true,
  110. PublicStats: true,
  111. },
  112. }
  113. c.UseMySQL(true)
  114. return c
  115. }
  116. // UseMySQL resets the Config's Database to use default values for a MySQL setup.
  117. func (cfg *Config) UseMySQL(fresh bool) {
  118. cfg.Database.Type = "mysql"
  119. if fresh {
  120. cfg.Database.Host = "localhost"
  121. cfg.Database.Port = 3306
  122. }
  123. }
  124. // UseSQLite resets the Config's Database to use default values for a SQLite setup.
  125. func (cfg *Config) UseSQLite(fresh bool) {
  126. cfg.Database.Type = "sqlite3"
  127. if fresh {
  128. cfg.Database.FileName = "writefreely.db"
  129. }
  130. }
  131. // IsSecureStandalone returns whether or not the application is running as a
  132. // standalone server with TLS enabled.
  133. func (cfg *Config) IsSecureStandalone() bool {
  134. return cfg.Server.Port == 443 && cfg.Server.TLSCertPath != "" && cfg.Server.TLSKeyPath != ""
  135. }
  136. func (ac *AppCfg) LandingPath() string {
  137. if !strings.HasPrefix(ac.Landing, "/") {
  138. return "/" + ac.Landing
  139. }
  140. return ac.Landing
  141. }
  142. // Load reads the given configuration file, then parses and returns it as a Config.
  143. func Load(fname string) (*Config, error) {
  144. if fname == "" {
  145. fname = FileName
  146. }
  147. cfg, err := ini.Load(fname)
  148. if err != nil {
  149. return nil, err
  150. }
  151. // Parse INI file
  152. uc := &Config{}
  153. err = cfg.MapTo(uc)
  154. if err != nil {
  155. return nil, err
  156. }
  157. return uc, nil
  158. }
  159. // Save writes the given Config to the given file.
  160. func Save(uc *Config, fname string) error {
  161. cfg := ini.Empty()
  162. err := ini.ReflectFrom(cfg, uc)
  163. if err != nil {
  164. return err
  165. }
  166. if fname == "" {
  167. fname = FileName
  168. }
  169. return cfg.SaveTo(fname)
  170. }