Add auditing to server CLI.

Also:
- simplify auditing in API layer
- reduce number of AddMeta calls
- have models serialize themselves
- more consistent field naming
Этот коммит содержится в:
Doug Lauder
2020-04-08 00:52:30 -04:00
коммит произвёл GitHub
родитель e2d1af17de
Коммит 6a27ed4a1d
45 изменённых файлов: 1488 добавлений и 244 удалений

Просмотреть файл

@@ -42,6 +42,7 @@ func createBot(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createBot", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("bot", bot)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_CREATE_BOT) {
c.SetPermissionError(model.PERMISSION_CREATE_BOT)
@@ -67,9 +68,7 @@ func createBot(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
// Note that the primary key of a bot is the UserId, and matches the primary key of the
// corresponding user.
auditRec.AddMeta("bot_id", createdBot.UserId)
auditRec.AddMeta("bot", createdBot) // overwrite meta
w.WriteHeader(http.StatusCreated)
w.Write(createdBot.ToJson())
@@ -104,6 +103,7 @@ func patchBot(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("bot", updatedBot)
w.Write(updatedBot.ToJson())
}
@@ -214,6 +214,7 @@ func updateBotActive(c *Context, w http.ResponseWriter, r *http.Request, active
}
auditRec.Success()
auditRec.AddMeta("bot", bot)
w.Write(bot.ToJson())
}
@@ -251,6 +252,7 @@ func assignBot(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("bot", bot)
w.Write(bot.ToJson())
}

Просмотреть файл

@@ -73,7 +73,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createChannel", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channel", channel)
if channel.Type == model.CHANNEL_OPEN && !c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_CREATE_PUBLIC_CHANNEL) {
c.SetPermissionError(model.PERMISSION_CREATE_PUBLIC_CHANNEL)
@@ -92,7 +92,7 @@ func createChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("channel_id", sc.Id)
auditRec.AddMeta("channel", sc) // overwrite meta
c.LogAudit("name=" + channel.Name)
w.WriteHeader(http.StatusCreated)
@@ -120,7 +120,6 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateChannel", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
originalOldChannel, err := c.App.GetChannel(channel.Id)
if err != nil {
@@ -129,7 +128,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
oldChannel := originalOldChannel.DeepCopy()
auditRec.AddMeta("channel_name", oldChannel.Name)
auditRec.AddMeta("channel", oldChannel)
switch oldChannel.Type {
case model.CHANNEL_OPEN:
@@ -146,7 +145,7 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
case model.CHANNEL_GROUP, model.CHANNEL_DIRECT:
// Modifying the header is not linked to any specific permission for group/dm channels, so just check for membership.
if _, err := c.App.GetChannelMember(channel.Id, c.App.Session().UserId); err != nil {
if _, errGet := c.App.GetChannelMember(channel.Id, c.App.Session().UserId); errGet != nil {
c.Err = model.NewAppError("updateChannel", "api.channel.patch_update_channel.forbidden.app_error", nil, "", http.StatusForbidden)
return
}
@@ -191,10 +190,12 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
oldChannel.GroupConstrained = channel.GroupConstrained
}
if _, err := c.App.UpdateChannel(oldChannel); err != nil {
updatedChannel, err := c.App.UpdateChannel(oldChannel)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("update", updatedChannel)
if oldChannelDisplayName != channel.DisplayName {
if err := c.App.PostUpdateChannelDisplayNameMessage(c.App.Session().UserId, channel, oldChannelDisplayName, channel.DisplayName); err != nil {
@@ -222,8 +223,7 @@ func convertChannelToPrivate(c *Context, w http.ResponseWriter, r *http.Request)
auditRec := c.MakeAuditRecord("convertChannelToPrivate", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", oldPublicChannel.Id)
auditRec.AddMeta("channel_name", oldPublicChannel.Name)
auditRec.AddMeta("channel", oldPublicChannel)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), oldPublicChannel.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
@@ -245,6 +245,7 @@ func convertChannelToPrivate(c *Context, w http.ResponseWriter, r *http.Request)
c.Err = err
return
}
auditRec.AddMeta("user", user)
oldPublicChannel.Type = model.CHANNEL_PRIVATE
@@ -281,10 +282,8 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateChannelPrivacy", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channel_type", channel.Type)
auditRec.AddMeta("new_channel_type", privacy)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("new_type", privacy)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
@@ -301,6 +300,7 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("user", user)
channel.Type = privacy
@@ -337,8 +337,7 @@ func patchChannel(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchChannel", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", oldChannel.Id)
auditRec.AddMeta("channel_name", oldChannel.Name)
auditRec.AddMeta("channel", oldChannel)
switch oldChannel.Type {
case model.CHANNEL_OPEN:
@@ -379,6 +378,7 @@ func patchChannel(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec.Success()
c.LogAudit("")
auditRec.AddMeta("patch", rchannel)
w.Write([]byte(rchannel.ToJson()))
}
@@ -398,8 +398,7 @@ func restoreChannel(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("restoreChannel", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channel", channel)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), teamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
@@ -475,8 +474,7 @@ func createDirectChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("channel_id", sc.Id)
auditRec.AddMeta("channel_name", sc.Name)
auditRec.AddMeta("channel", sc)
w.WriteHeader(http.StatusCreated)
w.Write([]byte(sc.ToJson()))
@@ -555,8 +553,7 @@ func createGroupChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("channel_id", groupChannel.Id)
auditRec.AddMeta("channel_name", groupChannel.Name)
auditRec.AddMeta("channel", groupChannel)
w.WriteHeader(http.StatusCreated)
w.Write([]byte(groupChannel.ToJson()))
@@ -1012,8 +1009,7 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("deleteChannel", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channeld", channel)
if channel.Type == model.CHANNEL_DIRECT || channel.Type == model.CHANNEL_GROUP {
c.Err = model.NewAppError("deleteChannel", "api.channel.delete_channel.type.invalid", nil, "", http.StatusBadRequest)
@@ -1404,8 +1400,7 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("addChannelMember", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channel", channel)
if channel.Type == model.CHANNEL_DIRECT || channel.Type == model.CHANNEL_GROUP {
c.Err = model.NewAppError("addUserToChannel", "api.channel.add_user_to_channel.type.app_error", nil, "", http.StatusBadRequest)
@@ -1506,8 +1501,7 @@ func removeChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("removeChannelMember", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("remove_user_id", user.Id)
if !(channel.Type == model.CHANNEL_OPEN || channel.Type == model.CHANNEL_PRIVATE) {
@@ -1586,8 +1580,7 @@ func updateChannelScheme(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("old_scheme_id", channel.SchemeId)
channel.SchemeId = &scheme.Id
@@ -1701,6 +1694,9 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request)
return
}
auditRec := c.MakeAuditRecord("patchChannelModerations", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
@@ -1711,6 +1707,7 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request)
c.Err = err
return
}
auditRec.AddMeta("channel", channel)
channelModerationsPatch := model.ChannelModerationsPatchFromJson(r.Body)
channelModerations, err := c.App.PatchChannelModerationsForChannel(channel, channelModerationsPatch)
@@ -1718,6 +1715,7 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request)
c.Err = err
return
}
auditRec.AddMeta("patch", channelModerationsPatch)
b, marshalErr := json.Marshal(channelModerations)
if marshalErr != nil {
@@ -1725,5 +1723,6 @@ func patchChannelModerations(c *Context, w http.ResponseWriter, r *http.Request)
return
}
auditRec.Success()
w.Write(b)
}

Просмотреть файл

@@ -51,8 +51,8 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("command_id", rcmd.Id)
c.LogAudit("success")
auditRec.AddMeta("command", rcmd)
w.WriteHeader(http.StatusCreated)
w.Write([]byte(rcmd.ToJson()))
@@ -71,15 +71,16 @@ func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec := c.MakeAuditRecord("updateCommand", audit.Fail)
auditRec.AddMeta("command_id", c.Params.CommandId)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
oldCmd, err := c.App.GetCommand(c.Params.CommandId)
if err != nil {
auditRec.AddMeta("command_id", c.Params.CommandId)
c.SetCommandNotFoundError()
return
}
auditRec.AddMeta("command", oldCmd)
if cmd.TeamId != oldCmd.TeamId {
c.Err = model.NewAppError("updateCommand", "api.command.team_mismatch.app_error", nil, "user_id="+c.App.Session().UserId, http.StatusBadRequest)
@@ -125,8 +126,6 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec := c.MakeAuditRecord("moveCommand", audit.Fail)
auditRec.AddMeta("command_id", c.Params.CommandId)
auditRec.AddMeta("to_team_id", cmr.TeamId)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
@@ -135,6 +134,7 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = appErr
return
}
auditRec.AddMeta("team", newTeam)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), newTeam.Id, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
c.LogAudit("fail - inappropriate permissions")
@@ -147,7 +147,7 @@ func moveCommand(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetCommandNotFoundError()
return
}
auditRec.AddMeta("from_team_id", cmd.TeamId)
auditRec.AddMeta("command", cmd)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), cmd.TeamId, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
c.LogAudit("fail - inappropriate permissions")
@@ -175,7 +175,6 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec := c.MakeAuditRecord("deleteCommand", audit.Fail)
auditRec.AddMeta("command_id", c.Params.CommandId)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
@@ -184,6 +183,7 @@ func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetCommandNotFoundError()
return
}
auditRec.AddMeta("command", cmd)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), cmd.TeamId, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
c.LogAudit("fail - inappropriate permissions")
@@ -301,6 +301,10 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("executeCommand", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("commandargs", commandArgs)
// checks that user is a member of the specified channel, and that they have permission to use slash commands in it
if !c.App.SessionHasPermissionToChannel(*c.App.Session(), commandArgs.ChannelId, model.PERMISSION_USE_SLASH_COMMANDS) {
c.SetPermissionError(model.PERMISSION_USE_SLASH_COMMANDS)
@@ -333,12 +337,15 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
commandArgs.Session = *c.App.Session()
commandArgs.SiteURL = c.GetSiteURLHeader()
auditRec.AddMeta("commandargs", commandArgs) // overwrite in case teamid changed
response, err := c.App.ExecuteCommand(commandArgs)
if err != nil {
c.Err = err
return
}
auditRec.Success()
w.Write([]byte(response.ToJson()))
}
@@ -369,15 +376,16 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec := c.MakeAuditRecord("regenCommandToken", audit.Fail)
auditRec.AddMeta("command_id", c.Params.CommandId)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
cmd, err := c.App.GetCommand(c.Params.CommandId)
if err != nil {
auditRec.AddMeta("command_id", c.Params.CommandId)
c.SetCommandNotFoundError()
return
}
auditRec.AddMeta("command", cmd)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), cmd.TeamId, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
c.LogAudit("fail - inappropriate permissions")

Просмотреть файл

@@ -57,12 +57,16 @@ func getComplianceReports(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getComplianceReports", audit.Fail)
defer c.LogAuditRec(auditRec)
crs, err := c.App.GetComplianceReports(c.Params.Page, c.Params.PerPage)
if err != nil {
c.Err = err
return
}
auditRec.Success()
w.Write([]byte(crs.ToJson()))
}
@@ -72,6 +76,9 @@ func getComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getComplianceReport", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
@@ -83,6 +90,10 @@ func getComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
auditRec.AddMeta("compliance_id", job.Id)
auditRec.AddMeta("compliance_desc", job.Desc)
w.Write([]byte(job.ToJson()))
}
@@ -106,14 +117,16 @@ func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request
c.Err = err
return
}
auditRec.AddMeta("compliance_id", job.Id)
auditRec.AddMeta("compliance_desc", job.Desc)
reportBytes, err := c.App.GetComplianceFile(job)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("length", len(reportBytes))
auditRec.AddMeta("compliance_desc", job.Desc)
c.LogAudit("downloaded " + job.Desc)
w.Header().Set("Cache-Control", "max-age=2592000, public")

Просмотреть файл

@@ -28,8 +28,13 @@ func getConfig(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getConfig", audit.Fail)
defer c.LogAuditRec(auditRec)
cfg := c.App.GetSanitizedConfig()
auditRec.Success()
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(cfg.ToJson()))
}

Просмотреть файл

@@ -87,8 +87,7 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.AddMeta("emoji_id", emoji.Id)
auditRec.AddMeta("emoji_name", emoji.Name)
auditRec.AddMeta("emoji", emoji)
newEmoji, err := c.App.CreateEmoji(c.App.Session().UserId, emoji, m)
if err != nil {
@@ -129,14 +128,14 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("deleteEmoji", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("emoji_id", c.Params.EmojiId)
emoji, err := c.App.GetEmoji(c.Params.EmojiId)
if err != nil {
auditRec.AddMeta("emoji_id", c.Params.EmojiId)
c.Err = err
return
}
auditRec.AddMeta("emoji_name", emoji.Name)
auditRec.AddMeta("emoji", emoji)
// Allow any user with DELETE_EMOJIS permission at Team level to delete emojis at system level
memberships, err := c.App.GetTeamMembersForUser(c.App.Session().UserId)

Просмотреть файл

@@ -157,7 +157,6 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F
auditRec := c.MakeAuditRecord("uploadFileSimple", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", c.Params.ChannelId)
auditRec.AddMeta("filename", c.Params.Filename)
if !c.App.SessionHasPermissionToChannel(*c.App.Session(), c.Params.ChannelId, model.PERMISSION_UPLOAD_FILE) {
c.SetPermissionError(model.PERMISSION_UPLOAD_FILE)
@@ -166,7 +165,6 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F
clientId := r.Form.Get("client_id")
auditRec.AddMeta("client_id", clientId)
auditRec.AddMeta("content_length", r.ContentLength)
info, appErr := c.App.UploadFileX(c.Params.ChannelId, c.Params.Filename, r.Body,
app.UploadFileSetTeamId(FILE_TEAM_ID),
@@ -178,6 +176,7 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F
c.Err = appErr
return nil
}
auditRec.AddMeta("file", info)
fileUploadResponse := &model.FileUploadResponse{
FileInfos: []*model.FileInfo{info},
@@ -328,7 +327,6 @@ NEXT_PART:
auditRec := c.MakeAuditRecord("uploadFileMultipart", audit.Fail)
auditRec.AddMeta("channel_id", c.Params.ChannelId)
auditRec.AddMeta("filename", filename)
auditRec.AddMeta("client_id", clientId)
info, appErr := c.App.UploadFileX(c.Params.ChannelId, filename, part,
@@ -342,6 +340,8 @@ NEXT_PART:
c.LogAuditRec(auditRec)
return nil
}
auditRec.AddMeta("file", info)
auditRec.Success()
c.LogAuditRec(auditRec)
@@ -430,7 +430,6 @@ func uploadFileMultipartLegacy(c *Context, mr *multipart.Reader,
auditRec := c.MakeAuditRecord("uploadFileMultipartLegacy", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channelId)
auditRec.AddMeta("filename", fileHeader.Filename)
auditRec.AddMeta("client_id", clientId)
info, appErr := c.App.UploadFileX(c.Params.ChannelId, fileHeader.Filename, f,
@@ -445,6 +444,7 @@ func uploadFileMultipartLegacy(c *Context, mr *multipart.Reader,
c.LogAuditRec(auditRec)
return nil
}
auditRec.AddMeta("file", info)
auditRec.Success()
c.LogAuditRec(auditRec)
@@ -469,11 +469,16 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
forceDownload = false
}
auditRec := c.MakeAuditRecord("getFile", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("force_download", forceDownload)
info, err := c.App.GetFileInfo(c.Params.FileId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("file", info)
if info.CreatorId != c.App.Session().UserId && !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), info.PostId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
@@ -488,6 +493,8 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
}
defer fileReader.Close()
auditRec.Success()
err = writeFileResponse(info.Name, info.MimeType, info.Size, time.Unix(0, info.UpdateAt*int64(1000*1000)), *c.App.Config().ServiceSettings.WebserverMode, fileReader, forceDownload, w, r)
if err != nil {
c.Err = err
@@ -548,11 +555,15 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getFileLink", audit.Fail)
defer c.LogAuditRec(auditRec)
info, err := c.App.GetFileInfo(c.Params.FileId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("file", info)
if info.CreatorId != c.App.Session().UserId && !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), info.PostId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
@@ -565,7 +576,11 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) {
}
resp := make(map[string]string)
resp["link"] = c.App.GeneratePublicLink(c.GetSiteURLHeader(), info)
link := c.App.GeneratePublicLink(c.GetSiteURLHeader(), info)
resp["link"] = link
auditRec.Success()
auditRec.AddMeta("link", link)
w.Write([]byte(model.MapToJson(resp)))
}

Просмотреть файл

@@ -108,7 +108,6 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchGroup", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("group_id", c.Params.GroupId)
if c.App.License() == nil || !*c.App.License().Features.LDAPGroups {
c.Err = model.NewAppError("Api4.patchGroup", "api.ldap_groups.license_error", nil, "", http.StatusNotImplemented)
@@ -125,9 +124,7 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("old_group_name", group.Name)
auditRec.AddMeta("old_group_display", group.DisplayName)
auditRec.AddMeta("old_group_desc", group.Description)
auditRec.AddMeta("group", group)
group.Patch(groupPatch)
@@ -136,10 +133,7 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("new_group_name", group.Name)
auditRec.AddMeta("new_group_display", group.DisplayName)
auditRec.AddMeta("new_group_desc", group.Description)
auditRec.AddMeta("patch", group)
b, marshalErr := json.Marshal(group)
if marshalErr != nil {
@@ -148,7 +142,6 @@ func patchGroup(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
w.Write(b)
}

Просмотреть файл

@@ -47,7 +47,7 @@ func createJob(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createJob", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("job_type", job.Type)
auditRec.AddMeta("job", job)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_JOBS) {
c.SetPermissionError(model.PERMISSION_MANAGE_JOBS)
@@ -61,7 +61,7 @@ func createJob(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("job_id", job.Id)
auditRec.AddMeta("job", job) // overwrite meta
w.WriteHeader(http.StatusCreated)
w.Write([]byte(job.ToJson()))

Просмотреть файл

@@ -149,8 +149,7 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("ldap_group_id", ldapGroup.Id)
auditRec.AddMeta("ldap_group_desc", ldapGroup.Description)
auditRec.AddMeta("ldap_group", ldapGroup)
if ldapGroup == nil {
c.Err = model.NewAppError("Api4.linkLdapGroup", "api.ldap_group.not_found", nil, "", http.StatusNotFound)
@@ -163,8 +162,7 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if group != nil {
auditRec.AddMeta("group_id", group.Id)
auditRec.AddMeta("group_name", group.Name)
auditRec.AddMeta("group", group)
}
var status int
@@ -177,7 +175,6 @@ func linkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
displayName = ldapGroup.DisplayName
}
auditRec.AddMeta("ldap_group_display", displayName)
// Group has been previously linked
if group != nil {
@@ -251,8 +248,7 @@ func unlinkLdapGroup(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("group_id", group.Id)
auditRec.AddMeta("group_name", group.Name)
auditRec.AddMeta("group", group)
if group.DeleteAt == 0 {
_, err = c.App.DeleteGroup(group.Id)

Просмотреть файл

@@ -32,8 +32,6 @@ func createOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createOAuthApp", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("oauth_app_name", oauthApp.Name)
auditRec.AddMeta("oauth_app_desc", oauthApp.Description)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_OAUTH) {
c.SetPermissionError(model.PERMISSION_MANAGE_OAUTH)
@@ -53,8 +51,7 @@ func createOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("oauth_app_id", rapp.Id)
auditRec.AddMeta("client_id", rapp.Id)
auditRec.AddMeta("oauth_app", rapp)
c.LogAudit("client_id=" + rapp.Id)
w.WriteHeader(http.StatusCreated)
@@ -82,7 +79,6 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetInvalidParam("oauth_app")
return
}
auditRec.AddMeta("oauth_app_name", oauthApp.Name)
// The app being updated in the payload must be the same one as indicated in the URL.
if oauthApp.Id != c.Params.AppId {
@@ -95,6 +91,7 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("oauth_app", oldOauthApp)
if c.App.Session().UserId != oldOauthApp.CreatorId && !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH)
@@ -112,6 +109,7 @@ func updateOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("update", updatedOauthApp)
c.LogAudit("success")
w.Write([]byte(updatedOauthApp.ToJson()))
@@ -204,7 +202,7 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("oauth_app_name", oauthApp.Name)
auditRec.AddMeta("oauth_app", oauthApp)
if c.App.Session().UserId != oauthApp.CreatorId && !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH)
@@ -243,7 +241,7 @@ func regenerateOAuthAppSecret(c *Context, w http.ResponseWriter, r *http.Request
c.Err = err
return
}
auditRec.AddMeta("oauth_app_name", oauthApp.Name)
auditRec.AddMeta("oauth_app", oauthApp)
if oauthApp.CreatorId != c.App.Session().UserId && !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH)

Просмотреть файл

@@ -46,7 +46,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createPost", audit.Fail)
defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel)
auditRec.AddMeta("channel_id", post.ChannelId)
auditRec.AddMeta("post", post)
hasPermission := false
if c.App.SessionHasPermissionToChannel(*c.App.Session(), post.ChannelId, model.PERMISSION_CREATE_POST) {
@@ -73,7 +73,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
auditRec.AddMeta("post_id", rp.Id)
auditRec.AddMeta("post", rp) // overwrite meta
setOnline := r.URL.Query().Get("set_online")
setOnlineBool := true // By default, always set online.
@@ -378,8 +378,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PERMISSION_DELETE_POST)
return
}
auditRec.AddMeta("channel_id", post.ChannelId)
auditRec.AddMeta("creator_user_id", post.UserId)
auditRec.AddMeta("post", post)
if c.App.Session().UserId == post.UserId {
if !c.App.SessionHasPermissionToChannel(*c.App.Session(), post.ChannelId, model.PERMISSION_DELETE_POST) {
@@ -532,9 +531,6 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updatePost", audit.Fail)
defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel)
auditRec.AddMeta("post_id", post.Id)
auditRec.AddMeta("channel_id", post.ChannelId)
auditRec.AddMeta("creator_user_id", post.UserId)
// The post being updated in the payload must be the same one as indicated in the URL.
if post.Id != c.Params.PostId {
@@ -552,6 +548,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PERMISSION_EDIT_POST)
return
}
auditRec.AddMeta("post", originalPost)
// Updating the file_ids of a post is not a supported operation and will be ignored
post.FileIds = originalPost.FileIds
@@ -572,6 +569,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("update", rpost)
w.Write([]byte(rpost.ToJson()))
}
@@ -591,7 +589,6 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchPost", audit.Fail)
defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel)
auditRec.AddMeta("post_id", c.Params.PostId)
// Updating the file_ids of a post is not a supported operation and will be ignored
post.FileIds = nil
@@ -606,8 +603,7 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PERMISSION_EDIT_POST)
return
}
auditRec.AddMeta("channel_id", originalPost.ChannelId)
auditRec.AddMeta("creator_user_id", originalPost.UserId)
auditRec.AddMeta("post", originalPost)
if c.App.Session().UserId != originalPost.UserId {
if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_EDIT_OTHERS_POSTS) {
@@ -623,6 +619,7 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("patch", patchedPost)
w.Write([]byte(patchedPost.ToJson()))
}
@@ -657,7 +654,6 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, r *http.Request, isPinn
auditRec := c.MakeAuditRecord("saveIsPinnedPost", audit.Fail)
defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel)
auditRec.AddMeta("post_id", c.Params.PostId)
if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_READ_CHANNEL) {
c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
@@ -676,8 +672,7 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, r *http.Request, isPinn
c.Err = err
return
}
auditRec.AddMeta("channel_id", post.ChannelId)
auditRec.AddMeta("creator_user_id", post.UserId)
auditRec.AddMeta("post", post)
channel, err := c.App.GetChannel(post.ChannelId)
if err != nil {
@@ -696,11 +691,12 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, r *http.Request, isPinn
patch := &model.PostPatch{}
patch.IsPinned = model.NewBool(isPinned)
_, err = c.App.PatchPost(c.Params.PostId, patch)
patchedPost, err := c.App.PatchPost(c.Params.PostId, patch)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("patch", patchedPost)
auditRec.Success()
ReturnStatusOK(w)

Просмотреть файл

@@ -93,16 +93,13 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchRole", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("role_id", c.Params.RoleId)
oldRole, err := c.App.GetRole(c.Params.RoleId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("role_id", oldRole.Name)
auditRec.AddMeta("role_desc", oldRole.Description)
auditRec.AddMeta("role_display", oldRole.DisplayName)
auditRec.AddMeta("role", oldRole)
if c.App.License() == nil && patch.Permissions != nil {
if oldRole.Name == "system_guest" || oldRole.Name == "team_guest" || oldRole.Name == "channel_guest" {
@@ -154,6 +151,7 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("patch", role)
c.LogAudit("")
w.Write([]byte(role.ToJson()))

Просмотреть файл

@@ -29,9 +29,7 @@ func createScheme(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createScheme", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("scheme_name", scheme.Name)
auditRec.AddMeta("scheme_display", scheme.DisplayName)
auditRec.AddMeta("scheme_desc", scheme.Description)
auditRec.AddMeta("scheme", scheme)
if c.App.License() == nil || !*c.App.License().Features.CustomPermissionsSchemes {
c.Err = model.NewAppError("Api4.CreateScheme", "api.scheme.create_scheme.license.error", nil, "", http.StatusNotImplemented)
@@ -50,7 +48,7 @@ func createScheme(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("scheme_id", scheme.Id)
auditRec.AddMeta("scheme", scheme) // overwrite meta
w.WriteHeader(http.StatusCreated)
w.Write([]byte(scheme.ToJson()))
@@ -173,10 +171,6 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchScheme", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("scheme_id", c.Params.SchemeId)
auditRec.AddMeta("new_scheme_name", patch.Name)
auditRec.AddMeta("new_scheme_display", patch.DisplayName)
auditRec.AddMeta("new_scheme_desc", patch.Description)
if c.App.License() == nil || !*c.App.License().Features.CustomPermissionsSchemes {
c.Err = model.NewAppError("Api4.PatchScheme", "api.scheme.patch_scheme.license.error", nil, "", http.StatusNotImplemented)
@@ -188,9 +182,7 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("old_scheme_name", scheme.Name)
auditRec.AddMeta("old_scheme_display", scheme.DisplayName)
auditRec.AddMeta("old_scheme_desc", scheme.Description)
auditRec.AddMeta("scheme", scheme)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
@@ -202,6 +194,7 @@ func patchScheme(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("patch", scheme)
auditRec.Success()
c.LogAudit("")
@@ -217,7 +210,6 @@ func deleteScheme(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("deleteScheme", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("scheme_id", c.Params.SchemeId)
if c.App.License() == nil || !*c.App.License().Features.CustomPermissionsSchemes {
c.Err = model.NewAppError("Api4.DeleteScheme", "api.scheme.delete_scheme.license.error", nil, "", http.StatusNotImplemented)
@@ -229,11 +221,14 @@ func deleteScheme(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if _, err := c.App.DeleteScheme(c.Params.SchemeId); err != nil {
scheme, err := c.App.DeleteScheme(c.Params.SchemeId)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("scheme", scheme)
ReturnStatusOK(w)
}

Просмотреть файл

@@ -183,18 +183,24 @@ func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getAudits", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
}
audits, err := c.App.GetAuditsPage("", c.Params.Page, c.Params.PerPage)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("page", c.Params.Page)
auditRec.AddMeta("audits_per_page", c.Params.LogsPerPage)
w.Write([]byte(audits.ToJson()))
}
@@ -245,6 +251,9 @@ func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getLogs", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
@@ -256,6 +265,9 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.AddMeta("page", c.Params.Page)
auditRec.AddMeta("logs_per_page", c.Params.LogsPerPage)
w.Write([]byte(model.ArrayToJson(lines)))
}

Просмотреть файл

@@ -84,8 +84,7 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
auditRec.AddMeta("team", team)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_CREATE_TEAM) {
c.Err = model.NewAppError("createTeam", "api.team.is_team_creation_allowed.disabled.app_error", nil, "", http.StatusForbidden)
@@ -101,7 +100,7 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
// Don't sanitize the team here since the user will be a team admin and their session won't reflect that yet
auditRec.Success()
auditRec.AddMeta("team_id", rteam.Id)
auditRec.AddMeta("team", team) // overwrite meta
w.WriteHeader(http.StatusCreated)
w.Write([]byte(rteam.ToJson()))
@@ -171,9 +170,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
auditRec.AddMeta("team", team)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
@@ -187,6 +184,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("update", updatedTeam)
c.App.SanitizeTeam(*c.App.Session(), updatedTeam)
w.Write([]byte(updatedTeam.ToJson()))
@@ -207,13 +205,16 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
}
if oldTeam, err := c.App.GetTeam(c.Params.TeamId); err == nil {
auditRec.AddMeta("team", oldTeam)
}
patchedTeam, err := c.App.PatchTeam(c.Params.TeamId, team)
if err != nil {
@@ -224,8 +225,7 @@ func patchTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.App.SanitizeTeam(*c.App.Session(), patchedTeam)
auditRec.Success()
auditRec.AddMeta("team_name", patchedTeam.Name)
auditRec.AddMeta("team_display", patchedTeam.DisplayName)
auditRec.AddMeta("patched", patchedTeam)
c.LogAudit("")
w.Write([]byte(patchedTeam.ToJson()))
@@ -244,7 +244,6 @@ func regenerateTeamInviteId(c *Context, w http.ResponseWriter, r *http.Request)
auditRec := c.MakeAuditRecord("regenerateTeamInviteId", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
patchedTeam, err := c.App.RegenerateTeamInviteId(c.Params.TeamId)
if err != nil {
@@ -255,8 +254,7 @@ func regenerateTeamInviteId(c *Context, w http.ResponseWriter, r *http.Request)
c.App.SanitizeTeam(*c.App.Session(), patchedTeam)
auditRec.Success()
auditRec.AddMeta("team_name", patchedTeam.Name)
auditRec.AddMeta("team_display", patchedTeam.DisplayName)
auditRec.AddMeta("team", patchedTeam)
c.LogAudit("")
w.Write([]byte(patchedTeam.ToJson()))
@@ -275,7 +273,10 @@ func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("deleteTeam", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if team, err := c.App.GetTeam(c.Params.TeamId); err == nil {
auditRec.AddMeta("team", team)
}
var err *model.AppError
if c.Params.Permanent && *c.App.Config().ServiceSettings.EnableAPITeamDeletion {
@@ -488,8 +489,7 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("addTeamMember", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("add_user_id", member.UserId)
auditRec.AddMeta("member", member)
if member.UserId == c.App.Session().UserId {
var team *model.Team
@@ -519,8 +519,7 @@ func addTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
auditRec.AddMeta("team", team)
if team.IsGroupConstrained() {
nonMembers, err := c.App.FilterNonGroupTeamMembers([]string{member.UserId}, team)
@@ -582,7 +581,7 @@ func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request)
auditRec.Success()
if member != nil {
auditRec.AddMeta("add_user_id", member.UserId)
auditRec.AddMeta("member", member)
}
w.WriteHeader(http.StatusCreated)
@@ -612,7 +611,6 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("addTeamMembers", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("count", len(members))
var memberIDs []string
@@ -626,8 +624,7 @@ func addTeamMembers(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
auditRec.AddMeta("team", team)
if team.IsGroupConstrained() {
nonMembers, err := c.App.FilterNonGroupTeamMembers(memberIDs, team)
@@ -702,7 +699,6 @@ func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("removeTeamMember", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if c.App.Session().UserId != c.Params.UserId {
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_REMOVE_USER_FROM_TEAM) {
@@ -716,15 +712,14 @@ func removeTeamMember(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
auditRec.AddMeta("team", team)
user, err := c.App.GetUser(c.Params.UserId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("remove_user_id", user.Id)
auditRec.AddMeta("user", user)
if team.IsGroupConstrained() && (c.Params.UserId != c.App.Session().UserId) && !user.IsBot {
c.Err = model.NewAppError("removeTeamMember", "api.team.remove_member.group_constrained.app_error", nil, "", http.StatusBadRequest)
@@ -807,20 +802,22 @@ func updateTeamMemberRoles(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateTeamMemberRoles", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("update_user_id", c.Params.UserId)
auditRec.AddMeta("roles", newRoles)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
return
}
if _, err := c.App.UpdateTeamMemberRoles(c.Params.TeamId, c.Params.UserId, newRoles); err != nil {
teamMember, err := c.App.UpdateTeamMemberRoles(c.Params.TeamId, c.Params.UserId, newRoles)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("member", teamMember)
ReturnStatusOK(w)
}
@@ -838,23 +835,22 @@ func updateTeamMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.Requ
auditRec := c.MakeAuditRecord("updateTeamMemberSchemeRoles", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
auditRec.AddMeta("update_user_id", c.Params.UserId)
auditRec.AddMeta("new_scheme_admin", schemeRoles.SchemeAdmin)
auditRec.AddMeta("new_scheme_user", schemeRoles.SchemeUser)
auditRec.AddMeta("new_scheme_guest", schemeRoles.SchemeGuest)
auditRec.AddMeta("roles", schemeRoles)
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), c.Params.TeamId, model.PERMISSION_MANAGE_TEAM_ROLES) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM_ROLES)
return
}
if _, err := c.App.UpdateTeamMemberSchemeRoles(c.Params.TeamId, c.Params.UserId, schemeRoles.SchemeGuest, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin); err != nil {
teamMember, err := c.App.UpdateTeamMemberSchemeRoles(c.Params.TeamId, c.Params.UserId, schemeRoles.SchemeGuest, schemeRoles.SchemeUser, schemeRoles.SchemeAdmin)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("member", teamMember)
ReturnStatusOK(w)
}
@@ -1370,7 +1366,6 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateTeamScheme", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("team_id", c.Params.TeamId)
if c.App.License() == nil {
c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.license.error", nil, "", http.StatusNotImplemented)
@@ -1388,9 +1383,7 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("scheme_id", scheme.Id)
auditRec.AddMeta("scheme_name", scheme.Name)
auditRec.AddMeta("scheme_display", scheme.DisplayName)
auditRec.AddMeta("scheme", scheme)
if scheme.Scope != model.SCHEME_SCOPE_TEAM {
c.Err = model.NewAppError("Api4.UpdateTeamScheme", "api.team.update_team_scheme.scheme_scope.error", nil, "", http.StatusBadRequest)
@@ -1403,8 +1396,7 @@ func updateTeamScheme(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("team_name", team.Name)
auditRec.AddMeta("team_display", team.DisplayName)
auditRec.AddMeta("team", team)
team.SchemeId = schemeID

Просмотреть файл

@@ -96,7 +96,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("invite_id", inviteId)
auditRec.AddMeta("create_username", user.Username)
auditRec.AddMeta("user", user)
// No permission check required
@@ -137,7 +137,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("create_user_id", ruser.Id)
auditRec.AddMeta("user", ruser) // overwrite meta
w.WriteHeader(http.StatusCreated)
w.Write([]byte(ruser.ToJson()))
@@ -425,11 +425,14 @@ func setProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("setProfileImage", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("set_user_id", c.Params.UserId)
if imageArray[0] != nil {
auditRec.AddMeta("filename", imageArray[0].Filename)
}
if user, err := c.App.GetUser(c.Params.UserId); err == nil {
auditRec.AddMeta("user", user)
}
imageData := imageArray[0]
if err := c.App.SetProfileImage(c.Params.UserId, imageData); err != nil {
c.Err = err
@@ -460,14 +463,13 @@ func setDefaultProfileImage(c *Context, w http.ResponseWriter, r *http.Request)
auditRec := c.MakeAuditRecord("setDefaultProfileImage", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("set_user_id", c.Params.UserId)
user, err := c.App.GetUser(c.Params.UserId)
if err != nil {
c.Err = err
return
}
auditRec.AddMeta("set_username", user.Username)
auditRec.AddMeta("user", user)
if err := c.App.SetDefaultProfileImage(user); err != nil {
c.Err = err
@@ -888,7 +890,6 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("update_user_id", user.Id)
if !c.App.SessionHasPermissionToUser(*c.App.Session(), user.Id) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -900,6 +901,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("user", ouser)
if c.App.Session().IsOAuth {
if ouser.Email != user.Email {
@@ -925,8 +927,7 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("update_username", ruser.Username)
auditRec.AddMeta("update_email", ruser.Email)
auditRec.AddMeta("update", ruser)
c.LogAudit("")
w.Write([]byte(ruser.ToJson()))
@@ -946,7 +947,6 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("patchUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("patch_user_id", c.Params.UserId)
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -958,6 +958,7 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetInvalidParam("user_id")
return
}
auditRec.AddMeta("user", ouser)
if c.App.Session().IsOAuth && patch.Email != nil {
if ouser.Email != *patch.Email {
@@ -989,8 +990,7 @@ func patchUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.App.SetAutoResponderStatus(ruser, ouser.NotifyProps)
auditRec.Success()
auditRec.AddMeta("patch_username", ruser.Username)
auditRec.AddMeta("patch_email", ruser.Email)
auditRec.AddMeta("patch", ruser)
c.LogAudit("")
w.Write([]byte(ruser.ToJson()))
@@ -1006,7 +1006,6 @@ func deleteUser(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("deleteUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("delete_user_id", c.Params.UserId)
if !c.App.SessionHasPermissionToUser(*c.App.Session(), userId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -1024,7 +1023,7 @@ func deleteUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("delete_username", user.Username)
auditRec.AddMeta("user", user)
if _, err = c.App.UpdateActive(user, false); err != nil {
c.Err = err
@@ -1051,20 +1050,21 @@ func updateUserRoles(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateUserRoles", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("update_user_id", c.Params.UserId)
auditRec.AddMeta("new_roles", newRoles)
auditRec.AddMeta("roles", newRoles)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_ROLES) {
c.SetPermissionError(model.PERMISSION_MANAGE_ROLES)
return
}
if _, err := c.App.UpdateUserRoles(c.Params.UserId, newRoles, true); err != nil {
user, err := c.App.UpdateUserRoles(c.Params.UserId, newRoles, true)
if err != nil {
c.Err = err
return
}
auditRec.Success()
auditRec.AddMeta("user", user)
c.LogAudit(fmt.Sprintf("user=%s roles=%s", c.Params.UserId, newRoles))
ReturnStatusOK(w)
@@ -1086,8 +1086,7 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateUserActive", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("update_user_id", c.Params.UserId)
auditRec.AddMeta("new_active", active)
auditRec.AddMeta("active", active)
// true when you're trying to de-activate yourself
isSelfDeactive := !active && c.Params.UserId == c.App.Session().UserId
@@ -1108,6 +1107,7 @@ func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("user", user)
if active && user.IsGuest() && !*c.App.Config().GuestAccountsSettings.Enable {
c.Err = model.NewAppError("updateUserActive", "api.user.update_active.cannot_enable_guest_when_guest_feature_is_disabled.app_error", nil, "userId="+c.Params.UserId, http.StatusUnauthorized)
@@ -1144,7 +1144,6 @@ func updateUserAuth(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateUserAuth", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("update_user_id", c.Params.UserId)
userAuth := model.UserAuthFromJson(r.Body)
if userAuth == nil {
@@ -1152,6 +1151,10 @@ func updateUserAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if user, err := c.App.GetUser(c.Params.UserId); err == nil {
auditRec.AddMeta("user", user)
}
user, err := c.App.UpdateUserAuth(c.Params.UserId, userAuth)
if err != nil {
c.Err = err
@@ -1207,7 +1210,6 @@ func updateUserMfa(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateUserMfa", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("update_user_id", c.Params.UserId)
if c.App.Session().IsOAuth {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -1220,6 +1222,10 @@ func updateUserMfa(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if user, err := c.App.GetUser(c.Params.UserId); err == nil {
auditRec.AddMeta("user", user)
}
props := model.StringInterfaceFromJson(r.Body)
activate, ok := props["activate"].(bool)
if !ok {
@@ -1290,9 +1296,12 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updatePassword", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("update_user_id", c.Params.UserId)
c.LogAudit("attempted")
if user, err := c.App.GetUser(c.Params.UserId); err == nil {
auditRec.AddMeta("user", user)
}
var err *model.AppError
if c.Params.UserId == c.App.Session().UserId {
currentPassword := props["current_password"]
@@ -1478,7 +1487,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta(audit.KeyUserID, user.Id)
auditRec.AddMeta("user", user)
if user.IsGuest() {
if c.App.License() == nil {
@@ -1575,7 +1584,6 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("revokeSession", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("revoke_user_id", c.Params.UserId)
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -1594,7 +1602,7 @@ func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("device_id", session.DeviceId)
auditRec.AddMeta("session", session)
if session.UserId != c.Params.UserId {
c.SetInvalidUrlParam("user_id")
@@ -1620,7 +1628,7 @@ func revokeAllSessionsForUser(c *Context, w http.ResponseWriter, r *http.Request
auditRec := c.MakeAuditRecord("revokeAllSessionsForUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("revoke_user_id", c.Params.UserId)
auditRec.AddMeta("user_id", c.Params.UserId)
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -1720,6 +1728,13 @@ func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getUserAudits", audit.Fail)
defer c.LogAuditRec(auditRec)
if user, err := c.App.GetUser(c.Params.UserId); err == nil {
auditRec.AddMeta("user", user)
}
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
return
@@ -1731,6 +1746,10 @@ func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec.Success()
auditRec.AddMeta("page", c.Params.Page)
auditRec.AddMeta("audits_per_page", c.Params.LogsPerPage)
w.Write([]byte(audits.ToJson()))
}
@@ -1777,8 +1796,7 @@ func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w)
return
}
auditRec.AddMeta("send_user_id", user.Id)
auditRec.AddMeta("send_username", user.Username)
auditRec.AddMeta("user", user)
if err = c.App.SendEmailVerification(user, user.Email); err != nil {
// Don't want to leak whether the email is valid or not
@@ -1844,7 +1862,10 @@ func createUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createUserAccessToken", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("create_user_id", c.Params.UserId)
if user, err := c.App.GetUser(c.Params.UserId); err == nil {
auditRec.AddMeta("user", user)
}
if c.App.Session().IsOAuth {
c.SetPermissionError(model.PERMISSION_CREATE_USER_ACCESS_TOKEN)
@@ -2004,7 +2025,10 @@ func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("revoke_user_id", accessToken.UserId)
if user, errGet := c.App.GetUser(accessToken.UserId); errGet == nil {
auditRec.AddMeta("user", user)
}
if !c.App.SessionHasPermissionToUserOrBot(*c.App.Session(), accessToken.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -2046,7 +2070,10 @@ func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request)
c.Err = err
return
}
auditRec.AddMeta("disable_user_id", accessToken.UserId)
if user, errGet := c.App.GetUser(accessToken.UserId); errGet == nil {
auditRec.AddMeta("user", user)
}
if !c.App.SessionHasPermissionToUserOrBot(*c.App.Session(), accessToken.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -2088,7 +2115,10 @@ func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("enabled_user_id", accessToken.UserId)
if user, errGet := c.App.GetUser(accessToken.UserId); errGet == nil {
auditRec.AddMeta("user", user)
}
if !c.App.SessionHasPermissionToUserOrBot(*c.App.Session(), accessToken.UserId) {
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
@@ -2118,6 +2148,10 @@ func saveUserTermsOfService(c *Context, w http.ResponseWriter, r *http.Request)
auditRec.AddMeta("terms_id", termsOfServiceId)
auditRec.AddMeta("accepted", accepted)
if user, err := c.App.GetUser(userId); err == nil {
auditRec.AddMeta("user", user)
}
if _, err := c.App.GetTermsOfService(termsOfServiceId); err != nil {
c.Err = err
return
@@ -2152,7 +2186,6 @@ func promoteGuestToUser(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("promoteGuestToUser", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("promote_user_id", c.Params.UserId)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_PROMOTE_GUEST) {
c.SetPermissionError(model.PERMISSION_PROMOTE_GUEST)
@@ -2164,7 +2197,7 @@ func promoteGuestToUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("promote_username", user.Username)
auditRec.AddMeta("user", user)
if !user.IsGuest() {
c.Err = model.NewAppError("Api4.promoteGuestToUser", "api.user.promote_guest_to_user.no_guest.app_error", nil, "", http.StatusNotImplemented)
@@ -2198,7 +2231,6 @@ func demoteUserToGuest(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("demoteUserToGuest", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("demote_user_id", c.Params.UserId)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_DEMOTE_TO_GUEST) {
c.SetPermissionError(model.PERMISSION_DEMOTE_TO_GUEST)
@@ -2210,7 +2242,7 @@ func demoteUserToGuest(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
auditRec.AddMeta("demote_username", user.Username)
auditRec.AddMeta("user", user)
if user.IsGuest() {
c.Err = model.NewAppError("Api4.demoteUserToGuest", "api.user.demote_user_to_guest.already_guest.app_error", nil, "", http.StatusNotImplemented)

Просмотреть файл

@@ -40,9 +40,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("createIncomingHook", audit.Fail)
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("channel_id", channel.Id)
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("team_id", channel.TeamId)
auditRec.AddMeta("channel", channel)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionToTeam(*c.App.Session(), channel.TeamId, model.PERMISSION_MANAGE_INCOMING_WEBHOOKS) {
@@ -63,8 +61,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
auditRec.AddMeta("hook_id", incomingHook.Id)
auditRec.AddMeta("hook_display", incomingHook.DisplayName)
auditRec.AddMeta("hook", incomingHook)
c.LogAudit("success")
w.WriteHeader(http.StatusCreated)

Просмотреть файл

@@ -5,6 +5,7 @@ package app
import (
"fmt"
"os/user"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/mlog"
@@ -33,6 +34,51 @@ func (a *App) GetAuditsPage(userId string, page int, perPage int) (model.Audits,
return a.Srv().Store.Audit().Get(userId, page*perPage, perPage)
}
// LogAuditRec logs an audit record using default CLILevel.
func (a *App) LogAuditRec(rec *audit.Record, err error) {
a.LogAuditRecWithLevel(rec, CLILevel, err)
}
// LogAuditRecWithLevel logs an audit record using specified Level.
func (a *App) LogAuditRecWithLevel(rec *audit.Record, level audit.Level, err error) {
if rec == nil {
return
}
if err != nil {
if appErr, ok := err.(*model.AppError); ok {
rec.AddMeta("err", appErr.Error())
rec.AddMeta("code", appErr.StatusCode)
} else {
rec.AddMeta("err", err)
}
rec.Fail()
}
a.Srv().Audit.LogRecord(level, *rec)
}
// MakeAuditRecord creates a audit record pre-populated with defaults.
func (a *App) MakeAuditRecord(event string, initialStatus string) *audit.Record {
var userID string
user, err := user.Current()
if err == nil {
userID = fmt.Sprintf("%s:%s", user.Uid, user.Username)
}
rec := &audit.Record{
APIPath: "",
Event: event,
Status: initialStatus,
UserID: userID,
SessionID: "",
Client: fmt.Sprintf("server %s-%s", model.BuildNumber, model.BuildHash),
IPAddress: "",
Meta: audit.Meta{audit.KeyClusterID: a.GetClusterId()},
}
rec.AddMetaTypeConverter(model.AuditModelTypeConv)
return rec
}
func (s *Server) configureAudit(adt *audit.Audit) {
adt.OnQueueFull = s.onAuditTargetQueueFull
adt.OnError = s.onAuditError

Просмотреть файл

@@ -6,6 +6,10 @@ package audit
// Meta represents metadata that can be added to a audit record as name/value pairs.
type Meta map[string]interface{}
// FuncMetaTypeConv defines a function that can convert meta data types into something
// that serializes well for audit records.
type FuncMetaTypeConv func(val interface{}) (newVal interface{}, converted bool)
// Record provides a consistent set of fields used for all audit logging.
type Record struct {
APIPath string
@@ -16,6 +20,7 @@ type Record struct {
Client string
IPAddress string
Meta Meta
metaConv []FuncMetaTypeConv
}
// Success marks the audit record status as successful.
@@ -33,5 +38,22 @@ func (rec *Record) AddMeta(name string, val interface{}) {
if rec.Meta == nil {
rec.Meta = Meta{}
}
// possibly convert val to something better suited for serializing
// via zero or more conversion functions.
var converted bool
for _, conv := range rec.metaConv {
val, converted = conv(val)
if converted {
break
}
}
rec.Meta[name] = val
}
// AddMetaTypeConverter adds a function capable of converting meta field types
// into something more suitable for serialization.
func (rec *Record) AddMetaTypeConverter(f FuncMetaTypeConv) {
rec.metaConv = append(rec.metaConv, f)
}

76
audit/record_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,76 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package audit
import (
"testing"
"github.com/stretchr/testify/require"
)
type bloated struct {
fld1 string
fld2 string
fld3 string
fld4 string
}
type wilted struct {
wilt1 string
}
func conv(val interface{}) (interface{}, bool) {
switch v := val.(type) {
case *bloated:
return &wilted{wilt1: v.fld1}, true
}
return val, false
}
func TestRecord_AddMeta(t *testing.T) {
type fields struct {
metaConv []FuncMetaTypeConv
}
type args struct {
name string
val interface{}
}
tests := []struct {
name string
fields fields
args args
wantWilt bool
wantVal string
}{
{name: "no converter", wantWilt: false, wantVal: "ok", fields: fields{}, args: args{name: "prop", val: "ok"}},
{name: "don't convert", wantWilt: false, wantVal: "ok", fields: fields{metaConv: []FuncMetaTypeConv{conv}}, args: args{name: "prop", val: "ok"}},
{name: "convert", wantWilt: true, wantVal: "1", fields: fields{metaConv: []FuncMetaTypeConv{conv}}, args: args{name: "prop", val: &bloated{
fld1: "1", fld2: "2", fld3: "3", fld4: "4"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rec := &Record{
metaConv: tt.fields.metaConv,
}
rec.AddMeta(tt.args.name, tt.args.val)
// fetch the prop store in auditRecord meta data
got, ok := rec.Meta["prop"]
require.True(t, ok)
// check if conversion was expected
val, ok := got.(*wilted)
require.Equal(t, tt.wantWilt, ok)
if ok {
// if converted to wilt then make sure field was copied
require.Equal(t, tt.wantVal, val.wilt1)
} else {
// if not converted, make sure val is unchanged
require.Equal(t, tt.wantVal, got)
}
})
}
}

Просмотреть файл

@@ -54,8 +54,7 @@ func NewSyslogTLSTarget(filter logr.Filter, formatter logr.Formatter, params *Sy
return s, nil
}
// Shutdown stops processing log records after making best
// effort to flush queue.
// Shutdown stops processing log records after making best effort to flush queue.
func (s *SyslogTLS) Shutdown(ctx context.Context) error {
errs := merror.New()

Просмотреть файл

@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -215,6 +216,11 @@ func createChannelCmdF(command *cobra.Command, args []string) error {
return errCreatedChannel
}
auditRec := a.MakeAuditRecord("createChannel", audit.Success)
auditRec.AddMeta("channel", createdChannel)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
CommandPrettyPrintln("Id: " + createdChannel.Id)
CommandPrettyPrintln("Name: " + createdChannel.Name)
CommandPrettyPrintln("Display Name: " + createdChannel.DisplayName)
@@ -251,7 +257,6 @@ func removeChannelUsersCmdF(command *cobra.Command, args []string) error {
removeUserFromChannel(a, channel, user, args[i+1])
}
}
return nil
}
@@ -262,13 +267,24 @@ func removeUserFromChannel(a *app.App, channel *model.Channel, user *model.User,
}
if err := a.RemoveUserFromChannel(user.Id, "", channel); err != nil {
CommandPrintErrorln("Unable to remove '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
return
}
auditRec := a.MakeAuditRecord("removeUserFromChannel", audit.Success)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("user", user)
a.LogAuditRec(auditRec, nil)
}
func removeAllUsersFromChannel(a *app.App, channel *model.Channel) {
if err := a.Srv().Store.Channel().PermanentDeleteMembersByChannel(channel.Id); err != nil {
CommandPrintErrorln("Unable to remove all users from " + channel.Name + ". Error: " + err.Error())
return
}
auditRec := a.MakeAuditRecord("removeAllUsersFromChannel", audit.Success)
auditRec.AddMeta("channel", channel)
a.LogAuditRec(auditRec, nil)
}
func addChannelUsersCmdF(command *cobra.Command, args []string) error {
@@ -287,7 +303,6 @@ func addChannelUsersCmdF(command *cobra.Command, args []string) error {
for i, user := range users {
addUserToChannel(a, channel, user, args[i+1])
}
return nil
}
@@ -298,7 +313,13 @@ func addUserToChannel(a *app.App, channel *model.Channel, user *model.User, user
}
if _, err := a.AddUserToChannel(user, channel); err != nil {
CommandPrintErrorln("Unable to add '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
return
}
auditRec := a.MakeAuditRecord("addUserToChannel", audit.Success)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("user", user)
a.LogAuditRec(auditRec, nil)
}
func archiveChannelsCmdF(command *cobra.Command, args []string) error {
@@ -316,9 +337,12 @@ func archiveChannelsCmdF(command *cobra.Command, args []string) error {
}
if err := a.Srv().Store.Channel().Delete(channel.Id, model.GetMillis()); err != nil {
CommandPrintErrorln("Unable to archive channel '" + channel.Name + "' error: " + err.Error())
continue
}
auditRec := a.MakeAuditRecord("archiveChannel", audit.Success)
auditRec.AddMeta("channel", channel)
a.LogAuditRec(auditRec, nil)
}
return nil
}
@@ -349,9 +373,12 @@ func deleteChannelsCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to delete channel '" + channel.Name + "' error: " + err.Error())
} else {
CommandPrettyPrintln("Deleted channel '" + channel.Name + "'")
auditRec := a.MakeAuditRecord("deleteChannel", audit.Success)
auditRec.AddMeta("channel", channel)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -392,7 +419,6 @@ func moveChannelsCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("Moved channel '" + channel.Name + "' to " + team.Name + "(" + team.Id + ") from " + originTeamID + ".")
}
}
return nil
}
@@ -403,6 +429,11 @@ func moveChannel(a *app.App, team *model.Team, channel *model.Channel, user *mod
return err
}
auditRec := a.MakeAuditRecord("moveChannel", audit.Success)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
if incomingWebhooks, err := a.GetIncomingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
return err
} else {
@@ -479,7 +510,11 @@ func restoreChannelsCmdF(command *cobra.Command, args []string) error {
}
if err := a.Srv().Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); err != nil {
CommandPrintErrorln("Unable to restore channel '" + args[i] + "'")
continue
}
auditRec := a.MakeAuditRecord("restoreChannel", audit.Success)
auditRec.AddMeta("channel", channel)
a.LogAuditRec(auditRec, nil)
}
suffix := ""
@@ -528,10 +563,17 @@ func modifyChannelCmdF(command *cobra.Command, args []string) error {
return fmt.Errorf("Unable to find user: '%v'", username)
}
if _, err := a.UpdateChannelPrivacy(channel, user); err != nil {
updatedChannel, errUpdate := a.UpdateChannelPrivacy(channel, user)
if errUpdate != nil {
return errors.Wrapf(err, "Failed to update channel ('%s') privacy", args[0])
}
auditRec := a.MakeAuditRecord("modifyChannel", audit.Success)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("user", user)
auditRec.AddMeta("update", updatedChannel)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -554,11 +596,16 @@ func renameChannelCmdF(command *cobra.Command, args []string) error {
return errdn
}
_, errch := a.RenameChannel(channel, newChannelName, newDisplayName)
updatedChannel, errch := a.RenameChannel(channel, newChannelName, newDisplayName)
if errch != nil {
return errors.Wrapf(errch, "Error in updating channel from %s to %s", channel.Name, newChannelName)
}
auditRec := a.MakeAuditRecord("renameChannel", audit.Success)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("update", updatedChannel)
a.LogAuditRec(auditRec, nil)
return nil
}

Просмотреть файл

@@ -10,6 +10,7 @@ import (
"fmt"
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/spf13/cobra"
)
@@ -172,11 +173,16 @@ func createCommandCmdF(command *cobra.Command, args []string) error {
URL: url,
}
if _, err := a.CreateCommand(newCommand); err != nil {
return errors.New("unable to create command '" + newCommand.DisplayName + "'. " + err.Error())
createdCommand, errCreate := a.CreateCommand(newCommand)
if errCreate != nil {
return errors.New("unable to create command '" + newCommand.DisplayName + "'. " + errCreate.Error())
}
CommandPrettyPrintln("created command '" + newCommand.DisplayName + "'")
auditRec := a.MakeAuditRecord("createCommand", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("command", createdCommand)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -224,9 +230,13 @@ func moveCommandCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to move command '" + command.DisplayName + "' error: " + err.Error())
} else {
CommandPrettyPrintln("Moved command '" + command.DisplayName + "'")
auditRec := a.MakeAuditRecord("moveCommand", audit.Success)
auditRec.AddMeta("team", team)
auditRec.AddMeta("command", command)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -282,15 +292,20 @@ func deleteCommandCmdF(command *cobra.Command, args []string) error {
command.SilenceUsage = true
return errors.New("Unable to find command '" + args[0] + "'")
}
if err := a.DeleteCommand(slashCommand.Id); err != nil {
command.SilenceUsage = true
return errors.New("Unable to delete command '" + slashCommand.Id + "' error: " + err.Error())
}
CommandPrettyPrintln("Deleted command '" + slashCommand.Id + "' (" + slashCommand.DisplayName + ")")
auditRec := a.MakeAuditRecord("deleteCommand", audit.Success)
auditRec.AddMeta("command", slashCommand)
a.LogAuditRec(auditRec, nil)
return nil
}
func modifyCommandCmdF(command *cobra.Command, args []string) error {
func modifyCommandCmdF(command *cobra.Command, args []string) (cmdError error) {
a, err := InitDBCommandContextCobra(command)
if err != nil {
return err
@@ -304,6 +319,10 @@ func modifyCommandCmdF(command *cobra.Command, args []string) error {
}
modifiedCommand := oldCommand
auditRec := a.MakeAuditRecord("modifyCommand", audit.Fail)
defer func() { a.LogAuditRec(auditRec, cmdError) }()
auditRec.AddMeta("command", oldCommand)
// get creator user
creator, _ := command.Flags().GetString("creator")
if creator != "" {
@@ -376,10 +395,14 @@ func modifyCommandCmdF(command *cobra.Command, args []string) error {
}
modifiedCommand.Method = method
if _, err := a.UpdateCommand(oldCommand, modifiedCommand); err != nil {
return errors.New("unable to modify command '" + modifiedCommand.DisplayName + "'. " + err.Error())
updatedCommand, errUpdated := a.UpdateCommand(oldCommand, modifiedCommand)
if errUpdated != nil {
return errors.New("unable to modify command '" + modifiedCommand.DisplayName + "'. " + errUpdated.Error())
}
CommandPrettyPrintln("modified command '" + modifiedCommand.DisplayName + "'")
auditRec.Success()
auditRec.AddMeta("update", updatedCommand)
return nil
}

Просмотреть файл

@@ -251,10 +251,23 @@ func configSetCmdF(command *cobra.Command, args []string) error {
return errors.New("Invalid locale configuration")
}
if _, err := configStore.Set(newConfig); err != nil {
return errors.Wrap(err, "failed to set config")
if _, errSet := configStore.Set(newConfig); errSet != nil {
return errors.Wrap(errSet, "failed to set config")
}
/*
Uncomment when CI unit test fail resolved.
a, errInit := InitDBCommandContextCobra(command)
if errInit == nil {
auditRec := a.MakeAuditRecord("configSet", audit.Success)
auditRec.AddMeta("setting", configSetting)
auditRec.AddMeta("new_value", newVal)
a.LogAuditRec(auditRec, nil)
a.Shutdown()
}
*/
return nil
}
@@ -456,10 +469,21 @@ func configResetCmdF(command *cobra.Command, args []string) error {
return errors.New("Invalid locale configuration")
}
if _, err := configStore.Set(tempConfig); err != nil {
return errors.Wrap(err, "failed to set config")
if _, errSet := configStore.Set(tempConfig); errSet != nil {
return errors.Wrap(errSet, "failed to set config")
}
/*
Uncomment when CI unit test fail resolved.
a, errInit := InitDBCommandContextCobra(command)
if errInit == nil {
auditRec := a.MakeAuditRecord("configReset", audit.Success)
a.LogAuditRec(auditRec, nil)
a.Shutdown()
}
*/
return nil
}

Просмотреть файл

@@ -8,6 +8,7 @@ import (
"os"
"time"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -130,9 +131,13 @@ func scheduleExportCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("ERROR: Message export job failed. Please check the server logs")
} else {
CommandPrettyPrintln("SUCCESS: Message export job complete")
auditRec := a.MakeAuditRecord("scheduleExport", audit.Success)
auditRec.AddMeta("format", format)
auditRec.AddMeta("start", startTime)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -162,6 +167,11 @@ func buildExportCmdF(format string) func(command *cobra.Command, args []string)
}
CommandPrettyPrintln("SUCCESS: Your data was exported.")
auditRec := a.MakeAuditRecord("buildExport", audit.Success)
auditRec.AddMeta("format", format)
auditRec.AddMeta("start", startTime)
a.LogAuditRec(auditRec, nil)
return nil
}
}
@@ -199,5 +209,10 @@ func bulkExportCmdF(command *cobra.Command, args []string) error {
return err
}
auditRec := a.MakeAuditRecord("bulkExport", audit.Success)
auditRec.AddMeta("all_teams", allTeams)
auditRec.AddMeta("file", args[0])
a.LogAuditRec(auditRec, nil)
return nil
}

Просмотреть файл

@@ -6,6 +6,7 @@ package commands
import (
"fmt"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/pkg/errors"
@@ -146,6 +147,10 @@ func channelGroupEnableCmdF(command *cobra.Command, args []string) error {
return appErr
}
auditRec := a.MakeAuditRecord("channelGroupEnable", audit.Success)
auditRec.AddMeta("channel", channel)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -166,6 +171,10 @@ func channelGroupDisableCmdF(command *cobra.Command, args []string) error {
return appErr
}
auditRec := a.MakeAuditRecord("channelGroupDisable", audit.Success)
auditRec.AddMeta("channel", channel)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -240,6 +249,10 @@ func teamGroupEnableCmdF(command *cobra.Command, args []string) error {
return appErr
}
auditRec := a.MakeAuditRecord("teamGroupEnable", audit.Success)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -260,6 +273,10 @@ func teamGroupDisableCmdF(command *cobra.Command, args []string) error {
return appErr
}
auditRec := a.MakeAuditRecord("teamGroupDisable", audit.Success)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
return nil
}

Просмотреть файл

@@ -9,6 +9,7 @@ import (
"fmt"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/spf13/cobra"
)
@@ -87,6 +88,11 @@ func slackImportCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("Finished Slack Import.")
CommandPrettyPrintln("")
auditRec := a.MakeAuditRecord("slackImport", audit.Success)
auditRec.AddMeta("team", team)
auditRec.AddMeta("file", args[1])
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -147,6 +153,9 @@ func bulkImportCmdF(command *cobra.Command, args []string) error {
if apply {
CommandPrettyPrintln("Finished Bulk Import.")
auditRec := a.MakeAuditRecord("bulkImport", audit.Success)
auditRec.AddMeta("file", args[0])
a.LogAuditRec(auditRec, nil)
} else {
CommandPrettyPrintln("Validation complete. You can now perform the import by rerunning this command with the --apply flag.")
}

Просмотреть файл

@@ -8,6 +8,7 @@ import (
"os/signal"
"syscall"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/viper"
"github.com/spf13/cobra"
@@ -55,6 +56,11 @@ func jobserverCmdF(command *cobra.Command, args []string) error {
defer a.Srv().Jobs.StopSchedulers()
}
if !noJobs || !noSchedule {
auditRec := a.MakeAuditRecord("jobServer", audit.Success)
a.LogAuditRec(auditRec, nil)
}
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-signalChan

Просмотреть файл

@@ -4,6 +4,7 @@
package commands
import (
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/spf13/cobra"
)
@@ -51,6 +52,8 @@ func ldapSyncCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("ERROR: AD/LDAP Synchronization please check the server logs")
} else {
CommandPrettyPrintln("SUCCESS: AD/LDAP Synchronization Complete")
auditRec := a.MakeAuditRecord("ldapSync", audit.Success)
a.LogAuditRec(auditRec, nil)
}
}
@@ -70,6 +73,8 @@ func ldapIdMigrateCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("ERROR: AD/LDAP IdAttribute migration failed! Error: " + err.Error())
} else {
CommandPrettyPrintln("SUCCESS: AD/LDAP IdAttribute migration complete. You can now change your IdAttribute to: " + toAttribute)
auditRec := a.MakeAuditRecord("ldapMigrate", audit.Success)
a.LogAuditRec(auditRec, nil)
}
}

Просмотреть файл

@@ -7,6 +7,7 @@ import (
"errors"
"io/ioutil"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/spf13/cobra"
)
@@ -50,5 +51,9 @@ func uploadLicenseCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("Uploaded license file")
auditRec := a.MakeAuditRecord("uploadLicense", audit.Success)
auditRec.AddMeta("file", args[0])
a.LogAuditRec(auditRec, nil)
return nil
}

Просмотреть файл

@@ -10,6 +10,7 @@ import (
"github.com/spf13/cobra"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/utils"
)
@@ -86,6 +87,9 @@ func resetPermissionsCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("Changes will take effect gradually as the server caches expire.")
CommandPrettyPrintln("For the changes to take effect immediately, go to the Mattermost System Console > General > Configuration and click \"Purge All Caches\".")
auditRec := a.MakeAuditRecord("resetPermissions", audit.Success)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -104,6 +108,9 @@ func exportPermissionsCmdF(command *cobra.Command, args []string) error {
return errors.New(err.Error())
}
auditRec := a.MakeAuditRecord("exportPermissions", audit.Success)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -124,5 +131,9 @@ func importPermissionsCmdF(command *cobra.Command, args []string) error {
}
defer file.Close()
auditRec := a.MakeAuditRecord("importPermissions", audit.Success)
auditRec.AddMeta("file", args[0])
a.LogAuditRec(auditRec, nil)
return a.ImportPermissions(file)
}

Просмотреть файл

@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -122,10 +123,12 @@ func pluginAddCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to add plugin: " + args[i] + ". Error: " + err.Error())
} else {
CommandPrettyPrintln("Added plugin: " + plugin)
auditRec := a.MakeAuditRecord("pluginAdd", audit.Success)
auditRec.AddMeta("plugin", plugin)
a.LogAuditRec(auditRec, nil)
}
fileReader.Close()
}
return nil
}
@@ -145,9 +148,11 @@ func pluginDeleteCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to delete plugin: " + plugin + ". Error: " + err.Error())
} else {
CommandPrettyPrintln("Deleted plugin: " + plugin)
auditRec := a.MakeAuditRecord("pluginDelete", audit.Success)
auditRec.AddMeta("plugin", plugin)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -167,9 +172,11 @@ func pluginEnableCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to enable plugin: " + plugin + ". Error: " + err.Error())
} else {
CommandPrettyPrintln("Enabled plugin: " + plugin)
auditRec := a.MakeAuditRecord("pluginEnable", audit.Success)
auditRec.AddMeta("plugin", plugin)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -189,9 +196,11 @@ func pluginDisableCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to disable plugin: " + plugin + ". Error: " + err.Error())
} else {
CommandPrettyPrintln("Disabled plugin: " + plugin)
auditRec := a.MakeAuditRecord("pluginDisable", audit.Success)
auditRec.AddMeta("plugin", plugin)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -277,9 +286,11 @@ func pluginAddPublicKeyCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to add public key: " + pkFile + ". Error: " + err.Error())
} else {
CommandPrettyPrintln("Added public key: " + pkFile)
auditRec := a.MakeAuditRecord("pluginAddPublicKey", audit.Success)
auditRec.AddMeta("file", pkFile)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -299,8 +310,10 @@ func pluginDeletePublicKeyCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to delete public key: " + pkFile + ". Error: " + err.Error())
} else {
CommandPrettyPrintln("Deleted public key: " + pkFile)
auditRec := a.MakeAuditRecord("pluginDeletePublicKey", audit.Success)
auditRec.AddMeta("file", pkFile)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}

Просмотреть файл

@@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/spf13/cobra"
)
@@ -49,5 +50,8 @@ func resetCmdF(command *cobra.Command, args []string) error {
a.Srv().Store.DropAllTables()
CommandPrettyPrintln("Database successfully reset")
auditRec := a.MakeAuditRecord("reset", audit.Success)
a.LogAuditRec(auditRec, nil)
return nil
}

Просмотреть файл

@@ -9,6 +9,7 @@ import (
"github.com/spf13/cobra"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
)
@@ -78,11 +79,16 @@ func makeSystemAdminCmdF(command *cobra.Command, args []string) error {
roles = append(roles, model.SYSTEM_ADMIN_ROLE_ID)
}
if _, err := a.UpdateUserRoles(user.Id, strings.Join(roles, " "), true); err != nil {
return err
updatedUser, errUpdate := a.UpdateUserRoles(user.Id, strings.Join(roles, " "), true)
if errUpdate != nil {
return errUpdate
}
}
auditRec := a.MakeAuditRecord("makeSystemAdmin", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("update", updatedUser)
a.LogAuditRec(auditRec, nil)
}
return nil
}
@@ -122,10 +128,15 @@ func makeMemberCmdF(command *cobra.Command, args []string) error {
newRoles = append(roles, model.SYSTEM_USER_ROLE_ID)
}
if _, err := a.UpdateUserRoles(user.Id, strings.Join(newRoles, " "), true); err != nil {
return err
updatedUser, errUpdate := a.UpdateUserRoles(user.Id, strings.Join(newRoles, " "), true)
if errUpdate != nil {
return errUpdate
}
}
auditRec := a.MakeAuditRecord("makeMember", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("update", updatedUser)
a.LogAuditRec(auditRec, nil)
}
return nil
}

Просмотреть файл

@@ -17,6 +17,7 @@ import (
"github.com/icrowley/fake"
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/utils"
"github.com/spf13/cobra"
@@ -365,10 +366,15 @@ func sampleDataCmdF(command *cobra.Command, args []string) error {
if err != nil {
return errors.New("Unable to read correctly the temporary file.")
}
var importErr *model.AppError
importErr, lineNumber := a.BulkImport(bulkFile, false, workers)
if importErr != nil {
return fmt.Errorf("%s: %s, %s (line: %d)", importErr.Where, importErr.Message, importErr.DetailedError, lineNumber)
}
auditRec := a.MakeAuditRecord("sampleData", audit.Success)
auditRec.AddMeta("file", bulkFile.Name())
a.LogAuditRec(auditRec, nil)
} else if bulk != "-" {
err := bulkFile.Close()
if err != nil {

Просмотреть файл

@@ -10,6 +10,7 @@ import (
"strings"
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/spf13/cobra"
)
@@ -169,10 +170,15 @@ func createTeamCmdF(command *cobra.Command, args []string) error {
Type: teamType,
}
if _, err := a.CreateTeam(team); err != nil {
return errors.New("Team creation failed: " + err.Error())
createdTeam, errCreate := a.CreateTeam(team)
if errCreate != nil {
return errors.New("Team creation failed: " + errCreate.Error())
}
auditRec := a.MakeAuditRecord("createTeam", audit.Success)
auditRec.AddMeta("team", createdTeam)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -203,7 +209,13 @@ func removeUserFromTeam(a *app.App, team *model.Team, user *model.User, userArg
}
if err := a.LeaveTeam(team, user, ""); err != nil {
CommandPrintErrorln("Unable to remove '" + userArg + "' from " + team.Name + ". Error: " + err.Error())
return
}
auditRec := a.MakeAuditRecord("removeUserFromTeam", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
}
func addUsersCmdF(command *cobra.Command, args []string) error {
@@ -222,7 +234,6 @@ func addUsersCmdF(command *cobra.Command, args []string) error {
for i, user := range users {
addUserToTeam(a, team, user, args[i+1])
}
return nil
}
@@ -233,7 +244,13 @@ func addUserToTeam(a *app.App, team *model.Team, user *model.User, userArg strin
}
if err := a.JoinUserToTeam(team, user, ""); err != nil {
CommandPrintErrorln("Unable to add '" + userArg + "' to " + team.Name)
return
}
auditRec := a.MakeAuditRecord("addUserToTeam", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
}
func deleteTeamsCmdF(command *cobra.Command, args []string) error {
@@ -269,9 +286,12 @@ func deleteTeamsCmdF(command *cobra.Command, args []string) error {
CommandPrintErrorln("Unable to delete team '" + team.Name + "' error: " + err.Error())
} else {
CommandPrettyPrintln("Deleted team '" + team.Name + "'")
auditRec := a.MakeAuditRecord("deleteTeams", audit.Success)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -349,6 +369,10 @@ func restoreTeamsCmdF(command *cobra.Command, args []string) error {
err := a.RestoreTeam(team.Id)
if err != nil {
CommandPrintErrorln("Unable to restore team '" + team.Name + "' error: " + err.Error())
} else {
auditRec := a.MakeAuditRecord("restoreTeams", audit.Success)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
}
}
return nil
@@ -385,9 +409,12 @@ func archiveTeamCmdF(command *cobra.Command, args []string) error {
}
if err := a.SoftDeleteTeam(team.Id); err != nil {
CommandPrintErrorln("Unable to archive team '"+team.Name+"' error: ", err)
} else {
auditRec := a.MakeAuditRecord("archiveTeam", audit.Success)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -418,11 +445,16 @@ func renameTeamCmdF(command *cobra.Command, args []string) error {
return errdn
}
_, errrt := a.RenameTeam(team, newTeamName, newDisplayName)
updatedTeam, errrt := a.RenameTeam(team, newTeamName, newDisplayName)
if errrt != nil {
CommandPrintErrorln("Unable to rename team to '"+newTeamName+"' error: ", errrt)
}
auditRec := a.MakeAuditRecord("renameTeam", audit.Success)
auditRec.AddMeta("team", team)
auditRec.AddMeta("update", updatedTeam)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -457,5 +489,11 @@ func modifyTeamCmdF(command *cobra.Command, args []string) error {
return errors.New("Failed to update privacy for team" + args[0])
}
auditRec := a.MakeAuditRecord("modifyTeam", audit.Success)
auditRec.AddMeta("team", team)
auditRec.AddMeta("type", team.Type)
auditRec.AddMeta("allow_open_invite", team.AllowOpenInvite)
a.LogAuditRec(auditRec, nil)
return nil
}

Просмотреть файл

@@ -11,6 +11,7 @@ import (
"strings"
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/spf13/cobra"
)
@@ -303,10 +304,16 @@ func changeUserActiveStatus(a *app.App, user *model.User, userArg string, activa
if user.IsSSOUser() {
fmt.Println("You must also deactivate this user in the SSO provider or they will be reactivated on next login or sync.")
}
if _, err := a.UpdateActive(user, activate); err != nil {
updatedUser, err := a.UpdateActive(user, activate)
if err != nil {
return fmt.Errorf("Unable to change activation status of user: %v", userArg)
}
auditRec := a.MakeAuditRecord("changeActiveUserStatus", audit.Success)
auditRec.AddMeta("user", updatedUser)
auditRec.AddMeta("activate", activate)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -388,6 +395,11 @@ func userCreateCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("email: " + ruser.Email)
CommandPrettyPrintln("auth_service: " + ruser.AuthService)
auditRec := a.MakeAuditRecord("userCreate", audit.Success)
auditRec.AddMeta("user", ruser)
auditRec.AddMeta("system_admin", systemAdmin)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -406,6 +418,10 @@ func usersToBots(args []string, a *app.App) {
}
CommandPrettyPrintln(fmt.Sprintf("User %s is converted to bot successfully", bot.UserId))
auditRec := a.MakeAuditRecord("userToBot", audit.Success)
auditRec.AddMeta("user", user)
a.LogAuditRec(auditRec, nil)
}
}
@@ -526,6 +542,12 @@ func botToUser(command *cobra.Command, args []string, a *app.App) error {
CommandPrettyPrintln("last_name: " + user.LastName)
CommandPrettyPrintln("roles: " + user.Roles)
CommandPrettyPrintln("locale: " + user.Locale)
auditRec := a.MakeAuditRecord("botToUser", audit.Success)
auditRec.AddMeta("bot", user)
auditRec.AddMeta("user", user)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -604,6 +626,11 @@ func inviteUser(a *app.App, email string, team *model.Team, teamArg string) erro
a.SendInviteEmails(team, "Administrator", "Mattermost CLI "+model.NewId(), invites, *a.Config().ServiceSettings.SiteURL)
CommandPrettyPrintln("Invites may or may not have been sent.")
auditRec := a.MakeAuditRecord("inviteUser", audit.Success)
auditRec.AddMeta("email", email)
auditRec.AddMeta("team", team)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -628,6 +655,10 @@ func resetUserPasswordCmdF(command *cobra.Command, args []string) error {
return err
}
auditRec := a.MakeAuditRecord("resetUserPassword", audit.Success)
auditRec.AddMeta("user", user)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -663,6 +694,11 @@ func updateUserEmailCmdF(command *cobra.Command, args []string) error {
return errors.New(errUpdate.Message)
}
auditRec := a.MakeAuditRecord("updateUserEmail", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("email", newEmail)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -678,7 +714,6 @@ func resetUserMfaCmdF(command *cobra.Command, args []string) error {
}
users := getUsersFromUserArgs(a, args)
for i, user := range users {
if user == nil {
return errors.New("Unable to find user '" + args[i] + "'")
@@ -687,6 +722,10 @@ func resetUserMfaCmdF(command *cobra.Command, args []string) error {
if err := a.DeactivateMfa(user.Id); err != nil {
return err
}
auditRec := a.MakeAuditRecord("resetUserMfa", audit.Success)
auditRec.AddMeta("user", user)
a.LogAuditRec(auditRec, nil)
}
return nil
@@ -735,6 +774,11 @@ func deleteUserCmdF(command *cobra.Command, args []string) error {
return err
}
}
auditRec := a.MakeAuditRecord("deleteUser", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("isBot", user.IsBot)
a.LogAuditRec(auditRec, nil)
}
return nil
@@ -770,9 +814,11 @@ func deleteAllUsersCommandF(command *cobra.Command, args []string) error {
if err := a.PermanentDeleteAllUsers(); err != nil {
return err
}
CommandPrettyPrintln("All user accounts successfully deleted.")
auditRec := a.MakeAuditRecord("deleteAllUsers", audit.Success)
a.LogAuditRec(auditRec, nil)
return nil
}
@@ -815,8 +861,15 @@ func migrateAuthToLdapCmdF(command *cobra.Command, args []string) error {
}
CommandPrettyPrintln("Successfully migrated accounts.")
}
if !dryRunFlag {
auditRec := a.MakeAuditRecord("migrateAuthToLdap", audit.Success)
auditRec.AddMeta("fromAuth", fromAuth)
auditRec.AddMeta("matchField", matchField)
auditRec.AddMeta("force", forceFlag)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}
@@ -871,8 +924,13 @@ func migrateAuthToSamlCmdF(command *cobra.Command, args []string) error {
}
CommandPrettyPrintln("Successfully migrated accounts.")
}
if !dryRunFlag {
auditRec := a.MakeAuditRecord("migrateAuthToSaml", audit.Success)
auditRec.AddMeta("auto", autoFlag)
a.LogAuditRec(auditRec, nil)
}
}
return nil
}

Просмотреть файл

@@ -8,6 +8,7 @@ import (
"net/http"
"strings"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/store"
"github.com/pkg/errors"
@@ -194,10 +195,16 @@ func createIncomingWebhookCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("Id: " + createdIncoming.Id)
CommandPrettyPrintln("Display Name: " + createdIncoming.DisplayName)
auditRec := app.MakeAuditRecord("createIncomingWebhook", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("channel", channel)
auditRec.AddMeta("hook", createdIncoming)
app.LogAuditRec(auditRec, nil)
return nil
}
func modifyIncomingWebhookCmdF(command *cobra.Command, args []string) error {
func modifyIncomingWebhookCmdF(command *cobra.Command, args []string) (cmdError error) {
app, err := InitDBCommandContextCobra(command)
if err != nil {
return err
@@ -216,6 +223,10 @@ func modifyIncomingWebhookCmdF(command *cobra.Command, args []string) error {
updatedHook := oldHook
auditRec := app.MakeAuditRecord("createIncomingWebhook", audit.Fail)
defer func() { app.LogAuditRec(auditRec, cmdError) }()
auditRec.AddMeta("hook", oldHook)
channelArg, _ := command.Flags().GetString("channel")
if channelArg != "" {
channel := getChannelFromChannelArg(app, channelArg)
@@ -240,10 +251,14 @@ func modifyIncomingWebhookCmdF(command *cobra.Command, args []string) error {
channelLocked, _ := command.Flags().GetBool("lock-to-channel")
updatedHook.ChannelLocked = channelLocked
if _, err := app.UpdateIncomingWebhook(oldHook, updatedHook); err != nil {
return err
updatedIncomingHook, errUpdated := app.UpdateIncomingWebhook(oldHook, updatedHook)
if errUpdated != nil {
return errUpdated
}
auditRec.Success()
auditRec.AddMeta("update", updatedIncomingHook)
return nil
}
@@ -313,9 +328,10 @@ func createOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
IconURL: iconURL,
}
var channel *model.Channel
channelArg, _ := command.Flags().GetString("channel")
if channelArg != "" {
channel := getChannelFromChannelArg(app, channelArg)
channel = getChannelFromChannelArg(app, channelArg)
if channel != nil {
outgoingWebhook.ChannelId = channel.Id
}
@@ -329,6 +345,14 @@ func createOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
CommandPrettyPrintln("Id: " + createdOutgoing.Id)
CommandPrettyPrintln("Display Name: " + createdOutgoing.DisplayName)
auditRec := app.MakeAuditRecord("createOutgoingWebhook", audit.Success)
auditRec.AddMeta("user", user)
auditRec.AddMeta("hook", createdOutgoing)
if channel != nil {
auditRec.AddMeta("channel", channel)
}
app.LogAuditRec(auditRec, nil)
return nil
}
@@ -409,10 +433,16 @@ func modifyOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
updatedHook.CallbackURLs = callbackURLs
}
if _, appErr := app.UpdateOutgoingWebhook(oldHook, updatedHook); appErr != nil {
updatedWebhook, appErr := app.UpdateOutgoingWebhook(oldHook, updatedHook)
if appErr != nil {
return appErr
}
auditRec := app.MakeAuditRecord("modifyOutgoingWebhook", audit.Success)
auditRec.AddMeta("hook", oldHook)
auditRec.AddMeta("update", updatedWebhook)
app.LogAuditRec(auditRec, nil)
return nil
}
@@ -435,6 +465,10 @@ func deleteWebhookCmdF(command *cobra.Command, args []string) error {
return errors.New("Unable to delete webhook '" + webhookId + "'")
}
auditRec := app.MakeAuditRecord("deleteWebhook", audit.Success)
auditRec.AddMeta("hook_id", webhookId)
app.LogAuditRec(auditRec, nil)
return nil
}
@@ -458,7 +492,7 @@ func showWebhookCmdF(command *cobra.Command, args []string) error {
return errors.New("Webhook with id " + webhookId + " not found")
}
func moveOutgoingWebhookCmd(command *cobra.Command, args []string) error {
func moveOutgoingWebhookCmd(command *cobra.Command, args []string) (cmdError error) {
app, err := InitDBCommandContextCobra(command)
if err != nil {
return err
@@ -484,6 +518,10 @@ func moveOutgoingWebhookCmd(command *cobra.Command, args []string) error {
return appError
}
auditRec := app.MakeAuditRecord("moveOutgoingWebhook", audit.Fail)
defer func() { app.LogAuditRec(auditRec, cmdError) }()
auditRec.AddMeta("hook", webhook)
channelName, channelErr := command.Flags().GetString("channel")
if channelErr != nil {
return channelErr
@@ -507,10 +545,14 @@ func moveOutgoingWebhookCmd(command *cobra.Command, args []string) error {
webhook.Id = ""
webhook.TeamId = newTeamId
_, createErr := app.CreateOutgoingWebhook(webhook)
updatedWebHook, createErr := app.CreateOutgoingWebhook(webhook)
if createErr != nil {
return model.NewAppError("moveOutgoingWebhookCmd", "cli.outgoing_webhook.inconsistent_state.app_error", nil, "", http.StatusInternalServerError)
}
auditRec.Success()
auditRec.AddMeta("update", updatedWebHook)
return nil
}

7
go.mod
Просмотреть файл

@@ -18,6 +18,7 @@ require (
github.com/dyatlov/go-opengraph v0.0.0-20180429202543-816b6608b3c8
github.com/fatih/color v1.9.0 // indirect
github.com/fortytw2/leaktest v1.3.0 // indirect
github.com/francoispqt/gojay v1.2.13
github.com/fsnotify/fsnotify v1.4.7
github.com/go-gorp/gorp v2.0.0+incompatible // indirect
github.com/go-sql-driver/mysql v1.5.0
@@ -43,7 +44,7 @@ require (
github.com/icrowley/fake v0.0.0-20180203215853-4178557ae428
github.com/jaytaylor/html2text v0.0.0-20190408195923-01ec452cbe43
github.com/jmoiron/sqlx v1.2.0
github.com/jonboulle/clockwork v0.1.0
github.com/jonboulle/clockwork v0.1.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/lib/pq v1.3.0
github.com/magiconair/properties v1.8.1 // indirect
@@ -69,9 +70,9 @@ require (
github.com/pelletier/go-toml v1.6.0 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.4.0
github.com/prometheus/client_model v0.2.0
github.com/prometheus/client_model v0.2.0 // indirect
github.com/rs/cors v1.7.0
github.com/russellhaering/goxmldsig v0.0.0-20180430223755-7acd5e4a6ef7
github.com/russellhaering/goxmldsig v0.0.0-20180430223755-7acd5e4a6ef7 // indirect
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/segmentio/analytics-go v3.1.0+incompatible
github.com/segmentio/backo-go v0.0.0-20160424052352-204274ad699c // indirect

1
go.sum
Просмотреть файл

@@ -282,6 +282,7 @@ github.com/mattermost/gosaml2 v0.3.2 h1:kq2dY5qUe6fPPHra171GVlgo+ycBsEog0gZMetxL
github.com/mattermost/gosaml2 v0.3.2/go.mod h1:Z429EIOiEi9kbq6yHoApfzlcXpa6dzRDc6pO+Vy2Ksk=
github.com/mattermost/ldap v0.0.0-20191128190019-9f62ba4b8d4d h1:2DV7VIlEv6J5R5o6tUcb3ZMKJYeeZuWZL7Rv1m23TgQ=
github.com/mattermost/ldap v0.0.0-20191128190019-9f62ba4b8d4d/go.mod h1:HLbgMEI5K131jpxGazJ97AxfPDt31osq36YS1oxFQPQ=
github.com/mattermost/mattermost-server v5.11.1+incompatible h1:LPzKY0+2Tic/ik67qIg6VrydRCgxNXZQXOeaiJ2rMBY=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 h1:G9tL6JXRBMzjuD1kkBtcnd42kUiT6QDwxfFYu7adM6o=
github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0/go.mod h1:nV5bfVpT//+B1RPD2JvRnxbkLmJEYXmRaaVl15fsXjs=
github.com/mattermost/viper v1.0.4 h1:cMYOz4PhguscGSPxrSokUtib5HrG4gCpiUh27wyA3d0=

663
model/auditconv.go Обычный файл
Просмотреть файл

@@ -0,0 +1,663 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import "github.com/francoispqt/gojay"
// AuditModelTypeConv converts key model types to something better suited for audit output.
func AuditModelTypeConv(val interface{}) (newVal interface{}, converted bool) {
if val == nil {
return nil, false
}
switch v := val.(type) {
case *Channel:
return newAuditChannel(v), true
case *Team:
return newAuditTeam(v), true
case *User:
return newAuditUser(v), true
case *Command:
return newAuditCommand(v), true
case *CommandArgs:
return newAuditCommandArgs(v), true
case *Bot:
return newAuditBot(v), true
case *ChannelModerationPatch:
return newAuditChannelModerationPatch(v), true
case *Emoji:
return newAuditEmoji(v), true
case *FileInfo:
return newAuditFileInfo(v), true
case *Group:
return newAuditGroup(v), true
case *Job:
return newAuditJob(v), true
case *OAuthApp:
return newAuditOAuthApp(v), true
case *Post:
return newAuditPost(v), true
case *Role:
return newAuditRole(v), true
case *Scheme:
return newAuditScheme(v), true
case *SchemeRoles:
return newAuditSchemeRoles(v), true
case *Session:
return newAuditSession(v), true
case *IncomingWebhook:
return newAuditIncomingWebhook(v), true
case *OutgoingWebhook:
return newAuditOutgoingWebhook(v), true
}
return val, false
}
type auditChannel struct {
ID string
Name string
Type string
}
// newAuditChannel creates a simplified representation of Channel for output to audit log.
func newAuditChannel(c *Channel) auditChannel {
var channel auditChannel
if c != nil {
channel.ID = c.Id
channel.Name = c.Name
channel.Type = c.Type
}
return channel
}
func (c auditChannel) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", c.ID)
enc.StringKey("name", c.Name)
enc.StringKey("type", c.Type)
}
func (c auditChannel) IsNil() bool {
return false
}
type auditTeam struct {
ID string
Name string
Type string
}
// newAuditTeam creates a simplified representation of Team for output to audit log.
func newAuditTeam(t *Team) auditTeam {
var team auditTeam
if t != nil {
team.ID = t.Id
team.Name = t.Name
team.Type = t.Type
}
return team
}
func (t auditTeam) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", t.ID)
enc.StringKey("name", t.Name)
enc.StringKey("type", t.Type)
}
func (t auditTeam) IsNil() bool {
return false
}
type auditUser struct {
ID string
Name string
Roles string
}
// newAuditUser creates a simplified representation of User for output to audit log.
func newAuditUser(u *User) auditUser {
var user auditUser
if u != nil {
user.ID = u.Id
user.Name = u.Username
user.Roles = u.Roles
}
return user
}
func (u auditUser) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", u.ID)
enc.StringKey("name", u.Name)
enc.StringKey("roles", u.Roles)
}
func (u auditUser) IsNil() bool {
return false
}
type auditCommand struct {
ID string
CreatorID string
TeamID string
Trigger string
Method string
Username string
IconURL string
AutoComplete bool
AutoCompleteDesc string
AutoCompleteHint string
DisplayName string
Description string
URL string
}
// newAuditCommand creates a simplified representation of Command for output to audit log.
func newAuditCommand(c *Command) auditCommand {
var cmd auditCommand
if c != nil {
cmd.ID = c.Id
cmd.CreatorID = c.CreatorId
cmd.TeamID = c.TeamId
cmd.Trigger = c.Trigger
cmd.Method = c.Method
cmd.Username = c.Username
cmd.IconURL = c.IconURL
cmd.AutoComplete = c.AutoComplete
cmd.AutoCompleteDesc = c.AutoCompleteDesc
cmd.AutoCompleteHint = c.AutoCompleteHint
cmd.DisplayName = c.DisplayName
cmd.Description = c.Description
cmd.URL = c.URL
}
return cmd
}
func (cmd auditCommand) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", cmd.ID)
enc.StringKey("creator_id", cmd.CreatorID)
enc.StringKey("team_id", cmd.TeamID)
enc.StringKey("trigger", cmd.Trigger)
enc.StringKey("method", cmd.Method)
enc.StringKey("username", cmd.Username)
enc.StringKey("icon_url", cmd.IconURL)
enc.BoolKey("auto_complete", cmd.AutoComplete)
enc.StringKey("auto_complete_desc", cmd.AutoCompleteDesc)
enc.StringKey("auto_complete_hint", cmd.AutoCompleteHint)
enc.StringKey("display", cmd.DisplayName)
enc.StringKey("desc", cmd.Description)
enc.StringKey("url", cmd.URL)
}
func (cmd auditCommand) IsNil() bool {
return false
}
type auditCommandArgs struct {
ChannelID string
TeamID string
TriggerID string
Command string
}
// newAuditCommandArgs creates a simplified representation of CommandArgs for output to audit log.
func newAuditCommandArgs(ca *CommandArgs) auditCommandArgs {
var cmdargs auditCommandArgs
if ca != nil {
cmdargs.ChannelID = ca.ChannelId
cmdargs.TeamID = ca.TeamId
cmdargs.TriggerID = ca.TriggerId
cmdargs.Command = ca.Command
}
return cmdargs
}
func (ca auditCommandArgs) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("channel_id", ca.ChannelID)
enc.StringKey("team_id", ca.TriggerID)
enc.StringKey("trigger_id", ca.TeamID)
enc.StringKey("command", ca.Command)
}
func (ca auditCommandArgs) IsNil() bool {
return false
}
type auditBot struct {
UserID string
Username string
Displayname string
}
// newAuditBot creates a simplified representation of Bot for output to audit log.
func newAuditBot(b *Bot) auditBot {
var bot auditBot
if b != nil {
bot.UserID = b.UserId
bot.Username = b.Username
bot.Displayname = b.DisplayName
}
return bot
}
func (b auditBot) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("user_id", b.UserID)
enc.StringKey("username", b.Username)
enc.StringKey("display", b.Displayname)
}
func (b auditBot) IsNil() bool {
return false
}
type auditChannelModerationPatch struct {
Name string
RoleGuests bool
RoleMembers bool
}
// newAuditChannelModerationPatch creates a simplified representation of ChannelModerationPatch for output to audit log.
func newAuditChannelModerationPatch(p *ChannelModerationPatch) auditChannelModerationPatch {
var patch auditChannelModerationPatch
if p != nil {
if p.Name != nil {
patch.Name = *p.Name
}
if p.Roles.Guests != nil {
patch.RoleGuests = *p.Roles.Guests
}
if p.Roles.Members != nil {
patch.RoleMembers = *p.Roles.Members
}
}
return patch
}
func (p auditChannelModerationPatch) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("name", p.Name)
enc.BoolKey("role_guests", p.RoleGuests)
enc.BoolKey("role_members", p.RoleMembers)
}
func (p auditChannelModerationPatch) IsNil() bool {
return false
}
type auditEmoji struct {
ID string
Name string
}
// newAuditEmoji creates a simplified representation of Emoji for output to audit log.
func newAuditEmoji(e *Emoji) auditEmoji {
var emoji auditEmoji
if e != nil {
emoji.ID = e.Id
emoji.Name = e.Name
}
return emoji
}
func (e auditEmoji) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", e.ID)
enc.StringKey("name", e.Name)
}
func (e auditEmoji) IsNil() bool {
return false
}
type auditFileInfo struct {
ID string
PostID string
Path string
Name string
Extension string
Size int64
}
// newAuditFileInfo creates a simplified representation of FileInfo for output to audit log.
func newAuditFileInfo(f *FileInfo) auditFileInfo {
var fi auditFileInfo
if f != nil {
fi.ID = f.Id
fi.PostID = f.PostId
fi.Path = f.Path
fi.Name = f.Name
fi.Extension = f.Extension
fi.Size = f.Size
}
return fi
}
func (fi auditFileInfo) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", fi.ID)
enc.StringKey("post_id", fi.PostID)
enc.StringKey("path", fi.Path)
enc.StringKey("name", fi.Name)
enc.StringKey("ext", fi.Extension)
enc.Int64Key("size", fi.Size)
}
func (fi auditFileInfo) IsNil() bool {
return false
}
type auditGroup struct {
ID string
Name string
DisplayName string
Description string
}
// newAuditGroup creates a simplified representation of Group for output to audit log.
func newAuditGroup(g *Group) auditGroup {
var group auditGroup
if g != nil {
group.ID = g.Id
group.Name = g.Name
group.DisplayName = g.DisplayName
group.Description = g.Description
}
return group
}
func (g auditGroup) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", g.ID)
enc.StringKey("name", g.Name)
enc.StringKey("display", g.DisplayName)
enc.StringKey("desc", g.Description)
}
func (g auditGroup) IsNil() bool {
return false
}
type auditJob struct {
ID string
Type string
Priority int64
StartAt int64
}
// newAuditJob creates a simplified representation of Job for output to audit log.
func newAuditJob(j *Job) auditJob {
var job auditJob
if j != nil {
job.ID = j.Id
job.Type = j.Type
job.Priority = j.Priority
job.StartAt = j.StartAt
}
return job
}
func (j auditJob) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", j.ID)
enc.StringKey("type", j.Type)
enc.Int64Key("priority", j.Priority)
enc.Int64Key("start_at", j.StartAt)
}
func (j auditJob) IsNil() bool {
return false
}
type auditOAuthApp struct {
ID string
CreatorID string
Name string
Description string
IsTrusted bool
}
// newAuditOAuthApp creates a simplified representation of OAuthApp for output to audit log.
func newAuditOAuthApp(o *OAuthApp) auditOAuthApp {
var oauth auditOAuthApp
if o != nil {
oauth.ID = o.Id
oauth.CreatorID = o.CreatorId
oauth.Name = o.Name
oauth.Description = o.Description
oauth.IsTrusted = o.IsTrusted
}
return oauth
}
func (o auditOAuthApp) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", o.ID)
enc.StringKey("creator_id", o.CreatorID)
enc.StringKey("name", o.Name)
enc.StringKey("desc", o.Description)
enc.BoolKey("trusted", o.IsTrusted)
}
func (o auditOAuthApp) IsNil() bool {
return false
}
type auditPost struct {
ID string
ChannelID string
Type string
IsPinned bool
}
// newAuditPost creates a simplified representation of Post for output to audit log.
func newAuditPost(p *Post) auditPost {
var post auditPost
if p != nil {
post.ID = p.Id
post.ChannelID = p.ChannelId
post.Type = p.Type
post.IsPinned = p.IsPinned
}
return post
}
func (p auditPost) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", p.ID)
enc.StringKey("channel_id", p.ChannelID)
enc.StringKey("type", p.Type)
enc.BoolKey("pinned", p.IsPinned)
}
func (p auditPost) IsNil() bool {
return false
}
type auditRole struct {
ID string
Name string
DisplayName string
Permissions []string
SchemeManaged bool
BuiltIn bool
}
// newAuditRole creates a simplified representation of Role for output to audit log.
func newAuditRole(r *Role) auditRole {
var role auditRole
if r != nil {
role.ID = r.Id
role.Name = r.Name
role.DisplayName = r.DisplayName
role.Permissions = append(role.Permissions, r.Permissions...)
role.SchemeManaged = r.SchemeManaged
role.BuiltIn = r.BuiltIn
}
return role
}
func (r auditRole) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", r.ID)
enc.StringKey("name", r.Name)
enc.StringKey("display", r.DisplayName)
enc.SliceStringKey("perms", r.Permissions)
enc.BoolKey("schemeManaged", r.SchemeManaged)
enc.BoolKey("builtin", r.BuiltIn)
}
func (r auditRole) IsNil() bool {
return false
}
type auditScheme struct {
ID string
Name string
DisplayName string
Scope string
}
// newAuditScheme creates a simplified representation of Scheme for output to audit log.
func newAuditScheme(s *Scheme) auditScheme {
var scheme auditScheme
if s != nil {
scheme.ID = s.Id
scheme.Name = s.Name
scheme.DisplayName = s.DisplayName
scheme.Scope = s.Scope
}
return scheme
}
func (s auditScheme) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", s.ID)
enc.StringKey("name", s.Name)
enc.StringKey("display", s.DisplayName)
enc.StringKey("scope", s.Scope)
}
func (s auditScheme) IsNil() bool {
return false
}
type auditSchemeRoles struct {
SchemeAdmin bool
SchemeUser bool
SchemeGuest bool
}
// newAuditSchemeRoles creates a simplified representation of SchemeRoles for output to audit log.
func newAuditSchemeRoles(s *SchemeRoles) auditSchemeRoles {
var roles auditSchemeRoles
if s != nil {
roles.SchemeAdmin = s.SchemeAdmin
roles.SchemeUser = s.SchemeUser
roles.SchemeGuest = s.SchemeGuest
}
return roles
}
func (s auditSchemeRoles) MarshalJSONObject(enc *gojay.Encoder) {
enc.BoolKey("admin", s.SchemeAdmin)
enc.BoolKey("user", s.SchemeUser)
enc.BoolKey("guest", s.SchemeGuest)
}
func (s auditSchemeRoles) IsNil() bool {
return false
}
type auditSession struct {
ID string
UserId string
DeviceId string
}
// newAuditSession creates a simplified representation of Session for output to audit log.
func newAuditSession(s *Session) auditSession {
var session auditSession
if s != nil {
session.ID = s.Id
session.UserId = s.UserId
session.DeviceId = s.DeviceId
}
return session
}
func (s auditSession) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", s.ID)
enc.StringKey("user_id", s.UserId)
enc.StringKey("device_id", s.DeviceId)
}
func (s auditSession) IsNil() bool {
return false
}
type auditIncomingWebhook struct {
ID string
ChannelID string
TeamId string
DisplayName string
Description string
}
// newAuditIncomingWebhook creates a simplified representation of IncomingWebhook for output to audit log.
func newAuditIncomingWebhook(h *IncomingWebhook) auditIncomingWebhook {
var hook auditIncomingWebhook
if h != nil {
hook.ID = h.Id
hook.ChannelID = h.ChannelId
hook.TeamId = h.TeamId
hook.DisplayName = h.DisplayName
hook.Description = h.Description
}
return hook
}
func (h auditIncomingWebhook) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", h.ID)
enc.StringKey("channel_id", h.ChannelID)
enc.StringKey("team_id", h.TeamId)
enc.StringKey("display", h.DisplayName)
enc.StringKey("desc", h.Description)
}
func (h auditIncomingWebhook) IsNil() bool {
return false
}
type auditOutgoingWebhook struct {
ID string
ChannelID string
TeamID string
TriggerWords StringArray
TriggerWhen int
DisplayName string
Description string
ContentType string
Username string
}
// newAuditOutgoingWebhook creates a simplified representation of OutgoingWebhook for output to audit log.
func newAuditOutgoingWebhook(h *OutgoingWebhook) auditOutgoingWebhook {
var hook auditOutgoingWebhook
if h != nil {
hook.ID = h.Id
hook.ChannelID = h.ChannelId
hook.TeamID = h.TeamId
hook.TriggerWords = h.TriggerWords
hook.TriggerWhen = h.TriggerWhen
hook.DisplayName = h.DisplayName
hook.Description = h.Description
hook.ContentType = h.ContentType
hook.Username = h.Username
}
return hook
}
func (h auditOutgoingWebhook) MarshalJSONObject(enc *gojay.Encoder) {
enc.StringKey("id", h.ID)
enc.StringKey("channel_id", h.ChannelID)
enc.StringKey("team_id", h.TeamID)
enc.SliceStringKey("trigger_words", h.TriggerWords)
enc.IntKey("trigger_when", h.TriggerWhen)
enc.StringKey("display", h.DisplayName)
enc.StringKey("desc", h.Description)
enc.StringKey("content_type", h.ContentType)
enc.StringKey("username", h.Username)
}
func (h auditOutgoingWebhook) IsNil() bool {
return false
}

51
model/auditconv_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,51 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"testing"
"github.com/stretchr/testify/assert"
)
type Sample struct {
flag bool
name string
}
func TestAuditModelTypeConv(t *testing.T) {
sample := &Sample{flag: true, name: "sample"}
sample2 := &Sample{name: "sample2"}
sampleArr := []*Sample{sample, sample2}
user := &User{}
type args struct {
val interface{}
}
tests := []struct {
name string
args args
wantConverted bool
wantNewVal interface{}
}{
{name: "nil value", args: args{val: nil}, wantConverted: false, wantNewVal: nil},
{name: "string value", args: args{val: "hello"}, wantConverted: false, wantNewVal: "hello"},
{name: "string array", args: args{val: []string{"hello", "there"}}, wantConverted: false, wantNewVal: []string{"hello", "there"}},
{name: "int value", args: args{val: 77}, wantConverted: false, wantNewVal: 77},
{name: "int array", args: args{val: []int{77, 68}}, wantConverted: false, wantNewVal: []int{77, 68}},
{name: "struct pointer value", args: args{val: sample}, wantConverted: false, wantNewVal: sample},
{name: "struct pointer array", args: args{val: sampleArr}, wantConverted: false, wantNewVal: sampleArr},
{name: "model user", args: args{val: user}, wantConverted: true, wantNewVal: "XXX"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotNewVal, gotConverted := AuditModelTypeConv(tt.args.val)
assert.Equal(t, tt.wantConverted, gotConverted)
if !tt.wantConverted {
assert.Equal(t, tt.wantNewVal, gotNewVal)
}
})
}
}

1
vendor/modules.txt поставляемый
Просмотреть файл

@@ -49,6 +49,7 @@ github.com/fatih/color
# github.com/fortytw2/leaktest v1.3.0
## explicit
# github.com/francoispqt/gojay v1.2.13
## explicit
github.com/francoispqt/gojay
# github.com/fsnotify/fsnotify v1.4.7
## explicit

Просмотреть файл

@@ -29,7 +29,7 @@ func (c *Context) LogAuditRec(rec *audit.Record) {
c.LogAuditRecWithLevel(rec, app.RestLevel)
}
// LogAuditRec logs an audit record using specificed Level.
// LogAuditRec logs an audit record using specified Level.
func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level audit.Level) {
if rec == nil {
return
@@ -42,15 +42,12 @@ func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level audit.Level) {
}
rec.Fail()
}
if cid := c.App.GetClusterId(); cid != "" {
rec.AddMeta(audit.KeyClusterID, cid)
}
c.App.Srv().Audit.LogRecord(level, *rec)
}
// MakeAuditRecord creates a audit record pre-populated with data from this context.
func (c *Context) MakeAuditRecord(event string, initialStatus string) *audit.Record {
return &audit.Record{
rec := &audit.Record{
APIPath: c.App.Path(),
Event: event,
Status: initialStatus,
@@ -58,8 +55,11 @@ func (c *Context) MakeAuditRecord(event string, initialStatus string) *audit.Rec
SessionID: c.App.Session().Id,
Client: c.App.UserAgent(),
IPAddress: c.App.IpAddress(),
Meta: audit.Meta{},
Meta: audit.Meta{audit.KeyClusterID: c.App.GetClusterId()},
}
rec.AddMetaTypeConverter(model.AuditModelTypeConv)
return rec
}
func (c *Context) LogAudit(extraInfo string) {