Manual Cherrypick: Add audits for accessing posts without membership (#31266) (#35022)

Automatic Merge
Этот коммит содержится в:
Daniel Espino García
2026-01-26 11:23:28 +01:00
коммит произвёл GitHub
родитель 12dce033d6
Коммит 21a86506f9
79 изменённых файлов: 1707 добавлений и 1001 удалений

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

@@ -167,13 +167,13 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
switch oldChannel.Type {
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePublicChannelProperties) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePublicChannelProperties); !ok {
c.SetPermissionError(model.PermissionManagePublicChannelProperties)
return
}
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePrivateChannelProperties) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePrivateChannelProperties); !ok {
c.SetPermissionError(model.PermissionManagePrivateChannelProperties)
return
}
@@ -278,14 +278,18 @@ func updateChannelPrivacy(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec.AddEventPriorState(channel)
if model.ChannelType(privacy) == model.ChannelTypeOpen && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionConvertPrivateChannelToPublic) {
c.SetPermissionError(model.PermissionConvertPrivateChannelToPublic)
return
if model.ChannelType(privacy) == model.ChannelTypeOpen {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionConvertPrivateChannelToPublic); !ok {
c.SetPermissionError(model.PermissionConvertPrivateChannelToPublic)
return
}
}
if model.ChannelType(privacy) == model.ChannelTypePrivate && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionConvertPublicChannelToPrivate) {
c.SetPermissionError(model.PermissionConvertPublicChannelToPrivate)
return
if model.ChannelType(privacy) == model.ChannelTypePrivate {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionConvertPublicChannelToPrivate); !ok {
c.SetPermissionError(model.PermissionConvertPublicChannelToPrivate)
return
}
}
if channel.Name == model.DefaultChannelName && model.ChannelType(privacy) == model.ChannelTypePrivate {
@@ -343,13 +347,13 @@ func patchChannel(c *Context, w http.ResponseWriter, r *http.Request) {
switch oldChannel.Type {
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePublicChannelProperties) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePublicChannelProperties); !ok {
c.SetPermissionError(model.PermissionManagePublicChannelProperties)
return
}
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePrivateChannelProperties) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePrivateChannelProperties); !ok {
c.SetPermissionError(model.PermissionManagePrivateChannelProperties)
return
}
@@ -631,12 +635,14 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
if channel.Type == model.ChannelTypeOpen {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionReadPublicChannel) && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
c.SetPermissionError(model.PermissionReadPublicChannel)
return
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionReadPublicChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadPublicChannel)
return
}
}
} else {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -664,7 +670,7 @@ func getChannelUnread(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -689,7 +695,7 @@ func getChannelStats(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -779,7 +785,8 @@ func getPinnedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
var hasPermission, isMember bool
if hasPermission, isMember = c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !hasPermission {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -795,7 +802,7 @@ func getPinnedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
}
clientPostList := c.App.PreparePostListForClient(c.AppContext, posts)
clientPostList, err = c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
clientPostList, isMemberForAllPreviews, err := c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
@@ -805,6 +812,14 @@ func getPinnedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
if err := clientPostList.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("updateChannelMemberRoles", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "channel_id", c.Params.ChannelId)
if !isMember || !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1001,7 +1016,7 @@ func getPublicChannelsByIdsForTeam(c *Context, w http.ResponseWriter, r *http.Re
if session := c.AppContext.Session(); session.IsGuest() {
for _, channel := range channels {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *session, channel.Id, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *session, channel.Id, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1392,14 +1407,18 @@ func deleteChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if channel.Type == model.ChannelTypeOpen && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionDeletePublicChannel) {
c.SetPermissionError(model.PermissionDeletePublicChannel)
return
if channel.Type == model.ChannelTypeOpen {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionDeletePublicChannel); !ok {
c.SetPermissionError(model.PermissionDeletePublicChannel)
return
}
}
if channel.Type == model.ChannelTypePrivate && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionDeletePrivateChannel) {
c.SetPermissionError(model.PermissionDeletePrivateChannel)
return
if channel.Type == model.ChannelTypePrivate {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionDeletePrivateChannel); !ok {
c.SetPermissionError(model.PermissionDeletePrivateChannel)
return
}
}
if c.Params.Permanent {
@@ -1436,16 +1455,19 @@ func getChannelByName(c *Context, w http.ResponseWriter, r *http.Request) {
}
if channel.Type == model.ChannelTypeOpen {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionReadPublicChannel) && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionReadChannel) {
c.SetPermissionError(model.PermissionReadPublicChannel)
return
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionReadPublicChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadPublicChannel)
return
}
}
} else {
// allows team admins to access private channel
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageTeam) &&
!c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionReadChannel) {
c.Err = model.NewAppError("getChannelByName", "app.channel.get_by_name.missing.app_error", nil, "teamId="+channel.TeamId+", "+"name="+channel.Name+"", http.StatusNotFound)
return
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionManageTeam) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionReadChannel); !ok {
c.Err = model.NewAppError("getChannelByName", "app.channel.get_by_name.missing.app_error", nil, "teamId="+channel.TeamId+", "+"name="+channel.Name+"", http.StatusNotFound)
return
}
}
}
@@ -1473,7 +1495,7 @@ func getChannelByNameForTeamName(c *Context, w http.ResponseWriter, r *http.Requ
return
}
channelOk := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionReadChannel)
channelOk, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionReadChannel)
if channel.Type == model.ChannelTypeOpen {
teamOk := c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionReadPublicChannel)
if !teamOk && !channelOk {
@@ -1505,7 +1527,7 @@ func getChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1533,7 +1555,7 @@ func getChannelMembersTimezones(c *Context, w http.ResponseWriter, r *http.Reque
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1564,7 +1586,7 @@ func getChannelMembersByIds(c *Context, w http.ResponseWriter, r *http.Request)
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1592,7 +1614,7 @@ func getChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1745,7 +1767,7 @@ func updateChannelMemberRoles(c *Context, w http.ResponseWriter, r *http.Request
model.AddEventParameterToAuditRec(auditRec, "props", props)
model.AddEventParameterToAuditRec(auditRec, "channel_id", c.Params.ChannelId)
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManageChannelRoles) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManageChannelRoles); !ok {
c.SetPermissionError(model.PermissionManageChannelRoles)
return
}
@@ -1777,7 +1799,7 @@ func updateChannelMemberSchemeRoles(c *Context, w http.ResponseWriter, r *http.R
model.AddEventParameterToAuditRec(auditRec, "channel_id", c.Params.ChannelId)
model.AddEventParameterAuditableToAuditRec(auditRec, "roles", &schemeRoles)
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManageChannelRoles) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManageChannelRoles); !ok {
c.SetPermissionError(model.PermissionManageChannelRoles)
return
}
@@ -1888,7 +1910,7 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
// Security check: if the user is a guest, they must have access to the channel
// to view its members
if c.AppContext.Session().IsGuest() {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if hasPermission, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !hasPermission {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1916,13 +1938,13 @@ func addChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
if c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionJoinPublicChannels) {
canAddSelf = true
}
if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePublicChannelMembers) {
if hasPermission, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePublicChannelMembers); hasPermission {
canAddOthers = true
}
}
if channel.Type == model.ChannelTypePrivate {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePrivateChannelMembers) {
if hasPermission, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePrivateChannelMembers); !hasPermission {
c.SetPermissionError(model.PermissionManagePrivateChannelMembers)
return
}
@@ -2085,14 +2107,18 @@ func removeChannelMember(c *Context, w http.ResponseWriter, r *http.Request) {
}
if c.Params.UserId != c.AppContext.Session().UserId {
if channel.Type == model.ChannelTypeOpen && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePublicChannelMembers) {
c.SetPermissionError(model.PermissionManagePublicChannelMembers)
return
if channel.Type == model.ChannelTypeOpen {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePublicChannelMembers); !ok {
c.SetPermissionError(model.PermissionManagePublicChannelMembers)
return
}
}
if channel.Type == model.ChannelTypePrivate && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePrivateChannelMembers) {
c.SetPermissionError(model.PermissionManagePrivateChannelMembers)
return
if channel.Type == model.ChannelTypePrivate {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channel.Id, model.PermissionManagePrivateChannelMembers); !ok {
c.SetPermissionError(model.PermissionManagePrivateChannelMembers)
return
}
}
}
@@ -2234,7 +2260,7 @@ func channelMemberCountsByGroup(c *Context, w http.ResponseWriter, r *http.Reque
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -2456,7 +2482,7 @@ func getGroupMessageMembersCommonTeams(c *Context, w http.ResponseWriter, r *htt
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -2530,12 +2556,12 @@ func canEditChannelBanner(c *Context, originalChannel *model.Channel) {
switch originalChannel.Type {
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePrivateChannelBanner) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePrivateChannelBanner); !ok {
c.SetPermissionError(model.PermissionManagePrivateChannelBanner)
return
}
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePublicChannelBanner) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionManagePublicChannelBanner); !ok {
c.SetPermissionError(model.PermissionManagePublicChannelBanner)
return
}
@@ -2550,7 +2576,7 @@ func getChannelAccessControlAttributes(c *Context, w http.ResponseWriter, r *htt
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}

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

@@ -59,13 +59,13 @@ func createChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
switch channel.Type {
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionAddBookmarkPublicChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionAddBookmarkPublicChannel); !ok {
c.SetPermissionError(model.PermissionAddBookmarkPublicChannel)
return
}
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionAddBookmarkPrivateChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionAddBookmarkPrivateChannel); !ok {
c.SetPermissionError(model.PermissionAddBookmarkPrivateChannel)
return
}
@@ -158,18 +158,23 @@ func updateChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
isMember := false
switch channel.Type {
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionEditBookmarkPublicChannel) {
ok, member := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionEditBookmarkPublicChannel)
if !ok {
c.SetPermissionError(model.PermissionEditBookmarkPublicChannel)
return
}
isMember = member
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionEditBookmarkPrivateChannel) {
ok, member := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionEditBookmarkPrivateChannel)
if !ok {
c.SetPermissionError(model.PermissionEditBookmarkPrivateChannel)
return
}
isMember = member
case model.ChannelTypeGroup, model.ChannelTypeDirect:
// Any member of DM/GMs but guests can manage channel bookmarks
@@ -178,6 +183,7 @@ func updateChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
isMember = true
user, gAppErr := c.App.GetUser(c.AppContext.Session().UserId)
if gAppErr != nil {
c.Err = gAppErr
@@ -201,6 +207,10 @@ func updateChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
auditRec.AddEventResultState(updateChannelBookmarkResponse)
auditRec.AddEventObjectType("updateChannelBookmarkResponse")
@@ -250,19 +260,22 @@ func updateChannelBookmarkSortOrder(c *Context, w http.ResponseWriter, r *http.R
return
}
isMember := false
switch channel.Type {
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionOrderBookmarkPublicChannel) {
ok, member := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionOrderBookmarkPublicChannel)
if !ok {
c.SetPermissionError(model.PermissionOrderBookmarkPublicChannel)
return
}
isMember = member
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionOrderBookmarkPrivateChannel) {
ok, member := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionOrderBookmarkPrivateChannel)
if !ok {
c.SetPermissionError(model.PermissionOrderBookmarkPrivateChannel)
return
}
isMember = member
case model.ChannelTypeGroup, model.ChannelTypeDirect:
// Any member of DM/GMs but guests can manage channel bookmarks
if _, errGet := c.App.GetChannelMember(c.AppContext, channel.Id, c.AppContext.Session().UserId); errGet != nil {
@@ -270,6 +283,7 @@ func updateChannelBookmarkSortOrder(c *Context, w http.ResponseWriter, r *http.R
return
}
isMember = true
user, gAppErr := c.App.GetUser(c.AppContext.Session().UserId)
if gAppErr != nil {
c.Err = gAppErr
@@ -292,6 +306,10 @@ func updateChannelBookmarkSortOrder(c *Context, w http.ResponseWriter, r *http.R
return
}
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
for _, b := range bookmarks {
if b.Id == c.Params.ChannelBookmarkId {
auditRec.AddEventResultState(b)
@@ -335,19 +353,22 @@ func deleteChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
isMember := false
switch channel.Type {
case model.ChannelTypeOpen:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionDeleteBookmarkPublicChannel) {
ok, member := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionDeleteBookmarkPublicChannel)
if !ok {
c.SetPermissionError(model.PermissionDeleteBookmarkPublicChannel)
return
}
isMember = member
case model.ChannelTypePrivate:
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionDeleteBookmarkPrivateChannel) {
ok, member := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionDeleteBookmarkPrivateChannel)
if !ok {
c.SetPermissionError(model.PermissionDeleteBookmarkPrivateChannel)
return
}
isMember = member
case model.ChannelTypeGroup, model.ChannelTypeDirect:
// Any member of DM/GMs but guests can manage channel bookmarks
if _, errGet := c.App.GetChannelMember(c.AppContext, channel.Id, c.AppContext.Session().UserId); errGet != nil {
@@ -355,6 +376,7 @@ func deleteChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
isMember = true
user, gAppErr := c.App.GetUser(c.AppContext.Session().UserId)
if gAppErr != nil {
c.Err = gAppErr
@@ -390,6 +412,10 @@ func deleteChannelBookmark(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
auditRec.AddEventResultState(bookmark)
c.LogAudit("bookmark=" + bookmark.DisplayName)
@@ -423,7 +449,8 @@ func listChannelBookmarksForChannel(c *Context, w http.ResponseWriter, r *http.R
}
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
hasPermission, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if !hasPermission {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -434,6 +461,13 @@ func listChannelBookmarksForChannel(c *Context, w http.ResponseWriter, r *http.R
return
}
auditRec := c.MakeAuditRecord("listChannelBookmarksForChannel", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "channel_id", c.Params.ChannelId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
if err := json.NewEncoder(w).Encode(bookmarks); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}

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

@@ -323,7 +323,7 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
model.AddEventParameterAuditableToAuditRec(auditRec, "command_args", &commandArgs)
// Checks that user is a member of the specified channel, and that they have permission to create a post in it.
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), commandArgs.ChannelId, model.PermissionCreatePost) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), commandArgs.ChannelId, model.PermissionCreatePost); !ok {
c.SetPermissionError(model.PermissionCreatePost)
return
}

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

@@ -38,7 +38,7 @@ func upsertDraft(c *Context, w http.ResponseWriter, r *http.Request) {
hasPermission := false
if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), draft.ChannelId, model.PermissionCreatePost) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), draft.ChannelId, model.PermissionCreatePost); ok {
hasPermission = true
} else if channel, err := c.App.GetChannel(c.AppContext, draft.ChannelId); err == nil {
// Temporary permission check method until advanced permissions, please do not copy

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

@@ -142,7 +142,7 @@ func uploadFileSimple(c *Context, r *http.Request, timestamp time.Time) *model.F
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "channel_id", c.Params.ChannelId)
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionUploadFile) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionUploadFile); !ok {
c.SetPermissionError(model.PermissionUploadFile)
return nil
}
@@ -297,7 +297,7 @@ NextPart:
if c.Err != nil {
return nil
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionUploadFile) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionUploadFile); !ok {
c.SetPermissionError(model.PermissionUploadFile)
return nil
}
@@ -391,7 +391,7 @@ func uploadFileMultipartLegacy(c *Context, mr *multipart.Reader,
if c.Err != nil {
return nil
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionUploadFile) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionUploadFile); !ok {
c.SetPermissionError(model.PermissionUploadFile)
return nil
}
@@ -488,7 +488,7 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
perm := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
perm, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if info.CreatorId == model.BookmarkFileOwner {
if !perm {
c.SetPermissionError(model.PermissionReadChannelContent)
@@ -510,6 +510,10 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec.Success()
web.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 !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getFileThumbnail(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -531,7 +535,7 @@ func getFileThumbnail(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
perm := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
perm, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if info.CreatorId == model.BookmarkFileOwner {
if !perm {
c.SetPermissionError(model.PermissionReadChannelContent)
@@ -556,6 +560,13 @@ func getFileThumbnail(c *Context, w http.ResponseWriter, r *http.Request) {
defer fileReader.Close()
web.WriteFileResponse(info.Name, ThumbnailImageType, 0, time.Unix(0, info.UpdateAt*int64(1000*1000)), *c.App.Config().ServiceSettings.WebserverMode, fileReader, forceDownload, w, r)
auditRec := c.MakeAuditRecord("getFileThumbnail", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "file_id", c.Params.FileId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -585,7 +596,7 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
perm := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
perm, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if info.CreatorId == model.BookmarkFileOwner {
if !perm {
c.SetPermissionError(model.PermissionReadChannelContent)
@@ -601,6 +612,10 @@ func getFileLink(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
resp := make(map[string]string)
link := c.App.GeneratePublicLink(c.GetSiteURLHeader(), info)
resp["link"] = link
@@ -631,7 +646,7 @@ func getFilePreview(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
perm := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
perm, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if info.CreatorId == model.BookmarkFileOwner {
if !perm {
c.SetPermissionError(model.PermissionReadChannelContent)
@@ -656,6 +671,13 @@ func getFilePreview(c *Context, w http.ResponseWriter, r *http.Request) {
defer fileReader.Close()
web.WriteFileResponse(info.Name, PreviewImageType, 0, time.Unix(0, info.UpdateAt*int64(1000*1000)), *c.App.Config().ServiceSettings.WebserverMode, fileReader, forceDownload, w, r)
auditRec := c.MakeAuditRecord("getFilePreview", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "file_id", c.Params.FileId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -676,7 +698,7 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
perm := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
perm, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if info.CreatorId == model.BookmarkFileOwner {
if !perm {
c.SetPermissionError(model.PermissionReadChannelContent)
@@ -691,6 +713,14 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
if err := json.NewEncoder(w).Encode(info); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getFileInfo", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "file_id", c.Params.FileId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getPublicFile(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -795,7 +825,7 @@ func searchFiles(c *Context, w http.ResponseWriter, r *http.Request, teamID stri
startTime := time.Now()
results, err := c.App.SearchFilesInTeamForUser(c.AppContext, terms, c.AppContext.Session().UserId, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
results, allFilesHaveMembership, err := c.App.SearchFilesInTeamForUser(c.AppContext, terms, c.AppContext.Session().UserId, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
metrics := c.App.Metrics()
@@ -813,6 +843,16 @@ func searchFiles(c *Context, w http.ResponseWriter, r *http.Request, teamID stri
if err := json.NewEncoder(w).Encode(results); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("searchFiles", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterAuditableToAuditRec(auditRec, "search_params", params)
if !allFilesHaveMembership {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
}
func setInaccessibleFileHeader(w http.ResponseWriter, appErr *model.AppError) {

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

@@ -702,7 +702,7 @@ func verifyLinkUnlinkPermission(c *Context, syncableType model.GroupSyncableType
permission = model.PermissionManagePublicChannelMembers
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), syncableID, permission) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), syncableID, permission); !ok {
return model.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission})
}
}
@@ -936,7 +936,7 @@ func getGroupsByChannelCommon(c *Context, r *http.Request) ([]byte, *model.AppEr
} else {
permission = model.PermissionReadPublicChannelGroups
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, permission) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, permission); !ok {
return nil, model.MakePermissionError(c.AppContext.Session(), []*model.Permission{permission})
}
@@ -1102,7 +1102,7 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
permission = model.PermissionManagePublicChannelMembers
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), NotAssociatedToChannelID, permission) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), NotAssociatedToChannelID, permission); !ok {
c.SetPermissionError(permission)
return
}
@@ -1121,7 +1121,7 @@ func getGroups(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
permission = model.PermissionManagePublicChannelMembers
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), ChannelIDForMemberCount, permission) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), ChannelIDForMemberCount, permission); !ok {
c.SetPermissionError(permission)
return
}

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

@@ -49,12 +49,12 @@ func doPostAction(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
} else {
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -118,7 +118,7 @@ func submitDialog(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}

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

@@ -104,7 +104,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
rp, err := c.App.CreatePostAsUser(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(&post), c.AppContext.Session().Id, setOnlineBool)
rp, isMemberForPreviews, err := c.App.CreatePostAsUser(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(&post), c.AppContext.Session().Id, setOnlineBool)
if err != nil {
c.Err = err
return
@@ -113,6 +113,14 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec.AddEventResultState(rp)
auditRec.AddEventObjectType("post")
if !isMemberForPreviews {
previewPost := rp.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
if setOnlineBool {
c.App.SetStatusOnline(c.AppContext.Session().UserId, false)
}
@@ -155,12 +163,13 @@ func createEphemeralPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
rp := c.App.SendEphemeralPost(c.AppContext, ephRequest.UserID, c.App.PostWithProxyRemovedFromImageURLs(ephRequest.Post))
// We prepare again the post here, so we can ignore the isMemberForPreviews return value from SendEphemeralPost
rp, _ := c.App.SendEphemeralPost(c.AppContext, ephRequest.UserID, c.App.PostWithProxyRemovedFromImageURLs(ephRequest.Post))
w.WriteHeader(http.StatusCreated)
rp = model.AddPostActionCookies(rp, c.App.PostActionCookieSecret())
rp = c.App.PreparePostForClientWithEmbedsAndImages(c.AppContext, rp, true, false, true)
rp, err := c.App.SanitizePostMetadataForUser(c.AppContext, rp, c.AppContext.Session().UserId)
rp, isMemberForPreviews, err := c.App.SanitizePostMetadataForUser(c.AppContext, rp, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
@@ -168,6 +177,19 @@ func createEphemeralPost(c *Context, w http.ResponseWriter, r *http.Request) {
if err := rp.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("createEphemeralPost", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_id", rp.Id)
if !isMemberForPreviews {
previewPost := rp.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
}
func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -216,7 +238,8 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = err
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
hasPermission, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if !hasPermission {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -275,7 +298,7 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
c.App.AddCursorIdsForPostList(list, afterPost, beforePost, since, page, perPage, collapsedThreads)
clientPostList := c.App.PreparePostListForClient(c.AppContext, list)
clientPostList, err = c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
clientPostList, isMemberForAllPreviews, err := c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
@@ -284,6 +307,16 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
if err := clientPostList.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getPostsForChannel", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "channel_id", channelId)
if !isMember || !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access_on_previews", true)
}
}
}
func getPostsForChannelAroundLastUnread(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -304,7 +337,8 @@ func getPostsForChannelAroundLastUnread(c *Context, w http.ResponseWriter, r *ht
c.Err = err
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
hasPermission, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if !hasPermission {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -343,7 +377,7 @@ func getPostsForChannelAroundLastUnread(c *Context, w http.ResponseWriter, r *ht
postList.PrevPostId = c.App.GetPrevPostIdFromPostList(postList, collapsedThreads)
clientPostList := c.App.PreparePostListForClient(c.AppContext, postList)
clientPostList, err = c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
clientPostList, isMemberForAllPreviews, err := c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
@@ -355,6 +389,17 @@ func getPostsForChannelAroundLastUnread(c *Context, w http.ResponseWriter, r *ht
if err := clientPostList.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getPostsForChannelAroundLastUnread", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "channel_id", channelId)
if !isMember || !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access_on_previews", true)
}
}
}
func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -402,6 +447,7 @@ func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request)
pl := model.NewPostList()
channelReadPermission := make(map[string]bool)
isMemberForAllPosts := true
for _, post := range posts.Posts {
allowed, ok := channelReadPermission[post.ChannelId]
@@ -413,8 +459,11 @@ func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request)
if !ok {
continue
}
if c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
hasPermission, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if hasPermission {
allowed = true
isMemberForAllPosts = isMemberForAllPosts && isMember
}
channelReadPermission[post.ChannelId] = allowed
@@ -430,11 +479,23 @@ func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request)
pl.SortByCreateAt()
clientPostList := c.App.PreparePostListForClient(c.AppContext, pl)
clientPostList, err = c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
clientPostList, isMemberForAllPreviews, err := c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
}
auditRec := c.MakeAuditRecord("getFlaggedPosts", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "channel_id", channelId)
if !isMemberForAllPosts || !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access_on_previews", true)
}
}
if err := clientPostList.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
@@ -453,7 +514,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
post, err := c.App.GetPostIfAuthorized(c.AppContext, c.Params.PostId, c.AppContext.Session(), includeDeleted)
post, err, isMember := c.App.GetPostIfAuthorized(c.AppContext, c.Params.PostId, c.AppContext.Session(), includeDeleted)
if err != nil {
c.Err = err
@@ -466,7 +527,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
post = c.App.PreparePostForClientWithEmbedsAndImages(c.AppContext, post, false, false, true)
post, err = c.App.SanitizePostMetadataForUser(c.AppContext, post, c.AppContext.Session().UserId)
post, previewIsMember, err := c.App.SanitizePostMetadataForUser(c.AppContext, post, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
@@ -480,6 +541,20 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
if err := post.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getPost", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_id", c.Params.PostId)
if !isMember || !previewIsMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !previewIsMember {
previewPost := post.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
}
}
}
// getPostsByIds also sets a header to indicate, if posts were truncated as per the cloud plan's limit.
@@ -519,16 +594,20 @@ func getPostsByIds(c *Context, w http.ResponseWriter, r *http.Request) {
}
var posts = []*model.Post{}
isMemberForAllPosts := true
for _, post := range postsList {
channel, ok := channelMap[post.ChannelId]
if !ok {
continue
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
hasPermission, isMemberForCurrentPost := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if !hasPermission {
continue
}
isMemberForAllPosts = isMemberForAllPosts && isMemberForCurrentPost
post = c.App.PreparePostForClient(c.AppContext, post, false, false, true)
post.StripActionIntegrations()
posts = append(posts, post)
@@ -539,6 +618,14 @@ func getPostsByIds(c *Context, w http.ResponseWriter, r *http.Request) {
if err := json.NewEncoder(w).Encode(posts); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getPostsByIds", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_ids", postIDs)
if !isMemberForAllPosts {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getEditHistoryForPost(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -553,7 +640,8 @@ func getEditHistoryForPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, model.PermissionEditPost) {
ok, isMember := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, model.PermissionEditPost)
if !ok {
c.SetPermissionError(model.PermissionEditPost)
return
}
@@ -569,6 +657,14 @@ func getEditHistoryForPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getEditHistoryForPost", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_id", c.Params.PostId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
if err := json.NewEncoder(w).Encode(postsList); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
@@ -608,12 +704,12 @@ func deletePost(c *Context, w http.ResponseWriter, _ *http.Request) {
auditRec.AddEventObjectType("post")
if c.AppContext.Session().UserId == post.UserId {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), post.ChannelId, model.PermissionDeletePost) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), post.ChannelId, model.PermissionDeletePost); !ok {
c.SetPermissionError(model.PermissionDeletePost)
return
}
} else {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), post.ChannelId, model.PermissionDeleteOthersPosts) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), post.ChannelId, model.PermissionDeleteOthersPosts); !ok {
c.SetPermissionError(model.PermissionDeleteOthersPosts)
return
}
@@ -739,7 +835,8 @@ func getPostThread(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if _, err = c.App.GetPostIfAuthorized(c.AppContext, post.Id, c.AppContext.Session(), false); err != nil {
var isMember bool
if _, err, isMember = c.App.GetPostIfAuthorized(c.AppContext, post.Id, c.AppContext.Session(), false); err != nil {
c.Err = err
return
}
@@ -749,7 +846,7 @@ func getPostThread(c *Context, w http.ResponseWriter, r *http.Request) {
}
clientPostList := c.App.PreparePostListForClient(c.AppContext, list)
clientPostList, err = c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
clientPostList, isMemberForAllPreviews, err := c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
@@ -760,6 +857,17 @@ func getPostThread(c *Context, w http.ResponseWriter, r *http.Request) {
if err := clientPostList.EncodeJSON(w); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getPostThread", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_id", c.Params.PostId)
if !isMember || !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access_on_previews", true)
}
}
}
func searchPostsInTeam(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -824,7 +932,7 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request, teamId stri
startTime := time.Now()
results, err := c.App.SearchPostsForUser(c.AppContext, terms, c.AppContext.Session().UserId, teamId, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
results, allPostHaveMembership, err := c.App.SearchPostsForUser(c.AppContext, terms, c.AppContext.Session().UserId, teamId, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
elapsedTime := float64(time.Since(startTime)) / float64(time.Second)
metrics := c.App.Metrics()
@@ -839,12 +947,19 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request, teamId stri
}
clientPostList := c.App.PreparePostListForClient(c.AppContext, results.PostList)
clientPostList, err = c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
clientPostList, isMemberForAllPreviews, err := c.App.SanitizePostListMetadataForUser(c.AppContext, clientPostList, c.AppContext.Session().UserId)
if err != nil {
c.Err = err
return
}
if !allPostHaveMembership || !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForAllPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access_on_previews", true)
}
}
results = model.MakePostSearchResults(clientPostList, results.Matches)
model.AddEventParameterAuditableToAuditRec(auditRec, "search_results", results)
auditRec.Success()
@@ -888,7 +1003,8 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, model.PermissionEditPost) {
ok, isMember := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, model.PermissionEditPost)
if !ok {
c.SetPermissionError(model.PermissionEditPost)
return
}
@@ -903,7 +1019,8 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
}
if c.AppContext.Session().UserId != originalPost.UserId {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, model.PermissionEditOthersPosts) {
// We don't need to check the member here, since we already checked it above
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, model.PermissionEditOthersPosts); !ok {
c.SetPermissionError(model.PermissionEditOthersPosts)
return
}
@@ -916,12 +1033,22 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
rpost, err := c.App.UpdatePost(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(&post), &model.UpdatePostOptions{SafeUpdate: false})
rpost, isMemberForPreviews, err := c.App.UpdatePost(c.AppContext, c.App.PostWithProxyRemovedFromImageURLs(&post), &model.UpdatePostOptions{SafeUpdate: false})
if err != nil {
c.Err = err
return
}
if !isMember || !isMemberForPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForPreviews {
previewPost := rpost.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
}
}
auditRec.Success()
auditRec.AddEventResultState(rpost)
@@ -954,17 +1081,21 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
postPatchChecks(c, auditRec, post.Message)
isMember := postPatchChecks(c, auditRec, post.Message)
if c.Err != nil {
return
}
patchedPost, err := c.App.PatchPost(c.AppContext, c.Params.PostId, c.App.PostPatchWithProxyRemovedFromImageURLs(&post), nil)
patchedPost, isMemberForPReviews, err := c.App.PatchPost(c.AppContext, c.Params.PostId, c.App.PostPatchWithProxyRemovedFromImageURLs(&post), nil)
if err != nil {
c.Err = err
return
}
if !isMember || !isMemberForPReviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
auditRec.AddEventResultState(patchedPost)
@@ -973,11 +1104,11 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
func postPatchChecks(c *Context, auditRec *model.AuditRecord, message *string) {
func postPatchChecks(c *Context, auditRec *model.AuditRecord, message *string) bool {
originalPost, err := c.App.GetSinglePost(c.AppContext, c.Params.PostId, false)
if err != nil {
c.SetPermissionError(model.PermissionEditPost)
return
return false
}
auditRec.AddEventPriorState(originalPost)
auditRec.AddEventObjectType("post")
@@ -990,15 +1121,18 @@ func postPatchChecks(c *Context, auditRec *model.AuditRecord, message *string) {
permission = model.PermissionEditOthersPosts
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, permission) {
ok, isMember := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), originalPost.ChannelId, permission)
if !ok {
c.SetPermissionError(permission)
return
return false
}
if *c.App.Config().ServiceSettings.PostEditTimeLimit != -1 && model.GetMillis() > originalPost.CreateAt+int64(*c.App.Config().ServiceSettings.PostEditTimeLimit*1000) && message != nil {
c.Err = model.NewAppError("patchPost", "api.post.update_post.permissions_time_limit.app_error", map[string]any{"timeLimit": *c.App.Config().ServiceSettings.PostEditTimeLimit}, "", http.StatusBadRequest)
return
return isMember
}
return isMember
}
func setPostUnread(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1014,7 +1148,7 @@ func setPostUnread(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PermissionEditOtherUsers)
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -1039,7 +1173,7 @@ func setPostReminder(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PermissionEditOtherUsers)
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -1082,7 +1216,8 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, isPinned bool) {
c.Err = err
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
ok, isMember := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
if !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -1090,11 +1225,22 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, isPinned bool) {
patch := &model.PostPatch{}
patch.IsPinned = model.NewPointer(isPinned)
patchedPost, err := c.App.PatchPost(c.AppContext, c.Params.PostId, patch, nil)
patchedPost, isMemberForPreviews, err := c.App.PatchPost(c.AppContext, c.Params.PostId, patch, nil)
if err != nil {
c.Err = err
return
}
if !isMember || !isMemberForPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForPreviews {
previewPost := patchedPost.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
}
}
auditRec.AddEventResultState(patchedPost)
auditRec.Success()
@@ -1126,7 +1272,7 @@ func acknowledgePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -1165,7 +1311,7 @@ func unacknowledgePost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -1246,7 +1392,7 @@ func moveThread(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
sourcePost, err := c.App.GetPostIfAuthorized(c.AppContext, c.Params.PostId, c.AppContext.Session(), false)
sourcePost, err, _ := c.App.GetPostIfAuthorized(c.AppContext, c.Params.PostId, c.AppContext.Session(), false)
if err != nil {
c.Err = err
if err.Id == "app.post.cloud.get.app_error" {
@@ -1273,7 +1419,8 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
ok, isMember := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId)
if !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -1300,6 +1447,14 @@ func getFileInfosForPost(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("getFileInfosForPost", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_id", c.Params.PostId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
w.Header().Set("Cache-Control", "max-age=2592000, private")
w.Header().Set(model.HeaderEtagServer, model.GetEtagForFileInfos(infos))
if _, err := w.Write(js); err != nil {
@@ -1360,17 +1515,27 @@ func restorePostVersion(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
postPatchChecks(c, auditRec, &toRestorePost.Message)
isMember := postPatchChecks(c, auditRec, &toRestorePost.Message)
if c.Err != nil {
return
}
updatedPost, appErr := c.App.RestorePostVersion(c.AppContext, c.AppContext.Session().UserId, c.Params.PostId, restoreVersionId)
updatedPost, isMemberForPreview, appErr := c.App.RestorePostVersion(c.AppContext, c.AppContext.Session().UserId, c.Params.PostId, restoreVersionId)
if appErr != nil {
c.Err = appErr
return
}
if !isMember || !isMemberForPreview {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
if !isMemberForPreview {
previewPost := updatedPost.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
}
}
auditRec.Success()
auditRec.AddEventResultState(updatedPost)

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

@@ -1375,7 +1375,7 @@ func TestUpdatePost(t *testing.T) {
fileIds[i] = fileResp.FileInfos[0].Id
}
rpost, appErr := th.App.CreatePost(th.Context, &model.Post{
rpost, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
@@ -1408,7 +1408,7 @@ func TestUpdatePost(t *testing.T) {
t.Run("join/leave post", func(t *testing.T) {
var rpost2 *model.Post
rpost2, appErr = th.App.CreatePost(th.Context, &model.Post{
rpost2, _, appErr = th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
Type: model.PostTypeJoinLeave,
@@ -1426,7 +1426,7 @@ func TestUpdatePost(t *testing.T) {
CheckBadRequestStatus(t, resp)
})
rpost3, appErr := th.App.CreatePost(th.Context, &model.Post{
rpost3, _, appErr := th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
UserId: th.BasicUser.Id,
@@ -1458,7 +1458,7 @@ func TestUpdatePost(t *testing.T) {
*cfg.ServiceSettings.PostEditTimeLimit = -1
})
rpost4, appErr := th.App.CreatePost(th.Context, &model.Post{
rpost4, _, appErr := th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
UserId: th.BasicUser.Id,
@@ -1538,7 +1538,7 @@ func TestUpdatePost(t *testing.T) {
fileInfo := fileResponse.FileInfos[0]
// create new post
post, appErr := th.App.CreatePost(th.Context, &model.Post{
post, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
@@ -1574,7 +1574,7 @@ func TestUpdatePost(t *testing.T) {
fileInfo := fileResponse.FileInfos[0]
// create new post
post, appErr := th.App.CreatePost(th.Context, &model.Post{
post, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
@@ -1612,7 +1612,7 @@ func TestUpdatePost(t *testing.T) {
fileInfo := fileResponse.FileInfos[0]
// create new post
post, appErr := th.App.CreatePost(th.Context, &model.Post{
post, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
@@ -1658,7 +1658,7 @@ func TestUpdatePost(t *testing.T) {
fileInfo2 := fileResponse2.FileInfos[0]
// create new post
post, appErr := th.App.CreatePost(th.Context, &model.Post{
post, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: channel.Id,
Message: "zz" + model.NewId() + "a",
@@ -4322,13 +4322,13 @@ func TestSetChannelUnread(t *testing.T) {
t.Run("Unread on a direct channel in a thread", func(t *testing.T) {
dc := th.CreateDmChannel(th.CreateUser())
rootPost, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: u1.Id, CreateAt: now, ChannelId: dc.Id, Message: "root"}, dc, model.CreatePostFlags{})
rootPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: u1.Id, CreateAt: now, ChannelId: dc.Id, Message: "root"}, dc, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: u1.Id, CreateAt: now + 10, ChannelId: dc.Id, Message: "reply 1"}, dc, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: u1.Id, CreateAt: now + 10, ChannelId: dc.Id, Message: "reply 1"}, dc, model.CreatePostFlags{})
require.Nil(t, appErr)
reply2, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: u1.Id, CreateAt: now + 20, ChannelId: dc.Id, Message: "reply 2"}, dc, model.CreatePostFlags{})
reply2, _, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: u1.Id, CreateAt: now + 20, ChannelId: dc.Id, Message: "reply 2"}, dc, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: u1.Id, CreateAt: now + 30, ChannelId: dc.Id, Message: "reply 3"}, dc, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: u1.Id, CreateAt: now + 30, ChannelId: dc.Id, Message: "reply 3"}, dc, model.CreatePostFlags{})
require.Nil(t, appErr)
// Ensure that post have been read
@@ -4428,19 +4428,19 @@ func TestSetPostUnreadWithoutCollapsedThreads(t *testing.T) {
// user1: a root post
// user2: Another root mention @u1
user1Mention := " @" + th.BasicUser.Username
rootPost1, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "first root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
rootPost1, _, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "first root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hello"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hello"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
replyPost1, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
replyPost1, _, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another reply"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another reply"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "a root post"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "a root post"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
t.Run("Mark reply post as unread", func(t *testing.T) {
@@ -4546,7 +4546,7 @@ func TestGetEditHistoryForPost(t *testing.T) {
UserId: th.BasicUser.Id,
}
rpost, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
rpost, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
time.Sleep(1 * time.Millisecond)
@@ -4617,7 +4617,7 @@ func TestGetEditHistoryForPost(t *testing.T) {
FileIds: []string{fileInfo1.Id, fileInfo2.Id},
}
createdPost, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
createdPost, _, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
require.Contains(t, createdPost.FileIds, fileInfo1.Id)
require.Contains(t, createdPost.FileIds, fileInfo2.Id)
@@ -4774,7 +4774,7 @@ func TestCreatePostNotificationsWithCRT(t *testing.T) {
require.NoError(t, err)
// post a reply on the thread
_, appErr := th.App.CreatePostAsUser(th.Context, tc.post, th.Context.Session().Id, false)
_, _, appErr := th.App.CreatePostAsUser(th.Context, tc.post, th.Context.Session().Id, false)
require.Nil(t, appErr)
var caught bool

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

@@ -10,7 +10,7 @@ import (
func userCreatePostPermissionCheckWithContext(c *Context, channelId string) {
hasPermission := false
if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionCreatePost) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionCreatePost); ok {
hasPermission = true
} else if channel, err := c.App.GetChannel(c.AppContext, channelId); err == nil {
// Temporary permission check method until advanced permissions, please do not copy

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

@@ -131,7 +131,7 @@ func updatePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}

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

@@ -57,7 +57,7 @@ func getReactions(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.PostId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.PostId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -117,7 +117,7 @@ func getBulkReactions(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
for _, postId := range postIds {
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), postId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), postId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}

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

@@ -261,7 +261,7 @@ func getSharedChannelRemotes(c *Context, w http.ResponseWriter, r *http.Request)
return
}
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), c.Params.ChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}

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

@@ -149,7 +149,7 @@ func TestSharedChannelPostMetadataSync(t *testing.T) {
})
// Create a local post with priority metadata
originalPost, appErr := th.App.CreatePost(th.Context, &model.Post{
originalPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: testChannel.Id,
Message: "Test post with priority metadata @" + th.BasicUser2.Username,
@@ -204,7 +204,7 @@ func TestSharedChannelPostMetadataSync(t *testing.T) {
})
// Create post with acknowledgement request
originalPost, appErr := th.App.CreatePost(th.Context, &model.Post{
originalPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: testChannel.Id,
Message: "Test post requesting acknowledgements @" + th.BasicUser2.Username,
@@ -274,7 +274,7 @@ func TestSharedChannelPostMetadataSync(t *testing.T) {
})
// Create post with acknowledgement request
originalPost, appErr := th.App.CreatePost(th.Context, &model.Post{
originalPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: testChannel.Id,
Message: "Test post for ack count sync @" + th.BasicUser2.Username,
@@ -370,7 +370,7 @@ func TestSharedChannelPostMetadataSync(t *testing.T) {
})
// Create post with persistent notifications enabled
_, appErr := th.App.CreatePost(th.Context, &model.Post{
_, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: testChannel.Id,
Message: "Test post with persistent notifications @" + th.BasicUser2.Username,
@@ -535,7 +535,7 @@ func TestSharedChannelPostMetadataSync(t *testing.T) {
// STEP 1: Server A creates a post with acknowledgement request
t.Log("=== STEP 1: Server A creates post with ack request ===")
originalPost, appErr := th.App.CreatePost(th.Context, &model.Post{
originalPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: testChannel.Id,
Message: "Cross-cluster ack test - please acknowledge",

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

@@ -739,7 +739,9 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
}
// Return post data only when PostId is passed.
if ack.PostId != "" && ack.NotificationType == model.PushTypeMessage {
if _, appErr := c.App.GetPostIfAuthorized(c.AppContext, ack.PostId, c.AppContext.Session(), false); appErr != nil {
var isMember bool
var appErr *model.AppError
if _, appErr, isMember = c.App.GetPostIfAuthorized(c.AppContext, ack.PostId, c.AppContext.Session(), false); appErr != nil {
c.Err = appErr
return
}
@@ -759,6 +761,14 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
if err2 := json.NewEncoder(w).Encode(msg); err2 != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err2))
}
auditRec := c.MakeAuditRecord("notificationAck", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "post_id", ack.PostId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
return

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

@@ -56,7 +56,7 @@ func createUpload(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
} else {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), us.ChannelId, model.PermissionUploadFile) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), us.ChannelId, model.PermissionUploadFile); !ok {
c.SetPermissionError(model.PermissionUploadFile)
return
}
@@ -142,7 +142,10 @@ func uploadData(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
} else {
if us.UserId != c.AppContext.Session().UserId || !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), us.ChannelId, model.PermissionUploadFile) {
if us.UserId != c.AppContext.Session().UserId {
c.SetPermissionError(model.PermissionUploadFile)
return
} else if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), us.ChannelId, model.PermissionUploadFile); !ok {
c.SetPermissionError(model.PermissionUploadFile)
return
}

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

@@ -933,7 +933,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
profiles, appErr = c.App.GetUsersWithoutTeamPage(userGetOptions, c.IsSystemAdmin())
} else if notInChannelId != "" {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), notInChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), notInChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -975,7 +975,7 @@ func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
profiles, appErr = c.App.GetUsersInTeamPage(userGetOptions, c.IsSystemAdmin())
}
} else if inChannelId != "" {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), inChannelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), inChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -1182,14 +1182,18 @@ func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
if props.InChannelId != "" && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), props.InChannelId, model.PermissionReadChannel) {
c.SetPermissionError(model.PermissionReadChannel)
return
if props.InChannelId != "" {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), props.InChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
}
if props.NotInChannelId != "" && !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), props.NotInChannelId, model.PermissionReadChannel) {
c.SetPermissionError(model.PermissionReadChannel)
return
if props.NotInChannelId != "" {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), props.NotInChannelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
}
if props.TeamId != "" && !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), props.TeamId, model.PermissionViewTeam) {
@@ -1275,7 +1279,7 @@ func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
}
if channelId != "" {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionReadChannel) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelId, model.PermissionReadChannel); !ok {
c.SetPermissionError(model.PermissionReadChannel)
return
}
@@ -3084,7 +3088,7 @@ func publishUserTyping(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.HasPermissionToChannel(c.AppContext, c.Params.UserId, typingRequest.ChannelId, model.PermissionCreatePost) {
if ok, _ := c.App.HasPermissionToChannel(c.AppContext, c.Params.UserId, typingRequest.ChannelId, model.PermissionCreatePost); !ok {
c.SetPermissionError(model.PermissionCreatePost)
return
}
@@ -3411,7 +3415,8 @@ func getThreadForUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PermissionEditOtherUsers)
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.ThreadId, model.PermissionReadChannelContent) {
ok, isMember := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.ThreadId)
if !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -3433,6 +3438,14 @@ func getThreadForUser(c *Context, w http.ResponseWriter, r *http.Request) {
if err := json.NewEncoder(w).Encode(thread); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
auditRec := c.MakeAuditRecord("getThreadForUser", model.AuditStatusSuccess)
defer c.LogAuditRec(auditRec)
model.AddEventParameterToAuditRec(auditRec, "thread_id", c.Params.ThreadId)
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
}
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -3528,11 +3541,16 @@ func updateReadStateThreadByUser(c *Context, w http.ResponseWriter, r *http.Requ
c.SetPermissionError(model.PermissionEditOtherUsers)
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.ThreadId, model.PermissionReadChannelContent) {
ok, isMember := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.ThreadId)
if !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
thread, err := c.App.UpdateThreadReadForUser(c.AppContext, c.AppContext.Session().Id, c.Params.UserId, c.Params.TeamId, c.Params.ThreadId, c.Params.Timestamp)
if err != nil {
c.Err = err
@@ -3564,10 +3582,14 @@ func setUnreadThreadByPostId(c *Context, w http.ResponseWriter, r *http.Request)
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.ThreadId, model.PermissionReadChannelContent) {
ok, isMember := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.ThreadId)
if !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
// We want to make sure the thread is followed when marking as unread
// https://mattermost.atlassian.net/browse/MM-36430
@@ -3606,7 +3628,7 @@ func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
c.SetPermissionError(model.PermissionEditOtherUsers)
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.ThreadId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.ThreadId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
@@ -3639,7 +3661,7 @@ func followThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.ThreadId, model.PermissionReadChannelContent) {
if ok, _ := c.App.SessionHasPermissionToReadPost(c.AppContext, *c.AppContext.Session(), c.Params.ThreadId); !ok {
c.SetPermissionError(model.PermissionReadChannelContent)
return
}

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

@@ -7523,7 +7523,7 @@ func TestThreadSocketEvents(t *testing.T) {
require.NoError(t, err)
CheckCreatedStatus(t, resp)
replyPost, appErr := th.App.CreatePostAsUser(th.Context, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply @" + th.BasicUser.Username, UserId: th.BasicUser2.Id, RootId: rpost.Id}, th.Context.Session().Id, false)
replyPost, _, appErr := th.App.CreatePostAsUser(th.Context, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply @" + th.BasicUser.Username, UserId: th.BasicUser2.Id, RootId: rpost.Id}, th.Context.Session().Id, false)
require.Nil(t, appErr)
defer func() {
err = th.App.Srv().Store().Post().PermanentDeleteByUser(th.Context, th.BasicUser.Id)
@@ -7700,7 +7700,7 @@ func TestThreadSocketEvents(t *testing.T) {
for _, tc := range testCases {
// post a reply on the thread
_, appErr = th.App.CreatePostAsUser(th.Context, tc.post, th.Context.Session().Id, false)
_, _, appErr = th.App.CreatePostAsUser(th.Context, tc.post, th.Context.Session().Id, false)
require.Nil(t, appErr)
var caught bool
@@ -7734,18 +7734,18 @@ func TestThreadSocketEvents(t *testing.T) {
rpost2 := &model.Post{ChannelId: th.BasicChannel.Id, UserId: th.BasicUser2.Id, Message: "root post"}
var appErr *model.AppError
rpost2, appErr = th.App.CreatePostAsUser(th.Context, rpost2, th.Context.Session().Id, false)
rpost2, _, appErr = th.App.CreatePostAsUser(th.Context, rpost2, th.Context.Session().Id, false)
require.Nil(t, appErr)
reply1 := &model.Post{ChannelId: th.BasicChannel.Id, UserId: th.BasicUser2.Id, Message: "reply 1", RootId: rpost2.Id}
reply2 := &model.Post{ChannelId: th.BasicChannel.Id, UserId: th.BasicUser2.Id, Message: "reply 2", RootId: rpost2.Id}
reply3 := &model.Post{ChannelId: th.BasicChannel.Id, UserId: th.BasicUser2.Id, Message: "mention @" + th.BasicUser.Username, RootId: rpost2.Id}
_, appErr = th.App.CreatePostAsUser(th.Context, reply1, th.Context.Session().Id, false)
_, _, appErr = th.App.CreatePostAsUser(th.Context, reply1, th.Context.Session().Id, false)
require.Nil(t, appErr)
_, appErr = th.App.CreatePostAsUser(th.Context, reply2, th.Context.Session().Id, false)
_, _, appErr = th.App.CreatePostAsUser(th.Context, reply2, th.Context.Session().Id, false)
require.Nil(t, appErr)
_, appErr = th.App.CreatePostAsUser(th.Context, reply3, th.Context.Session().Id, false)
_, _, appErr = th.App.CreatePostAsUser(th.Context, reply3, th.Context.Session().Id, false)
require.Nil(t, appErr)
count := 0

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

@@ -50,7 +50,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.LogAudit("fail - bad channel permissions")
c.SetPermissionError(model.PermissionReadChannelContent)
return
@@ -154,10 +154,12 @@ func updateIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if channel.Type != model.ChannelTypeOpen && !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel) {
c.LogAudit("fail - bad channel permissions")
c.SetPermissionError(model.PermissionReadChannelContent)
return
if channel.Type != model.ChannelTypeOpen {
if ok, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel); !ok {
c.LogAudit("fail - bad channel permissions")
c.SetPermissionError(model.PermissionReadChannelContent)
return
}
}
incomingHook, err := c.App.UpdateIncomingWebhook(oldHook, &updatedHook)
@@ -275,8 +277,14 @@ func getIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageIncomingWebhooks) ||
(channel.Type != model.ChannelTypeOpen && !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)) {
isPrivate := channel.Type != model.ChannelTypeOpen
restrictedChannel := false
if isPrivate {
hasChannelPermission, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
restrictedChannel = !hasChannelPermission
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageIncomingWebhooks) || restrictedChannel {
c.LogAudit("fail - bad permissions")
c.SetPermissionError(model.PermissionManageIncomingWebhooks)
return
@@ -329,8 +337,14 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec.AddMeta("channel_name", channel.Name)
auditRec.AddMeta("team_id", hook.TeamId)
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageIncomingWebhooks) ||
(channel.Type != model.ChannelTypeOpen && !c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)) {
isPrivate := channel.Type != model.ChannelTypeOpen
restrictedChannel := false
if isPrivate {
hasChannelPermission, _ := c.App.SessionHasPermissionToReadChannel(c.AppContext, *c.AppContext.Session(), channel)
restrictedChannel = !hasChannelPermission
}
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), hook.TeamId, model.PermissionManageIncomingWebhooks) || restrictedChannel {
c.LogAudit("fail - bad permissions")
c.SetPermissionError(model.PermissionManageIncomingWebhooks)
return
@@ -481,13 +495,13 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
)
if channelID != "" {
if !c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOutgoingWebhooks) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOutgoingWebhooks); !ok {
c.SetPermissionError(model.PermissionManageOutgoingWebhooks)
return
}
// Remove userId as a filter if they have permission to manage others.
if c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOthersOutgoingWebhooks) {
if ok, _ := c.App.SessionHasPermissionToChannel(c.AppContext, *c.AppContext.Session(), channelID, model.PermissionManageOthersOutgoingWebhooks); ok {
userID = ""
}

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

@@ -91,42 +91,52 @@ func (a *App) SessionHasPermissionToTeams(c request.CTX, session model.Session,
return true
}
func (a *App) SessionHasPermissionToChannel(c request.CTX, session model.Session, channelID string, permission *model.Permission) bool {
// SessionHasPermissionToChannel checks if the session has permission to the given channel.
//
// Returns:
//
// (hasPermission, isMember)
//
// hasPermission: true if the user has the specified permission for the channel, otherwise false.
// isMember: used for auditing access without membership. True if the user is a member of the channel, otherwise false.
func (a *App) SessionHasPermissionToChannel(c request.CTX, session model.Session, channelID string, permission *model.Permission) (hasPermission bool, isMember bool) {
if channelID == "" {
return false
return false, false
}
channel, appErr := a.GetChannel(c, channelID)
if appErr != nil && appErr.StatusCode == http.StatusNotFound {
return false
return false, false
} else if appErr != nil {
c.Logger().Warn("Failed to get channel", mlog.String("channel_id", channelID), mlog.Err(appErr))
}
if session.IsUnrestricted() || a.RolesGrantPermission(session.GetUserRoles(), model.PermissionManageSystem.Id) {
return true
if session.IsUnrestricted() {
return true, false
}
if appErr == nil && a.isChannelArchivedAndHidden(channel) {
return false
return false, false
}
isMember = false
ids, err := a.Srv().Store().Channel().GetAllChannelMembersForUser(c, session.UserId, true, true)
var channelRoles []string
if err == nil {
if roles, ok := ids[channelID]; ok {
isMember = true
channelRoles = strings.Fields(roles)
if a.RolesGrantPermission(channelRoles, permission.Id) {
return true
return true, isMember
}
}
}
if appErr == nil && channel.TeamId != "" {
return a.SessionHasPermissionToTeam(session, channel.TeamId, permission)
return a.SessionHasPermissionToTeam(session, channel.TeamId, permission), isMember
}
return a.SessionHasPermissionTo(session, permission)
return a.SessionHasPermissionTo(session, permission), isMember
}
// SessionHasPermissionToChannels returns true only if user has access to all channels.
@@ -221,6 +231,21 @@ func (a *App) SessionHasPermissionToChannelByPost(session model.Session, postID
return a.SessionHasPermissionTo(session, permission)
}
func (a *App) SessionHasPermissionToReadPost(rctx request.CTX, session model.Session, postID string) (hasPErmission bool, isMember bool) {
if postID == "" {
return false, false
}
channel, err := a.Srv().Store().Channel().GetForPost(postID)
if err != nil {
// Original implementation (SessionHasPermissionToChannelByPost) still checks for
// general permissions even if the channel is not found, and some tests rely on this behavior.
return a.SessionHasPermissionTo(session, model.PermissionReadChannelContent), false
}
return a.SessionHasPermissionToReadChannel(rctx, session, channel)
}
func (a *App) SessionHasPermissionToCategory(c request.CTX, session model.Session, userID, teamID, categoryId string) bool {
if a.SessionHasPermissionTo(session, model.PermissionEditOtherUsers) {
return true
@@ -298,11 +323,21 @@ func (a *App) HasPermissionToTeam(c request.CTX, askingUserId string, teamID str
return a.HasPermissionTo(askingUserId, permission)
}
func (a *App) HasPermissionToChannel(c request.CTX, askingUserId string, channelID string, permission *model.Permission) bool {
// HasPermissionToChannel determines if the specified user has the given permission on the provided channel.
//
// Returns:
//
// (hasPermission, isMember)
//
// hasPermission: true if the user has the specified permission for the channel, otherwise false.
// isMember: used for auditing access without membership. True if the user is a member of the channel, otherwise false.
func (a *App) HasPermissionToChannel(c request.CTX, askingUserId string, channelID string, permission *model.Permission) (hasPermission bool, isMember bool) {
if channelID == "" || askingUserId == "" {
return false
return false, false
}
isMember = false
// We call GetAllChannelMembersForUser instead of just getting
// a single member from the DB, because it's cache backed
// and this is a very frequent call.
@@ -310,19 +345,20 @@ func (a *App) HasPermissionToChannel(c request.CTX, askingUserId string, channel
var channelRoles []string
if err == nil {
if roles, ok := ids[channelID]; ok {
isMember = true
channelRoles = strings.Fields(roles)
if a.RolesGrantPermission(channelRoles, permission.Id) {
return true
return true, isMember
}
}
}
channel, appErr := a.GetChannel(c, channelID)
if appErr == nil && channel.TeamId != "" {
return a.HasPermissionToTeam(c, askingUserId, channel.TeamId, permission)
return a.HasPermissionToTeam(c, askingUserId, channel.TeamId, permission), isMember
}
return a.HasPermissionTo(askingUserId, permission)
return a.HasPermissionTo(askingUserId, permission), isMember
}
func (a *App) HasPermissionToChannelByPost(c request.CTX, askingUserId string, postID string, permission *model.Permission) bool {
@@ -411,34 +447,53 @@ func (a *App) SessionHasPermissionToManageBot(rctx request.CTX, session model.Se
return nil
}
func (a *App) SessionHasPermissionToReadChannel(c request.CTX, session model.Session, channel *model.Channel) bool {
// SessionHasPermissionToReadChannel checks whether the given session has permission
// to read the specified channel.
//
// Returns:
//
// (hasPermission, isMember)
//
// hasPermission: true if the user has permission to read the channel, false otherwise
// isMember: used for auditing access without membership. True if the user is a member of the channel, false otherwise
func (a *App) SessionHasPermissionToReadChannel(c request.CTX, session model.Session, channel *model.Channel) (hasPermission bool, isMember bool) {
if session.IsUnrestricted() {
return true
return true, false
}
return a.HasPermissionToReadChannel(c, session.UserId, channel)
}
func (a *App) HasPermissionToReadChannel(c request.CTX, userID string, channel *model.Channel) bool {
// HasPermissionToReadChannel determines if the specified user has permission to read the given channel.
//
// Returns:
//
// (hasPermission, isMember)
//
// hasPermission: true if the user has permission to read the channel, false otherwise
// isMember: used for auditing access without membership. True if the user is a member of the channel, false otherwise
func (a *App) HasPermissionToReadChannel(c request.CTX, userID string, channel *model.Channel) (hasPermission bool, isMember bool) {
if a.isChannelArchivedAndHidden(channel) {
return false
return false, false
}
if a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionReadChannelContent) {
return true
if ok, member := a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionReadChannelContent); ok {
return true, member
}
if channel.Type == model.ChannelTypeOpen && !*a.Config().ComplianceSettings.Enable {
return a.HasPermissionToTeam(c, userID, channel.TeamId, model.PermissionReadPublicChannel)
return a.HasPermissionToTeam(c, userID, channel.TeamId, model.PermissionReadPublicChannel), false
}
return false
return false, false
}
func (a *App) HasPermissionToChannelMemberCount(c request.CTX, userID string, channel *model.Channel) bool {
if a.isChannelArchivedAndHidden(channel) {
return false
}
if a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionReadChannelContent) {
if ok, _ := a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionReadChannelContent); ok {
return true
}

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

@@ -238,7 +238,9 @@ func TestSessionHasPermissionToChannel(t *testing.T) {
}
t.Run("basic user can access basic channel", func(t *testing.T) {
assert.True(t, th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicChannel.Id, model.PermissionAddReaction))
ok, isMember := th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicChannel.Id, model.PermissionAddReaction)
assert.True(t, ok)
assert.True(t, isMember)
})
t.Run("basic user cannot access archived channel if setting is off", func(t *testing.T) {
@@ -247,7 +249,9 @@ func TestSessionHasPermissionToChannel(t *testing.T) {
})
err := th.App.DeleteChannel(th.Context, th.BasicChannel, th.SystemAdminUser.Id)
require.Nil(t, err)
assert.False(t, th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicChannel.Id, model.PermissionReadChannel))
ok, _ := th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicChannel.Id, model.PermissionReadChannel)
assert.False(t, ok)
})
t.Run("basic user can access archived channel if setting is on", func(t *testing.T) {
@@ -256,7 +260,20 @@ func TestSessionHasPermissionToChannel(t *testing.T) {
})
err := th.App.DeleteChannel(th.Context, th.BasicChannel, th.SystemAdminUser.Id)
require.Nil(t, err)
assert.True(t, th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicChannel.Id, model.PermissionReadChannel))
ok, isMember := th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicChannel.Id, model.PermissionReadChannel)
assert.True(t, ok)
assert.True(t, isMember)
})
t.Run("admin user can access channel if not a member", func(t *testing.T) {
adminSession := model.Session{
UserId: th.SystemAdminUser.Id,
Roles: model.SystemAdminRoleId,
}
ok, isMember := th.App.SessionHasPermissionToChannel(th.Context, adminSession, th.BasicChannel.Id, model.PermissionAddReaction)
assert.True(t, ok)
assert.False(t, isMember)
})
t.Run("does not panic if fetching channel causes an error", func(t *testing.T) {
@@ -287,7 +304,9 @@ func TestSessionHasPermissionToChannel(t *testing.T) {
// If there's an error returned from the GetChannel call the code should continue to cascade and since there
// are no session level permissions in this test case, the permission should be denied.
assert.False(t, th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicUser.Id, model.PermissionAddReaction))
ok, isMember := th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicUser.Id, model.PermissionAddReaction)
assert.False(t, ok)
assert.False(t, isMember)
// MM-63624, check with TeamSettings.ExperimentalViewArchivedChannels off
th.App.Srv().SetStore(mainHelper.GetStore())
@@ -296,7 +315,9 @@ func TestSessionHasPermissionToChannel(t *testing.T) {
})
th.App.Srv().SetStore(&mockStore)
assert.False(t, th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicUser.Id, model.PermissionAddReaction))
ok, isMember = th.App.SessionHasPermissionToChannel(th.Context, session, th.BasicUser.Id, model.PermissionAddReaction)
assert.False(t, ok)
assert.False(t, isMember)
})
}
@@ -796,6 +817,7 @@ func TestHasPermissionToReadChannel(t *testing.T) {
channelIsOpen bool
canReadPublicChannel bool
expected bool
isAdmin bool
}{
{
name: "Cannot read archived channels if the config doesn't allow it",
@@ -857,10 +879,25 @@ func TestHasPermissionToReadChannel(t *testing.T) {
canReadPublicChannel: true,
expected: true,
},
{
name: "Can read private channels if it is a sysadmin and it is not member of the channel",
configComplianceEnabled: false,
channelDeleted: false,
canReadChannel: false,
channelIsOpen: false,
canReadPublicChannel: false,
expected: true,
isAdmin: true,
},
}
for _, tc := range ttcc {
t.Run(tc.name, func(t *testing.T) {
user := th.BasicUser2
if tc.isAdmin {
user = th.SystemAdminUser
}
th.App.UpdateConfig(func(cfg *model.Config) {
configViewArchived := tc.configViewArchived
configComplianceEnabled := tc.configComplianceEnabled
@@ -880,7 +917,7 @@ func TestHasPermissionToReadChannel(t *testing.T) {
channel = th.CreatePrivateChannel(th.Context, team)
}
if tc.canReadChannel {
_, err := th.App.AddUserToChannel(th.Context, th.BasicUser2, channel, false)
_, err := th.App.AddUserToChannel(th.Context, user, channel, false)
require.Nil(t, err)
}
@@ -891,8 +928,13 @@ func TestHasPermissionToReadChannel(t *testing.T) {
require.Nil(t, err)
}
result := th.App.HasPermissionToReadChannel(th.Context, th.BasicUser2.Id, channel)
result, isMember := th.App.HasPermissionToReadChannel(th.Context, user.Id, channel)
require.Equal(t, tc.expected, result)
if result {
require.Equal(t, tc.canReadChannel, isMember)
} else {
require.Equal(t, false, isMember)
}
})
}
}
@@ -1006,3 +1048,226 @@ func TestHasPermissionToChannelByPost(t *testing.T) {
require.Equal(t, true, th.App.HasPermissionToChannelByPost(th.Context, th.SystemAdminUser.Id, post.Id, model.PermissionReadChannel))
})
}
func TestHasPermissionToChannel(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
channel := th.CreateChannel(th.Context, th.BasicTeam)
_, appErr := th.App.AddUserToChannel(th.Context, th.BasicUser, channel, false)
assert.Nil(t, appErr)
archivedChannel := th.CreateChannel(th.Context, th.BasicTeam)
_, appErr = th.App.AddUserToChannel(th.Context, th.BasicUser, archivedChannel, false)
assert.Nil(t, appErr)
appErr = th.App.DeleteChannel(th.Context, archivedChannel, th.SystemAdminUser.Id)
assert.Nil(t, appErr)
t.Run("read channel", func(t *testing.T) {
ok, isMember := th.App.HasPermissionToChannel(th.Context, th.BasicUser.Id, channel.Id, model.PermissionReadChannel)
assert.True(t, ok)
assert.True(t, isMember)
ok, isMember = th.App.HasPermissionToChannel(th.Context, th.BasicUser2.Id, channel.Id, model.PermissionReadChannel)
assert.False(t, ok)
assert.False(t, isMember)
})
t.Run("read archived channel", func(t *testing.T) {
ok, isMember := th.App.HasPermissionToChannel(th.Context, th.BasicUser.Id, archivedChannel.Id, model.PermissionReadChannel)
assert.True(t, ok)
assert.True(t, isMember)
ok, isMember = th.App.HasPermissionToChannel(th.Context, th.BasicUser2.Id, archivedChannel.Id, model.PermissionReadChannel)
assert.False(t, ok)
assert.False(t, isMember)
})
t.Run("read public channel", func(t *testing.T) {
ok, isMember := th.App.HasPermissionToChannel(th.Context, th.BasicUser.Id, channel.Id, model.PermissionReadPublicChannel)
assert.True(t, ok)
assert.True(t, isMember)
ok, isMember = th.App.HasPermissionToChannel(th.Context, th.BasicUser2.Id, channel.Id, model.PermissionReadPublicChannel)
assert.True(t, ok)
assert.False(t, isMember)
})
t.Run("read channel - user is admin", func(t *testing.T) {
ok, isMember := th.App.HasPermissionToChannel(th.Context, th.SystemAdminUser.Id, channel.Id, model.PermissionReadChannel)
assert.True(t, ok)
assert.False(t, isMember)
})
}
func TestSessionHasPermissionToReadChannel(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
channel := th.CreateChannel(th.Context, th.BasicTeam)
_, appErr := th.App.AddUserToChannel(th.Context, th.BasicUser, channel, false)
assert.Nil(t, appErr)
archivedChannel := th.CreateChannel(th.Context, th.BasicTeam)
_, appErr = th.App.AddUserToChannel(th.Context, th.BasicUser, archivedChannel, false)
assert.Nil(t, appErr)
appErr = th.App.DeleteChannel(th.Context, archivedChannel, th.SystemAdminUser.Id)
assert.Nil(t, appErr)
t.Run("basic user can read channel", func(t *testing.T) {
session := model.Session{
UserId: th.BasicUser.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadChannel(th.Context, session, channel)
assert.True(t, ok)
assert.True(t, isMember)
})
t.Run("basic user cannot read channel if not a member and not public", func(t *testing.T) {
privateChannel := th.CreatePrivateChannel(th.Context, th.BasicTeam)
session := model.Session{
UserId: th.BasicUser2.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadChannel(th.Context, session, privateChannel)
assert.False(t, ok)
assert.False(t, isMember)
})
t.Run("basic user can read archived channel if member", func(t *testing.T) {
session := model.Session{
UserId: th.BasicUser.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadChannel(th.Context, session, archivedChannel)
assert.True(t, ok)
assert.True(t, isMember)
})
t.Run("non-member can read public channel", func(t *testing.T) {
session := model.Session{
UserId: th.BasicUser2.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadChannel(th.Context, session, channel)
assert.True(t, ok)
assert.False(t, isMember)
})
t.Run("admin can read any channel", func(t *testing.T) {
session := model.Session{
UserId: th.SystemAdminUser.Id,
Roles: model.SystemAdminRoleId,
}
ok, isMember := th.App.SessionHasPermissionToReadChannel(th.Context, session, channel)
assert.True(t, ok)
assert.False(t, isMember)
})
}
func TestSessionHasPermissionToReadPost(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
// Create a post in a public channel, ensure basic user can read it.
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "hello world",
}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, err)
t.Run("basic user can read their post", func(t *testing.T) {
session := model.Session{
UserId: th.BasicUser.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, post.Id)
assert.True(t, ok)
assert.True(t, isMember)
})
t.Run("other member in channel can read post", func(t *testing.T) {
// Add BasicUser2 to channel
_, aerr := th.App.AddUserToChannel(th.Context, th.BasicUser2, th.BasicChannel, false)
require.Nil(t, aerr)
session := model.Session{
UserId: th.BasicUser2.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, post.Id)
assert.True(t, ok)
assert.True(t, isMember)
})
t.Run("non-member can read post in public channel", func(t *testing.T) {
// Remove BasicUser2 from channel
aerr := th.App.removeUserFromChannel(th.Context, th.BasicUser2.Id, th.SystemAdminUser.Id, th.BasicChannel)
assert.Nil(t, aerr)
session := model.Session{
UserId: th.BasicUser2.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, post.Id)
assert.True(t, ok)
assert.False(t, isMember)
})
t.Run("non-member cannot read post in private channel", func(t *testing.T) {
privateChan := th.CreatePrivateChannel(th.Context, th.BasicTeam)
privatePost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: privateChan.Id,
Message: "private message",
}, privateChan, model.CreatePostFlags{})
require.Nil(t, err)
session := model.Session{
UserId: th.BasicUser2.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, privatePost.Id)
assert.False(t, ok)
assert.False(t, isMember)
})
t.Run("admin can read post even if not a channel member", func(t *testing.T) {
privateChan := th.CreatePrivateChannel(th.Context, th.BasicTeam)
privatePost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: privateChan.Id,
Message: "private admin",
}, privateChan, model.CreatePostFlags{})
require.Nil(t, err)
session := model.Session{
UserId: th.SystemAdminUser.Id,
Roles: model.SystemAdminRoleId,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, privatePost.Id)
assert.True(t, ok)
assert.False(t, isMember)
})
t.Run("returns false for empty postID", func(t *testing.T) {
session := model.Session{
UserId: th.BasicUser.Id,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, "")
assert.False(t, ok)
assert.False(t, isMember)
})
t.Run("returns permission based on system level if postID is missing", func(t *testing.T) {
// To simulate a missing post, use a postID that doesn't exist
session := model.Session{
UserId: th.SystemAdminUser.Id,
Roles: model.SystemAdminRoleId,
}
ok, isMember := th.App.SessionHasPermissionToReadPost(th.Context, session, model.NewId())
assert.True(t, ok)
assert.False(t, isMember)
// Basic user, should be false
session = model.Session{
UserId: th.BasicUser2.Id,
}
ok, isMember = th.App.SessionHasPermissionToReadPost(th.Context, session, model.NewId())
assert.False(t, ok)
assert.False(t, isMember)
})
}

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

@@ -77,7 +77,7 @@ func (a *App) SendAutoResponse(rctx request.CTX, channel *model.Channel, receive
UserId: receiver.Id,
}
if _, err := a.CreatePost(rctx, autoResponderPost, channel, model.CreatePostFlags{}); err != nil {
if _, _, err := a.CreatePost(rctx, autoResponderPost, channel, model.CreatePostFlags{}); err != nil {
return false, err
}

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

@@ -110,7 +110,7 @@ func TestSendAutoResponseIfNecessary(t *testing.T) {
channel := th.CreateDmChannel(receiver)
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: NewTestId(),
UserId: th.BasicUser.Id,
@@ -141,7 +141,7 @@ func TestSendAutoResponseIfNecessary(t *testing.T) {
channel := th.CreateDmChannel(receiver)
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: NewTestId(),
UserId: th.BasicUser.Id,
@@ -159,7 +159,7 @@ func TestSendAutoResponseIfNecessary(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: th.BasicChannel.Id,
Message: NewTestId(),
UserId: th.BasicUser.Id,
@@ -200,7 +200,7 @@ func TestSendAutoResponseIfNecessary(t *testing.T) {
botUser, err := th.App.GetUser(bot.UserId)
assert.Nil(t, err)
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: NewTestId(),
UserId: botUser.Id,
@@ -236,7 +236,7 @@ func TestSendAutoResponseIfNecessary(t *testing.T) {
// which needs to be cleaned up.
require.NoError(t, th.GetSqlStore().Post().PermanentDeleteByUser(th.Context, th.BasicUser.Id))
savedPost, err := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
ChannelId: channel.Id,
Message: patch.NotifyProps["auto_responder_message"],
UserId: receiver.Id,
@@ -274,7 +274,7 @@ func TestSendAutoResponseSuccess(t *testing.T) {
userUpdated1, err := th.App.PatchUser(th.Context, user.Id, patch, true)
require.Nil(t, err)
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: th.BasicChannel.Id,
Message: "zz" + model.NewId() + "a",
UserId: th.BasicUser.Id,
@@ -319,7 +319,7 @@ func TestSendAutoResponseSuccessOnThread(t *testing.T) {
userUpdated1, err := th.App.PatchUser(th.Context, user.Id, patch, true)
require.Nil(t, err)
parentPost, _ := th.App.CreatePost(th.Context, &model.Post{
parentPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: th.BasicChannel.Id,
Message: "zz" + model.NewId() + "a",
UserId: th.BasicUser.Id,
@@ -327,7 +327,7 @@ func TestSendAutoResponseSuccessOnThread(t *testing.T) {
th.BasicChannel,
model.CreatePostFlags{SetOnline: true})
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: th.BasicChannel.Id,
Message: "zz" + model.NewId() + "a",
UserId: th.BasicUser.Id,
@@ -373,7 +373,7 @@ func TestSendAutoResponseFailure(t *testing.T) {
userUpdated1, err := th.App.PatchUser(th.Context, user.Id, patch, true)
require.Nil(t, err)
savedPost, _ := th.App.CreatePost(th.Context, &model.Post{
savedPost, _, _ := th.App.CreatePost(th.Context, &model.Post{
ChannelId: th.BasicChannel.Id,
Message: "zz" + model.NewId() + "a",
UserId: th.BasicUser.Id,

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

@@ -157,7 +157,7 @@ func (a *App) CreateBot(rctx request.CTX, bot *model.Bot) (*model.Bot, *model.Ap
Message: T("api.bot.teams_channels.add_message_mobile"),
}
if _, err := a.CreatePostAsUser(rctx, botAddPost, rctx.Session().Id, true); err != nil {
if _, _, err := a.CreatePostAsUser(rctx, botAddPost, rctx.Session().Id, true); err != nil {
return nil, err
}
}
@@ -565,7 +565,7 @@ func (a *App) notifySysadminsBotOwnerDeactivated(rctx request.CTX, userID string
Type: model.PostTypeSystemGeneric,
}
_, appErr = a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true})
if appErr != nil {
return appErr
}

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

@@ -847,7 +847,7 @@ func (a *App) postChannelPrivacyMessage(c request.CTX, user *model.User, channel
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postChannelPrivacyMessage", "api.channel.post_channel_privacy_message.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -902,7 +902,7 @@ func (a *App) RestoreChannel(c request.CTX, channel *model.Channel, userID strin
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
c.Logger().Warn("Failed to post unarchive message", mlog.Err(err))
}
} else {
@@ -923,7 +923,7 @@ func (a *App) RestoreChannel(c request.CTX, channel *model.Channel, userID strin
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
c.Logger().Error("Failed to post unarchive message", mlog.Err(err))
}
})
@@ -1560,7 +1560,7 @@ func (a *App) DeleteChannel(c request.CTX, channel *model.Channel, userID string
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
c.Logger().Warn("Failed to post archive message", mlog.Err(err))
}
} else {
@@ -1578,7 +1578,7 @@ func (a *App) DeleteChannel(c request.CTX, channel *model.Channel, userID string
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
c.Logger().Warn("Failed to post archive message", mlog.Err(err))
}
}
@@ -1900,7 +1900,7 @@ func (a *App) PostUpdateChannelHeaderMessage(c request.CTX, userID string, chann
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("", "api.channel.post_update_channel_header_message_and_forget.post.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -1933,7 +1933,7 @@ func (a *App) PostUpdateChannelPurposeMessage(c request.CTX, userID string, chan
"new_purpose": newChannelPurpose,
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("", "app.channel.post_update_channel_purpose_message.post.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -1960,7 +1960,7 @@ func (a *App) PostUpdateChannelDisplayNameMessage(c request.CTX, userID string,
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("PostUpdateChannelDisplayNameMessage", "api.channel.post_update_channel_displayname_message_and_forget.create_post.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2477,7 +2477,7 @@ func (a *App) postJoinChannelMessage(c request.CTX, user *model.User, channel *m
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postJoinChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2495,7 +2495,7 @@ func (a *App) postJoinTeamMessage(c request.CTX, user *model.User, channel *mode
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postJoinTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2578,7 +2578,7 @@ func (a *App) postLeaveChannelMessage(c request.CTX, user *model.User, channel *
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postLeaveChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2607,7 +2607,7 @@ func (a *App) PostAddToChannelMessage(c request.CTX, user *model.User, addedUser
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postAddToChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2629,7 +2629,7 @@ func (a *App) postAddToTeamMessage(c request.CTX, user *model.User, addedUser *m
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postAddToTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2661,7 +2661,7 @@ func (a *App) postRemoveFromChannelMessage(c request.CTX, removerUserId string,
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -2894,9 +2894,16 @@ func (a *App) ValidateUserPermissionsOnChannels(c request.CTX, userId string, ch
continue
}
if channel.Type == model.ChannelTypePrivate && a.HasPermissionToChannel(c, userId, channelId, model.PermissionManagePrivateChannelMembers) {
allowedChannelIds = append(allowedChannelIds, channelId)
} else if channel.Type == model.ChannelTypeOpen && a.HasPermissionToChannel(c, userId, channelId, model.PermissionManagePublicChannelMembers) {
allowedPrivate := false
if channel.Type == model.ChannelTypePrivate {
allowedPrivate, _ = a.HasPermissionToChannel(c, userId, channelId, model.PermissionManagePrivateChannelMembers)
}
allowedPublic := false
if channel.Type == model.ChannelTypeOpen {
allowedPublic, _ = a.HasPermissionToChannel(c, userId, channelId, model.PermissionManagePublicChannelMembers)
}
if allowedPrivate || allowedPublic {
allowedChannelIds = append(allowedChannelIds, channelId)
} else {
c.Logger().Info("Invite users to team - no permission to add members to that channel. UserId: " + userId + " ChannelId: " + channelId)
@@ -3453,7 +3460,7 @@ func (a *App) postChannelMoveMessage(c request.CTX, user *model.User, channel *m
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postChannelMoveMessage", "api.team.move_channel.post.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -3967,7 +3974,7 @@ func (a *App) postMessageForConvertGroupMessageToChannel(c request.CTX, channelI
return appErr
}
if _, appErr := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); appErr != nil {
if _, _, appErr := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); appErr != nil {
c.Logger().Error("Failed to create post for notifying about GM converted to private channel", mlog.Err(appErr))
return model.NewAppError(

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

@@ -269,7 +269,7 @@ func TestMoveChannel(t *testing.T) {
ChannelId: channel.Id,
Message: "test",
}
post, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
post, _, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
require.Nil(t, appErr)
// Post a reply to the thread
@@ -279,7 +279,7 @@ func TestMoveChannel(t *testing.T) {
RootId: post.Id,
Message: "reply",
}
_, appErr = th.App.CreatePost(th.Context, reply, channel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, reply, channel, model.CreatePostFlags{})
require.Nil(t, appErr)
// Check that the thread count before move
@@ -772,7 +772,7 @@ func TestUsersAndPostsCreateActivityInChannel(t *testing.T) {
Message: "root post",
UserId: th.BasicUser.Id,
}
_, err = th.App.CreatePost(th.Context, post, channel1, model.CreatePostFlags{})
_, _, err = th.App.CreatePost(th.Context, post, channel1, model.CreatePostFlags{})
require.Nil(t, err, "Failed to create post.")
_, err = th.App.AddUserToChannel(th.Context, user, channel2, false)
@@ -799,7 +799,7 @@ func TestUsersAndPostsCreateActivityInChannel(t *testing.T) {
}
err = th.App.RemoveUserFromChannel(th.Context, user4.Id, user4.Id, channel4)
require.Nil(t, err, "Failed to create post.")
_, err = th.App.CreatePost(th.Context, post2, channel5, model.CreatePostFlags{})
_, _, err = th.App.CreatePost(th.Context, post2, channel5, model.CreatePostFlags{})
require.Nil(t, err, "Failed to create post.")
_, err = th.App.AddUserToChannel(th.Context, user, channel6, false)
require.Nil(t, err, "Failed to add user to channel.")
@@ -845,7 +845,7 @@ func TestLeaveDefaultChannel(t *testing.T) {
Message: "root post",
UserId: th.BasicUser.Id,
}
rpost, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
rpost, _, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
reply := &model.Post{
@@ -854,7 +854,7 @@ func TestLeaveDefaultChannel(t *testing.T) {
UserId: th.BasicUser.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, reply, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, reply, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
threads, appErr := th.App.GetThreadsForUser(th.BasicUser.Id, townSquare.TeamId, model.GetUserThreadsOpts{})
@@ -884,7 +884,7 @@ func TestLeaveChannel(t *testing.T) {
UserId: th.BasicUser.Id,
}
rpost, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
rpost, _, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
reply := &model.Post{
@@ -893,7 +893,7 @@ func TestLeaveChannel(t *testing.T) {
UserId: th.BasicUser.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, reply, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, reply, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
return rpost
@@ -1805,7 +1805,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
_, appErr := th.App.AddUserToChannel(th.Context, u2, c2, false)
require.Nil(t, appErr)
p4, appErr := th.App.CreatePost(th.Context, &model.Post{
p4, _, appErr := th.App.CreatePost(th.Context, &model.Post{
UserId: u2.Id,
ChannelId: c2.Id,
Message: "@" + u1.Username,
@@ -1813,7 +1813,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
require.Nil(t, appErr)
th.CreatePost(c2)
_, appErr = th.App.CreatePost(th.Context, &model.Post{
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{
UserId: u2.Id,
ChannelId: c2.Id,
RootId: p4.Id,
@@ -1841,7 +1841,7 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
th.CreatePost(dc)
th.CreatePost(dc)
_, appErr := th.App.CreatePost(th.Context, &model.Post{ChannelId: dc.Id, UserId: th.BasicUser.Id, Message: "testReply", RootId: dm1.Id}, dc, model.CreatePostFlags{})
_, _, appErr := th.App.CreatePost(th.Context, &model.Post{ChannelId: dc.Id, UserId: th.BasicUser.Id, Message: "testReply", RootId: dm1.Id}, dc, model.CreatePostFlags{})
assert.Nil(t, appErr)
response, appErr := th.App.MarkChannelAsUnreadFromPost(th.Context, dm1.Id, u2.Id, true)
@@ -2491,11 +2491,13 @@ func TestPatchChannelModerationsForChannel(t *testing.T) {
_, appErr := th.App.PatchChannelModerationsForChannel(th.Context, channel.DeepCopy(), addCreatePosts)
require.Nil(t, appErr)
require.True(t, th.App.SessionHasPermissionToChannel(th.Context, mockSession, channel.Id, model.PermissionCreatePost))
ok, _ := th.App.SessionHasPermissionToChannel(th.Context, mockSession, channel.Id, model.PermissionCreatePost)
require.True(t, ok)
_, appErr = th.App.PatchChannelModerationsForChannel(th.Context, channel.DeepCopy(), removeCreatePosts)
require.Nil(t, appErr)
require.False(t, th.App.SessionHasPermissionToChannel(th.Context, mockSession, channel.Id, model.PermissionCreatePost))
ok, _ = th.App.SessionHasPermissionToChannel(th.Context, mockSession, channel.Id, model.PermissionCreatePost)
require.False(t, ok)
})
}
@@ -2609,7 +2611,7 @@ func TestViewChannelCollapsedThreadsTurnedOff(t *testing.T) {
Message: "root post @" + u1.Username,
UserId: u2.Id,
}
rpost1, appErr := th.App.CreatePost(th.Context, post1, c1, model.CreatePostFlags{SetOnline: true})
rpost1, _, appErr := th.App.CreatePost(th.Context, post1, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// mention the user in a reply post
@@ -2619,7 +2621,7 @@ func TestViewChannelCollapsedThreadsTurnedOff(t *testing.T) {
UserId: u2.Id,
RootId: rpost1.Id,
}
_, appErr = th.App.CreatePost(th.Context, post2, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, post2, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// Check we have unread mention in the thread
@@ -2686,19 +2688,19 @@ func TestMarkChannelAsUnreadFromPostCollapsedThreadsTurnedOff(t *testing.T) {
// user1: a root post
// user2: Another root mention @u1
user1Mention := " @" + th.BasicUser.Username
rootPost1, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "first root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
rootPost1, _, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "first root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hello"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hello"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
replyPost1, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
replyPost1, _, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another reply"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another reply"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost1.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "a root post"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "a root post"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "another root mention" + user1Mention}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
t.Run("Mark reply post as unread", func(t *testing.T) {
@@ -2756,17 +2758,17 @@ func TestMarkUnreadCRTOffUpdatesThreads(t *testing.T) {
appErr := th.App.PermanentDeleteUser(th.Context, user3)
require.Nil(t, appErr)
}()
rootPost, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "root post"}, th.BasicChannel, model.CreatePostFlags{})
rootPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "root post"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
r1, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "reply 1"}, th.BasicChannel, model.CreatePostFlags{})
r1, _, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "reply 1"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "reply 2 @" + user3.Username}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "reply 2 @" + user3.Username}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
_, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "reply 3"}, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "reply 3"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
editedPost := r1.Clone()
editedPost.Message += " edited"
_, appErr = th.App.UpdatePost(th.Context, editedPost, &model.UpdatePostOptions{SafeUpdate: false})
_, _, appErr = th.App.UpdatePost(th.Context, editedPost, &model.UpdatePostOptions{SafeUpdate: false})
require.Nil(t, appErr)
th.LinkUserToTeam(user3, th.BasicTeam)
@@ -3309,7 +3311,7 @@ func TestGetChannelFileCount(t *testing.T) {
Message: "This is a test post",
UserId: th.BasicUser.Id,
}
post, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
post, _, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
require.Nil(t, appErr)
fileInfo1 := &model.FileInfo{

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

@@ -70,7 +70,12 @@ func (a *App) CreateCommandPost(c request.CTX, post *model.Post, teamID string,
}
if response.ResponseType == model.CommandResponseTypeInChannel {
return a.CreatePostMissingChannel(c, post, true, true)
// The post is only used for tests, so even if there are membership issues, we won't send the post to the client.
createdPost, _, appErr := a.CreatePostMissingChannel(c, post, true, true)
if appErr != nil {
return nil, appErr
}
return createdPost, nil
}
if (response.ResponseType == "" || response.ResponseType == model.CommandResponseTypeEphemeral) && (response.Text != "" || response.Attachments != nil) {

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

@@ -556,7 +556,7 @@ func TestExportDMandGMPost(t *testing.T) {
Message: "aa" + model.NewId() + "a",
UserId: th1.BasicUser.Id,
}
_, appErr := th1.App.CreatePost(th1.Context, p1, dmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr := th1.App.CreatePost(th1.Context, p1, dmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
p2 := &model.Post{
@@ -564,7 +564,7 @@ func TestExportDMandGMPost(t *testing.T) {
Message: "bb" + model.NewId() + "a",
UserId: th1.BasicUser.Id,
}
_, appErr = th1.App.CreatePost(th1.Context, p2, dmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th1.App.CreatePost(th1.Context, p2, dmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// GM posts
@@ -573,7 +573,7 @@ func TestExportDMandGMPost(t *testing.T) {
Message: "cc" + model.NewId() + "a",
UserId: th1.BasicUser.Id,
}
_, appErr = th1.App.CreatePost(th1.Context, p3, gmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th1.App.CreatePost(th1.Context, p3, gmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
p4 := &model.Post{
@@ -581,7 +581,7 @@ func TestExportDMandGMPost(t *testing.T) {
Message: "dd" + model.NewId() + "a",
UserId: th1.BasicUser.Id,
}
_, appErr = th1.App.CreatePost(th1.Context, p4, gmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th1.App.CreatePost(th1.Context, p4, gmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
posts, err := th1.App.Srv().Store().Post().GetDirectPostParentsForExportAfter(1000, "0000000", false)
@@ -646,7 +646,7 @@ func TestExportPostWithProps(t *testing.T) {
},
UserId: th1.BasicUser.Id,
}
_, appErr := th1.App.CreatePost(th1.Context, p1, dmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr := th1.App.CreatePost(th1.Context, p1, dmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
p2 := &model.Post{
@@ -657,7 +657,7 @@ func TestExportPostWithProps(t *testing.T) {
},
UserId: th1.BasicUser.Id,
}
_, appErr = th1.App.CreatePost(th1.Context, p2, gmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th1.App.CreatePost(th1.Context, p2, gmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
posts, err := th1.App.Srv().Store().Post().GetDirectPostParentsForExportAfter(1000, "0000000", false)
@@ -1079,7 +1079,7 @@ func TestBuildPostReplies(t *testing.T) {
fileIDs = append(fileIDs, info.Id)
}
post, err := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, RootId: rootID, FileIds: fileIDs}, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, RootId: rootID, FileIds: fileIDs}, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
return post
@@ -1640,7 +1640,7 @@ func TestExportDeactivatedUserDMs(t *testing.T) {
Message: initialMessage,
UserId: th1.BasicUser.Id,
}
initialPostCreated, appErr := th1.App.CreatePost(th1.Context, initialPost, dmChannel, model.CreatePostFlags{SetOnline: true})
initialPostCreated, _, appErr := th1.App.CreatePost(th1.Context, initialPost, dmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// 2. Have user2 reply with TWO types of replies:
@@ -1653,7 +1653,7 @@ func TestExportDeactivatedUserDMs(t *testing.T) {
UserId: user2.Id,
RootId: initialPostCreated.Id, // This makes it a threaded reply
}
_, appErr = th1.App.CreatePost(th1.Context, threadedReply, dmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th1.App.CreatePost(th1.Context, threadedReply, dmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// 2b. User2 sends a standalone reply (NOT in a thread)
@@ -1664,7 +1664,7 @@ func TestExportDeactivatedUserDMs(t *testing.T) {
UserId: user2.Id,
// No RootId, making it a standalone message, not a thread reply
}
_, appErr = th1.App.CreatePost(th1.Context, nonThreadedReply, dmChannel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th1.App.CreatePost(th1.Context, nonThreadedReply, dmChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// 3. Now deactivate user2

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

@@ -1460,12 +1460,12 @@ func populateZipfile(w *zip.Writer, fileDatas []model.FileData) error {
return nil
}
func (a *App) SearchFilesInTeamForUser(c request.CTX, terms string, userId string, teamId string, isOrSearch bool, includeDeletedChannels bool, timeZoneOffset int, page, perPage int) (*model.FileInfoList, *model.AppError) {
func (a *App) SearchFilesInTeamForUser(c request.CTX, terms string, userId string, teamId string, isOrSearch bool, includeDeletedChannels bool, timeZoneOffset int, page, perPage int) (*model.FileInfoList, bool, *model.AppError) {
paramsList := model.ParseSearchParams(strings.TrimSpace(terms), timeZoneOffset)
includeDeleted := includeDeletedChannels && *a.Config().TeamSettings.ExperimentalViewArchivedChannels
if !*a.Config().ServiceSettings.EnableFileSearch {
return nil, model.NewAppError("SearchFilesInTeamForUser", "store.sql_file_info.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v", teamId, userId), http.StatusNotImplemented)
return nil, false, model.NewAppError("SearchFilesInTeamForUser", "store.sql_file_info.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v", teamId, userId), http.StatusNotImplemented)
}
finalParamsList := []*model.SearchParams{}
@@ -1489,7 +1489,7 @@ func (a *App) SearchFilesInTeamForUser(c request.CTX, terms string, userId strin
// If the processed search params are empty, return empty search results.
if len(finalParamsList) == 0 {
return model.NewFileInfoList(), nil
return model.NewFileInfoList(), true, nil
}
fileInfoSearchResults, nErr := a.Srv().Store().FileInfo().Search(c, finalParamsList, userId, teamId, page, perPage)
@@ -1497,26 +1497,27 @@ func (a *App) SearchFilesInTeamForUser(c request.CTX, terms string, userId strin
var appErr *model.AppError
switch {
case errors.As(nErr, &appErr):
return nil, appErr
return nil, false, appErr
default:
return nil, model.NewAppError("SearchFilesInTeamForUser", "app.post.search.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
return nil, false, model.NewAppError("SearchFilesInTeamForUser", "app.post.search.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
if appErr := a.filterInaccessibleFiles(fileInfoSearchResults, filterFileOptions{assumeSortedCreatedAt: true}); appErr != nil {
return nil, appErr
return nil, false, appErr
}
if appErr := a.FilterFilesByChannelPermissions(c, fileInfoSearchResults, userId); appErr != nil {
return nil, appErr
allFilesHaveMembership, appErr := a.FilterFilesByChannelPermissions(c, fileInfoSearchResults, userId)
if appErr != nil {
return nil, false, appErr
}
return fileInfoSearchResults, nil
return fileInfoSearchResults, allFilesHaveMembership, nil
}
func (a *App) FilterFilesByChannelPermissions(rctx request.CTX, fileList *model.FileInfoList, userID string) *model.AppError {
func (a *App) FilterFilesByChannelPermissions(rctx request.CTX, fileList *model.FileInfoList, userID string) (bool, *model.AppError) {
if fileList == nil || fileList.FileInfos == nil || len(fileList.FileInfos) == 0 {
return nil
return true, nil // On an empty file list, we consider all files as having membership
}
channels := make(map[string]*model.Channel)
@@ -1530,7 +1531,7 @@ func (a *App) FilterFilesByChannelPermissions(rctx request.CTX, fileList *model.
channelIDs := slices.Collect(maps.Keys(channels))
channelList, err := a.GetChannels(rctx, channelIDs)
if err != nil && err.StatusCode != http.StatusNotFound {
return err
return false, err
}
for _, channel := range channelList {
channels[channel.Id] = channel
@@ -1540,6 +1541,7 @@ func (a *App) FilterFilesByChannelPermissions(rctx request.CTX, fileList *model.
channelReadPermission := make(map[string]bool)
filteredFiles := make(map[string]*model.FileInfo)
filteredOrder := []string{}
allFilesHaveMembership := true
for _, fileID := range fileList.Order {
fileInfo, ok := fileList.FileInfos[fileID]
@@ -1550,10 +1552,14 @@ func (a *App) FilterFilesByChannelPermissions(rctx request.CTX, fileList *model.
if _, ok := channelReadPermission[fileInfo.ChannelId]; !ok {
channel := channels[fileInfo.ChannelId]
allowed := false
isMember := true
if channel != nil {
allowed = a.HasPermissionToReadChannel(rctx, userID, channel)
allowed, isMember = a.HasPermissionToReadChannel(rctx, userID, channel)
}
channelReadPermission[fileInfo.ChannelId] = allowed
if allowed {
allFilesHaveMembership = allFilesHaveMembership && isMember
}
}
if channelReadPermission[fileInfo.ChannelId] {
@@ -1565,7 +1571,7 @@ func (a *App) FilterFilesByChannelPermissions(rctx request.CTX, fileList *model.
fileList.FileInfos = filteredFiles
fileList.Order = filteredOrder
return nil
return allFilesHaveMembership, nil
}
func (a *App) ExtractContentFromFileInfo(rctx request.CTX, fileInfo *model.FileInfo) error {

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

@@ -299,13 +299,13 @@ func TestMigrateFilenamesToFileInfos(t *testing.T) {
fpath := fmt.Sprintf("/teams/%v/channels/%v/users/%v/%v/test.png", th.BasicTeam.Id, th.BasicChannel.Id, th.BasicUser.Id, fileID)
_, err := th.App.WriteFile(file, fpath)
require.Nil(t, err)
rpost, err := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, Filenames: []string{fmt.Sprintf("/%v/%v/%v/test.png", th.BasicChannel.Id, th.BasicUser.Id, fileID)}}, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
rpost, _, err := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, Filenames: []string{fmt.Sprintf("/%v/%v/%v/test.png", th.BasicChannel.Id, th.BasicUser.Id, fileID)}}, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
infos = th.App.MigrateFilenamesToFileInfos(th.Context, rpost)
assert.Equal(t, 1, len(infos))
rpost, err = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, Filenames: []string{fmt.Sprintf("/%v/%v/%v/../../test.png", th.BasicChannel.Id, th.BasicUser.Id, fileID)}}, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
rpost, _, err = th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser.Id, ChannelId: th.BasicChannel.Id, Filenames: []string{fmt.Sprintf("/%v/%v/%v/../../test.png", th.BasicChannel.Id, th.BasicUser.Id, fileID)}}, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
infos = th.App.MigrateFilenamesToFileInfos(th.Context, rpost)
@@ -482,7 +482,7 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
page := 0
results, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
results, allFilesHaveMembership, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
require.Nil(t, err)
require.NotNil(t, results)
@@ -495,6 +495,7 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
fileInfos[1].Id,
fileInfos[0].Id,
}, results.Order)
require.True(t, allFilesHaveMembership)
})
t.Run("should not return later pages of fileInfos from database", func(t *testing.T) {
@@ -503,11 +504,12 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
page := 1
results, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
results, allFilesHaveMembership, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
require.Nil(t, err)
require.NotNil(t, results)
assert.Equal(t, []string{}, results.Order)
require.True(t, allFilesHaveMembership)
})
t.Run("should return first page of fileInfos from ElasticSearch", func(t *testing.T) {
@@ -533,11 +535,12 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
th.App.Srv().Platform().SearchEngine.ElasticsearchEngine = nil
}()
results, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
results, allFilesHaveMembership, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
require.Nil(t, err)
require.NotNil(t, results)
assert.Equal(t, resultsPage, results.Order)
require.True(t, allFilesHaveMembership)
es.AssertExpectations(t)
})
@@ -561,11 +564,12 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
th.App.Srv().Platform().SearchEngine.ElasticsearchEngine = nil
}()
results, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
results, allFilesHaveMembership, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
require.Nil(t, err)
require.NotNil(t, results)
assert.Equal(t, resultsPage, results.Order)
require.True(t, allFilesHaveMembership)
es.AssertExpectations(t)
})
@@ -586,7 +590,7 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
th.App.Srv().Platform().SearchEngine.ElasticsearchEngine = nil
}()
results, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
results, allFilesHaveMembership, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
require.Nil(t, err)
require.NotNil(t, results)
@@ -599,6 +603,7 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
fileInfos[1].Id,
fileInfos[0].Id,
}, results.Order)
require.True(t, allFilesHaveMembership)
es.AssertExpectations(t)
})
@@ -619,10 +624,11 @@ func TestSearchFilesInTeamForUser(t *testing.T) {
th.App.Srv().Platform().SearchEngine.ElasticsearchEngine = nil
}()
results, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
results, allFilesHaveMembership, err := th.App.SearchFilesInTeamForUser(th.Context, searchTerm, th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, page, perPage)
require.Nil(t, err)
assert.Equal(t, []string{}, results.Order)
require.True(t, allFilesHaveMembership)
es.AssertExpectations(t)
})
}
@@ -749,16 +755,18 @@ func TestSetFileSearchableContent(t *testing.T) {
})
require.NoError(t, err)
result, appErr := th.App.SearchFilesInTeamForUser(th.Context, "searchable", th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, 0, 60)
result, allFilesHaveMembership, appErr := th.App.SearchFilesInTeamForUser(th.Context, "searchable", th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, 0, 60)
require.Nil(t, appErr)
assert.Equal(t, 0, len(result.Order))
require.True(t, allFilesHaveMembership)
appErr = th.App.SetFileSearchableContent(th.Context, fileInfo.Id, "searchable")
require.Nil(t, appErr)
result, appErr = th.App.SearchFilesInTeamForUser(th.Context, "searchable", th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, 0, 60)
result, allFilesHaveMembership, appErr = th.App.SearchFilesInTeamForUser(th.Context, "searchable", th.BasicUser.Id, th.BasicTeam.Id, false, false, 0, 0, 60)
require.Nil(t, appErr)
assert.Equal(t, 1, len(result.Order))
require.True(t, allFilesHaveMembership)
}
func TestPermanentDeleteFilesByPost(t *testing.T) {
@@ -786,7 +794,7 @@ func TestPermanentDeleteFilesByPost(t *testing.T) {
FileIds: []string{info1.Id},
}
post, err = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
assert.Nil(t, err)
err = th.App.PermanentDeleteFilesByPost(th.Context, post.Id)
@@ -810,7 +818,7 @@ func TestPermanentDeleteFilesByPost(t *testing.T) {
CreateAt: 0,
}
post, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
assert.Nil(t, err)
err = th.App.PermanentDeleteFilesByPost(th.Context, post.Id)
@@ -853,7 +861,7 @@ func TestFilterFilesByChannelPermissions(t *testing.T) {
fileList.Order = []string{fileInfo1.Id, fileInfo2.Id, fileInfo3.Id}
// BasicUser should have access to all files
appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
_, appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
require.Nil(t, appErr)
require.Len(t, fileList.FileInfos, 3)
require.Len(t, fileList.Order, 3)
@@ -866,7 +874,7 @@ func TestFilterFilesByChannelPermissions(t *testing.T) {
fileList.FileInfos[fileInfo3.Id] = fileInfo3
fileList.Order = []string{fileInfo1.Id, fileInfo2.Id, fileInfo3.Id}
appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, guestUser.Id)
_, appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, guestUser.Id)
require.Nil(t, appErr)
require.Len(t, fileList.FileInfos, 3)
require.Len(t, fileList.Order, 3)
@@ -904,7 +912,7 @@ func TestFilterFilesByChannelPermissions(t *testing.T) {
fileList.FileInfos[fileInfo3.Id] = fileInfo3
fileList.Order = []string{fileInfo1.Id, fileInfo2.Id, fileInfo3.Id}
appErr = th.App.FilterFilesByChannelPermissions(th.Context, fileList, guestUser.Id)
_, appErr = th.App.FilterFilesByChannelPermissions(th.Context, fileList, guestUser.Id)
require.Nil(t, appErr)
require.Len(t, fileList.FileInfos, 0)
require.Len(t, fileList.Order, 0)
@@ -912,14 +920,14 @@ func TestFilterFilesByChannelPermissions(t *testing.T) {
t.Run("should handle empty file list", func(t *testing.T) {
fileList := model.NewFileInfoList()
appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
_, appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
require.Nil(t, appErr)
require.Len(t, fileList.FileInfos, 0)
require.Len(t, fileList.Order, 0)
})
t.Run("should handle nil file list", func(t *testing.T) {
appErr := th.App.FilterFilesByChannelPermissions(th.Context, nil, th.BasicUser.Id)
_, appErr := th.App.FilterFilesByChannelPermissions(th.Context, nil, th.BasicUser.Id)
require.Nil(t, appErr)
})
@@ -933,7 +941,7 @@ func TestFilterFilesByChannelPermissions(t *testing.T) {
fileList.FileInfos[fileWithoutChannel.Id] = fileWithoutChannel
fileList.Order = []string{fileWithoutChannel.Id}
appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
_, appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
require.Nil(t, appErr)
require.Len(t, fileList.FileInfos, 0)
require.Len(t, fileList.Order, 0)
@@ -949,7 +957,7 @@ func TestFilterFilesByChannelPermissions(t *testing.T) {
fileList.FileInfos[fileWithInvalidChannel.Id] = fileWithInvalidChannel
fileList.Order = []string{fileWithInvalidChannel.Id}
appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
_, appErr := th.App.FilterFilesByChannelPermissions(th.Context, fileList, th.BasicUser.Id)
require.Nil(t, appErr)
require.Len(t, fileList.FileInfos, 0)
require.Len(t, fileList.Order, 0)

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

@@ -518,7 +518,7 @@ func (th *TestHelper) CreatePost(channel *model.Channel, postOptions ...PostOpti
}
var err *model.AppError
if post, err = th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if post, _, err = th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
panic(err)
}
return post
@@ -533,7 +533,7 @@ func (th *TestHelper) CreateMessagePost(channel *model.Channel, message string)
}
var err *model.AppError
if post, err = th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if post, _, err = th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
panic(err)
}
return post
@@ -553,7 +553,7 @@ func (th *TestHelper) CreatePostReply(root *model.Post) *model.Post {
if err != nil {
panic(err)
}
if post, err = th.App.CreatePost(th.Context, post, ch, model.CreatePostFlags{SetOnline: true}); err != nil {
if post, _, err = th.App.CreatePost(th.Context, post, ch, model.CreatePostFlags{SetOnline: true}); err != nil {
panic(err)
}
return post
@@ -861,7 +861,7 @@ func (th *TestHelper) PostPatch(post *model.Post, message string, options ...Pos
optionFunc(postPatch)
}
updatedPost, appErr := th.App.PatchPost(th.Context, post.Id, postPatch, nil)
updatedPost, _, appErr := th.App.PatchPost(th.Context, post.Id, postPatch, nil)
if appErr != nil {
panic(appErr)
}

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

@@ -280,7 +280,7 @@ func (a *App) DoPostActionWithCookie(c request.CTX, postID, actionId, userID, se
response.Update.IsPinned = originalIsPinned
response.Update.HasReactions = originalHasReactions
if _, appErr = a.UpdatePost(c, response.Update, &model.UpdatePostOptions{SafeUpdate: false}); appErr != nil {
if _, _, appErr = a.UpdatePost(c, response.Update, &model.UpdatePostOptions{SafeUpdate: false}); appErr != nil {
return "", appErr
}
}

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

@@ -59,7 +59,7 @@ func TestPostActionInvalidURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -113,7 +113,7 @@ func TestPostActionEmptyResponse(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -157,7 +157,7 @@ func TestPostActionEmptyResponse(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -268,7 +268,7 @@ func TestPostAction(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -305,7 +305,7 @@ func TestPostAction(t *testing.T) {
},
}
post2, err := th.App.CreatePostAsUser(th.Context, &menuPost, "", true)
post2, _, err := th.App.CreatePostAsUser(th.Context, &menuPost, "", true)
require.Nil(t, err)
attachments2, ok := post2.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -363,7 +363,7 @@ func TestPostAction(t *testing.T) {
},
}
postplugin, err := th.App.CreatePostAsUser(th.Context, &interactivePostPlugin, "", true)
postplugin, _, err := th.App.CreatePostAsUser(th.Context, &interactivePostPlugin, "", true)
require.Nil(t, err)
attachmentsPlugin, ok := postplugin.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -411,7 +411,7 @@ func TestPostAction(t *testing.T) {
},
}
postSiteURL, err := th.App.CreatePostAsUser(th.Context, &interactivePostSiteURL, "", true)
postSiteURL, _, err := th.App.CreatePostAsUser(th.Context, &interactivePostSiteURL, "", true)
require.Nil(t, err)
attachmentsSiteURL, ok := postSiteURL.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -453,7 +453,7 @@ func TestPostAction(t *testing.T) {
},
}
postSubpath, err := th.App.CreatePostAsUser(th.Context, &interactivePostSubpath, "", true)
postSubpath, _, err := th.App.CreatePostAsUser(th.Context, &interactivePostSubpath, "", true)
require.Nil(t, err)
attachmentsSubpath, ok := postSubpath.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
@@ -529,7 +529,7 @@ func TestPostActionProps(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -715,7 +715,7 @@ func TestPostActionRelativeURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -755,7 +755,7 @@ func TestPostActionRelativeURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -795,7 +795,7 @@ func TestPostActionRelativeURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -835,7 +835,7 @@ func TestPostActionRelativeURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -875,7 +875,7 @@ func TestPostActionRelativeURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -953,7 +953,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -993,7 +993,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -1033,7 +1033,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)
@@ -1073,7 +1073,7 @@ func TestPostActionRelativePluginURL(t *testing.T) {
},
}
post, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
post, _, err := th.App.CreatePostAsUser(th.Context, &interactivePost, "", true)
require.Nil(t, err)
attachments, ok := post.GetProp(model.PostPropsAttachments).([]*model.SlackAttachment)
require.True(t, ok)

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

@@ -825,7 +825,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
a.sanitizeProfiles(userThread.Participants, false)
userThread.Post.SanitizeProps()
sanitizedPost, err := a.SanitizePostMetadataForUser(c, userThread.Post, uid)
sanitizedPost, isMemberForPreview, err := a.SanitizePostMetadataForUser(c, userThread.Post, uid)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonParseError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Failed to sanitize metadata",
@@ -849,6 +849,18 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
message.Add("previous_unread_mentions", previousUnreadMentions)
message.Add("previous_unread_replies", previousUnreadReplies)
auditRec := a.MakeAuditRecord(c, "websocketPost", model.AuditStatusSuccess)
defer a.LogAuditRec(c, auditRec, nil)
model.AddEventParameterToAuditRec(auditRec, "post_id", userThread.Post.Id)
if !isMemberForPreview {
previewPost := userThread.Post.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
a.Publish(message)
}
}
@@ -1008,7 +1020,7 @@ func (a *App) RemoveNotifications(c request.CTX, post *model.Post, channel *mode
a.sanitizeProfiles(userThread.Participants, false)
userThread.Post.SanitizeProps()
sanitizedPost, err1 := a.SanitizePostMetadataForUser(c, userThread.Post, userID)
sanitizedPost, isMemberForPreview, err1 := a.SanitizePostMetadataForUser(c, userThread.Post, userID)
if err1 != nil {
return err1
}
@@ -1019,6 +1031,18 @@ func (a *App) RemoveNotifications(c request.CTX, post *model.Post, channel *mode
c.Logger().Warn("Failed to encode thread to JSON")
}
auditRec := a.MakeAuditRecord(c, "websocketPost", model.AuditStatusSuccess)
defer a.LogAuditRec(c, auditRec, nil)
model.AddEventParameterToAuditRec(auditRec, "post_id", userThread.Post.Id)
if !isMemberForPreview {
previewPost := userThread.Post.GetPreviewPost()
if previewPost != nil {
model.AddEventParameterToAuditRec(auditRec, "preview_post_id", previewPost.Post.Id)
}
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
message := model.NewWebSocketEvent(model.WebsocketEventThreadUpdated, team.Id, "", userID, nil, "")
message.Add("thread", string(payload))
message.Add("previous_unread_mentions", previousUnreadMentions)
@@ -1451,7 +1475,7 @@ func getMentionsEnabledFields(post *model.Post) model.StringArray {
// allowChannelMentions returns whether or not the channel mentions are allowed for the given post.
func (a *App) allowChannelMentions(c request.CTX, post *model.Post, numProfiles int) bool {
if !a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseChannelMentions) {
if ok, _ := a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseChannelMentions); !ok {
return false
}
@@ -1472,7 +1496,7 @@ func (a *App) allowGroupMentions(c request.CTX, post *model.Post) bool {
return false
}
if !a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseGroupMentions) {
if ok, _ := a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseGroupMentions); !ok {
return false
}

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

@@ -45,7 +45,7 @@ func TestSendNotifications(t *testing.T) {
_, appErr := th.App.AddUserToChannel(th.Context, th.BasicUser2, th.BasicChannel, false)
require.Nil(t, appErr)
post1, createPostErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
post1, _, createPostErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "@" + th.BasicUser2.Username,
@@ -76,7 +76,7 @@ func TestSendNotifications(t *testing.T) {
Message: fmt.Sprintf("hello @%s group", *group.Name),
CreateAt: model.GetMillis() - 10000,
}
groupMentionPost, createPostErr := th.App.CreatePost(th.Context, groupMentionPost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
groupMentionPost, _, createPostErr := th.App.CreatePost(th.Context, groupMentionPost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, createPostErr)
mentions, err := th.App.SendNotifications(th.Context, groupMentionPost, th.BasicTeam, th.BasicChannel, th.BasicUser, nil, true)
@@ -96,7 +96,7 @@ func TestSendNotifications(t *testing.T) {
dm, appErr := th.App.GetOrCreateDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
require.Nil(t, appErr)
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
post2, _, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: dm.Id,
Message: "dm message",
@@ -112,7 +112,7 @@ func TestSendNotifications(t *testing.T) {
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
post3, _, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: dm.Id,
Message: "dm message",
@@ -137,7 +137,7 @@ func TestSendNotifications(t *testing.T) {
}
channel := th.CreateGroupChannel(th.Context, users[0], users[1])
post2, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
post2, _, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: users[0].Id,
ChannelId: channel.Id,
Message: "gm message",
@@ -153,7 +153,7 @@ func TestSendNotifications(t *testing.T) {
appErr = th.App.Srv().InvalidateAllCaches()
require.Nil(t, appErr)
post3, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
post3, _, appErr := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: users[0].Id,
ChannelId: channel.Id,
Message: "gm message",
@@ -179,7 +179,7 @@ func TestSendNotifications(t *testing.T) {
Props: model.StringInterface{model.PostPropsFromWebhook: "true", model.PostPropsOverrideUsername: "a bot"},
}
rootPost, appErr := th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
rootPost, _, appErr := th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
require.Nil(t, appErr)
childPost := &model.Post{
@@ -188,7 +188,7 @@ func TestSendNotifications(t *testing.T) {
RootId: rootPost.Id,
Message: "a reply",
}
childPost, appErr = th.App.CreatePostMissingChannel(th.Context, childPost, false, true)
childPost, _, appErr = th.App.CreatePostMissingChannel(th.Context, childPost, false, true)
require.Nil(t, appErr)
postList := model.PostList{
@@ -361,7 +361,7 @@ func TestSendNotifications_MentionsFollowers(t *testing.T) {
}
// Use CreatePost instead of SendNotifications here since we need that to set up some threads state
_, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
received1 := <-messages1
@@ -580,7 +580,7 @@ func TestSendNotificationsWithManyUsers(t *testing.T) {
users = append(users, user)
}
_, appErr1 := th.App.CreatePostMissingChannel(th.Context, &model.Post{
_, _, appErr1 := th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "@channel",
@@ -600,7 +600,7 @@ func TestSendNotificationsWithManyUsers(t *testing.T) {
}
})
_, appErr1 = th.App.CreatePostMissingChannel(th.Context, &model.Post{
_, _, appErr1 = th.App.CreatePostMissingChannel(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "@channel",
@@ -2860,7 +2860,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
Message: "root post by user1",
UserId: u1.Id,
}
rpost, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
rpost, _, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost1 := &model.Post{
@@ -2869,7 +2869,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
UserId: u2.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost2 := &model.Post{
@@ -2878,7 +2878,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
UserId: u1.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
threadMembership, appErr := th.App.GetThreadMembershipForUser(u2.Id, rpost.Id)
@@ -2910,7 +2910,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
Props: model.StringInterface{model.PostPropsFromWebhook: "true", model.PostPropsOverrideUsername: "a bot"},
}
rootPost, appErr := th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
rootPost, _, appErr := th.App.CreatePostMissingChannel(th.Context, rootPost, false, true)
require.Nil(t, appErr)
childPost := &model.Post{
@@ -2919,7 +2919,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
RootId: rootPost.Id,
Message: "a reply",
}
childPost, appErr = th.App.CreatePostMissingChannel(th.Context, childPost, false, true)
childPost, _, appErr = th.App.CreatePostMissingChannel(th.Context, childPost, false, true)
require.Nil(t, appErr)
postList := model.PostList{
@@ -2955,7 +2955,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
Message: "root post by user1",
UserId: u1.Id,
}
rpost, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
rpost, _, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// Remove user1 from the channel
@@ -2968,7 +2968,7 @@ func TestReplyPostNotificationsWithCRT(t *testing.T) {
UserId: u2.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// Ensure user1 is not auto-following the thread
@@ -3001,7 +3001,7 @@ func TestChannelAutoFollowThreads(t *testing.T) {
Message: "root post by user3",
UserId: u3.Id,
}
rpost, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
rpost, _, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost1 := &model.Post{
@@ -3010,7 +3010,7 @@ func TestChannelAutoFollowThreads(t *testing.T) {
UserId: u1.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// user-2 starts auto-following thread
@@ -3032,7 +3032,7 @@ func TestChannelAutoFollowThreads(t *testing.T) {
UserId: u1.Id,
RootId: rpost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
// Do NOT start auto-following thread, once "un-followed"
@@ -3064,7 +3064,7 @@ func TestRemoveNotifications(t *testing.T) {
Message: "root post by user1",
UserId: u1.Id,
}
rootPost, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
rootPost, _, appErr := th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost1 := &model.Post{
@@ -3073,7 +3073,7 @@ func TestRemoveNotifications(t *testing.T) {
UserId: u2.Id,
RootId: rootPost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost2 := &model.Post{
@@ -3082,7 +3082,7 @@ func TestRemoveNotifications(t *testing.T) {
UserId: u1.Id,
RootId: rootPost.Id,
}
replyPost2, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
replyPost2, _, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
_, appErr = th.App.DeletePost(th.Context, replyPost2.Id, u1.Id)
@@ -3121,7 +3121,7 @@ func TestRemoveNotifications(t *testing.T) {
Message: "root post by user1",
UserId: u1.Id,
}
rootPost, appErr = th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
rootPost, _, appErr = th.App.CreatePost(th.Context, rootPost, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost1 := &model.Post{
@@ -3130,7 +3130,7 @@ func TestRemoveNotifications(t *testing.T) {
UserId: u2.Id,
RootId: rootPost.Id,
}
_, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
_, _, appErr = th.App.CreatePost(th.Context, replyPost1, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
replyPost2 := &model.Post{
@@ -3139,7 +3139,7 @@ func TestRemoveNotifications(t *testing.T) {
UserId: u1.Id,
RootId: rootPost.Id,
}
replyPost2, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
replyPost2, _, appErr = th.App.CreatePost(th.Context, replyPost2, c1, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
_, appErr = th.App.DeletePost(th.Context, replyPost2.Id, u1.Id)

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

@@ -164,7 +164,7 @@ func (a *App) upgradePlanAdminNotifyPost(c request.CTX, workspaceName string, us
props["trial"] = trial
post.SetProps(props)
_, appErr = a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true})
_, _, appErr = a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true})
if appErr != nil {
c.Logger().Warn("Error creating post", mlog.Err(appErr))

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

@@ -61,8 +61,18 @@ func (ms *mockSuite) UserCanSeeOtherUser(c request.CTX, userID string, otherUser
return true, nil
}
func (ms *mockSuite) HasPermissionToReadChannel(c request.CTX, userID string, channel *model.Channel) bool {
return true
func (ms *mockSuite) HasPermissionToReadChannel(rctx request.CTX, userID string, channel *model.Channel) (bool, bool) {
return true, true
}
func (ms *mockSuite) MakeAuditRecord(rctx request.CTX, event string, initialStatus string) *model.AuditRecord {
return &model.AuditRecord{
Status: initialStatus,
EventName: event,
}
}
func (ms *mockSuite) LogAuditRec(rctx request.CTX, auditRec *model.AuditRecord, err error) {
}
func setupDBStore(tb testing.TB) (store.Store, *model.SqlSettings) {

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

@@ -48,21 +48,56 @@ func (_m *SuiteIFace) GetSession(token string) (*model.Session, *model.AppError)
return r0, r1
}
// HasPermissionToReadChannel provides a mock function with given fields: c, userID, channel
func (_m *SuiteIFace) HasPermissionToReadChannel(c request.CTX, userID string, channel *model.Channel) bool {
ret := _m.Called(c, userID, channel)
// HasPermissionToReadChannel provides a mock function with given fields: rctx, userID, channel
func (_m *SuiteIFace) HasPermissionToReadChannel(rctx request.CTX, userID string, channel *model.Channel) (bool, bool) {
ret := _m.Called(rctx, userID, channel)
if len(ret) == 0 {
panic("no return value specified for HasPermissionToReadChannel")
}
var r0 bool
var r1 bool
if rf, ok := ret.Get(0).(func(request.CTX, string, *model.Channel) (bool, bool)); ok {
return rf(rctx, userID, channel)
}
if rf, ok := ret.Get(0).(func(request.CTX, string, *model.Channel) bool); ok {
r0 = rf(c, userID, channel)
r0 = rf(rctx, userID, channel)
} else {
r0 = ret.Get(0).(bool)
}
if rf, ok := ret.Get(1).(func(request.CTX, string, *model.Channel) bool); ok {
r1 = rf(rctx, userID, channel)
} else {
r1 = ret.Get(1).(bool)
}
return r0, r1
}
// LogAuditRec provides a mock function with given fields: rctx, auditRec, err
func (_m *SuiteIFace) LogAuditRec(rctx request.CTX, auditRec *model.AuditRecord, err error) {
_m.Called(rctx, auditRec, err)
}
// MakeAuditRecord provides a mock function with given fields: rctx, event, initialStatus
func (_m *SuiteIFace) MakeAuditRecord(rctx request.CTX, event string, initialStatus string) *model.AuditRecord {
ret := _m.Called(rctx, event, initialStatus)
if len(ret) == 0 {
panic("no return value specified for MakeAuditRecord")
}
var r0 *model.AuditRecord
if rf, ok := ret.Get(0).(func(request.CTX, string, string) *model.AuditRecord); ok {
r0 = rf(rctx, event, initialStatus)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AuditRecord)
}
}
return r0
}
@@ -84,9 +119,9 @@ func (_m *SuiteIFace) RolesGrantPermission(roleNames []string, permissionId stri
return r0
}
// UserCanSeeOtherUser provides a mock function with given fields: c, userID, otherUserId
func (_m *SuiteIFace) UserCanSeeOtherUser(c request.CTX, userID string, otherUserId string) (bool, *model.AppError) {
ret := _m.Called(c, userID, otherUserId)
// UserCanSeeOtherUser provides a mock function with given fields: rctx, userID, otherUserId
func (_m *SuiteIFace) UserCanSeeOtherUser(rctx request.CTX, userID string, otherUserId string) (bool, *model.AppError) {
ret := _m.Called(rctx, userID, otherUserId)
if len(ret) == 0 {
panic("no return value specified for UserCanSeeOtherUser")
@@ -95,16 +130,16 @@ func (_m *SuiteIFace) UserCanSeeOtherUser(c request.CTX, userID string, otherUse
var r0 bool
var r1 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, string, string) (bool, *model.AppError)); ok {
return rf(c, userID, otherUserId)
return rf(rctx, userID, otherUserId)
}
if rf, ok := ret.Get(0).(func(request.CTX, string, string) bool); ok {
r0 = rf(c, userID, otherUserId)
r0 = rf(rctx, userID, otherUserId)
} else {
r0 = ret.Get(0).(bool)
}
if rf, ok := ret.Get(1).(func(request.CTX, string, string) *model.AppError); ok {
r1 = rf(c, userID, otherUserId)
r1 = rf(rctx, userID, otherUserId)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)

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

@@ -28,8 +28,10 @@ const (
type SuiteIFace interface {
GetSession(token string) (*model.Session, *model.AppError)
RolesGrantPermission(roleNames []string, permissionId string) bool
HasPermissionToReadChannel(c request.CTX, userID string, channel *model.Channel) bool
UserCanSeeOtherUser(c request.CTX, userID string, otherUserId string) (bool, *model.AppError)
HasPermissionToReadChannel(rctx request.CTX, userID string, channel *model.Channel) (bool, bool)
UserCanSeeOtherUser(rctx request.CTX, userID string, otherUserId string) (bool, *model.AppError)
MakeAuditRecord(rctx request.CTX, event string, initialStatus string) *model.AuditRecord
LogAuditRec(rctx request.CTX, auditRec *model.AuditRecord, err error)
}
type webConnActivityMessage struct {

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

@@ -591,7 +591,7 @@ func (api *PluginAPI) SearchPostsInTeamForUser(teamID string, userID string, sea
includeDeletedChannels = *searchParams.IncludeDeletedChannels
}
results, appErr := api.app.SearchPostsForUser(api.ctx, terms, userID, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
results, _, appErr := api.app.SearchPostsForUser(api.ctx, terms, userID, teamID, isOrSearch, includeDeletedChannels, timeZoneOffset, page, perPage)
if results != nil {
results = results.ForPlugin()
}
@@ -773,7 +773,7 @@ func (api *PluginAPI) DeleteGroupSyncable(groupID string, syncableID string, syn
func (api *PluginAPI) CreatePost(post *model.Post) (*model.Post, *model.AppError) {
post.AddProp(model.PostPropsFromPlugin, "true")
post, appErr := api.app.CreatePostMissingChannel(api.ctx, post, true, true)
post, _, appErr := api.app.CreatePostMissingChannel(api.ctx, post, true, true)
if post != nil {
post = post.ForPlugin()
}
@@ -793,11 +793,13 @@ func (api *PluginAPI) GetReactions(postID string) ([]*model.Reaction, *model.App
}
func (api *PluginAPI) SendEphemeralPost(userID string, post *model.Post) *model.Post {
return api.app.SendEphemeralPost(api.ctx, userID, post).ForPlugin()
newPost, _ := api.app.SendEphemeralPost(api.ctx, userID, post)
return newPost.ForPlugin()
}
func (api *PluginAPI) UpdateEphemeralPost(userID string, post *model.Post) *model.Post {
return api.app.UpdateEphemeralPost(api.ctx, userID, post).ForPlugin()
newPost, _ := api.app.UpdateEphemeralPost(api.ctx, userID, post)
return newPost.ForPlugin()
}
func (api *PluginAPI) DeleteEphemeralPost(userID, postID string) {
@@ -858,7 +860,7 @@ func (api *PluginAPI) GetPostsForChannel(channelID string, page, perPage int) (*
}
func (api *PluginAPI) UpdatePost(post *model.Post) (*model.Post, *model.AppError) {
post, appErr := api.app.UpdatePost(api.ctx, post, &model.UpdatePostOptions{SafeUpdate: false})
post, _, appErr := api.app.UpdatePost(api.ctx, post, &model.UpdatePostOptions{SafeUpdate: false})
if post != nil {
post = post.ForPlugin()
}
@@ -1104,7 +1106,8 @@ func (api *PluginAPI) HasPermissionToTeam(userID, teamID string, permission *mod
}
func (api *PluginAPI) HasPermissionToChannel(userID, channelID string, permission *model.Permission) bool {
return api.app.HasPermissionToChannel(api.ctx, userID, channelID, permission)
ok, _ := api.app.HasPermissionToChannel(api.ctx, userID, channelID, permission)
return ok
}
func (api *PluginAPI) RolesGrantPermission(roleNames []string, permissionId string) bool {

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

@@ -112,7 +112,7 @@ func TestHookMessageWillBePosted(t *testing.T) {
Message: "message_",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
if assert.NotNil(t, err) {
assert.Equal(t, "Post rejected by plugin. rejected", err.Message)
}
@@ -154,7 +154,7 @@ func TestHookMessageWillBePosted(t *testing.T) {
Message: "message_",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
if assert.NotNil(t, err) {
assert.Equal(t, "Post rejected by plugin. rejected", err.Message)
}
@@ -195,7 +195,7 @@ func TestHookMessageWillBePosted(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
post, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
assert.Equal(t, "message", post.Message)
@@ -240,7 +240,7 @@ func TestHookMessageWillBePosted(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
post, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
assert.Equal(t, "message_fromplugin", post.Message)
@@ -307,7 +307,7 @@ func TestHookMessageWillBePosted(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
post, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
assert.Equal(t, "prefix_message_suffix", post.Message)
})
@@ -353,7 +353,7 @@ func TestHookMessageHasBeenPosted(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
}
@@ -394,11 +394,11 @@ func TestHookMessageWillBeUpdated(t *testing.T) {
Message: "message_",
CreateAt: model.GetMillis() - 10000,
}
post, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
assert.Equal(t, "message_", post.Message)
post.Message = post.Message + "edited_"
post, err = th.App.UpdatePost(th.Context, post, &model.UpdatePostOptions{SafeUpdate: true})
post, _, err = th.App.UpdatePost(th.Context, post, &model.UpdatePostOptions{SafeUpdate: true})
require.Nil(t, err)
assert.Equal(t, "message_edited_fromplugin", post.Message)
}
@@ -444,11 +444,11 @@ func TestHookMessageHasBeenUpdated(t *testing.T) {
Message: "message_",
CreateAt: model.GetMillis() - 10000,
}
post, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
assert.Equal(t, "message_", post.Message)
post.Message = post.Message + "edited"
_, err = th.App.UpdatePost(th.Context, post, &model.UpdatePostOptions{SafeUpdate: true})
_, _, err = th.App.UpdatePost(th.Context, post, &model.UpdatePostOptions{SafeUpdate: true})
require.Nil(t, err)
}
@@ -492,7 +492,7 @@ func TestHookMessageHasBeenDeleted(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
_, err = th.App.DeletePost(th.Context, post.Id, th.BasicUser.Id)
require.Nil(t, err)
@@ -1081,7 +1081,7 @@ func TestHookContext(t *testing.T) {
Message: "not this",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(ctx, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(ctx, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
}
@@ -1670,7 +1670,7 @@ func TestHookMessagesWillBeConsumed(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, newPost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, newPost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
post, err := th.App.GetSinglePost(th.Context, newPost.Id, true)
@@ -1695,7 +1695,7 @@ func TestHookMessagesWillBeConsumed(t *testing.T) {
Message: "message",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, newPost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, newPost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
post, err := th.App.GetSinglePost(th.Context, newPost.Id, true)

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

@@ -765,7 +765,7 @@ func TestPluginPanicLogs(t *testing.T) {
Message: "message_",
CreateAt: model.GetMillis() - 10000,
}
_, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
_, _, err := th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
assert.Nil(t, err)
th.TestLogger.Flush()

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

@@ -37,32 +37,32 @@ const (
var atMentionPattern = regexp.MustCompile(`\B@`)
func (a *App) CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError) {
func (a *App) CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, bool, *model.AppError) {
// Check that channel has not been deleted
channel, errCh := a.Srv().Store().Channel().Get(post.ChannelId, true)
if errCh != nil {
err := model.NewAppError("CreatePostAsUser", "api.context.invalid_param.app_error", map[string]any{"Name": "post.channel_id"}, "", http.StatusBadRequest).Wrap(errCh)
return nil, err
return nil, false, err
}
if strings.HasPrefix(post.Type, model.PostSystemMessagePrefix) {
err := model.NewAppError("CreatePostAsUser", "api.context.invalid_param.app_error", map[string]any{"Name": "post.type"}, "", http.StatusBadRequest)
return nil, err
return nil, false, err
}
if channel.DeleteAt != 0 {
err := model.NewAppError("createPost", "api.post.create_post.can_not_post_to_deleted.error", nil, "", http.StatusBadRequest)
return nil, err
return nil, false, err
}
rp, err := a.CreatePost(c, post, channel, model.CreatePostFlags{TriggerWebhooks: true, SetOnline: setOnline})
rp, isMemberForPreviews, err := a.CreatePost(c, post, channel, model.CreatePostFlags{TriggerWebhooks: true, SetOnline: setOnline})
if err != nil {
if err.Id == "api.post.create_post.root_id.app_error" ||
err.Id == "api.post.create_post.channel_root_id.app_error" {
err.StatusCode = http.StatusBadRequest
}
return nil, err
return nil, false, err
}
// Update the Channel LastViewAt only if:
@@ -115,19 +115,19 @@ func (a *App) CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId
}
}
return rp, nil
return rp, isMemberForPreviews, nil
}
func (a *App) CreatePostMissingChannel(c request.CTX, post *model.Post, triggerWebhooks bool, setOnline bool) (*model.Post, *model.AppError) {
func (a *App) CreatePostMissingChannel(c request.CTX, post *model.Post, triggerWebhooks bool, setOnline bool) (*model.Post, bool, *model.AppError) {
channel, err := a.Srv().Store().Channel().Get(post.ChannelId, true)
if err != nil {
errCtx := map[string]any{"channel_id": post.ChannelId}
var nfErr *store.ErrNotFound
switch {
case errors.As(err, &nfErr):
return nil, model.NewAppError("CreatePostMissingChannel", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
return nil, false, model.NewAppError("CreatePostMissingChannel", "app.channel.get.existing.app_error", errCtx, "", http.StatusNotFound).Wrap(err)
default:
return nil, model.NewAppError("CreatePostMissingChannel", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
return nil, false, model.NewAppError("CreatePostMissingChannel", "app.channel.get.find.app_error", errCtx, "", http.StatusInternalServerError).Wrap(err)
}
}
@@ -168,7 +168,7 @@ func (a *App) deduplicateCreatePost(rctx request.CTX, post *model.Post) (foundPo
// If the other thread finished creating the post, return the created post back to the
// client, making the API call feel idempotent.
actualPost, err := a.GetPostIfAuthorized(rctx, postID, rctx.Session(), false)
actualPost, err, _ := a.GetPostIfAuthorized(rctx, postID, rctx.Session(), false)
if err != nil && err.StatusCode == http.StatusForbidden {
rctx.Logger().Warn("Ignoring pending_post_id for which the user is unauthorized", mlog.String("pending_post_id", post.PendingPostId), mlog.String("post_id", postID), mlog.Err(err))
return nil, nil
@@ -181,17 +181,25 @@ func (a *App) deduplicateCreatePost(rctx request.CTX, post *model.Post) (foundPo
return actualPost, nil
}
func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel, flags model.CreatePostFlags) (savedPost *model.Post, err *model.AppError) {
func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel, flags model.CreatePostFlags) (savedPost *model.Post, isMemberForPreviews bool, err *model.AppError) {
if !a.Config().FeatureFlags.EnableSharedChannelsDMs && channel.IsShared() && (channel.Type == model.ChannelTypeDirect || channel.Type == model.ChannelTypeGroup) {
return nil, model.NewAppError("CreatePost", "app.post.create_post.shared_dm_or_gm.app_error", nil, "", http.StatusBadRequest)
return nil, false, model.NewAppError("CreatePost", "app.post.create_post.shared_dm_or_gm.app_error", nil, "", http.StatusBadRequest)
}
foundPost, err := a.deduplicateCreatePost(c, post)
if err != nil {
return nil, err
return nil, false, err
}
if foundPost != nil {
return foundPost, nil
isMemberForPreviews = true
if previewPost := foundPost.GetPreviewPost(); previewPost != nil {
var member *model.ChannelMember
member, err = a.GetChannelMember(c, previewPost.Post.ChannelId, c.Session().UserId)
if err != nil || member == nil {
isMemberForPreviews = false
}
}
return foundPost, isMemberForPreviews, nil
}
// If we get this far, we've recorded the client-provided pending post id to the cache.
@@ -224,7 +232,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
return nil
})
if err != nil {
return nil, model.NewAppError("CreatePost", "api.post.post_priority.persistent_notification_validation_error.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
return nil, false, model.NewAppError("CreatePost", "api.post.post_priority.persistent_notification_validation_error.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
}
@@ -245,9 +253,9 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
var nfErr *store.ErrNotFound
switch {
case errors.As(nErr, &nfErr):
return nil, model.NewAppError("CreatePost", MissingAccountError, nil, "", http.StatusNotFound).Wrap(nErr)
return nil, false, model.NewAppError("CreatePost", MissingAccountError, nil, "", http.StatusNotFound).Wrap(nErr)
default:
return nil, model.NewAppError("CreatePost", "app.user.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
return nil, false, model.NewAppError("CreatePost", "app.user.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
@@ -264,16 +272,18 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
}
var ephemeralPost *model.Post
if post.Type == "" && !a.HasPermissionToChannel(c, user.Id, channel.Id, model.PermissionUseChannelMentions) {
mention := post.DisableMentionHighlights()
if mention != "" {
T := i18n.GetUserTranslations(user.Locale)
ephemeralPost = &model.Post{
UserId: user.Id,
RootId: post.RootId,
ChannelId: channel.Id,
Message: T("model.post.channel_notifications_disabled_in_channel.message", model.StringInterface{"ChannelName": channel.Name, "Mention": mention}),
Props: model.StringInterface{model.PostPropsMentionHighlightDisabled: true},
if post.Type == "" {
if hasPermission, _ := a.HasPermissionToChannel(c, user.Id, channel.Id, model.PermissionUseChannelMentions); !hasPermission {
mention := post.DisableMentionHighlights()
if mention != "" {
T := i18n.GetUserTranslations(user.Locale)
ephemeralPost = &model.Post{
UserId: user.Id,
RootId: post.RootId,
ChannelId: channel.Id,
Message: T("model.post.channel_notifications_disabled_in_channel.message", model.StringInterface{"ChannelName": channel.Name, "Mention": mention}),
Props: model.StringInterface{model.PostPropsMentionHighlightDisabled: true},
}
}
}
}
@@ -283,23 +293,23 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
if pchan != nil {
result := <-pchan
if result.NErr != nil {
return nil, model.NewAppError("createPost", "api.post.create_post.root_id.app_error", nil, "", http.StatusBadRequest).Wrap(result.NErr)
return nil, false, model.NewAppError("createPost", "api.post.create_post.root_id.app_error", nil, "", http.StatusBadRequest).Wrap(result.NErr)
}
parentPostList = result.Data
if len(parentPostList.Posts) == 0 || !parentPostList.IsChannelId(post.ChannelId) {
return nil, model.NewAppError("createPost", "api.post.create_post.channel_root_id.app_error", nil, "", http.StatusInternalServerError)
return nil, false, model.NewAppError("createPost", "api.post.create_post.channel_root_id.app_error", nil, "", http.StatusInternalServerError)
}
rootPost := parentPostList.Posts[post.RootId]
if rootPost.RootId != "" {
return nil, model.NewAppError("createPost", "api.post.create_post.root_id.app_error", nil, "", http.StatusBadRequest)
return nil, false, model.NewAppError("createPost", "api.post.create_post.root_id.app_error", nil, "", http.StatusBadRequest)
}
}
post.Hashtags, _ = model.ParseHashtags(post.Message)
if err = a.FillInPostProps(c, post, channel); err != nil {
return nil, err
return nil, false, err
}
// Temporary fix so old plugins don't clobber new fields in SlackAttachment struct, see MM-13088
@@ -344,7 +354,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
}, plugin.MessageWillBePostedID)
if rejectionError != nil {
return nil, rejectionError
return nil, false, rejectionError
}
// Pre-fill the CreateAt field for link previews to get the correct timestamp.
@@ -364,18 +374,18 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
var invErr *store.ErrInvalidInput
switch {
case errors.As(nErr, &appErr):
return nil, appErr
return nil, false, appErr
case errors.As(nErr, &invErr):
return nil, model.NewAppError("CreatePost", "app.post.save.existing.app_error", nil, "", http.StatusBadRequest).Wrap(nErr)
return nil, false, model.NewAppError("CreatePost", "app.post.save.existing.app_error", nil, "", http.StatusBadRequest).Wrap(nErr)
default:
return nil, model.NewAppError("CreatePost", "app.post.save.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
return nil, false, model.NewAppError("CreatePost", "app.post.save.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
// Update the mapping from pending post id to the actual post id, for any clients that
// might be duplicating requests.
if appErr := a.Srv().seenPendingPostIdsCache.SetWithExpiry(post.PendingPostId, rpost.Id, pendingPostIDsCacheTTL); appErr != nil {
return nil, model.NewAppError("CreatePost", "api.post.deduplicate_create_post.cache_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
return nil, false, model.NewAppError("CreatePost", "api.post.deduplicate_create_post.cache_error", nil, "", http.StatusInternalServerError).Wrap(appErr)
}
if a.Metrics() != nil {
@@ -420,7 +430,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
mlog.String("reason", model.NotificationReasonResolvePersistentNotificationError),
mlog.Err(appErr),
)
return nil, appErr
return nil, false, appErr
}
}
@@ -444,12 +454,12 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
a.SendEphemeralPost(c, post.UserId, ephemeralPost)
}
rpost, err = a.SanitizePostMetadataForUser(c, rpost, c.Session().UserId)
rpost, isMemberForPreviews, err = a.SanitizePostMetadataForUser(c, rpost, c.Session().UserId)
if err != nil {
return nil, err
return nil, false, err
}
return rpost, nil
return rpost, isMemberForPreviews, nil
}
func (a *App) addPostPreviewProp(rctx request.CTX, post *model.Post) (*model.Post, error) {
@@ -515,15 +525,17 @@ func (a *App) FillInPostProps(c request.CTX, post *model.Post, channel *model.Ch
}
for _, mentioned := range mentionedChannels {
if mentioned.Type == model.ChannelTypeOpen && a.HasPermissionToReadChannel(c, post.UserId, mentioned) {
team, err := a.Srv().Store().Team().Get(mentioned.TeamId)
if err != nil {
c.Logger().Warn("Failed to get team of the channel mention", mlog.String("team_id", channel.TeamId), mlog.String("channel_id", channel.Id), mlog.Err(err))
continue
}
channelMentionsProp[mentioned.Name] = map[string]any{
"display_name": mentioned.DisplayName,
"team_name": team.Name,
if mentioned.Type == model.ChannelTypeOpen {
if ok, _ := a.HasPermissionToReadChannel(c, post.UserId, mentioned); ok {
team, err := a.Srv().Store().Team().Get(mentioned.TeamId)
if err != nil {
c.Logger().Warn("Failed to get team of the channel mention", mlog.String("team_id", channel.TeamId), mlog.String("channel_id", channel.Id), mlog.Err(err))
continue
}
channelMentionsProp[mentioned.Name] = map[string]any{
"display_name": mentioned.DisplayName,
"team_name": team.Name,
}
}
}
}
@@ -536,7 +548,12 @@ func (a *App) FillInPostProps(c request.CTX, post *model.Post, channel *model.Ch
}
matched := atMentionPattern.MatchString(post.Message)
if a.Srv().License() != nil && *a.Srv().License().Features.LDAPGroups && matched && !a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseGroupMentions) {
shouldAddProp := false
if a.Srv().License() != nil && *a.Srv().License().Features.LDAPGroups && matched {
hasPermission, _ := a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseGroupMentions)
shouldAddProp = !hasPermission
}
if shouldAddProp {
post.AddProp(model.PostPropsGroupHighlightDisabled, true)
}
@@ -593,7 +610,7 @@ func (a *App) handlePostEvents(c request.CTX, post *model.Post, user *model.User
return nil
}
func (a *App) SendEphemeralPost(c request.CTX, userID string, post *model.Post) *model.Post {
func (a *App) SendEphemeralPost(c request.CTX, userID string, post *model.Post) (*model.Post, bool) {
post.Type = model.PostTypeEphemeral
// fill in fields which haven't been specified which have sensible defaults
@@ -612,7 +629,7 @@ func (a *App) SendEphemeralPost(c request.CTX, userID string, post *model.Post)
post = a.PreparePostForClientWithEmbedsAndImages(c, post, true, false, true)
post = model.AddPostActionCookies(post, a.PostActionCookieSecret())
sanitizedPost, appErr := a.SanitizePostMetadataForUser(c, post, userID)
sanitizedPost, isMemberForPreviews, appErr := a.SanitizePostMetadataForUser(c, post, userID)
if appErr != nil {
c.Logger().Error("Failed to sanitize post metadata for user", mlog.String("user_id", userID), mlog.Err(appErr))
@@ -630,10 +647,10 @@ func (a *App) SendEphemeralPost(c request.CTX, userID string, post *model.Post)
message.Add("post", postJSON)
a.Publish(message)
return post
return post, isMemberForPreviews
}
func (a *App) UpdateEphemeralPost(c request.CTX, userID string, post *model.Post) *model.Post {
func (a *App) UpdateEphemeralPost(c request.CTX, userID string, post *model.Post) (*model.Post, bool) {
post.Type = model.PostTypeEphemeral
post.UpdateAt = model.GetMillis()
@@ -646,7 +663,7 @@ func (a *App) UpdateEphemeralPost(c request.CTX, userID string, post *model.Post
post = a.PreparePostForClientWithEmbedsAndImages(c, post, true, false, true)
post = model.AddPostActionCookies(post, a.PostActionCookieSecret())
sanitizedPost, appErr := a.SanitizePostMetadataForUser(c, post, userID)
sanitizedPost, isMemberForPreviews, appErr := a.SanitizePostMetadataForUser(c, post, userID)
if appErr != nil {
c.Logger().Error("Failed to sanitize post metadata for user", mlog.String("user_id", userID), mlog.Err(appErr))
@@ -664,7 +681,7 @@ func (a *App) UpdateEphemeralPost(c request.CTX, userID string, post *model.Post
message.Add("post", postJSON)
a.Publish(message)
return post
return post, isMemberForPreviews
}
func (a *App) DeleteEphemeralPost(rctx request.CTX, userID, postID string) {
@@ -685,7 +702,7 @@ func (a *App) DeleteEphemeralPost(rctx request.CTX, userID, postID string) {
a.Publish(message)
}
func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updatePostOptions *model.UpdatePostOptions) (*model.Post, *model.AppError) {
func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updatePostOptions *model.UpdatePostOptions) (*model.Post, bool, *model.AppError) {
if updatePostOptions == nil {
updatePostOptions = model.DefaultUpdatePostOptions()
}
@@ -698,11 +715,11 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
var invErr *store.ErrInvalidInput
switch {
case errors.As(nErr, &invErr):
return nil, model.NewAppError("UpdatePost", "app.post.get.app_error", nil, "", http.StatusBadRequest).Wrap(nErr)
return nil, false, model.NewAppError("UpdatePost", "app.post.get.app_error", nil, "", http.StatusBadRequest).Wrap(nErr)
case errors.As(nErr, &nfErr):
return nil, model.NewAppError("UpdatePost", "app.post.get.app_error", nil, "", http.StatusNotFound).Wrap(nErr)
return nil, false, model.NewAppError("UpdatePost", "app.post.get.app_error", nil, "", http.StatusNotFound).Wrap(nErr)
default:
return nil, model.NewAppError("UpdatePost", "app.post.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
return nil, false, model.NewAppError("UpdatePost", "app.post.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
oldPost := postLists.Posts[receivedUpdatedPost.Id]
@@ -710,26 +727,26 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
var appErr *model.AppError
if oldPost == nil {
appErr = model.NewAppError("UpdatePost", "api.post.update_post.find.app_error", nil, "id="+receivedUpdatedPost.Id, http.StatusBadRequest)
return nil, appErr
return nil, false, appErr
}
if oldPost.DeleteAt != 0 {
appErr = model.NewAppError("UpdatePost", "api.post.update_post.permissions_details.app_error", map[string]any{"PostId": receivedUpdatedPost.Id}, "", http.StatusBadRequest)
return nil, appErr
return nil, false, appErr
}
if oldPost.IsSystemMessage() {
appErr = model.NewAppError("UpdatePost", "api.post.update_post.system_message.app_error", nil, "id="+receivedUpdatedPost.Id, http.StatusBadRequest)
return nil, appErr
return nil, false, appErr
}
channel, appErr := a.GetChannel(c, oldPost.ChannelId)
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
if channel.DeleteAt != 0 {
return nil, model.NewAppError("UpdatePost", "api.post.update_post.can_not_update_post_in_deleted.error", nil, "", http.StatusBadRequest)
return nil, false, model.NewAppError("UpdatePost", "api.post.update_post.can_not_update_post_in_deleted.error", nil, "", http.StatusBadRequest)
}
newPost := oldPost.Clone()
@@ -748,7 +765,7 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
var fileIds []string
fileIds, appErr = a.processPostFileChanges(c, receivedUpdatedPost, oldPost, updatePostOptions)
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
newPost.FileIds = fileIds
}
@@ -759,7 +776,7 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
}
if appErr = a.FillInPostProps(c, newPost, nil); appErr != nil {
return nil, appErr
return nil, false, appErr
}
if receivedUpdatedPost.IsRemote() {
@@ -773,7 +790,7 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
return newPost != nil
}, plugin.MessageWillBeUpdatedID)
if newPost == nil {
return nil, model.NewAppError("UpdatePost", "Post rejected by plugin. "+rejectionReason, nil, "", http.StatusBadRequest)
return nil, false, model.NewAppError("UpdatePost", "Post rejected by plugin. "+rejectionReason, nil, "", http.StatusBadRequest)
}
// Always use incoming metadata when provided, otherwise retain existing
if receivedUpdatedPost.Metadata != nil {
@@ -788,9 +805,9 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
if nErr != nil {
switch {
case errors.As(nErr, &appErr):
return nil, appErr
return nil, false, appErr
default:
return nil, model.NewAppError("UpdatePost", "app.post.update.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
return nil, false, model.NewAppError("UpdatePost", "app.post.update.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
}
@@ -812,20 +829,20 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
rpost, nErr = a.addPostPreviewProp(c, rpost)
if nErr != nil {
return nil, model.NewAppError("UpdatePost", "app.post.update.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
return nil, false, model.NewAppError("UpdatePost", "app.post.update.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
message := model.NewWebSocketEvent(model.WebsocketEventPostEdited, "", rpost.ChannelId, "", nil, "")
appErr = a.publishWebsocketEventForPost(c, rpost, message)
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
a.invalidateCacheForChannelPosts(rpost.ChannelId)
userID := c.Session().UserId
sanitizedPost, appErr := a.SanitizePostMetadataForUser(c, rpost, userID)
sanitizedPost, isMemberForPreviews, appErr := a.SanitizePostMetadataForUser(c, rpost, userID)
if appErr != nil {
mlog.Error("Failed to sanitize post metadata for user", mlog.String("user_id", userID), mlog.Err(appErr))
@@ -836,7 +853,7 @@ func (a *App) UpdatePost(c request.CTX, receivedUpdatedPost *model.Post, updateP
}
rpost = sanitizedPost
return rpost, nil
return rpost, isMemberForPreviews, nil
}
func (a *App) publishWebsocketEventForPost(rctx request.CTX, post *model.Post, message *model.WebSocketEvent) *model.AppError {
@@ -945,7 +962,9 @@ func (a *App) setupBroadcastHookForPermalink(rctx request.CTX, post *model.Post,
// In case the user does have permission to read, we set the metadata back.
// Note that this is the return value to the post creator, and has nothing to do
// with the content of the websocket broadcast to that user or any other.
if a.HasPermissionToReadChannel(rctx, post.UserId, permalinkPreviewedChannel) {
// We also don't check the membership for the previewed post, since
// the broadcast handler will create the audit events if needed.
if ok, _ := a.HasPermissionToReadChannel(rctx, post.UserId, permalinkPreviewedChannel); ok {
post.AddProp(model.PostPropsPreviewedPost, previewProp)
post.Metadata.Embeds = append(post.Metadata.Embeds, &model.PostEmbed{Type: model.PostEmbedPermalink, Data: permalinkPreviewedPost})
}
@@ -954,39 +973,39 @@ func (a *App) setupBroadcastHookForPermalink(rctx request.CTX, post *model.Post,
return nil
}
func (a *App) PatchPost(c request.CTX, postID string, patch *model.PostPatch, patchPostOptions *model.UpdatePostOptions) (*model.Post, *model.AppError) {
func (a *App) PatchPost(c request.CTX, postID string, patch *model.PostPatch, patchPostOptions *model.UpdatePostOptions) (*model.Post, bool, *model.AppError) {
if patchPostOptions == nil {
patchPostOptions = model.DefaultUpdatePostOptions()
}
post, err := a.GetSinglePost(c, postID, false)
if err != nil {
return nil, err
return nil, false, err
}
channel, err := a.GetChannel(c, post.ChannelId)
if err != nil {
return nil, err
return nil, false, err
}
if channel.DeleteAt != 0 {
err = model.NewAppError("PatchPost", "api.post.patch_post.can_not_update_post_in_deleted.error", nil, "", http.StatusBadRequest)
return nil, err
return nil, false, err
}
if !a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseChannelMentions) {
if ok, _ := a.HasPermissionToChannel(c, post.UserId, post.ChannelId, model.PermissionUseChannelMentions); !ok {
patch.DisableMentionHighlights()
}
post.Patch(patch)
patchPostOptions.SafeUpdate = false
updatedPost, err := a.UpdatePost(c, post, patchPostOptions)
updatedPost, isMemberForPreviews, err := a.UpdatePost(c, post, patchPostOptions)
if err != nil {
return nil, err
return nil, false, err
}
return updatedPost, nil
return updatedPost, isMemberForPreviews, nil
}
func (a *App) GetPostsPage(options model.GetPostsOptions) (*model.PostList, *model.AppError) {
@@ -1715,13 +1734,13 @@ func (a *App) SearchPostsInTeam(teamID string, paramsList []*model.SearchParams)
})
}
func (a *App) SearchPostsForUser(c request.CTX, terms string, userID string, teamID string, isOrSearch bool, includeDeletedChannels bool, timeZoneOffset int, page, perPage int) (*model.PostSearchResults, *model.AppError) {
func (a *App) SearchPostsForUser(c request.CTX, terms string, userID string, teamID string, isOrSearch bool, includeDeletedChannels bool, timeZoneOffset int, page, perPage int) (*model.PostSearchResults, bool, *model.AppError) {
var postSearchResults *model.PostSearchResults
paramsList := model.ParseSearchParams(strings.TrimSpace(terms), timeZoneOffset)
includeDeleted := includeDeletedChannels && *a.Config().TeamSettings.ExperimentalViewArchivedChannels
if !*a.Config().ServiceSettings.EnablePostSearch {
return nil, model.NewAppError("SearchPostsForUser", "store.sql_post.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v", teamID, userID), http.StatusNotImplemented)
return nil, false, model.NewAppError("SearchPostsForUser", "store.sql_post.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v", teamID, userID), http.StatusNotImplemented)
}
finalParamsList := []*model.SearchParams{}
@@ -1748,7 +1767,7 @@ func (a *App) SearchPostsForUser(c request.CTX, terms string, userID string, tea
// If the processed search params are empty, return empty search results.
if len(finalParamsList) == 0 {
return model.MakePostSearchResults(model.NewPostList(), nil), nil
return model.MakePostSearchResults(model.NewPostList(), nil), true, nil
}
postSearchResults, err := a.Srv().Store().Post().SearchPostsForUser(c, finalParamsList, userID, teamID, page, perPage)
@@ -1756,26 +1775,27 @@ func (a *App) SearchPostsForUser(c request.CTX, terms string, userID string, tea
var appErr *model.AppError
switch {
case errors.As(err, &appErr):
return nil, appErr
return nil, false, appErr
default:
return nil, model.NewAppError("SearchPostsForUser", "app.post.search.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
return nil, false, model.NewAppError("SearchPostsForUser", "app.post.search.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
}
if appErr := a.filterInaccessiblePosts(postSearchResults.PostList, filterPostOptions{assumeSortedCreatedAt: true}); appErr != nil {
return nil, appErr
return nil, false, appErr
}
if appErr := a.FilterPostsByChannelPermissions(c, postSearchResults.PostList, userID); appErr != nil {
return nil, appErr
allPostHaveMembership, appErr := a.FilterPostsByChannelPermissions(c, postSearchResults.PostList, userID)
if appErr != nil {
return nil, false, appErr
}
return postSearchResults, nil
return postSearchResults, allPostHaveMembership, nil
}
func (a *App) FilterPostsByChannelPermissions(rctx request.CTX, postList *model.PostList, userID string) *model.AppError {
func (a *App) FilterPostsByChannelPermissions(rctx request.CTX, postList *model.PostList, userID string) (bool, *model.AppError) {
if postList == nil || postList.Posts == nil || len(postList.Posts) == 0 {
return nil
return true, nil // On an empty post list, we consider all posts as having membership
}
channels := make(map[string]*model.Channel)
@@ -1789,7 +1809,7 @@ func (a *App) FilterPostsByChannelPermissions(rctx request.CTX, postList *model.
channelIDs := slices.Collect(maps.Keys(channels))
channelList, err := a.GetChannels(rctx, channelIDs)
if err != nil && err.StatusCode != http.StatusNotFound {
return err
return false, err
}
for _, channel := range channelList {
channels[channel.Id] = channel
@@ -1799,6 +1819,7 @@ func (a *App) FilterPostsByChannelPermissions(rctx request.CTX, postList *model.
channelReadPermission := make(map[string]bool)
filteredPosts := make(map[string]*model.Post)
filteredOrder := []string{}
allPostHaveMembership := true
for _, postID := range postList.Order {
post, ok := postList.Posts[postID]
@@ -1809,10 +1830,14 @@ func (a *App) FilterPostsByChannelPermissions(rctx request.CTX, postList *model.
if _, ok := channelReadPermission[post.ChannelId]; !ok {
channel := channels[post.ChannelId]
allowed := false
isMember := true
if channel != nil {
allowed = a.HasPermissionToReadChannel(rctx, userID, channel)
allowed, isMember = a.HasPermissionToReadChannel(rctx, userID, channel)
}
channelReadPermission[post.ChannelId] = allowed
if allowed {
allPostHaveMembership = allPostHaveMembership && isMember
}
}
if channelReadPermission[post.ChannelId] {
@@ -1824,7 +1849,7 @@ func (a *App) FilterPostsByChannelPermissions(rctx request.CTX, postList *model.
postList.Posts = filteredPosts
postList.Order = filteredOrder
return nil
return allPostHaveMembership, nil
}
func (a *App) GetFileInfosForPostWithMigration(rctx request.CTX, postID string, includeDeleted bool) ([]*model.FileInfo, *model.AppError) {
@@ -2176,28 +2201,29 @@ func (a *App) GetThreadMembershipsForUser(userID, teamID string) ([]*model.Threa
return a.Srv().Store().Thread().GetMembershipsForUser(userID, teamID)
}
func (a *App) GetPostIfAuthorized(c request.CTX, postID string, session *model.Session, includeDeleted bool) (*model.Post, *model.AppError) {
func (a *App) GetPostIfAuthorized(c request.CTX, postID string, session *model.Session, includeDeleted bool) (*model.Post, *model.AppError, bool) {
post, err := a.GetSinglePost(c, postID, includeDeleted)
if err != nil {
return nil, err
return nil, err, false
}
channel, err := a.GetChannel(c, post.ChannelId)
if err != nil {
return nil, err
return nil, err, false
}
if !a.SessionHasPermissionToReadChannel(c, *session, channel) {
ok, isMember := a.SessionHasPermissionToReadChannel(c, *session, channel)
if !ok {
if channel.Type == model.ChannelTypeOpen && !*a.Config().ComplianceSettings.Enable {
if !a.SessionHasPermissionToTeam(*session, channel.TeamId, model.PermissionReadPublicChannel) {
return nil, model.MakePermissionError(session, []*model.Permission{model.PermissionReadPublicChannel})
return nil, model.MakePermissionError(session, []*model.Permission{model.PermissionReadPublicChannel}), false
}
} else {
return nil, model.MakePermissionError(session, []*model.Permission{model.PermissionReadChannelContent})
return nil, model.MakePermissionError(session, []*model.Permission{model.PermissionReadChannelContent}), false
}
}
return post, nil
return post, nil, isMember
}
// GetPostsByIds response bool value indicates, if the post is inaccessible due to cloud plan's limit.
@@ -2380,7 +2406,7 @@ func (a *App) CheckPostReminders(rctx request.CTX) {
},
}
if _, err := a.CreatePost(request.EmptyContext(a.Log()), dm, ch, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(request.EmptyContext(a.Log()), dm, ch, model.CreatePostFlags{SetOnline: true}); err != nil {
rctx.Logger().Error("Failed to post reminder message", mlog.Err(err))
}
}
@@ -2448,9 +2474,9 @@ func (a *App) GetPostInfo(c request.CTX, postID string) (*model.PostInfo, *model
if channel.Type == model.ChannelTypeOpen {
hasPermissionToAccessChannel = true
} else if channel.Type == model.ChannelTypePrivate {
hasPermissionToAccessChannel = a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionManagePrivateChannelMembers)
hasPermissionToAccessChannel, _ = a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionManagePrivateChannelMembers)
} else if channel.Type == model.ChannelTypeDirect || channel.Type == model.ChannelTypeGroup {
hasPermissionToAccessChannel = a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionReadChannelContent)
hasPermissionToAccessChannel, _ = a.HasPermissionToChannel(c, userID, channel.Id, model.PermissionReadChannelContent)
}
}
@@ -2567,7 +2593,7 @@ func (a *App) ValidateMoveOrCopy(c request.CTX, wpl *model.WranglerPostList, ori
return nil
}
func (a *App) CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, targetChannel *model.Channel) (*model.Post, *model.AppError) {
func (a *App) CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, targetChannel *model.Channel) (*model.Post, bool, *model.AppError) {
var appErr *model.AppError
var newRootPost *model.Post
@@ -2587,15 +2613,15 @@ func (a *App) CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, t
for _, fileID := range post.FileIds {
oldFileInfo, appErr = a.GetFileInfo(c, fileID)
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
fileBytes, appErr = a.GetFile(c, fileID)
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
newFileInfo, appErr = a.UploadFile(c, fileBytes, targetChannel.Id, oldFileInfo.Name)
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
newFileIDs = append(newFileIDs, newFileInfo.Id)
@@ -2605,6 +2631,8 @@ func (a *App) CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, t
}
}
var isMemberForPreviews bool
for i, post := range wpl.Posts {
var reactions []*model.Reaction
@@ -2620,16 +2648,16 @@ func (a *App) CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, t
newPost.ChannelId = targetChannel.Id
if i == 0 {
newPost, appErr = a.CreatePost(c, newPost, targetChannel, model.CreatePostFlags{})
newPost, isMemberForPreviews, appErr = a.CreatePost(c, newPost, targetChannel, model.CreatePostFlags{})
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
newRootPost = newPost.Clone()
} else {
newPost.RootId = newRootPost.Id
newPost, appErr = a.CreatePost(c, newPost, targetChannel, model.CreatePostFlags{})
newPost, _, appErr = a.CreatePost(c, newPost, targetChannel, model.CreatePostFlags{})
if appErr != nil {
return nil, appErr
return nil, false, appErr
}
}
@@ -2643,7 +2671,7 @@ func (a *App) CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, t
}
}
return newRootPost, nil
return newRootPost, isMemberForPreviews, nil
}
func (a *App) MoveThread(c request.CTX, postID string, sourceChannelID, channelID string, user *model.User) *model.AppError {
@@ -2689,7 +2717,7 @@ func (a *App) MoveThread(c request.CTX, postID string, sourceChannelID, channelI
// To simulate the move, we first copy the original messages(s) to the
// new channel and later delete the original messages(s).
newRootPost, appErr := a.CopyWranglerPostlist(c, wpl, targetChannel)
newRootPost, _, appErr := a.CopyWranglerPostlist(c, wpl, targetChannel)
if appErr != nil {
return appErr
}
@@ -2702,7 +2730,7 @@ func (a *App) MoveThread(c request.CTX, postID string, sourceChannelID, channelI
ephemeralPostProps := model.StringInterface{
"TranslationID": "app.post.move_thread.from_another_channel",
}
_, appErr = a.CreatePost(c, &model.Post{
_, _, appErr = a.CreatePost(c, &model.Post{
UserId: user.Id,
Type: model.PostTypeWrangler,
RootId: newRootPost.Id,
@@ -2750,7 +2778,7 @@ func (a *App) MoveThread(c request.CTX, postID string, sourceChannelID, channelI
ephemeralPostProps["NumMessages"] = wpl.NumPosts()
_, appErr = a.CreatePost(c, &model.Post{
_, _, appErr = a.CreatePost(c, &model.Post{
UserId: user.Id,
Type: model.PostTypeWrangler,
ChannelId: originalChannel.Id,
@@ -2871,7 +2899,8 @@ func (a *App) SendTestMessage(c request.CTX, userID string) (*model.Post, *model
UserId: bot.UserId,
}
post, err = a.CreatePost(c, post, channel, model.CreatePostFlags{ForceNotification: true})
// We don't check the preview membership because the test message does not send a link to a different post.
post, _, err = a.CreatePost(c, post, channel, model.CreatePostFlags{ForceNotification: true})
if err != nil {
return nil, model.NewAppError("SendTestMessage", "app.notifications.send_test_message.errors.create_post", nil, "", http.StatusInternalServerError).Wrap(err)
}

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

@@ -24,7 +24,7 @@ func testSaveAcknowledgementForPost(t *testing.T) {
defer th.TearDown()
t.Run("save acknowledgment for post should save acknowledgement", func(t *testing.T) {
post, err := th.App.CreatePostAsUser(th.Context, &model.Post{
post, _, err := th.App.CreatePostAsUser(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "message",
@@ -41,7 +41,7 @@ func testSaveAcknowledgementForPost(t *testing.T) {
})
t.Run("saving acknowledgment should update the post's update_at", func(t *testing.T) {
post, err := th.App.CreatePostAsUser(th.Context, &model.Post{
post, _, err := th.App.CreatePostAsUser(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "message",
@@ -65,7 +65,7 @@ func testDeleteAcknowledgementForPost(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
defer th.TearDown()
post, err1 := th.App.CreatePostAsUser(th.Context, &model.Post{
post, _, err1 := th.App.CreatePostAsUser(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
CreateAt: model.GetMillis(),
@@ -138,7 +138,7 @@ func testGetAcknowledgementsForPostList(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
defer th.TearDown()
p1, err := th.App.CreatePostAsUser(th.Context, &model.Post{
p1, _, err := th.App.CreatePostAsUser(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
CreateAt: model.GetMillis(),
@@ -146,7 +146,7 @@ func testGetAcknowledgementsForPostList(t *testing.T) {
}, "", true)
require.Nil(t, err)
p2, err := th.App.CreatePostAsUser(th.Context, &model.Post{
p2, _, err := th.App.CreatePostAsUser(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
CreateAt: model.GetMillis(),
@@ -154,7 +154,7 @@ func testGetAcknowledgementsForPostList(t *testing.T) {
}, "", true)
require.Nil(t, err)
p3, err := th.App.CreatePostAsUser(th.Context, &model.Post{
p3, _, err := th.App.CreatePostAsUser(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
CreateAt: model.GetMillis(),

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

@@ -228,50 +228,48 @@ func removeEmbeddedPostsFromMetadata(post *model.Post) {
post.Metadata.Embeds = newEmbeds
}
func (a *App) sanitizePostMetadataForUserAndChannel(c request.CTX, post *model.Post, previewedPost *model.PreviewPost, previewedChannel *model.Channel, userID string) *model.Post {
if post.Metadata == nil || len(post.Metadata.Embeds) == 0 || previewedPost == nil {
return post
}
if previewedChannel != nil && !a.HasPermissionToReadChannel(c, userID, previewedChannel) {
removePermalinkMetadataFromPost(post)
}
return post
}
func (a *App) SanitizePostMetadataForUser(c request.CTX, post *model.Post, userID string) (*model.Post, *model.AppError) {
func (a *App) SanitizePostMetadataForUser(c request.CTX, post *model.Post, userID string) (*model.Post, bool, *model.AppError) {
if post.Metadata == nil || len(post.Metadata.Embeds) == 0 {
return post, nil
return post, true, nil
}
previewPost := post.GetPreviewPost()
if previewPost == nil {
return post, nil
return post, true, nil
}
previewedChannel, err := a.GetChannel(c, previewPost.Post.ChannelId)
if err != nil {
return nil, err
return nil, false, err
}
if previewedChannel != nil && !a.HasPermissionToReadChannel(c, userID, previewedChannel) {
removePermalinkMetadataFromPost(post)
isMember := true
if previewedChannel != nil {
var hasPermission bool
hasPermission, isMember = a.HasPermissionToReadChannel(c, userID, previewedChannel)
if !hasPermission {
removePermalinkMetadataFromPost(post)
// Since we remove the permalink metadata, we return true
isMember = true
}
}
return post, nil
return post, isMember, nil
}
func (a *App) SanitizePostListMetadataForUser(c request.CTX, postList *model.PostList, userID string) (*model.PostList, *model.AppError) {
func (a *App) SanitizePostListMetadataForUser(c request.CTX, postList *model.PostList, userID string) (*model.PostList, bool, *model.AppError) {
clonedPostList := postList.Clone()
allPreviewsHaveMembership := true
for postID, post := range clonedPostList.Posts {
sanitizedPost, err := a.SanitizePostMetadataForUser(c, post, userID)
sanitizedPost, isMember, err := a.SanitizePostMetadataForUser(c, post, userID)
if err != nil {
return nil, err
return nil, false, err
}
clonedPostList.Posts[postID] = sanitizedPost
allPreviewsHaveMembership = allPreviewsHaveMembership && isMember
}
return clonedPostList, nil
return clonedPostList, allPreviewsHaveMembership, nil
}
func (a *App) getFileMetadataForPost(rctx request.CTX, post *model.Post, fromMaster bool) ([]*model.FileInfo, int64, *model.AppError) {

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

@@ -194,7 +194,7 @@ func TestPreparePostForClient(t *testing.T) {
fileInfo.ChannelId = th.BasicChannel.Id
require.Nil(t, err)
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
FileIds: []string{fileInfo.Id},
@@ -222,7 +222,7 @@ func TestPreparePostForClient(t *testing.T) {
emoji := th.CreateEmoji()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: ":" + emoji.Name + ": :taco:",
@@ -266,7 +266,7 @@ func TestPreparePostForClient(t *testing.T) {
emoji3 := th.CreateEmoji()
emoji4 := th.CreateEmoji()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: ":" + emoji3.Name + ": :taco:",
@@ -307,7 +307,7 @@ func TestPreparePostForClient(t *testing.T) {
*cfg.ServiceSettings.EnablePostIconOverride = override
})
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "Test",
@@ -364,7 +364,7 @@ func TestPreparePostForClient(t *testing.T) {
th := setup(t)
defer th.TearDown()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: fmt.Sprintf("This is ![our logo](%s/test-image2.png) and ![our icon](%s/test-image1.png)", server.URL, server.URL),
@@ -393,7 +393,7 @@ func TestPreparePostForClient(t *testing.T) {
th := setup(t)
defer th.TearDown()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "some post",
@@ -426,7 +426,7 @@ func TestPreparePostForClient(t *testing.T) {
th := setup(t)
defer th.TearDown()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: `This is our logo: ` + server.URL + `/test-image2.png
@@ -462,7 +462,7 @@ func TestPreparePostForClient(t *testing.T) {
th := setup(t)
defer th.TearDown()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: `This is our web page: ` + server.URL,
@@ -537,7 +537,7 @@ func TestPreparePostForClient(t *testing.T) {
}
prepost.AddProp(model.PostPropsUnsafeLinks, "true")
post, err := th.App.CreatePost(th.Context, prepost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, prepost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
clientPost := th.App.PreparePostForClient(th.Context, post, false, false, false)
@@ -553,7 +553,7 @@ func TestPreparePostForClient(t *testing.T) {
Message: `Bla bla bla: ` + fmt.Sprintf(tc.link, server.URL),
}
post, err := th.App.CreatePost(th.Context, prepost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, err := th.App.CreatePost(th.Context, prepost, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, err)
clientPost := th.App.PreparePostForClient(th.Context, post, false, false, false)
@@ -569,7 +569,7 @@ func TestPreparePostForClient(t *testing.T) {
th := setup(t)
defer th.TearDown()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Props: map[string]any{
@@ -610,7 +610,7 @@ func TestPreparePostForClient(t *testing.T) {
fileInfo, err := th.App.DoUploadFile(th.Context, time.Now(), th.BasicTeam.Id, th.BasicChannel.Id, th.BasicUser.Id, "test.txt", []byte("test"), true)
require.Nil(t, err)
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
Message: "test",
FileIds: []string{fileInfo.Id},
UserId: th.BasicUser.Id,
@@ -645,7 +645,7 @@ func TestPreparePostForClient(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id
referencedPost, err := th.App.CreatePost(th.Context, &model.Post{
referencedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "hello world",
@@ -655,7 +655,7 @@ func TestPreparePostForClient(t *testing.T) {
link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id)
previewPost, err := th.App.CreatePost(th.Context, &model.Post{
previewPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: link,
@@ -703,7 +703,7 @@ func TestPreparePostForClient(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
referencedPost, err := th.App.CreatePost(th.Context, &model.Post{
referencedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: testCase.Channel.Id,
Message: "hello world",
@@ -713,7 +713,7 @@ func TestPreparePostForClient(t *testing.T) {
link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id)
previewPost, err := th.App.CreatePost(th.Context, &model.Post{
previewPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: link,
@@ -741,7 +741,7 @@ func TestPreparePostForClient(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id
referencedPost, err := th.App.CreatePost(th.Context, &model.Post{
referencedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: `This is our logo: ` + server.URL + `/test-image2.png`,
@@ -751,7 +751,7 @@ func TestPreparePostForClient(t *testing.T) {
link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id)
previewPost, err := th.App.CreatePost(th.Context, &model.Post{
previewPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: link,
@@ -778,7 +778,7 @@ func TestPreparePostForClient(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id
nestedPermalinkPost, err := th.App.CreatePost(th.Context, &model.Post{
nestedPermalinkPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: `This is our logo: ` + server.URL + `/test-image2.png`,
@@ -788,7 +788,7 @@ func TestPreparePostForClient(t *testing.T) {
nestedLink := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, nestedPermalinkPost.Id)
referencedPost, err := th.App.CreatePost(th.Context, &model.Post{
referencedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: nestedLink,
@@ -798,7 +798,7 @@ func TestPreparePostForClient(t *testing.T) {
link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id)
previewPost, err := th.App.CreatePost(th.Context, &model.Post{
previewPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: link,
@@ -825,7 +825,7 @@ func TestPreparePostForClient(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id
referencedPost, err := th.App.CreatePost(th.Context, &model.Post{
referencedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "hello world",
@@ -834,7 +834,7 @@ func TestPreparePostForClient(t *testing.T) {
link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id)
previewPost, err := th.App.CreatePost(th.Context, &model.Post{
previewPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: link,
@@ -951,7 +951,7 @@ func testProxyOpenGraphImage(t *testing.T, th *TestHelper, shouldProxy bool) {
serverURL = server.URL
defer server.Close()
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: `This is our web page: ` + server.URL,
@@ -2963,131 +2963,6 @@ func TestContainsPermalink(t *testing.T) {
}
}
func TestSanitizePostMetadataForUserAndChannel(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
defer th.TearDown()
enableLinkPreviews := *th.App.Config().ServiceSettings.EnableLinkPreviews
siteURL := *th.App.Config().ServiceSettings.SiteURL
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.ServiceSettings.EnableLinkPreviews = &enableLinkPreviews
cfg.ServiceSettings.SiteURL = &siteURL
})
}()
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.EnableLinkPreviews = true
*cfg.ServiceSettings.SiteURL = "http://mymattermost.com"
})
t.Run("should not preview for users with no access to the channel", func(t *testing.T) {
directChannel, err := th.App.createDirectChannel(th.Context, th.BasicUser.Id, th.BasicUser2.Id)
assert.Nil(t, err)
userID := model.NewId()
post := &model.Post{
Id: userID,
Metadata: &model.PostMetadata{
Embeds: []*model.PostEmbed{
{
Type: model.PostEmbedPermalink,
Data: &model.PreviewPost{
PostID: "permalink_post_id",
Post: &model.Post{
Id: "permalink_post_id",
Message: "permalink post message",
ChannelId: directChannel.Id,
},
},
},
},
},
}
previewedPost := model.NewPreviewPost(post, th.BasicTeam, directChannel)
actual := th.App.sanitizePostMetadataForUserAndChannel(th.Context, post, previewedPost, directChannel, th.BasicUser2.Id)
assert.NotNil(t, actual.Metadata.Embeds[0].Data)
guestID := model.NewId()
guest := &model.User{
Email: "success+" + guestID + "@simulator.amazonses.com",
Username: "un_" + guestID,
Nickname: "nn_" + guestID,
Password: "Password1",
EmailVerified: true,
}
guest, appErr := th.App.CreateGuest(th.Context, guest)
require.Nil(t, appErr)
actual = th.App.sanitizePostMetadataForUserAndChannel(th.Context, post, previewedPost, directChannel, guest.Id)
assert.Len(t, actual.Metadata.Embeds, 0)
})
t.Run("should not preview for archived channels", func(t *testing.T) {
experimentalViewArchivedChannels := *th.App.Config().TeamSettings.ExperimentalViewArchivedChannels
defer func() {
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.TeamSettings.ExperimentalViewArchivedChannels = &experimentalViewArchivedChannels
})
}()
publicChannel, err := th.App.CreateChannel(th.Context, &model.Channel{
Name: model.NewId(),
Type: model.ChannelTypeOpen,
TeamId: th.BasicTeam.Id,
CreatorId: th.SystemAdminUser.Id,
}, true)
require.Nil(t, err)
require.NotEmpty(t, publicChannel.Id)
err = th.App.DeleteChannel(th.Context, publicChannel, th.SystemAdminUser.Id)
require.Nil(t, err)
publicChannel, err = th.App.GetChannel(th.Context, publicChannel.Id)
require.Nil(t, err)
require.NotEmpty(t, publicChannel.Id)
require.NotEqual(t, 0, publicChannel.DeleteAt)
post := &model.Post{
Id: th.BasicUser.Id,
Metadata: &model.PostMetadata{
Embeds: []*model.PostEmbed{
{
Type: model.PostEmbedPermalink,
Data: &model.PreviewPost{
PostID: "permalink_post_id",
Post: &model.Post{
Id: "permalink_post_id",
Message: "permalink post message",
ChannelId: publicChannel.Id,
},
},
},
},
},
}
previewedPost := model.NewPreviewPost(post, th.BasicTeam, publicChannel)
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.TeamSettings.ExperimentalViewArchivedChannels = true
})
actual := th.App.sanitizePostMetadataForUserAndChannel(th.Context, post, previewedPost, publicChannel, th.BasicUser.Id)
assert.NotNil(t, actual.Metadata.Embeds[0].Data)
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.TeamSettings.ExperimentalViewArchivedChannels = false
})
actual = th.App.sanitizePostMetadataForUserAndChannel(th.Context, post, previewedPost, publicChannel, th.BasicUser.Id)
assert.Len(t, actual.Metadata.Embeds, 0)
})
}
func TestSanitizePostMetaDataForAudit(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t).InitBasic()
@@ -3099,7 +2974,7 @@ func TestSanitizePostMetaDataForAudit(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id
referencedPost, err := th.App.CreatePost(th.Context, &model.Post{
referencedPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: "hello world",
@@ -3109,7 +2984,7 @@ func TestSanitizePostMetaDataForAudit(t *testing.T) {
link := fmt.Sprintf("%s/%s/pl/%s", *th.App.Config().ServiceSettings.SiteURL, th.BasicTeam.Name, referencedPost.Id)
previewPost, err := th.App.CreatePost(th.Context, &model.Post{
previewPost, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: th.BasicUser.Id,
ChannelId: th.BasicChannel.Id,
Message: link,
@@ -3202,15 +3077,16 @@ func TestSanitizePostMetadataForUser(t *testing.T) {
},
}
sanitizedPost, err := th.App.SanitizePostMetadataForUser(th.Context, post, th.BasicUser.Id)
sanitizedPost, isMemberForPreviews, err := th.App.SanitizePostMetadataForUser(th.Context, post, th.BasicUser.Id)
require.Nil(t, err)
require.NotNil(t, sanitizedPost)
require.Equal(t, 1, len(sanitizedPost.Metadata.Embeds))
require.Equal(t, model.PostEmbedLink, sanitizedPost.Metadata.Embeds[0].Type)
require.True(t, isMemberForPreviews)
})
t.Run("should remove embeds for archived channels if the config does not allow it", func(t *testing.T) {
t.Run("should not remove embeds for archived channels", func(t *testing.T) {
publicChannel, err := th.App.CreateChannel(th.Context, &model.Channel{
Name: model.NewId(),
Type: model.ChannelTypeOpen,
@@ -3264,7 +3140,7 @@ func TestSanitizePostMetadataForUser(t *testing.T) {
*cfg.TeamSettings.ExperimentalViewArchivedChannels = true
})
sanitizedPost, err := th.App.SanitizePostMetadataForUser(th.Context, post, th.BasicUser.Id)
sanitizedPost, _, err := th.App.SanitizePostMetadataForUser(th.Context, post, th.BasicUser.Id)
require.Nil(t, err)
require.NotNil(t, sanitizedPost)
@@ -3275,7 +3151,7 @@ func TestSanitizePostMetadataForUser(t *testing.T) {
*cfg.TeamSettings.ExperimentalViewArchivedChannels = false
})
sanitizedPost, err = th.App.SanitizePostMetadataForUser(th.Context, post, th.BasicUser.Id)
sanitizedPost, _, err = th.App.SanitizePostMetadataForUser(th.Context, post, th.BasicUser.Id)
require.Nil(t, err)
require.NotNil(t, sanitizedPost)

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

@@ -99,7 +99,7 @@ func postHardenedModeCheck(hardenedModeEnabled, isIntegration bool, props model.
func userCreatePostPermissionCheckWithApp(c request.CTX, a *App, userId, channelId string) *model.AppError {
hasPermission := false
if a.HasPermissionToChannel(c, userId, channelId, model.PermissionCreatePost) {
if ok, _ := a.HasPermissionToChannel(c, userId, channelId, model.PermissionCreatePost); ok {
hasPermission = true
} else if channel, err := a.GetChannel(c, channelId); err == nil {
// Temporary permission check method until advanced permissions, please do not copy

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

@@ -219,7 +219,7 @@ func TestSendPersistentNotifications(t *testing.T) {
},
},
}
_, appErr = th.App.CreatePost(th.Context, p1, th.BasicChannel, model.CreatePostFlags{})
_, _, appErr = th.App.CreatePost(th.Context, p1, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
err := th.App.SendPersistentNotifications()
@@ -263,7 +263,7 @@ func TestSendPersistentNotificationsBotSender(t *testing.T) {
// Simulate old timestamp so persistent notifications are sent right away
CreateAt: time.Now().Add(-5 * time.Minute).UnixMilli(),
}
post, appErr = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{})
post, _, appErr = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
assert.EventuallyWithT(t, func(c *assert.CollectT) {
@@ -314,7 +314,7 @@ func TestSendPersistentNotificationsBotSenderNotInChannel(t *testing.T) {
},
CreateAt: time.Now().Add(-5 * time.Minute).UnixMilli(),
}
post, appErr = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
post, _, appErr = th.App.CreatePost(th.Context, post, th.BasicChannel, model.CreatePostFlags{SetOnline: true})
require.Nil(t, appErr)
assert.EventuallyWithT(t, func(c *assert.CollectT) {

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

@@ -13,7 +13,7 @@ import (
"github.com/mattermost/mattermost/server/public/shared/request"
)
func (a *App) RestorePostVersion(c request.CTX, userID, postID, restoreVersionID string) (*model.Post, *model.AppError) {
func (a *App) RestorePostVersion(c request.CTX, userID, postID, restoreVersionID string) (*model.Post, bool, *model.AppError) {
toRestorePostVersion, err := a.Srv().Store().Post().GetSingle(c, restoreVersionID, true)
if err != nil {
var statusCode int
@@ -25,24 +25,24 @@ func (a *App) RestorePostVersion(c request.CTX, userID, postID, restoreVersionID
statusCode = http.StatusInternalServerError
}
return nil, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.get_single.app_error", nil, err.Error(), statusCode)
return nil, false, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.get_single.app_error", nil, err.Error(), statusCode)
}
// restoreVersionID needs to be an old version of postID
// this is only a safeguard and this should never happen in practice.
if toRestorePostVersion.OriginalId != postID {
return nil, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.not_an_history_item.app_error", nil, "", http.StatusBadRequest)
return nil, false, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.not_an_history_item.app_error", nil, "", http.StatusBadRequest)
}
// the user needs to be the author of the post
// this is only a safeguard and this should never happen in practice.
if toRestorePostVersion.UserId != userID {
return nil, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.not_allowed.app_error", nil, "", http.StatusForbidden)
return nil, false, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.not_allowed.app_error", nil, "", http.StatusForbidden)
}
// the old version of post needs to be a deleted post
if toRestorePostVersion.DeleteAt == 0 {
return nil, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.not_valid_post_history_item.app_error", nil, "", http.StatusBadRequest)
return nil, false, model.NewAppError("RestorePostVersion", "app.post.restore_post_version.not_valid_post_history_item.app_error", nil, "", http.StatusBadRequest)
}
postPatch := &model.PostPatch{

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

@@ -34,9 +34,10 @@ func TestRestorePostVersion(t *testing.T) {
require.Equal(t, "new message 2", editHistory[0].Message)
// now we'll restore a post version
restoredPost, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, editHistory[0].Id)
restoredPost, isMemberForPreview, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, editHistory[0].Id)
require.Nil(t, appErr)
require.Equal(t, "new message 2", restoredPost.Message)
require.True(t, isMemberForPreview)
// verify from database
fetchedPost, err = th.App.Srv().Store().Post().GetSingle(th.Context, post.Id, true)
@@ -85,10 +86,11 @@ func TestRestorePostVersion(t *testing.T) {
require.Equal(t, 1, len(editHistory[1].FileIds))
// now we'll restore a post version
restoredPost, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, editHistory[1].Id)
restoredPost, isMemberForPreview, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, editHistory[1].Id)
require.Nil(t, appErr)
require.Equal(t, "original message", restoredPost.Message)
require.Equal(t, 1, len(restoredPost.FileIds))
require.True(t, isMemberForPreview)
// verify from database
fetchedPost, err = th.App.Srv().Store().Post().GetSingle(th.Context, post.Id, true)
@@ -125,7 +127,7 @@ func TestRestorePostVersion(t *testing.T) {
// now we'll restore a post version
otherPost := th.CreatePost(th.BasicChannel)
restoredPost, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, otherPost.Id)
restoredPost, _, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, otherPost.Id)
require.NotNil(t, appErr)
require.Equal(t, http.StatusBadRequest, appErr.StatusCode)
require.Equal(t, "app.post.restore_post_version.not_an_history_item.app_error", appErr.Id)
@@ -138,7 +140,7 @@ func TestRestorePostVersion(t *testing.T) {
})
t.Run("should return an error if the post does not exist", func(t *testing.T) {
restoredPost, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, model.NewId(), model.NewId())
restoredPost, _, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, model.NewId(), model.NewId())
require.NotNil(t, appErr)
require.Equal(t, http.StatusNotFound, appErr.StatusCode)
require.Equal(t, "app.post.restore_post_version.get_single.app_error", appErr.Id)
@@ -150,7 +152,7 @@ func TestRestorePostVersion(t *testing.T) {
// now we'll restore a post version
invalidRestorePostIUd := model.NewId()
restoredPost, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, invalidRestorePostIUd)
restoredPost, _, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, invalidRestorePostIUd)
require.NotNil(t, appErr)
require.Equal(t, http.StatusNotFound, appErr.StatusCode)
require.Equal(t, "app.post.restore_post_version.get_single.app_error", appErr.Id)
@@ -172,7 +174,7 @@ func TestRestorePostVersion(t *testing.T) {
require.Equal(t, "other post original message", otherPostEditHistory[0].Message)
// we'll specify post's ID and other post's version ID, his should fail
restoredPost, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, otherPostEditHistory[0].Id)
restoredPost, _, appErr := th.App.RestorePostVersion(th.Context, th.BasicUser.Id, post.Id, otherPostEditHistory[0].Id)
require.NotNil(t, appErr)
require.Equal(t, "app.post.restore_post_version.not_an_history_item.app_error", appErr.Id)
require.Equal(t, http.StatusBadRequest, appErr.StatusCode)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@@ -111,7 +111,7 @@ func TestSharedChannelSyncForReactionActions(t *testing.T) {
channel := th.CreateChannel(th.Context, th.BasicTeam, WithShared(true))
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: user.Id,
ChannelId: channel.Id,
Message: "Hello folks",
@@ -146,7 +146,7 @@ func TestSharedChannelSyncForReactionActions(t *testing.T) {
channel := th.CreateChannel(th.Context, th.BasicTeam, WithShared(true))
post, err := th.App.CreatePost(th.Context, &model.Post{
post, _, err := th.App.CreatePost(th.Context, &model.Post{
UserId: user.Id,
ChannelId: channel.Id,
Message: "Hello folks",

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

@@ -136,7 +136,7 @@ func (a *App) SendReportToUser(rctx request.CTX, job *model.Job, format string)
FileIds: []string{fileInfo.Id},
}
_, err = a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true})
_, _, err = a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true})
return err
}
@@ -250,7 +250,7 @@ func (a *App) StartUsersBatchExport(rctx request.CTX, ro *model.UserReportOption
UserId: systemBot.UserId,
}
if _, err := a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
rctx.Logger().Error("Failed to post batch export message", mlog.Err(err))
}
})

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

@@ -195,7 +195,7 @@ func (a *App) postScheduledPost(rctx request.CTX, scheduledPost *model.Scheduled
TriggerWebhooks: true,
SetOnline: false,
}
_, appErr = a.CreatePost(rctx, post, channel, createPostFlags)
_, _, appErr = a.CreatePost(rctx, post, channel, createPostFlags)
if appErr != nil {
rctx.Logger().Error(
"App.processScheduledPostBatch: failed to post scheduled post",
@@ -454,7 +454,7 @@ func (a *App) notifyUser(rctx request.CTX, userId string, userFailedMessages []*
UserId: systemBot.UserId,
}
if _, err := a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(rctx, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
rctx.Logger().Error("Failed to post notification about failed scheduled messages", mlog.Err(err))
}
}

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

@@ -366,7 +366,7 @@ func TestApp_RemoteUnsharing(t *testing.T) {
UserId: th.BasicUser.Id,
Message: "Test message after remote 1 unshare",
}
_, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
_, _, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{})
require.Nil(t, appErr)
// Get post count after creating the test post but before "remote-initiated unshare"

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

@@ -114,7 +114,7 @@ func (cfg *AutoPostCreator) CreateRandomPostNested(c request.CTX, rootID string)
post.UserId = cfg.UsersToPostFrom[i]
}
}
rpost, err := cfg.a.CreatePostMissingChannel(c, post, true, true)
rpost, _, err := cfg.a.CreatePostMissingChannel(c, post, true, true)
if err != nil {
return nil, err
}

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

@@ -46,7 +46,7 @@ func (*HeaderProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandA
switch channel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelProperties) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelProperties); !ok {
return &model.CommandResponse{
Text: args.T("api.command_channel_header.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
@@ -54,7 +54,7 @@ func (*HeaderProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandA
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelProperties) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelProperties); !ok {
return &model.CommandResponse{
Text: args.T("api.command_channel_header.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,

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

@@ -46,14 +46,14 @@ func (*PurposeProvider) DoCommand(a *app.App, c request.CTX, args *model.Command
switch channel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelProperties) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelProperties); !ok {
return &model.CommandResponse{
Text: args.T("api.command_channel_purpose.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelProperties) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelProperties); !ok {
return &model.CommandResponse{
Text: args.T("api.command_channel_purpose.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,

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

@@ -49,14 +49,14 @@ func (*RenameProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandA
switch channel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelProperties) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelProperties); !ok {
return &model.CommandResponse{
Text: args.T("api.command_channel_rename.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelProperties) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelProperties); !ok {
return &model.CommandResponse{
Text: args.T("api.command_channel_rename.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,

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

@@ -89,7 +89,7 @@ func (*EchoProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArg
time.Sleep(time.Duration(delay) * time.Second)
if _, err := a.CreatePostMissingChannel(c, post, true, true); err != nil {
if _, _, err := a.CreatePostMissingChannel(c, post, true, true); err != nil {
c.Logger().Error("Unable to create /echo post.", mlog.Err(err))
}
})

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

@@ -126,7 +126,7 @@ func (*groupmsgProvider) DoCommand(a *app.App, c request.CTX, args *model.Comman
post.Message = parsedMessage
post.ChannelId = groupChannel.Id
post.UserId = args.UserId
if _, err := a.CreatePostMissingChannel(c, post, true, true); err != nil {
if _, _, err := a.CreatePostMissingChannel(c, post, true, true); err != nil {
return &model.CommandResponse{Text: args.T("api.command_groupmsg.fail.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}
}

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

@@ -274,7 +274,7 @@ func (i *InviteProvider) checkPermissions(a *app.App, c request.CTX, args *model
for _, targetChannel := range targetChannels {
switch targetChannel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, targetChannel.Id, model.PermissionManagePublicChannelMembers) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, targetChannel.Id, model.PermissionManagePublicChannelMembers); !ok {
*resps = append(*resps, args.T("api.command_invite.permission.app_error", map[string]any{
"User": targetUser.Username,
"Channel": targetChannel.Name,
@@ -282,7 +282,7 @@ func (i *InviteProvider) checkPermissions(a *app.App, c request.CTX, args *model
continue
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, targetChannel.Id, model.PermissionManagePrivateChannelMembers) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, targetChannel.Id, model.PermissionManagePrivateChannelMembers); !ok {
if _, err = a.GetChannelMember(c, targetChannel.Id, args.UserId); err == nil {
// User doing the inviting is a member of the channel.
*resps = append(*resps, args.T("api.command_invite.permission.app_error", map[string]any{

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

@@ -55,11 +55,11 @@ func (*JoinProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArg
switch channel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, channel.Id, model.PermissionJoinPublicChannels) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, channel.Id, model.PermissionJoinPublicChannels); !ok {
return &model.CommandResponse{Text: args.T("api.command_join.fail.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, channel.Id, model.PermissionReadChannel) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, channel.Id, model.PermissionReadChannel); !ok {
return &model.CommandResponse{Text: args.T("api.command_join.fail.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}
default:

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

@@ -672,7 +672,7 @@ func (*LoadTestProvider) URLCommand(a *app.App, c request.CTX, args *model.Comma
post.ChannelId = args.ChannelId
post.UserId = args.UserId
if _, err := a.CreatePostMissingChannel(c, post, false, true); err != nil {
if _, _, err := a.CreatePostMissingChannel(c, post, false, true); err != nil {
return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.CommandResponseTypeEphemeral}, err
}
}
@@ -721,7 +721,7 @@ func (*LoadTestProvider) JSONCommand(a *app.App, c request.CTX, args *model.Comm
post.Message = message
}
if _, err := a.CreatePostMissingChannel(c, &post, false, true); err != nil {
if _, _, err := a.CreatePostMissingChannel(c, &post, false, true); err != nil {
return &model.CommandResponse{Text: "Unable to create post", ResponseType: model.CommandResponseTypeEphemeral}, err
}

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

@@ -100,7 +100,7 @@ func (*msgProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs
post.Message = parsedMessage
post.ChannelId = targetChannelID
post.UserId = args.UserId
if _, err = a.CreatePostMissingChannel(c, post, true, true); err != nil {
if _, _, err = a.CreatePostMissingChannel(c, post, true, true); err != nil {
return &model.CommandResponse{Text: args.T("api.command_msg.fail.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}
}

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

@@ -75,14 +75,14 @@ func doCommand(a *app.App, c request.CTX, args *model.CommandArgs, message strin
switch channel.Type {
case model.ChannelTypeOpen:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelMembers) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePublicChannelMembers); !ok {
return &model.CommandResponse{
Text: args.T("api.command_remove.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,
}
}
case model.ChannelTypePrivate:
if !a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelMembers) {
if ok, _ := a.HasPermissionToChannel(c, args.UserId, args.ChannelId, model.PermissionManagePrivateChannelMembers); !ok {
return &model.CommandResponse{
Text: args.T("api.command_remove.permission.app_error"),
ResponseType: model.CommandResponseTypeEphemeral,

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

@@ -344,7 +344,7 @@ func (th *TestHelper) createPost(tb testing.TB, channel *model.Channel) *model.P
CreateAt: model.GetMillis() - 10000,
}
post, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{SetOnline: true})
post, _, appErr := th.App.CreatePost(th.Context, post, channel, model.CreatePostFlags{SetOnline: true})
require.Nil(tb, appErr)
return post
}

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

@@ -1288,7 +1288,7 @@ func (a *App) postLeaveTeamMessage(c request.CTX, user *model.User, channel *mod
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}
@@ -1306,7 +1306,7 @@ func (a *App) postRemoveFromTeamMessage(c request.CTX, user *model.User, channel
},
}
if _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
if _, _, err := a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true}); err != nil {
return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, "", http.StatusInternalServerError).Wrap(err)
}

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

@@ -1187,12 +1187,14 @@ func TestAppUpdateTeamScheme(t *testing.T) {
},
}
// ensure user can update channel properties before applying the scheme
require.True(t, th.App.SessionHasPermissionToChannel(th.Context, session, channel.Id, model.PermissionManagePublicChannelProperties))
ok, _ := th.App.SessionHasPermissionToChannel(th.Context, session, channel.Id, model.PermissionManagePublicChannelProperties)
require.True(t, ok)
// apply the team scheme
team2.SchemeId = &team2Scheme.Id
_, appErr = th.App.UpdateTeamScheme(team2)
require.Nil(t, appErr)
require.False(t, th.App.SessionHasPermissionToChannel(th.Context, session, channel.Id, model.PermissionManagePublicChannelProperties))
ok, _ = th.App.SessionHasPermissionToChannel(th.Context, session, channel.Id, model.PermissionManagePublicChannelProperties)
require.False(t, ok)
}
func TestGetTeamMembers(t *testing.T) {

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

@@ -2895,7 +2895,7 @@ func (a *App) UpdateThreadFollowForUserFromChannelAdd(c request.CTX, userID, tea
}
a.sanitizeProfiles(userThread.Participants, false)
userThread.Post.SanitizeProps()
sanitizedPost, appErr := a.SanitizePostMetadataForUser(c, userThread.Post, userID)
sanitizedPost, isMemberForPreviews, appErr := a.SanitizePostMetadataForUser(c, userThread.Post, userID)
if appErr != nil {
return appErr
}
@@ -2909,6 +2909,16 @@ func (a *App) UpdateThreadFollowForUserFromChannelAdd(c request.CTX, userID, tea
message.Add("previous_unread_replies", int64(0))
message.Add("previous_unread_mentions", int64(0))
auditRec := a.MakeAuditRecord(c, "websocketPost", model.AuditStatusSuccess)
defer a.LogAuditRec(c, auditRec, nil)
model.AddEventParameterToAuditRec(auditRec, "post_id", userThread.Post.Id)
model.AddEventParameterToAuditRec(auditRec, "user_id", userID)
model.AddEventParameterToAuditRec(auditRec, "source", "UpdateThreadFollowForUserFromChannelAdd")
if !isMemberForPreviews {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
auditRec.Success()
a.Publish(message)
return nil
}

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

@@ -2180,9 +2180,9 @@ func TestUpdateThreadReadForUser(t *testing.T) {
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
})
rootPost, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, model.CreatePostFlags{})
rootPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
replyPost, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, model.CreatePostFlags{})
replyPost, _, appErr := th.App.CreatePost(th.Context, &model.Post{RootId: rootPost.Id, UserId: th.BasicUser2.Id, CreateAt: model.GetMillis(), ChannelId: th.BasicChannel.Id, Message: "hi"}, th.BasicChannel, model.CreatePostFlags{})
require.Nil(t, appErr)
threads, appErr := th.App.GetThreadsForUser(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
require.Nil(t, appErr)

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

@@ -151,7 +151,8 @@ func (h *permalinkBroadcastHook) Process(msg *platform.HookedWebSocketEvent, web
}
rctx := request.EmptyContext(webConn.Platform.Log())
if !webConn.Suite.HasPermissionToReadChannel(rctx, webConn.UserId, previewChannel) {
ok, isMember := webConn.Suite.HasPermissionToReadChannel(rctx, webConn.UserId, previewChannel)
if !ok {
// Do nothing.
// In this case, the sanitized post is already attached to the ws event.
return nil
@@ -164,6 +165,16 @@ func (h *permalinkBroadcastHook) Process(msg *platform.HookedWebSocketEvent, web
}
msg.Add("post", postJSON)
auditRec := webConn.Suite.MakeAuditRecord(rctx, "websocketPost", model.AuditStatusSuccess)
defer webConn.Suite.LogAuditRec(rctx, auditRec, nil)
model.AddEventParameterToAuditRec(auditRec, "channel_id", previewChannel.Id)
model.AddEventParameterToAuditRec(auditRec, "user_id", webConn.UserId)
model.AddEventParameterToAuditRec(auditRec, "source", "permalinkBroadcastHook")
if !isMember {
model.AddEventParameterToAuditRec(auditRec, "non_channel_member_access", true)
}
return nil
}

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

@@ -371,7 +371,7 @@ func (a *App) CreateWebhookPost(c request.CTX, userID string, channel *model.Cha
}
for _, split := range splits {
if _, err = a.CreatePost(c, split, channel, model.CreatePostFlags{}); err != nil {
if _, _, err := a.CreatePost(c, split, channel, model.CreatePostFlags{}); err != nil {
return nil, model.NewAppError("CreateWebhookPost", "api.post.create_webhook_post.creating.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
}
@@ -847,7 +847,12 @@ func (a *App) HandleIncomingWebhook(c request.CTX, hookID string, req *model.Inc
return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.user.app_error", map[string]any{"user": hook.UserId}, "", http.StatusForbidden).Wrap(resultU.NErr)
}
if channel.Type != model.ChannelTypeOpen && !a.HasPermissionToChannel(c, hook.UserId, channel.Id, model.PermissionReadChannelContent) {
restrictedChannel := false
if channel.Type != model.ChannelTypeOpen {
hasPermission, _ := a.HasPermissionToChannel(c, hook.UserId, channel.Id, model.PermissionReadChannelContent)
restrictedChannel = !hasPermission
}
if restrictedChannel {
return model.NewAppError("HandleIncomingWebhook", "web.incoming_webhook.permissions.app_error", map[string]any{"user": hook.UserId, "channel": channel.Id}, "", http.StatusForbidden)
}

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

@@ -27,7 +27,7 @@ func (api *API) userTyping(req *model.WebSocketRequest) (map[string]any, *model.
return nil, NewInvalidWebSocketParamError(req.Action, "channel_id")
}
if !api.App.SessionHasPermissionToChannel(request.EmptyContext(api.App.Log()), req.Session, channelId, model.PermissionCreatePost) {
if hasPermission, _ := api.App.SessionHasPermissionToChannel(request.EmptyContext(api.App.Log()), req.Session, channelId, model.PermissionCreatePost); !hasPermission {
return nil, NewInvalidWebSocketParamError(req.Action, "channel_id")
}

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

@@ -22,10 +22,10 @@ func (s *MmctlE2ETestSuite) TestPostListCmd() {
channel, err := s.th.App.CreateChannel(s.th.Context, &model.Channel{Name: channelName, DisplayName: channelDisplayName, Type: model.ChannelTypePrivate, TeamId: s.th.BasicTeam.Id}, false)
s.Require().Nil(err)
post1, err := s.th.App.CreatePost(s.th.Context, &model.Post{Message: model.NewRandomString(15), UserId: s.th.BasicUser.Id, ChannelId: channel.Id}, channel, model.CreatePostFlags{})
post1, _, err := s.th.App.CreatePost(s.th.Context, &model.Post{Message: model.NewRandomString(15), UserId: s.th.BasicUser.Id, ChannelId: channel.Id}, channel, model.CreatePostFlags{})
s.Require().Nil(err)
post2, err := s.th.App.CreatePost(s.th.Context, &model.Post{Message: model.NewRandomString(15), UserId: s.th.BasicUser.Id, ChannelId: channel.Id}, channel, model.CreatePostFlags{})
post2, _, err := s.th.App.CreatePost(s.th.Context, &model.Post{Message: model.NewRandomString(15), UserId: s.th.BasicUser.Id, ChannelId: channel.Id}, channel, model.CreatePostFlags{})
s.Require().Nil(err)
return channelName, post1, post2

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

@@ -142,7 +142,7 @@ func (_m *MockAppIface) CreateGroupChannel(c request.CTX, userIDs []string, crea
}
// CreatePost provides a mock function with given fields: c, post, channel, flags
func (_m *MockAppIface) CreatePost(c request.CTX, post *model.Post, channel *model.Channel, flags model.CreatePostFlags) (*model.Post, *model.AppError) {
func (_m *MockAppIface) CreatePost(c request.CTX, post *model.Post, channel *model.Channel, flags model.CreatePostFlags) (*model.Post, bool, *model.AppError) {
ret := _m.Called(c, post, channel, flags)
if len(ret) == 0 {
@@ -150,8 +150,9 @@ func (_m *MockAppIface) CreatePost(c request.CTX, post *model.Post, channel *mod
}
var r0 *model.Post
var r1 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, *model.Post, *model.Channel, model.CreatePostFlags) (*model.Post, *model.AppError)); ok {
var r1 bool
var r2 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, *model.Post, *model.Channel, model.CreatePostFlags) (*model.Post, bool, *model.AppError)); ok {
return rf(c, post, channel, flags)
}
if rf, ok := ret.Get(0).(func(request.CTX, *model.Post, *model.Channel, model.CreatePostFlags) *model.Post); ok {
@@ -162,15 +163,21 @@ func (_m *MockAppIface) CreatePost(c request.CTX, post *model.Post, channel *mod
}
}
if rf, ok := ret.Get(1).(func(request.CTX, *model.Post, *model.Channel, model.CreatePostFlags) *model.AppError); ok {
if rf, ok := ret.Get(1).(func(request.CTX, *model.Post, *model.Channel, model.CreatePostFlags) bool); ok {
r1 = rf(c, post, channel, flags)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
r1 = ret.Get(1).(bool)
}
if rf, ok := ret.Get(2).(func(request.CTX, *model.Post, *model.Channel, model.CreatePostFlags) *model.AppError); ok {
r2 = rf(c, post, channel, flags)
} else {
if ret.Get(2) != nil {
r2 = ret.Get(2).(*model.AppError)
}
}
return r0, r1
return r0, r1, r2
}
// CreateUploadSession provides a mock function with given fields: c, us
@@ -707,7 +714,7 @@ func (_m *MockAppIface) SaveReactionForPost(c request.CTX, reaction *model.React
}
// SendEphemeralPost provides a mock function with given fields: c, userId, post
func (_m *MockAppIface) SendEphemeralPost(c request.CTX, userId string, post *model.Post) *model.Post {
func (_m *MockAppIface) SendEphemeralPost(c request.CTX, userId string, post *model.Post) (*model.Post, bool) {
ret := _m.Called(c, userId, post)
if len(ret) == 0 {
@@ -715,6 +722,10 @@ func (_m *MockAppIface) SendEphemeralPost(c request.CTX, userId string, post *mo
}
var r0 *model.Post
var r1 bool
if rf, ok := ret.Get(0).(func(request.CTX, string, *model.Post) (*model.Post, bool)); ok {
return rf(c, userId, post)
}
if rf, ok := ret.Get(0).(func(request.CTX, string, *model.Post) *model.Post); ok {
r0 = rf(c, userId, post)
} else {
@@ -723,11 +734,17 @@ func (_m *MockAppIface) SendEphemeralPost(c request.CTX, userId string, post *mo
}
}
return r0
if rf, ok := ret.Get(1).(func(request.CTX, string, *model.Post) bool); ok {
r1 = rf(c, userId, post)
} else {
r1 = ret.Get(1).(bool)
}
return r0, r1
}
// UpdatePost provides a mock function with given fields: c, post, updatePostOptions
func (_m *MockAppIface) UpdatePost(c request.CTX, post *model.Post, updatePostOptions *model.UpdatePostOptions) (*model.Post, *model.AppError) {
func (_m *MockAppIface) UpdatePost(c request.CTX, post *model.Post, updatePostOptions *model.UpdatePostOptions) (*model.Post, bool, *model.AppError) {
ret := _m.Called(c, post, updatePostOptions)
if len(ret) == 0 {
@@ -735,8 +752,9 @@ func (_m *MockAppIface) UpdatePost(c request.CTX, post *model.Post, updatePostOp
}
var r0 *model.Post
var r1 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, *model.Post, *model.UpdatePostOptions) (*model.Post, *model.AppError)); ok {
var r1 bool
var r2 *model.AppError
if rf, ok := ret.Get(0).(func(request.CTX, *model.Post, *model.UpdatePostOptions) (*model.Post, bool, *model.AppError)); ok {
return rf(c, post, updatePostOptions)
}
if rf, ok := ret.Get(0).(func(request.CTX, *model.Post, *model.UpdatePostOptions) *model.Post); ok {
@@ -747,15 +765,21 @@ func (_m *MockAppIface) UpdatePost(c request.CTX, post *model.Post, updatePostOp
}
}
if rf, ok := ret.Get(1).(func(request.CTX, *model.Post, *model.UpdatePostOptions) *model.AppError); ok {
if rf, ok := ret.Get(1).(func(request.CTX, *model.Post, *model.UpdatePostOptions) bool); ok {
r1 = rf(c, post, updatePostOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
r1 = ret.Get(1).(bool)
}
if rf, ok := ret.Get(2).(func(request.CTX, *model.Post, *model.UpdatePostOptions) *model.AppError); ok {
r2 = rf(c, post, updatePostOptions)
} else {
if ret.Get(2) != nil {
r2 = ret.Get(2).(*model.AppError)
}
}
return r0, r1
return r0, r1, r2
}
// UserCanSeeOtherUser provides a mock function with given fields: c, userID, otherUserId

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

@@ -38,7 +38,7 @@ func TestProcessPermalinkToRemote(t *testing.T) {
mockServer.On("Log").Return(logger)
mockApp := scs.app.(*MockAppIface)
mockApp.On("SendEphemeralPost", mock.Anything, "user", mock.AnythingOfType("*model.Post")).Return(&model.Post{}).Times(1)
mockApp.On("SendEphemeralPost", mock.Anything, "user", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, true).Times(1)
defer mockApp.AssertExpectations(t)
t.Run("same channel", func(t *testing.T) {

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

@@ -54,7 +54,7 @@ type PlatformIface interface {
}
type AppIface interface {
SendEphemeralPost(c request.CTX, userId string, post *model.Post) *model.Post
SendEphemeralPost(c request.CTX, userId string, post *model.Post) (*model.Post, bool)
CreateChannelWithUser(c request.CTX, channel *model.Channel, userId string) (*model.Channel, *model.AppError)
GetOrCreateDirectChannel(c request.CTX, userId, otherUserId string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError)
CreateGroupChannel(c request.CTX, userIDs []string, creatorId string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError)
@@ -63,8 +63,8 @@ type AppIface interface {
AddUserToTeamByTeamId(c request.CTX, teamId string, user *model.User) *model.AppError
RemoveUserFromChannel(c request.CTX, userID string, removerUserId string, channel *model.Channel) *model.AppError
PermanentDeleteChannel(c request.CTX, channel *model.Channel) *model.AppError
CreatePost(c request.CTX, post *model.Post, channel *model.Channel, flags model.CreatePostFlags) (savedPost *model.Post, err *model.AppError)
UpdatePost(c request.CTX, post *model.Post, updatePostOptions *model.UpdatePostOptions) (*model.Post, *model.AppError)
CreatePost(c request.CTX, post *model.Post, channel *model.Channel, flags model.CreatePostFlags) (savedPost *model.Post, isMemberForPreviews bool, err *model.AppError)
UpdatePost(c request.CTX, post *model.Post, updatePostOptions *model.UpdatePostOptions) (*model.Post, bool, *model.AppError)
DeletePost(c request.CTX, postID, deleteByID string) (*model.Post, *model.AppError)
SaveReactionForPost(c request.CTX, reaction *model.Reaction) (*model.Reaction, *model.AppError)
DeleteReactionForPost(c request.CTX, reaction *model.Reaction) *model.AppError
@@ -315,7 +315,7 @@ func (scs *Service) postUnshareNotification(channelID string, creatorID string,
}
logger := scs.server.Log()
_, appErr := scs.app.CreatePost(request.EmptyContext(logger), post, channel, model.CreatePostFlags{})
_, _, appErr := scs.app.CreatePost(request.EmptyContext(logger), post, channel, model.CreatePostFlags{})
if appErr != nil {
scs.server.Log().Log(

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

@@ -493,7 +493,7 @@ func (scs *Service) upsertSyncPost(post *model.Post, targetChannel *model.Channe
scs.transformMentionsOnReceive(rctx, post, targetChannel, rc, mentionTransforms)
rpost, appErr = scs.app.CreatePost(rctx, post, targetChannel, model.CreatePostFlags{TriggerWebhooks: true, SetOnline: true})
rpost, _, appErr = scs.app.CreatePost(rctx, post, targetChannel, model.CreatePostFlags{TriggerWebhooks: true, SetOnline: true})
if appErr == nil {
scs.server.Log().Log(mlog.LvlSharedChannelServiceDebug, "Created sync post",
mlog.String("post_id", post.Id),
@@ -527,7 +527,7 @@ func (scs *Service) upsertSyncPost(post *model.Post, targetChannel *model.Channe
}
// First update the basic post
rpost, appErr = scs.app.UpdatePost(rctx, post, nil)
rpost, _, appErr = scs.app.UpdatePost(rctx, post, nil)
if appErr != nil {
rerr := errors.New(appErr.Error())
return nil, rerr