1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-19 23:48:51 +00:00

update repo share

1. reshare repo after user/admin transfer repo
2. show org repo share out list at share popup in org mode
This commit is contained in:
lian 2016-06-24 11:10:26 +08:00
parent 85bb2cd076
commit ed10512a53
4 changed files with 300 additions and 40 deletions

View File

@ -32,15 +32,25 @@ class DirSharedItemsEndpoint(APIView):
""" """
authentication_classes = (TokenAuthentication, SessionAuthentication) authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, IsRepoAccessible) permission_classes = (IsAuthenticated, IsRepoAccessible)
throttle_classes = (UserRateThrottle, ) throttle_classes = (UserRateThrottle,)
def list_user_shared_items(self, request, repo_id, path): def list_user_shared_items(self, request, repo_id, path):
username = request.user.username username = request.user.username
if path == '/':
share_items = seafile_api.list_repo_shared_to(username, repo_id) if is_org_context(request):
org_id = request.user.org.org_id
if path == '/':
share_items = seafile_api.list_org_repo_shared_to(org_id,
username, repo_id)
else:
share_items = seafile_api.get_org_shared_users_for_subdir(org_id,
repo_id, path, username)
else: else:
share_items = seafile_api.get_shared_users_for_subdir(repo_id, if path == '/':
path, username) share_items = seafile_api.list_repo_shared_to(username, repo_id)
else:
share_items = seafile_api.get_shared_users_for_subdir(repo_id,
path, username)
ret = [] ret = []
for item in share_items: for item in share_items:
ret.append({ ret.append({
@ -55,11 +65,20 @@ class DirSharedItemsEndpoint(APIView):
def list_group_shared_items(self, request, repo_id, path): def list_group_shared_items(self, request, repo_id, path):
username = request.user.username username = request.user.username
if path == '/': if is_org_context(request):
share_items = seafile_api.list_repo_shared_group_by_user(username, repo_id) org_id = request.user.org.org_id
if path == '/':
share_items = seafile_api.list_org_repo_shared_group(org_id,
username, repo_id)
else:
share_items = seafile_api.get_org_shared_groups_for_subdir(org_id,
repo_id, path, username)
else: else:
share_items = seafile_api.get_shared_groups_for_subdir(repo_id, if path == '/':
path, username) share_items = seafile_api.list_repo_shared_group_by_user(username, repo_id)
else:
share_items = seafile_api.get_shared_groups_for_subdir(repo_id,
path, username)
ret = [] ret = []
for item in share_items: for item in share_items:
ret.append({ ret.append({

View File

@ -20,7 +20,7 @@ from rest_framework.response import Response
from django.contrib.auth.hashers import check_password from django.contrib.auth.hashers import check_password
from django.contrib.sites.models import RequestSite from django.contrib.sites.models import RequestSite
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import F, Q from django.db.models import F
from django.http import HttpResponse from django.http import HttpResponse
from django.template import RequestContext from django.template import RequestContext
from django.template.loader import render_to_string from django.template.loader import render_to_string
@ -55,7 +55,6 @@ from seahub.group.utils import BadGroupNameError, ConflictGroupNameError, \
from seahub.thumbnail.utils import generate_thumbnail from seahub.thumbnail.utils import generate_thumbnail
from seahub.notifications.models import UserNotification from seahub.notifications.models import UserNotification
from seahub.options.models import UserOptions from seahub.options.models import UserOptions
from seahub.contacts.models import Contact
from seahub.profile.models import Profile, DetailedProfile from seahub.profile.models import Profile, DetailedProfile
from seahub.signals import (repo_created, repo_deleted) from seahub.signals import (repo_created, repo_deleted)
from seahub.share.models import FileShare, OrgFileShare, UploadLinkShare from seahub.share.models import FileShare, OrgFileShare, UploadLinkShare
@ -86,7 +85,7 @@ if HAS_OFFICE_CONVERTER:
from seahub.utils import query_office_convert_status, prepare_converted_html from seahub.utils import query_office_convert_status, prepare_converted_html
import seahub.settings as settings import seahub.settings as settings
from seahub.settings import THUMBNAIL_EXTENSION, THUMBNAIL_ROOT, \ from seahub.settings import THUMBNAIL_EXTENSION, THUMBNAIL_ROOT, \
ENABLE_GLOBAL_ADDRESSBOOK, FILE_LOCK_EXPIRATION_DAYS, \ FILE_LOCK_EXPIRATION_DAYS, \
ENABLE_THUMBNAIL, ENABLE_FOLDER_PERM ENABLE_THUMBNAIL, ENABLE_FOLDER_PERM
try: try:
from seahub.settings import CLOUD_MODE from seahub.settings import CLOUD_MODE
@ -1072,48 +1071,120 @@ class RepoOwner(APIView):
content_type=json_content_type) content_type=json_content_type)
def put(self, request, repo_id, format=None): def put(self, request, repo_id, format=None):
repo = get_repo(repo_id) """ Currently only for transfer repo.
if not repo:
error_msg = 'Library %s not found.' % repo_id Permission checking:
return api_error(status.HTTP_404_NOT_FOUND, error_msg) 1. only repo owner can transfer repo.
"""
org_id = None org_id = None
if is_org_context(request): if is_org_context(request):
org_id = request.user.org.org_id org_id = request.user.org.org_id
# check permission # argument check
if org_id:
repo_owner = seafile_api.get_org_repo_owner(repo.id)
else:
repo_owner = seafile_api.get_repo_owner(repo.id)
if request.user.username != repo_owner:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# check new owner validation
new_owner = request.data.get('owner', '').lower() new_owner = request.data.get('owner', '').lower()
if not new_owner:
error_msg = 'owner invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
repo = seafile_api.get_repo(repo_id)
if not repo:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
try: try:
User.objects.get(email=new_owner) User.objects.get(email=new_owner)
except User.DoesNotExist: except User.DoesNotExist:
error_msg = 'User %s not found.' % new_owner error_msg = 'User %s not found.' % new_owner
return api_error(status.HTTP_404_NOT_FOUND, error_msg) return api_error(status.HTTP_404_NOT_FOUND, error_msg)
if org_id and not ccnet_api.org_user_exists(org_id, new_owner):
error_msg = _(u'User %s not found in organization.') % new_owner
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
if org_id: if org_id:
if not ccnet_api.org_user_exists(org_id, new_owner): repo_owner = seafile_api.get_org_repo_owner(repo_id)
error_msg = _(u'User %s not found in organization.') % new_owner else:
return api_error(status.HTTP_404_NOT_FOUND, error_msg) repo_owner = seafile_api.get_repo_owner(repo_id)
username = request.user.username
if username != repo_owner:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
# get users/groups repo already shared to
if org_id:
shared_users = seafile_api.list_org_repo_shared_to(org_id,
repo_owner, repo_id)
shared_groups = seafile_api.list_org_repo_shared_group(org_id,
repo_owner, repo_id)
pub_repos = seaserv.seafserv_threaded_rpc.list_org_inner_pub_repos_by_owner(
org_id, repo_owner)
else:
shared_users = seafile_api.list_repo_shared_to(
repo_owner, repo_id)
shared_groups = seafile_api.list_repo_shared_group_by_user(
repo_owner, repo_id)
pub_repos = seaserv.seafserv_threaded_rpc.list_inner_pub_repos_by_owner(
repo_owner)
# transfer repo # transfer repo
if org_id: try:
seafile_api.set_org_repo_owner(org_id, repo_id, new_owner) if org_id:
else: seafile_api.set_org_repo_owner(org_id, repo_id, new_owner)
if ccnet_api.get_orgs_by_user(new_owner):
# can not transfer library to organization user %s.
error_msg = 'Email %s invalid.' % new_owner
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
else: else:
seafile_api.set_repo_owner(repo_id, new_owner) if ccnet_api.get_orgs_by_user(new_owner):
# can not transfer library to organization user %s.
error_msg = 'Email %s invalid.' % new_owner
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
else:
seafile_api.set_repo_owner(repo_id, new_owner)
except SearpcError as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
# reshare repo
for shared_user in shared_users:
shared_username = shared_user.user
if new_owner == shared_username:
continue
if org_id:
seaserv.seafserv_threaded_rpc.org_add_share(org_id, repo_id,
new_owner, shared_username, shared_user.perm)
else:
seafile_api.share_repo(repo_id, new_owner,
shared_username, shared_user.perm)
for shared_group in shared_groups:
shared_group_id = shared_group.group_id
if not ccnet_api.is_group_user(shared_group_id, new_owner):
continue
if org_id:
seafile_api.add_org_group_repo(repo_id, org_id,
shared_group_id, new_owner, shared_group.perm)
else:
seafile_api.set_group_repo(repo_id, shared_group_id,
new_owner, shared_group.perm)
for pub_repo in pub_repos:
if repo_id != pub_repo.id:
continue
if org_id:
seaserv.seafserv_threaded_rpc.set_org_inner_pub_repo(
org_id, repo_id, pub_repo.permission)
else:
seaserv.seafserv_threaded_rpc.set_inner_pub_repo(
repo_id, pub_repo.permission)
break
return HttpResponse(json.dumps({'success': True}), return HttpResponse(json.dumps({'success': True}),
content_type=json_content_type) content_type=json_content_type)

View File

@ -22,7 +22,7 @@ from django.utils.translation import ugettext as _
import seaserv import seaserv
from seaserv import ccnet_threaded_rpc, seafserv_threaded_rpc, \ from seaserv import ccnet_threaded_rpc, seafserv_threaded_rpc, \
seafile_api, get_group, get_group_members seafile_api, get_group, get_group_members, ccnet_api
from pysearpc import SearpcError from pysearpc import SearpcError
from seahub.base.accounts import User from seahub.base.accounts import User
@ -1611,8 +1611,45 @@ def sys_repo_transfer(request):
except SearpcError: # XXX: ignore rpc not found error except SearpcError: # XXX: ignore rpc not found error
pass pass
repo_owner = seafile_api.get_repo_owner(repo_id)
shared_users = seafile_api.list_repo_shared_to(
repo_owner, repo_id)
shared_groups = seafile_api.list_repo_shared_group_by_user(
repo_owner, repo_id)
pub_repos = seaserv.seafserv_threaded_rpc.list_inner_pub_repos_by_owner(
repo_owner)
# transfer repo
seafile_api.set_repo_owner(repo_id, new_owner) seafile_api.set_repo_owner(repo_id, new_owner)
# reshare repo
for shared_user in shared_users:
shared_username = shared_user.user
if new_owner == shared_username:
continue
seafile_api.share_repo(repo_id, new_owner,
shared_username, shared_user.perm)
for shared_group in shared_groups:
shared_group_id = shared_group.group_id
if not ccnet_api.is_group_user(shared_group_id, new_owner):
continue
seafile_api.set_group_repo(repo_id, shared_group_id,
new_owner, shared_group.perm)
for pub_repo in pub_repos:
if repo_id != pub_repo.id:
continue
seaserv.seafserv_threaded_rpc.set_inner_pub_repo(
repo_id, pub_repo.permission)
break
messages.success(request, _(u'Successfully transfered.')) messages.success(request, _(u'Successfully transfered.'))
return HttpResponseRedirect(next) return HttpResponseRedirect(next)

View File

@ -4,12 +4,17 @@ import json
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from seahub.test_utils import BaseTestCase from seahub.test_utils import BaseTestCase
from seahub.base.accounts import User
from tests.common.utils import randstring from tests.common.utils import randstring
class RepoTest(BaseTestCase): from seaserv import seafile_api, ccnet_api
class RepoOwnerTest(BaseTestCase):
def setUp(self): def setUp(self):
self.user_name = self.user.username
self.user_repo_id = self.repo.id self.user_repo_id = self.repo.id
self.group_id = self.group.id
def tearDown(self): def tearDown(self):
self.remove_repo() self.remove_repo()
@ -36,6 +41,134 @@ class RepoTest(BaseTestCase):
resp = self.client.put(url, data, 'application/x-www-form-urlencoded') resp = self.client.put(url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code) self.assertEqual(200, resp.status_code)
def test_reshare_to_user_after_transfer_repo(self):
tmp_user = 'tmp_user@email.com'
User.objects.create_user(tmp_user)
# share user's repo to tmp_user with 'rw' permission
seafile_api.share_repo(self.user_repo_id, self.user.username,
tmp_user, 'rw')
assert seafile_api.check_permission_by_path(self.user_repo_id,
'/', tmp_user) == 'rw'
self.login_as(self.user)
url = reverse("api2-repo-owner", args=[self.user_repo_id])
data = 'owner=%s' % self.admin.email
resp = self.client.put(url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
assert seafile_api.check_permission_by_path(self.user_repo_id,
'/', tmp_user) == 'rw'
def test_not_reshare_to_user_after_transfer_repo(self):
# Remove share if repo already shared to new owner
# share user's repo to admin with 'rw' permission
seafile_api.share_repo(self.user_repo_id, self.user.username,
self.admin.username, 'rw')
# repo in admin's be shared repo list
shared_repos = seafile_api.get_share_in_repo_list(self.admin.username, -1, -1)
assert shared_repos[0].repo_name == self.repo.repo_name
self.login_as(self.user)
url = reverse("api2-repo-owner", args=[self.user_repo_id])
data = 'owner=%s' % self.admin.email
resp = self.client.put(url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
# repo NOT in admin's be shared repo list
shared_repos = seafile_api.get_share_in_repo_list(self.admin.username, -1, -1)
assert len(shared_repos) == 0
def test_reshare_to_group_after_transfer_repo(self):
# If new owner in group repo shared to, reshare to group
# share user's repo to group with 'r' permission
seafile_api.set_group_repo(self.user_repo_id, self.group_id,
self.user_name, 'r')
group_repos = seafile_api.get_repos_by_group(self.group_id)
assert group_repos[0].permission == 'r'
# add admin user to group
ccnet_api.group_add_member(self.group_id, self.user_name, self.admin.username)
self.login_as(self.user)
url = reverse("api2-repo-owner", args=[self.user_repo_id])
data = 'owner=%s' % self.admin.email
# transfer repo to admin
resp = self.client.put(url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
group_repos = seafile_api.get_repos_by_group(self.group_id)
assert group_repos[0].permission == 'r'
def test_not_reshare_to_group_after_transfer_repo(self):
# If new owner NOT in group repo shared to, NOT reshare to group
# share user's repo to group with 'r' permission
seafile_api.set_group_repo(self.user_repo_id, self.group_id,
self.user_name, 'r')
group_repos = seafile_api.get_repos_by_group(self.group_id)
assert group_repos[0].permission == 'r'
self.login_as(self.user)
url = reverse("api2-repo-owner", args=[self.user_repo_id])
data = 'owner=%s' % self.admin.email
# transfer repo to admin
resp = self.client.put(url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
group_repos = seafile_api.get_repos_by_group(self.group_id)
assert len(group_repos) == 0
def test_reshare_to_user_group_after_transfer_repo(self):
tmp_user = 'tmp_user@email.com'
User.objects.create_user(tmp_user)
# add admin user to group
ccnet_api.group_add_member(self.group_id, self.user_name, self.admin.username)
# share user's repo to tmp_user with 'rw' permission
seafile_api.share_repo(self.user_repo_id, self.user.username,
tmp_user, 'rw')
# share user's repo to group with 'r' permission
seafile_api.set_group_repo(self.user_repo_id, self.group_id,
self.user_name, 'r')
group_repos = seafile_api.get_repos_by_group(self.group_id)
assert group_repos[0].permission == 'r'
assert seafile_api.check_permission_by_path(self.user_repo_id,
'/', tmp_user) == 'rw'
self.login_as(self.user)
url = reverse("api2-repo-owner", args=[self.user_repo_id])
data = 'owner=%s' % self.admin.email
# transfer repo to admin
resp = self.client.put(url, data, 'application/x-www-form-urlencoded')
self.assertEqual(200, resp.status_code)
group_repos = seafile_api.get_repos_by_group(self.group_id)
assert group_repos[0].permission == 'r'
assert seafile_api.check_permission_by_path(self.user_repo_id,
'/', tmp_user) == 'rw'
def test_can_not_transfer_if_not_repo_owner(self): def test_can_not_transfer_if_not_repo_owner(self):
self.login_as(self.admin) self.login_as(self.admin)