github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+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  	"strings"
    10  	"time"
    11  
    12  	"runtime/debug"
    13  
    14  	"net/http"
    15  
    16  	l4g "github.com/alecthomas/log4go"
    17  	"github.com/mattermost/mattermost-server/model"
    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  	l4g.Info(utils.T("api.context.invalidate_all_caches"))
   141  	a.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) GetConfig() *model.Config {
   152  	json := a.Config().ToJson()
   153  	cfg := model.ConfigFromJson(strings.NewReader(json))
   154  	cfg.Sanitize()
   155  
   156  	return cfg
   157  }
   158  
   159  func (a *App) SaveConfig(cfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError {
   160  	oldCfg := a.Config()
   161  	cfg.SetDefaults()
   162  	a.Desanitize(cfg)
   163  
   164  	if err := cfg.IsValid(); err != nil {
   165  		return err
   166  	}
   167  
   168  	if err := utils.ValidateLdapFilter(cfg, a.Ldap); err != nil {
   169  		return err
   170  	}
   171  
   172  	if *a.Config().ClusterSettings.Enable && *a.Config().ClusterSettings.ReadOnlyConfig {
   173  		return model.NewAppError("saveConfig", "ent.cluster.save_config.error", nil, "", http.StatusForbidden)
   174  	}
   175  
   176  	a.DisableConfigWatch()
   177  	a.UpdateConfig(func(update *model.Config) {
   178  		*update = *cfg
   179  	})
   180  	a.PersistConfig()
   181  	a.ReloadConfig()
   182  	a.EnableConfigWatch()
   183  
   184  	if a.Metrics != nil {
   185  		if *a.Config().MetricsSettings.Enable {
   186  			a.Metrics.StartServer()
   187  		} else {
   188  			a.Metrics.StopServer()
   189  		}
   190  	}
   191  
   192  	if a.Cluster != nil {
   193  		err := a.Cluster.ConfigChanged(cfg, oldCfg, sendConfigChangeClusterMessage)
   194  		if err != nil {
   195  			return err
   196  		}
   197  	}
   198  
   199  	// start/restart email batching job if necessary
   200  	a.InitEmailBatching()
   201  
   202  	return nil
   203  }
   204  
   205  func (a *App) RecycleDatabaseConnection() {
   206  	oldStore := a.Srv.Store
   207  
   208  	l4g.Warn(utils.T("api.admin.recycle_db_start.warn"))
   209  	a.Srv.Store = a.newStore()
   210  	a.Jobs.Store = a.Srv.Store
   211  
   212  	if a.Srv.Store != oldStore {
   213  		time.Sleep(20 * time.Second)
   214  		oldStore.Close()
   215  	}
   216  
   217  	l4g.Warn(utils.T("api.admin.recycle_db_end.warn"))
   218  }
   219  
   220  func (a *App) TestEmail(userId string, cfg *model.Config) *model.AppError {
   221  	if len(cfg.EmailSettings.SMTPServer) == 0 {
   222  		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)
   223  	}
   224  
   225  	// if the user hasn't changed their email settings, fill in the actual SMTP password so that
   226  	// the user can verify an existing SMTP connection
   227  	if cfg.EmailSettings.SMTPPassword == model.FAKE_SETTING {
   228  		if cfg.EmailSettings.SMTPServer == a.Config().EmailSettings.SMTPServer &&
   229  			cfg.EmailSettings.SMTPPort == a.Config().EmailSettings.SMTPPort &&
   230  			cfg.EmailSettings.SMTPUsername == a.Config().EmailSettings.SMTPUsername {
   231  			cfg.EmailSettings.SMTPPassword = a.Config().EmailSettings.SMTPPassword
   232  		} else {
   233  			return model.NewAppError("testEmail", "api.admin.test_email.reenter_password", nil, "", http.StatusBadRequest)
   234  		}
   235  	}
   236  	if user, err := a.GetUser(userId); err != nil {
   237  		return err
   238  	} else {
   239  		T := utils.GetUserTranslations(user.Locale)
   240  		license := a.License()
   241  		if err := utils.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg, license != nil && *license.Features.Compliance); err != nil {
   242  			return err
   243  		}
   244  	}
   245  
   246  	return nil
   247  }