system.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package server
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "os"
  6. "github.com/usememos/memos/api"
  7. "github.com/usememos/memos/common"
  8. metric "github.com/usememos/memos/plugin/metrics"
  9. "github.com/labstack/echo/v4"
  10. )
  11. func (s *Server) registerSystemRoutes(g *echo.Group) {
  12. g.GET("/ping", func(c echo.Context) error {
  13. data := s.Profile
  14. c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
  15. if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(data)); err != nil {
  16. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose system profile").SetInternal(err)
  17. }
  18. return nil
  19. })
  20. g.GET("/status", func(c echo.Context) error {
  21. ctx := c.Request().Context()
  22. hostUserType := api.Host
  23. hostUserFind := api.UserFind{
  24. Role: &hostUserType,
  25. }
  26. hostUser, err := s.Store.FindUser(ctx, &hostUserFind)
  27. if err != nil && common.ErrorCode(err) != common.NotFound {
  28. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
  29. }
  30. if hostUser != nil {
  31. // data desensitize
  32. hostUser.OpenID = ""
  33. hostUser.Email = ""
  34. }
  35. systemStatus := api.SystemStatus{
  36. Host: hostUser,
  37. Profile: *s.Profile,
  38. DBSize: 0,
  39. AllowSignUp: false,
  40. AdditionalStyle: "",
  41. AdditionalScript: "",
  42. CustomizedProfile: api.CustomizedProfile{
  43. Name: "memos",
  44. LogoURL: "",
  45. Description: "",
  46. Locale: "en",
  47. Appearance: "system",
  48. ExternalURL: "",
  49. },
  50. }
  51. systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
  52. if err != nil {
  53. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
  54. }
  55. for _, systemSetting := range systemSettingList {
  56. var value interface{}
  57. err := json.Unmarshal([]byte(systemSetting.Value), &value)
  58. if err != nil {
  59. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal system setting").SetInternal(err)
  60. }
  61. if systemSetting.Name == api.SystemSettingAllowSignUpName {
  62. systemStatus.AllowSignUp = value.(bool)
  63. } else if systemSetting.Name == api.SystemSettingAdditionalStyleName {
  64. systemStatus.AdditionalStyle = value.(string)
  65. } else if systemSetting.Name == api.SystemSettingAdditionalScriptName {
  66. systemStatus.AdditionalScript = value.(string)
  67. } else if systemSetting.Name == api.SystemSettingCustomizedProfileName {
  68. valueMap := value.(map[string]interface{})
  69. systemStatus.CustomizedProfile = api.CustomizedProfile{}
  70. if v := valueMap["name"]; v != nil {
  71. systemStatus.CustomizedProfile.Name = v.(string)
  72. }
  73. if v := valueMap["logoUrl"]; v != nil {
  74. systemStatus.CustomizedProfile.LogoURL = v.(string)
  75. }
  76. if v := valueMap["description"]; v != nil {
  77. systemStatus.CustomizedProfile.Description = v.(string)
  78. }
  79. if v := valueMap["locale"]; v != nil {
  80. systemStatus.CustomizedProfile.Locale = v.(string)
  81. }
  82. if v := valueMap["appearance"]; v != nil {
  83. systemStatus.CustomizedProfile.Appearance = v.(string)
  84. }
  85. if v := valueMap["externalUrl"]; v != nil {
  86. systemStatus.CustomizedProfile.ExternalURL = v.(string)
  87. }
  88. }
  89. }
  90. userID, ok := c.Get(getUserIDContextKey()).(int)
  91. // Get database size for host user.
  92. if ok {
  93. user, err := s.Store.FindUser(ctx, &api.UserFind{
  94. ID: &userID,
  95. })
  96. if err != nil {
  97. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  98. }
  99. if user != nil && user.Role == api.Host {
  100. fi, err := os.Stat(s.Profile.DSN)
  101. if err != nil {
  102. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to read database fileinfo").SetInternal(err)
  103. }
  104. systemStatus.DBSize = fi.Size()
  105. }
  106. }
  107. c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
  108. if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemStatus)); err != nil {
  109. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system status response").SetInternal(err)
  110. }
  111. return nil
  112. })
  113. g.POST("/system/setting", func(c echo.Context) error {
  114. ctx := c.Request().Context()
  115. userID, ok := c.Get(getUserIDContextKey()).(int)
  116. if !ok {
  117. return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
  118. }
  119. user, err := s.Store.FindUser(ctx, &api.UserFind{
  120. ID: &userID,
  121. })
  122. if err != nil {
  123. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  124. }
  125. if user == nil || user.Role != api.Host {
  126. return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
  127. }
  128. systemSettingUpsert := &api.SystemSettingUpsert{}
  129. if err := json.NewDecoder(c.Request().Body).Decode(systemSettingUpsert); err != nil {
  130. return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post system setting request").SetInternal(err)
  131. }
  132. if err := systemSettingUpsert.Validate(); err != nil {
  133. return echo.NewHTTPError(http.StatusBadRequest, "system setting invalidate").SetInternal(err)
  134. }
  135. systemSetting, err := s.Store.UpsertSystemSetting(ctx, systemSettingUpsert)
  136. if err != nil {
  137. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert system setting").SetInternal(err)
  138. }
  139. s.Collector.Collect(ctx, &metric.Metric{
  140. Name: "systemSetting updated",
  141. Labels: map[string]string{"field": string(systemSettingUpsert.Name)},
  142. })
  143. c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
  144. if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSetting)); err != nil {
  145. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting response").SetInternal(err)
  146. }
  147. return nil
  148. })
  149. g.GET("/system/setting", func(c echo.Context) error {
  150. ctx := c.Request().Context()
  151. systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
  152. if err != nil {
  153. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
  154. }
  155. c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
  156. if err := json.NewEncoder(c.Response().Writer).Encode(composeResponse(systemSettingList)); err != nil {
  157. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to encode system setting list response").SetInternal(err)
  158. }
  159. return nil
  160. })
  161. g.POST("/system/vacuum", func(c echo.Context) error {
  162. ctx := c.Request().Context()
  163. userID, ok := c.Get(getUserIDContextKey()).(int)
  164. if !ok {
  165. return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
  166. }
  167. user, err := s.Store.FindUser(ctx, &api.UserFind{
  168. ID: &userID,
  169. })
  170. if err != nil {
  171. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  172. }
  173. if user == nil || user.Role != api.Host {
  174. return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
  175. }
  176. if err := s.Store.Vacuum(ctx); err != nil {
  177. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
  178. }
  179. c.Response().WriteHeader(http.StatusOK)
  180. return nil
  181. })
  182. }