Skip to content

Commit

Permalink
add can_share_repo role permission (#6234)
Browse files Browse the repository at this point in the history
* add can_share_repo role permission

* update

* update

---------

Co-authored-by: r350178982 <32759763+r350178982@users.noreply.github.com>
  • Loading branch information
imwhatiam and r350178982 authored Jun 24, 2024
1 parent ce19f90 commit 2694bff
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 38 deletions.
28 changes: 16 additions & 12 deletions frontend/src/components/dialog/share-dialog.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import { gettext, username, canGenerateShareLink, canGenerateUploadLink, canInvitePeople, additionalShareDialogNote, enableOCM, isPro } from '../../utils/constants';
import { gettext, username, canGenerateShareLink, canGenerateUploadLink, canInvitePeople, additionalShareDialogNote, enableOCM, isPro, canShareRepo } from '../../utils/constants';
import ShareLinkPanel from '../share-link-panel';
import GenerateUploadLink from './generate-upload-link';
import ShareToUser from './share-to-user';
Expand Down Expand Up @@ -131,17 +131,21 @@ class ShareDialog extends React.Component {
}
{enableDirPrivateShare &&
<Fragment>
<NavItem role="tab" aria-selected={activeTab === 'shareToUser'} aria-controls="share-to-user-panel">
<NavLink className={activeTab === 'shareToUser' ? 'active' : ''} onClick={this.toggle.bind(this, 'shareToUser')} tabIndex="0" onKeyDown={this.onTabKeyDown}>
{gettext('Share to user')}
</NavLink>
</NavItem>
<NavItem role="tab" aria-selected={activeTab === 'shareToGroup'} aria-controls="share-to-group-panel">
<NavLink className={activeTab === 'shareToGroup' ? 'active' : ''} onClick={this.toggle.bind(this, 'shareToGroup')} tabIndex="0" onKeyDown={this.onTabKeyDown}>
{gettext('Share to group')}
</NavLink>
</NavItem>
{isPro && !isCustomPermission && (
{ canShareRepo && (
<NavItem role="tab" aria-selected={activeTab === 'shareToUser'} aria-controls="share-to-user-panel">
<NavLink className={activeTab === 'shareToUser' ? 'active' : ''} onClick={this.toggle.bind(this, 'shareToUser')} tabIndex="0" onKeyDown={this.onTabKeyDown}>
{gettext('Share to user')}
</NavLink>
</NavItem>
)}
{ canShareRepo && (
<NavItem role="tab" aria-selected={activeTab === 'shareToGroup'} aria-controls="share-to-group-panel">
<NavLink className={activeTab === 'shareToGroup' ? 'active' : ''} onClick={this.toggle.bind(this, 'shareToGroup')} tabIndex="0" onKeyDown={this.onTabKeyDown}>
{gettext('Share to group')}
</NavLink>
</NavItem>
)}
{isPro && !isCustomPermission && canShareRepo && (
<NavItem role="tab" aria-selected={activeTab === 'customSharePermission'} aria-controls="custom-share-perm-panel">
<NavLink className={activeTab === 'customSharePermission' ? 'active' : ''} onClick={this.toggle.bind(this, 'customSharePermission')} tabIndex="0" onKeyDown={this.onTabKeyDown}>
{gettext('Custom sharing permissions')}
Expand Down
18 changes: 10 additions & 8 deletions frontend/src/components/main-side-nav.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from '@gatsbyjs/reach-router';
import { gettext, siteRoot, canAddRepo, canGenerateShareLink, canGenerateUploadLink, canInvitePeople, enableOCM, enableOCMViaWebdav } from '../utils/constants';
import { gettext, siteRoot, canAddRepo, canShareRepo, canGenerateShareLink, canGenerateUploadLink, canInvitePeople, enableOCM, enableOCMViaWebdav } from '../utils/constants';
import { seafileAPI } from '../utils/seafile-api';
import { Utils } from '../utils/utils';
import toaster from './toast';
Expand Down Expand Up @@ -138,20 +138,22 @@ class MainSideNav extends React.Component {
}
return (
<ul className={`nav sub-nav nav-pills flex-column ${this.state.sharedExtended ? 'side-panel-slide' : 'side-panel-slide-up'}`} style={style} >
{canAddRepo && (
{canAddRepo && canShareRepo && (
<li className="nav-item">
<Link to={siteRoot + 'share-admin-libs/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-libs')}`} title={gettext('Libraries')} onClick={(e) => this.tabItemClick(e, 'share-admin-libs')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Libraries')}</span>
</Link>
</li>
)}
<li className="nav-item">
<Link to={siteRoot + 'share-admin-folders/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-folders')}`} title={gettext('Folders')} onClick={(e) => this.tabItemClick(e, 'share-admin-folders')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Folders')}</span>
</Link>
</li>
{canShareRepo && (
<li className="nav-item">
<Link to={siteRoot + 'share-admin-folders/'} className={`nav-link ellipsis ${this.getActiveClass('share-admin-folders')}`} title={gettext('Folders')} onClick={(e) => this.tabItemClick(e, 'share-admin-folders')}>
<span aria-hidden="true" className="sharp">#</span>
<span className="nav-text">{gettext('Folders')}</span>
</Link>
</li>
)}
{linksNavItem}
</ul>
);
Expand Down
1 change: 1 addition & 0 deletions frontend/src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const name = window.app.pageOptions.name;
export const contactEmail = window.app.pageOptions.contactEmail;
export const username = window.app.pageOptions.username;
export const canAddRepo = window.app.pageOptions.canAddRepo;
export const canShareRepo = window.app.pageOptions.canShareRepo;
export const canAddGroup = window.app.pageOptions.canAddGroup;
export const groupImportMembersExtraMsg = window.app.pageOptions.groupImportMembersExtraMsg;
export const canGenerateShareLink = window.app.pageOptions.canGenerateShareLink;
Expand Down
15 changes: 15 additions & 0 deletions seahub/api2/endpoints/custom_share_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ def get(self, request, repo_id):
"""List custom share permissions
"""
# permission check
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

if not check_folder_permission(request, repo_id, '/'):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
Expand All @@ -53,6 +56,9 @@ def get(self, request, repo_id):
def post(self, request, repo_id):
"""Add a custom share permission
"""
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

username = request.user.username
# argument check
permission = request.data.get('permission', None)
Expand Down Expand Up @@ -98,6 +104,9 @@ def get(self, request, repo_id, permission_id):
"""get a custom share permission
"""
# permission check
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

if not check_folder_permission(request, repo_id, '/'):
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
Expand All @@ -122,6 +131,9 @@ def put(self, request, repo_id, permission_id):
"""Update a custom share permission
"""
# argument check
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

permission = request.data.get('permission', None)
if not permission:
error_msg = 'permission invalid.'
Expand Down Expand Up @@ -170,6 +182,9 @@ def put(self, request, repo_id, permission_id):
def delete(self, request, repo_id, permission_id):
"""Delete a custom share permission
"""
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

username = request.user.username

# permission check
Expand Down
53 changes: 37 additions & 16 deletions seahub/api2/endpoints/dir_shared_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ def list_user_shared_items(self, request, repo_id, path):
org_id = request.user.org.org_id
if path == '/':
share_items = seafile_api.list_org_repo_shared_to(org_id,
repo_owner, repo_id)
repo_owner,
repo_id)
else:
share_items = seafile_api.get_org_shared_users_for_subdir(org_id,
repo_id, path, repo_owner)
repo_id,
path,
repo_owner)
else:
repo_owner = seafile_api.get_repo_owner(repo_id)
if path == '/':
Expand Down Expand Up @@ -98,10 +101,13 @@ def list_group_shared_items(self, request, repo_id, path):
org_id = request.user.org.org_id
if path == '/':
share_items = seafile_api.list_org_repo_shared_group(org_id,
repo_owner, repo_id)
repo_owner,
repo_id)
else:
share_items = seafile_api.get_org_shared_groups_for_subdir(org_id,
repo_id, path, repo_owner)
repo_id,
path,
repo_owner)
else:
repo_owner = seafile_api.get_repo_owner(repo_id)
if path == '/':
Expand Down Expand Up @@ -129,11 +135,10 @@ def list_group_shared_items(self, request, repo_id, path):
org_id, repo_id, path, repo_owner, group_id)
else:
if path == '/':
seafile_api.unset_group_repo(repo_id, group_id,
repo_owner)
seafile_api.unset_group_repo(repo_id, group_id, repo_owner)
else:
seafile_api.unshare_subdir_for_group(
repo_id, path, repo_owner, group_id)
seafile_api.unshare_subdir_for_group(repo_id, path,
repo_owner, group_id)
continue

ret.append({
Expand Down Expand Up @@ -197,6 +202,9 @@ def has_shared_to_group(self, request, repo_id, path, group_id):
def get(self, request, repo_id, format=None):
"""List shared items(shared to users/groups) for a folder/library.
"""
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

repo = seafile_api.get_repo(repo_id)
if not repo:
return api_error(status.HTTP_404_NOT_FOUND, 'Library %s not found.' % repo_id)
Expand All @@ -220,6 +228,9 @@ def get(self, request, repo_id, format=None):
def post(self, request, repo_id, format=None):
"""Update shared item permission.
"""
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

username = request.user.username
repo = seafile_api.get_repo(repo_id)
if not repo:
Expand Down Expand Up @@ -305,6 +316,10 @@ def post(self, request, repo_id, format=None):
content_type=json_content_type)

def put(self, request, repo_id, format=None):

if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

username = request.user.username
repo = seafile_api.get_repo(repo_id)
if not repo:
Expand Down Expand Up @@ -368,16 +383,16 @@ def put(self, request, repo_id, format=None):

if not is_org_user(to_user, int(org_id)):
org_name = request.user.org.org_name
error_msg = 'User %s is not member of organization %s.' \
% (to_user, org_name)
error_msg = f'User {to_user} is not member of organization {org_name}.'

result['failed'].append({
'email': to_user,
'error_msg': error_msg
})
continue

# when calling seafile API to share authority related functions, change the uesrname to repo owner.
# when calling seafile API to share authority related functions,
# change the uesrname to repo owner.
repo_owner = seafile_api.get_org_repo_owner(repo_id)
# can't share to owner
if to_user == repo_owner:
Expand Down Expand Up @@ -477,7 +492,8 @@ def put(self, request, repo_id, format=None):
try:
org_id = None
if is_org_context(request):
# when calling seafile API to share authority related functions, change the uesrname to repo owner.
# when calling seafile API to share authority related functions,
# change the uesrname to repo owner.
repo_owner = seafile_api.get_org_repo_owner(repo_id)
org_id = request.user.org.org_id

Expand Down Expand Up @@ -513,9 +529,14 @@ def put(self, request, repo_id, format=None):
continue

return HttpResponse(json.dumps(result),
status=200, content_type=json_content_type)
status=200,
content_type=json_content_type)

def delete(self, request, repo_id, format=None):

if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

username = request.user.username
repo = seafile_api.get_repo(repo_id)
if not repo:
Expand Down Expand Up @@ -556,7 +577,7 @@ def delete(self, request, repo_id, format=None):

# Delete share permission at ExtraSharePermission table.
if path == '/':
ExtraSharePermission.objects.delete_share_permission(repo_id,
ExtraSharePermission.objects.delete_share_permission(repo_id,
shared_to)

org_id = None
Expand Down Expand Up @@ -601,8 +622,8 @@ def delete(self, request, repo_id, format=None):

# delete share permission if repo is deleted
if path == '/':
ExtraGroupsSharePermission.objects.delete_share_permission(repo_id,
group_id)
ExtraGroupsSharePermission.objects.delete_share_permission(repo_id,
group_id)
send_perm_audit_msg('delete-repo-perm', username, group_id,
repo_id, path, permission)

Expand Down
2 changes: 2 additions & 0 deletions seahub/api2/endpoints/shared_folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def get(self, request, format=None):
Permission checking:
1. all authenticated user can perform this action.
"""
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

shared_repos = []
username = request.user.username
Expand Down
9 changes: 8 additions & 1 deletion seahub/api2/endpoints/shared_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def get(self, request, format=None):
Permission checking:
1. all authenticated user can perform this action.
"""
if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

shared_repos = []
username = request.user.username
Expand Down Expand Up @@ -128,6 +130,9 @@ def put(self, request, repo_id, format=None):
Permission checking:
1. Only repo owner can update.
"""

if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

# argument check
permission = request.data.get('permission', None)
Expand Down Expand Up @@ -244,7 +249,9 @@ def delete(self, request, repo_id, format=None):
Permission checking:
1. Only repo owner and system admin can unshare a publib library.
"""

if not request.user.permissions.can_share_repo():
return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

# argument check
share_type = request.GET.get('share_type', None)
if not share_type:
Expand Down
3 changes: 3 additions & 0 deletions seahub/base/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ def _get_perm_by_roles(self, perm_name):
def can_add_repo(self):
return self._get_perm_by_roles('can_add_repo')

def can_share_repo(self):
return self._get_perm_by_roles('can_share_repo')

def can_add_group(self):
return self._get_perm_by_roles('can_add_group')

Expand Down
2 changes: 2 additions & 0 deletions seahub/role_permissions/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def merge_roles(default, custom):
DEFAULT_ENABLED_ROLE_PERMISSIONS = {
DEFAULT_USER: {
'can_add_repo': True,
'can_share_repo': True,
'can_add_group': True,
'can_view_org': True,
'can_add_public_repo': False,
Expand All @@ -48,6 +49,7 @@ def merge_roles(default, custom):
},
GUEST_USER: {
'can_add_repo': False,
'can_share_repo': False,
'can_add_group': False,
'can_view_org': False,
'can_add_public_repo': False,
Expand Down
1 change: 1 addition & 0 deletions seahub/templates/base_for_react.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
guideEnabled: {% if guide_enabled %} true {% else %} false {% endif %},
trashReposExpireDays: {% if trash_repos_expire_days >= 0 %} {{ trash_repos_expire_days }} {% else %} null {% endif %},
canAddRepo: {% if user.permissions.can_add_repo %} true {% else %} false {% endif %},
canShareRepo: {% if user.permissions.can_share_repo %} true {% else %} false {% endif %},
canAddGroup: {% if user.permissions.can_add_group %} true {% else %} false {% endif %},
groupImportMembersExtraMsg: "{{group_import_members_extra_msg}}",
canGenerateShareLink: {% if user.permissions.can_generate_share_link %} true {% else %} false {% endif %},
Expand Down
2 changes: 1 addition & 1 deletion tests/seahub/role_permissions/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ def test_get_available_role(self):
assert DEFAULT_USER in get_available_roles()

def test_get_enabled_role_permissions_by_role(self):
assert len(list(get_enabled_role_permissions_by_role(DEFAULT_USER).keys())) == 19
assert len(list(get_enabled_role_permissions_by_role(DEFAULT_USER).keys())) == 20

0 comments on commit 2694bff

Please sign in to comment.