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:
@@ -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: {
|
||||
|
@@ -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: {
|
||||
|
26
frontend/src/shared-dtable-row.js
Normal file
26
frontend/src/shared-dtable-row.js
Normal 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')
|
||||
);
|
@@ -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)
|
||||
|
30
seahub/dtable/migrations/0004_dtablerowshares.py
Normal file
30
seahub/dtable/migrations/0004_dtablerowshares.py
Normal 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',
|
||||
},
|
||||
),
|
||||
]
|
@@ -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,
|
||||
}
|
||||
|
@@ -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'),
|
||||
]
|
||||
|
@@ -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:
|
||||
|
@@ -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 }}',
|
||||
|
35
seahub/templates/shared_dtable_row_view_react.html
Normal file
35
seahub/templates/shared_dtable_row_view_react.html
Normal 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>
|
@@ -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'),
|
||||
|
||||
|
@@ -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"])
|
||||
|
Reference in New Issue
Block a user