1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-13 05:39:59 +00:00

dtable row share link (#4067)

* rebase master

* fix rebase error

* return dtable columns
This commit is contained in:
王健辉
2019-09-30 09:40:14 +08:00
committed by Daniel Pan
parent 63bd44acf7
commit 0d885aa2b8
12 changed files with 455 additions and 41 deletions

View File

@@ -229,6 +229,11 @@ module.exports = {
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + "/dtable-form-view.js",
],
sharedDTableRow: [
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + "/shared-dtable-row.js",
],
},
output: {

View File

@@ -94,6 +94,7 @@ module.exports = {
appDTable: [require.resolve('./polyfills'), paths.appSrc + "/app-dtable"],
dtableAssetFileView: [require.resolve('./polyfills'), paths.appSrc + "/dtable-asset-file-view.js"],
dtableFormView: [require.resolve('./polyfills'), paths.appSrc + "/dtable-form-view.js"],
sharedDTableRow: [require.resolve('./polyfills'), paths.appSrc + "/shared-dtable-row.js"],
},
output: {

View File

@@ -0,0 +1,26 @@
import React from 'react';
import ReactDOM from 'react-dom';
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import './css/text-file-view.css';
const { rowContent, columns } = window.shared.pageOptions;
class SharedDTableRowView extends React.Component {
render() {
return (
<div className="shared-file-view-body text-file-view">
<CodeMirror
ref="code-mirror-editor"
value={rowContent + columns}
/>
</div>
);
}
}
ReactDOM.render(
<SharedDTableRowView />,
document.getElementById('wrapper')
);

View File

@@ -18,7 +18,7 @@ from seaserv import seafile_api, ccnet_api
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.api2.utils import api_error
from seahub.dtable.models import Workspaces, DTables
from seahub.dtable.models import Workspaces, DTables, DTableRowShares
from seahub.base.templatetags.seahub_tags import email2nickname
from seahub.group.utils import group_id_to_name
from seahub.utils import is_valid_dirent_name, is_org_context, normalize_file_path, \
@@ -276,7 +276,7 @@ class DTableView(APIView):
dtable = DTables.objects.get_dtable(workspace, old_table_name)
if not dtable:
error_msg = 'dtable %s not found.' % old_table_name
error_msg = 'DTable %s not found.' % old_table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
old_table_file_name = old_table_name + FILE_TYPE
@@ -346,7 +346,7 @@ class DTableView(APIView):
dtable = DTables.objects.get_dtable(workspace, table_name)
if not dtable:
error_msg = 'dtable %s not found.' % table_name
error_msg = 'DTable %s not found.' % table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
table_path = normalize_file_path(table_file_name)
@@ -432,7 +432,7 @@ class DTableAssetUploadLinkView(APIView):
dtable = DTables.objects.get_dtable(workspace, table_name)
if not dtable:
error_msg = 'dtable %s not found.' % table_name
error_msg = 'DTable %s not found.' % table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
@@ -475,9 +475,7 @@ class DTableAccessTokenView(APIView):
def get(self, request, workspace_id, name):
"""get dtable access token
"""
table_name = name
table_file_name = table_name + FILE_TYPE
# resource check
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
@@ -493,13 +491,7 @@ class DTableAccessTokenView(APIView):
dtable = DTables.objects.get_dtable(workspace, table_name)
if not dtable:
error_msg = 'dtable %s not found.' % table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
table_path = normalize_file_path(table_file_name)
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
if not table_file_id:
error_msg = 'file %s not found.' % table_file_name
error_msg = 'DTable %s not found.' % table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
@@ -525,3 +517,178 @@ class DTableAccessTokenView(APIView):
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'access_token': access_token})
class DTableRowSharesView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def get(self, request):
"""get a dtable row share link
Permission:
1. owner
2. group member
3. shared user with `rw` or `admin` permission
"""
# argument check
workspace_id = request.GET.get('workspace_id', None)
if not workspace_id:
error_msg = 'workspace_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
table_name = request.GET.get('name', None)
if not table_name:
error_msg = 'name invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
table_id = request.GET.get('table_id', None)
if not table_id:
error_msg = 'table_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
row_id = request.GET.get('row_id', None)
if not row_id:
error_msg = 'row_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
if not workspace:
error_msg = 'Workspace %s not found.' % workspace_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:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
dtable = DTables.objects.get_dtable(workspace, table_name)
if not dtable:
error_msg = 'DTable %s not found.' % table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
username = request.user.username
if check_dtable_permission(username, workspace, dtable) not in WRITE_PERMISSION_TUPLE:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
dtable_uuid = dtable.uuid.hex
try:
row_share = DTableRowShares.objects.get_dtable_row_share(
username, workspace_id, dtable_uuid, table_id, row_id
)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({"row_share": row_share}, status=status.HTTP_200_OK)
def post(self, request):
"""create a dtable row share link
Permission:
1. owner
2. group member
3. shared user with `rw` or `admin` permission
"""
# argument check
workspace_id = request.POST.get('workspace_id')
if not workspace_id:
error_msg = 'workspace_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
table_name = request.POST.get('name')
if not table_name:
error_msg = 'name invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
table_id = request.POST.get('table_id')
if not table_id:
error_msg = 'table_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
row_id = request.POST.get('row_id')
if not row_id:
error_msg = 'row_id invalid.'
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
# resource check
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
if not workspace:
error_msg = 'Workspace %s not found.' % workspace_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:
error_msg = 'Library %s not found.' % repo_id
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
dtable = DTables.objects.get_dtable(workspace, table_name)
if not dtable:
error_msg = 'DTable %s not found.' % table_name
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
# permission check
username = request.user.username
if check_dtable_permission(username, workspace, dtable) not in WRITE_PERMISSION_TUPLE:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
dtable_uuid = dtable.uuid.hex
row_share = DTableRowShares.objects.get_dtable_row_share(
username, workspace_id, dtable_uuid, table_id, row_id
)
if row_share:
error_msg = 'Row share link %s already exists.' % row_share['token']
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
try:
row_share = DTableRowShares.objects.add_dtable_row_share(
username, workspace_id, dtable_uuid, table_id, row_id
)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({"row_share": row_share}, status=status.HTTP_201_CREATED)
class DTableRowShareView(APIView):
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (IsAuthenticated, )
throttle_classes = (UserRateThrottle, )
def delete(self, request, token):
""" Delete share link.
Permission:
1. dtable row share owner;
"""
# resource check
row_share = DTableRowShares.objects.get_dtable_row_share_by_token(token)
if not row_share:
return Response({'success': True}, status=status.HTTP_200_OK)
# permission check
username = request.user.username
row_share_owner = row_share.username
if username != row_share_owner:
error_msg = 'Permission denied.'
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
try:
DTableRowShares.objects.delete_dtable_row_share(token)
except Exception as e:
logger.error(e)
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
return Response({'success': True}, status=status.HTTP_200_OK)

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.23 on 2019-09-17 10:47
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dtable', '0003_auto'),
]
operations = [
migrations.CreateModel(
name='DTableRowShares',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(db_index=True, max_length=255)),
('workspace_id', models.IntegerField(db_index=True)),
('dtable_uuid', models.CharField(db_index=True, max_length=36)),
('table_id', models.CharField(max_length=36)),
('row_id', models.CharField(db_index=True, max_length=36)),
('token', models.CharField(max_length=100, unique=True)),
],
options={
'db_table': 'dtable_row_shares',
},
),
]

View File

@@ -114,9 +114,9 @@ class DTablesManager(models.Manager):
except self.model.DoesNotExist:
return None
def get_dtable_by_uuid(self, uuid):
def get_dtable_by_uuid(self, dtable_uuid):
try:
return super(DTablesManager, self).get(uuid=uuid)
return super(DTablesManager, self).get(uuid=dtable_uuid)
except self.model.DoesNotExist:
return None
@@ -364,3 +364,78 @@ class DTableFormLinks(models.Model):
'form_id': self.form_id,
'token': self.token,
}
class DTableRowSharesManager(models.Manager):
def add_dtable_row_share(self, username, workspace_id, dtable_uuid, table_id, row_id):
token = uuid.uuid4()
row_share_obj = self.model(
username=username,
workspace_id=workspace_id,
dtable_uuid=dtable_uuid,
table_id=table_id,
row_id=row_id,
token=token
)
row_share_obj.save()
row_share = row_share_obj.to_dict()
row_share["row_share_link"] = "%s/dtable/row-share-links/%s" % (SERVICE_URL, token)
return row_share
def get_dtable_row_share(self, username, workspace_id, dtable_uuid, table_id, row_id):
row_shares = super(DTableRowSharesManager, self).filter(
username=username,
workspace_id=workspace_id,
dtable_uuid=dtable_uuid,
table_id=table_id,
row_id=row_id
)
if len(row_shares) > 0:
row_share_obj = row_shares[0]
row_share = row_share_obj.to_dict()
row_share["row_share_link"] = "%s/dtable/row-share-links/%s" % \
(SERVICE_URL, row_share_obj.token)
return row_share
else:
return None
def get_dtable_row_share_by_token(self, token):
try:
return super(DTableRowSharesManager, self).get(token=token)
except self.model.DoesNotExist:
return None
def delete_dtable_row_share(self, token):
try:
row_share = super(DTableRowSharesManager, self).get(token=token)
row_share.delete()
return True
except self.model.DoesNotExist:
return False
class DTableRowShares(models.Model):
username = models.CharField(max_length=255, db_index=True)
workspace_id = models.IntegerField(db_index=True)
dtable_uuid = models.CharField(max_length=36, db_index=True)
table_id = models.CharField(max_length=36)
row_id = models.CharField(max_length=36, db_index=True)
token = models.CharField(max_length=100, unique=True)
objects = DTableRowSharesManager()
class Meta:
db_table = 'dtable_row_shares'
def to_dict(self):
return {
'id': self.pk,
'username': self.username,
'workspace_id': self.workspace_id,
'dtable_uuid': self.dtable_uuid,
'table_id': self.table_id,
'row_id': self.row_id,
'token': self.token,
}

View File

@@ -2,7 +2,7 @@
from django.conf.urls import url
from .views import dtable_file_view, dtable_asset_access, dtable_asset_file_view, dtable_form_view, \
dtable_share_link_view
dtable_share_link_view, dtable_row_share_link_view
urlpatterns = [
url(r'^workspace/(?P<workspace_id>\d+)/dtable/(?P<name>.*)/$', dtable_file_view, name='dtable_file_view'),
@@ -10,4 +10,5 @@ urlpatterns = [
url(r'^workspace/(?P<workspace_id>\d+)/asset-file/(?P<dtable_id>[-0-9a-f]{36})/(?P<path>.*)$', dtable_asset_file_view, name='dtable_asset_file_view'),
url(r'^dtable/forms/(?P<token>[-0-9a-f]{36})$', dtable_form_view, name='dtable_form_view'),
url(r'^dtable/links/(?P<token>[-0-9a-f]+)/$', dtable_share_link_view, name='dtable_share_link_view'),
url(r'^dtable/row-share-links/(?P<token>[-0-9a-f]{36})$', dtable_row_share_link_view, name='dtable_row_share_link_view'),
]

View File

@@ -10,13 +10,13 @@ from django.shortcuts import render
from django.utils.translation import ugettext as _
from seaserv import seafile_api
from seahub.dtable.models import Workspaces, DTables, DTableFormLinks, DTableShareLinks
from seahub.dtable.models import Workspaces, DTables, DTableFormLinks, DTableShareLinks, \
DTableRowShares
from seahub.utils import normalize_file_path, render_error, render_permission_error, \
gen_file_get_url, get_file_type_and_ext, gen_inner_file_get_url
from seahub.auth.decorators import login_required
from seahub.settings import SHARE_LINK_EXPIRE_DAYS_MIN, SHARE_LINK_EXPIRE_DAYS_MAX, \
SHARE_LINK_EXPIRE_DAYS_DEFAULT, DTABLE_SERVER_URL, SEAFILE_COLLAB_SERVER, MEDIA_URL, \
FILE_ENCODING_LIST, DTABLE_PRIVATE_KEY
from seahub.settings import DTABLE_SERVER_URL, SEAFILE_COLLAB_SERVER, MEDIA_URL, \
DTABLE_PRIVATE_KEY, FILE_ENCODING_LIST
from seahub.dtable.utils import check_dtable_permission
from seahub.constants import PERMISSION_ADMIN, PERMISSION_READ_WRITE
from seahub.views.file import get_file_content
@@ -39,22 +39,16 @@ def dtable_file_view(request, workspace_id, name):
# resource check
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
if not workspace:
raise Http404
return render_error(request, 'Workspace does not exist.')
repo_id = workspace.repo_id
repo = seafile_api.get_repo(repo_id)
if not repo:
raise Http404
return render_error(request, 'Library does not exist.')
dtable = DTables.objects.get_dtable(workspace, name)
if not dtable:
return render_error(request, _('Table does not exist'))
table_file_name = name + FILE_TYPE
table_path = normalize_file_path(table_file_name)
table_file_id = seafile_api.get_file_id_by_path(repo_id, table_path)
if not table_file_id:
return render_error(request, _('Table does not exist'))
return render_error(request, 'DTable does not exist')
# permission check
username = request.user.username
@@ -62,13 +56,7 @@ def dtable_file_view(request, workspace_id, name):
return render_permission_error(request, _('Permission denied.'))
return_dict = {
'share_link_expire_days_default': SHARE_LINK_EXPIRE_DAYS_DEFAULT,
'share_link_expire_days_min': SHARE_LINK_EXPIRE_DAYS_MIN,
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
'repo': repo,
'filename': name,
'path': table_path,
'filetype': 'dtable',
'workspace_id': workspace_id,
'dtable_uuid': dtable.uuid.hex,
'media_url': MEDIA_URL,
@@ -93,21 +81,21 @@ def dtable_asset_access(request, workspace_id, dtable_id, path):
# resource check
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
if not workspace:
raise Http404
return render_error(request, 'Workspace does not exist.')
repo_id = workspace.repo_id
repo = seafile_api.get_repo(repo_id)
if not repo:
raise Http404
return render_error(request, 'Library does not exist.')
dtable = DTables.objects.get_dtable_by_uuid(dtable_id)
if not dtable:
raise Http404
return render_error(request, 'DTable does not exist.')
asset_path = normalize_file_path(os.path.join('/asset', dtable_id, path))
asset_id = seafile_api.get_file_id_by_path(repo_id, asset_path)
if not asset_id:
raise Http404
return render_error(request, 'Asset file does not exist.')
# permission check
username = request.user.username
@@ -238,6 +226,68 @@ def dtable_form_view(request, token):
return render(request, 'dtable_form_view_react.html', return_dict)
@login_required
def dtable_row_share_link_view(request, token):
# resource check
dtable_row_share = DTableRowShares.objects.get_dtable_row_share_by_token(token)
if not dtable_row_share:
return render_error(request, 'DTable row share link does not exist.')
workspace_id = dtable_row_share.workspace_id
workspace = Workspaces.objects.get_workspace_by_id(workspace_id)
if not workspace:
return render_error(request, 'Workspace does not exist.')
repo_id = workspace.repo_id
repo = seafile_api.get_repo(repo_id)
if not repo:
return render_error(request, 'Library does not exist.')
dtable_uuid = dtable_row_share.dtable_uuid
dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid)
if not dtable:
return render_error(request, 'DTable %s does not exist' % dtable_uuid)
# generate json web token
username = request.user.username
payload = {
'exp': int(time.time()) + 86400 * 3,
'dtable_uuid': dtable.uuid.hex,
'username': username,
}
try:
access_token = jwt.encode(
payload, DTABLE_PRIVATE_KEY, algorithm='HS256'
)
except Exception as e:
logger.error(e)
return render_error(request, _('Internal Server Error'))
url_for_row = '%s/api/v1/dtables/%s/tables/%s/rows/%s/' % \
(DTABLE_SERVER_URL.strip('/'), dtable_uuid, dtable_row_share.table_id, dtable_row_share.row_id)
req_for_row = requests.Request(url_for_row, headers={"Authorization": "Token %s" % access_token.decode()})
url_for_columns = '%s/api/v1/dtables/%s/tables/%s/columns/' % \
(DTABLE_SERVER_URL.strip('/'), dtable_uuid, dtable_row_share.table_id)
req_for_columns = requests.Request(url_for_columns, headers={"Authorization": "Token %s" % access_token.decode()})
try:
row_content = requests.urlopen(req_for_row).read().decode()
columns = requests.urlopen(req_for_columns).read().decode()
except Exception as e:
logger.error(e)
return render_error(request, _('Internal Server Error'))
return_dict = {
'row_content': row_content,
'columns': columns,
}
return render(request, 'shared_dtable_row_view_react.html', return_dict)
def dtable_share_link_view(request, token):
dsl = DTableShareLinks.objects.filter(token=token).first()
if not dsl:

View File

@@ -36,7 +36,6 @@
contactEmail: "{{request.user.username|email2contact_email|escapejs}}",
fileName: '{{ filename|escapejs }}',
filePath: '{{ path|escapejs }}',
workspaceID: '{{ workspace_id }}',
dtableUuid: '{{ dtable_uuid }}',
mediaUrl: '{{ media_url }}',

View File

@@ -0,0 +1,35 @@
{% extends "base_for_react.html" %}
{% load seahub_tags i18n staticfiles %}
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE }}">
<head>
<title>{% block sub_title %}{% endblock %}{{ site_title }}</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="keywords" content="{% trans "File Collaboration Team Organization" %}" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<link rel="shortcut icon" href="{{ MEDIA_URL }}{{ favicon_path }}" />
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}fontawesome/css/fontawesome-all.min.css" />
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/seafile-ui.css" />
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/sf_font3/iconfont.css" />
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/dtable-font.css" />
</head>
<body>
<div id="wrapper" class="{{ LANGUAGE_CODE }}"></div>
<div id="modal-wrapper" class="{{ LANGUAGE_CODE }}"></div>
{% block extra_script %}
<script type="text/javascript">
window.shared = {
pageOptions: {
rowContent: '{{ row_content|escapejs }}',
columns: '{{ columns|escapejs }}',
}
};
</script>
{% render_bundle 'sharedDTableRow' 'js' %}
{% endblock %}
</body>
</html>

View File

@@ -91,7 +91,7 @@ from seahub.api2.endpoints.starred_items import StarredItems
from seahub.api2.endpoints.markdown_lint import MarkdownLintView
from seahub.api2.endpoints.public_repos_search import PublishedRepoSearchView
from seahub.api2.endpoints.dtable import WorkspacesView, DTableView, DTablesView, \
DTableAssetUploadLinkView, DTableAccessTokenView
DTableAssetUploadLinkView, DTableAccessTokenView, DTableRowSharesView, DTableRowSharesView, DTableRowShareView
from seahub.api2.endpoints.dtable_api_token import DTableAPITokensView, DTableAPITokenView, DTableAppAccessTokenView
from seahub.api2.endpoints.dtable_forms import DTableFormLinksView, DTableFormLinkView
from seahub.api2.endpoints.dtable_share import SharedDTablesView, DTableShareView
@@ -396,6 +396,8 @@ urlpatterns = [
url(r'^api/v2.1/dtable/app-access-token/$', DTableAppAccessTokenView.as_view(), name='api-v2.1-dtable-app-access-token'),
url(r'^api/v2.1/dtable-form-links/$', DTableFormLinksView.as_view(), name='api-v2.1-dtable-form-links'),
url(r'^api/v2.1/dtable-form-links/(?P<token>[-0-9a-f]{36})/$', DTableFormLinkView.as_view(), name='api-v2.1-dtable-form-link'),
url(r'^api/v2.1/dtable-row-shares/$', DTableRowSharesView.as_view(), name='api-v2.1-dtable-row-shares'),
url(r'^api/v2.1/dtable-row-shares/(?P<token>[-0-9a-f]{36})/$', DTableRowShareView.as_view(), name='api-v2.1-dtable-row-share'),
url(r'^api/v2.1/recent-added-files/$', RecentAddedFilesView.as_view(), name='api-v2.1-recent-added-files'),

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import json
import uuid
from django.core.urlresolvers import reverse
@@ -7,6 +8,7 @@ from seaserv import seafile_api
from seahub.dtable.models import Workspaces
from seahub.test_utils import BaseTestCase
from tests.common.utils import randstring
class WorkspacesViewTest(BaseTestCase):
@@ -191,3 +193,24 @@ class DTableTest(BaseTestCase):
url4 = reverse('api-v2.1-dtable-access-token', args=[self.workspace.id, 'table11'])
resp = self.client.get(url4, {}, 'application/x-www-form-urlencoded')
self.assertEqual(404, resp.status_code)
def test_create_dtable_row_share(self):
resp = self.client.post(self.url1, {'name': 'table12', 'owner': self.user.username})
self.assertEqual(201, resp.status_code)
json_resp = json.loads(resp.content)
assert json_resp["table"]["name"] == 'table12'
url4 = reverse('api-v2.1-dtable-row-shares')
resp = self.client.post(
url4,
{
'workspace_id': self.workspace.id,
'name': 'table12',
'table_id': randstring(4),
'row_id': uuid.uuid4()
}
)
self.assertEqual(201, resp.status_code)
json_resp = json.loads(resp.content)
self.assertIsNotNone(json_resp["row_share"])