github.com/vnforks/kid@v5.11.1+incompatible/app/admin.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package app 5 6 import ( 7 "io" 8 "os" 9 "time" 10 11 "runtime/debug" 12 13 "net/http" 14 15 "github.com/mattermost/mattermost-server/mlog" 16 "github.com/mattermost/mattermost-server/model" 17 "github.com/mattermost/mattermost-server/services/mailservice" 18 "github.com/mattermost/mattermost-server/utils" 19 ) 20 21 func (a *App) GetLogs(page, perPage int) ([]string, *model.AppError) { 22 var lines []string 23 if a.Cluster != nil && *a.Config().ClusterSettings.Enable { 24 lines = append(lines, "-----------------------------------------------------------------------------------------------------------") 25 lines = append(lines, "-----------------------------------------------------------------------------------------------------------") 26 lines = append(lines, a.Cluster.GetMyClusterInfo().Hostname) 27 lines = append(lines, "-----------------------------------------------------------------------------------------------------------") 28 lines = append(lines, "-----------------------------------------------------------------------------------------------------------") 29 } 30 31 melines, err := a.GetLogsSkipSend(page, perPage) 32 if err != nil { 33 return nil, err 34 } 35 36 lines = append(lines, melines...) 37 38 if a.Cluster != nil && *a.Config().ClusterSettings.Enable { 39 clines, err := a.Cluster.GetLogs(page, perPage) 40 if err != nil { 41 return nil, err 42 } 43 44 lines = append(lines, clines...) 45 } 46 47 return lines, nil 48 } 49 50 func (a *App) GetLogsSkipSend(page, perPage int) ([]string, *model.AppError) { 51 var lines []string 52 53 if *a.Config().LogSettings.EnableFile { 54 file, err := os.Open(utils.GetLogFileLocation(*a.Config().LogSettings.FileLocation)) 55 if err != nil { 56 return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError) 57 } 58 59 defer file.Close() 60 61 var newLine = []byte{'\n'} 62 var lineCount int 63 const searchPos = -1 64 lineEndPos, err := file.Seek(0, io.SeekEnd) 65 if err != nil { 66 return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError) 67 } 68 for { 69 pos, err := file.Seek(searchPos, io.SeekCurrent) 70 if err != nil { 71 return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError) 72 } 73 74 b := make([]byte, 1) 75 _, err = file.ReadAt(b, pos) 76 if err != nil { 77 return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError) 78 } 79 80 if b[0] == newLine[0] || pos == 0 { 81 lineCount++ 82 if lineCount > page*perPage { 83 line := make([]byte, lineEndPos-pos) 84 _, err := file.ReadAt(line, pos) 85 if err != nil { 86 return nil, model.NewAppError("getLogs", "api.admin.file_read_error", nil, err.Error(), http.StatusInternalServerError) 87 } 88 lines = append(lines, string(line)) 89 } 90 if pos == 0 { 91 break 92 } 93 lineEndPos = pos 94 } 95 96 if len(lines) == perPage { 97 break 98 } 99 } 100 101 for i, j := 0, len(lines)-1; i < j; i, j = i+1, j-1 { 102 lines[i], lines[j] = lines[j], lines[i] 103 } 104 } else { 105 lines = append(lines, "") 106 } 107 108 return lines, nil 109 } 110 111 func (a *App) GetClusterStatus() []*model.ClusterInfo { 112 infos := make([]*model.ClusterInfo, 0) 113 114 if a.Cluster != nil { 115 infos = a.Cluster.GetClusterInfos() 116 } 117 118 return infos 119 } 120 121 func (a *App) InvalidateAllCaches() *model.AppError { 122 debug.FreeOSMemory() 123 a.InvalidateAllCachesSkipSend() 124 125 if a.Cluster != nil { 126 127 msg := &model.ClusterMessage{ 128 Event: model.CLUSTER_EVENT_INVALIDATE_ALL_CACHES, 129 SendType: model.CLUSTER_SEND_RELIABLE, 130 WaitForAllToSend: true, 131 } 132 133 a.Cluster.SendClusterMessage(msg) 134 } 135 136 return nil 137 } 138 139 func (a *App) InvalidateAllCachesSkipSend() { 140 mlog.Info("Purging all caches") 141 a.Srv.sessionCache.Purge() 142 ClearStatusCache() 143 a.Srv.Store.Channel().ClearCaches() 144 a.Srv.Store.User().ClearCaches() 145 a.Srv.Store.Post().ClearCaches() 146 a.Srv.Store.FileInfo().ClearCaches() 147 a.Srv.Store.Webhook().ClearCaches() 148 a.LoadLicense() 149 } 150 151 func (a *App) RecycleDatabaseConnection() { 152 oldStore := a.Srv.Store 153 154 mlog.Warn("Attempting to recycle the database connection.") 155 a.Srv.Store = a.Srv.newStore() 156 a.Srv.Jobs.Store = a.Srv.Store 157 158 if a.Srv.Store != oldStore { 159 time.Sleep(20 * time.Second) 160 oldStore.Close() 161 } 162 163 mlog.Warn("Finished recycling the database connection.") 164 } 165 166 func (a *App) TestEmail(userId string, cfg *model.Config) *model.AppError { 167 if len(*cfg.EmailSettings.SMTPServer) == 0 { 168 return model.NewAppError("testEmail", "api.admin.test_email.missing_server", nil, utils.T("api.context.invalid_param.app_error", map[string]interface{}{"Name": "SMTPServer"}), http.StatusBadRequest) 169 } 170 171 // if the user hasn't changed their email settings, fill in the actual SMTP password so that 172 // the user can verify an existing SMTP connection 173 if *cfg.EmailSettings.SMTPPassword == model.FAKE_SETTING { 174 if *cfg.EmailSettings.SMTPServer == *a.Config().EmailSettings.SMTPServer && 175 *cfg.EmailSettings.SMTPPort == *a.Config().EmailSettings.SMTPPort && 176 *cfg.EmailSettings.SMTPUsername == *a.Config().EmailSettings.SMTPUsername { 177 *cfg.EmailSettings.SMTPPassword = *a.Config().EmailSettings.SMTPPassword 178 } else { 179 return model.NewAppError("testEmail", "api.admin.test_email.reenter_password", nil, "", http.StatusBadRequest) 180 } 181 } 182 user, err := a.GetUser(userId) 183 if err != nil { 184 return err 185 } 186 187 T := utils.GetUserTranslations(user.Locale) 188 license := a.License() 189 if err := mailservice.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg, license != nil && *license.Features.Compliance); err != nil { 190 return model.NewAppError("testEmail", "app.admin.test_email.failure", map[string]interface{}{"Error": err.Error()}, "", http.StatusInternalServerError) 191 } 192 193 return nil 194 }