system.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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.SystemSettingOpenAIAPIKeyName {
  55. continue
  56. }
  57. var value interface{}
  58. err := json.Unmarshal([]byte(systemSetting.Value), &value)
  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 = value.(bool)
  64. } else if systemSetting.Name == api.SystemSettingDisablePublicMemosName {
  65. systemStatus.DisablePublicMemos = value.(bool)
  66. } else if systemSetting.Name == api.SystemSettingAdditionalStyleName {
  67. systemStatus.AdditionalStyle = value.(string)
  68. } else if systemSetting.Name == api.SystemSettingAdditionalScriptName {
  69. systemStatus.AdditionalScript = value.(string)
  70. } else if systemSetting.Name == api.SystemSettingCustomizedProfileName {
  71. valueMap := value.(map[string]interface{})
  72. systemStatus.CustomizedProfile = api.CustomizedProfile{}
  73. if v := valueMap["name"]; v != nil {
  74. systemStatus.CustomizedProfile.Name = v.(string)
  75. }
  76. if v := valueMap["logoUrl"]; v != nil {
  77. systemStatus.CustomizedProfile.LogoURL = v.(string)
  78. }
  79. if v := valueMap["description"]; v != nil {
  80. systemStatus.CustomizedProfile.Description = v.(string)
  81. }
  82. if v := valueMap["locale"]; v != nil {
  83. systemStatus.CustomizedProfile.Locale = v.(string)
  84. }
  85. if v := valueMap["appearance"]; v != nil {
  86. systemStatus.CustomizedProfile.Appearance = v.(string)
  87. }
  88. if v := valueMap["externalUrl"]; v != nil {
  89. systemStatus.CustomizedProfile.ExternalURL = v.(string)
  90. }
  91. } else if systemSetting.Name == api.SystemSettingStorageServiceIDName {
  92. systemStatus.StorageServiceID = int(value.(float64))
  93. }
  94. }
  95. userID, ok := c.Get(getUserIDContextKey()).(int)
  96. // Get database size for host user.
  97. if ok {
  98. user, err := s.Store.FindUser(ctx, &api.UserFind{
  99. ID: &userID,
  100. })
  101. if err != nil {
  102. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  103. }
  104. if user != nil && user.Role == api.Host {
  105. fi, err := os.Stat(s.Profile.DSN)
  106. if err != nil {
  107. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to read database fileinfo").SetInternal(err)
  108. }
  109. systemStatus.DBSize = fi.Size()
  110. }
  111. }
  112. return c.JSON(http.StatusOK, composeResponse(systemStatus))
  113. })
  114. g.POST("/system/setting", func(c echo.Context) error {
  115. ctx := c.Request().Context()
  116. userID, ok := c.Get(getUserIDContextKey()).(int)
  117. if !ok {
  118. return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
  119. }
  120. user, err := s.Store.FindUser(ctx, &api.UserFind{
  121. ID: &userID,
  122. })
  123. if err != nil {
  124. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  125. }
  126. if user == nil || user.Role != api.Host {
  127. return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
  128. }
  129. systemSettingUpsert := &api.SystemSettingUpsert{}
  130. if err := json.NewDecoder(c.Request().Body).Decode(systemSettingUpsert); err != nil {
  131. return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post system setting request").SetInternal(err)
  132. }
  133. if err := systemSettingUpsert.Validate(); err != nil {
  134. return echo.NewHTTPError(http.StatusBadRequest, "system setting invalidate").SetInternal(err)
  135. }
  136. systemSetting, err := s.Store.UpsertSystemSetting(ctx, systemSettingUpsert)
  137. if err != nil {
  138. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upsert system setting").SetInternal(err)
  139. }
  140. return c.JSON(http.StatusOK, composeResponse(systemSetting))
  141. })
  142. g.GET("/system/setting", func(c echo.Context) error {
  143. ctx := c.Request().Context()
  144. userID, ok := c.Get(getUserIDContextKey()).(int)
  145. if !ok {
  146. return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
  147. }
  148. user, err := s.Store.FindUser(ctx, &api.UserFind{
  149. ID: &userID,
  150. })
  151. if err != nil {
  152. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  153. }
  154. if user == nil || user.Role != api.Host {
  155. return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
  156. }
  157. systemSettingList, err := s.Store.FindSystemSettingList(ctx, &api.SystemSettingFind{})
  158. if err != nil {
  159. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
  160. }
  161. return c.JSON(http.StatusOK, composeResponse(systemSettingList))
  162. })
  163. g.POST("/system/vacuum", func(c echo.Context) error {
  164. ctx := c.Request().Context()
  165. userID, ok := c.Get(getUserIDContextKey()).(int)
  166. if !ok {
  167. return echo.NewHTTPError(http.StatusUnauthorized, "Missing user in session")
  168. }
  169. user, err := s.Store.FindUser(ctx, &api.UserFind{
  170. ID: &userID,
  171. })
  172. if err != nil {
  173. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user").SetInternal(err)
  174. }
  175. if user == nil || user.Role != api.Host {
  176. return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
  177. }
  178. if err := s.Store.Vacuum(ctx); err != nil {
  179. return echo.NewHTTPError(http.StatusInternalServerError, "Failed to vacuum database").SetInternal(err)
  180. }
  181. return c.JSON(http.StatusOK, true)
  182. })
  183. }
  184. func (s *Server) getSystemServerID(ctx context.Context) (string, error) {
  185. serverIDValue, err := s.Store.FindSystemSetting(ctx, &api.SystemSettingFind{
  186. Name: api.SystemSettingServerID,
  187. })
  188. if err != nil && common.ErrorCode(err) != common.NotFound {
  189. return "", err
  190. }
  191. if serverIDValue == nil || serverIDValue.Value == "" {
  192. serverIDValue, err = s.Store.UpsertSystemSetting(ctx, &api.SystemSettingUpsert{
  193. Name: api.SystemSettingServerID,
  194. Value: uuid.NewString(),
  195. })
  196. if err != nil {
  197. return "", err
  198. }
  199. }
  200. return serverIDValue.Value, nil
  201. }
  202. func (s *Server) getSystemSecretSessionName(ctx context.Context) (string, error) {
  203. secretSessionNameValue, err := s.Store.FindSystemSetting(ctx, &api.SystemSettingFind{
  204. Name: api.SystemSettingSecretSessionName,
  205. })
  206. if err != nil && common.ErrorCode(err) != common.NotFound {
  207. return "", err
  208. }
  209. if secretSessionNameValue == nil || secretSessionNameValue.Value == "" {
  210. secretSessionNameValue, err = s.Store.UpsertSystemSetting(ctx, &api.SystemSettingUpsert{
  211. Name: api.SystemSettingSecretSessionName,
  212. Value: uuid.NewString(),
  213. })
  214. if err != nil {
  215. return "", err
  216. }
  217. }
  218. return secretSessionNameValue.Value, nil
  219. }