1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-11 03:41:12 +00:00

sysadmin can share repo with admin permission

This commit is contained in:
zming
2018-01-29 13:07:08 +08:00
parent f797d2d523
commit 5f9033b5ff
7 changed files with 439 additions and 66 deletions

View File

@@ -13,10 +13,18 @@ from seaserv import seafile_api, ccnet_api
from seahub.api2.authentication import TokenAuthentication from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error from seahub.api2.utils import api_error
from seahub.share.models import ExtraSharePermission, ExtraGroupsSharePermission
from seahub.share.utils import update_user_dir_permission, \
update_group_dir_permission, share_dir_to_user, share_dir_to_group, \
has_shared_to_user, has_shared_to_group, check_user_share_out_permission, \
check_group_share_out_permission
from seahub.share.signals import share_repo_to_user_successful, share_repo_to_group_successful
from seahub.base.accounts import User from seahub.base.accounts import User
from seahub.base.templatetags.seahub_tags import email2nickname from seahub.base.templatetags.seahub_tags import email2nickname
from seahub.utils import is_valid_username from seahub.utils import is_valid_username, send_perm_audit_msg
from seahub.constants import PERMISSION_READ, PERMISSION_READ_WRITE, \
PERMISSION_ADMIN
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -54,7 +62,7 @@ def check_parameter(func):
error_msg = 'Folder %s not found.' % path error_msg = 'Folder %s not found.' % path
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
return func(view, request, repo_id, path, share_type, *args, **kwargs) return func(view, request, repo, path, share_type, *args, **kwargs)
return _decorated return _decorated
@@ -64,7 +72,7 @@ class AdminShares(APIView):
permission_classes = (IsAdminUser,) permission_classes = (IsAdminUser,)
@check_parameter @check_parameter
def get(self, request, repo_id, path, share_type): def get(self, request, repo, path, share_type):
""" List user/group shares """ List user/group shares
Permission checking: Permission checking:
@@ -75,32 +83,34 @@ class AdminShares(APIView):
# current `request.user.username` is admin user, # current `request.user.username` is admin user,
# so need to identify the repo owner specifically. # so need to identify the repo owner specifically.
repo_owner = seafile_api.get_repo_owner(repo_id) repo_owner = seafile_api.get_repo_owner(repo.repo_id)
if share_type == 'user': if share_type == 'user':
try: try:
if path == '/': if path == '/':
share_items = seafile_api.list_repo_shared_to( share_items = seafile_api.list_repo_shared_to(
repo_owner, repo_id) repo_owner, repo.repo_id)
else: else:
share_items = seafile_api.get_shared_users_for_subdir( share_items = seafile_api.get_shared_users_for_subdir(
repo_id, path, repo_owner) repo.repo_id, path, repo_owner)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
admin_users = ExtraSharePermission.objects.get_admin_users_by_repo(repo.repo_id)
for share_item in share_items: for share_item in share_items:
user_email = share_item.user user_email = share_item.user
user_name = email2nickname(user_email) if user_email else '--' user_name = email2nickname(user_email) if user_email else '--'
share_info = {} share_info = {}
share_info['repo_id'] = repo_id share_info['repo_id'] = repo.repo_id
share_info['path'] = path share_info['path'] = path
share_info['share_type'] = share_type share_info['share_type'] = share_type
share_info['user_email'] = user_email share_info['user_email'] = user_email
share_info['user_name'] = user_name share_info['user_name'] = user_name
share_info['permission'] = share_item.perm share_info['permission'] = share_item.perm
share_info['is_admin'] = user_email in admin_users
result.append(share_info) result.append(share_info)
@@ -108,15 +118,16 @@ class AdminShares(APIView):
try: try:
if path == '/': if path == '/':
share_items = seafile_api.list_repo_shared_group_by_user( share_items = seafile_api.list_repo_shared_group_by_user(
repo_owner, repo_id) repo_owner, repo.repo_id)
else: else:
share_items = seafile_api.get_shared_groups_for_subdir( share_items = seafile_api.get_shared_groups_for_subdir(
repo_id, path, repo_owner) repo.repo_id, path, repo_owner)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
admin_groups = ExtraGroupsSharePermission.objects.get_admin_groups_by_repo(repo.repo_id)
for share_item in share_items: for share_item in share_items:
group_id = share_item.group_id group_id = share_item.group_id
@@ -124,19 +135,20 @@ class AdminShares(APIView):
group_name = group.group_name if group else '--' group_name = group.group_name if group else '--'
share_info = {} share_info = {}
share_info['repo_id'] = repo_id share_info['repo_id'] = repo.repo_id
share_info['path'] = path share_info['path'] = path
share_info['share_type'] = share_type share_info['share_type'] = share_type
share_info['group_id'] = group_id share_info['group_id'] = group_id
share_info['group_name'] = group_name share_info['group_name'] = group_name
share_info['permission'] = share_item.perm share_info['permission'] = share_item.perm
share_info['is_admin'] = group_id in admin_groups
result.append(share_info) result.append(share_info)
return Response(result) return Response(result)
@check_parameter @check_parameter
def post(self, request, repo_id, path, share_type): def post(self, request, repo, path, share_type):
""" Admin share a library to user/group. """ Admin share a library to user/group.
Permission checking: Permission checking:
@@ -145,7 +157,9 @@ class AdminShares(APIView):
# argument check # argument check
permission = request.data.get('permission', None) permission = request.data.get('permission', None)
if not permission or permission not in ('r', 'rw'): if not permission or permission not in (PERMISSION_READ,
PERMISSION_READ_WRITE,
PERMISSION_ADMIN):
error_msg = 'permission invalid.' error_msg = 'permission invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
@@ -156,7 +170,8 @@ class AdminShares(APIView):
# current `request.user.username` is admin user, # current `request.user.username` is admin user,
# so need to identify the repo owner specifically. # so need to identify the repo owner specifically.
repo_owner = seafile_api.get_repo_owner(repo_id) repo_owner = seafile_api.get_repo_owner(repo.repo_id)
username = request.user.username
if share_type == 'user': if share_type == 'user':
for email in share_to: for email in share_to:
@@ -186,13 +201,21 @@ class AdminShares(APIView):
continue continue
if has_shared_to_user(repo.repo_id, path, email):
result['failed'].append({
'email': email,
'error_msg': _(u'This item has been shared to %s.') % email
})
continue
try: try:
if path == '/':
seafile_api.share_repo( share_dir_to_user(repo, path, repo_owner, username, email, permission)
repo_id, repo_owner, email, permission) share_repo_to_user_successful.send(sender=None, from_user=username,
else: to_user=email, repo=repo,
seafile_api.share_subdir_to_user( path=path, org_id=None)
repo_id, path, repo_owner, email, permission) send_perm_audit_msg('add-repo-perm', username, email,
repo.repo_id, path, permission)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
@@ -203,14 +226,14 @@ class AdminShares(APIView):
continue continue
new_perm = seafile_api.check_permission_by_path(repo_id, path, email)
result['success'].append({ result['success'].append({
"repo_id": repo_id, "repo_id": repo.repo_id,
"path": path, "path": path,
"share_type": share_type, "share_type": share_type,
"user_email": email, "user_email": email,
"user_name": email2nickname(email), "user_name": email2nickname(email),
"permission": new_perm "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission,
"is_admin": permission == PERMISSION_ADMIN
}) })
if share_type == 'group': if share_type == 'group':
@@ -235,13 +258,23 @@ class AdminShares(APIView):
continue continue
if has_shared_to_group(repo.repo_id, path, group_id):
result['failed'].append({
'group_name': group.group_name,
'error_msg': _(u'This item has been shared to %s.') % group.group_name
})
continue
try: try:
if path == '/': share_dir_to_group(repo, path, repo_owner, username, group_id, permission)
seafile_api.set_group_repo(
repo_id, group_id, repo_owner, permission) share_repo_to_group_successful.send(sender=None,
else: from_user=username,
seafile_api.share_subdir_to_group( group_id=group_id, repo=repo,
repo_id, path, repo_owner, group_id, permission) path=path, org_id=None)
send_perm_audit_msg('add-repo-perm', username, group_id,
repo.repo_id, path, permission)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
result['failed'].append({ result['failed'].append({
@@ -252,18 +285,19 @@ class AdminShares(APIView):
continue continue
result['success'].append({ result['success'].append({
"repo_id": repo_id, "repo_id": repo.repo_id,
"path": path, "path": path,
"share_type": share_type, "share_type": share_type,
"group_id": group_id, "group_id": group_id,
"group_name": group.group_name, "group_name": group.group_name,
"permission": permission "permission": PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission,
"is_admin": permission == PERMISSION_ADMIN
}) })
return Response(result) return Response(result)
@check_parameter @check_parameter
def put(self, request, repo_id, path, share_type): def put(self, request, repo, path, share_type):
""" Update user/group share permission. """ Update user/group share permission.
Permission checking: Permission checking:
@@ -272,18 +306,21 @@ class AdminShares(APIView):
# argument check # argument check
permission = request.data.get('permission', None) permission = request.data.get('permission', None)
if not permission or permission not in ('r', 'rw'): if not permission or permission not in (PERMISSION_READ,
PERMISSION_READ_WRITE,
PERMISSION_ADMIN):
error_msg = 'permission invalid.' error_msg = 'permission invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
share_info = {} share_info = {}
share_info['repo_id'] = repo_id share_info['repo_id'] = repo.repo_id
share_info['path'] = path share_info['path'] = path
share_info['share_type'] = share_type share_info['share_type'] = share_type
# current `request.user.username` is admin user, # current `request.user.username` is admin user,
# so need to identify the repo owner specifically. # so need to identify the repo owner specifically.
repo_owner = seafile_api.get_repo_owner(repo_id) repo_owner = seafile_api.get_repo_owner(repo.repo_id)
username = request.user.username
share_to = request.data.get('share_to', None) share_to = request.data.get('share_to', None)
if share_type == 'user': if share_type == 'user':
@@ -298,22 +335,24 @@ class AdminShares(APIView):
error_msg = 'User %s not found.' % email error_msg = 'User %s not found.' % email
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not has_shared_to_user(repo.repo_id, path, email):
error_msg = 'Shared items not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try: try:
if path == '/': update_user_dir_permission(repo.repo_id, path, repo_owner, email, permission)
seafile_api.set_share_permission(
repo_id, repo_owner, email, permission) send_perm_audit_msg('modify-repo-perm', username, email,
else: repo.repo_id, path, permission)
seafile_api.update_share_subdir_perm_for_user(
repo_id, path, repo_owner, email, permission)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
new_perm = seafile_api.check_permission_by_path(repo_id, path, email)
share_info['user_email'] = email share_info['user_email'] = email
share_info['user_name'] = email2nickname(email) share_info['user_name'] = email2nickname(email)
share_info['permission'] = new_perm share_info['permission'] = PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission
share_info['is_admin'] = permission == PERMISSION_ADMIN
if share_type == 'group': if share_type == 'group':
group_id = share_to group_id = share_to
@@ -328,13 +367,14 @@ class AdminShares(APIView):
error_msg = 'Group %s not found' % group_id error_msg = 'Group %s not found' % group_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if not has_shared_to_group(repo.repo_id, path, group_id):
error_msg = 'Shared items not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try: try:
if path == '/': update_group_dir_permission(repo.repo_id, path, repo_owner, group_id, permission)
seafile_api.set_group_repo_permission(group_id, send_perm_audit_msg('modify-repo-perm', username, group_id,
repo_id, permission) repo.repo_id, path, permission)
else:
seafile_api.update_share_subdir_perm_for_group(
repo_id, path, repo_owner, group_id, permission)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
@@ -342,12 +382,13 @@ class AdminShares(APIView):
share_info['group_id'] = group_id share_info['group_id'] = group_id
share_info['group_name'] = group.group_name share_info['group_name'] = group.group_name
share_info['permission'] = permission share_info['permission'] = PERMISSION_READ_WRITE if permission == PERMISSION_ADMIN else permission
share_info['is_admin'] = permission == PERMISSION_ADMIN
return Response(share_info) return Response(share_info)
@check_parameter @check_parameter
def delete(self, request, repo_id, path, share_type): def delete(self, request, repo, path, share_type):
""" Delete user/group share permission. """ Delete user/group share permission.
Permission checking: Permission checking:
@@ -356,7 +397,8 @@ class AdminShares(APIView):
# current `request.user.username` is admin user, # current `request.user.username` is admin user,
# so need to identify the repo owner specifically. # so need to identify the repo owner specifically.
repo_owner = seafile_api.get_repo_owner(repo_id) repo_owner = seafile_api.get_repo_owner(repo.repo_id)
username = request.user.username
share_to = request.data.get('share_to', None) share_to = request.data.get('share_to', None)
@@ -366,12 +408,24 @@ class AdminShares(APIView):
error_msg = 'email %s invalid.' % email error_msg = 'email %s invalid.' % email
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not has_shared_to_user(repo.repo_id, path, email):
error_msg = 'Shared items not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try: try:
permission = check_user_share_out_permission(repo.repo_id, path, email)
if path == '/': if path == '/':
seafile_api.remove_share(repo_id, repo_owner, email) seafile_api.remove_share(repo.repo_id, repo_owner, email)
else: else:
seafile_api.unshare_subdir_for_user( seafile_api.unshare_subdir_for_user(
repo_id, path, repo_owner, email) repo.repo_id, path, repo_owner, email)
if path == '/':
ExtraSharePermission.objects.delete_share_permission(repo.repo_id,
email)
send_perm_audit_msg('delete-repo-perm', username, email,
repo.repo_id, path, permission)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'
@@ -385,12 +439,26 @@ class AdminShares(APIView):
error_msg = 'group_id %s invalid' % group_id error_msg = 'group_id %s invalid' % group_id
return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
if not has_shared_to_group(repo.repo_id, path, group_id):
error_msg = 'Shared items not found'
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try: try:
permission = check_group_share_out_permission(repo.repo_id, path, group_id)
if path == '/': if path == '/':
seafile_api.unset_group_repo(repo_id, group_id, repo_owner) seafile_api.unset_group_repo(repo.repo_id, group_id, repo_owner)
else: else:
seafile_api.unshare_subdir_for_group( seafile_api.unshare_subdir_for_group(
repo_id, path, repo_owner, group_id) repo.repo_id, path, repo_owner, group_id)
if path == '/':
ExtraGroupsSharePermission.objects.delete_share_permission(repo.repo_id,
group_id)
send_perm_audit_msg('delete-repo-perm', username, group_id,
repo.repo_id, path, permission)
except Exception as e: except Exception as e:
logger.error(e) logger.error(e)
error_msg = 'Internal Server Error' error_msg = 'Internal Server Error'

View File

@@ -172,3 +172,45 @@ def check_group_share_in_permission(repo_id, group_id, is_org=False):
extra_permission = ExtraGroupsSharePermission.objects.get_group_permission(repo_id, group_id) extra_permission = ExtraGroupsSharePermission.objects.get_group_permission(repo_id, group_id)
return extra_permission if extra_permission else repo.permission return extra_permission if extra_permission else repo.permission
def has_shared_to_user(repo_id, path, username, org_id=None):
if org_id:
# 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)
if path == '/':
share_items = seafile_api.list_org_repo_shared_to(org_id,
repo_owner,
repo_id)
else:
share_items = seafile_api.get_org_shared_users_for_subdir(org_id,
repo_id,
path,
repo_owner)
else:
repo_owner = seafile_api.get_repo_owner(repo_id)
if path == '/':
share_items = seafile_api.list_repo_shared_to(repo_owner, repo_id)
else:
share_items = seafile_api.get_shared_users_for_subdir(repo_id,
path, repo_owner)
return username in [item.user for item in share_items]
def has_shared_to_group(repo_id, path, gid, org_id=None):
if org_id:
# 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)
if path == '/':
share_items = seafile_api.list_org_repo_shared_group(org_id,
repo_owner, repo_id)
else:
share_items = seafile_api.get_org_shared_groups_for_subdir(org_id,
repo_id, path, repo_owner)
else:
repo_owner = seafile_api.get_repo_owner(repo_id)
if path == '/':
share_items = seafile_api.list_repo_shared_group_by_user(repo_owner, repo_id)
else:
share_items = seafile_api.get_shared_groups_for_subdir(repo_id,
path, repo_owner)
return gid in [item.group_id for item in share_items]

View File

@@ -709,21 +709,43 @@
<td> <td>
<div class="perm"> <div class="perm">
<span> <span>
<% if (permission == 'rw') { %> <% if (is_pro && is_admin) { %>
{% trans "Read-Write" %} {% trans "Admin" %}
<% } else { %> <% } else { %>
{% trans "Read-Only" %} <% if (permission == 'rw') { %>
{% trans "Read-Write" %}
<% } else { %>
{% trans "Read-Only" %}
<% } %>
<% } %> <% } %>
</span> </span>
<a href="#" title="{% trans "Edit" %}" class="perm-edit-icon sf2-icon-edit op-icon vh"></a> <a href="#" title="{% trans "Edit" %}" class="perm-edit-icon sf2-icon-edit op-icon vh"></a>
</div> </div>
<select class="perm-toggle-select select-white hide w100"> <select class="perm-toggle-select select-white hide w100">
<% if (permission == 'rw') { %> <% if (is_pro) { %>
<option value="rw" selected="selected" >{% trans "Read-Write" %}</option> <% if (is_admin) { %>
<option value="r" >{% trans "Read-Only" %}</option> <option value="rw">{% trans "Read-Write" %}</option>
<option value="r">{% trans "Read-Only" %}</option>
<option value="admin" selected="selected">{% trans "Admin" %}</option>
<% } else { %>
<% if (permission == 'rw') { %>
<option value="rw" selected="selected">{% trans "Read-Write" %}</option>
<option value="r">{% trans "Read-Only" %}</option>
<option value="admin">{% trans "Admin" %}</option>
<% } else { %>
<option value="rw">{% trans "Read-Write" %}</option>
<option value="r" selected="selected">{% trans "Read-Only" %}</option>
<option value="admin">{% trans "Admin" %}</option>
<% } %>
<% } %>
<% } else { %> <% } else { %>
<option value="rw" >{% trans "Read-Write" %}</option> <% if (permission == 'rw') { %>
<option value="r" selected="selected" >{% trans "Read-Only" %}</option> <option value="rw" selected="selected">{% trans "Read-Write" %}</option>
<option value="r">{% trans "Read-Only" %}</option>
<% } else { %>
<option value="rw">{% trans "Read-Write" %}</option>
<option value="r" selected="selected">{% trans "Read-Only" %}</option>
<% } %>
<% } %> <% } %>
</select> </select>
</td> </td>
@@ -760,6 +782,9 @@
<select name="permission" class="share-permission-select w100"> <select name="permission" class="share-permission-select w100">
<option value="rw" selected="selected">{% trans "Read-Write" %}</option> <option value="rw" selected="selected">{% trans "Read-Write" %}</option>
<option value="r">{% trans "Read-Only" %}</option> <option value="r">{% trans "Read-Only" %}</option>
<% if (is_pro) { %>
<option value="admin">{% trans "Admin" %}</option>
<% } %>
</select> </select>
</td> </td>
<td><input type="submit" value="{% trans "Submit" %}" class="submit" /></td> <td><input type="submit" value="{% trans "Submit" %}" class="submit" /></td>
@@ -787,6 +812,9 @@
<select name="permission" class="share-permission-select w100"> <select name="permission" class="share-permission-select w100">
<option value="rw" selected="selected">{% trans "Read-Write" %}</option> <option value="rw" selected="selected">{% trans "Read-Write" %}</option>
<option value="r">{% trans "Read-Only" %}</option> <option value="r">{% trans "Read-Only" %}</option>
<% if (is_pro) { %>
<option value="admin">{% trans "Admin" %}</option>
<% } %>
</select> </select>
</td> </td>
<td><input type="submit" value="{% trans "Submit" %}" class="submit" /></td> <td><input type="submit" value="{% trans "Submit" %}" class="submit" /></td>

View File

@@ -20,6 +20,7 @@ from seahub.base.accounts import User
from seahub.utils.file_size import get_file_size_unit from seahub.utils.file_size import get_file_size_unit
from seahub.base.templatetags.seahub_tags import email2nickname,\ from seahub.base.templatetags.seahub_tags import email2nickname,\
email2contact_email email2contact_email
from seahub.share.models import ExtraSharePermission, ExtraGroupsSharePermission
TRAVIS = 'TRAVIS' in os.environ TRAVIS = 'TRAVIS' in os.environ
@@ -276,6 +277,12 @@ class Fixtures(Exam):
seafile_api.share_repo(self.repo.id, self.user.username, seafile_api.share_repo(self.repo.id, self.user.username,
self.admin.username, 'rw') self.admin.username, 'rw')
def share_repo_to_admin_with_admin_permission(self):
# share user's repo to admin with 'admin' permission
seafile_api.share_repo(self.repo.id, self.user.username,
self.admin.username, 'rw')
ExtraSharePermission.objects.create_share_permission(self.repo.id, self.admin.username, 'admin')
def share_org_repo_to_org_admin_with_rw_permission(self): def share_org_repo_to_org_admin_with_rw_permission(self):
seaserv.seafserv_threaded_rpc.org_add_share(self.org.org_id, self.org_repo.repo_id, seaserv.seafserv_threaded_rpc.org_add_share(self.org.org_id, self.org_repo.repo_id,
self.org_user.username, self.org_admin.username, self.org_user.username, self.org_admin.username,
@@ -322,6 +329,11 @@ class Fixtures(Exam):
seafile_api.set_group_repo( seafile_api.set_group_repo(
self.repo.id, self.group.id, self.user.username, 'rw') self.repo.id, self.group.id, self.user.username, 'rw')
def share_repo_to_group_with_admin_permission(self):
seafile_api.set_group_repo(
self.repo.id, self.group.id, self.user.username, 'rw')
ExtraGroupsSharePermission.objects.create_share_permission(self.repo.id, self.group.id, 'admin')
def share_org_repo_to_org_group_with_r_permission(self): def share_org_repo_to_org_group_with_r_permission(self):
seafile_api.add_org_group_repo(self.org_repo.repo_id, self.org.org_id, seafile_api.add_org_group_repo(self.org_repo.repo_id, self.org.org_id,
self.org_group.id, self.org_user.username, 'r') self.org_group.id, self.org_user.username, 'r')

View File

@@ -18,7 +18,7 @@ define([
}, },
render: function () { render: function () {
this.$el.html(this.template(this.item_data)); this.$el.html(this.template($.extend({}, this.item_data, {is_pro: app.pageOptions.is_pro})));
return this; return this;
}, },
@@ -77,6 +77,7 @@ define([
data: data, data: data,
success: function (data) { success: function (data) {
item_data.permission = data.permission; item_data.permission = data.permission;
item_data.is_admin = data.is_admin;
_this.render(); _this.render();
}, },
error: function(xhr) { error: function(xhr) {

View File

@@ -40,7 +40,8 @@ define([
this.$el.html(this.template({ this.$el.html(this.template({
title: gettext("Share {placeholder}") title: gettext("Share {placeholder}")
.replace('{placeholder}', '<span class="op-target ellipsis ellipsis-op-target" title="' + Common.HTMLescape(this.repo_name) + '">' + Common.HTMLescape(this.repo_name) + '</span>'), .replace('{placeholder}', '<span class="op-target ellipsis ellipsis-op-target" title="' + Common.HTMLescape(this.repo_name) + '">' + Common.HTMLescape(this.repo_name) + '</span>'),
repo_id: this.repo_id repo_id: this.repo_id,
is_pro: app.pageOptions.is_pro
})); }));
return this; return this;
@@ -76,6 +77,7 @@ define([
"user_email": item.user_email, "user_email": item.user_email,
"user_name": item.user_name, "user_name": item.user_name,
"permission": item.permission, "permission": item.permission,
"is_admin": item.is_admin,
"for_user": true "for_user": true
} }
}); });
@@ -113,6 +115,7 @@ define([
"group_id": item.group_id, "group_id": item.group_id,
"group_name": item.group_name, "group_name": item.group_name,
"permission": item.permission, "permission": item.permission,
"is_admin": item.is_admin,
'for_user': false 'for_user': false
} }
}); });
@@ -164,6 +167,7 @@ define([
"user_email": item.user_email, "user_email": item.user_email,
"user_name": item.user_name, "user_name": item.user_name,
"permission": item.permission, "permission": item.permission,
'is_admin': item.is_admin,
'for_user': true 'for_user': true
} }
}); });
@@ -237,6 +241,7 @@ define([
"group_id": item.group_id, "group_id": item.group_id,
"group_name": item.group_name, "group_name": item.group_name,
"permission": item.permission, "permission": item.permission,
'is_admin': item.is_admin,
'for_user': false 'for_user': false
} }
}); });

View File

@@ -5,6 +5,7 @@ from django.core.urlresolvers import reverse
from seaserv import seafile_api from seaserv import seafile_api
from seahub.test_utils import BaseTestCase from seahub.test_utils import BaseTestCase
from seahub.share.models import ExtraSharePermission
class Shares(BaseTestCase): class Shares(BaseTestCase):
@@ -41,6 +42,23 @@ class Shares(BaseTestCase):
assert json_resp[0]['user_email'] == self.admin_name assert json_resp[0]['user_email'] == self.admin_name
assert json_resp[0]['permission'] == 'rw' assert json_resp[0]['permission'] == 'rw'
def test_can_get_user_shared_with_admin(self):
self.share_repo_to_admin_with_admin_permission()
self.login_as(self.admin)
resp = self.client.get(self.url + self.para + '&share_type=user')
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert json_resp[0]['repo_id'] == self.repo_id
assert json_resp[0]['path'] == '/'
assert json_resp[0]['share_type'] == 'user'
assert json_resp[0]['user_email'] == self.admin_name
assert json_resp[0]['permission'] == 'rw'
assert json_resp[0]['is_admin'] == True
def test_can_get_group_shared(self): def test_can_get_group_shared(self):
self.share_repo_to_group_with_rw_permission() self.share_repo_to_group_with_rw_permission()
@@ -57,6 +75,23 @@ class Shares(BaseTestCase):
assert json_resp[0]['group_id'] == self.group_id assert json_resp[0]['group_id'] == self.group_id
assert json_resp[0]['permission'] == 'rw' assert json_resp[0]['permission'] == 'rw'
def test_can_get_group_shared_with_admin(self):
self.share_repo_to_group_with_admin_permission()
self.login_as(self.admin)
resp = self.client.get(self.url + self.para + '&share_type=group')
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert json_resp[0]['repo_id'] == self.repo_id
assert json_resp[0]['path'] == '/'
assert json_resp[0]['share_type'] == 'group'
assert json_resp[0]['group_id'] == self.group_id
assert json_resp[0]['permission'] == 'rw'
assert json_resp[0]['is_admin'] == True
def test_get_with_invalid_permission(self): def test_get_with_invalid_permission(self):
self.login_as(self.user) self.login_as(self.user)
@@ -85,6 +120,28 @@ class Shares(BaseTestCase):
assert json_resp['success'][0]['user_email'] == self.tmp_user_email assert json_resp['success'][0]['user_email'] == self.tmp_user_email
assert json_resp['success'][0]['permission'] == permission assert json_resp['success'][0]['permission'] == permission
def test_share_repo_to_user_with_admin_permission(self):
self.login_as(self.admin)
invalid_email = 'invalid@email.com'
permission = 'admin'
data = {
'repo_id': self.repo_id,
'share_type': 'user',
'permission': permission,
'share_to': [invalid_email, self.tmp_user_email]
}
resp = self.client.post(self.url, data)
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert json_resp['failed'][0]['user_email'] == invalid_email
assert json_resp['success'][0]['user_email'] == self.tmp_user_email
assert json_resp['success'][0]['permission'] == 'rw'
assert json_resp['success'][0]['is_admin'] == True
def test_share_repo_to_group(self): def test_share_repo_to_group(self):
self.login_as(self.admin) self.login_as(self.admin)
@@ -106,6 +163,28 @@ class Shares(BaseTestCase):
assert json_resp['success'][0]['group_id'] == self.group_id assert json_resp['success'][0]['group_id'] == self.group_id
assert json_resp['success'][0]['permission'] == permission assert json_resp['success'][0]['permission'] == permission
def test_share_repo_to_group_with_admin_permission(self):
self.login_as(self.admin)
invalid_group_id = 'invalid_group_id'
permission = 'admin'
data = {
'repo_id': self.repo_id,
'share_type': 'group',
'permission': permission,
'share_to': [invalid_group_id, self.group_id]
}
resp = self.client.post(self.url, data)
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert json_resp['failed'][0]['group_id'] == invalid_group_id
assert json_resp['success'][0]['group_id'] == self.group_id
assert json_resp['success'][0]['permission'] == 'rw'
assert json_resp['success'][0]['is_admin'] == True
def test_share_repo_with_invalid_user_permission(self): def test_share_repo_with_invalid_user_permission(self):
self.login_as(self.user) self.login_as(self.user)
@@ -143,6 +222,29 @@ class Shares(BaseTestCase):
assert seafile_api.check_permission_by_path(self.repo_id, \ assert seafile_api.check_permission_by_path(self.repo_id, \
'/', self.tmp_user_email) == modified_perm '/', self.tmp_user_email) == modified_perm
def test_modify_repo_user_share_permission_to_admin(self):
# user share repo to tmp user
init_permission = 'rw'
seafile_api.share_repo(self.repo_id,
self.user_name, self.tmp_user_email, init_permission)
assert seafile_api.check_permission_by_path(self.repo_id, \
'/', self.tmp_user_email) == init_permission
self.login_as(self.admin)
modified_perm = 'admin'
data = 'repo_id=%s&share_type=%s&permission=%s&share_to=%s' % \
(self.repo_id, 'user', modified_perm, self.tmp_user_email)
resp = self.client.put(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert json_resp['permission'] == 'rw'
assert json_resp['is_admin'] == True
assert json_resp['user_email'] == self.tmp_user_email
def test_modify_repo_group_share_permission(self): def test_modify_repo_group_share_permission(self):
# user share repo to tmp user # user share repo to tmp user
@@ -176,6 +278,34 @@ class Shares(BaseTestCase):
assert permission == modified_perm assert permission == modified_perm
def test_modify_repo_group_share_permission_to_admin(self):
# user share repo to tmp user
self.share_repo_to_group_with_rw_permission()
shared_groups = seafile_api.list_repo_shared_group(
self.user_name, self.repo_id)
for e in shared_groups:
if e.group_id == self.group_id:
permission = e.perm
break
assert permission == 'rw'
self.login_as(self.admin)
modified_perm = 'admin'
data = 'repo_id=%s&share_type=%s&permission=%s&share_to=%s' % \
(self.repo_id, 'group', modified_perm, self.group_id)
resp = self.client.put(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
json_resp = json.loads(resp.content)
assert json_resp['permission'] == 'rw'
assert json_resp['is_admin'] == True
assert json_resp['group_id'] == self.group_id
def test_modify_with_invalid_user_permission(self): def test_modify_with_invalid_user_permission(self):
self.login_as(self.user) self.login_as(self.user)
@@ -202,6 +332,44 @@ class Shares(BaseTestCase):
assert seafile_api.check_permission_by_path(self.repo_id, \ assert seafile_api.check_permission_by_path(self.repo_id, \
'/', self.tmp_user_email) is None '/', self.tmp_user_email) is None
def test_delete_repo_user_share_admin_permission(self):
# user share repo to tmp user
init_permission = 'rw'
seafile_api.share_repo(self.repo_id,
self.user_name, self.tmp_user_email, init_permission)
ExtraSharePermission.objects.create_share_permission(self.repo.id, self.tmp_user_email, 'admin')
assert seafile_api.check_permission_by_path(self.repo_id, \
'/', self.tmp_user_email) == init_permission
self.login_as(self.admin)
resp = self.client.get(self.url + self.para + '&share_type=user')
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert json_resp[0]['repo_id'] == self.repo_id
assert json_resp[0]['path'] == '/'
assert json_resp[0]['share_type'] == 'user'
assert json_resp[0]['user_email'] == self.tmp_user_email
assert json_resp[0]['permission'] == 'rw'
assert json_resp[0]['is_admin'] == True
data = 'repo_id=%s&share_type=%s&share_to=%s' % \
(self.repo_id, 'user', self.tmp_user_email)
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
assert seafile_api.check_permission_by_path(self.repo_id, \
'/', self.tmp_user_email) is None
resp = self.client.get(self.url + self.para + '&share_type=user')
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert not json_resp
def test_delete_repo_group_share_permission(self): def test_delete_repo_group_share_permission(self):
self.share_repo_to_group_with_rw_permission() self.share_repo_to_group_with_rw_permission()
@@ -218,7 +386,38 @@ class Shares(BaseTestCase):
self.login_as(self.admin) self.login_as(self.admin)
data = 'repo_id=%s&share_type=%s&share_to=%s' % \ data = 'repo_id=%s&share_type=%s&share_to=%s' % \
(self.repo_id, 'user', self.tmp_user_email) (self.repo_id, 'group', self.group_id)
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
def test_delete_repo_group_share_admin_permission(self):
self.share_repo_to_group_with_admin_permission()
shared_groups = seafile_api.list_repo_shared_group(
self.user_name, self.repo_id)
for e in shared_groups:
if e.group_id == self.group_id:
permission = e.perm
break
assert permission == 'rw'
self.login_as(self.admin)
resp = self.client.get(self.url + self.para + '&share_type=group')
json_resp = json.loads(resp.content)
self.assertEqual(200, resp.status_code)
assert json_resp[0]['repo_id'] == self.repo_id
assert json_resp[0]['path'] == '/'
assert json_resp[0]['share_type'] == 'group'
assert json_resp[0]['group_id'] == self.group_id
assert json_resp[0]['permission'] == 'rw'
assert json_resp[0]['is_admin'] == True
data = 'repo_id=%s&share_type=%s&share_to=%s' % \
(self.repo_id, 'group', self.group_id)
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded') resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code) self.assertEqual(200, resp.status_code)
@@ -227,3 +426,21 @@ class Shares(BaseTestCase):
self.login_as(self.user) self.login_as(self.user)
resp = self.client.delete(self.url, {}, 'application/x-www-form-urlencoded') resp = self.client.delete(self.url, {}, 'application/x-www-form-urlencoded')
self.assertEqual(403, resp.status_code) self.assertEqual(403, resp.status_code)
def test_delete_with_unshared_group(self):
self.login_as(self.admin)
data = 'repo_id=%s&share_type=%s&share_to=%s' % \
(self.repo_id, 'group', self.group_id)
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(404, resp.status_code)
def test_delete_with_unshared_user(self):
self.login_as(self.admin)
data = 'repo_id=%s&share_type=%s&share_to=%s' % \
(self.repo_id, 'user', self.tmp_user_email)
resp = self.client.delete(self.url, data, 'application/x-www-form-urlencoded')
self.assertEqual(404, resp.status_code)