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.
 
 
 
 
 

188 lines
5.7 KiB

  1. package writefreely
  2. import (
  3. "fmt"
  4. "github.com/gogits/gogs/pkg/tool"
  5. "github.com/gorilla/mux"
  6. "github.com/writeas/impart"
  7. "github.com/writeas/web-core/auth"
  8. "github.com/writeas/writefreely/config"
  9. "net/http"
  10. "runtime"
  11. "strconv"
  12. "time"
  13. )
  14. var (
  15. appStartTime = time.Now()
  16. sysStatus systemStatus
  17. )
  18. type systemStatus struct {
  19. Uptime string
  20. NumGoroutine int
  21. // General statistics.
  22. MemAllocated string // bytes allocated and still in use
  23. MemTotal string // bytes allocated (even if freed)
  24. MemSys string // bytes obtained from system (sum of XxxSys below)
  25. Lookups uint64 // number of pointer lookups
  26. MemMallocs uint64 // number of mallocs
  27. MemFrees uint64 // number of frees
  28. // Main allocation heap statistics.
  29. HeapAlloc string // bytes allocated and still in use
  30. HeapSys string // bytes obtained from system
  31. HeapIdle string // bytes in idle spans
  32. HeapInuse string // bytes in non-idle span
  33. HeapReleased string // bytes released to the OS
  34. HeapObjects uint64 // total number of allocated objects
  35. // Low-level fixed-size structure allocator statistics.
  36. // Inuse is bytes used now.
  37. // Sys is bytes obtained from system.
  38. StackInuse string // bootstrap stacks
  39. StackSys string
  40. MSpanInuse string // mspan structures
  41. MSpanSys string
  42. MCacheInuse string // mcache structures
  43. MCacheSys string
  44. BuckHashSys string // profiling bucket hash table
  45. GCSys string // GC metadata
  46. OtherSys string // other system allocations
  47. // Garbage collector statistics.
  48. NextGC string // next run in HeapAlloc time (bytes)
  49. LastGC string // last run in absolute time (ns)
  50. PauseTotalNs string
  51. PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
  52. NumGC uint32
  53. }
  54. func handleViewAdminDash(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
  55. updateAppStats()
  56. p := struct {
  57. *UserPage
  58. SysStatus systemStatus
  59. Config config.AppCfg
  60. Message, ConfigMessage string
  61. AboutPage, PrivacyPage string
  62. }{
  63. UserPage: NewUserPage(app, r, u, "Admin", nil),
  64. SysStatus: sysStatus,
  65. Config: app.cfg.App,
  66. Message: r.FormValue("m"),
  67. ConfigMessage: r.FormValue("cm"),
  68. }
  69. var err error
  70. p.AboutPage, err = getAboutPage(app)
  71. if err != nil {
  72. return err
  73. }
  74. p.PrivacyPage, _, err = getPrivacyPage(app)
  75. if err != nil {
  76. return err
  77. }
  78. showUserPage(w, "admin", p)
  79. return nil
  80. }
  81. func handleAdminUpdateSite(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
  82. vars := mux.Vars(r)
  83. id := vars["page"]
  84. // Validate
  85. if id != "about" && id != "privacy" {
  86. return impart.HTTPError{http.StatusNotFound, "No such page."}
  87. }
  88. // Update page
  89. m := ""
  90. err := app.db.UpdateDynamicContent(id, r.FormValue("content"))
  91. if err != nil {
  92. m = "?m=" + err.Error()
  93. }
  94. return impart.HTTPError{http.StatusFound, "/admin" + m + "#page-" + id}
  95. }
  96. func handleAdminUpdateConfig(app *app, u *User, w http.ResponseWriter, r *http.Request) error {
  97. app.cfg.App.SiteName = r.FormValue("site_name")
  98. app.cfg.App.SiteDesc = r.FormValue("site_desc")
  99. app.cfg.App.OpenRegistration = r.FormValue("open_registration") == "on"
  100. mul, err := strconv.Atoi(r.FormValue("min_username_len"))
  101. if err == nil {
  102. app.cfg.App.MinUsernameLen = mul
  103. }
  104. mb, err := strconv.Atoi(r.FormValue("max_blogs"))
  105. if err == nil {
  106. app.cfg.App.MaxBlogs = mb
  107. }
  108. app.cfg.App.Federation = r.FormValue("federation") == "on"
  109. app.cfg.App.PublicStats = r.FormValue("public_stats") == "on"
  110. app.cfg.App.Private = r.FormValue("private") == "on"
  111. m := "?cm=Configuration+saved."
  112. err = config.Save(app.cfg)
  113. if err != nil {
  114. m = "?cm=" + err.Error()
  115. }
  116. return impart.HTTPError{http.StatusFound, "/admin" + m + "#config"}
  117. }
  118. func updateAppStats() {
  119. sysStatus.Uptime = tool.TimeSincePro(appStartTime)
  120. m := new(runtime.MemStats)
  121. runtime.ReadMemStats(m)
  122. sysStatus.NumGoroutine = runtime.NumGoroutine()
  123. sysStatus.MemAllocated = tool.FileSize(int64(m.Alloc))
  124. sysStatus.MemTotal = tool.FileSize(int64(m.TotalAlloc))
  125. sysStatus.MemSys = tool.FileSize(int64(m.Sys))
  126. sysStatus.Lookups = m.Lookups
  127. sysStatus.MemMallocs = m.Mallocs
  128. sysStatus.MemFrees = m.Frees
  129. sysStatus.HeapAlloc = tool.FileSize(int64(m.HeapAlloc))
  130. sysStatus.HeapSys = tool.FileSize(int64(m.HeapSys))
  131. sysStatus.HeapIdle = tool.FileSize(int64(m.HeapIdle))
  132. sysStatus.HeapInuse = tool.FileSize(int64(m.HeapInuse))
  133. sysStatus.HeapReleased = tool.FileSize(int64(m.HeapReleased))
  134. sysStatus.HeapObjects = m.HeapObjects
  135. sysStatus.StackInuse = tool.FileSize(int64(m.StackInuse))
  136. sysStatus.StackSys = tool.FileSize(int64(m.StackSys))
  137. sysStatus.MSpanInuse = tool.FileSize(int64(m.MSpanInuse))
  138. sysStatus.MSpanSys = tool.FileSize(int64(m.MSpanSys))
  139. sysStatus.MCacheInuse = tool.FileSize(int64(m.MCacheInuse))
  140. sysStatus.MCacheSys = tool.FileSize(int64(m.MCacheSys))
  141. sysStatus.BuckHashSys = tool.FileSize(int64(m.BuckHashSys))
  142. sysStatus.GCSys = tool.FileSize(int64(m.GCSys))
  143. sysStatus.OtherSys = tool.FileSize(int64(m.OtherSys))
  144. sysStatus.NextGC = tool.FileSize(int64(m.NextGC))
  145. sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000)
  146. sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000)
  147. sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000)
  148. sysStatus.NumGC = m.NumGC
  149. }
  150. func adminResetPassword(app *app, u *User, newPass string) error {
  151. hashedPass, err := auth.HashPass([]byte(newPass))
  152. if err != nil {
  153. return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not create password hash: %v", err)}
  154. }
  155. err = app.db.ChangePassphrase(u.ID, true, "", hashedPass)
  156. if err != nil {
  157. return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not update passphrase: %v", err)}
  158. }
  159. return nil
  160. }