system.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package v1
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/labstack/echo/v4"
  6. "github.com/usememos/memos/common/log"
  7. "github.com/usememos/memos/server/profile"
  8. "github.com/usememos/memos/store"
  9. "go.uber.org/zap"
  10. )
  11. type SystemStatus struct {
  12. Host *User `json:"host"`
  13. Profile profile.Profile `json:"profile"`
  14. DBSize int64 `json:"dbSize"`
  15. // System settings
  16. // Allow sign up.
  17. AllowSignUp bool `json:"allowSignUp"`
  18. // Disable public memos.
  19. DisablePublicMemos bool `json:"disablePublicMemos"`
  20. // Max upload size.
  21. MaxUploadSizeMiB int `json:"maxUploadSizeMiB"`
  22. // Additional style.
  23. AdditionalStyle string `json:"additionalStyle"`
  24. // Additional script.
  25. AdditionalScript string `json:"additionalScript"`
  26. // Customized server profile, including server name and external url.
  27. CustomizedProfile CustomizedProfile `json:"customizedProfile"`
  28. // Storage service ID.
  29. StorageServiceID int `json:"storageServiceId"`
  30. // Local storage path.
  31. LocalStoragePath string `json:"localStoragePath"`
  32. // Memo display with updated timestamp.
  33. MemoDisplayWithUpdatedTs bool `json:"memoDisplayWithUpdatedTs"`
  34. }
  35. func (s *APIV1Service) registerSystemRoutes(g *echo.Group) {
  36. g.GET("/ping", func(c echo.Context) error {
  37. return c.JSON(http.StatusOK, s.Profile)
  38. })
  39. g.GET("/status", func(c echo.Context) error {
  40. ctx := c.Request().Context()
  41. systemStatus := SystemStatus{
  42. Profile: *s.Profile,
  43. DBSize: 0,
  44. AllowSignUp: false,
  45. DisablePublicMemos: false,
  46. MaxUploadSizeMiB: 32,
  47. AdditionalStyle: "",
  48. AdditionalScript: "",
  49. CustomizedProfile: CustomizedProfile{
  50. Name: "memos",
  51. LogoURL: "",
  52. Description: "",
  53. Locale: "en",
  54. Appearance: "system",
  55. ExternalURL: "",
  56. },
  57. StorageServiceID: DatabaseStorage,
  58. LocalStoragePath: "assets/{timestamp}_{filename}",
  59. MemoDisplayWithUpdatedTs: false,
  60. }
  61. hostUserType := store.RoleHost
  62. hostUser, err := s.Store.GetUser(ctx, &store.FindUser{
  63. Role: &hostUserType,
  64. })
  65. if err != nil {
  66. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find host user").SetInternal(err)
  67. }
  68. if hostUser != nil {
  69. systemStatus.Host = convertUserFromStore(hostUser)
  70. // data desensitize
  71. systemStatus.Host.OpenID = ""
  72. systemStatus.Host.Email = ""
  73. systemStatus.Host.AvatarURL = ""
  74. }
  75. systemSettingList, err := s.Store.ListSystemSettings(ctx, &store.FindSystemSetting{})
  76. if err != nil {
  77. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
  78. }
  79. for _, systemSetting := range systemSettingList {
  80. if systemSetting.Name == SystemSettingServerIDName.String() || systemSetting.Name == SystemSettingSecretSessionName.String() || systemSetting.Name == SystemSettingTelegramBotTokenName.String() {
  81. continue
  82. }
  83. var baseValue any
  84. err := json.Unmarshal([]byte(systemSetting.Value), &baseValue)
  85. if err != nil {
  86. log.Warn("Failed to unmarshal system setting value", zap.String("setting name", systemSetting.Name))
  87. continue
  88. }
  89. switch systemSetting.Name {
  90. case SystemSettingAllowSignUpName.String():
  91. systemStatus.AllowSignUp = baseValue.(bool)
  92. case SystemSettingDisablePublicMemosName.String():
  93. systemStatus.DisablePublicMemos = baseValue.(bool)
  94. case SystemSettingMaxUploadSizeMiBName.String():
  95. systemStatus.MaxUploadSizeMiB = int(baseValue.(float64))
  96. case SystemSettingAdditionalStyleName.String():
  97. systemStatus.AdditionalStyle = baseValue.(string)
  98. case SystemSettingAdditionalScriptName.String():
  99. systemStatus.AdditionalScript = baseValue.(string)
  100. case SystemSettingCustomizedProfileName.String():
  101. customizedProfile := CustomizedProfile{}
  102. if err := json.Unmarshal([]byte(systemSetting.Value), &customizedProfile); err != nil {
  103. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal system setting customized profile value").SetInternal(err)
  104. }
  105. systemStatus.CustomizedProfile = customizedProfile
  106. case SystemSettingStorageServiceIDName.String():
  107. systemStatus.StorageServiceID = int(baseValue.(float64))
  108. case SystemSettingLocalStoragePathName.String():
  109. systemStatus.LocalStoragePath = baseValue.(string)
  110. case SystemSettingMemoDisplayWithUpdatedTsName.String():
  111. systemStatus.MemoDisplayWithUpdatedTs = baseValue.(bool)
  112. default:
  113. log.Warn("Unknown system setting name", zap.String("setting name", systemSetting.Name))
  114. }
  115. }
  116. return c.JSON(http.StatusOK, systemStatus)
  117. })
  118. g.POST("/system/vacuum", func(c echo.Context) error {
  119. ctx := c.Request().Context()
  120. userID, ok := c.Get(getUserIDContextKey()).(int)
  121. if !ok {
  122. return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
  123. }
  124. user, err := s.Store.GetUser(ctx, &store.FindUser{
  125. ID: &userID,
  126. })
  127. if err != nil {
  128. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  129. }
  130. if user == nil || user.Role != store.RoleHost {
  131. return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
  132. }
  133. if err := s.Store.Vacuum(ctx); err != nil {
  134. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
  135. }
  136. return c.JSON(http.StatusOK, true)
  137. })
  138. }