system.go 7.6 KB

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