github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/system.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package api4 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "fmt" 10 "io" 11 "io/ioutil" 12 "net/http" 13 "path" 14 "runtime" 15 "strconv" 16 "time" 17 18 "github.com/pkg/errors" 19 20 "github.com/masterhung0112/hk_server/v5/audit" 21 "github.com/masterhung0112/hk_server/v5/model" 22 "github.com/masterhung0112/hk_server/v5/services/cache" 23 "github.com/masterhung0112/hk_server/v5/services/upgrader" 24 "github.com/masterhung0112/hk_server/v5/shared/mlog" 25 ) 26 27 const ( 28 RedirectLocationCacheSize = 10000 29 DefaultServerBusySeconds = 3600 30 MaxServerBusySeconds = 86400 31 ) 32 33 var redirectLocationDataCache = cache.NewLRU(cache.LRUOptions{ 34 Size: RedirectLocationCacheSize, 35 }) 36 37 func (api *API) InitSystem() { 38 api.BaseRoutes.System.Handle("/ping", api.ApiHandler(getSystemPing)).Methods("GET") 39 40 api.BaseRoutes.System.Handle("/timezones", api.ApiSessionRequired(getSupportedTimezones)).Methods("GET") 41 42 api.BaseRoutes.ApiRoot.Handle("/audits", api.ApiSessionRequired(getAudits)).Methods("GET") 43 api.BaseRoutes.ApiRoot.Handle("/email/test", api.ApiSessionRequired(testEmail)).Methods("POST") 44 api.BaseRoutes.ApiRoot.Handle("/site_url/test", api.ApiSessionRequired(testSiteURL)).Methods("POST") 45 api.BaseRoutes.ApiRoot.Handle("/file/s3_test", api.ApiSessionRequired(testS3)).Methods("POST") 46 api.BaseRoutes.ApiRoot.Handle("/database/recycle", api.ApiSessionRequired(databaseRecycle)).Methods("POST") 47 api.BaseRoutes.ApiRoot.Handle("/caches/invalidate", api.ApiSessionRequired(invalidateCaches)).Methods("POST") 48 49 api.BaseRoutes.ApiRoot.Handle("/logs", api.ApiSessionRequired(getLogs)).Methods("GET") 50 api.BaseRoutes.ApiRoot.Handle("/logs", api.ApiHandler(postLog)).Methods("POST") 51 52 api.BaseRoutes.ApiRoot.Handle("/analytics/old", api.ApiSessionRequired(getAnalytics)).Methods("GET") 53 54 api.BaseRoutes.ApiRoot.Handle("/redirect_location", api.ApiSessionRequiredTrustRequester(getRedirectLocation)).Methods("GET") 55 56 api.BaseRoutes.ApiRoot.Handle("/notifications/ack", api.ApiSessionRequired(pushNotificationAck)).Methods("POST") 57 58 api.BaseRoutes.ApiRoot.Handle("/server_busy", api.ApiSessionRequired(setServerBusy)).Methods("POST") 59 api.BaseRoutes.ApiRoot.Handle("/server_busy", api.ApiSessionRequired(getServerBusyExpires)).Methods("GET") 60 api.BaseRoutes.ApiRoot.Handle("/server_busy", api.ApiSessionRequired(clearServerBusy)).Methods("DELETE") 61 api.BaseRoutes.ApiRoot.Handle("/upgrade_to_enterprise", api.ApiSessionRequired(upgradeToEnterprise)).Methods("POST") 62 api.BaseRoutes.ApiRoot.Handle("/upgrade_to_enterprise/status", api.ApiSessionRequired(upgradeToEnterpriseStatus)).Methods("GET") 63 api.BaseRoutes.ApiRoot.Handle("/restart", api.ApiSessionRequired(restart)).Methods("POST") 64 api.BaseRoutes.ApiRoot.Handle("/warn_metrics/status", api.ApiSessionRequired(getWarnMetricsStatus)).Methods("GET") 65 api.BaseRoutes.ApiRoot.Handle("/warn_metrics/ack/{warn_metric_id:[A-Za-z0-9-_]+}", api.ApiHandler(sendWarnMetricAckEmail)).Methods("POST") 66 api.BaseRoutes.ApiRoot.Handle("/warn_metrics/trial-license-ack/{warn_metric_id:[A-Za-z0-9-_]+}", api.ApiHandler(requestTrialLicenseAndAckWarnMetric)).Methods("POST") 67 api.BaseRoutes.System.Handle("/notices/{team_id:[A-Za-z0-9]+}", api.ApiSessionRequired(getProductNotices)).Methods("GET") 68 api.BaseRoutes.System.Handle("/notices/view", api.ApiSessionRequired(updateViewedProductNotices)).Methods("PUT") 69 70 api.BaseRoutes.System.Handle("/support_packet", api.ApiSessionRequired(generateSupportPacket)).Methods("GET") 71 } 72 73 func generateSupportPacket(c *Context, w http.ResponseWriter, r *http.Request) { 74 const FileMime = "application/zip" 75 const OutputDirectory = "support_packet" 76 77 // Checking to see if the user is a admin of any sort or not 78 // If they are a admin, they should theoritcally have access to one or more of the system console read permissions 79 if !c.App.SessionHasPermissionToAny(*c.AppContext.Session(), model.SysconsoleReadPermissions) { 80 c.SetPermissionError(model.SysconsoleReadPermissions...) 81 return 82 } 83 84 // Checking to see if the server has a e10 or e20 license (this feature is only permitted for servers with licenses) 85 if c.App.Srv().License() == nil { 86 c.Err = model.NewAppError("Api4.generateSupportPacket", "api.no_license", nil, "", http.StatusForbidden) 87 return 88 } 89 90 fileDatas := c.App.GenerateSupportPacket() 91 92 // Constructing the ZIP file name as per spec (mattermost_support_packet_YYYY-MM-DD-HH-MM.zip) 93 now := time.Now() 94 outputZipFilename := fmt.Sprintf("mattermost_support_packet_%s.zip", now.Format("2006-01-02-03-04")) 95 96 fileStorageBackend, fileBackendErr := c.App.FileBackend() 97 if fileBackendErr != nil { 98 c.Err = fileBackendErr 99 return 100 } 101 102 // We do this incase we get concurrent requests, we will always have a unique directory. 103 // This is to avoid the situation where we try to write to the same directory while we are trying to delete it (further down) 104 outputDirectoryToUse := OutputDirectory + "_" + model.NewId() 105 err := c.App.CreateZipFileAndAddFiles(fileStorageBackend, fileDatas, outputZipFilename, outputDirectoryToUse) 106 if err != nil { 107 c.Err = model.NewAppError("Api4.generateSupportPacket", "api.unable_to_create_zip_file", nil, err.Error(), http.StatusForbidden) 108 return 109 } 110 111 fileBytes, err := fileStorageBackend.ReadFile(path.Join(outputDirectoryToUse, outputZipFilename)) 112 defer fileStorageBackend.RemoveDirectory(outputDirectoryToUse) 113 if err != nil { 114 c.Err = model.NewAppError("Api4.generateSupportPacket", "api.unable_to_read_file_from_backend", nil, err.Error(), http.StatusForbidden) 115 return 116 } 117 fileBytesReader := bytes.NewReader(fileBytes) 118 119 // Send the zip file back to client 120 // We are able to pass 0 for content size due to the fact that Golang's serveContent (https://golang.org/src/net/http/fs.go) 121 // already sets that for us 122 writeFileResponse(outputZipFilename, FileMime, 0, now, *c.App.Config().ServiceSettings.WebserverMode, fileBytesReader, true, w, r) 123 } 124 125 func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) { 126 reqs := c.App.Config().ClientRequirements 127 128 s := make(map[string]string) 129 s[model.STATUS] = model.STATUS_OK 130 s["AndroidLatestVersion"] = reqs.AndroidLatestVersion 131 s["AndroidMinVersion"] = reqs.AndroidMinVersion 132 s["DesktopLatestVersion"] = reqs.DesktopLatestVersion 133 s["DesktopMinVersion"] = reqs.DesktopMinVersion 134 s["IosLatestVersion"] = reqs.IosLatestVersion 135 s["IosMinVersion"] = reqs.IosMinVersion 136 137 testflag := c.App.Config().FeatureFlags.TestFeature 138 if testflag != "off" { 139 s["TestFeatureFlag"] = testflag 140 } 141 142 actualGoroutines := runtime.NumGoroutine() 143 if *c.App.Config().ServiceSettings.GoroutineHealthThreshold > 0 && actualGoroutines >= *c.App.Config().ServiceSettings.GoroutineHealthThreshold { 144 mlog.Warn("The number of running goroutines is over the health threshold", mlog.Int("goroutines", actualGoroutines), mlog.Int("health_threshold", *c.App.Config().ServiceSettings.GoroutineHealthThreshold)) 145 s[model.STATUS] = model.STATUS_UNHEALTHY 146 } 147 148 // Enhanced ping health check: 149 // If an extra form value is provided then perform extra health checks for 150 // database and file storage backends. 151 if r.FormValue("get_server_status") != "" { 152 dbStatusKey := "database_status" 153 s[dbStatusKey] = model.STATUS_OK 154 155 writeErr := c.App.DBHealthCheckWrite() 156 if writeErr != nil { 157 mlog.Warn("Unable to write to database.", mlog.Err(writeErr)) 158 s[dbStatusKey] = model.STATUS_UNHEALTHY 159 s[model.STATUS] = model.STATUS_UNHEALTHY 160 } 161 162 writeErr = c.App.DBHealthCheckDelete() 163 if writeErr != nil { 164 mlog.Warn("Unable to remove ping health check value from database.", mlog.Err(writeErr)) 165 s[dbStatusKey] = model.STATUS_UNHEALTHY 166 s[model.STATUS] = model.STATUS_UNHEALTHY 167 } 168 169 if s[dbStatusKey] == model.STATUS_OK { 170 mlog.Debug("Able to write to database.") 171 } 172 173 filestoreStatusKey := "filestore_status" 174 s[filestoreStatusKey] = model.STATUS_OK 175 appErr := c.App.TestFileStoreConnection() 176 if appErr != nil { 177 s[filestoreStatusKey] = model.STATUS_UNHEALTHY 178 s[model.STATUS] = model.STATUS_UNHEALTHY 179 } 180 181 w.Header().Set(model.STATUS, s[model.STATUS]) 182 w.Header().Set(dbStatusKey, s[dbStatusKey]) 183 w.Header().Set(filestoreStatusKey, s[filestoreStatusKey]) 184 } 185 186 if s[model.STATUS] != model.STATUS_OK { 187 w.WriteHeader(http.StatusInternalServerError) 188 } 189 w.Write([]byte(model.MapToJson(s))) 190 } 191 192 func testEmail(c *Context, w http.ResponseWriter, r *http.Request) { 193 cfg := model.ConfigFromJson(r.Body) 194 if cfg == nil { 195 cfg = c.App.Config() 196 } 197 198 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_TEST_EMAIL) { 199 c.SetPermissionError(model.PERMISSION_TEST_EMAIL) 200 return 201 } 202 203 if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin { 204 c.Err = model.NewAppError("testEmail", "api.restricted_system_admin", nil, "", http.StatusForbidden) 205 return 206 } 207 208 err := c.App.TestEmail(c.AppContext.Session().UserId, cfg) 209 if err != nil { 210 c.Err = err 211 return 212 } 213 214 ReturnStatusOK(w) 215 } 216 217 func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) { 218 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_TEST_SITE_URL) { 219 c.SetPermissionError(model.PERMISSION_TEST_SITE_URL) 220 return 221 } 222 223 if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin { 224 c.Err = model.NewAppError("testSiteURL", "api.restricted_system_admin", nil, "", http.StatusForbidden) 225 return 226 } 227 228 props := model.MapFromJson(r.Body) 229 siteURL := props["site_url"] 230 if siteURL == "" { 231 c.SetInvalidParam("site_url") 232 return 233 } 234 235 err := c.App.TestSiteURL(siteURL) 236 if err != nil { 237 c.Err = err 238 return 239 } 240 241 ReturnStatusOK(w) 242 } 243 244 func getAudits(c *Context, w http.ResponseWriter, r *http.Request) { 245 auditRec := c.MakeAuditRecord("getAudits", audit.Fail) 246 defer c.LogAuditRec(auditRec) 247 248 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_READ_AUDITS) { 249 c.SetPermissionError(model.PERMISSION_READ_AUDITS) 250 return 251 } 252 253 audits, err := c.App.GetAuditsPage("", c.Params.Page, c.Params.PerPage) 254 if err != nil { 255 c.Err = err 256 return 257 } 258 259 auditRec.Success() 260 auditRec.AddMeta("page", c.Params.Page) 261 auditRec.AddMeta("audits_per_page", c.Params.LogsPerPage) 262 263 w.Write([]byte(audits.ToJson())) 264 } 265 266 func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) { 267 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_RECYCLE_DATABASE_CONNECTIONS) { 268 c.SetPermissionError(model.PERMISSION_RECYCLE_DATABASE_CONNECTIONS) 269 return 270 } 271 272 auditRec := c.MakeAuditRecord("databaseRecycle", audit.Fail) 273 defer c.LogAuditRec(auditRec) 274 275 if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin { 276 c.Err = model.NewAppError("databaseRecycle", "api.restricted_system_admin", nil, "", http.StatusForbidden) 277 return 278 } 279 280 c.App.RecycleDatabaseConnection() 281 282 auditRec.Success() 283 ReturnStatusOK(w) 284 } 285 286 func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) { 287 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_INVALIDATE_CACHES) { 288 c.SetPermissionError(model.PERMISSION_INVALIDATE_CACHES) 289 return 290 } 291 292 auditRec := c.MakeAuditRecord("invalidateCaches", audit.Fail) 293 defer c.LogAuditRec(auditRec) 294 295 if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin { 296 c.Err = model.NewAppError("invalidateCaches", "api.restricted_system_admin", nil, "", http.StatusForbidden) 297 return 298 } 299 300 err := c.App.Srv().InvalidateAllCaches() 301 if err != nil { 302 c.Err = err 303 return 304 } 305 306 auditRec.Success() 307 308 w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") 309 ReturnStatusOK(w) 310 } 311 312 func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { 313 auditRec := c.MakeAuditRecord("getLogs", audit.Fail) 314 defer c.LogAuditRec(auditRec) 315 316 if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin { 317 c.Err = model.NewAppError("getLogs", "api.restricted_system_admin", nil, "", http.StatusForbidden) 318 return 319 } 320 321 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_GET_LOGS) { 322 c.SetPermissionError(model.PERMISSION_GET_LOGS) 323 return 324 } 325 326 lines, err := c.App.GetLogs(c.Params.Page, c.Params.LogsPerPage) 327 if err != nil { 328 c.Err = err 329 return 330 } 331 332 auditRec.AddMeta("page", c.Params.Page) 333 auditRec.AddMeta("logs_per_page", c.Params.LogsPerPage) 334 335 w.Write([]byte(model.ArrayToJson(lines))) 336 } 337 338 func postLog(c *Context, w http.ResponseWriter, r *http.Request) { 339 forceToDebug := false 340 341 if !*c.App.Config().ServiceSettings.EnableDeveloper { 342 if c.AppContext.Session().UserId == "" { 343 c.Err = model.NewAppError("postLog", "api.context.permissions.app_error", nil, "", http.StatusForbidden) 344 return 345 } 346 347 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 348 forceToDebug = true 349 } 350 } 351 352 m := model.MapFromJson(r.Body) 353 lvl := m["level"] 354 msg := m["message"] 355 356 if len(msg) > 400 { 357 msg = msg[0:399] 358 } 359 360 msg = "Client Logs API Endpoint Message: " + msg 361 fields := []mlog.Field{ 362 mlog.String("type", "client_message"), 363 mlog.String("user_agent", c.AppContext.UserAgent()), 364 } 365 366 if !forceToDebug && lvl == "ERROR" { 367 mlog.Error(msg, fields...) 368 } else { 369 mlog.Debug(msg, fields...) 370 } 371 372 m["message"] = msg 373 w.Write([]byte(model.MapToJson(m))) 374 } 375 376 func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) { 377 name := r.URL.Query().Get("name") 378 teamId := r.URL.Query().Get("team_id") 379 380 if name == "" { 381 name = "standard" 382 } 383 384 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_GET_ANALYTICS) { 385 c.SetPermissionError(model.PERMISSION_GET_ANALYTICS) 386 return 387 } 388 389 rows, err := c.App.GetAnalytics(name, teamId) 390 if err != nil { 391 c.Err = err 392 return 393 } 394 395 if rows == nil { 396 c.SetInvalidParam("name") 397 return 398 } 399 400 w.Write([]byte(rows.ToJson())) 401 } 402 403 func getSupportedTimezones(c *Context, w http.ResponseWriter, r *http.Request) { 404 supportedTimezones := c.App.Timezones().GetSupported() 405 if supportedTimezones == nil { 406 supportedTimezones = make([]string, 0) 407 } 408 409 b, err := json.Marshal(supportedTimezones) 410 if err != nil { 411 c.Logger.Warn("Unable to marshal JSON in timezones.", mlog.Err(err)) 412 w.WriteHeader(http.StatusInternalServerError) 413 } 414 415 w.Write(b) 416 } 417 418 func testS3(c *Context, w http.ResponseWriter, r *http.Request) { 419 cfg := model.ConfigFromJson(r.Body) 420 if cfg == nil { 421 cfg = c.App.Config() 422 } 423 424 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_TEST_S3) { 425 c.SetPermissionError(model.PERMISSION_TEST_S3) 426 return 427 } 428 429 if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin { 430 c.Err = model.NewAppError("testS3", "api.restricted_system_admin", nil, "", http.StatusForbidden) 431 return 432 } 433 434 err := c.App.CheckMandatoryS3Fields(&cfg.FileSettings) 435 if err != nil { 436 c.Err = err 437 return 438 } 439 440 if *cfg.FileSettings.AmazonS3SecretAccessKey == model.FAKE_SETTING { 441 cfg.FileSettings.AmazonS3SecretAccessKey = c.App.Config().FileSettings.AmazonS3SecretAccessKey 442 } 443 444 appErr := c.App.TestFileStoreConnectionWithConfig(&cfg.FileSettings) 445 if appErr != nil { 446 c.Err = appErr 447 return 448 } 449 450 ReturnStatusOK(w) 451 } 452 453 func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) { 454 m := make(map[string]string) 455 m["location"] = "" 456 457 if !*c.App.Config().ServiceSettings.EnableLinkPreviews { 458 w.Write([]byte(model.MapToJson(m))) 459 return 460 } 461 462 url := r.URL.Query().Get("url") 463 if url == "" { 464 c.SetInvalidParam("url") 465 return 466 } 467 468 var location string 469 if err := redirectLocationDataCache.Get(url, &location); err == nil { 470 m["location"] = location 471 w.Write([]byte(model.MapToJson(m))) 472 return 473 } 474 475 client := c.App.HTTPService().MakeClient(false) 476 client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 477 return http.ErrUseLastResponse 478 } 479 480 res, err := client.Head(url) 481 if err != nil { 482 // Cache failures to prevent retries. 483 redirectLocationDataCache.SetWithExpiry(url, "", 1*time.Hour) 484 // Always return a success status and a JSON string to limit information returned to client. 485 w.Write([]byte(model.MapToJson(m))) 486 return 487 } 488 defer func() { 489 io.Copy(ioutil.Discard, res.Body) 490 res.Body.Close() 491 }() 492 493 location = res.Header.Get("Location") 494 redirectLocationDataCache.SetWithExpiry(url, location, 1*time.Hour) 495 m["location"] = location 496 497 w.Write([]byte(model.MapToJson(m))) 498 } 499 500 func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) { 501 ack, err := model.PushNotificationAckFromJson(r.Body) 502 if err != nil { 503 c.Err = model.NewAppError("pushNotificationAck", 504 "api.push_notifications_ack.message.parse.app_error", 505 nil, 506 err.Error(), 507 http.StatusBadRequest, 508 ) 509 return 510 } 511 512 if !*c.App.Config().EmailSettings.SendPushNotifications { 513 c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.disabled.app_error", nil, "", http.StatusNotImplemented) 514 return 515 } 516 517 err = c.App.SendAckToPushProxy(ack) 518 if ack.IsIdLoaded { 519 if err != nil { 520 // Log the error only, then continue to fetch notification message 521 c.App.NotificationsLog().Error("Notification ack not sent to push proxy", 522 mlog.String("ackId", ack.Id), 523 mlog.String("type", ack.NotificationType), 524 mlog.String("postId", ack.PostId), 525 mlog.String("status", err.Error()), 526 ) 527 } 528 529 notificationInterface := c.App.Notification() 530 531 if notificationInterface == nil { 532 c.Err = model.NewAppError("pushNotificationAck", "api.system.id_loaded.not_available.app_error", nil, "", http.StatusFound) 533 return 534 } 535 536 msg, appError := notificationInterface.GetNotificationMessage(ack, c.AppContext.Session().UserId) 537 if appError != nil { 538 c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.id_loaded.fetch.app_error", nil, appError.Error(), http.StatusInternalServerError) 539 return 540 } 541 542 w.Write([]byte(msg.ToJson())) 543 544 return 545 } else if err != nil { 546 c.Err = model.NewAppError("pushNotificationAck", "api.push_notifications_ack.forward.app_error", nil, err.Error(), http.StatusInternalServerError) 547 return 548 } 549 550 ReturnStatusOK(w) 551 } 552 553 func setServerBusy(c *Context, w http.ResponseWriter, r *http.Request) { 554 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 555 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 556 return 557 } 558 559 // number of seconds to keep server marked busy 560 secs := r.URL.Query().Get("seconds") 561 if secs == "" { 562 secs = strconv.FormatInt(DefaultServerBusySeconds, 10) 563 } 564 565 i, err := strconv.ParseInt(secs, 10, 64) 566 if err != nil || i <= 0 || i > MaxServerBusySeconds { 567 c.SetInvalidUrlParam(fmt.Sprintf("seconds must be 1 - %d", MaxServerBusySeconds)) 568 return 569 } 570 571 auditRec := c.MakeAuditRecord("setServerBusy", audit.Fail) 572 defer c.LogAuditRec(auditRec) 573 auditRec.AddMeta("seconds", i) 574 575 c.App.Srv().Busy.Set(time.Second * time.Duration(i)) 576 mlog.Warn("server busy state activated - non-critical services disabled", mlog.Int64("seconds", i)) 577 578 auditRec.Success() 579 ReturnStatusOK(w) 580 } 581 582 func clearServerBusy(c *Context, w http.ResponseWriter, r *http.Request) { 583 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 584 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 585 return 586 } 587 588 auditRec := c.MakeAuditRecord("clearServerBusy", audit.Fail) 589 defer c.LogAuditRec(auditRec) 590 591 c.App.Srv().Busy.Clear() 592 mlog.Info("server busy state cleared - non-critical services enabled") 593 594 auditRec.Success() 595 ReturnStatusOK(w) 596 } 597 598 func getServerBusyExpires(c *Context, w http.ResponseWriter, r *http.Request) { 599 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 600 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 601 return 602 } 603 w.Write([]byte(c.App.Srv().Busy.ToJson())) 604 } 605 606 func upgradeToEnterprise(c *Context, w http.ResponseWriter, r *http.Request) { 607 auditRec := c.MakeAuditRecord("upgradeToEnterprise", audit.Fail) 608 defer c.LogAuditRec(auditRec) 609 610 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 611 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 612 return 613 } 614 615 if model.BuildEnterpriseReady == "true" { 616 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.already-enterprise.app_error", nil, "", http.StatusTooManyRequests) 617 return 618 } 619 620 percentage, _ := c.App.Srv().UpgradeToE0Status() 621 622 if percentage > 0 { 623 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.app_error", nil, "", http.StatusTooManyRequests) 624 return 625 } 626 if percentage == 100 { 627 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.already-done.app_error", nil, "", http.StatusTooManyRequests) 628 return 629 } 630 631 if err := c.App.Srv().CanIUpgradeToE0(); err != nil { 632 var ipErr *upgrader.InvalidPermissions 633 var iaErr *upgrader.InvalidArch 634 switch { 635 case errors.As(err, &ipErr): 636 params := map[string]interface{}{ 637 "MattermostUsername": ipErr.MattermostUsername, 638 "FileUsername": ipErr.FileUsername, 639 "Path": ipErr.Path, 640 } 641 if ipErr.ErrType == "invalid-user-and-permission" { 642 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.invalid-user-and-permission.app_error", params, err.Error(), http.StatusForbidden) 643 } else if ipErr.ErrType == "invalid-user" { 644 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.invalid-user.app_error", params, err.Error(), http.StatusForbidden) 645 } else if ipErr.ErrType == "invalid-permission" { 646 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.invalid-permission.app_error", params, err.Error(), http.StatusForbidden) 647 } 648 case errors.As(err, &iaErr): 649 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.system_not_supported.app_error", nil, err.Error(), http.StatusForbidden) 650 default: 651 c.Err = model.NewAppError("upgradeToEnterprise", "api.upgrade_to_enterprise.generic_error.app_error", nil, err.Error(), http.StatusForbidden) 652 } 653 return 654 } 655 656 c.App.Srv().Go(func() { 657 c.App.Srv().UpgradeToE0() 658 }) 659 660 auditRec.Success() 661 w.WriteHeader(http.StatusAccepted) 662 ReturnStatusOK(w) 663 } 664 665 func upgradeToEnterpriseStatus(c *Context, w http.ResponseWriter, r *http.Request) { 666 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 667 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 668 return 669 } 670 671 percentage, err := c.App.Srv().UpgradeToE0Status() 672 var s map[string]interface{} 673 if err != nil { 674 var isErr *upgrader.InvalidSignature 675 switch { 676 case errors.As(err, &isErr): 677 appErr := model.NewAppError("upgradeToEnterpriseStatus", "api.upgrade_to_enterprise_status.app_error", nil, err.Error(), http.StatusBadRequest) 678 s = map[string]interface{}{"percentage": 0, "error": appErr.Message} 679 default: 680 appErr := model.NewAppError("upgradeToEnterpriseStatus", "api.upgrade_to_enterprise_status.signature.app_error", nil, err.Error(), http.StatusBadRequest) 681 s = map[string]interface{}{"percentage": 0, "error": appErr.Message} 682 } 683 } else { 684 s = map[string]interface{}{"percentage": percentage, "error": nil} 685 } 686 687 w.Write([]byte(model.StringInterfaceToJson(s))) 688 } 689 690 func restart(c *Context, w http.ResponseWriter, r *http.Request) { 691 auditRec := c.MakeAuditRecord("restartServer", audit.Fail) 692 defer c.LogAuditRec(auditRec) 693 694 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 695 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 696 return 697 } 698 699 auditRec.Success() 700 ReturnStatusOK(w) 701 time.Sleep(1 * time.Second) 702 703 go func() { 704 c.App.Srv().Restart() 705 }() 706 } 707 708 func getWarnMetricsStatus(c *Context, w http.ResponseWriter, r *http.Request) { 709 if !c.App.SessionHasPermissionToAny(*c.AppContext.Session(), model.SysconsoleReadPermissions) { 710 c.SetPermissionError(model.SysconsoleReadPermissions...) 711 return 712 } 713 714 license := c.App.Srv().License() 715 if license != nil { 716 mlog.Debug("License is present, skip.") 717 return 718 } 719 720 status, err := c.App.GetWarnMetricsStatus() 721 if err != nil { 722 c.Err = err 723 return 724 } 725 726 w.Write([]byte(model.MapWarnMetricStatusToJson(status))) 727 } 728 729 func sendWarnMetricAckEmail(c *Context, w http.ResponseWriter, r *http.Request) { 730 auditRec := c.MakeAuditRecord("sendWarnMetricAckEmail", audit.Fail) 731 defer c.LogAuditRec(auditRec) 732 c.LogAudit("attempt") 733 734 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 735 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 736 return 737 } 738 739 license := c.App.Srv().License() 740 if license != nil { 741 mlog.Debug("License is present, skip.") 742 return 743 } 744 745 user, appErr := c.App.GetUser(c.AppContext.Session().UserId) 746 if appErr != nil { 747 c.Err = appErr 748 return 749 } 750 751 ack := model.SendWarnMetricAckFromJson(r.Body) 752 if ack == nil { 753 c.SetInvalidParam("ack") 754 return 755 } 756 757 appErr = c.App.NotifyAndSetWarnMetricAck(c.Params.WarnMetricId, user, ack.ForceAck, false) 758 if appErr != nil { 759 c.Err = appErr 760 } 761 762 auditRec.Success() 763 ReturnStatusOK(w) 764 } 765 766 func requestTrialLicenseAndAckWarnMetric(c *Context, w http.ResponseWriter, r *http.Request) { 767 auditRec := c.MakeAuditRecord("requestTrialLicenseAndAckWarnMetric", audit.Fail) 768 defer c.LogAuditRec(auditRec) 769 c.LogAudit("attempt") 770 771 if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_MANAGE_SYSTEM) { 772 c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) 773 return 774 } 775 776 if model.BuildEnterpriseReady != "true" { 777 mlog.Debug("Not Enterprise Edition, skip.") 778 return 779 } 780 781 license := c.App.Srv().License() 782 if license != nil { 783 mlog.Debug("License is present, skip.") 784 return 785 } 786 787 if err := c.App.RequestLicenseAndAckWarnMetric(c.AppContext, c.Params.WarnMetricId, false); err != nil { 788 c.Err = err 789 return 790 } 791 792 auditRec.Success() 793 ReturnStatusOK(w) 794 } 795 796 func getProductNotices(c *Context, w http.ResponseWriter, r *http.Request) { 797 c.RequireTeamId() 798 if c.Err != nil { 799 return 800 } 801 802 client, parseError := model.NoticeClientTypeFromString(r.URL.Query().Get("client")) 803 if parseError != nil { 804 c.SetInvalidParam("client") 805 return 806 } 807 clientVersion := r.URL.Query().Get("clientVersion") 808 locale := r.URL.Query().Get("locale") 809 810 notices, err := c.App.GetProductNotices(c.AppContext, c.AppContext.Session().UserId, c.Params.TeamId, client, clientVersion, locale) 811 812 if err != nil { 813 c.Err = err 814 return 815 } 816 result, _ := notices.Marshal() 817 _, _ = w.Write(result) 818 } 819 820 func updateViewedProductNotices(c *Context, w http.ResponseWriter, r *http.Request) { 821 auditRec := c.MakeAuditRecord("updateViewedProductNotices", audit.Fail) 822 defer c.LogAuditRec(auditRec) 823 c.LogAudit("attempt") 824 825 ids := model.ArrayFromJson(r.Body) 826 err := c.App.UpdateViewedProductNotices(c.AppContext.Session().UserId, ids) 827 if err != nil { 828 c.Err = err 829 return 830 } 831 832 auditRec.Success() 833 ReturnStatusOK(w) 834 }