config-core.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //
  2. // Copyright (C) 2017-2021 Marcus Rohrmoser, http://purl.mro.name/ShaarliGo
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. //
  17. package main
  18. import (
  19. "crypto/rand"
  20. "encoding/base64"
  21. "fmt"
  22. "io"
  23. "io/ioutil"
  24. "os"
  25. "path/filepath"
  26. "gopkg.in/yaml.v2"
  27. )
  28. var configFileName string
  29. func init() {
  30. configFileName = filepath.Join(dirApp, "config.yaml")
  31. }
  32. type RegexpReplaceAllString struct {
  33. Regexp string `yaml:"regexp"`
  34. ReplaceAllString string `yaml:"replace_all_string"`
  35. }
  36. // manual polymorphism in loadConfi
  37. type Pinboard struct {
  38. Endpoint string
  39. Prefix string
  40. }
  41. // manual polymorphism in loadConfi
  42. type Mastodon struct {
  43. Endpoint string
  44. Token string
  45. Prefix string
  46. Limit string
  47. }
  48. type Config struct {
  49. Title string `yaml:"title"`
  50. Uid string `yaml:"uid"`
  51. PwdBcrypt string `yaml:"pwd_bcrypt"`
  52. CookieStoreSecret string `yaml:"cookie_secret"`
  53. TimeZone string `yaml:"timezone"`
  54. LinksPerPage int `yaml:"links_per_page"` // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L18
  55. BanAfter int `yaml:"ban_after"` // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L20
  56. BanSeconds int `yaml:"ban_seconds"` // https://github.com/sebsauvage/Shaarli/blob/master/index.php#L21
  57. UrlCleaner []RegexpReplaceAllString `yaml:"url_cleaner"`
  58. Posse_ []map[string]string `yaml:"posse"`
  59. Posse []interface{} `yaml:"-"`
  60. // Redirector string `yaml:"redirector"` // actually a prefix to href - Hardcoded in xslt
  61. }
  62. func loadConfi(dat []byte) (Config, error) {
  63. ret := Config{}
  64. if err := yaml.Unmarshal(dat, &ret); err != nil {
  65. return Config{}, err
  66. }
  67. if ret.CookieStoreSecret == "" {
  68. buf := make([]byte, 32)
  69. if _, err := io.ReadFull(rand.Reader, buf); err != nil {
  70. return Config{}, err
  71. }
  72. ret.CookieStoreSecret = base64.StdEncoding.EncodeToString(buf)
  73. }
  74. ret.LinksPerPage = max(1, ret.LinksPerPage)
  75. ret.BanAfter = max(1, ret.BanAfter)
  76. ret.BanSeconds = max(1, ret.BanSeconds)
  77. // a hack to get a polymoprhic list.
  78. for _, m := range ret.Posse_ {
  79. if pi, ok := m["pinboard"]; ok {
  80. ret.Posse = append(ret.Posse, Pinboard{
  81. Endpoint: pi,
  82. Prefix: m["prefix"],
  83. })
  84. }
  85. if ma, ok := m["mastodon"]; ok {
  86. ret.Posse = append(ret.Posse, Mastodon{
  87. Endpoint: ma,
  88. Prefix: m["prefix"],
  89. Token: m["token"],
  90. Limit: m["limit"],
  91. })
  92. }
  93. }
  94. return ret, nil
  95. }
  96. func LoadConfig() (Config, error) {
  97. if read, err := ioutil.ReadFile(configFileName); err != nil {
  98. return Config{}, err
  99. } else {
  100. return loadConfi(read)
  101. }
  102. }
  103. func (cfg Config) Save() error {
  104. if out, err := yaml.Marshal(cfg); err == nil {
  105. tmpFileName := fmt.Sprintf("%s~%d", configFileName, os.Getpid())
  106. if err = os.MkdirAll(filepath.Dir(configFileName), 0770); err == nil {
  107. if err = ioutil.WriteFile(tmpFileName, out, 0660); err == nil {
  108. err = os.Rename(tmpFileName, configFileName)
  109. }
  110. }
  111. return err
  112. } else {
  113. return err
  114. }
  115. }
  116. func (cfg Config) IsConfigured() bool {
  117. return cfg.PwdBcrypt != ""
  118. }