mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-22 03:47:09 +00:00
@@ -26,7 +26,6 @@ const tablePropTypes = {
|
||||
onUnfreezedItem: PropTypes.func.isRequired,
|
||||
onFreezedItem: PropTypes.func.isRequired,
|
||||
isItemFreezed: PropTypes.bool.isRequired,
|
||||
isPersonal: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
class Table extends Component {
|
||||
@@ -135,9 +134,7 @@ class Table extends Component {
|
||||
<DropdownMenu className="drop-list" right={true}>
|
||||
<DropdownItem onClick={this.onRenameTableCancel}>{gettext('Rename')}</DropdownItem>
|
||||
<DropdownItem onClick={this.onDeleteTableCancel}>{gettext('Delete')}</DropdownItem>
|
||||
{this.props.isPersonal &&
|
||||
<DropdownItem onClick={this.onShareTableCancel}>{gettext('Share')}</DropdownItem>
|
||||
}
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
}
|
||||
@@ -258,7 +255,6 @@ class Workspace extends Component {
|
||||
onFreezedItem={this.onFreezedItem}
|
||||
onUnfreezedItem={this.onUnfreezedItem}
|
||||
isItemFreezed={isItemFreezed}
|
||||
isPersonal={isPersonal}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@@ -112,20 +112,19 @@ class WorkspacesView(APIView):
|
||||
logger.warning('Library %s not found.' % repo_id)
|
||||
continue
|
||||
|
||||
if '@seafile_group' in owner:
|
||||
group_id = int(owner.split('@')[0])
|
||||
owner_name = group_id_to_name(group_id)
|
||||
owner_type = "Group"
|
||||
else:
|
||||
owner_name = email2nickname(owner)
|
||||
owner_type = "Personal"
|
||||
res = workspace.to_dict()
|
||||
|
||||
table_list = DTables.objects.get_dtable_by_workspace(workspace)
|
||||
|
||||
res = workspace.to_dict()
|
||||
res["owner_name"] = owner_name
|
||||
res["owner_type"] = owner_type
|
||||
res["table_list"] = table_list
|
||||
|
||||
if '@seafile_group' in owner:
|
||||
group_id = owner.split('@')[0]
|
||||
res["owner_name"] = group_id_to_name(group_id)
|
||||
res["owner_type"] = "Group"
|
||||
else:
|
||||
res["owner_name"] = email2nickname(owner)
|
||||
res["owner_type"] = "Personal"
|
||||
|
||||
workspace_list.append(res)
|
||||
|
||||
return Response({"workspace_list": workspace_list}, status=status.HTTP_200_OK)
|
||||
|
@@ -7,7 +7,7 @@ from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from django.utils.translation import ugettext as _
|
||||
import seaserv
|
||||
from seaserv import seafile_api
|
||||
|
||||
from seahub.base.accounts import User
|
||||
@@ -22,7 +22,7 @@ from seahub.utils import normalize_file_path
|
||||
from seahub.constants import PERMISSION_ADMIN, PERMISSION_PREVIEW, PERMISSION_PREVIEW_EDIT, \
|
||||
PERMISSION_READ, PERMISSION_READ_WRITE
|
||||
from seahub.api2.endpoints.dtable import FILE_TYPE
|
||||
from seahub.group.utils import group_id_to_name
|
||||
from seahub.group.utils import group_id_to_name, is_group_member
|
||||
from seahub.utils.timeutils import datetime_to_isoformat_timestr
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -66,7 +66,12 @@ class SharedDTablesView(APIView):
|
||||
dtable_info['updated_at'] = datetime_to_isoformat_timestr(dtable.updated_at)
|
||||
dtable_info['permission'] = permission
|
||||
dtable_info['from_user'] = from_user
|
||||
dtable_info['from_user_name'] = email2nickname(from_user)
|
||||
|
||||
if '@seafile_group' in from_user:
|
||||
group_id = from_user.split('@')[0]
|
||||
dtable_info['from_user_name'] = group_id_to_name(group_id)
|
||||
else:
|
||||
dtable_info['from_user_name'] = email2nickname(from_user)
|
||||
|
||||
table_list.append(dtable_info)
|
||||
|
||||
@@ -108,6 +113,14 @@ class DTableShareView(APIView):
|
||||
error_msg = 'Workspace %s not found.' % workspace_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
group_id = ''
|
||||
if '@seafile_group' in workspace.owner:
|
||||
group_id = workspace.owner.split('@')[0]
|
||||
group = seaserv.get_group(group_id)
|
||||
if not group:
|
||||
error_msg = 'Group %s not found.' % group_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
repo_id = workspace.repo_id
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
@@ -126,13 +139,24 @@ class DTableShareView(APIView):
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if from_user != dtable.creator:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
username = request.user.username
|
||||
if group_id:
|
||||
if not is_group_member(group_id, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if to_user == from_user:
|
||||
error_msg = 'table %s can not be shared to owner.' % table_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
if is_group_member(group_id, to_user):
|
||||
error_msg = 'table %s can not be shared to group member.' % table_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
from_user = group_id + GROUP_DOMAIN
|
||||
else:
|
||||
if from_user != dtable.creator:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if from_user == to_user:
|
||||
error_msg = 'table %s can not be shared to owner.' % table_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# org check
|
||||
if is_org_context(request):
|
||||
@@ -164,7 +188,7 @@ class DTableShareView(APIView):
|
||||
def get(self, request, workspace_id, name):
|
||||
"""list share users in dtable share
|
||||
"""
|
||||
from_user = request.user.username
|
||||
username = request.user.username
|
||||
table_name = name
|
||||
table_file_name = table_name + FILE_TYPE
|
||||
|
||||
@@ -174,6 +198,14 @@ class DTableShareView(APIView):
|
||||
error_msg = 'Workspace %s not found.' % workspace_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
group_id = ''
|
||||
if '@seafile_group' in workspace.owner:
|
||||
group_id = workspace.owner.split('@')[0]
|
||||
group = seaserv.get_group(group_id)
|
||||
if not group:
|
||||
error_msg = 'Group %s not found.' % group_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
repo_id = workspace.repo_id
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
@@ -192,9 +224,14 @@ class DTableShareView(APIView):
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if from_user != dtable.creator:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
if group_id:
|
||||
if not is_group_member(group_id, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
else:
|
||||
if username != dtable.creator:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
# main
|
||||
try:
|
||||
@@ -215,7 +252,7 @@ class DTableShareView(APIView):
|
||||
def put(self, request, workspace_id, name):
|
||||
"""modify dtable share permission
|
||||
"""
|
||||
from_user = request.user.username
|
||||
username = request.user.username
|
||||
table_name = name
|
||||
table_file_name = table_name + FILE_TYPE
|
||||
|
||||
@@ -242,6 +279,14 @@ class DTableShareView(APIView):
|
||||
error_msg = 'Workspace %s not found.' % workspace_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
group_id = ''
|
||||
if '@seafile_group' in workspace.owner:
|
||||
group_id = workspace.owner.split('@')[0]
|
||||
group = seaserv.get_group(group_id)
|
||||
if not group:
|
||||
error_msg = 'Group %s not found.' % group_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
repo_id = workspace.repo_id
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
@@ -260,13 +305,22 @@ class DTableShareView(APIView):
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if from_user != dtable.creator:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
if group_id:
|
||||
if not is_group_member(group_id, username):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if to_user == from_user:
|
||||
error_msg = 'table %s can not be shared to owner.' % table_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
if is_group_member(group_id, to_user):
|
||||
error_msg = 'table %s can not be shared to group member.' % table_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
else:
|
||||
if username != dtable.creator:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if username == to_user:
|
||||
error_msg = 'table %s can not be shared to owner.' % table_name
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# main
|
||||
try:
|
||||
@@ -312,6 +366,14 @@ class DTableShareView(APIView):
|
||||
error_msg = 'Workspace %s not found.' % workspace_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
group_id = ''
|
||||
if '@seafile_group' in workspace.owner:
|
||||
group_id = workspace.owner.split('@')[0]
|
||||
group = seaserv.get_group(group_id)
|
||||
if not group:
|
||||
error_msg = 'Group %s not found.' % group_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
repo_id = workspace.repo_id
|
||||
repo = seafile_api.get_repo(repo_id)
|
||||
if not repo:
|
||||
@@ -337,9 +399,14 @@ class DTableShareView(APIView):
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
if username not in (obj.to_user, obj.from_user):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
if group_id:
|
||||
if not is_group_member(group_id, username) and username != obj.to_user:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
else:
|
||||
if username not in (obj.to_user, obj.from_user):
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
obj.delete()
|
||||
except Exception as e:
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse
|
||||
from seahub.dtable.models import Workspaces, DTableShare, DTables
|
||||
from seaserv import seafile_api
|
||||
@@ -13,6 +14,8 @@ try:
|
||||
except ImportError:
|
||||
LOCAL_PRO_DEV_ENV = False
|
||||
|
||||
GROUP_DOMAIN = '@seafile_group'
|
||||
|
||||
|
||||
class SharedDTablesViewTest(BaseTestCase):
|
||||
def setUp(self):
|
||||
@@ -80,15 +83,55 @@ class DTableShareViewTest(BaseTestCase):
|
||||
|
||||
self.url = reverse('api-v2.1-dtable-share', args=[self.workspace.id, self.dtable.name])
|
||||
|
||||
# add user to group
|
||||
self.login_as(self.user)
|
||||
self.group_id = self.group.id
|
||||
self.endpoint = reverse('api-v2.1-group-members', args=[self.group_id])
|
||||
self.client.post(self.endpoint, {
|
||||
'email': self.user.email
|
||||
})
|
||||
self.logout()
|
||||
|
||||
# create group workspace
|
||||
group_repo_id = seafile_api.create_repo(
|
||||
_("My Workspace"),
|
||||
_("My Workspace"),
|
||||
"dtable@seafile"
|
||||
)
|
||||
self.group_workspace = Workspaces.objects.create_workspace(
|
||||
str(self.group_id) + GROUP_DOMAIN, group_repo_id
|
||||
)
|
||||
assert len(Workspaces.objects.all()) == 2
|
||||
|
||||
# create group dtable
|
||||
seafile_api.post_empty_file(
|
||||
group_repo_id, '/', 'group.dtable', self.user.username
|
||||
)
|
||||
self.group_dtable = DTables.objects.create_dtable(
|
||||
self.user.username, self.group_workspace, 'group'
|
||||
)
|
||||
assert len(DTables.objects.all()) == 2
|
||||
|
||||
# share group dtable to admin
|
||||
DTableShare.objects.add(
|
||||
self.group_dtable, str(self.group_id) + GROUP_DOMAIN, self.admin.username, 'rw'
|
||||
)
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
|
||||
self.url2 = reverse(
|
||||
'api-v2.1-dtable-share', args=[self.group_workspace.id, self.group_dtable.name]
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
workspace = Workspaces.objects.get_workspace_by_owner(self.user.username)
|
||||
workspace_id = workspace.id
|
||||
Workspaces.objects.delete_workspace(workspace_id)
|
||||
|
||||
self.remove_repo()
|
||||
self.remove_group()
|
||||
|
||||
def test_can_post(self):
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
@@ -102,9 +145,25 @@ class DTableShareViewTest(BaseTestCase):
|
||||
self.assertEqual(201, resp.status_code)
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
|
||||
def test_can_not_post_with_already_share(self):
|
||||
def test_can_post_group_share(self):
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
self.login_as(self.user)
|
||||
|
||||
data = {
|
||||
'email': self.admin.username,
|
||||
'permission': 'rw',
|
||||
}
|
||||
|
||||
resp = self.client.post(self.url2, data)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
|
||||
def test_can_not_post_with_already_share(self):
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
|
||||
self.login_as(self.user)
|
||||
|
||||
data = {
|
||||
@@ -115,7 +174,7 @@ class DTableShareViewTest(BaseTestCase):
|
||||
self.assertEqual(409, resp.status_code)
|
||||
|
||||
def test_can_not_post_with_not_owner(self):
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
@@ -129,7 +188,7 @@ class DTableShareViewTest(BaseTestCase):
|
||||
self.assertEqual(403, resp.status_code)
|
||||
|
||||
def test_can_not_post_with_share_to_owner(self):
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
@@ -142,11 +201,25 @@ class DTableShareViewTest(BaseTestCase):
|
||||
resp = self.client.post(self.url, data)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_can_not_post_to_group_member(self):
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
self.login_as(self.user)
|
||||
|
||||
data = {
|
||||
'email': self.user.username,
|
||||
'permission': 'rw',
|
||||
}
|
||||
resp = self.client.post(self.url2, data)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_can_not_post_with_share_to_org_user(self):
|
||||
if not LOCAL_PRO_DEV_ENV:
|
||||
return
|
||||
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
@@ -193,8 +266,22 @@ class DTableShareViewTest(BaseTestCase):
|
||||
assert DTableShare.objects.get_by_dtable_and_to_user(
|
||||
self.dtable, self.admin.username).permission == 'r'
|
||||
|
||||
def test_can_put_group_share(self):
|
||||
self.login_as(self.user)
|
||||
|
||||
data = {
|
||||
'email': self.admin.username,
|
||||
'permission': 'r',
|
||||
}
|
||||
resp = self.client.put(self.url2, json.dumps(data), 'application/json')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
assert DTableShare.objects.get_by_dtable_and_to_user(
|
||||
self.group_dtable, self.admin.username
|
||||
).permission == 'r'
|
||||
|
||||
def test_can_not_put_with_not_shared(self):
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
@@ -228,6 +315,7 @@ class DTableShareViewTest(BaseTestCase):
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_can_delete(self):
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
self.login_as(self.user)
|
||||
|
||||
data = {
|
||||
@@ -235,7 +323,18 @@ class DTableShareViewTest(BaseTestCase):
|
||||
}
|
||||
resp = self.client.delete(self.url, json.dumps(data), 'application/json')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
|
||||
def test_can_delete_group_share(self):
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
self.login_as(self.user)
|
||||
|
||||
data = {
|
||||
'email': self.admin.username,
|
||||
}
|
||||
resp = self.client.delete(self.url2, json.dumps(data), 'application/json')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
|
||||
def test_can_delete_with_share_user(self):
|
||||
self.login_as(self.admin)
|
||||
@@ -245,10 +344,10 @@ class DTableShareViewTest(BaseTestCase):
|
||||
}
|
||||
resp = self.client.delete(self.url, json.dumps(data), 'application/json')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
|
||||
def test_can_not_delete_with_not_shared(self):
|
||||
assert len(DTableShare.objects.all()) == 1
|
||||
assert len(DTableShare.objects.all()) == 2
|
||||
DTableShare.objects.all().delete()
|
||||
assert len(DTableShare.objects.all()) == 0
|
||||
|
||||
|
Reference in New Issue
Block a user