github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+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 12 l4g "github.com/alecthomas/log4go" 13 "github.com/mattermost/mattermost-server/model" 14 "github.com/mattermost/mattermost-server/utils" 15 ) 16 17 func (api *API) InitSystem() { 18 api.BaseRoutes.System.Handle("/ping", api.ApiHandler(getSystemPing)).Methods("GET") 19 20 api.BaseRoutes.ApiRoot.Handle("/config", api.ApiSessionRequired(getConfig)).Methods("GET") 21 api.BaseRoutes.ApiRoot.Handle("/config", api.ApiSessionRequired(updateConfig)).Methods("PUT") 22 api.BaseRoutes.ApiRoot.Handle("/config/reload", api.ApiSessionRequired(configReload)).Methods("POST") 23 api.BaseRoutes.ApiRoot.Handle("/config/client", api.ApiHandler(getClientConfig)).Methods("GET") 24 25 api.BaseRoutes.ApiRoot.Handle("/license", api.ApiSessionRequired(addLicense)).Methods("POST") 26 api.BaseRoutes.ApiRoot.Handle("/license", api.ApiSessionRequired(removeLicense)).Methods("DELETE") 27 api.BaseRoutes.ApiRoot.Handle("/license/client", api.ApiHandler(getClientLicense)).Methods("GET") 28 29 api.BaseRoutes.ApiRoot.Handle("/audits", api.ApiSessionRequired(getAudits)).Methods("GET") 30 api.BaseRoutes.ApiRoot.Handle("/email/test", api.ApiSessionRequired(testEmail)).Methods("POST") 31 api.BaseRoutes.ApiRoot.Handle("/file/s3_test", api.ApiSessionRequired(testS3)).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 w.Write([]byte(model.MapToJson(c.App.ClientConfigWithNoAccounts()))) 250 } 251 252 func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) { 253 format := r.URL.Query().Get("format") 254 255 if format == "" { 256 c.Err = model.NewAppError("getClientLicense", "api.license.client.old_format.app_error", nil, "", http.StatusNotImplemented) 257 return 258 } 259 260 if format != "old" { 261 c.SetInvalidParam("format") 262 return 263 } 264 265 etag := c.App.GetClientLicenseEtag(true) 266 if c.HandleEtag(etag, "Get Client License", w, r) { 267 return 268 } 269 270 var clientLicense map[string]string 271 272 if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 273 clientLicense = c.App.ClientLicense() 274 } else { 275 clientLicense = c.App.GetSanitizedClientLicense() 276 } 277 278 w.Header().Set(model.HEADER_ETAG_SERVER, etag) 279 w.Write([]byte(model.MapToJson(clientLicense))) 280 } 281 282 func addLicense(c *Context, w http.ResponseWriter, r *http.Request) { 283 c.LogAudit("attempt") 284 285 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 286 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 287 return 288 } 289 290 err := r.ParseMultipartForm(*c.App.Config().FileSettings.MaxFileSize) 291 if err != nil { 292 http.Error(w, err.Error(), http.StatusBadRequest) 293 return 294 } 295 296 m := r.MultipartForm 297 298 fileArray, ok := m.File["license"] 299 if !ok { 300 c.Err = model.NewAppError("addLicense", "api.license.add_license.no_file.app_error", nil, "", http.StatusBadRequest) 301 return 302 } 303 304 if len(fileArray) <= 0 { 305 c.Err = model.NewAppError("addLicense", "api.license.add_license.array.app_error", nil, "", http.StatusBadRequest) 306 return 307 } 308 309 fileData := fileArray[0] 310 311 file, err := fileData.Open() 312 if err != nil { 313 c.Err = model.NewAppError("addLicense", "api.license.add_license.open.app_error", nil, err.Error(), http.StatusBadRequest) 314 return 315 } 316 defer file.Close() 317 318 buf := bytes.NewBuffer(nil) 319 io.Copy(buf, file) 320 321 if license, err := c.App.SaveLicense(buf.Bytes()); err != nil { 322 if err.Id == model.EXPIRED_LICENSE_ERROR { 323 c.LogAudit("failed - expired or non-started license") 324 } else if err.Id == model.INVALID_LICENSE_ERROR { 325 c.LogAudit("failed - invalid license") 326 } else { 327 c.LogAudit("failed - unable to save license") 328 } 329 c.Err = err 330 return 331 } else { 332 c.LogAudit("success") 333 w.Write([]byte(license.ToJson())) 334 } 335 } 336 337 func removeLicense(c *Context, w http.ResponseWriter, r *http.Request) { 338 c.LogAudit("attempt") 339 340 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 341 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 342 return 343 } 344 345 if err := c.App.RemoveLicense(); err != nil { 346 c.Err = err 347 return 348 } 349 350 c.LogAudit("success") 351 ReturnStatusOK(w) 352 } 353 354 func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { 355 name := r.URL.Query().Get("name") 356 teamId := r.URL.Query().Get("team_id") 357 358 if name == "" { 359 name = "standard" 360 } 361 362 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 363 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 364 return 365 } 366 367 rows, err := c.App.GetAnalytics(name, teamId) 368 if err != nil { 369 c.Err = err 370 return 371 } 372 373 if rows == nil { 374 c.SetInvalidParam("name") 375 return 376 } 377 378 w.Write([]byte(rows.ToJson())) 379 } 380 381 func testS3(c *Context, w http.ResponseWriter, r *http.Request) { 382 cfg := model.ConfigFromJson(r.Body) 383 if cfg == nil { 384 cfg = c.App.Config() 385 } 386 387 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 388 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 389 return 390 } 391 392 err := utils.CheckMandatoryS3Fields(&cfg.FileSettings) 393 if err != nil { 394 c.Err = err 395 return 396 } 397 398 if cfg.FileSettings.AmazonS3SecretAccessKey == model.FAKE_SETTING { 399 cfg.FileSettings.AmazonS3SecretAccessKey = c.App.Config().FileSettings.AmazonS3SecretAccessKey 400 } 401 402 license := c.App.License() 403 backend, appErr := utils.NewFileBackend(&cfg.FileSettings, license != nil && *license.Features.Compliance) 404 if appErr == nil { 405 appErr = backend.TestConnection() 406 } 407 if appErr != nil { 408 c.Err = appErr 409 return 410 } 411 412 ReturnStatusOK(w) 413 }