github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+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 err := c.App.SaveConfig(cfg, true) 125 if err != nil { 126 c.Err = err 127 return 128 } 129 130 c.LogAudit("updateConfig") 131 132 cfg = c.App.GetConfig() 133 134 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 135 w.Write([]byte(cfg.ToJson())) 136 } 137 138 func getAudits(c *Context, w http.ResponseWriter, r *http.Request) { 139 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 140 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 141 return 142 } 143 144 audits, err := c.App.GetAuditsPage("", c.Params.Page, c.Params.PerPage) 145 146 if err != nil { 147 c.Err = err 148 return 149 } 150 151 w.Write([]byte(audits.ToJson())) 152 } 153 154 func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) { 155 156 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 157 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 158 return 159 } 160 161 c.App.RecycleDatabaseConnection() 162 163 ReturnStatusOK(w) 164 } 165 166 func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) { 167 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 168 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 169 return 170 } 171 172 err := c.App.InvalidateAllCaches() 173 if err != nil { 174 c.Err = err 175 return 176 } 177 178 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 179 ReturnStatusOK(w) 180 } 181 182 func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { 183 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 184 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 185 return 186 } 187 188 lines, err := c.App.GetLogs(c.Params.Page, c.Params.LogsPerPage) 189 if err != nil { 190 c.Err = err 191 return 192 } 193 194 w.Write([]byte(model.ArrayToJson(lines))) 195 } 196 197 func postLog(c *Context, w http.ResponseWriter, r *http.Request) { 198 forceToDebug := false 199 200 if !*c.App.Config().ServiceSettings.EnableDeveloper { 201 if c.Session.UserId == "" { 202 c.Err = model.NewAppError("postLog", "api.context.permissions.app_error", nil, "", http.StatusForbidden) 203 return 204 } 205 206 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 207 forceToDebug = true 208 } 209 } 210 211 m := model.MapFromJson(r.Body) 212 lvl := m["level"] 213 msg := m["message"] 214 215 if len(msg) > 400 { 216 msg = msg[0:399] 217 } 218 219 if !forceToDebug && lvl == "ERROR" { 220 err := &model.AppError{} 221 err.Message = msg 222 err.Id = msg 223 err.Where = "client" 224 c.LogError(err) 225 } else { 226 l4g.Debug(msg) 227 } 228 229 m["message"] = msg 230 w.Write([]byte(model.MapToJson(m))) 231 } 232 233 func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) { 234 format := r.URL.Query().Get("format") 235 236 if format == "" { 237 c.Err = model.NewAppError("getClientConfig", "api.config.client.old_format.app_error", nil, "", http.StatusNotImplemented) 238 return 239 } 240 241 if format != "old" { 242 c.SetInvalidParam("format") 243 return 244 } 245 246 respCfg := map[string]string{} 247 for k, v := range c.App.ClientConfig() { 248 respCfg[k] = v 249 } 250 251 respCfg["NoAccounts"] = strconv.FormatBool(c.App.IsFirstUserAccount()) 252 253 w.Write([]byte(model.MapToJson(respCfg))) 254 } 255 256 func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) { 257 format := r.URL.Query().Get("format") 258 259 if format == "" { 260 c.Err = model.NewAppError("getClientLicense", "api.license.client.old_format.app_error", nil, "", http.StatusNotImplemented) 261 return 262 } 263 264 if format != "old" { 265 c.SetInvalidParam("format") 266 return 267 } 268 269 etag := utils.GetClientLicenseEtag(true) 270 if c.HandleEtag(etag, "Get Client License", w, r) { 271 return 272 } 273 274 var clientLicense map[string]string 275 276 if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 277 clientLicense = utils.ClientLicense() 278 } else { 279 clientLicense = utils.GetSanitizedClientLicense() 280 } 281 282 w.Header().Set(model.HEADER_ETAG_SERVER, etag) 283 w.Write([]byte(model.MapToJson(clientLicense))) 284 } 285 286 func addLicense(c *Context, w http.ResponseWriter, r *http.Request) { 287 c.LogAudit("attempt") 288 289 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 290 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 291 return 292 } 293 294 err := r.ParseMultipartForm(*c.App.Config().FileSettings.MaxFileSize) 295 if err != nil { 296 http.Error(w, err.Error(), http.StatusBadRequest) 297 return 298 } 299 300 m := r.MultipartForm 301 302 fileArray, ok := m.File["license"] 303 if !ok { 304 c.Err = model.NewAppError("addLicense", "api.license.add_license.no_file.app_error", nil, "", http.StatusBadRequest) 305 return 306 } 307 308 if len(fileArray) <= 0 { 309 c.Err = model.NewAppError("addLicense", "api.license.add_license.array.app_error", nil, "", http.StatusBadRequest) 310 return 311 } 312 313 fileData := fileArray[0] 314 315 file, err := fileData.Open() 316 if err != nil { 317 c.Err = model.NewAppError("addLicense", "api.license.add_license.open.app_error", nil, err.Error(), http.StatusBadRequest) 318 return 319 } 320 defer file.Close() 321 322 buf := bytes.NewBuffer(nil) 323 io.Copy(buf, file) 324 325 if license, err := c.App.SaveLicense(buf.Bytes()); err != nil { 326 if err.Id == model.EXPIRED_LICENSE_ERROR { 327 c.LogAudit("failed - expired or non-started license") 328 } else if err.Id == model.INVALID_LICENSE_ERROR { 329 c.LogAudit("failed - invalid license") 330 } else { 331 c.LogAudit("failed - unable to save license") 332 } 333 c.Err = err 334 return 335 } else { 336 c.LogAudit("success") 337 w.Write([]byte(license.ToJson())) 338 } 339 } 340 341 func removeLicense(c *Context, w http.ResponseWriter, r *http.Request) { 342 c.LogAudit("attempt") 343 344 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 345 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 346 return 347 } 348 349 if err := c.App.RemoveLicense(); err != nil { 350 c.Err = err 351 return 352 } 353 354 c.LogAudit("success") 355 ReturnStatusOK(w) 356 } 357 358 func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { 359 name := r.URL.Query().Get("name") 360 teamId := r.URL.Query().Get("team_id") 361 362 if name == "" { 363 name = "standard" 364 } 365 366 if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { 367 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 368 return 369 } 370 371 rows, err := c.App.GetAnalytics(name, teamId) 372 if err != nil { 373 c.Err = err 374 return 375 } 376 377 if rows == nil { 378 c.SetInvalidParam("name") 379 return 380 } 381 382 w.Write([]byte(rows.ToJson())) 383 }