github.com/wgh-/mattermost-server@v4.8.0-rc2+incompatible/api4/system.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package api4 5 6 import ( 7 "bytes" 8 "io" 9 "net/http" 10 "runtime" 11 "strconv" 12 13 l4g "github.com/alecthomas/log4go" 14 "github.com/mattermost/mattermost-server/model" 15 "github.com/mattermost/mattermost-server/utils" 16 ) 17 18 func (api *API) InitSystem() { 19 api.BaseRoutes.System.Handle("/ping", api.ApiHandler(getSystemPing)).Methods("GET") 20 21 api.BaseRoutes.ApiRoot.Handle("/config", api.ApiSessionRequired(getConfig)).Methods("GET") 22 api.BaseRoutes.ApiRoot.Handle("/config", api.ApiSessionRequired(updateConfig)).Methods("PUT") 23 api.BaseRoutes.ApiRoot.Handle("/config/reload", api.ApiSessionRequired(configReload)).Methods("POST") 24 api.BaseRoutes.ApiRoot.Handle("/config/client", api.ApiHandler(getClientConfig)).Methods("GET") 25 26 api.BaseRoutes.ApiRoot.Handle("/license", api.ApiSessionRequired(addLicense)).Methods("POST") 27 api.BaseRoutes.ApiRoot.Handle("/license", api.ApiSessionRequired(removeLicense)).Methods("DELETE") 28 api.BaseRoutes.ApiRoot.Handle("/license/client", api.ApiHandler(getClientLicense)).Methods("GET") 29 30 api.BaseRoutes.ApiRoot.Handle("/audits", api.ApiSessionRequired(getAudits)).Methods("GET") 31 api.BaseRoutes.ApiRoot.Handle("/email/test", api.ApiSessionRequired(testEmail)).Methods("POST") 32 api.BaseRoutes.ApiRoot.Handle("/database/recycle", api.ApiSessionRequired(databaseRecycle)).Methods("POST") 33 api.BaseRoutes.ApiRoot.Handle("/caches/invalidate", api.ApiSessionRequired(invalidateCaches)).Methods("POST") 34 35 api.BaseRoutes.ApiRoot.Handle("/logs", api.ApiSessionRequired(getLogs)).Methods("GET") 36 api.BaseRoutes.ApiRoot.Handle("/logs", api.ApiHandler(postLog)).Methods("POST") 37 38 api.BaseRoutes.ApiRoot.Handle("/analytics/old", api.ApiSessionRequired(getAnalytics)).Methods("GET") 39 } 40 41 func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) { 42 43 actualGoroutines := runtime.NumGoroutine() 44 if *c.App.Config().ServiceSettings.GoroutineHealthThreshold <= 0 || actualGoroutines <= *c.App.Config().ServiceSettings.GoroutineHealthThreshold { 45 m := make(map[string]string) 46 m[model.STATUS] = model.STATUS_OK 47 48 reqs := c.App.Config().ClientRequirements 49 m["AndroidLatestVersion"] = reqs.AndroidLatestVersion 50 m["AndroidMinVersion"] = reqs.AndroidMinVersion 51 m["DesktopLatestVersion"] = reqs.DesktopLatestVersion 52 m["DesktopMinVersion"] = reqs.DesktopMinVersion 53 m["IosLatestVersion"] = reqs.IosLatestVersion 54 m["IosMinVersion"] = reqs.IosMinVersion 55 56 w.Write([]byte(model.MapToJson(m))) 57 } else { 58 rdata := map[string]string{} 59 rdata["status"] = "unhealthy" 60 61 l4g.Warn(utils.T("api.system.go_routines"), actualGoroutines, *c.App.Config().ServiceSettings.GoroutineHealthThreshold) 62 63 w.WriteHeader(http.StatusInternalServerError) 64 w.Write([]byte(model.MapToJson(rdata))) 65 } 66 } 67 68 func testEmail(c *Context, w http.ResponseWriter, r *http.Request) { 69 cfg := model.ConfigFromJson(r.Body) 70 if cfg == nil { 71 cfg = c.App.Config() 72 } 73 74 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 75 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 76 return 77 } 78 79 err := c.App.TestEmail(c.Session.UserId, cfg) 80 if err != nil { 81 c.Err = err 82 return 83 } 84 85 ReturnStatusOK(w) 86 } 87 88 func getConfig(c *Context, w http.ResponseWriter, r *http.Request) { 89 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 90 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 91 return 92 } 93 94 cfg := c.App.GetConfig() 95 96 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 97 w.Write([]byte(cfg.ToJson())) 98 } 99 100 func configReload(c *Context, w http.ResponseWriter, r *http.Request) { 101 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 102 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 103 return 104 } 105 106 c.App.ReloadConfig() 107 108 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 109 ReturnStatusOK(w) 110 } 111 112 func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) { 113 cfg := model.ConfigFromJson(r.Body) 114 if cfg == nil { 115 c.SetInvalidParam("config") 116 return 117 } 118 119 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 120 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 121 return 122 } 123 124 // Do not allow plugin uploads to be toggled through the API 125 cfg.PluginSettings.EnableUploads = c.App.GetConfig().PluginSettings.EnableUploads 126 127 err := c.App.SaveConfig(cfg, true) 128 if err != nil { 129 c.Err = err 130 return 131 } 132 133 c.LogAudit("updateConfig") 134 135 cfg = c.App.GetConfig() 136 137 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 138 w.Write([]byte(cfg.ToJson())) 139 } 140 141 func getAudits(c *Context, w http.ResponseWriter, r *http.Request) { 142 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 143 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 144 return 145 } 146 147 audits, err := c.App.GetAuditsPage("", c.Params.Page, c.Params.PerPage) 148 149 if err != nil { 150 c.Err = err 151 return 152 } 153 154 w.Write([]byte(audits.ToJson())) 155 } 156 157 func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) { 158 159 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 160 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 161 return 162 } 163 164 c.App.RecycleDatabaseConnection() 165 166 ReturnStatusOK(w) 167 } 168 169 func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) { 170 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 171 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 172 return 173 } 174 175 err := c.App.InvalidateAllCaches() 176 if err != nil { 177 c.Err = err 178 return 179 } 180 181 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 182 ReturnStatusOK(w) 183 } 184 185 func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { 186 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 187 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 188 return 189 } 190 191 lines, err := c.App.GetLogs(c.Params.Page, c.Params.LogsPerPage) 192 if err != nil { 193 c.Err = err 194 return 195 } 196 197 w.Write([]byte(model.ArrayToJson(lines))) 198 } 199 200 func postLog(c *Context, w http.ResponseWriter, r *http.Request) { 201 forceToDebug := false 202 203 if !*c.App.Config().ServiceSettings.EnableDeveloper { 204 if c.Session.UserId == "" { 205 c.Err = model.NewAppError("postLog", "api.context.permissions.app_error", nil, "", http.StatusForbidden) 206 return 207 } 208 209 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 210 forceToDebug = true 211 } 212 } 213 214 m := model.MapFromJson(r.Body) 215 lvl := m["level"] 216 msg := m["message"] 217 218 if len(msg) > 400 { 219 msg = msg[0:399] 220 } 221 222 if !forceToDebug && lvl == "ERROR" { 223 err := &model.AppError{} 224 err.Message = msg 225 err.Id = msg 226 err.Where = "client" 227 c.LogError(err) 228 } else { 229 l4g.Debug(msg) 230 } 231 232 m["message"] = msg 233 w.Write([]byte(model.MapToJson(m))) 234 } 235 236 func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) { 237 format := r.URL.Query().Get("format") 238 239 if format == "" { 240 c.Err = model.NewAppError("getClientConfig", "api.config.client.old_format.app_error", nil, "", http.StatusNotImplemented) 241 return 242 } 243 244 if format != "old" { 245 c.SetInvalidParam("format") 246 return 247 } 248 249 respCfg := map[string]string{} 250 for k, v := range c.App.ClientConfig() { 251 respCfg[k] = v 252 } 253 254 respCfg["NoAccounts"] = strconv.FormatBool(c.App.IsFirstUserAccount()) 255 256 w.Write([]byte(model.MapToJson(respCfg))) 257 } 258 259 func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) { 260 format := r.URL.Query().Get("format") 261 262 if format == "" { 263 c.Err = model.NewAppError("getClientLicense", "api.license.client.old_format.app_error", nil, "", http.StatusNotImplemented) 264 return 265 } 266 267 if format != "old" { 268 c.SetInvalidParam("format") 269 return 270 } 271 272 etag := c.App.GetClientLicenseEtag(true) 273 if c.HandleEtag(etag, "Get Client License", w, r) { 274 return 275 } 276 277 var clientLicense map[string]string 278 279 if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 280 clientLicense = c.App.ClientLicense() 281 } else { 282 clientLicense = c.App.GetSanitizedClientLicense() 283 } 284 285 w.Header().Set(model.HEADER_ETAG_SERVER, etag) 286 w.Write([]byte(model.MapToJson(clientLicense))) 287 } 288 289 func addLicense(c *Context, w http.ResponseWriter, r *http.Request) { 290 c.LogAudit("attempt") 291 292 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 293 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 294 return 295 } 296 297 err := r.ParseMultipartForm(*c.App.Config().FileSettings.MaxFileSize) 298 if err != nil { 299 http.Error(w, err.Error(), http.StatusBadRequest) 300 return 301 } 302 303 m := r.MultipartForm 304 305 fileArray, ok := m.File["license"] 306 if !ok { 307 c.Err = model.NewAppError("addLicense", "api.license.add_license.no_file.app_error", nil, "", http.StatusBadRequest) 308 return 309 } 310 311 if len(fileArray) <= 0 { 312 c.Err = model.NewAppError("addLicense", "api.license.add_license.array.app_error", nil, "", http.StatusBadRequest) 313 return 314 } 315 316 fileData := fileArray[0] 317 318 file, err := fileData.Open() 319 if err != nil { 320 c.Err = model.NewAppError("addLicense", "api.license.add_license.open.app_error", nil, err.Error(), http.StatusBadRequest) 321 return 322 } 323 defer file.Close() 324 325 buf := bytes.NewBuffer(nil) 326 io.Copy(buf, file) 327 328 if license, err := c.App.SaveLicense(buf.Bytes()); err != nil { 329 if err.Id == model.EXPIRED_LICENSE_ERROR { 330 c.LogAudit("failed - expired or non-started license") 331 } else if err.Id == model.INVALID_LICENSE_ERROR { 332 c.LogAudit("failed - invalid license") 333 } else { 334 c.LogAudit("failed - unable to save license") 335 } 336 c.Err = err 337 return 338 } else { 339 c.LogAudit("success") 340 w.Write([]byte(license.ToJson())) 341 } 342 } 343 344 func removeLicense(c *Context, w http.ResponseWriter, r *http.Request) { 345 c.LogAudit("attempt") 346 347 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 348 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 349 return 350 } 351 352 if err := c.App.RemoveLicense(); err != nil { 353 c.Err = err 354 return 355 } 356 357 c.LogAudit("success") 358 ReturnStatusOK(w) 359 } 360 361 func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { 362 name := r.URL.Query().Get("name") 363 teamId := r.URL.Query().Get("team_id") 364 365 if name == "" { 366 name = "standard" 367 } 368 369 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 370 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 371 return 372 } 373 374 rows, err := c.App.GetAnalytics(name, teamId) 375 if err != nil { 376 c.Err = err 377 return 378 } 379 380 if rows == nil { 381 c.SetInvalidParam("name") 382 return 383 } 384 385 w.Write([]byte(rows.ToJson())) 386 }