general cleanup (#8387)
Этот коммит содержится в:
@@ -364,10 +364,6 @@ func NewInvalidParamError(where string, name string) *model.AppError {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) SetUnknownError(where string, details string) {
|
|
||||||
c.Err = model.NewAppError(where, "api.context.unknown.app_error", nil, details, http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) SetPermissionError(permission *model.Permission) {
|
func (c *Context) SetPermissionError(permission *model.Permission) {
|
||||||
c.Err = model.NewAppError("Permissions", "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", "+"permission="+permission.Id, http.StatusForbidden)
|
c.Err = model.NewAppError("Permissions", "api.context.permissions.app_error", nil, "userId="+c.Session.UserId+", "+"permission="+permission.Id, http.StatusForbidden)
|
||||||
}
|
}
|
||||||
@@ -387,11 +383,6 @@ func (c *Context) SetSiteURLHeader(url string) {
|
|||||||
c.siteURLHeader = strings.TrimRight(url, "/")
|
c.siteURLHeader = strings.TrimRight(url, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO see where these are used
|
|
||||||
func (c *Context) GetTeamURLFromTeam(team *model.Team) string {
|
|
||||||
return c.GetSiteURLHeader() + "/" + team.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) GetTeamURL() string {
|
func (c *Context) GetTeamURL() string {
|
||||||
if !c.teamURLValid {
|
if !c.teamURLValid {
|
||||||
c.SetTeamURLFromSession()
|
c.SetTeamURLFromSession()
|
||||||
@@ -406,10 +397,6 @@ func (c *Context) GetSiteURLHeader() string {
|
|||||||
return c.siteURLHeader
|
return c.siteURLHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) GetCurrentTeamMember() *model.TeamMember {
|
|
||||||
return c.Session.GetTeamByTeamId(c.TeamId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Context) HandleEtag(etag string, routeName string, w http.ResponseWriter, r *http.Request) bool {
|
func (c *Context) HandleEtag(etag string, routeName string, w http.ResponseWriter, r *http.Request) bool {
|
||||||
metrics := c.App.Metrics
|
metrics := c.App.Metrics
|
||||||
if et := r.Header.Get(model.HEADER_ETAG_CLIENT); len(etag) > 0 {
|
if et := r.Header.Get(model.HEADER_ETAG_CLIENT); len(etag) > 0 {
|
||||||
|
|||||||
@@ -510,18 +510,6 @@ func CheckUserSanitization(t *testing.T, user *model.User) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckTeamSanitization(t *testing.T, team *model.Team) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if team.Email != "" {
|
|
||||||
t.Fatal("email wasn't blank")
|
|
||||||
}
|
|
||||||
|
|
||||||
if team.AllowedDomains != "" {
|
|
||||||
t.Fatal("'allowed domains' wasn't blank")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckEtag(t *testing.T, data interface{}, resp *model.Response) {
|
func CheckEtag(t *testing.T, data interface{}, resp *model.Response) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
@@ -669,21 +657,6 @@ func CheckInternalErrorStatus(t *testing.T, resp *model.Response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckPayLoadTooLargeStatus(t *testing.T, resp *model.Response) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if resp.Error == nil {
|
|
||||||
t.Fatal("should have errored with status:" + strconv.Itoa(http.StatusRequestEntityTooLarge))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusRequestEntityTooLarge {
|
|
||||||
t.Log("actual: " + strconv.Itoa(resp.StatusCode))
|
|
||||||
t.Log("expected: " + strconv.Itoa(http.StatusRequestEntityTooLarge))
|
|
||||||
t.Fatal("wrong status code")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readTestFile(name string) ([]byte, error) {
|
func readTestFile(name string) ([]byte, error) {
|
||||||
path, _ := utils.FindDir("tests")
|
path, _ := utils.FindDir("tests")
|
||||||
file, err := os.Open(path + "/" + name)
|
file, err := os.Open(path + "/" + name)
|
||||||
|
|||||||
@@ -510,7 +510,6 @@ func commandWebhook(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func decodePayload(payload io.Reader) (*model.IncomingWebhookRequest, *model.AppError) {
|
func decodePayload(payload io.Reader) (*model.IncomingWebhookRequest, *model.AppError) {
|
||||||
decodeError := &model.AppError{}
|
|
||||||
incomingWebhookPayload, decodeError := model.IncomingWebhookRequestFromJson(payload)
|
incomingWebhookPayload, decodeError := model.IncomingWebhookRequestFromJson(payload)
|
||||||
|
|
||||||
if decodeError != nil {
|
if decodeError != nil {
|
||||||
|
|||||||
@@ -135,10 +135,6 @@ func (me *TestHelper) InitBasic() *TestHelper {
|
|||||||
return me
|
return me
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *TestHelper) MakeUsername() string {
|
|
||||||
return "un_" + model.NewId()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TestHelper) MakeEmail() string {
|
func (me *TestHelper) MakeEmail() string {
|
||||||
return "success_" + model.NewId() + "@simulator.amazonses.com"
|
return "success_" + model.NewId() + "@simulator.amazonses.com"
|
||||||
}
|
}
|
||||||
@@ -191,10 +187,6 @@ func (me *TestHelper) CreateChannel(team *model.Team) *model.Channel {
|
|||||||
return me.createChannel(team, model.CHANNEL_OPEN)
|
return me.createChannel(team, model.CHANNEL_OPEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *TestHelper) CreatePrivateChannel(team *model.Team) *model.Channel {
|
|
||||||
return me.createChannel(team, model.CHANNEL_PRIVATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TestHelper) createChannel(team *model.Team, channelType string) *model.Channel {
|
func (me *TestHelper) createChannel(team *model.Team, channelType string) *model.Channel {
|
||||||
id := model.NewId()
|
id := model.NewId()
|
||||||
|
|
||||||
|
|||||||
@@ -181,18 +181,6 @@ func (a *App) HasPermissionToChannelByPost(askingUserId string, postId string, p
|
|||||||
return a.HasPermissionTo(askingUserId, permission)
|
return a.HasPermissionTo(askingUserId, permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) HasPermissionToUser(askingUserId string, userId string) bool {
|
|
||||||
if askingUserId == userId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.HasPermissionTo(askingUserId, model.PERMISSION_EDIT_OTHER_USERS) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) CheckIfRolesGrantPermission(roles []string, permissionId string) bool {
|
func (a *App) CheckIfRolesGrantPermission(roles []string, permissionId string) bool {
|
||||||
for _, roleId := range roles {
|
for _, roleId := range roles {
|
||||||
if role := a.Role(roleId); role == nil {
|
if role := a.Role(roleId); role == nil {
|
||||||
|
|||||||
@@ -9,16 +9,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
USER_PASSWORD = "passwd"
|
USER_PASSWORD = "passwd"
|
||||||
CHANNEL_TYPE = model.CHANNEL_OPEN
|
CHANNEL_TYPE = model.CHANNEL_OPEN
|
||||||
FUZZ_USER_EMAIL_PREFIX_LEN = 10
|
BTEST_TEAM_DISPLAY_NAME = "TestTeam"
|
||||||
BTEST_TEAM_DISPLAY_NAME = "TestTeam"
|
BTEST_TEAM_NAME = "z-z-testdomaina"
|
||||||
BTEST_TEAM_NAME = "z-z-testdomaina"
|
BTEST_TEAM_EMAIL = "test@nowhere.com"
|
||||||
BTEST_TEAM_EMAIL = "test@nowhere.com"
|
BTEST_TEAM_TYPE = model.TEAM_OPEN
|
||||||
BTEST_TEAM_TYPE = model.TEAM_OPEN
|
BTEST_USER_NAME = "Mr. Testing Tester"
|
||||||
BTEST_USER_NAME = "Mr. Testing Tester"
|
BTEST_USER_EMAIL = "success+ttester@simulator.amazonses.com"
|
||||||
BTEST_USER_EMAIL = "success+ttester@simulator.amazonses.com"
|
BTEST_USER_PASSWORD = "passwd"
|
||||||
BTEST_USER_PASSWORD = "passwd"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -29,8 +28,5 @@ var (
|
|||||||
USER_EMAIL_LEN = utils.Range{Begin: 15, End: 30}
|
USER_EMAIL_LEN = utils.Range{Begin: 15, End: 30}
|
||||||
CHANNEL_DISPLAY_NAME_LEN = utils.Range{Begin: 10, End: 20}
|
CHANNEL_DISPLAY_NAME_LEN = utils.Range{Begin: 10, End: 20}
|
||||||
CHANNEL_NAME_LEN = utils.Range{Begin: 5, End: 20}
|
CHANNEL_NAME_LEN = utils.Range{Begin: 5, End: 20}
|
||||||
POST_MESSAGE_LEN = utils.Range{Begin: 100, End: 400}
|
|
||||||
POST_HASHTAGS_NUM = utils.Range{Begin: 5, End: 10}
|
|
||||||
POST_MENTIONS_NUM = utils.Range{Begin: 0, End: 3}
|
|
||||||
TEST_IMAGE_FILENAMES = []string{"test.png", "testjpg.jpg", "testgif.gif"}
|
TEST_IMAGE_FILENAMES = []string{"test.png", "testjpg.jpg", "testgif.gif"}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -90,18 +90,3 @@ func (cfg *AutoPostCreator) CreateRandomPost() (*model.Post, bool) {
|
|||||||
}
|
}
|
||||||
return result.Data.(*model.Post), true
|
return result.Data.(*model.Post), true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *AutoPostCreator) CreateTestPosts(rangePosts utils.Range) ([]*model.Post, bool) {
|
|
||||||
numPosts := utils.RandIntFromRange(rangePosts)
|
|
||||||
posts := make([]*model.Post, numPosts)
|
|
||||||
|
|
||||||
for i := 0; i < numPosts; i++ {
|
|
||||||
var err bool
|
|
||||||
posts[i], err = cfg.CreateRandomPost()
|
|
||||||
if !err {
|
|
||||||
return posts, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return posts, true
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -377,7 +377,7 @@ func (a *App) postChannelPrivacyMessage(user *model.User, channel *model.Channel
|
|||||||
})[channel.Type]
|
})[channel.Type]
|
||||||
post := &model.Post{
|
post := &model.Post{
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
Message: fmt.Sprintf(utils.T("api.channel.change_channel_privacy." + privacy)),
|
Message: utils.T("api.channel.change_channel_privacy." + privacy),
|
||||||
Type: model.POST_CHANGE_CHANNEL_PRIVACY,
|
Type: model.POST_CHANGE_CHANNEL_PRIVACY,
|
||||||
UserId: user.Id,
|
UserId: user.Id,
|
||||||
Props: model.StringInterface{
|
Props: model.StringInterface{
|
||||||
@@ -1062,7 +1062,7 @@ func (a *App) LeaveChannel(channelId string, userId string) *model.AppError {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.Name == model.DEFAULT_CHANNEL && *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages == false {
|
if channel.Name == model.DEFAULT_CHANNEL && !*a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,28 +84,6 @@ func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
const TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN = time.Second
|
const TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN = time.Second
|
||||||
|
|
||||||
type VaryBy struct {
|
|
||||||
useIP bool
|
|
||||||
useAuth bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *VaryBy) Key(r *http.Request) string {
|
|
||||||
key := ""
|
|
||||||
|
|
||||||
if m.useAuth {
|
|
||||||
token, tokenLocation := ParseAuthTokenFromRequest(r)
|
|
||||||
if tokenLocation != TokenLocationNotFound {
|
|
||||||
key += token
|
|
||||||
} else if m.useIP { // If we don't find an authentication token and IP based is enabled, fall back to IP
|
|
||||||
key += utils.GetIpAddress(r)
|
|
||||||
}
|
|
||||||
} else if m.useIP { // Only if Auth based is not enabed do we use a plain IP based
|
|
||||||
key = utils.GetIpAddress(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
func redirectHTTPToHTTPS(w http.ResponseWriter, r *http.Request) {
|
func redirectHTTPToHTTPS(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Host == "" {
|
if r.Host == "" {
|
||||||
http.Error(w, "Not Found", http.StatusNotFound)
|
http.Error(w, "Not Found", http.StatusNotFound)
|
||||||
@@ -223,31 +201,6 @@ func (a *App) StartServer() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type tcpKeepAliveListener struct {
|
|
||||||
*net.TCPListener
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
|
||||||
tc, err := ln.AcceptTCP()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tc.SetKeepAlive(true)
|
|
||||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
|
||||||
return tc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) Listen(addr string) (net.Listener, error) {
|
|
||||||
if addr == "" {
|
|
||||||
addr = ":http"
|
|
||||||
}
|
|
||||||
ln, err := net.Listen("tcp", addr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tcpKeepAliveListener{ln.(*net.TCPListener)}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) StopServer() {
|
func (a *App) StopServer() {
|
||||||
if a.Srv.Server != nil {
|
if a.Srv.Server != nil {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN)
|
ctx, cancel := context.WithTimeout(context.Background(), TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN)
|
||||||
|
|||||||
@@ -109,13 +109,11 @@ func SlackParseUsers(data io.Reader) ([]SlackUser, error) {
|
|||||||
decoder := json.NewDecoder(data)
|
decoder := json.NewDecoder(data)
|
||||||
|
|
||||||
var users []SlackUser
|
var users []SlackUser
|
||||||
if err := decoder.Decode(&users); err != nil {
|
err := decoder.Decode(&users)
|
||||||
// This actually returns errors that are ignored.
|
// This actually returns errors that are ignored.
|
||||||
// In this case it is erroring because of a null that Slack
|
// In this case it is erroring because of a null that Slack
|
||||||
// introduced. So we just return the users here.
|
// introduced. So we just return the users here.
|
||||||
return users, err
|
return users, err
|
||||||
}
|
|
||||||
return users, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SlackParsePosts(data io.Reader) ([]SlackPost, error) {
|
func SlackParsePosts(data io.Reader) ([]SlackPost, error) {
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ const (
|
|||||||
TOKEN_TYPE_PASSWORD_RECOVERY = "password_recovery"
|
TOKEN_TYPE_PASSWORD_RECOVERY = "password_recovery"
|
||||||
TOKEN_TYPE_VERIFY_EMAIL = "verify_email"
|
TOKEN_TYPE_VERIFY_EMAIL = "verify_email"
|
||||||
PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour
|
PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour
|
||||||
VERIFY_EMAIL_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour
|
|
||||||
IMAGE_PROFILE_PIXEL_DIMENSION = 128
|
IMAGE_PROFILE_PIXEL_DIMENSION = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ func sampleDataCmdF(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
importErr, lineNumber := a.BulkImport(bulkFile, false, workers)
|
importErr, lineNumber := a.BulkImport(bulkFile, false, workers)
|
||||||
if importErr != nil {
|
if importErr != nil {
|
||||||
return errors.New(fmt.Sprintf("%s: %s, %s (line: %d)", importErr.Where, importErr.Message, importErr.DetailedError, lineNumber))
|
return fmt.Errorf("%s: %s, %s (line: %d)", importErr.Where, importErr.Message, importErr.DetailedError, lineNumber)
|
||||||
}
|
}
|
||||||
} else if bulk != "-" {
|
} else if bulk != "-" {
|
||||||
err := bulkFile.Close()
|
err := bulkFile.Close()
|
||||||
@@ -395,7 +395,7 @@ func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndCh
|
|||||||
position := rand.Intn(len(possibleTeams))
|
position := rand.Intn(len(possibleTeams))
|
||||||
team := possibleTeams[position]
|
team := possibleTeams[position]
|
||||||
possibleTeams = append(possibleTeams[:position], possibleTeams[position+1:]...)
|
possibleTeams = append(possibleTeams[:position], possibleTeams[position+1:]...)
|
||||||
if teamChannels, err := teamsAndChannels[team]; err == true {
|
if teamChannels, err := teamsAndChannels[team]; err {
|
||||||
teams = append(teams, createTeamMembership(channelMemberships, teamChannels, &team))
|
teams = append(teams, createTeamMembership(channelMemberships, teamChannels, &team))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,10 +429,7 @@ func createTeamMembership(numOfchannels int, teamChannels []string, teamName *st
|
|||||||
roles = "team_user team_admin"
|
roles = "team_user team_admin"
|
||||||
}
|
}
|
||||||
channels := []app.UserChannelImportData{}
|
channels := []app.UserChannelImportData{}
|
||||||
teamChannelsCopy := []string{}
|
teamChannelsCopy := append([]string(nil), teamChannels...)
|
||||||
for _, value := range teamChannels {
|
|
||||||
teamChannelsCopy = append(teamChannelsCopy, value)
|
|
||||||
}
|
|
||||||
for x := 0; x < numOfchannels; x++ {
|
for x := 0; x < numOfchannels; x++ {
|
||||||
if len(teamChannelsCopy) == 0 {
|
if len(teamChannelsCopy) == 0 {
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package jobs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
l4g "github.com/alecthomas/log4go"
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestWorker struct {
|
|
||||||
srv *JobServer
|
|
||||||
name string
|
|
||||||
stop chan bool
|
|
||||||
stopped chan bool
|
|
||||||
jobs chan model.Job
|
|
||||||
}
|
|
||||||
|
|
||||||
func (srv *JobServer) MakeTestWorker(name string) *TestWorker {
|
|
||||||
return &TestWorker{
|
|
||||||
srv: srv,
|
|
||||||
name: name,
|
|
||||||
stop: make(chan bool, 1),
|
|
||||||
stopped: make(chan bool, 1),
|
|
||||||
jobs: make(chan model.Job),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (worker *TestWorker) Run() {
|
|
||||||
l4g.Debug("Worker %v: Started", worker.name)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
l4g.Debug("Worker %v: Finished", worker.name)
|
|
||||||
worker.stopped <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-worker.stop:
|
|
||||||
l4g.Debug("Worker %v: Received stop signal", worker.name)
|
|
||||||
return
|
|
||||||
case job := <-worker.jobs:
|
|
||||||
l4g.Debug("Worker %v: Received a new candidate job.", worker.name)
|
|
||||||
worker.DoJob(&job)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (worker *TestWorker) DoJob(job *model.Job) {
|
|
||||||
if claimed, err := worker.srv.ClaimJob(job); err != nil {
|
|
||||||
l4g.Error("Job: %v: Error occurred while trying to claim job: %v", job.Id, err.Error())
|
|
||||||
return
|
|
||||||
} else if !claimed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelCtx, cancelCancelWatcher := context.WithCancel(context.Background())
|
|
||||||
cancelWatcherChan := make(chan interface{}, 1)
|
|
||||||
go worker.srv.CancellationWatcher(cancelCtx, job.Id, cancelWatcherChan)
|
|
||||||
|
|
||||||
defer cancelCancelWatcher()
|
|
||||||
|
|
||||||
counter := 0
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-cancelWatcherChan:
|
|
||||||
l4g.Debug("Job %v: Job has been canceled via CancellationWatcher.", job.Id)
|
|
||||||
if err := worker.srv.SetJobCanceled(job); err != nil {
|
|
||||||
l4g.Error("Failed to mark job: %v as canceled. Error: %v", job.Id, err.Error())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case <-worker.stop:
|
|
||||||
l4g.Debug("Job %v: Job has been canceled via Worker Stop.", job.Id)
|
|
||||||
if err := worker.srv.SetJobCanceled(job); err != nil {
|
|
||||||
l4g.Error("Failed to mark job: %v as canceled. Error: %v", job.Id, err.Error())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
case <-time.After(5 * time.Second):
|
|
||||||
counter++
|
|
||||||
if counter > 10 {
|
|
||||||
l4g.Debug("Job %v: Job completed.", job.Id)
|
|
||||||
if err := worker.srv.SetJobSuccess(job); err != nil {
|
|
||||||
l4g.Error("Failed to mark job: %v as succeeded. Error: %v", job.Id, err.Error())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
if err := worker.srv.SetJobProgress(job, int64(counter*10)); err != nil {
|
|
||||||
l4g.Error("Job: %v: an error occured while trying to set job progress: %v", job.Id, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (worker *TestWorker) Stop() {
|
|
||||||
l4g.Debug("Worker %v: Stopping", worker.name)
|
|
||||||
worker.stop <- true
|
|
||||||
<-worker.stopped
|
|
||||||
}
|
|
||||||
|
|
||||||
func (worker *TestWorker) JobChannel() chan<- model.Job {
|
|
||||||
return worker.jobs
|
|
||||||
}
|
|
||||||
@@ -503,19 +503,6 @@ func initializeDefaultRoles() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoleIdsToString(roles []string) string {
|
|
||||||
output := ""
|
|
||||||
for _, role := range roles {
|
|
||||||
output += role + ", "
|
|
||||||
}
|
|
||||||
|
|
||||||
if output == "" {
|
|
||||||
return "[<NO ROLES>]"
|
|
||||||
}
|
|
||||||
|
|
||||||
return output[:len(output)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
initializePermissions()
|
initializePermissions()
|
||||||
initializeDefaultRoles()
|
initializeDefaultRoles()
|
||||||
|
|||||||
@@ -86,12 +86,7 @@ func (o *Channel) Etag() string {
|
|||||||
return Etag(o.Id, o.UpdateAt)
|
return Etag(o.Id, o.UpdateAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Channel) StatsEtag() string {
|
|
||||||
return Etag(o.Id, o.ExtraUpdateAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *Channel) IsValid() *AppError {
|
func (o *Channel) IsValid() *AppError {
|
||||||
|
|
||||||
if len(o.Id) != 26 {
|
if len(o.Id) != 26 {
|
||||||
return NewAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
return NewAppError("Channel.IsValid", "model.channel.is_valid.id.app_error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClusterInfo struct {
|
type ClusterInfo struct {
|
||||||
@@ -22,11 +21,6 @@ func (me *ClusterInfo) ToJson() string {
|
|||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *ClusterInfo) Copy() *ClusterInfo {
|
|
||||||
json := me.ToJson()
|
|
||||||
return ClusterInfoFromJson(strings.NewReader(json))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
|
func ClusterInfoFromJson(data io.Reader) *ClusterInfo {
|
||||||
var me *ClusterInfo
|
var me *ClusterInfo
|
||||||
json.NewDecoder(data).Decode(&me)
|
json.NewDecoder(data).Decode(&me)
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ const (
|
|||||||
SERVICE_GOOGLE = "google"
|
SERVICE_GOOGLE = "google"
|
||||||
SERVICE_OFFICE365 = "office365"
|
SERVICE_OFFICE365 = "office365"
|
||||||
|
|
||||||
WEBSERVER_MODE_REGULAR = "regular"
|
|
||||||
WEBSERVER_MODE_GZIP = "gzip"
|
|
||||||
WEBSERVER_MODE_DISABLED = "disabled"
|
|
||||||
|
|
||||||
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
|
GENERIC_NO_CHANNEL_NOTIFICATION = "generic_no_channel"
|
||||||
GENERIC_NOTIFICATION = "generic"
|
GENERIC_NOTIFICATION = "generic"
|
||||||
FULL_NOTIFICATION = "full"
|
FULL_NOTIFICATION = "full"
|
||||||
@@ -99,15 +95,12 @@ const (
|
|||||||
|
|
||||||
EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION = ""
|
EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION = ""
|
||||||
|
|
||||||
SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK = "https://about.mattermost.com/default-terms/"
|
SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK = "https://about.mattermost.com/default-terms/"
|
||||||
SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK = "https://about.mattermost.com/default-privacy-policy/"
|
SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK = "https://about.mattermost.com/default-privacy-policy/"
|
||||||
SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK = "https://about.mattermost.com/default-about/"
|
SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK = "https://about.mattermost.com/default-about/"
|
||||||
SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/"
|
SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/"
|
||||||
SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/"
|
SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/"
|
||||||
SUPPORT_SETTINGS_DEFAULT_ADMINISTRATORS_GUIDE_LINK = "https://about.mattermost.com/administrators-guide/"
|
SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com"
|
||||||
SUPPORT_SETTINGS_DEFAULT_TROUBLESHOOTING_FORUM_LINK = "https://about.mattermost.com/troubleshooting-forum/"
|
|
||||||
SUPPORT_SETTINGS_DEFAULT_COMMERCIAL_SUPPORT_LINK = "https://about.mattermost.com/commercial-support/"
|
|
||||||
SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com"
|
|
||||||
|
|
||||||
LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = ""
|
LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = ""
|
||||||
LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE = ""
|
LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE = ""
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ func (emoji *Emoji) PreSave() {
|
|||||||
emoji.UpdateAt = emoji.CreateAt
|
emoji.UpdateAt = emoji.CreateAt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emoji *Emoji) PreUpdate() {
|
|
||||||
emoji.UpdateAt = GetMillis()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (emoji *Emoji) ToJson() string {
|
func (emoji *Emoji) ToJson() string {
|
||||||
b, _ := json.Marshal(emoji)
|
b, _ := json.Marshal(emoji)
|
||||||
return string(b)
|
return string(b)
|
||||||
|
|||||||
@@ -5,5 +5,4 @@ package model
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
USER_AUTH_SERVICE_LDAP = "ldap"
|
USER_AUTH_SERVICE_LDAP = "ldap"
|
||||||
LDAP_SYNC_TASK_NAME = "LDAP Syncronization"
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,15 +13,6 @@ import (
|
|||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
PLUGIN_CONFIG_TYPE_TEXT = "text"
|
|
||||||
PLUGIN_CONFIG_TYPE_BOOL = "bool"
|
|
||||||
PLUGIN_CONFIG_TYPE_RADIO = "radio"
|
|
||||||
PLUGIN_CONFIG_TYPE_DROPDOWN = "dropdown"
|
|
||||||
PLUGIN_CONFIG_TYPE_GENERATED = "generated"
|
|
||||||
PLUGIN_CONFIG_TYPE_USERNAME = "username"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PluginOption struct {
|
type PluginOption struct {
|
||||||
// The display name for the option.
|
// The display name for the option.
|
||||||
DisplayName string `json:"display_name" yaml:"display_name"`
|
DisplayName string `json:"display_name" yaml:"display_name"`
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func TestManifestUnmarshal(t *testing.T) {
|
|||||||
&PluginSetting{
|
&PluginSetting{
|
||||||
Key: "thesetting",
|
Key: "thesetting",
|
||||||
DisplayName: "thedisplayname",
|
DisplayName: "thedisplayname",
|
||||||
Type: PLUGIN_CONFIG_TYPE_DROPDOWN,
|
Type: "dropdown",
|
||||||
HelpText: "thehelptext",
|
HelpText: "thehelptext",
|
||||||
RegenerateHelpText: "theregeneratehelptext",
|
RegenerateHelpText: "theregeneratehelptext",
|
||||||
Placeholder: "theplaceholder",
|
Placeholder: "theplaceholder",
|
||||||
@@ -181,7 +181,7 @@ func TestManifestJson(t *testing.T) {
|
|||||||
&PluginSetting{
|
&PluginSetting{
|
||||||
Key: "thesetting",
|
Key: "thesetting",
|
||||||
DisplayName: "thedisplayname",
|
DisplayName: "thedisplayname",
|
||||||
Type: PLUGIN_CONFIG_TYPE_DROPDOWN,
|
Type: "dropdown",
|
||||||
HelpText: "thehelptext",
|
HelpText: "thehelptext",
|
||||||
RegenerateHelpText: "theregeneratehelptext",
|
RegenerateHelpText: "theregeneratehelptext",
|
||||||
Placeholder: "theplaceholder",
|
Placeholder: "theplaceholder",
|
||||||
@@ -246,7 +246,7 @@ func TestManifestClientManifest(t *testing.T) {
|
|||||||
&PluginSetting{
|
&PluginSetting{
|
||||||
Key: "thesetting",
|
Key: "thesetting",
|
||||||
DisplayName: "thedisplayname",
|
DisplayName: "thedisplayname",
|
||||||
Type: PLUGIN_CONFIG_TYPE_DROPDOWN,
|
Type: "dropdown",
|
||||||
HelpText: "thehelptext",
|
HelpText: "thehelptext",
|
||||||
RegenerateHelpText: "theregeneratehelptext",
|
RegenerateHelpText: "theregeneratehelptext",
|
||||||
Placeholder: "theplaceholder",
|
Placeholder: "theplaceholder",
|
||||||
|
|||||||
@@ -141,17 +141,6 @@ func OAuthAppFromJson(data io.Reader) *OAuthApp {
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
func OAuthAppMapToJson(a map[string]*OAuthApp) string {
|
|
||||||
b, _ := json.Marshal(a)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OAuthAppMapFromJson(data io.Reader) map[string]*OAuthApp {
|
|
||||||
var apps map[string]*OAuthApp
|
|
||||||
json.NewDecoder(data).Decode(&apps)
|
|
||||||
return apps
|
|
||||||
}
|
|
||||||
|
|
||||||
func OAuthAppListToJson(l []*OAuthApp) string {
|
func OAuthAppListToJson(l []*OAuthApp) string {
|
||||||
b, _ := json.Marshal(l)
|
b, _ := json.Marshal(l)
|
||||||
return string(b)
|
return string(b)
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ import (
|
|||||||
const (
|
const (
|
||||||
USER_AUTH_SERVICE_SAML = "saml"
|
USER_AUTH_SERVICE_SAML = "saml"
|
||||||
USER_AUTH_SERVICE_SAML_TEXT = "With SAML"
|
USER_AUTH_SERVICE_SAML_TEXT = "With SAML"
|
||||||
SAML_IDP_CERTIFICATE = 1
|
|
||||||
SAML_PRIVATE_KEY = 2
|
|
||||||
SAML_PUBLIC_CERT = 3
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SamlAuthRequest struct {
|
type SamlAuthRequest struct {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -20,11 +19,6 @@ type SearchParams struct {
|
|||||||
OrTerms bool
|
OrTerms bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *SearchParams) ToJson() string {
|
|
||||||
b, _ := json.Marshal(o)
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
var searchFlags = [...]string{"from", "channel", "in"}
|
var searchFlags = [...]string{"from", "channel", "in"}
|
||||||
|
|
||||||
func splitWords(text string) []string {
|
func splitWords(text string) []string {
|
||||||
|
|||||||
@@ -243,15 +243,6 @@ func (o *Team) Sanitize() {
|
|||||||
o.AllowedDomains = ""
|
o.AllowedDomains = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Team) SanitizeForNotLoggedIn() {
|
|
||||||
o.Email = ""
|
|
||||||
o.AllowedDomains = ""
|
|
||||||
o.CompanyName = ""
|
|
||||||
if !o.AllowOpenInvite {
|
|
||||||
o.InviteId = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Team) Patch(patch *TeamPatch) {
|
func (t *Team) Patch(patch *TeamPatch) {
|
||||||
if patch.DisplayName != nil {
|
if patch.DisplayName != nil {
|
||||||
t.DisplayName = *patch.DisplayName
|
t.DisplayName = *patch.DisplayName
|
||||||
|
|||||||
@@ -373,12 +373,6 @@ func (u *User) MakeNonNil() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) AddProp(key string, value string) {
|
|
||||||
u.MakeNonNil()
|
|
||||||
|
|
||||||
u.Props[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) AddNotifyProp(key string, value string) {
|
func (u *User) AddNotifyProp(key string, value string) {
|
||||||
u.MakeNonNil()
|
u.MakeNonNil()
|
||||||
|
|
||||||
|
|||||||
@@ -394,9 +394,6 @@ func ClearMentionTags(post string) string {
|
|||||||
return post
|
return post
|
||||||
}
|
}
|
||||||
|
|
||||||
var UrlRegex = regexp.MustCompile(`^((?:[a-z]+:\/\/)?(?:(?:[a-z0-9\-]+\.)+(?:[a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(?:\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(?:\?[a-z0-9+_~\-\.%=&]*)?)?(?:#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(?:\s+|$)$`)
|
|
||||||
var PartialUrlRegex = regexp.MustCompile(`/([A-Za-z0-9]{26})/([A-Za-z0-9]{26})/((?:[A-Za-z0-9]{26})?.+(?:\.[A-Za-z0-9]{3,})?)`)
|
|
||||||
|
|
||||||
func IsValidHttpUrl(rawUrl string) bool {
|
func IsValidHttpUrl(rawUrl string) bool {
|
||||||
if strings.Index(rawUrl, "http://") != 0 && strings.Index(rawUrl, "https://") != 0 {
|
if strings.Index(rawUrl, "http://") != 0 && strings.Index(rawUrl, "https://") != 0 {
|
||||||
return false
|
return false
|
||||||
@@ -409,18 +406,6 @@ func IsValidHttpUrl(rawUrl string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsValidHttpsUrl(rawUrl string) bool {
|
|
||||||
if strings.Index(rawUrl, "https://") != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := url.ParseRequestURI(rawUrl); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsValidTurnOrStunServer(rawUri string) bool {
|
func IsValidTurnOrStunServer(rawUri string) bool {
|
||||||
if strings.Index(rawUri, "turn:") != 0 && strings.Index(rawUri, "stun:") != 0 {
|
if strings.Index(rawUri, "turn:") != 0 && strings.Index(rawUri, "stun:") != 0 {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -107,10 +107,6 @@ func GetPreviousVersion(version string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsOfficalBuild() bool {
|
|
||||||
return BuildNumber != "_BUILD_NUMBER_"
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsCurrentVersion(versionToCheck string) bool {
|
func IsCurrentVersion(versionToCheck string) bool {
|
||||||
currentMajor, currentMinor, _ := SplitVersion(CurrentVersion)
|
currentMajor, currentMinor, _ := SplitVersion(CurrentVersion)
|
||||||
toCheckMajor, toCheckMinor, _ := SplitVersion(versionToCheck)
|
toCheckMajor, toCheckMinor, _ := SplitVersion(versionToCheck)
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ package store
|
|||||||
import "github.com/mattermost/mattermost-server/model"
|
import "github.com/mattermost/mattermost-server/model"
|
||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
type ResultHandler func(*StoreResult)
|
|
||||||
|
|
||||||
type LayeredStoreSupplierResult struct {
|
type LayeredStoreSupplierResult struct {
|
||||||
StoreResult
|
StoreResult
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MODE_DEV = "dev"
|
|
||||||
MODE_BETA = "beta"
|
|
||||||
MODE_PROD = "prod"
|
|
||||||
LOG_ROTATE_SIZE = 10000
|
LOG_ROTATE_SIZE = 10000
|
||||||
LOG_FILENAME = "mattermost.log"
|
LOG_FILENAME = "mattermost.log"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -91,11 +91,6 @@ func GetUserTranslations(locale string) i18n.TranslateFunc {
|
|||||||
return translations
|
return translations
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetTranslations(locale string) i18n.TranslateFunc {
|
|
||||||
translations := TfuncWithFallback(locale)
|
|
||||||
return translations
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetTranslationsAndLocale(w http.ResponseWriter, r *http.Request) (i18n.TranslateFunc, string) {
|
func GetTranslationsAndLocale(w http.ResponseWriter, r *http.Request) (i18n.TranslateFunc, string) {
|
||||||
// This is for checking against locales like pt_BR or zn_CN
|
// This is for checking against locales like pt_BR or zn_CN
|
||||||
headerLocaleFull := strings.Split(r.Header.Get("Accept-Language"), ",")[0]
|
headerLocaleFull := strings.Split(r.Header.Get("Accept-Language"), ",")[0]
|
||||||
|
|||||||
33
utils/log.go
33
utils/log.go
@@ -1,33 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
l4g "github.com/alecthomas/log4go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// InfoReader logs the content of the io.Reader and returns a new io.Reader
|
|
||||||
// with the same content as the received io.Reader.
|
|
||||||
// If you pass reader by reference, it won't be re-created unless the loglevel
|
|
||||||
// includes Debug.
|
|
||||||
// If an error is returned, the reader is consumed an cannot be read again.
|
|
||||||
func InfoReader(reader io.Reader, message string) (io.Reader, error) {
|
|
||||||
var err error
|
|
||||||
l4g.Info(func() string {
|
|
||||||
content, err := ioutil.ReadAll(reader)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
reader = bytes.NewReader(content)
|
|
||||||
|
|
||||||
return message + string(content)
|
|
||||||
})
|
|
||||||
|
|
||||||
return reader, err
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
// glue functions that allow logger.go to leverage log4Go to write JSON-formatted log records to a file
|
|
||||||
|
|
||||||
package logger
|
|
||||||
|
|
||||||
import (
|
|
||||||
l4g "github.com/alecthomas/log4go"
|
|
||||||
"github.com/mattermost/mattermost-server/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
// newJSONLogWriter is a utility method for creating a FileLogWriter set up to
|
|
||||||
// output JSON record log messages instead of line-based ones.
|
|
||||||
func newJSONLogWriter(fname string, rotate bool) *l4g.FileLogWriter {
|
|
||||||
return l4g.NewFileLogWriter(fname, rotate).SetFormat(
|
|
||||||
`{"level": "%L",
|
|
||||||
"timestamp": "%D %T",
|
|
||||||
"source": "%S",
|
|
||||||
"message": %M
|
|
||||||
}`).SetRotateLines(utils.LOG_ROTATE_SIZE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewJSONFileLogger - Create a new logger with a "file" filter configured to send JSON-formatted log messages at
|
|
||||||
// or above lvl to a file with the specified filename.
|
|
||||||
func NewJSONFileLogger(lvl l4g.Level, filename string) l4g.Logger {
|
|
||||||
return l4g.Logger{
|
|
||||||
"file": &l4g.Filter{Level: lvl, LogWriter: newJSONLogWriter(filename, false)},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See License.txt for license information.
|
|
||||||
|
|
||||||
// this is a new logger interface for mattermost
|
|
||||||
|
|
||||||
package logger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
l4g "github.com/alecthomas/log4go"
|
|
||||||
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
|
||||||
"github.com/mattermost/mattermost-server/utils"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// this pattern allows us to "mock" the underlying l4g code when unit testing
|
|
||||||
var logger l4g.Logger
|
|
||||||
var debugLog = l4g.Debug
|
|
||||||
var infoLog = l4g.Info
|
|
||||||
var errorLog = l4g.Error
|
|
||||||
|
|
||||||
// assumes that ../config.go::configureLog has already been called, and has in turn called l4g.close() to clean up
|
|
||||||
// any old filters that we might have previously created
|
|
||||||
func initL4g(logSettings model.LogSettings) {
|
|
||||||
// TODO: add support for newConfig.LogSettings.EnableConsole. Right now, ../config.go sets it up in its configureLog
|
|
||||||
// method. If we also set it up here, messages will be written to the console twice. Eventually, when all instances
|
|
||||||
// of l4g have been replaced by this logger, we can move that code to here
|
|
||||||
if logSettings.EnableFile {
|
|
||||||
level := l4g.DEBUG
|
|
||||||
if logSettings.FileLevel == "INFO" {
|
|
||||||
level = l4g.INFO
|
|
||||||
} else if logSettings.FileLevel == "WARN" {
|
|
||||||
level = l4g.WARNING
|
|
||||||
} else if logSettings.FileLevel == "ERROR" {
|
|
||||||
level = l4g.ERROR
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a logger that writes JSON objects to a file, and override our log methods to use it
|
|
||||||
if logger != nil {
|
|
||||||
logger.Close()
|
|
||||||
}
|
|
||||||
logger = NewJSONFileLogger(level, utils.GetLogFileLocation(logSettings.FileLocation)+".jsonl")
|
|
||||||
debugLog = logger.Debug
|
|
||||||
infoLog = logger.Info
|
|
||||||
errorLog = logger.Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// contextKey lets us add contextual information to log messages
|
|
||||||
type contextKey string
|
|
||||||
|
|
||||||
func (c contextKey) String() string {
|
|
||||||
return string(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextKeyUserID contextKey = contextKey("user_id")
|
|
||||||
const contextKeyRequestID contextKey = contextKey("request_id")
|
|
||||||
|
|
||||||
// any contextKeys added to this array will be serialized in every log message
|
|
||||||
var contextKeys = [2]contextKey{contextKeyUserID, contextKeyRequestID}
|
|
||||||
|
|
||||||
// WithUserId adds a user id to the specified context. If the returned Context is subsequently passed to a logging
|
|
||||||
// method, the user id will automatically be included in the logged message
|
|
||||||
func WithUserId(ctx context.Context, userID string) context.Context {
|
|
||||||
return context.WithValue(ctx, contextKeyUserID, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRequestId adds a request id to the specified context. If the returned Context is subsequently passed to a logging
|
|
||||||
// method, the request id will automatically be included in the logged message
|
|
||||||
func WithRequestId(ctx context.Context, requestID string) context.Context {
|
|
||||||
return context.WithValue(ctx, contextKeyRequestID, requestID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// extracts known contextKey values from the specified Context and assembles them into the returned map
|
|
||||||
func serializeContext(ctx context.Context) map[string]string {
|
|
||||||
serialized := make(map[string]string)
|
|
||||||
for _, key := range contextKeys {
|
|
||||||
value, ok := ctx.Value(key).(string)
|
|
||||||
if ok {
|
|
||||||
serialized[string(key)] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return serialized
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the path to the next file up the callstack that has a different name than this file
|
|
||||||
// in other words, finds the path to the file that is doing the logging.
|
|
||||||
// Removes machine-specific prefix, so returned path starts with /mattermost-server.
|
|
||||||
// Looks a maximum of 10 frames up the call stack to find a file that has a different name than this one.
|
|
||||||
func getCallerFilename() (string, error) {
|
|
||||||
_, currentFilename, _, ok := runtime.Caller(0)
|
|
||||||
if !ok {
|
|
||||||
return "", errors.New("Failed to traverse stack frame")
|
|
||||||
}
|
|
||||||
|
|
||||||
platformDirectory := currentFilename
|
|
||||||
for filepath.Base(platformDirectory) != "platform" {
|
|
||||||
platformDirectory = filepath.Dir(platformDirectory)
|
|
||||||
if platformDirectory == "." || platformDirectory == string(filepath.Separator) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 1; i < 10; i++ {
|
|
||||||
_, parentFilename, _, ok := runtime.Caller(i)
|
|
||||||
if !ok {
|
|
||||||
return "", errors.New("Failed to traverse stack frame")
|
|
||||||
} else if parentFilename != currentFilename && strings.Contains(parentFilename, platformDirectory) {
|
|
||||||
// trim parentFilename such that we return the path to parentFilename, relative to platformDirectory
|
|
||||||
return parentFilename[strings.LastIndex(parentFilename, platformDirectory)+len(platformDirectory)+1:], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", errors.New("Failed to traverse stack frame")
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates a JSON representation of a log message
|
|
||||||
func serializeLogMessage(ctx context.Context, message string) string {
|
|
||||||
callerFilename, err := getCallerFilename()
|
|
||||||
if err != nil {
|
|
||||||
callerFilename = "Unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes, err := json.Marshal(&struct {
|
|
||||||
Context map[string]string `json:"context"`
|
|
||||||
File string `json:"file"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}{
|
|
||||||
serializeContext(ctx),
|
|
||||||
callerFilename,
|
|
||||||
message,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
errorLog("Failed to serialize log message %v", message)
|
|
||||||
}
|
|
||||||
return string(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatMessage(args ...interface{}) string {
|
|
||||||
msg, ok := args[0].(string)
|
|
||||||
if !ok {
|
|
||||||
panic("Second argument is not of type string")
|
|
||||||
}
|
|
||||||
if len(args) > 1 {
|
|
||||||
variables := args[1:]
|
|
||||||
msg = fmt.Sprintf(msg, variables...)
|
|
||||||
}
|
|
||||||
return msg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugc logs a debugLog level message, including context information that is stored in the first parameter.
|
|
||||||
// If two parameters are supplied, the second must be a message string, and will be logged directly.
|
|
||||||
// If more than two parameters are supplied, the second parameter must be a format string, and the remaining parameters
|
|
||||||
// must be the variables to substitute into the format string, following the convention of the fmt.Sprintf(...) function.
|
|
||||||
func Debugc(ctx context.Context, args ...interface{}) {
|
|
||||||
debugLog(func() string {
|
|
||||||
msg := formatMessage(args...)
|
|
||||||
return serializeLogMessage(ctx, msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debugf logs a debugLog level message.
|
|
||||||
// If one parameter is supplied, it must be a message string, and will be logged directly.
|
|
||||||
// If two or more parameters are specified, the first parameter must be a format string, and the remaining parameters
|
|
||||||
// must be the variables to substitute into the format string, following the convention of the fmt.Sprintf(...) function.
|
|
||||||
func Debugf(args ...interface{}) {
|
|
||||||
debugLog(func() string {
|
|
||||||
msg := formatMessage(args...)
|
|
||||||
return serializeLogMessage(context.Background(), msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infoc logs an infoLog level message, including context information that is stored in the first parameter.
|
|
||||||
// If two parameters are supplied, the second must be a message string, and will be logged directly.
|
|
||||||
// If more than two parameters are supplied, the second parameter must be a format string, and the remaining parameters
|
|
||||||
// must be the variables to substitute into the format string, following the convention of the fmt.Sprintf(...) function.
|
|
||||||
func Infoc(ctx context.Context, args ...interface{}) {
|
|
||||||
infoLog(func() string {
|
|
||||||
msg := formatMessage(args...)
|
|
||||||
return serializeLogMessage(ctx, msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infof logs an infoLog level message.
|
|
||||||
// If one parameter is supplied, it must be a message string, and will be logged directly.
|
|
||||||
// If two or more parameters are specified, the first parameter must be a format string, and the remaining parameters
|
|
||||||
// must be the variables to substitute into the format string, following the convention of the fmt.Sprintf(...) function.
|
|
||||||
func Infof(args ...interface{}) {
|
|
||||||
infoLog(func() string {
|
|
||||||
msg := formatMessage(args...)
|
|
||||||
return serializeLogMessage(context.Background(), msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorc logs an error level message, including context information that is stored in the first parameter.
|
|
||||||
// If two parameters are supplied, the second must be a message string, and will be logged directly.
|
|
||||||
// If more than two parameters are supplied, the second parameter must be a format string, and the remaining parameters
|
|
||||||
// must be the variables to substitute into the format string, following the convention of the fmt.Sprintf(...) function.
|
|
||||||
func Errorc(ctx context.Context, args ...interface{}) {
|
|
||||||
errorLog(func() string {
|
|
||||||
msg := formatMessage(args...)
|
|
||||||
return serializeLogMessage(ctx, msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf logs an error level message.
|
|
||||||
// If one parameter is supplied, it must be a message string, and will be logged directly.
|
|
||||||
// If two or more parameters are specified, the first parameter must be a format string, and the remaining parameters
|
|
||||||
// must be the variables to substitute into the format string, following the convention of the fmt.Sprintf(...) function.
|
|
||||||
func Errorf(args ...interface{}) {
|
|
||||||
errorLog(func() string {
|
|
||||||
msg := formatMessage(args...)
|
|
||||||
return serializeLogMessage(context.Background(), msg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -186,10 +186,8 @@ func sendMail(mimeTo, smtpTo string, from mail.Address, subject, htmlBody string
|
|||||||
"Auto-Submitted": {"auto-generated"},
|
"Auto-Submitted": {"auto-generated"},
|
||||||
"Precedence": {"bulk"},
|
"Precedence": {"bulk"},
|
||||||
}
|
}
|
||||||
if mimeHeaders != nil {
|
for k, v := range mimeHeaders {
|
||||||
for k, v := range mimeHeaders {
|
headers[k] = []string{encodeRFC2047Word(v)}
|
||||||
headers[k] = []string{encodeRFC2047Word(v)}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m := gomail.NewMessage(gomail.SetCharset("UTF-8"))
|
m := gomail.NewMessage(gomail.SetCharset("UTF-8"))
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user