mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-16 15:19:06 +00:00
add can_share_repo role permission (#6234)
* add can_share_repo role permission * update * update --------- Co-authored-by: r350178982 <32759763+r350178982@users.noreply.github.com>
This commit is contained in:
@@ -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';
|
||||
@@ -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')}
|
||||
|
@@ -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';
|
||||
@@ -138,7 +138,7 @@ 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>
|
||||
@@ -146,12 +146,14 @@ class MainSideNav extends React.Component {
|
||||
</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>
|
||||
);
|
||||
|
@@ -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;
|
||||
|
@@ -29,6 +29,9 @@ class CustomSharePermissionsView(APIView):
|
||||
"""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)
|
||||
@@ -53,6 +56,9 @@ class CustomSharePermissionsView(APIView):
|
||||
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)
|
||||
@@ -98,6 +104,9 @@ class CustomSharePermissionView(APIView):
|
||||
"""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)
|
||||
@@ -122,6 +131,9 @@ class CustomSharePermissionView(APIView):
|
||||
"""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.'
|
||||
@@ -170,6 +182,9 @@ class CustomSharePermissionView(APIView):
|
||||
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
|
||||
|
@@ -61,10 +61,13 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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 == '/':
|
||||
@@ -98,10 +101,13 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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 == '/':
|
||||
@@ -129,11 +135,10 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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({
|
||||
@@ -197,6 +202,9 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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)
|
||||
@@ -220,6 +228,9 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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:
|
||||
@@ -305,6 +316,10 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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:
|
||||
@@ -368,8 +383,7 @@ class DirSharedItemsEndpoint(APIView):
|
||||
|
||||
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,
|
||||
@@ -377,7 +391,8 @@ class DirSharedItemsEndpoint(APIView):
|
||||
})
|
||||
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:
|
||||
@@ -477,7 +492,8 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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
|
||||
|
||||
@@ -513,9 +529,14 @@ class DirSharedItemsEndpoint(APIView):
|
||||
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:
|
||||
@@ -556,7 +577,7 @@ class DirSharedItemsEndpoint(APIView):
|
||||
|
||||
# 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
|
||||
@@ -601,8 +622,8 @@ class DirSharedItemsEndpoint(APIView):
|
||||
|
||||
# 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)
|
||||
|
||||
|
@@ -33,6 +33,8 @@ class SharedFolders(APIView):
|
||||
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
|
||||
|
@@ -38,6 +38,8 @@ class SharedRepos(APIView):
|
||||
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
|
||||
@@ -128,6 +130,9 @@ class SharedRepo(APIView):
|
||||
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)
|
||||
@@ -244,7 +249,9 @@ class SharedRepo(APIView):
|
||||
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:
|
||||
|
@@ -359,6 +359,9 @@ class UserPermissions(object):
|
||||
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')
|
||||
|
||||
|
@@ -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,
|
||||
@@ -48,6 +49,7 @@ DEFAULT_ENABLED_ROLE_PERMISSIONS = {
|
||||
},
|
||||
GUEST_USER: {
|
||||
'can_add_repo': False,
|
||||
'can_share_repo': False,
|
||||
'can_add_group': False,
|
||||
'can_view_org': False,
|
||||
'can_add_public_repo': False,
|
||||
|
@@ -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 %},
|
||||
|
@@ -11,4 +11,4 @@ class UtilsTest(BaseTestCase):
|
||||
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
|
||||
|
Reference in New Issue
Block a user