mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-21 13:38:56 +02:00
fixing role dropdown for admins
This commit is contained in:
parent
098868387e
commit
84614b8f4f
@ -22,6 +22,7 @@ const linkBoardMessage = "@%s linked the board [%s](%s) with this channel"
|
|||||||
const unlinkBoardMessage = "@%s unlinked the board [%s](%s) with this channel"
|
const unlinkBoardMessage = "@%s unlinked the board [%s](%s) with this channel"
|
||||||
|
|
||||||
var errNoDefaultCategoryFound = errors.New("no default category found for user")
|
var errNoDefaultCategoryFound = errors.New("no default category found for user")
|
||||||
|
var errMemberRoleCannotBeChanged = errors.New("cannot change the role of this member")
|
||||||
|
|
||||||
func (a *App) GetBoard(boardID string) (*model.Board, error) {
|
func (a *App) GetBoard(boardID string) (*model.Board, error) {
|
||||||
board, err := a.store.GetBoard(boardID)
|
board, err := a.store.GetBoard(boardID)
|
||||||
@ -604,6 +605,10 @@ func (a *App) UpdateBoardMember(member *model.BoardMember) (*model.BoardMember,
|
|||||||
return nil, bErr
|
return nil, bErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.permissions.HasPermissionToTeam(member.UserID, board.TeamID, model.PermissionManageTeam) {
|
||||||
|
return nil, errMemberRoleCannotBeChanged
|
||||||
|
}
|
||||||
|
|
||||||
oldMember, err := a.store.GetMemberForBoard(member.BoardID, member.UserID)
|
oldMember, err := a.store.GetMemberForBoard(member.BoardID, member.UserID)
|
||||||
if model.IsErrNotFound(err) {
|
if model.IsErrNotFound(err) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -1598,6 +1598,34 @@ func TestUpdateMember(t *testing.T) {
|
|||||||
require.True(t, members[0].SchemeAdmin)
|
require.True(t, members[0].SchemeAdmin)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("should not update a member if they are a team admin or higher", func(t *testing.T) {
|
||||||
|
th := SetupTestHelper(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
newBoard := &model.Board{
|
||||||
|
Title: "title",
|
||||||
|
Type: model.BoardTypePrivate,
|
||||||
|
TeamID: teamID,
|
||||||
|
}
|
||||||
|
board, err := th.Server.App().CreateBoard(newBoard, th.GetUser1().ID, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
memberUpdate := &model.BoardMember{
|
||||||
|
UserID: th.GetUser1().ID,
|
||||||
|
BoardID: board.ID,
|
||||||
|
SchemeEditor: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedUser1Member, resp := th.Client.UpdateBoardMember(memberUpdate)
|
||||||
|
th.CheckBadRequest(resp)
|
||||||
|
require.Nil(t, updatedUser1Member)
|
||||||
|
|
||||||
|
members, err := th.Server.App().GetMembersForBoard(board.ID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, members, 1)
|
||||||
|
require.True(t, members[0].SchemeAdmin)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("should always disable the admin role on update member if the user is a guest", func(t *testing.T) {
|
t.Run("should always disable the admin role on update member if the user is a guest", func(t *testing.T) {
|
||||||
th := SetupTestHelperPluginMode(t)
|
th := SetupTestHelperPluginMode(t)
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
@ -78,8 +78,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot 1`]
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Commenter"
|
aria-label="Commenter"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -109,8 +107,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot 1`]
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Editor"
|
aria-label="Editor"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -140,8 +136,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot 1`]
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Admin"
|
aria-label="Admin"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -177,8 +171,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot 1`]
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
class="MenuOption MenuSeparator menu-separator"
|
class="MenuOption MenuSeparator menu-separator"
|
||||||
/>
|
/>
|
||||||
@ -332,8 +324,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in p
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Commenter"
|
aria-label="Commenter"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -363,8 +353,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in p
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Editor"
|
aria-label="Editor"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -394,8 +382,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in p
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Admin"
|
aria-label="Admin"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -431,8 +417,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in p
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
class="MenuOption MenuSeparator menu-separator"
|
class="MenuOption MenuSeparator menu-separator"
|
||||||
/>
|
/>
|
||||||
@ -586,9 +570,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in t
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div />
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Editor"
|
aria-label="Editor"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -618,8 +599,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in t
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
aria-label="Admin"
|
aria-label="Admin"
|
||||||
class="MenuOption TextOption menu-option"
|
class="MenuOption TextOption menu-option"
|
||||||
@ -655,8 +634,6 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot in t
|
|||||||
class="noicon"
|
class="noicon"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
<div
|
||||||
class="MenuOption MenuSeparator menu-separator"
|
class="MenuOption MenuSeparator menu-separator"
|
||||||
/>
|
/>
|
||||||
@ -786,141 +763,7 @@ exports[`src/components/shareBoard/userPermissionsRow should match snapshot-admi
|
|||||||
<div
|
<div
|
||||||
class="menu-options"
|
class="menu-options"
|
||||||
>
|
>
|
||||||
<div>
|
<div />
|
||||||
<div
|
|
||||||
aria-label="Viewer"
|
|
||||||
class="MenuOption TextOption menu-option"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="d-flex menu-option__check"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-option__icon"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="empty-icon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="menu-option__content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-name"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="noicon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="Commenter"
|
|
||||||
class="MenuOption TextOption menu-option"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="d-flex menu-option__check"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-option__icon"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="empty-icon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="menu-option__content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-name"
|
|
||||||
>
|
|
||||||
Commenter
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="noicon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="Editor"
|
|
||||||
class="MenuOption TextOption menu-option"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="d-flex menu-option__check"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-option__icon"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="empty-icon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="menu-option__content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-name"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="noicon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="Admin"
|
|
||||||
class="MenuOption TextOption menu-option"
|
|
||||||
role="button"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="d-flex menu-option__check"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-option__icon"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="CheckIcon Icon"
|
|
||||||
viewBox="0 0 100 100"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<polyline
|
|
||||||
points="20,60 40,80 80,40"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="menu-option__content"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="menu-name"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="noicon"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="MenuOption MenuSeparator menu-separator"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
aria-label="Remove member"
|
aria-label="Remove member"
|
||||||
|
@ -83,38 +83,43 @@ const UserPermissionsRow = (props: Props): JSX.Element => {
|
|||||||
position='left'
|
position='left'
|
||||||
parentRef={menuWrapperRef}
|
parentRef={menuWrapperRef}
|
||||||
>
|
>
|
||||||
{(board.minimumRole === MemberRole.Viewer || board.minimumRole === MemberRole.None) &&
|
{
|
||||||
<Menu.Text
|
(!user.permissions || user.permissions?.find((s) => s !== 'manage_system' && s !== 'manage_team')) &&
|
||||||
id={MemberRole.Viewer}
|
<>
|
||||||
check={true}
|
{(board.minimumRole === MemberRole.Viewer || board.minimumRole === MemberRole.None) &&
|
||||||
icon={currentRole === MemberRole.Viewer ? <CheckIcon/> : <div className='empty-icon'/>}
|
<Menu.Text
|
||||||
name={intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'})}
|
id={MemberRole.Viewer}
|
||||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Viewer)}
|
check={true}
|
||||||
/>}
|
icon={currentRole === MemberRole.Viewer ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||||
{!board.isTemplate && (board.minimumRole === MemberRole.None || board.minimumRole === MemberRole.Commenter || board.minimumRole === MemberRole.Viewer) &&
|
name={intl.formatMessage({id: 'BoardMember.schemeViewer', defaultMessage: 'Viewer'})}
|
||||||
<Menu.Text
|
onClick={() => props.onUpdateBoardMember(member, MemberRole.Viewer)}
|
||||||
id={MemberRole.Commenter}
|
/>}
|
||||||
check={true}
|
{!board.isTemplate && (board.minimumRole === MemberRole.None || board.minimumRole === MemberRole.Commenter || board.minimumRole === MemberRole.Viewer) &&
|
||||||
icon={currentRole === MemberRole.Commenter ? <CheckIcon/> : <div className='empty-icon'/>}
|
<Menu.Text
|
||||||
name={intl.formatMessage({id: 'BoardMember.schemeCommenter', defaultMessage: 'Commenter'})}
|
id={MemberRole.Commenter}
|
||||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Commenter)}
|
check={true}
|
||||||
/>}
|
icon={currentRole === MemberRole.Commenter ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||||
<Menu.Text
|
name={intl.formatMessage({id: 'BoardMember.schemeCommenter', defaultMessage: 'Commenter'})}
|
||||||
id={MemberRole.Editor}
|
onClick={() => props.onUpdateBoardMember(member, MemberRole.Commenter)}
|
||||||
check={true}
|
/>}
|
||||||
icon={currentRole === MemberRole.Editor ? <CheckIcon/> : <div className='empty-icon'/>}
|
<Menu.Text
|
||||||
name={intl.formatMessage({id: 'BoardMember.schemeEditor', defaultMessage: 'Editor'})}
|
id={MemberRole.Editor}
|
||||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Editor)}
|
check={true}
|
||||||
/>
|
icon={currentRole === MemberRole.Editor ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||||
{user.is_guest !== true &&
|
name={intl.formatMessage({id: 'BoardMember.schemeEditor', defaultMessage: 'Editor'})}
|
||||||
<Menu.Text
|
onClick={() => props.onUpdateBoardMember(member, MemberRole.Editor)}
|
||||||
id={MemberRole.Admin}
|
/>
|
||||||
check={true}
|
{user.is_guest !== true &&
|
||||||
icon={currentRole === MemberRole.Admin ? <CheckIcon/> : <div className='empty-icon'/>}
|
<Menu.Text
|
||||||
name={intl.formatMessage({id: 'BoardMember.schemeAdmin', defaultMessage: 'Admin'})}
|
id={MemberRole.Admin}
|
||||||
onClick={() => props.onUpdateBoardMember(member, MemberRole.Admin)}
|
check={true}
|
||||||
/>}
|
icon={currentRole === MemberRole.Admin ? <CheckIcon/> : <div className='empty-icon'/>}
|
||||||
<Menu.Separator/>
|
name={intl.formatMessage({id: 'BoardMember.schemeAdmin', defaultMessage: 'Admin'})}
|
||||||
|
onClick={() => props.onUpdateBoardMember(member, MemberRole.Admin)}
|
||||||
|
/>}
|
||||||
|
<Menu.Separator/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
<Menu.Text
|
<Menu.Text
|
||||||
id='Remove'
|
id='Remove'
|
||||||
name={intl.formatMessage({id: 'ShareBoard.userPermissionsRemoveMemberText', defaultMessage: 'Remove member'})}
|
name={intl.formatMessage({id: 'ShareBoard.userPermissionsRemoveMemberText', defaultMessage: 'Remove member'})}
|
||||||
|
Loading…
Reference in New Issue
Block a user