* create ChannelBookmarks table

* ChannelBookmark model

* channel bookamrks Store layer

* add GetBookmarksForAllChannelByIdSince

* add channel bookmarks to test store

* Add channel bookmarks to app layer

* remove index for createAt in channel bookmarks migrations

* remove createAt from select channel bookmark query and enable store delete bookmark test

* update reponse of UpdateBookmark

* rename db migration files

* channel bookmarks store update sort order

* channel bookmarks app layer update sort order

* fix lint & tests

* Fix lint and introduce util functions to insert / remove from slice

* remove model etag

* i18n

* defer remove file info after test run

* Fix tests passing the request context

* fix migrations

* fix TestRetry

* Add bookmark permissions (#25560)

* Adds channel bookmarks permissions

* Fix linter

* Remove unnecessary empty lines

* Remove scss change as it's not necessary anymore

* Fix mock store

* Fix mock store and add role entry

* Fix test

* Adds cypress test and update permissions migration to update admin roles

* Adds channel bookmarks roles to default admin roles

* Adds bookmark permissions to default role permissions constant in webapp

* Update mmctl test

* Update permission test after normalising the roles

* fix store tests

* fix app layer tests

* Add new bookmark endpoint (#25624)

* Adds channel bookmarks api scaffold and create endpoint

* Applies review comments to the API docs

* Adds websocket test to create channel bookmark

---------

Co-authored-by: Mattermost Build <build@mattermost.com>

* MM-54426 exclude Channel Bookmarks files from data retention (#25656)

* Augment channel APIs to include bookmarks (#25567)

* update files docs for server 9.4

* Adds update channel bookmark endpoint (#25653)

* Adds update channel bookmark sort order endpoint (#25686)

* Adds update channel bookmark endpoint

* Updates edit app method to return the right deleted bookmark and adds tests

* Adds the update channel bookmark sort order endpoint

* Fix repeated test after merge

* Assign right permissions to each test

* Update store and app layer to return specific errors and add tests

* Adds delete channel bookmark endpoint (#25693)

* Updates edit app method to return the right deleted bookmark and adds tests

* Fix repeated test after merge

* Updates edit app method to return the right deleted bookmark and adds tests

* Adds delete channel bookmark endpoint

* Adds list channel bookmarks endpoint (#25700)

* Add channel moderation to bookmarks (#25716)

* fix migrations index

* fix getChannelsForTeamForUser

* fix getChannelsForTeamForUser

* fix bad merge client4

* fix file api with bookmark permission

* add ChannelBookmarks feature flag

* add missing translations

* Set DB column for type as enum

* use custom type for bookmark query using sqlx

* use transaction when saving bookmark

* return NewErrNotFound instead of Sql.ErrNoRows

* use squirrel for IN query

* add a limit of 1K for records in GetBookmarksForAllChannelByIdSince

* UpdateSortOrder with one single query instead of multiple updates

* fix shadow declaration

* fix channel bookmarks permission string definition in admin console

* fix another shadow declaration

* Fix model conversion

* add SplitSliceInChunks

* remove include bookmarks in channels api

* Cap amount of bookmarks per channel

* add etag back to get channels

* feedback review

* update file info when replacing a bookmark file

* return 501 not implemented when the license is not available

* add detail message when getting channel member on bookmark api

* start audit before permission check on create bookmark api

* use require.Eventuallyf for testing WS events

* remove unnecessary log in app layer

* use require instead of assert to avoid panics

* enforce limit when querying bookmarks since

* prevent to create/update bookmark if file is already attached

* fix lint

* delete file when a bookmark is deleted

* Dot allow to set a fileId and a url at the same time to a bookmark

* fix query to delete a file that belongs to a bookmark

* do not patch the bookmark type

* Server side FeatureFlag check (#26145)

* use ff in server, set ff to false

* turn on FF for unit tests

* defer unset FF for unit tests

* turn ff on for testing

* only allow attaching files that were uploaded for bookmark

* Set feature flag off as default

* fix lint

* update email templates as PR failed

* revert templates

* force the assignment of ID when creating a bookmark

* Fix unit tests

---------

Co-authored-by: Miguel de la Cruz <miguel@mcrx.me>
Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Caleb Roseland <caleb@calebroseland.com>
Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>
Этот коммит содержится в:
Elias Nahum
2024-03-12 22:36:05 +08:00
коммит произвёл GitHub
родитель 2480a6c646
Коммит 7e9cd04a8b
66 изменённых файлов: 6578 добавлений и 57 удалений

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

@@ -506,6 +506,7 @@ type AppIface interface {
CopyFileInfos(rctx request.CTX, userID string, fileIDs []string) ([]string, *model.AppError)
CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, targetChannel *model.Channel) (*model.Post, *model.AppError)
CreateChannel(c request.CTX, channel *model.Channel, addMember bool) (*model.Channel, *model.AppError)
CreateChannelBookmark(c request.CTX, newBookmark *model.ChannelBookmark, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError)
CreateChannelWithUser(c request.CTX, channel *model.Channel, userID string) (*model.Channel, *model.AppError)
CreateCommand(cmd *model.Command) (*model.Command, *model.AppError)
CreateCommandWebhook(commandID string, args *model.CommandArgs) (*model.CommandWebhook, *model.AppError)
@@ -550,6 +551,7 @@ type AppIface interface {
DeleteAllKeysForPlugin(pluginID string) *model.AppError
DeleteBrandImage(rctx request.CTX) *model.AppError
DeleteChannel(c request.CTX, channel *model.Channel, userID string) *model.AppError
DeleteChannelBookmark(bookmarkId, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError)
DeleteCommand(commandID string) *model.AppError
DeleteDraft(rctx request.CTX, draft *model.Draft, connectionID string) *model.AppError
DeleteEmoji(c request.CTX, emoji *model.Emoji) *model.AppError
@@ -627,9 +629,11 @@ type AppIface interface {
GetAuditsPage(rctx request.CTX, userID string, page int, perPage int) (model.Audits, *model.AppError)
GetAuthorizationCode(c request.CTX, w http.ResponseWriter, r *http.Request, service string, props map[string]string, loginHint string) (string, *model.AppError)
GetAuthorizedAppsForUser(userID string, page, perPage int) ([]*model.OAuthApp, *model.AppError)
GetBookmark(bookmarkId string, includeDeleted bool) (*model.ChannelBookmarkWithFileInfo, *model.AppError)
GetBrandImage(rctx request.CTX) ([]byte, *model.AppError)
GetBulkReactionsForPosts(postIDs []string) (map[string][]*model.Reaction, *model.AppError)
GetChannel(c request.CTX, channelID string) (*model.Channel, *model.AppError)
GetChannelBookmarks(channelId string, since int64) ([]*model.ChannelBookmarkWithFileInfo, *model.AppError)
GetChannelByName(c request.CTX, channelName, teamID string, includeDeleted bool) (*model.Channel, *model.AppError)
GetChannelByNameForTeamName(c request.CTX, channelName, teamName string, includeDeleted bool) (*model.Channel, *model.AppError)
GetChannelCounts(c request.CTX, teamID string, userID string) (*model.ChannelCounts, *model.AppError)
@@ -1147,6 +1151,8 @@ type AppIface interface {
UnregisterPluginForSharedChannels(pluginID string) error
UnshareChannel(channelID string) (bool, error)
UpdateActive(c request.CTX, user *model.User, active bool) (*model.User, *model.AppError)
UpdateChannelBookmark(c request.CTX, updateBookmark *model.ChannelBookmarkWithFileInfo, connectionId string) (*model.UpdateChannelBookmarkResponse, *model.AppError)
UpdateChannelBookmarkSortOrder(bookmarkId, channelId string, newIndex int64, connectionId string) ([]*model.ChannelBookmarkWithFileInfo, *model.AppError)
UpdateChannelMemberNotifyProps(c request.CTX, data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError)
UpdateChannelMemberRoles(c request.CTX, channelID string, userID string, newRoles string) (*model.ChannelMember, *model.AppError)
UpdateChannelMemberSchemeRoles(c request.CTX, channelID string, userID string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError)

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

@@ -127,10 +127,26 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PermissionManagePrivateChannelMembers.Id,
model.PermissionDeletePost.Id,
model.PermissionEditPost.Id,
model.PermissionAddBookmarkPublicChannel.Id,
model.PermissionEditBookmarkPublicChannel.Id,
model.PermissionDeleteBookmarkPublicChannel.Id,
model.PermissionOrderBookmarkPublicChannel.Id,
model.PermissionAddBookmarkPrivateChannel.Id,
model.PermissionEditBookmarkPrivateChannel.Id,
model.PermissionDeleteBookmarkPrivateChannel.Id,
model.PermissionOrderBookmarkPrivateChannel.Id,
},
"channel_admin": {
model.PermissionManageChannelRoles.Id,
model.PermissionUseGroupMentions.Id,
model.PermissionAddBookmarkPublicChannel.Id,
model.PermissionEditBookmarkPublicChannel.Id,
model.PermissionDeleteBookmarkPublicChannel.Id,
model.PermissionOrderBookmarkPublicChannel.Id,
model.PermissionAddBookmarkPrivateChannel.Id,
model.PermissionEditBookmarkPrivateChannel.Id,
model.PermissionDeleteBookmarkPrivateChannel.Id,
model.PermissionOrderBookmarkPrivateChannel.Id,
},
"team_user": {
model.PermissionListTeamChannels.Id,
@@ -166,6 +182,14 @@ func TestDoAdvancedPermissionsMigration(t *testing.T) {
model.PermissionConvertPrivateChannelToPublic.Id,
model.PermissionDeletePost.Id,
model.PermissionDeleteOthersPosts.Id,
model.PermissionAddBookmarkPublicChannel.Id,
model.PermissionEditBookmarkPublicChannel.Id,
model.PermissionDeleteBookmarkPublicChannel.Id,
model.PermissionOrderBookmarkPublicChannel.Id,
model.PermissionAddBookmarkPrivateChannel.Id,
model.PermissionEditBookmarkPrivateChannel.Id,
model.PermissionDeleteBookmarkPrivateChannel.Id,
model.PermissionOrderBookmarkPrivateChannel.Id,
},
"system_user": {
model.PermissionListPublicTeams.Id,

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

@@ -1122,7 +1122,7 @@ func buildChannelModerations(c request.CTX, channelType model.ChannelType, membe
Enabled: higherScopedMemberPermissions[permissionKey],
}
if permissionKey == "manage_members" {
if permissionKey == "manage_members" || permissionKey == "manage_bookmarks" {
roles.Guests = nil
} else {
roles.Guests = &model.ChannelModeratedRole{

152
server/channels/app/channel_bookmark.go Обычный файл
Просмотреть файл

@@ -0,0 +1,152 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"encoding/json"
"errors"
"net/http"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/request"
"github.com/mattermost/mattermost/server/v8/channels/store"
)
func (a *App) GetChannelBookmarks(channelId string, since int64) ([]*model.ChannelBookmarkWithFileInfo, *model.AppError) {
bookmarks, err := a.Srv().Store().ChannelBookmark().GetBookmarksForChannelSince(channelId, since)
if err != nil {
return nil, model.NewAppError("GetChannelBookmarks", "app.channel.bookmark.get.app_error", nil, "", http.StatusNotFound).Wrap(err)
}
return bookmarks, nil
}
func (a *App) GetBookmark(bookmarkId string, includeDeleted bool) (*model.ChannelBookmarkWithFileInfo, *model.AppError) {
bookmark, err := a.Srv().Store().ChannelBookmark().Get(bookmarkId, includeDeleted)
if err != nil {
return nil, model.NewAppError("GetBookmark", "app.channel.bookmark.get.app_error", nil, "", http.StatusNotFound).Wrap(err)
}
return bookmark, nil
}
func (a *App) CreateChannelBookmark(c request.CTX, newBookmark *model.ChannelBookmark, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError) {
newBookmark.OwnerId = c.Session().UserId //ensure that the bookmark is being created by the user who owns the session
newBookmark.Id = "" // ensure that creating a new bookmark generates a new ID
bookmark, err := a.Srv().Store().ChannelBookmark().Save(newBookmark, true)
if err != nil {
return nil, model.NewAppError("CreateChannelBookmark", "app.channel.bookmark.save.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
message := model.NewWebSocketEvent(model.WebsocketEventChannelBookmarkCreated, "", bookmark.ChannelId, "", nil, connectionId)
bookmarkJSON, jsonErr := json.Marshal(bookmark)
if jsonErr != nil {
return nil, model.NewAppError("CreateChannelBookmark", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("bookmark", string(bookmarkJSON))
a.Publish(message)
return bookmark, nil
}
func (a *App) UpdateChannelBookmark(c request.CTX, updateBookmark *model.ChannelBookmarkWithFileInfo, connectionId string) (*model.UpdateChannelBookmarkResponse, *model.AppError) {
response := &model.UpdateChannelBookmarkResponse{}
if updateBookmark.OwnerId == c.Session().UserId {
isAnotherFile := updateBookmark.FileInfo != nil && updateBookmark.FileId != "" && updateBookmark.FileId != updateBookmark.FileInfo.Id
if isAnotherFile {
if fileAlreadyAttachedErr := a.Srv().Store().ChannelBookmark().ErrorIfBookmarkFileInfoAlreadyAttached(updateBookmark.FileId); fileAlreadyAttachedErr != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "app.channel.bookmark.update.app_error", nil, "", http.StatusInternalServerError).Wrap(fileAlreadyAttachedErr)
}
}
if err := a.Srv().Store().ChannelBookmark().Update(updateBookmark.ChannelBookmark); err != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "app.channel.bookmark.update.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
if isAnotherFile {
fileInfo, fileErr := a.Srv().Store().FileInfo().Get(updateBookmark.FileId)
if fileErr != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "app.channel.bookmark.get_existing.app_err", nil, "", http.StatusNotFound).Wrap(fileErr)
}
response.Updated = updateBookmark.ToBookmarkWithFileInfo(fileInfo)
} else {
response.Updated = updateBookmark.ToBookmarkWithFileInfo(updateBookmark.FileInfo)
}
} else {
existingBookmark, ebErr := a.Srv().Store().ChannelBookmark().Get(updateBookmark.Id, false)
if ebErr != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "app.channel.bookmark.get_existing.app_err", nil, "", http.StatusNotFound).Wrap(ebErr)
}
existingBookmark.DeleteAt = model.GetMillis()
if err := a.Srv().Store().ChannelBookmark().Delete(updateBookmark.Id, false); err != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "app.channel.bookmark.delete.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
newBookmark := updateBookmark.SetOriginal(c.Session().UserId)
bookmark, err := a.Srv().Store().ChannelBookmark().Save(newBookmark, false)
if err != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "app.channel.bookmark.save.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
response.Updated = bookmark
response.Deleted = existingBookmark.ToBookmarkWithFileInfo(nil)
}
message := model.NewWebSocketEvent(model.WebsocketEventChannelBookmarkUpdated, "", updateBookmark.ChannelId, "", nil, connectionId)
bookmarkJSON, jsonErr := json.Marshal(response)
if jsonErr != nil {
return nil, model.NewAppError("UpdateChannelBookmark", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("bookmarks", string(bookmarkJSON))
a.Publish(message)
return response, nil
}
func (a *App) DeleteChannelBookmark(bookmarkId, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError) {
if err := a.Srv().Store().ChannelBookmark().Delete(bookmarkId, true); err != nil {
return nil, model.NewAppError("DeleteChannelBookmark", "app.channel.bookmark.delete.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
bookmark, err := a.GetBookmark(bookmarkId, true)
if err != nil {
return nil, model.NewAppError("DeleteChannelBookmark", "app.channel.bookmark.get.app_error", nil, "", http.StatusNotFound).Wrap(err)
}
message := model.NewWebSocketEvent(model.WebsocketEventChannelBookmarkDeleted, "", bookmark.ChannelId, "", nil, connectionId)
bookmarkJSON, jsonErr := json.Marshal(bookmark)
if jsonErr != nil {
return nil, model.NewAppError("DeleteChannelBookmark", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("bookmark", string(bookmarkJSON))
a.Publish(message)
return bookmark, nil
}
func (a *App) UpdateChannelBookmarkSortOrder(bookmarkId, channelId string, newIndex int64, connectionId string) ([]*model.ChannelBookmarkWithFileInfo, *model.AppError) {
bookmarks, err := a.Srv().Store().ChannelBookmark().UpdateSortOrder(bookmarkId, channelId, newIndex)
if err != nil {
var iiErr *store.ErrInvalidInput
var nfErr *store.ErrNotFound
switch {
case errors.As(err, &iiErr):
return nil, model.NewAppError("UpdateSortOrder", "app.channel.bookmark.update_sort.invalid_input.app_error", nil, "", http.StatusBadRequest).Wrap(err)
case errors.As(err, &nfErr):
return nil, model.NewAppError("UpdateSortOrder", "app.channel.bookmark.update_sort.missing_bookmark.app_error", nil, "", http.StatusNotFound).Wrap(err)
default:
return nil, model.NewAppError("UpdateSortOrder", "app.channel.bookmark.update_sort.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
}
message := model.NewWebSocketEvent(model.WebsocketEventChannelBookmarkSorted, "", channelId, "", nil, connectionId)
bookmarkJSON, jsonErr := json.Marshal(bookmarks)
if jsonErr != nil {
return nil, model.NewAppError("UpdateSortOrder", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("bookmarks", string(bookmarkJSON))
a.Publish(message)
return bookmarks, nil
}

498
server/channels/app/channel_bookmark_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,498 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package app
import (
"fmt"
"testing"
"time"
"github.com/mattermost/mattermost/server/public/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func find_bookmark(slice []*model.ChannelBookmarkWithFileInfo, id string) *model.ChannelBookmarkWithFileInfo {
for _, element := range slice {
if element.Id == id {
return element
}
}
return nil
}
func createBookmark(name string, bookmarkType model.ChannelBookmarkType, channelId string, fileId string) *model.ChannelBookmark {
bookmark := &model.ChannelBookmark{
ChannelId: channelId,
DisplayName: name,
LinkUrl: "https://mattermost.com",
Type: bookmarkType,
Emoji: ":smile:",
FileId: fileId,
}
return bookmark
}
func TestCreateBookmark(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
t.Run("create a channel bookmark", func(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
bookmark1 := createBookmark("Link bookmark test", model.ChannelBookmarkLink, th.BasicChannel.Id, "")
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark1, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
assert.Equal(t, bookmarkResp.ChannelId, th.BasicChannel.Id)
assert.NotEmpty(t, bookmarkResp.Id)
bookmark2 := createBookmark("File bookmark test", model.ChannelBookmarkFile, th.BasicChannel.Id, "")
bookmarkResp, err = th.App.CreateChannelBookmark(th.Context, bookmark2, "")
assert.Nil(t, bookmarkResp)
assert.NotNil(t, err)
})
t.Run("Cannot create more than MaxBookmarksPerChannel", func(t *testing.T) {
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
for i := 1; i < model.MaxBookmarksPerChannel; i++ {
bookmark := createBookmark(fmt.Sprintf("Link bookmark test %d", i), model.ChannelBookmarkLink, th.BasicChannel.Id, "")
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
assert.Equal(t, bookmarkResp.ChannelId, th.BasicChannel.Id)
assert.NotEmpty(t, bookmarkResp.Id)
}
bookmark := createBookmark("Bookmark that should not be added", model.ChannelBookmarkLink, th.BasicChannel.Id, "")
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark, "")
assert.Nil(t, bookmarkResp)
assert.NotNil(t, err)
})
}
func TestUpdateBookmark(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
var updateBookmark *model.ChannelBookmarkWithFileInfo
var testUpdateAnotherFile = func(th *TestHelper, t *testing.T) {
file := &model.FileInfo{
Id: model.NewId(),
CreatorId: model.BookmarkFileOwner,
Path: "somepath",
ThumbnailPath: "thumbpath",
PreviewPath: "prevPath",
Name: "test file",
Extension: "png",
MimeType: "images/png",
Size: 873182,
Width: 3076,
Height: 2200,
HasPreviewImage: true,
}
th.App.Srv().Store().FileInfo().Save(th.Context, file)
defer th.App.Srv().Store().FileInfo().PermanentDelete(th.Context, file.Id)
bookmark2 := createBookmark("File to be updated", model.ChannelBookmarkFile, th.BasicChannel.Id, file.Id)
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark2, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
file2 := &model.FileInfo{
Id: model.NewId(),
CreatorId: model.BookmarkFileOwner,
Path: "somepath",
ThumbnailPath: "thumbpath",
PreviewPath: "prevPath",
Name: "test file",
Extension: "png",
MimeType: "images/png",
Size: 873182,
Width: 3076,
Height: 2200,
HasPreviewImage: true,
}
th.App.Srv().Store().FileInfo().Save(th.Context, file2)
th.App.Srv().Store().FileInfo().AttachToPost(th.Context, file2.Id, model.NewId(), th.BasicChannel.Id, model.BookmarkFileOwner)
defer th.App.Srv().Store().FileInfo().PermanentDelete(th.Context, file2.Id)
bookmark2.FileId = file2.Id
bookmarkResp, err = th.App.CreateChannelBookmark(th.Context, bookmark2, "")
require.NotNil(t, err)
require.Nil(t, bookmarkResp)
}
t.Run("same user update a channel bookmark", func(t *testing.T) {
bookmark1 := &model.ChannelBookmark{
ChannelId: th.BasicChannel.Id,
DisplayName: "Link bookmark test",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
Emoji: ":smile:",
}
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark1, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
updateBookmark = bookmarkResp.Clone()
updateBookmark.DisplayName = "New name"
time.Sleep(1 * time.Millisecond) // to avoid collisions
response, _ := th.App.UpdateChannelBookmark(th.Context, updateBookmark, "")
require.NotNil(t, response)
assert.Greater(t, response.Updated.UpdateAt, response.Updated.CreateAt)
testUpdateAnotherFile(th, t)
})
t.Run("another user update a channel bookmark", func(t *testing.T) {
updateBookmark2 := updateBookmark.Clone()
updateBookmark2.DisplayName = "Another new name"
th.Context.Session().UserId = th.BasicUser2.Id
response, _ := th.App.UpdateChannelBookmark(th.Context, updateBookmark2, "")
require.NotNil(t, response)
assert.Equal(t, response.Updated.OriginalId, response.Deleted.Id)
assert.Equal(t, response.Updated.DeleteAt, int64(0))
assert.Greater(t, response.Deleted.DeleteAt, int64(0))
assert.Equal(t, "Another new name", response.Updated.DisplayName)
assert.Equal(t, "New name", response.Deleted.DisplayName)
testUpdateAnotherFile(th, t)
})
t.Run("update an already deleted channel bookmark", func(t *testing.T) {
bookmark1 := &model.ChannelBookmark{
ChannelId: th.BasicChannel.Id,
DisplayName: "Link bookmark test",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
Emoji: ":smile:",
}
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark1, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
updateBookmark = bookmarkResp.Clone()
_, err = th.App.DeleteChannelBookmark(updateBookmark.Id, "")
assert.Nil(t, err)
updateBookmark.DisplayName = "New name"
_, err = th.App.UpdateChannelBookmark(th.Context, updateBookmark, "")
assert.NotNil(t, err)
})
t.Run("update a nonexisting channel bookmark", func(t *testing.T) {
updateBookmark := &model.ChannelBookmark{
Id: model.NewId(),
ChannelId: th.BasicChannel.Id,
DisplayName: "Link bookmark test",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
Emoji: ":smile:",
}
_, err := th.App.UpdateChannelBookmark(th.Context, updateBookmark.ToBookmarkWithFileInfo(nil), "")
assert.NotNil(t, err)
assert.Equal(t, "app.channel.bookmark.get_existing.app_err", err.Id)
})
}
func TestDeleteBookmark(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
t.Run("delete a channel bookmark", func(t *testing.T) {
bookmark1 := &model.ChannelBookmark{
ChannelId: th.BasicChannel.Id,
DisplayName: "Link bookmark test",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
Emoji: ":smile:",
}
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
bookmarkResp, err := th.App.CreateChannelBookmark(th.Context, bookmark1, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
bookmarkResp, err = th.App.DeleteChannelBookmark(bookmarkResp.Id, "")
require.Nil(t, err)
require.NotNil(t, bookmarkResp)
assert.Greater(t, bookmarkResp.DeleteAt, int64(0))
})
}
func TestGetChannelBookmarks(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
bookmark1 := &model.ChannelBookmark{
ChannelId: th.BasicChannel.Id,
DisplayName: "Bookmark 1",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
Emoji: ":smile:",
}
th.App.CreateChannelBookmark(th.Context, bookmark1, "")
file := &model.FileInfo{
Id: model.NewId(),
CreatorId: model.BookmarkFileOwner,
Path: "somepath",
ThumbnailPath: "thumbpath",
PreviewPath: "prevPath",
Name: "test file",
Extension: "png",
MimeType: "images/png",
Size: 873182,
Width: 3076,
Height: 2200,
HasPreviewImage: true,
}
th.App.Srv().Store().FileInfo().Save(th.Context, file)
defer th.App.Srv().Store().FileInfo().PermanentDelete(th.Context, file.Id)
bookmark2 := &model.ChannelBookmark{
ChannelId: th.BasicChannel.Id,
DisplayName: "Bookmark 2",
FileId: file.Id,
Type: model.ChannelBookmarkFile,
Emoji: ":smile:",
}
th.App.CreateChannelBookmark(th.Context, bookmark2, "")
t.Run("get bookmarks of a channel", func(t *testing.T) {
bookmarks, err := th.App.GetChannelBookmarks(th.BasicChannel.Id, 0)
require.Nil(t, err)
require.NotNil(t, bookmarks)
assert.Len(t, bookmarks, 2)
})
t.Run("get bookmarks of a channel after one is deleted (aka only return the changed bookmarks)", func(t *testing.T) {
now := model.GetMillis()
th.App.DeleteChannelBookmark(bookmark1.Id, "")
bookmarks, err := th.App.GetChannelBookmarks(th.BasicChannel.Id, 0)
require.Nil(t, err)
require.NotNil(t, bookmarks)
assert.Len(t, bookmarks, 1)
bookmarks, err = th.App.GetChannelBookmarks(th.BasicChannel.Id, now)
require.Nil(t, err)
require.NotNil(t, bookmarks)
assert.Len(t, bookmarks, 1)
deleted := false
for _, b := range bookmarks {
if b.DeleteAt > 0 {
deleted = true
break
}
}
assert.Equal(t, deleted, true)
})
}
func TestUpdateChannelBookmarkSortOrder(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
channelId := th.BasicChannel.Id
th.Context.Session().UserId = th.BasicUser.Id // set the user for the session
bookmark0 := &model.ChannelBookmark{
ChannelId: channelId,
DisplayName: "Bookmark 0",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
Emoji: ":smile:",
}
file := &model.FileInfo{
Id: model.NewId(),
CreatorId: model.BookmarkFileOwner,
Path: "somepath",
ThumbnailPath: "thumbpath",
PreviewPath: "prevPath",
Name: "test file",
Extension: "png",
MimeType: "images/png",
Size: 873182,
Width: 3076,
Height: 2200,
HasPreviewImage: true,
}
bookmark1 := &model.ChannelBookmark{
ChannelId: channelId,
DisplayName: "Bookmark 1",
FileId: file.Id,
Type: model.ChannelBookmarkFile,
Emoji: ":smile:",
}
_, err := th.App.Srv().Store().FileInfo().Save(th.Context, file)
require.NoError(t, err)
defer th.App.Srv().Store().FileInfo().PermanentDelete(th.Context, file.Id)
bookmark2 := &model.ChannelBookmark{
ChannelId: channelId,
DisplayName: "Bookmark 2",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
}
bookmark3 := &model.ChannelBookmark{
ChannelId: channelId,
DisplayName: "Bookmark 3",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
}
bookmark4 := &model.ChannelBookmark{
ChannelId: channelId,
DisplayName: "Bookmark 4",
LinkUrl: "https://mattermost.com",
Type: model.ChannelBookmarkLink,
}
bookmarkResp, appErr := th.App.CreateChannelBookmark(th.Context, bookmark0, "")
require.Nil(t, appErr)
require.NotNil(t, bookmarkResp)
bookmark0 = bookmarkResp.ChannelBookmark.Clone()
bookmarkResp, appErr = th.App.CreateChannelBookmark(th.Context, bookmark1, "")
require.Nil(t, appErr)
require.NotNil(t, bookmarkResp)
bookmark1 = bookmarkResp.ChannelBookmark.Clone()
bookmarkResp, appErr = th.App.CreateChannelBookmark(th.Context, bookmark2, "")
require.Nil(t, appErr)
require.NotNil(t, bookmarkResp)
bookmark2 = bookmarkResp.ChannelBookmark.Clone()
bookmarkResp, appErr = th.App.CreateChannelBookmark(th.Context, bookmark3, "")
require.Nil(t, appErr)
require.NotNil(t, bookmarkResp)
bookmark3 = bookmarkResp.ChannelBookmark.Clone()
bookmarkResp, appErr = th.App.CreateChannelBookmark(th.Context, bookmark4, "")
require.Nil(t, appErr)
require.NotNil(t, bookmarkResp)
bookmark4 = bookmarkResp.ChannelBookmark.Clone()
t.Run("change order of bookmarks first to last", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark0.Id, channelId, int64(4), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(4))
})
t.Run("change order of bookmarks last to first", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark0.Id, channelId, int64(0), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(4))
})
t.Run("change order of bookmarks first to third", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark0.Id, channelId, int64(2), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(4))
// now reset order
th.App.UpdateChannelBookmarkSortOrder(bookmark0.Id, channelId, int64(0), "")
})
t.Run("change order of bookmarks second to third", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark1.Id, channelId, int64(2), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(4))
})
t.Run("change order of bookmarks third to second", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark1.Id, channelId, int64(1), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(4))
})
t.Run("change order of bookmarks last to previous last", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark4.Id, channelId, int64(3), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(4))
})
t.Run("change order of bookmarks last to second", func(t *testing.T) {
bookmarks, sortErr := th.App.UpdateChannelBookmarkSortOrder(bookmark3.Id, channelId, int64(1), "")
require.Nil(t, sortErr)
require.NotNil(t, bookmarks)
assert.Equal(t, find_bookmark(bookmarks, bookmark0.Id).SortOrder, int64(0))
assert.Equal(t, find_bookmark(bookmarks, bookmark3.Id).SortOrder, int64(1))
assert.Equal(t, find_bookmark(bookmarks, bookmark1.Id).SortOrder, int64(2))
assert.Equal(t, find_bookmark(bookmarks, bookmark2.Id).SortOrder, int64(3))
assert.Equal(t, find_bookmark(bookmarks, bookmark4.Id).SortOrder, int64(4))
})
t.Run("change order of bookmarks error when new index is out of bounds", func(t *testing.T) {
_, appErr = th.App.UpdateChannelBookmarkSortOrder(bookmark3.Id, channelId, int64(-1), "")
assert.Error(t, appErr)
_, appErr = th.App.UpdateChannelBookmarkSortOrder(bookmark3.Id, channelId, int64(5), "")
assert.Error(t, appErr)
})
t.Run("change order of bookmarks error when bookmark not found", func(t *testing.T) {
_, appErr = th.App.UpdateChannelBookmarkSortOrder(model.NewId(), channelId, int64(0), "")
assert.Error(t, appErr)
})
}

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

@@ -1716,6 +1716,7 @@ func TestPatchChannelModerationsForChannel(t *testing.T) {
createReactions := model.ChannelModeratedPermissions[1]
manageMembers := model.ChannelModeratedPermissions[2]
channelMentions := model.ChannelModeratedPermissions[3]
manageBookmarks := model.ChannelModeratedPermissions[4]
nonChannelModeratedPermission := model.PermissionCreateBot.Id
@@ -1809,6 +1810,26 @@ func TestPatchChannelModerationsForChannel(t *testing.T) {
},
},
},
{
Name: "Removing manage bookmarks from members role",
ChannelModerationsPatch: []*model.ChannelModerationPatch{
{
Name: &manageBookmarks,
Roles: &model.ChannelModeratedRolesPatch{Members: model.NewBool(false)},
},
},
PermissionsModeratedByPatch: map[string]*model.ChannelModeratedRoles{
manageBookmarks: {
Members: &model.ChannelModeratedRole{Value: false, Enabled: true},
},
},
RevertChannelModerationsPatch: []*model.ChannelModerationPatch{
{
Name: &manageBookmarks,
Roles: &model.ChannelModeratedRolesPatch{Members: model.NewBool(true)},
},
},
},
{
Name: "Removing create posts from guests role",
ChannelModerationsPatch: []*model.ChannelModerationPatch{
@@ -1881,6 +1902,18 @@ func TestPatchChannelModerationsForChannel(t *testing.T) {
ShouldError: false,
ShouldHaveNoChannelScheme: true,
},
{
Name: "Removing manage bookmarks from guests role should not error",
ChannelModerationsPatch: []*model.ChannelModerationPatch{
{
Name: &manageBookmarks,
Roles: &model.ChannelModeratedRolesPatch{Guests: model.NewBool(false)},
},
},
PermissionsModeratedByPatch: map[string]*model.ChannelModeratedRoles{},
ShouldError: false,
ShouldHaveNoChannelScheme: true,
},
{
Name: "Removing a permission that is not channel moderated should not error",
ChannelModerationsPatch: []*model.ChannelModerationPatch{
@@ -1981,6 +2014,12 @@ func TestPatchChannelModerationsForChannel(t *testing.T) {
Members: model.NewBool(true),
},
},
{
Name: &manageBookmarks,
Roles: &model.ChannelModeratedRolesPatch{
Members: model.NewBool(true),
},
},
},
PermissionsModeratedByPatch: map[string]*model.ChannelModeratedRoles{},
ShouldHaveNoChannelScheme: true,
@@ -2039,7 +2078,7 @@ func TestPatchChannelModerationsForChannel(t *testing.T) {
if permission, found := tc.PermissionsModeratedByPatch[moderation.Name]; found && permission.Guests != nil {
require.Equal(t, moderation.Roles.Guests.Value, permission.Guests.Value)
require.Equal(t, moderation.Roles.Guests.Enabled, permission.Guests.Enabled)
} else if moderation.Name == manageMembers {
} else if moderation.Name == manageMembers || moderation.Name == "manage_bookmarks" {
require.Empty(t, moderation.Roles.Guests)
} else {
require.Equal(t, moderation.Roles.Guests.Value, true)

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

@@ -704,6 +704,7 @@ func (t *UploadFileTask) init(a *App) {
t.fileinfo.CreatorId = t.UserId
t.fileinfo.CreateAt = t.Timestamp.UnixNano() / int64(time.Millisecond)
t.fileinfo.Path = t.pathPrefix() + t.Name
t.fileinfo.ChannelId = t.ChannelId
t.limitedInput = &io.LimitedReader{
R: t.Input,
@@ -950,6 +951,12 @@ func (t *UploadFileTask) postprocessImage(file io.Reader) {
}
func (t UploadFileTask) pathPrefix() string {
if t.UserId == model.BookmarkFileOwner {
return model.BookmarkFileOwner +
"/teams/" + t.TeamId +
"/channels/" + t.ChannelId +
"/" + t.fileinfo.Id + "/"
}
return t.Timestamp.Format("20060102") +
"/teams/" + t.TeamId +
"/channels/" + t.ChannelId +
@@ -1003,6 +1010,9 @@ func (a *App) DoUploadFileExpectModification(c request.CTX, now time.Time, rawTe
info.CreateAt = now.UnixNano() / int64(time.Millisecond)
pathPrefix := now.Format("20060102") + "/teams/" + teamID + "/channels/" + channelID + "/users/" + userID + "/" + info.Id + "/"
if userID == model.BookmarkFileOwner {
pathPrefix = model.BookmarkFileOwner + "/teams/" + teamID + "/channels/" + channelID + "/" + info.Id + "/"
}
info.Path = pathPrefix + filename
if info.IsImage() && !info.IsSvg() {

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

@@ -96,6 +96,16 @@ func TestDoUploadFile(t *testing.T) {
value = fmt.Sprintf("20090305/teams/%v/channels/%v/users/%v/%v/%v", teamID, channelID, userID, info4.Id, filename)
assert.Equal(t, value, info4.Path, "stored file at incorrect path")
info5, err := th.App.DoUploadFile(th.Context, time.Date(2008, 3, 5, 1, 2, 3, 4, time.Local), teamID, channelID, model.BookmarkFileOwner, filename, data)
require.Nil(t, err, "DoUploadFile should succeed with valid data")
defer func() {
th.App.Srv().Store().FileInfo().PermanentDelete(th.Context, info5.Id)
th.App.RemoveFile(info3.Path)
}()
value = fmt.Sprintf("%v/teams/%v/channels/%v/%v/%v", model.BookmarkFileOwner, teamID, channelID, info5.Id, filename)
assert.Equal(t, value, info5.Path, "stored file at incorrect path")
}
func TestUploadFile(t *testing.T) {

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

@@ -1994,6 +1994,28 @@ func (a *OpenTracingAppLayer) CreateChannel(c request.CTX, channel *model.Channe
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) CreateChannelBookmark(c request.CTX, newBookmark *model.ChannelBookmark, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateChannelBookmark")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.CreateChannelBookmark(c, newBookmark, connectionId)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) CreateChannelScheme(c request.CTX, channel *model.Channel) (*model.Scheme, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateChannelScheme")
@@ -3093,6 +3115,28 @@ func (a *OpenTracingAppLayer) DeleteChannel(c request.CTX, channel *model.Channe
return resultVar0
}
func (a *OpenTracingAppLayer) DeleteChannelBookmark(bookmarkId string, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DeleteChannelBookmark")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.DeleteChannelBookmark(bookmarkId, connectionId)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) DeleteChannelScheme(c request.CTX, channel *model.Channel) (*model.Channel, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DeleteChannelScheme")
@@ -5138,6 +5182,28 @@ func (a *OpenTracingAppLayer) GetAuthorizedAppsForUser(userID string, page int,
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetBookmark(bookmarkId string, includeDeleted bool) (*model.ChannelBookmarkWithFileInfo, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetBookmark")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetBookmark(bookmarkId, includeDeleted)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetBot(rctx request.CTX, botUserId string, includeDeleted bool) (*model.Bot, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetBot")
@@ -5248,6 +5314,28 @@ func (a *OpenTracingAppLayer) GetChannel(c request.CTX, channelID string) (*mode
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetChannelBookmarks(channelId string, since int64) ([]*model.ChannelBookmarkWithFileInfo, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelBookmarks")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetChannelBookmarks(channelId, since)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetChannelByName(c request.CTX, channelName string, teamID string, includeDeleted bool) (*model.Channel, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetChannelByName")
@@ -17562,6 +17650,50 @@ func (a *OpenTracingAppLayer) UpdateChannel(c request.CTX, channel *model.Channe
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) UpdateChannelBookmark(c request.CTX, updateBookmark *model.ChannelBookmarkWithFileInfo, connectionId string) (*model.UpdateChannelBookmarkResponse, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateChannelBookmark")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.UpdateChannelBookmark(c, updateBookmark, connectionId)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) UpdateChannelBookmarkSortOrder(bookmarkId string, channelId string, newIndex int64, connectionId string) ([]*model.ChannelBookmarkWithFileInfo, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateChannelBookmarkSortOrder")
a.ctx = newCtx
a.app.Srv().Store().SetContext(newCtx)
defer func() {
a.app.Srv().Store().SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.UpdateChannelBookmarkSortOrder(bookmarkId, channelId, newIndex, connectionId)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) UpdateChannelMemberNotifyProps(c request.CTX, data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateChannelMemberNotifyProps")

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

@@ -1156,6 +1156,31 @@ func (a *App) getAddOutgoingOAuthConnectionsPermissions() (permissionsMap, error
return t, nil
}
func (a *App) getAddChannelBookmarksPermissionsMigration() (permissionsMap, error) {
transformations := []permissionTransformation{}
transformations = append(transformations, permissionTransformation{
On: permissionOr(
isRole(model.ChannelUserRoleId),
isRole(model.ChannelAdminRoleId),
isRole(model.TeamAdminRoleId),
isRole(model.SystemAdminRoleId),
),
Add: []string{
model.PermissionAddBookmarkPublicChannel.Id,
model.PermissionEditBookmarkPublicChannel.Id,
model.PermissionDeleteBookmarkPublicChannel.Id,
model.PermissionOrderBookmarkPublicChannel.Id,
model.PermissionAddBookmarkPrivateChannel.Id,
model.PermissionEditBookmarkPrivateChannel.Id,
model.PermissionDeleteBookmarkPrivateChannel.Id,
model.PermissionOrderBookmarkPrivateChannel.Id,
},
})
return transformations, nil
}
// DoPermissionsMigrations execute all the permissions migrations need by the current version.
func (a *App) DoPermissionsMigrations() error {
return a.Srv().doPermissionsMigrations()
@@ -1202,6 +1227,7 @@ func (s *Server) doPermissionsMigrations() error {
{Key: model.MigrationKeyAddReadChannelContentPermissions, Migration: a.getAddChannelReadContentPermissions},
{Key: model.MigrationKeyAddIPFilteringPermissions, Migration: a.getAddIPFilterPermissionsMigration},
{Key: model.MigrationKeyAddOutgoingOAuthConnectionsPermissions, Migration: a.getAddOutgoingOAuthConnectionsPermissions},
{Key: model.MigrationKeyAddChannelBookmarksPermissions, Migration: a.getAddChannelBookmarksPermissionsMigration},
}
roles, err := s.Store().Role().GetAll()